From f349d265f88ffd0bb7fcdd98d3d90d3a8f3149fb Mon Sep 17 00:00:00 2001 From: Christopher Dusovic Date: Mon, 6 Jun 2016 17:05:56 -0700 Subject: [PATCH 1/4] Stop testing query if planner fails --- bql/planner/planner_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/bql/planner/planner_test.go b/bql/planner/planner_test.go index e29491fc..bbe40338 100644 --- a/bql/planner/planner_test.go +++ b/bql/planner/planner_test.go @@ -461,6 +461,7 @@ func TestPlannerQuery(t *testing.T) { tbl, err := plnr.Excecute(ctx) if err != nil { t.Errorf("planner.Excecute failed for query %q with error %v", entry.q, err) + continue } if got, want := len(tbl.Bindings()), entry.nbs; got != want { t.Errorf("tbl.Bindings returned the wrong number of bindings for %q; got %d, want %d", entry.q, got, want) From baa6da502a5458112a71bc1f387334a0024cf480 Mon Sep 17 00:00:00 2001 From: Christopher Dusovic Date: Mon, 6 Jun 2016 17:08:32 -0700 Subject: [PATCH 2/4] Add tests for AS keyword --- bql/planner/planner_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bql/planner/planner_test.go b/bql/planner/planner_test.go index bbe40338..b3d28b04 100644 --- a/bql/planner/planner_test.go +++ b/bql/planner/planner_test.go @@ -272,11 +272,21 @@ func TestPlannerQuery(t *testing.T) { nbs: 3, nrws: len(strings.Split(testTriples, "\n")) - 1, }, + { + q: `select ?s as ?s1, ?p as ?p1, ?o as ?o1 from ?test where {?s ?p ?o};`, + nbs: 3, + nrws: len(strings.Split(testTriples, "\n")) - 1, + }, { q: `select ?p, ?o from ?test where {/u ?p ?o};`, nbs: 2, nrws: 2, }, + { + q: `select ?p as ?p1, ?o as ?o1 from ?test where {/u ?p ?o};`, + nbs: 2, + nrws: 2, + }, { q: `select ?s, ?p from ?test where {?s ?p /t};`, nbs: 2, @@ -312,6 +322,11 @@ func TestPlannerQuery(t *testing.T) { nbs: 1, nrws: 4, }, + { + q: `select ?s as ?s1 from ?test where {?s "is_a"@[] /t};`, + nbs: 1, + nrws: 4, + }, { q: `select ?o from ?test where {/u "parent_of"@[] ?o. ?o "parent_of"@[] /u};`, nbs: 1, From 61608dd8ed88647f9612e63a82604a681ebaa9f0 Mon Sep 17 00:00:00 2001 From: Christopher Dusovic Date: Mon, 6 Jun 2016 17:13:26 -0700 Subject: [PATCH 3/4] Fix AS keyword bug --- bql/planner/planner.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bql/planner/planner.go b/bql/planner/planner.go index aa05dcd7..9244dd71 100644 --- a/bql/planner/planner.go +++ b/bql/planner/planner.go @@ -485,8 +485,14 @@ func (p *queryPlan) processGraphPattern(ctx context.Context, lo *storage.LookupO // groups it by if needed. func (p *queryPlan) projectAndGroupBy() error { grp := p.stm.GroupByBindings() - if len(grp) == 0 { - // The table only needs to be projected. + if len(grp) == 0 { // The table only needs to be projected. + p.tbl.AddBindings(p.stm.OutputBindings()) + // For each row, copy each input binding value to its appropriate alias. + for _, prj := range p.stm.Projections() { + for _, row := range p.tbl.Rows() { + row[prj.Alias] = row[prj.Binding] + } + } return p.tbl.ProjectBindings(p.stm.OutputBindings()) } // The table needs to be group reduced. From 05997a86af64f3e659f486dd05686e98484f11b0 Mon Sep 17 00:00:00 2001 From: Christopher Dusovic Date: Mon, 6 Jun 2016 17:16:09 -0700 Subject: [PATCH 4/4] Add benchmarks for AS keyword --- bql/planner/planner_test.go | 70 +++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/bql/planner/planner_test.go b/bql/planner/planner_test.go index b3d28b04..78b686a5 100644 --- a/bql/planner/planner_test.go +++ b/bql/planner/planner_test.go @@ -260,6 +260,32 @@ func populateTestStore(t *testing.T) storage.Store { return s } +func populateBenchmarkStore(b *testing.B) storage.Store { + s, ctx := memory.NewStore(), context.Background() + g, err := s.NewGraph(ctx, "?test") + if err != nil { + b.Fatalf("memory.NewGraph failed to create \"?test\" with error %v", err) + } + buf := bytes.NewBufferString(testTriples) + if _, err := io.ReadIntoGraph(ctx, g, buf, literal.DefaultBuilder()); err != nil { + b.Fatalf("io.ReadIntoGraph failed to read test graph with error %v", err) + } + trpls := make(chan *triple.Triple) + go func() { + if err := g.Triples(ctx, trpls); err != nil { + b.Fatal(err) + } + }() + cnt := 0 + for _ = range trpls { + cnt++ + } + if got, want := cnt, len(strings.Split(testTriples, "\n"))-1; got != want { + b.Fatalf("Failed to import all test triples; got %v, want %v", got, want) + } + return s +} + func TestPlannerQuery(t *testing.T) { ctx := context.Background() testTable := []struct { @@ -535,3 +561,47 @@ func TestTreeTravesalToRoot(t *testing.T) { t.Errorf("planner.Excecute failed to return the expected number of rows for query %q; got %d want %d\nGot:\n%v\n", traversalQuery, got, want, tbl) } } + +// benchmarkQuery is a helper function that runs a specified query on the testing data set for benchmarking purposes. +func benchmarkQuery(query string, b *testing.B) { + ctx := context.Background() + + s := populateBenchmarkStore(b) + p, err := grammar.NewParser(grammar.SemanticBQL()) + if err != nil { + b.Fatalf("grammar.NewParser: should have produced a valid BQL parser with error %v", err) + } + b.ResetTimer() + for n := 0; n < b.N; n++ { + st := &semantic.Statement{} + if err := p.Parse(grammar.NewLLk(query, 1), st); err != nil { + b.Errorf("Parser.consume: failed to parse query %q with error %v", query, err) + } + plnr, err := New(ctx, s, st, 0) + if err != nil { + b.Errorf("planner.New failed to create a valid query plan with error %v", err) + } + _, err = plnr.Excecute(ctx) + if err != nil { + b.Errorf("planner.Excecute failed for query %q with error %v", query, err) + } + } +} + +// These benchmark tests are used to observe the difference in speed between queries using the "as" keyword as opposed +// to queries that do not. +func BenchmarkReg1(b *testing.B) { + benchmarkQuery(`select ?p, ?o as ?o1 from ?test where {/u ?p ?o};`, b) +} + +func BenchmarkAs1(b *testing.B) { + benchmarkQuery(`select ?p as ?p1, ?o as ?o1 from ?test where {/u ?p ?o};`, b) +} + +func BenchmarkReg2(b *testing.B) { + benchmarkQuery(`select ?s, ?p, ?o from ?test where {?s ?p ?o};`, b) +} + +func BenchmarkAs2(b *testing.B) { + benchmarkQuery(`select ?s as ?s1, ?p as ?p1, ?o as ?o1 from ?test where {?s ?p ?o};`, b) +}