Skip to content

Commit

Permalink
Prevent index creation on undeclared path
Browse files Browse the repository at this point in the history
  • Loading branch information
asdine committed Jun 27, 2022
1 parent 22fc22c commit 3f32bcb
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 52 deletions.
4 changes: 2 additions & 2 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestOpen(t *testing.T) {
err = db.Exec(`
CREATE TABLE tableA (a INTEGER UNIQUE NOT NULL, b (c (d DOUBLE PRIMARY KEY)));
CREATE TABLE tableB (a TEXT NOT NULL DEFAULT 'hello', PRIMARY KEY (a));
CREATE TABLE tableC;
CREATE TABLE tableC (a INTEGER, b BOOL);
CREATE INDEX tableC_a_b_idx ON tableC(a, b);
CREATE SEQUENCE seqD INCREMENT BY 10 CYCLE MINVALUE 100 NO MAXVALUE START 500;
Expand Down Expand Up @@ -116,7 +116,7 @@ func TestOpen(t *testing.T) {
`{"name":"tableA", "sql":"CREATE TABLE tableA (a INTEGER NOT NULL, b (c (d DOUBLE NOT NULL)), CONSTRAINT tableA_a_unique UNIQUE (a), CONSTRAINT tableA_pk PRIMARY KEY (b.c.d))", "namespace":10, "type":"table"}`,
`{"name":"tableA_a_idx", "owner":{"table_name":"tableA", "paths":["a"]}, "sql":"CREATE UNIQUE INDEX tableA_a_idx ON tableA (a)", "namespace":11, "type":"index"}`,
`{"name":"tableB", "sql":"CREATE TABLE tableB (a TEXT NOT NULL DEFAULT \"hello\", CONSTRAINT tableB_pk PRIMARY KEY (a))", "namespace":12, "type":"table"}`,
`{"name":"tableC", "docid_sequence_name":"tableC_seq", "sql":"CREATE TABLE tableC (...)", "namespace":13, "type":"table"}`,
`{"name":"tableC", "docid_sequence_name":"tableC_seq", "sql":"CREATE TABLE tableC (a INTEGER, b BOOLEAN)", "namespace":13, "type":"table"}`,
`{"name":"tableC_a_b_idx", "owner":{"table_name":"tableC"}, "sql":"CREATE INDEX tableC_a_b_idx ON tableC (a, b)", "namespace":14, "type":"index"}`,
`{"name":"tableC_seq", "owner":{"table_name":"tableC"}, "sql":"CREATE SEQUENCE tableC_seq CACHE 64", "type":"sequence"}`,
}
Expand Down
2 changes: 1 addition & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Example() {
defer db.Close()

// Create a table. Genji tables are schemaless by default, you don't need to specify a schema.
err = db.Exec("CREATE TABLE user")
err = db.Exec("CREATE TABLE user (name text, ...)")
if err != nil {
panic(err)
}
Expand Down
10 changes: 9 additions & 1 deletion internal/database/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,19 @@ func (c *Catalog) CreateIndex(tx *Transaction, info *IndexInfo) error {
}

// check if the associated table exists
_, err = c.GetTableInfo(info.Owner.TableName)
ti, err := c.GetTableInfo(info.Owner.TableName)
if err != nil {
return err
}

// check if the indexed fields exist
for _, p := range info.Paths {
fc := ti.GetFieldConstraintForPath(p)
if fc == nil {
return errors.Errorf("field %q does not exist for table %q", p, ti.TableName)
}
}

info.StoreNamespace, err = c.generateStoreName(tx)
if err != nil {
return err
Expand Down
38 changes: 31 additions & 7 deletions internal/database/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ func TestCatalogCreateIndex(t *testing.T) {

updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error {
return catalog.CreateTable(tx, "test", &database.TableInfo{
FieldConstraints: database.MustNewFieldConstraints(
&database.FieldConstraint{Field: "a", Type: types.TextValue},
),
TableConstraints: []*database.TableConstraint{
{Paths: []document.Path{testutil.ParseDocumentPath(t, "a")}, PrimaryKey: true},
},
Expand Down Expand Up @@ -321,7 +324,11 @@ func TestCatalogCreateIndex(t *testing.T) {
db := testutil.NewTestDB(t)

updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error {
return catalog.CreateTable(tx, "test", nil)
return catalog.CreateTable(tx, "test", &database.TableInfo{
FieldConstraints: database.MustNewFieldConstraints(
&database.FieldConstraint{Field: "foo", Type: types.TextValue},
),
})
})

updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error {
Expand Down Expand Up @@ -356,25 +363,37 @@ func TestCatalogCreateIndex(t *testing.T) {
db := testutil.NewTestDB(t)

updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error {
return catalog.CreateTable(tx, "test", nil)
return catalog.CreateTable(tx, "test", &database.TableInfo{
FieldConstraints: database.MustNewFieldConstraints(
&database.FieldConstraint{Field: "foo", Type: types.DocumentValue, AnonymousType: &database.AnonymousType{
FieldConstraints: database.MustNewFieldConstraints(
&database.FieldConstraint{Field: " bar ", Type: types.DocumentValue, AnonymousType: &database.AnonymousType{
FieldConstraints: database.MustNewFieldConstraints(
&database.FieldConstraint{Field: "c", Type: types.TextValue},
),
}},
),
}},
),
})
})

updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error {
err := catalog.CreateIndex(tx, &database.IndexInfo{
Owner: database.Owner{TableName: "test"}, Paths: []document.Path{testutil.ParseDocumentPath(t, "foo.a[10].` bar `.c")},
Owner: database.Owner{TableName: "test"}, Paths: []document.Path{testutil.ParseDocumentPath(t, "foo.` bar `.c")},
})
assert.NoError(t, err)

_, err = catalog.GetIndex(tx, "test_foo.a[10]. bar .c_idx")
_, err = catalog.GetIndex(tx, "test_foo. bar .c_idx")
assert.NoError(t, err)

// create another one
err = catalog.CreateIndex(tx, &database.IndexInfo{
Owner: database.Owner{TableName: "test"}, Paths: []document.Path{testutil.ParseDocumentPath(t, "foo.a[10].` bar `.c")},
Owner: database.Owner{TableName: "test"}, Paths: []document.Path{testutil.ParseDocumentPath(t, "foo.` bar `.c")},
})
assert.NoError(t, err)

_, err = catalog.GetIndex(tx, "test_foo.a[10]. bar .c_idx1")
_, err = catalog.GetIndex(tx, "test_foo. bar .c_idx1")
assert.NoError(t, err)
return nil
})
Expand All @@ -386,7 +405,12 @@ func TestTxDropIndex(t *testing.T) {
db := testutil.NewTestDB(t)

updateCatalog(t, db, func(tx *database.Transaction, catalog *database.Catalog) error {
err := catalog.CreateTable(tx, "test", nil)
err := catalog.CreateTable(tx, "test", &database.TableInfo{
FieldConstraints: database.MustNewFieldConstraints(
&database.FieldConstraint{Field: "foo", Type: types.TextValue},
&database.FieldConstraint{Field: "bar", Type: types.AnyValue},
),
})
assert.NoError(t, err)
err = catalog.CreateIndex(tx, &database.IndexInfo{
IndexName: "idxFoo", Owner: database.Owner{TableName: "test"}, Paths: []document.Path{testutil.ParseDocumentPath(t, "foo")},
Expand Down
21 changes: 1 addition & 20 deletions internal/database/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,26 +168,7 @@ func (ti *TableInfo) GetPrimaryKey() *PrimaryKey {
}

func (ti *TableInfo) GetFieldConstraintForPath(p document.Path) *FieldConstraint {
var cur *FieldConstraints = &ti.FieldConstraints
for i := range p {
if cur == nil {
return nil
}
fc, ok := cur.ByField[p[i].FieldName]
if !ok {
return nil
}
if i == len(p)-1 {
return fc
}

if fc.AnonymousType == nil {
return nil
}
cur = &fc.AnonymousType.FieldConstraints
}

return nil
return ti.FieldConstraints.GetFieldConstraintForPath(p)
}

// String returns a SQL representation.
Expand Down
12 changes: 6 additions & 6 deletions internal/planner/optimizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func TestSelectIndex_Simple(t *testing.T) {
defer cleanup()

testutil.MustExec(t, db, tx, `
CREATE TABLE foo (k INT PRIMARY KEY, c INT);
CREATE TABLE foo (k INT PRIMARY KEY, a INT, b INT, c INT, d ANY);
CREATE INDEX idx_foo_a ON foo(a);
CREATE INDEX idx_foo_b ON foo(b);
CREATE UNIQUE INDEX idx_foo_c ON foo(c);
Expand Down Expand Up @@ -700,7 +700,7 @@ func TestSelectIndex_Composite(t *testing.T) {
defer cleanup()

testutil.MustExec(t, db, tx, `
CREATE TABLE foo (k INT PRIMARY KEY, c INT);
CREATE TABLE foo (k INT PRIMARY KEY, a ANY, b ANY, c INT, d ANY, x ANY, y ANY, z ANY);
CREATE INDEX idx_foo_a ON foo(a);
CREATE INDEX idx_foo_b ON foo(b);
CREATE UNIQUE INDEX idx_foo_c ON foo(c);
Expand Down Expand Up @@ -754,10 +754,10 @@ func TestSelectIndex_Composite(t *testing.T) {
testutil.MustExec(t, db, tx, `
CREATE TABLE foo (
k ARRAY PRIMARY KEY,
a ARRAY
a ARRAY,
b ANY
);
CREATE INDEX idx_foo_a_b ON foo(a, b);
CREATE INDEX idx_foo_a0 ON foo(a[0]);
INSERT INTO foo (k, a, b) VALUES
([1, 1], [1, 1], [1, 1]),
([2, 2], [2, 2], [2, 2]),
Expand Down Expand Up @@ -848,8 +848,8 @@ func TestOptimize(t *testing.T) {
db, tx, cleanup := testutil.NewTestTx(t)
defer cleanup()
testutil.MustExec(t, db, tx, `
CREATE TABLE foo;
CREATE TABLE bar;
CREATE TABLE foo(a any, d any);
CREATE TABLE bar(a, d);
CREATE INDEX idx_foo_a_d ON foo(a, d);
CREATE INDEX idx_bar_a_d ON bar(a, d);
`)
Expand Down
12 changes: 6 additions & 6 deletions internal/query/statement/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ func TestCreateIndex(t *testing.T) {
{"Basic", "CREATE INDEX idx ON test (foo)", false},
{"If not exists", "CREATE INDEX IF NOT EXISTS idx ON test (foo.bar)", false},
{"Duplicate", "CREATE INDEX idx ON test (foo.bar);CREATE INDEX idx ON test (foo.bar)", true},
{"Unique", "CREATE UNIQUE INDEX IF NOT EXISTS idx ON test (foo[1])", false},
{"No name", "CREATE UNIQUE INDEX ON test (foo[1])", false},
{"No name if not exists", "CREATE UNIQUE INDEX IF NOT EXISTS ON test (foo[1])", true},
{"Unique", "CREATE UNIQUE INDEX IF NOT EXISTS idx ON test (foo)", false},
{"No name", "CREATE UNIQUE INDEX ON test (foo)", false},
{"No name if not exists", "CREATE UNIQUE INDEX IF NOT EXISTS ON test (foo)", true},
{"No fields", "CREATE INDEX idx ON test", true},
{"Composite (2)", "CREATE INDEX idx ON test (foo, bar)", false},
{"Composite (4)", "CREATE INDEX idx ON test (foo, bar, baz, baf)", false},
{"Composite (2)", "CREATE INDEX idx ON test (foo, baz)", false},
{"Composite (3)", "CREATE INDEX idx ON test (foo, baz, baf)", false},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
db, tx, cleanup := testutil.NewTestTx(t)
defer cleanup()

testutil.MustExec(t, db, tx, "CREATE TABLE test")
testutil.MustExec(t, db, tx, "CREATE TABLE test(foo (bar TEXT), baz any, baf any)")

err := testutil.Exec(db, tx, test.query)
if test.fails {
Expand Down
2 changes: 1 addition & 1 deletion internal/query/statement/explain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestExplainStmt(t *testing.T) {
assert.NoError(t, err)
defer db.Close()

err = db.Exec("CREATE TABLE test (k INTEGER PRIMARY KEY)")
err = db.Exec("CREATE TABLE test (k INTEGER PRIMARY KEY, a any, b any, x any, y any)")
assert.NoError(t, err)
err = db.Exec(`
CREATE INDEX idx_a ON test (a);
Expand Down
2 changes: 1 addition & 1 deletion internal/query/statement/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestInsertStmt(t *testing.T) {
assert.NoError(t, err)
defer db.Close()

err = db.Exec("CREATE TABLE test")
err = db.Exec("CREATE TABLE test(a any, b any, c any)")
assert.NoError(t, err)
if withIndexes {
err = db.Exec(`
Expand Down
4 changes: 2 additions & 2 deletions internal/query/statement/reindex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func TestReIndex(t *testing.T) {
defer cleanup()

testutil.MustExec(t, db, tx, `
CREATE TABLE test1;
CREATE TABLE test2;
CREATE TABLE test1(a any, b any);
CREATE TABLE test2(a any, b any);
CREATE INDEX idx_test1_a ON test1(a);
CREATE INDEX idx_test1_b ON test1(b);
Expand Down
4 changes: 2 additions & 2 deletions internal/query/statement/select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func TestSelectStmt(t *testing.T) {
assert.NoError(t, err)
defer db.Close()

err = db.Exec("CREATE TABLE test; CREATE INDEX idx_foo ON test(foo);")
err = db.Exec("CREATE TABLE test(foo any); CREATE INDEX idx_foo ON test(foo);")
assert.NoError(t, err)

err = db.Exec(`INSERT INTO test (foo) VALUES (1), ('hello'), (2), (true)`)
Expand Down Expand Up @@ -293,7 +293,7 @@ func TestSelectStmt(t *testing.T) {
defer db.Close()

err = db.Exec(`
CREATE TABLE test;
CREATE TABLE test(a any);
INSERT INTO test (a) VALUES ([1,2,3]), ([4, 5, 6]);
`)
assert.NoError(t, err)
Expand Down
2 changes: 2 additions & 0 deletions internal/testutil/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ func Query(db *database.Database, tx *database.Transaction, q string, params ...
}

func MustExec(t *testing.T, db *database.Database, tx *database.Transaction, q string, params ...environment.Param) {
t.Helper()

err := Exec(db, tx, q, params...)
assert.NoError(t, err)
}
Expand Down
2 changes: 1 addition & 1 deletion sqltests/CREATE_INDEX/base.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- setup:
CREATE TABLE test;
CREATE TABLE test (a int);

-- test: named index
CREATE INDEX test_a_idx ON test(a);
Expand Down
19 changes: 19 additions & 0 deletions sqltests/CREATE_INDEX/undeclared.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- test: undeclared field
CREATE TABLE test;
CREATE INDEX test_a_idx ON test(a);
-- error:

-- test: undeclared field: IF NOT EXISTS
CREATE TABLE test;
CREATE INDEX IF NOT EXISTS test_a_idx ON test(a);
-- error:

-- test: undeclared field: other fields
CREATE TABLE test(b int);
CREATE INDEX test_a_idx ON test(a);
-- error:

-- test: undeclared field: variadic
CREATE TABLE test(b int, ...);
CREATE INDEX test_a_idx ON test(a);
-- error:
2 changes: 1 addition & 1 deletion sqltests/SELECT/order_by.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- setup:
CREATE TABLE test;
CREATE TABLE test(a double);
INSERT INTO test (a) VALUES (1), (2), (3);

-- suite: no index
Expand Down
2 changes: 1 addition & 1 deletion sqltests/SELECT/projection_table.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- setup:
CREATE TABLE test;
CREATE TABLE test(a double, ...);
INSERT INTO test(a, b, c) VALUES (1, {a: 1}, [true]);

-- suite: no index
Expand Down

0 comments on commit 3f32bcb

Please sign in to comment.