featurebase/sql3/test/defs/defs_sql1.go
Seebs a158bba125 Simplify/centralize time parsing
We had a bunch of different places which had basically the
same logic, except that some were testing both RFC3339Nano
and RFC3339 formats, and some weren't.

This turns out not to matter, because the fractional second
part is always permitted and never required, so those two
formats are identical.

Mostly, though, we now ensure that everything we do that is
trying to convert timestamps has the same logic, so if we
want to make changes to that logic, we have a central point,
which lives in the parser.

This came out of an attempt to figure out why the RFC3339
case wasn't getting any test coverage.
2023-04-07 17:02:37 -05:00

561 lines
17 KiB
Go

package defs
import (
"fmt"
"time"
"github.com/featurebasedb/featurebase/v3/sql3/parser"
)
var sql1TestsGrouper = TableTest{
name: "sql1testsgrouper",
Table: tbl(
"grouper",
srcHdrs(
srcHdr("_id", fldTypeID),
srcHdr("color", fldTypeString),
srcHdr("score", fldTypeInt, "min -1000", "max 1000"),
srcHdr("age", fldTypeInt, "min 0", "max 100"),
srcHdr("height", fldTypeInt, "min 0", "max 1000"),
srcHdr("timestamp", fldTypeTimestamp),
),
srcRows(
srcRow(int64(1), string("blue"), int64(-10), int64(27), int64(20), string("2011-04-02T12:32:00Z")),
srcRow(int64(2), string("blue"), int64(-8), int64(16), int64(30), string("2011-01-02T12:32:00Z")),
srcRow(int64(3), string("red"), int64(6), int64(19), int64(40), string("2012-01-02T12:32:00Z")),
srcRow(int64(4), string("green"), int64(0), int64(27), int64(50), string("2013-09-02T12:32:00Z")),
srcRow(int64(5), string("blue"), int64(-2), int64(16), int64(60), string("2014-01-02T12:32:00Z")),
srcRow(int64(6), string("blue"), int64(100), int64(34), int64(70), string("2010-05-02T12:32:00Z")),
srcRow(int64(7), string("blue"), int64(0), int64(27), int64(80), string("2016-08-02T12:32:00Z")),
srcRow(int64(8), nil, int64(-13), int64(16), int64(90), string("2020-01-02T12:32:00Z")),
srcRow(int64(9), string("red"), int64(80), int64(16), int64(100), string("2000-03-02T12:32:00Z")),
srcRow(int64(10), string("red"), int64(-2), int64(31), int64(110), string("2018-01-02T12:32:00Z")),
),
),
SQLTests: nil,
}
var sql1TestsJoiner = TableTest{
name: "sql1testsjoiner",
Table: tbl(
"joiner",
srcHdrs(
srcHdr("_id", fldTypeID),
srcHdr("grouperid", fldTypeInt, "min 0", "max 1000"),
srcHdr("jointype", fldTypeInt, "min -1000", "max 1000"),
),
srcRows(
srcRow(int64(1), int64(1), int64(1)),
srcRow(int64(2), int64(2), int64(1)),
srcRow(int64(3), int64(5), int64(1)),
srcRow(int64(4), int64(6), int64(1)),
srcRow(int64(5), int64(7), int64(1)),
srcRow(int64(6), int64(3), int64(2)),
srcRow(int64(7), int64(8), int64(2)),
srcRow(int64(8), int64(9), int64(2)),
srcRow(int64(9), int64(1), int64(3)),
srcRow(int64(10), int64(2), int64(3)),
),
),
SQLTests: nil,
}
var sql1TestsDelete = TableTest{
name: "sql1testsdelete",
Table: tbl(
"delete_me",
srcHdrs(
srcHdr("_id", fldTypeID),
srcHdr("unused", fldTypeInt),
),
srcRows(srcRow(int64(1), int64(1))),
),
SQLTests: nil,
}
// grouperTimeX extracts the time associated with record ID x.
// note that the record IDs are 1..10, not 0..9, so we subtract one.
func grouperTimeX(x int) time.Time {
t, err := parser.ConvertStringToTimestamp(sql1TestsGrouper.Table.rows[0][x-1][5].(string))
if err != nil {
panic(fmt.Sprintf("failed to parse time for id %d", x))
}
return t
}
var sql1TestsQueries = TableTest{
name: "sql1testsqueries",
SQLTests: []SQLTest{
{
// Extract(Limit(All(), limit=100, offset=0),Rows(age))
SQLs: sqls("select age from grouper;"),
ExpHdrs: hdrs(
hdr("age", fldTypeInt),
),
ExpRows: rows(
row(int64(27)),
row(int64(16)),
row(int64(19)),
row(int64(27)),
row(int64(16)),
row(int64(34)),
row(int64(27)),
row(int64(16)),
row(int64(16)),
row(int64(31)),
),
Compare: CompareExactOrdered,
},
{
// Extract(Limit(ConstRow(columns=[2]), limit=100, offset=0),Rows(age),Rows(color),Rows(height),Rows(score))
SQLs: sqls("select * from grouper where _id=2;"),
ExpHdrs: hdrs(
hdr("_id", fldTypeID),
hdr("age", fldTypeInt),
hdr("color", fldTypeString),
hdr("height", fldTypeInt),
hdr("score", fldTypeInt),
hdr("timestamp", fldTypeTimestamp),
),
ExpRows: rows(
row(int64(2), int64(16), string("blue"), int64(30), int64(-8), grouperTimeX(2)),
),
Compare: CompareExactOrdered,
},
{
// Extract(Limit(ConstRow(columns=[2]), limit=100, offset=0),Rows(age),Rows(color),Rows(height),Rows(score))
SQLs: sqls("select * from grouper;"),
ExpHdrs: hdrs(
hdr("_id", fldTypeID),
hdr("age", fldTypeInt),
hdr("color", fldTypeString),
hdr("height", fldTypeInt),
hdr("score", fldTypeInt),
hdr("timestamp", fldTypeTimestamp),
),
ExpRows: rows(
row(int64(1), int64(27), string("blue"), int64(20), int64(-10), grouperTimeX(0+1)),
row(int64(2), int64(16), string("blue"), int64(30), int64(-8), grouperTimeX(1+1)),
row(int64(3), int64(19), string("red"), int64(40), int64(6), grouperTimeX(2+1)),
row(int64(4), int64(27), string("green"), int64(50), int64(0), grouperTimeX(3+1)),
row(int64(5), int64(16), string("blue"), int64(60), int64(-2), grouperTimeX(4+1)),
row(int64(6), int64(34), string("blue"), int64(70), int64(100), grouperTimeX(5+1)),
row(int64(7), int64(27), string("blue"), int64(80), int64(0), grouperTimeX(6+1)),
row(int64(8), int64(16), nil, int64(90), int64(-13), grouperTimeX(7+1)),
row(int64(9), int64(16), string("red"), int64(100), int64(80), grouperTimeX(8+1)),
row(int64(10), int64(31), string("red"), int64(110), int64(-2), grouperTimeX(9+1)),
),
Compare: CompareExactOrdered,
},
// join
{
// Count(Intersect(All(),Distinct(Row(grouperid!=null),index='joiner',field='grouperid')))
SQLs: sqls("select count(*) from grouper g INNER JOIN joiner j ON g._id = j.grouperid;"),
ExpHdrs: hdrs(
hdr("", fldTypeInt),
),
ExpRows: rows(
row(int64(10)),
),
Compare: CompareExactOrdered,
},
{
// Intersect(All(),Distinct(Row(grouperid!=null),index='joiner',field='grouperid'))
SQLs: sqls("select distinct _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid;"),
ExpHdrs: hdrs(hdr("_id", fldTypeID)),
ExpRows: rows(
row(int64(1)),
row(int64(2)),
row(int64(3)),
row(int64(5)),
row(int64(6)),
row(int64(7)),
row(int64(8)),
row(int64(9)),
),
Compare: CompareExactUnordered,
},
{
// Intersect(Row(color='red'),Distinct(Row(grouperid!=null),index='joiner',field='grouperid'))
SQLs: sqls("select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where g.color = 'red';"),
ExpHdrs: hdrs(hdr("_id", fldTypeID)),
ExpRows: rows(
row(int64(3)),
row(int64(9)),
),
Compare: CompareExactUnordered,
},
{
// Intersect(Row(color='red'),Distinct(Row(jointype=2),index='joiner',field='grouperid'))
SQLs: sqls("select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where g.color = 'red' and j.jointype = 2;"),
ExpHdrs: hdrs(hdr("_id", fldTypeID)),
ExpRows: rows(
row(int64(3)),
row(int64(9)),
),
Compare: CompareExactUnordered,
},
// order by
{
// Distinct(Row(score!=null),index='grouper',field='score')
SQLs: sqls("select distinct score from grouper order by score asc;"),
ExpHdrs: hdrs(hdr("score", fldTypeInt)),
ExpRows: rows(
row(int64(-13)),
row(int64(-10)),
row(int64(-8)),
row(int64(-2)),
row(int64(0)),
row(int64(6)),
row(int64(80)),
row(int64(100)),
),
Compare: CompareExactOrdered,
},
{
// Distinct(Row(score!=null),index='grouper',field='score')
SQLs: sqls("select distinct score from grouper order by score desc;"),
ExpHdrs: hdrs(hdr("score", fldTypeInt)),
ExpRows: rows(
row(int64(100)),
row(int64(80)),
row(int64(6)),
row(int64(0)),
row(int64(-2)),
row(int64(-8)),
row(int64(-10)),
row(int64(-13)),
),
Compare: CompareExactOrdered,
},
// {
// // Distinct(Row(score!=null),index='grouper',field='score')
// SQLs: sqls("select distinct score from grouper order by score asc limit 5;"),
// ExpHdrs: hdrs(hdr("score", fldTypeInt)),
// ExpRows: rows(
// row(int64(-13)),
// row(int64(-10)),
// row(int64(-8)),
// row(int64(-2)),
// row(int64(0)),
// ),
// Compare: CompareExactOrdered,
// },
// {
// // Distinct(Row(score!=null),index='grouper',field='score')
// SQLs: sqls("select distinct score from grouper order by score desc limit 5;"),
// ExpHdrs: hdrs(hdr("score", fldTypeInt)),
// ExpRows: rows(
// row(int64(100)),
// row(int64(80)),
// row(int64(6)),
// row(int64(0)),
// row(int64(-2)),
// ),
// Compare: CompareExactOrdered,
// },
// distinct
{
// Distinct(Row(score!=null),index='grouper',field='score')
SQLs: sqls("select distinct score from grouper;"),
ExpHdrs: hdrs(hdr("score", fldTypeInt)),
ExpRows: rows(
row(int64(-13)),
row(int64(-10)),
row(int64(-8)),
row(int64(-2)),
row(int64(0)),
row(int64(6)),
row(int64(80)),
row(int64(100)),
),
Compare: CompareExactUnordered,
},
{
// Distinct(Row(height!=null),index='grouper',field='height')
SQLs: sqls("select distinct height from grouper;"),
ExpHdrs: hdrs(hdr("height", fldTypeInt)),
ExpRows: rows(
row(int64(20)),
row(int64(30)),
row(int64(40)),
row(int64(50)),
row(int64(60)),
row(int64(70)),
row(int64(80)),
row(int64(90)),
row(int64(100)),
row(int64(110)),
),
Compare: CompareExactUnordered,
},
// groupby
{
// GroupBy(Rows(field='age'),limit=100)
SQLs: sqls("select age as yrs, count(*) as cnt from grouper group by age;"),
ExpHdrs: hdrs(
hdr("yrs", fldTypeInt),
hdr("cnt", fldTypeInt),
),
ExpRows: rows(
row(int64(16), int64(4)),
row(int64(19), int64(1)),
row(int64(27), int64(3)),
row(int64(31), int64(1)),
row(int64(34), int64(1)),
),
Compare: CompareExactUnordered,
},
// {
// // GroupBy(Rows(field='age'),Rows(field='color'),limit=100)
// SQLs: sqls("select age, color, count(*) from grouper group by age, color;"),
// ExpHdrs: hdrs(
// hdr("age", fldTypeInt),
// hdr("color", fldTypeString),
// hdr("", fldTypeInt),
// ),
// ExpRows: rows(
// row(int64(16), "blue", int64(2)),
// row(int64(16), "red", int64(1)),
// row(int64(19), "red", int64(1)),
// row(int64(27), "blue", int64(2)),
// row(int64(27), "green", int64(1)),
// row(int64(31), "red", int64(1)),
// row(int64(34), "blue", int64(1)),
// ),
// Compare: CompareExactUnordered,
// },
// {
// // GroupBy(Rows(field='age'),Rows(field='color'),limit=100,filter=Row(age=27),aggregate=Sum(field='height'))
// SQLs: sqls("select age, color, sum(height) from grouper where age = 27 group by age, color;"),
// ExpHdrs: hdrs(
// hdr("age", fldTypeInt),
// hdr("color", fldTypeString),
// hdr("", fldTypeInt),
// ),
// ExpRows: rows(
// row(int64(27), "blue", int64(100)),
// row(int64(27), "green", int64(50)),
// ),
// Compare: CompareExactUnordered,
// },
// {
// // GroupBy(Rows(field='age'),limit=100,having=Condition(count>1))
// SQLs: sqls("select age, count(*) as cnt from grouper group by age having count(*) > 1;"),
// ExpHdrs: hdrs(
// hdr("age", fldTypeInt),
// hdr("", fldTypeInt),
// ),
// ExpRows: rows(
// row(int64(16), int64(4)),
// row(int64(27), int64(3)),
// ),
// Compare: CompareExactUnordered,
// },
// {
// // GroupBy(Rows(field='age'),limit=100,having=Condition(1<=count<=3))
// SQLs: sqls("select age, count(*) from grouper group by age having count(*) between 1 and 3;"),
// ExpHdrs: hdrs(
// hdr("age", fldTypeInt),
// hdr("", fldTypeInt),
// ),
// ExpRows: rows(
// row(int64(19), int64(1)),
// row(int64(27), int64(3)),
// row(int64(31), int64(1)),
// row(int64(34), int64(1)),
// ),
// Compare: CompareExactUnordered,
// },
// {
// // GroupBy(Rows(field='age'),limit=3)
// SQLs: sqls("select age, count(*) as cnt from grouper group by age order by cnt desc, age desc limit 3;"),
// ExpHdrs: hdrs(
// hdr("age", fldTypeInt),
// hdr("cnt", fldTypeInt),
// ),
// ExpRows: rows(
// row(int64(16), int64(4)),
// row(int64(27), int64(3)),
// row(int64(19), int64(1)),
// ),
// Compare: CompareExactOrdered,
// },
{
// GroupBy(Rows(field='age'),Rows(field='height'),filter=Intersect(Row(timestamp>"2017-09-02T12:32:00Z"),Row(height>40)))
SQLs: sqls("select age, height from grouper where timestamp > '2017-09-02T12:32:00Z' and height > 40 group by age, height;"),
ExpHdrs: hdrs(
hdr("age", fldTypeInt),
hdr("height", fldTypeInt),
),
ExpRows: rows(
row(int64(16), int64(90)),
row(int64(31), int64(110)),
),
Compare: CompareExactUnordered,
},
{
// Extract(Union(Row(timestamp>"2017-09-02T12:32:00Z"),Row(height>90)),Rows(age), Rows(height))
SQLs: sqls("select age, height from grouper where timestamp > '2017-09-02T12:32:00Z' or height > 90;"),
ExpHdrs: hdrs(
hdr("age", fldTypeInt),
hdr("height", fldTypeInt),
),
ExpRows: rows(
row(int64(16), int64(90)),
row(int64(16), int64(100)),
row(int64(31), int64(110)),
),
Compare: CompareExactUnordered,
},
{
//Extract(Intersect(Row(timestamp>"2017-09-02T12:32:00Z"),Row(timestamp<"2019-09-02T12:32:00Z")),Rows(age), Rows(height))
SQLs: sqls("select age, height from grouper where timestamp > '2017-09-02T12:32:00Z' and timestamp < '2019-09-02T12:32:00Z';"),
ExpHdrs: hdrs(
hdr("age", fldTypeInt),
hdr("height", fldTypeInt),
),
ExpRows: rows(
row(int64(31), int64(110)),
),
Compare: CompareExactUnordered,
},
{
//Extract(Intersect(Row(timestamp>"2017-09-02T12:32:00Z"),Row(timestamp<"2019-09-02T12:32:00Z")),Rows(age), Rows(height))
//Testing the parenthesis around where clause
SQLs: sqls("select age, height from grouper where (timestamp > '2017-09-02T12:32:00Z' and timestamp < '2019-09-02T12:32:00Z');"),
ExpHdrs: hdrs(
hdr("age", fldTypeInt),
hdr("height", fldTypeInt),
),
ExpRows: rows(
row(int64(31), int64(110)),
),
Compare: CompareExactUnordered,
},
{
//Testing empty parenthesis around where clause
SQLs: sqls("select age, height from grouper where ();"),
ExpErr: "expected expression, found",
},
{
//Distinct(Row(timestamp>"2019-09-02T12:32:00Z"), index='grouper',field='age')
SQLs: sqls("select distinct age from grouper where timestamp > '2019-09-02T12:32:00Z';"),
ExpHdrs: hdrs(
hdr("age", fldTypeInt),
),
ExpRows: rows(
row(int64(16)),
),
Compare: CompareExactUnordered,
},
{
SQLs: sqls("show tables;"),
ExpHdrs: hdrs(
hdr("_id", fldTypeString),
hdr("name", fldTypeString),
hdr("owner", fldTypeString),
hdr("updated_by", fldTypeString),
hdr("created_at", fldTypeTimestamp),
hdr("updated_at", fldTypeTimestamp),
hdr("keys", fldTypeBool),
hdr("space_used", fldTypeInt),
hdr("description", fldTypeString),
),
ExpRows: rows(
row(nil, "grouper"),
row(nil, "joiner"),
row(nil, "delete_me"),
),
Compare: ComparePartial,
},
{
SQLs: sqls("show columns from grouper;"),
ExpHdrs: hdrs(
hdr("_id", fldTypeString),
hdr("name", fldTypeString),
hdr("type", fldTypeString),
hdr("created_at", fldTypeTimestamp),
hdr("keys", fldTypeBool),
hdr("cache_type", fldTypeString),
hdr("cache_size", fldTypeInt),
hdr("scale", fldTypeInt),
hdr("min", fldTypeInt),
hdr("max", fldTypeInt),
hdr("timeunit", fldTypeString),
hdr("epoch", fldTypeInt),
hdr("timequantum", fldTypeString),
hdr("ttl", fldTypeString),
),
ExpRows: rows(
row(nil, string("age"), string("int")),
row(nil, string("color"), string("string")),
row(nil, string("height"), string("int")),
row(nil, string("score"), string("int")),
row(nil, string("timestamp"), string("timestamp")),
),
Compare: ComparePartial,
},
// {
// SQLs: sqls("drop table delete_me;"),
// ExpHdrs: hdrs(),
// ExpRows: rows(),
// Compare: CompareExactOrdered,
// },
// The following cases test different paths within the `case *sqlparser.AndExpr`
// of extract.go by providing different WHERE conditions.
{
// len(left) == 2 && len(right) == 1
// right[0].table == left[0].table
SQLs: sqls("select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where g.color = 'red' and j.jointype = 2 and g.age = 16;"),
ExpHdrs: hdrs(hdr("_id", fldTypeID)),
ExpRows: rows(
row(int64(9)),
),
Compare: CompareExactUnordered,
},
{
// len(left) == 2 && len(right) == 1
// right[0].table == left[1].table {
SQLs: sqls("select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where j.jointype = 2 and g.color = 'red' and g.age = 16;"),
ExpHdrs: hdrs(hdr("_id", fldTypeID)),
ExpRows: rows(
row(int64(9)),
),
Compare: CompareExactUnordered,
},
{
// len(left) == 1 && len(right) == 1 && left[0].table != right[0].table
SQLs: sqls("select _id from grouper g INNER JOIN joiner j ON g._id = j.grouperid where g.color = 'red' and g.age = 16 and j.jointype = 2;"),
ExpHdrs: hdrs(hdr("_id", fldTypeID)),
ExpRows: rows(
row(int64(9)),
),
Compare: CompareExactUnordered,
},
{
SQLs: sqls("select * from index_not_found;"),
ExpErr: "table or view 'index_not_found' not found",
},
{
SQLs: sqls("select field_not_found from grouper;"),
ExpErr: "column 'field_not_found' not found",
},
{
SQLs: sqls("select * from grouper, index_not_found;"),
ExpErr: "table or view 'index_not_found' not found",
},
{
SQLs: sqls("select _id, age, field_not_found from grouper;"),
ExpErr: "column 'field_not_found' not found",
},
{
SQLs: sqls("select age, color, count(*) from grouper group by field_not_found, age, color;"),
ExpErr: "column 'field_not_found' not found",
},
{
SQLs: sqls("select count(*) from grouper inner join joiner on grouper._id = joiner.field_not_found;"),
ExpErr: "column 'field_not_found' not found",
},
},
}