package parser_test import ( "math" "testing" "github.com/chaisql/chai/internal/database" "github.com/chaisql/chai/internal/query/statement" "github.com/chaisql/chai/internal/sql/parser" "github.com/stretchr/testify/require" ) func TestParserCreateIndex(t *testing.T) { tests := []struct { name string s string expected statement.Statement errored bool }{ {"Basic", "CREATE INDEX idx ON test (foo)", &statement.CreateIndexStmt{ Info: database.IndexInfo{ IndexName: "idx", Owner: database.Owner{TableName: "test"}, Columns: []string{"foo"}, }}, false}, {"If not exists", "CREATE INDEX IF NOT EXISTS idx ON test (foo)", &statement.CreateIndexStmt{ Info: database.IndexInfo{ IndexName: "idx", Owner: database.Owner{TableName: "test"}, Columns: []string{"foo"}, }, IfNotExists: true}, false}, {"Unique", "CREATE UNIQUE INDEX IF NOT EXISTS idx ON test (foo)", &statement.CreateIndexStmt{ Info: database.IndexInfo{ IndexName: "idx", Owner: database.Owner{TableName: "test"}, Columns: []string{"foo"}, Unique: true, }, IfNotExists: true}, false}, {"No name", "CREATE UNIQUE INDEX ON test (foo)", &statement.CreateIndexStmt{ Info: database.IndexInfo{Owner: database.Owner{TableName: "test"}, Columns: []string{"foo"}, Unique: true}}, false}, {"No name with IF NOT EXISTS", "CREATE UNIQUE INDEX IF NOT EXISTS ON test (foo)", nil, true}, {"More than 1 path", "CREATE INDEX idx ON test (foo, bar)", &statement.CreateIndexStmt{ Info: database.IndexInfo{ IndexName: "idx", Owner: database.Owner{TableName: "test"}, Columns: []string{ "foo", "bar", }, }, }, false}, {"No fields", "CREATE INDEX idx ON test", nil, true}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { stmts, err := parser.ParseQuery(test.s) if test.errored { require.Error(t, err) return } require.NoError(t, err) require.Len(t, stmts, 1) require.EqualValues(t, test.expected, stmts[0]) }) } } func TestParserCreateSequence(t *testing.T) { tests := []struct { name string s string expected statement.Statement errored bool }{ {"Basic", "CREATE SEQUENCE seq", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"If not exists", "CREATE SEQUENCE IF NOT EXISTS seq", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, IfNotExists: true, }, false}, {"AS integer", "CREATE SEQUENCE seq AS TINYINT", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"AS double", "CREATE SEQUENCE seq AS DOUBLE", nil, true}, {"INCREMENT", "CREATE SEQUENCE seq INCREMENT 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 10, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"INCREMENT BY", "CREATE SEQUENCE seq INCREMENT BY 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 10, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"INCREMENT BY 0", "CREATE SEQUENCE seq INCREMENT BY 0", nil, true}, {"NO MINVALUE", "CREATE SEQUENCE seq NO MINVALUE", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"NO MAXVALUE", "CREATE SEQUENCE seq NO MAXVALUE", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"NO CYCLE", "CREATE SEQUENCE seq NO CYCLE", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1}, }, false}, {"NO SUGAR", "CREATE SEQUENCE seq NO SUGAR", nil, true}, {"MINVALUE 10", "CREATE SEQUENCE seq MINVALUE 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 10, Max: math.MaxInt64, Start: 10, Cache: 1}, }, false}, {"MINVALUE 'hello'", "CREATE SEQUENCE seq MINVALUE 'hello'", nil, true}, {"MAXVALUE 10", "CREATE SEQUENCE seq MAXVALUE 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: 10, Start: 1, Cache: 1}, }, false}, {"MAXVALUE 'hello'", "CREATE SEQUENCE seq MAXVALUE 'hello'", nil, true}, {"START WITH 10", "CREATE SEQUENCE seq START WITH 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 10, Cache: 1}, }, false}, {"START WITH 'hello'", "CREATE SEQUENCE seq START WITH 'hello'", nil, true}, {"START 10", "CREATE SEQUENCE seq START 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 10, Cache: 1}, }, false}, {"CACHE 10", "CREATE SEQUENCE seq CACHE 10", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 10}, }, false}, {"CACHE 'hello'", "CREATE SEQUENCE seq CACHE 'hello'", nil, true}, {"CACHE -10", "CREATE SEQUENCE seq CACHE -10", nil, true}, {"CYCLE", "CREATE SEQUENCE seq CYCLE", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: 1, Min: 1, Max: math.MaxInt64, Start: 1, Cache: 1, Cycle: true}, }, false}, {"Order 1", ` CREATE SEQUENCE IF NOT EXISTS seq AS INTEGER INCREMENT BY 2 NO MINVALUE MAXVALUE 10 START WITH 5 CACHE 5 CYCLE `, &statement.CreateSequenceStmt{ IfNotExists: true, Info: database.SequenceInfo{ Name: "seq", IncrementBy: 2, Min: 1, Max: 10, Start: 5, Cache: 5, Cycle: true, }, }, false}, {"Order 2", ` CREATE SEQUENCE IF NOT EXISTS seq CYCLE MAXVALUE 10 INCREMENT BY 2 START WITH 5 AS INTEGER NO MINVALUE CACHE 5 `, &statement.CreateSequenceStmt{ IfNotExists: true, Info: database.SequenceInfo{ Name: "seq", IncrementBy: 2, Min: 1, Max: 10, Start: 5, Cache: 5, Cycle: true, }, }, false}, {"NO MINVALUE with MINVALUE 10", "CREATE SEQUENCE seq NO MINVALUE MINVALUE 10", nil, true}, {"NO MAXVALUE with MAXVALUE 10", "CREATE SEQUENCE seq NO MAXVALUE MAXVALUE 10", nil, true}, {"NO CYCLE with CYCLE", "CREATE SEQUENCE seq NO MAXVALUE MAXVALUE 10", nil, true}, {"duplicate AS INT", "CREATE SEQUENCE seq AS INT AS INT", nil, true}, {"duplicate INCREMENT BY", "CREATE SEQUENCE seq INCREMENT BY 10 INCREMENT BY 10", nil, true}, {"duplicate NO MINVALUE", "CREATE SEQUENCE seq NO MINVALUE NO MINVALUE", nil, true}, {"duplicate NO MAXVALUE", "CREATE SEQUENCE seq NO MAXVALUE NO MAXVALUE", nil, true}, {"duplicate NO CYCLE", "CREATE SEQUENCE seq NO CYCLE NO CYCLE", nil, true}, {"duplicate MINVALUE", "CREATE SEQUENCE seq MINVALUE 10 MINVALUE 10", nil, true}, {"duplicate MAXVALUE", "CREATE SEQUENCE seq MAXVALUE 10 MAXVALUE 10", nil, true}, {"duplicate START WITH", "CREATE SEQUENCE seq START WITH 10 START WITH 10", nil, true}, {"duplicate CACHE", "CREATE SEQUENCE seq CACHE 10 CACHE 10", nil, true}, {"duplicate CYCLE", "CREATE SEQUENCE seq CYCLE CYCLE", nil, true}, {"BAD MINVALUE MAXVALUE", "CREATE SEQUENCE seq MINVALUE 10 MAXVALUE 5", nil, true}, {"BAD START", "CREATE SEQUENCE seq MINVALUE 5 MAXVALUE 10 START 100", nil, true}, {"BAD START", "CREATE SEQUENCE seq MINVALUE 5 MAXVALUE 10 START -100", nil, true}, {"MINVALUE 10 DESC", "CREATE SEQUENCE seq MINVALUE 10 MAXVALUE 100 INCREMENT BY -1", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: -1, Min: 10, Max: 100, Start: 100, Cache: 1}, }, false}, {"NO MINVALUE DESC", "CREATE SEQUENCE seq NO MINVALUE MAXVALUE 100 INCREMENT BY -1", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: -1, Min: math.MinInt64, Max: 100, Start: 100, Cache: 1}, }, false}, {"NO MAXVALUE DESC", "CREATE SEQUENCE seq NO MINVALUE NO MAXVALUE INCREMENT BY -1", &statement.CreateSequenceStmt{ Info: database.SequenceInfo{Name: "seq", IncrementBy: -1, Min: math.MinInt64, Max: -1, Start: -1, Cache: 1}, }, false}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { stmts, err := parser.ParseQuery(test.s) if test.errored { require.Error(t, err) return } require.NoError(t, err) require.Len(t, stmts, 1) require.EqualValues(t, test.expected, stmts[0]) }) } }