Skip to content

Commit 4eafaab

Browse files
committed
Implemented CREATE TABLE LIKE and updated information_schema.
1 parent e81d5c8 commit 4eafaab

File tree

10 files changed

+277
-97
lines changed

10 files changed

+277
-97
lines changed

enginetest/enginetests.go

Lines changed: 177 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -606,122 +606,208 @@ func TestVersionedViews(t *testing.T, harness Harness) {
606606
}
607607

608608
func TestCreateTable(t *testing.T, harness Harness) {
609-
require := require.New(t)
610-
611609
e := NewEngine(t, harness)
610+
ctx := NewContext(harness)
612611

613-
TestQuery(t, harness, e,
614-
"CREATE TABLE t1(a INTEGER, b TEXT, c DATE, "+
615-
"d TIMESTAMP, e VARCHAR(20), f BLOB NOT NULL, "+
616-
"b1 BOOL, b2 BOOLEAN NOT NULL, g DATETIME, h CHAR(40))",
617-
[]sql.Row(nil),
618-
)
612+
t.Run("Assortment of types without pk", func(t *testing.T) {
613+
TestQuery(t, harness, e,
614+
"CREATE TABLE t1(a INTEGER, b TEXT, c DATE, "+
615+
"d TIMESTAMP, e VARCHAR(20), f BLOB NOT NULL, "+
616+
"b1 BOOL, b2 BOOLEAN NOT NULL, g DATETIME, h CHAR(40))",
617+
[]sql.Row(nil),
618+
)
619619

620-
db, err := e.Catalog.Database("mydb")
621-
require.NoError(err)
620+
db, err := e.Catalog.Database("mydb")
621+
require.NoError(t, err)
622622

623-
ctx := NewContext(harness)
624-
testTable, ok, err := db.GetTableInsensitive(ctx, "t1")
625-
require.NoError(err)
626-
require.True(ok)
623+
ctx := NewContext(harness)
624+
testTable, ok, err := db.GetTableInsensitive(ctx, "t1")
625+
require.NoError(t, err)
626+
require.True(t, ok)
627+
628+
s := sql.Schema{
629+
{Name: "a", Type: sql.Int32, Nullable: true, Source: "t1"},
630+
{Name: "b", Type: sql.Text, Nullable: true, Source: "t1"},
631+
{Name: "c", Type: sql.Date, Nullable: true, Source: "t1"},
632+
{Name: "d", Type: sql.Timestamp, Nullable: true, Source: "t1"},
633+
{Name: "e", Type: sql.MustCreateStringWithDefaults(sqltypes.VarChar, 20), Nullable: true, Source: "t1"},
634+
{Name: "f", Type: sql.Blob, Source: "t1"},
635+
{Name: "b1", Type: sql.Boolean, Nullable: true, Source: "t1"},
636+
{Name: "b2", Type: sql.Boolean, Source: "t1"},
637+
{Name: "g", Type: sql.Datetime, Nullable: true, Source: "t1"},
638+
{Name: "h", Type: sql.MustCreateStringWithDefaults(sqltypes.Char, 40), Nullable: true, Source: "t1"},
639+
}
627640

628-
s := sql.Schema{
629-
{Name: "a", Type: sql.Int32, Nullable: true, Source: "t1"},
630-
{Name: "b", Type: sql.Text, Nullable: true, Source: "t1"},
631-
{Name: "c", Type: sql.Date, Nullable: true, Source: "t1"},
632-
{Name: "d", Type: sql.Timestamp, Nullable: true, Source: "t1"},
633-
{Name: "e", Type: sql.MustCreateStringWithDefaults(sqltypes.VarChar, 20), Nullable: true, Source: "t1"},
634-
{Name: "f", Type: sql.Blob, Source: "t1"},
635-
{Name: "b1", Type: sql.Boolean, Nullable: true, Source: "t1"},
636-
{Name: "b2", Type: sql.Boolean, Source: "t1"},
637-
{Name: "g", Type: sql.Datetime, Nullable: true, Source: "t1"},
638-
{Name: "h", Type: sql.MustCreateStringWithDefaults(sqltypes.Char, 40), Nullable: true, Source: "t1"},
639-
}
641+
require.Equal(t, s, testTable.Schema())
642+
})
640643

641-
require.Equal(s, testTable.Schema())
644+
t.Run("Primary key declared in column", func(t *testing.T) {
645+
TestQuery(t, harness, e,
646+
"CREATE TABLE t2 (a INTEGER NOT NULL PRIMARY KEY, "+
647+
"b VARCHAR(10) NOT NULL)",
648+
[]sql.Row(nil),
649+
)
642650

643-
TestQuery(t, harness, e,
644-
"CREATE TABLE t2 (a INTEGER NOT NULL PRIMARY KEY, "+
645-
"b VARCHAR(10) NOT NULL)",
646-
[]sql.Row(nil),
647-
)
651+
db, err := e.Catalog.Database("mydb")
652+
require.NoError(t, err)
648653

649-
db, err = e.Catalog.Database("mydb")
650-
require.NoError(err)
654+
testTable, ok, err := db.GetTableInsensitive(ctx, "t2")
655+
require.NoError(t, err)
656+
require.True(t, ok)
651657

652-
testTable, ok, err = db.GetTableInsensitive(ctx, "t2")
653-
require.NoError(err)
654-
require.True(ok)
658+
s := sql.Schema{
659+
{Name: "a", Type: sql.Int32, Nullable: false, PrimaryKey: true, Source: "t2"},
660+
{Name: "b", Type: sql.MustCreateStringWithDefaults(sqltypes.VarChar, 10), Nullable: false, Source: "t2"},
661+
}
655662

656-
s = sql.Schema{
657-
{Name: "a", Type: sql.Int32, Nullable: false, PrimaryKey: true, Source: "t2"},
658-
{Name: "b", Type: sql.MustCreateStringWithDefaults(sqltypes.VarChar, 10), Nullable: false, Source: "t2"},
659-
}
663+
require.Equal(t, s, testTable.Schema())
664+
})
660665

661-
require.Equal(s, testTable.Schema())
666+
t.Run("Multiple primary keys", func(t *testing.T) {
667+
TestQuery(t, harness, e,
668+
"CREATE TABLE t3(a INTEGER NOT NULL,"+
669+
"b TEXT NOT NULL,"+
670+
"c bool, primary key (a,b))",
671+
[]sql.Row(nil),
672+
)
662673

663-
TestQuery(t, harness, e,
664-
"CREATE TABLE t3(a INTEGER NOT NULL,"+
665-
"b TEXT NOT NULL,"+
666-
"c bool, primary key (a,b))",
667-
[]sql.Row(nil),
668-
)
674+
db, err := e.Catalog.Database("mydb")
675+
require.NoError(t, err)
669676

670-
db, err = e.Catalog.Database("mydb")
671-
require.NoError(err)
677+
testTable, ok, err := db.GetTableInsensitive(ctx, "t3")
678+
require.NoError(t, err)
679+
require.True(t, ok)
672680

673-
testTable, ok, err = db.GetTableInsensitive(ctx, "t3")
674-
require.NoError(err)
675-
require.True(ok)
681+
s := sql.Schema{
682+
{Name: "a", Type: sql.Int32, Nullable: false, PrimaryKey: true, Source: "t3"},
683+
{Name: "b", Type: sql.Text, Nullable: false, PrimaryKey: true, Source: "t3"},
684+
{Name: "c", Type: sql.Boolean, Nullable: true, Source: "t3"},
685+
}
676686

677-
s = sql.Schema{
678-
{Name: "a", Type: sql.Int32, Nullable: false, PrimaryKey: true, Source: "t3"},
679-
{Name: "b", Type: sql.Text, Nullable: false, PrimaryKey: true, Source: "t3"},
680-
{Name: "c", Type: sql.Boolean, Nullable: true, Source: "t3"},
681-
}
687+
require.Equal(t, s, testTable.Schema())
688+
})
682689

683-
require.Equal(s, testTable.Schema())
690+
t.Run("Including comment", func(t *testing.T) {
691+
TestQuery(t, harness, e,
692+
"CREATE TABLE t4(a INTEGER,"+
693+
"b TEXT NOT NULL COMMENT 'comment',"+
694+
"c bool, primary key (a))",
695+
[]sql.Row(nil),
696+
)
684697

685-
TestQuery(t, harness, e,
686-
"CREATE TABLE t4(a INTEGER,"+
687-
"b TEXT NOT NULL COMMENT 'comment',"+
688-
"c bool, primary key (a))",
689-
[]sql.Row(nil),
690-
)
698+
db, err := e.Catalog.Database("mydb")
699+
require.NoError(t, err)
691700

692-
db, err = e.Catalog.Database("mydb")
693-
require.NoError(err)
701+
testTable, ok, err := db.GetTableInsensitive(ctx, "t4")
702+
require.NoError(t, err)
703+
require.True(t, ok)
694704

695-
testTable, ok, err = db.GetTableInsensitive(ctx, "t4")
696-
require.NoError(err)
697-
require.True(ok)
705+
s := sql.Schema{
706+
{Name: "a", Type: sql.Int32, Nullable: false, PrimaryKey: true, Source: "t4"},
707+
{Name: "b", Type: sql.Text, Nullable: false, PrimaryKey: false, Source: "t4", Comment: "comment"},
708+
{Name: "c", Type: sql.Boolean, Nullable: true, Source: "t4"},
709+
}
698710

699-
s = sql.Schema{
700-
{Name: "a", Type: sql.Int32, Nullable: false, PrimaryKey: true, Source: "t4"},
701-
{Name: "b", Type: sql.Text, Nullable: false, PrimaryKey: false, Source: "t4", Comment: "comment"},
702-
{Name: "c", Type: sql.Boolean, Nullable: true, Source: "t4"},
703-
}
711+
require.Equal(t, s, testTable.Schema())
712+
})
704713

705-
require.Equal(s, testTable.Schema())
714+
t.Run("If not exists", func(t *testing.T) {
715+
TestQuery(t, harness, e,
716+
"CREATE TABLE IF NOT EXISTS t4(a INTEGER,"+
717+
"b TEXT NOT NULL,"+
718+
"c bool, primary key (a))",
719+
[]sql.Row(nil),
720+
)
706721

707-
TestQuery(t, harness, e,
708-
"CREATE TABLE IF NOT EXISTS t4(a INTEGER,"+
722+
_, _, err := e.Query(NewContext(harness), "CREATE TABLE t4(a INTEGER,"+
709723
"b TEXT NOT NULL,"+
710-
"c bool, primary key (a))",
711-
[]sql.Row(nil),
712-
)
724+
"c bool, primary key (a))")
725+
require.Error(t, err)
726+
require.True(t, sql.ErrTableAlreadyExists.Is(err))
727+
})
713728

714-
_, _, err = e.Query(NewContext(harness), "CREATE TABLE t4(a INTEGER,"+
715-
"b TEXT NOT NULL,"+
716-
"c bool, primary key (a))")
717-
require.Error(err)
718-
require.True(sql.ErrTableAlreadyExists.Is(err))
729+
t.Run("With default", func(t *testing.T) {
730+
//TODO: NOW(millseconds) must match timestamp(milliseconds), else it's an error
731+
_, _, err := e.Query(NewContext(harness), "CREATE TABLE t5(a INTEGER,"+
732+
"`create_time` timestamp(6) NOT NULL DEFAULT NOW(6),"+
733+
"primary key (a))")
734+
require.NoError(t, err)
735+
})
719736

720-
//TODO: NOW(millseconds) must match timestamp(milliseconds), else it's an error
721-
_, _, err = e.Query(NewContext(harness), "CREATE TABLE t10(a INTEGER,"+
722-
"`create_time` timestamp(6) NOT NULL DEFAULT NOW(6),"+
723-
"primary key (a))")
724-
require.NoError(err)
737+
t.Run("CREATE LIKE assortment of types without primary key", func(t *testing.T) {
738+
TestQuery(t, harness, e,
739+
"CREATE TABLE t6 LIKE t1",
740+
[]sql.Row(nil),
741+
)
742+
743+
db, err := e.Catalog.Database("mydb")
744+
require.NoError(t, err)
745+
746+
testTable, ok, err := db.GetTableInsensitive(ctx, "t6")
747+
require.NoError(t, err)
748+
require.True(t, ok)
749+
750+
s := sql.Schema{
751+
{Name: "a", Type: sql.Int32, Nullable: true, Source: "t6"},
752+
{Name: "b", Type: sql.Text, Nullable: true, Source: "t6"},
753+
{Name: "c", Type: sql.Date, Nullable: true, Source: "t6"},
754+
{Name: "d", Type: sql.Timestamp, Nullable: true, Source: "t6"},
755+
{Name: "e", Type: sql.MustCreateStringWithDefaults(sqltypes.VarChar, 20), Nullable: true, Source: "t6"},
756+
{Name: "f", Type: sql.Blob, Source: "t6"},
757+
{Name: "b1", Type: sql.Boolean, Nullable: true, Source: "t6"},
758+
{Name: "b2", Type: sql.Boolean, Source: "t6"},
759+
{Name: "g", Type: sql.Datetime, Nullable: true, Source: "t6"},
760+
{Name: "h", Type: sql.MustCreateStringWithDefaults(sqltypes.Char, 40), Nullable: true, Source: "t6"},
761+
}
762+
763+
require.Equal(t, s, testTable.Schema())
764+
})
765+
766+
t.Run("CREATE LIKE with indexes, default, and comments", func(t *testing.T) {
767+
_, iter, err := e.Query(ctx, "CREATE TABLE t7pre("+
768+
"pk bigint primary key,"+
769+
"v1 bigint default (2) comment 'hi there',"+
770+
"index idx_v1 (v1) comment 'index here'"+
771+
")")
772+
if plan.ErrNotIndexable.Is(err) {
773+
t.Skip("test requires index creation")
774+
}
775+
require.NoError(t, err)
776+
_, err = sql.RowIterToRows(iter)
777+
require.NoError(t, err)
778+
TestQuery(t, harness, e,
779+
"CREATE TABLE t7 LIKE t7pre",
780+
[]sql.Row(nil),
781+
)
782+
783+
db, err := e.Catalog.Database("mydb")
784+
require.NoError(t, err)
785+
testTable, ok, err := db.GetTableInsensitive(ctx, "t7")
786+
require.NoError(t, err)
787+
require.True(t, ok)
788+
indexableTable, ok := testTable.(sql.IndexedTable)
789+
require.True(t, ok)
790+
791+
s := sql.Schema{
792+
{Name: "pk", Type: sql.Int64, PrimaryKey: true, Nullable: false, Source: "t7"},
793+
{Name: "v1", Type: sql.Int64, Nullable: true, Source: "t7",
794+
Default: parse.MustStringToColumnDefaultValue(ctx, "(2)", sql.Int64, true), Comment: "hi there"},
795+
}
796+
require.Equal(t, s, indexableTable.Schema())
797+
798+
indexes, err := indexableTable.GetIndexes(ctx)
799+
require.NoError(t, err)
800+
indexFound := false
801+
for _, index := range indexes {
802+
if index.ID() == "idx_v1" {
803+
indexFound = true
804+
require.Len(t, index.Expressions(), 1)
805+
require.True(t, strings.HasSuffix(index.Expressions()[0], "v1"))
806+
require.Equal(t, "index here", index.Comment())
807+
}
808+
}
809+
require.True(t, indexFound)
810+
})
725811
}
726812

727813
func TestDropTable(t *testing.T, harness Harness) {

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2t
104104
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
105105
github.com/lestrrat-go/strftime v1.0.1 h1:o7qz5pmLzPDLyGW4lG6JvTKPUfTFXwe+vOamIYWtnVU=
106106
github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g=
107+
github.com/liquidata-inc/vitess v0.0.0-20200911213404-87f76781a7c7 h1:CGiw+RfbIXsE+BPA8d7WpyvOVJUyw1OzDNxxTMa8qtI=
108+
github.com/liquidata-inc/vitess v0.0.0-20200911213404-87f76781a7c7/go.mod h1:8PM478sNETVVNWL2tVW+Uy4LIH31/x/tphLIRPh/hF4=
107109
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
108110
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
109111
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=

memory/mergeable_index.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type MergeableIndex struct {
1616
Exprs []sql.Expression
1717
Name string
1818
Unique bool
19+
CommentStr string
1920
}
2021

2122
var _ sql.Index = (*MergeableIndex)(nil)
@@ -41,7 +42,7 @@ func (i *MergeableIndex) IsUnique() bool {
4142
}
4243

4344
func (i *MergeableIndex) Comment() string {
44-
return "" // TODO: implement
45+
return i.CommentStr
4546
}
4647

4748
func (i *MergeableIndex) IndexType() string {

memory/table.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ func (t *Table) DropForeignKey(ctx *sql.Context, fkName string) error {
790790
return nil
791791
}
792792

793-
func (t *Table) createIndex(name string, columns []sql.IndexColumn, constraint sql.IndexConstraint) (sql.Index, error) {
793+
func (t *Table) createIndex(name string, columns []sql.IndexColumn, constraint sql.IndexConstraint, comment string) (sql.Index, error) {
794794
if t.indexes[name] != nil {
795795
// TODO: extract a standard error type for this
796796
return nil, fmt.Errorf("Error: index already exists")
@@ -811,6 +811,7 @@ func (t *Table) createIndex(name string, columns []sql.IndexColumn, constraint s
811811
Exprs: exprs,
812812
Name: name,
813813
Unique: constraint == sql.IndexConstraint_Unique,
814+
CommentStr: comment,
814815
},
815816
}, nil
816817
}
@@ -837,7 +838,7 @@ func (t *Table) CreateIndex(ctx *sql.Context, indexName string, using sql.IndexU
837838
t.indexes = make(map[string]sql.Index)
838839
}
839840

840-
index, err := t.createIndex(indexName, columns, constraint)
841+
index, err := t.createIndex(indexName, columns, constraint, comment)
841842
if err != nil {
842843
return err
843844
}

0 commit comments

Comments
 (0)