|
|
@@ -0,0 +1,72 @@
|
|
|
+package executor
|
|
|
+
|
|
|
+import (
|
|
|
+ "strings"
|
|
|
+ "testing"
|
|
|
+)
|
|
|
+
|
|
|
+func TestCreateTablePrimaryKeyConstraints(t *testing.T) {
|
|
|
+ tests := []struct {
|
|
|
+ name string
|
|
|
+ sql string
|
|
|
+ wantErr string
|
|
|
+ wantPrimaryKey string
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "composite table-level primary key is rejected",
|
|
|
+ sql: "CREATE TABLE t (a TEXT, b TEXT, PRIMARY KEY (a, b))",
|
|
|
+ wantErr: "composite primary key",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "duplicate column composite primary key is rejected",
|
|
|
+ sql: "CREATE TABLE t (a TEXT, PRIMARY KEY (a, a))",
|
|
|
+ wantErr: "composite primary key",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "single-column table-level primary key is accepted",
|
|
|
+ sql: "CREATE TABLE t (a TEXT, PRIMARY KEY (a))",
|
|
|
+ wantPrimaryKey: "a",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "inline primary key is accepted",
|
|
|
+ sql: "CREATE TABLE t (a TEXT PRIMARY KEY)",
|
|
|
+ wantPrimaryKey: "a",
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tt := range tests {
|
|
|
+ t.Run(tt.name, func(t *testing.T) {
|
|
|
+ _, schema, table := newTestDB(t)
|
|
|
+ e := newExec(schema, table)
|
|
|
+
|
|
|
+ _, err := execSQL(e, tt.sql)
|
|
|
+ if tt.wantErr != "" {
|
|
|
+ if err == nil {
|
|
|
+ t.Fatalf("expected %q to fail", tt.sql)
|
|
|
+ }
|
|
|
+ if !strings.Contains(err.Error(), tt.wantErr) {
|
|
|
+ t.Fatalf("error = %q, want it to contain %q", err, tt.wantErr)
|
|
|
+ }
|
|
|
+ if schema.TableExists("t") {
|
|
|
+ t.Fatal("rejected CREATE TABLE left a schema behind")
|
|
|
+ }
|
|
|
+ if _, err := execSQL(e, "SELECT * FROM t"); err == nil {
|
|
|
+ t.Fatal("rejected CREATE TABLE left a usable table behind")
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("exec %q: %v", tt.sql, err)
|
|
|
+ }
|
|
|
+ got, err := schema.GetSchema("t")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("get schema: %v", err)
|
|
|
+ }
|
|
|
+ if got.PrimaryKey != tt.wantPrimaryKey {
|
|
|
+ t.Fatalf("PrimaryKey = %q, want %q", got.PrimaryKey, tt.wantPrimaryKey)
|
|
|
+ }
|
|
|
+ execMust(t, e, "INSERT INTO t (a) VALUES ('x')")
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|