Files
chaisql/internal/sql/parser/select_test.go
2021-05-23 23:50:18 +04:00

150 lines
5.2 KiB
Go

package parser_test
import (
"testing"
"github.com/genjidb/genji/internal/expr"
"github.com/genjidb/genji/internal/query"
"github.com/genjidb/genji/internal/sql/parser"
"github.com/genjidb/genji/internal/stream"
"github.com/genjidb/genji/internal/testutil"
"github.com/stretchr/testify/require"
)
func TestParserSelect(t *testing.T) {
tests := []struct {
name string
s string
expected *stream.Stream
mustFail bool
}{
{"NoTable", "SELECT 1",
stream.New(stream.Project(testutil.ParseNamedExpr(t, "1"))),
false,
},
{"NoTableWithTuple", "SELECT (1, 2)",
stream.New(stream.Project(testutil.ParseNamedExpr(t, "[1, 2]"))),
false,
},
{"NoTableWithBrackets", "SELECT [1, 2]",
stream.New(stream.Project(testutil.ParseNamedExpr(t, "[1, 2]"))),
false,
},
{"NoTableWithINOperator", "SELECT 1 in (1, 2), 3",
stream.New(stream.Project(
testutil.ParseNamedExpr(t, "1 IN [1, 2]"),
testutil.ParseNamedExpr(t, "3"),
)),
false,
},
{"NoCond", "SELECT * FROM test",
stream.New(stream.SeqScan("test")).Pipe(stream.Project(expr.Wildcard{})),
false,
},
{"WithFields", "SELECT a, b FROM test",
stream.New(stream.SeqScan("test")).Pipe(stream.Project(testutil.ParseNamedExpr(t, "a"), testutil.ParseNamedExpr(t, "b"))),
false,
},
{"WithFieldsWithQuotes", "SELECT `long \"path\"` FROM test",
stream.New(stream.SeqScan("test")).Pipe(stream.Project(testutil.ParseNamedExpr(t, "`long \"path\"`", "long \"path\""))),
false,
},
{"WithAlias", "SELECT a AS A, b FROM test",
stream.New(stream.SeqScan("test")).Pipe(stream.Project(testutil.ParseNamedExpr(t, "a", "A"), testutil.ParseNamedExpr(t, "b"))),
false,
},
{"WithFields and wildcard", "SELECT a, b, * FROM test",
stream.New(stream.SeqScan("test")).Pipe(stream.Project(testutil.ParseNamedExpr(t, "a"), testutil.ParseNamedExpr(t, "b"), expr.Wildcard{})),
false,
},
{"WithExpr", "SELECT a > 1 FROM test",
stream.New(stream.SeqScan("test")).Pipe(stream.Project(testutil.ParseNamedExpr(t, "a > 1", "a > 1"))),
false,
},
{"WithCond", "SELECT * FROM test WHERE age = 10",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})),
false,
},
{"WithGroupBy", "SELECT a.b.c FROM test WHERE age = 10 GROUP BY a.b.c",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.GroupBy(parser.MustParseExpr("a.b.c"))).
Pipe(stream.HashAggregate()).
Pipe(stream.Project(testutil.ParseNamedExpr(t, "a.b.c"))),
false,
},
{"WithOrderBy", "SELECT * FROM test WHERE age = 10 ORDER BY a.b.c",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})).
Pipe(stream.Sort(testutil.ParsePath(t, "a.b.c"))),
false,
},
{"WithOrderBy ASC", "SELECT * FROM test WHERE age = 10 ORDER BY a.b.c ASC",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})).
Pipe(stream.Sort(testutil.ParsePath(t, "a.b.c"))),
false,
},
{"WithOrderBy DESC", "SELECT * FROM test WHERE age = 10 ORDER BY a.b.c DESC",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})).
Pipe(stream.SortReverse(testutil.ParsePath(t, "a.b.c"))),
false,
},
{"WithLimit", "SELECT * FROM test WHERE age = 10 LIMIT 20",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})).
Pipe(stream.Take(20)),
false,
},
{"WithOffset", "SELECT * FROM test WHERE age = 10 OFFSET 20",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})).
Pipe(stream.Skip(20)),
false,
},
{"WithLimitThenOffset", "SELECT * FROM test WHERE age = 10 LIMIT 10 OFFSET 20",
stream.New(stream.SeqScan("test")).
Pipe(stream.Filter(parser.MustParseExpr("age = 10"))).
Pipe(stream.Project(expr.Wildcard{})).
Pipe(stream.Skip(20)).
Pipe(stream.Take(10)),
false,
},
{"WithOffsetThenLimit", "SELECT * FROM test WHERE age = 10 OFFSET 20 LIMIT 10", nil, true},
{"With aggregation function", "SELECT COUNT(*) FROM test",
stream.New(stream.SeqScan("test")).
Pipe(stream.HashAggregate(&expr.CountFunc{Wildcard: true})).
Pipe(stream.Project(testutil.ParseNamedExpr(t, "COUNT(*)"))),
false},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
q, err := parser.ParseQuery(test.s)
if !test.mustFail {
require.NoError(t, err)
require.Len(t, q.Statements, 1)
st, err := q.Statements[0].(*query.SelectStmt).ToStream()
require.NoError(t, err)
require.EqualValues(t, &query.StreamStmt{Stream: test.expected, ReadOnly: true}, st)
} else {
require.Error(t, err)
}
})
}
}
func BenchmarkSelect(b *testing.B) {
for i := 0; i < b.N; i++ {
parser.ParseQuery("SELECT a, b.c[100].d AS `foo` FROM `some table` WHERE d.e[100] >= 12 AND c.d IN ([1, true], [2, false]) GROUP BY d.e[0] LIMIT 10 + 10 OFFSET 20 - 20 ORDER BY d DESC")
}
}