featurebase/sql/mapper_test.go
2020-08-18 15:53:26 +02:00

394 lines
9.7 KiB
Go

// Copyright 2020 Pilosa Corp.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sql
import (
"fmt"
"testing"
"vitess.io/vitess/go/vt/sqlparser"
)
func TestParse(t *testing.T) {
tests := []struct {
sql string
expMask QueryMask
}{
{
sql: "select _id from tbl",
expMask: QueryMask{
SelectMask: SelectPartID,
FromMask: FromPartTable,
},
},
{
sql: "select * from tbl",
expMask: QueryMask{
SelectMask: SelectPartStar,
FromMask: FromPartTable,
},
},
{
sql: "select fld from tbl",
expMask: QueryMask{
SelectMask: SelectPartField,
FromMask: FromPartTable,
},
},
{
sql: "select fld1, fld2 from tbl",
expMask: QueryMask{
SelectMask: SelectPartFields,
FromMask: FromPartTable,
},
},
{
sql: "select count(*) from tbl",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartTable,
},
},
{
sql: "select min(fld) from tbl",
expMask: QueryMask{
SelectMask: SelectPartMinField,
FromMask: FromPartTable,
},
},
{
sql: "select max(fld) from tbl",
expMask: QueryMask{
SelectMask: SelectPartMaxField,
FromMask: FromPartTable,
},
},
{
sql: "select sum(fld) from tbl",
expMask: QueryMask{
SelectMask: SelectPartSumField,
FromMask: FromPartTable,
},
},
{
sql: "select avg(fld) from tbl",
expMask: QueryMask{
SelectMask: SelectPartAvgField,
FromMask: FromPartTable,
},
},
{
sql: "select _id, count(*) from tbl",
expMask: QueryMask{
SelectMask: SelectPartID | SelectPartCountStar,
FromMask: FromPartTable,
},
},
{
sql: "select _id from tbl1, tbl2",
expMask: QueryMask{
SelectMask: SelectPartID,
FromMask: FromPartTables,
},
},
{
sql: "select _id from tbl1 INNER JOIN tbl2",
expMask: QueryMask{
SelectMask: SelectPartID,
FromMask: FromPartJoin,
},
},
{
sql: "select * from tbl where _id = 1",
expMask: QueryMask{
SelectMask: SelectPartStar,
FromMask: FromPartTable,
WhereMask: WherePartIDCondition,
},
},
{
sql: "select * from tbl where fld = 1",
expMask: QueryMask{
SelectMask: SelectPartStar,
FromMask: FromPartTable,
WhereMask: WherePartFieldCondition,
},
},
{
sql: "select * from tbl group by fld",
expMask: QueryMask{
SelectMask: SelectPartStar,
FromMask: FromPartTable,
GroupByMask: GroupByPartField,
},
},
{
sql: "select * from tbl group by fld1, fld2",
expMask: QueryMask{
SelectMask: SelectPartStar,
FromMask: FromPartTable,
GroupByMask: GroupByPartFields,
},
},
{
sql: "select fld, sum(fld) from tbl group by fld",
expMask: QueryMask{
SelectMask: SelectPartField | SelectPartSumField,
FromMask: FromPartTable,
GroupByMask: GroupByPartField,
},
},
{
sql: "select fld, sum(fld) from tbl group by fld having sum > 10",
expMask: QueryMask{
SelectMask: SelectPartField | SelectPartSumField,
FromMask: FromPartTable,
GroupByMask: GroupByPartField,
HavingMask: HavingPartCondition,
},
},
{
sql: "select fld from tbl order by fld",
expMask: QueryMask{
SelectMask: SelectPartField,
FromMask: FromPartTable,
OrderByMask: OrderByPartField,
},
},
{
sql: "select fld from tbl order by fld1, fld2",
expMask: QueryMask{
SelectMask: SelectPartField,
FromMask: FromPartTable,
OrderByMask: OrderByPartFields,
},
},
{
sql: "select fld from tbl limit 10",
expMask: QueryMask{
SelectMask: SelectPartField,
FromMask: FromPartTable,
LimitMask: LimitPartLimit,
},
},
{
sql: "select fld from tbl limit 10, 5",
expMask: QueryMask{
SelectMask: SelectPartField,
FromMask: FromPartTable,
LimitMask: LimitPartLimit | LimitPartOffset,
},
},
{
sql: "select distinct fld from tbl",
expMask: QueryMask{
SelectMask: SelectPartDistinct | SelectPartField,
FromMask: FromPartTable,
},
},
{
sql: "select count(*) from tbl where fld = 1",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartTable,
WhereMask: WherePartFieldCondition,
},
},
{
sql: "select count(*) from tbl where fld1 = 1 and fld2 = 2",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartTable,
WhereMask: WherePartMultiFieldCondition,
},
},
{
sql: "select count(*) from tbl where fld1 = 1 or fld2 = 2",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartTable,
WhereMask: WherePartMultiFieldCondition,
},
},
{
sql: "select _id from tbl where not fld = 1 limit 10",
expMask: QueryMask{
SelectMask: SelectPartID,
FromMask: FromPartTable,
WhereMask: WherePartFieldCondition,
LimitMask: LimitPartLimit,
},
},
{
sql: "select _id from tbl where fld between 1 and 3",
expMask: QueryMask{
SelectMask: SelectPartID,
FromMask: FromPartTable,
WhereMask: WherePartFieldCondition,
},
},
{
sql: "select _id from tbl where fld1 between 1 and 3 and fld2 = 2",
expMask: QueryMask{
SelectMask: SelectPartID,
FromMask: FromPartTable,
WhereMask: WherePartMultiFieldCondition,
},
},
{
sql: "select count(*) from tbl where fld is not null",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartTable,
WhereMask: WherePartFieldCondition,
},
},
{
sql: "select fld, count(*) from tbl group by fld",
expMask: QueryMask{
SelectMask: SelectPartField | SelectPartCountStar,
FromMask: FromPartTable,
GroupByMask: GroupByPartField,
},
},
{
sql: "select fld1, fld2, count(*) from grouper group by fld1, fld2",
expMask: QueryMask{
SelectMask: SelectPartFields | SelectPartCountStar,
FromMask: FromPartTable,
GroupByMask: GroupByPartFields,
},
},
{
sql: "select fld1, fld2, count(*) from tbl where fld1 = 1 group by fld1, fld2 limit 1",
expMask: QueryMask{
SelectMask: SelectPartFields | SelectPartCountStar,
FromMask: FromPartTable,
WhereMask: WherePartFieldCondition,
GroupByMask: GroupByPartFields,
LimitMask: LimitPartLimit,
},
},
{
sql: "select count(distinct fld) from tbl",
expMask: QueryMask{
SelectMask: SelectPartCountDistinctField,
FromMask: FromPartTable,
},
},
{
sql: "select count(*) from tbl1 INNER JOIN tbl2 ON tbl1._id = tbl2.bsi",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartJoin,
},
},
{
sql: "select count(*) from tbl1 INNER JOIN tbl2 ON tbl1._id = tbl2.bsi where tbl1.fld1 = 1 and tbl2.fld2 = 2",
expMask: QueryMask{
SelectMask: SelectPartCountStar,
FromMask: FromPartJoin,
WhereMask: WherePartMultiFieldCondition,
},
},
}
mapper := NewMapper()
for i, test := range tests {
t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) {
_, mask, err := mapper.Parse(test.sql)
if err != nil {
t.Fatal(err)
}
if mask != test.expMask {
t.Fatalf("expected mask: %v, but got: %v", test.expMask, mask)
}
})
}
}
// This thing passes even if join is not implemented.
// TODO: make this actually a test
func TestSelectJoin(t *testing.T) {
tests := []struct {
sql string
}{
{
// Count(Intersect(All(),Distinct(Row(grouperid!=null),index='joiner',field='grouperid')))
sql: "select count(*) from grouper g INNER JOIN joiner j ON g._id = j.grouperid",
},
{
// Intersect(All(),Distinct(Row(grouperid!=null),index='joiner',field='grouperid'))
sql: "select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid",
},
{
// Intersect(Row(color='red'),Distinct(Row(grouperid!=null),index='joiner',field='grouperid'))
sql: "select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where g.color = 'red'",
},
{
// Intersect(All(),Distinct(Row(grouperid!=null),index='joiner',field='grouperid'))
sql: "select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where g.color = 'red' and j.jointype = 2",
},
}
mapper := NewMapper()
for i, test := range tests {
t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) {
if m, err := mapper.MapSQL(test.sql); err != nil {
t.Fatal(err)
} else {
if stmt, ok := m.Statement.(*sqlparser.Select); !ok {
t.Fatalf("%s: expected Statement: sqlparser.Select, got %T", test.sql, m.Statement)
} else {
t.Logf("%+v\n", stmt)
}
}
})
}
}
func TestOrderBy(t *testing.T) {
tests := []struct {
sql string
}{
{
sql: "select distinct score from grouper order by score asc",
},
{
sql: "select distinct score from grouper order by score desc",
},
{
sql: "select distinct score from grouper order by score asc limit 5",
},
{
sql: "select distinct score from grouper order by score desc limit 5",
},
}
mapper := NewMapper()
for i, test := range tests {
t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) {
if m, err := mapper.MapSQL(test.sql); err != nil {
t.Fatal(err)
} else {
if stmt, ok := m.Statement.(*sqlparser.Select); !ok {
t.Fatalf("%s: expected Statement: sqlparser.Select, got %T", test.sql, m.Statement)
} else {
t.Logf("%+v\n", stmt)
}
}
})
}
}