unique_constraint_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package executor
  2. import (
  3. "strings"
  4. "testing"
  5. )
  6. func TestCreateTableInlineUniqueConstraint(t *testing.T) {
  7. _, schema, table := newTestDB(t)
  8. e := newExec(schema, table)
  9. execMust(t, e, "CREATE TABLE login_source (id INTEGER PRIMARY KEY, name TEXT UNIQUE)")
  10. execMust(t, e, "INSERT INTO login_source VALUES (1, 'github')")
  11. _, err := execSQL(e, "INSERT INTO login_source VALUES (2, 'github')")
  12. if err == nil {
  13. t.Fatal("expected unique violation for inline column UNIQUE")
  14. }
  15. if !strings.Contains(err.Error(), "UNIQUE constraint failed") {
  16. t.Fatalf("unexpected error: %v", err)
  17. }
  18. }
  19. func TestCreateTableCompositeUniqueConstraint(t *testing.T) {
  20. _, schema, table := newTestDB(t)
  21. e := newExec(schema, table)
  22. execMust(t, e, "CREATE TABLE access_token (id INTEGER PRIMARY KEY, sha1 TEXT, sha256 TEXT, CONSTRAINT uni_access_token_sha1 UNIQUE(sha1), CONSTRAINT uni_access_token_sha256 UNIQUE(sha256))")
  23. execMust(t, e, "INSERT INTO access_token (sha1, sha256) VALUES ('s1', 'h1')")
  24. if _, err := execSQL(e, "INSERT INTO access_token (sha1, sha256) VALUES ('s1', 'h2')"); err == nil {
  25. t.Fatal("expected unique violation on sha1")
  26. }
  27. if _, err := execSQL(e, "INSERT INTO access_token (sha1, sha256) VALUES ('s2', 'h1')"); err == nil {
  28. t.Fatal("expected unique violation on sha256")
  29. }
  30. execMust(t, e, "INSERT INTO access_token (sha1, sha256) VALUES ('s2', 'h2')")
  31. }
  32. func TestCreateTableMultiColumnUniqueConstraint(t *testing.T) {
  33. _, schema, table := newTestDB(t)
  34. e := newExec(schema, table)
  35. execMust(t, e, "CREATE TABLE t (id INTEGER PRIMARY KEY, a TEXT, b TEXT, CONSTRAINT uq_ab UNIQUE(a, b))")
  36. execMust(t, e, "INSERT INTO t VALUES (1, 'x', 'y')")
  37. execMust(t, e, "INSERT INTO t VALUES (2, 'x', 'z')")
  38. if _, err := execSQL(e, "INSERT INTO t VALUES (3, 'x', 'y')"); err == nil {
  39. t.Fatal("expected unique violation on composite (x,y)")
  40. }
  41. }
  42. func TestCreateTableUniqueConstraintReportedInCatalog(t *testing.T) {
  43. _, schema, table := newTestDB(t)
  44. e := newExec(schema, table)
  45. execMust(t, e, "CREATE TABLE t (id INTEGER PRIMARY KEY, name TEXT, CONSTRAINT uq_t_name UNIQUE(name))")
  46. res := execMust(t, e, "PRAGMA index_list('t')")
  47. found := false
  48. for _, row := range res.Rows {
  49. // columns: seq, name, unique, origin, partial
  50. if row[1] == "uq_t_name" {
  51. found = true
  52. if row[2] != int64(1) {
  53. t.Fatalf("index uq_t_name unique flag = %v, want 1", row[2])
  54. }
  55. }
  56. }
  57. if !found {
  58. t.Fatalf("named unique constraint not reported in index_list: %v", res.Rows)
  59. }
  60. }
  61. func TestCreateTableIfNotExistsWithUniqueConstraint(t *testing.T) {
  62. _, schema, table := newTestDB(t)
  63. e := newExec(schema, table)
  64. execMust(t, e, "CREATE TABLE IF NOT EXISTS t (id INTEGER PRIMARY KEY, name TEXT UNIQUE)")
  65. execMust(t, e, "INSERT INTO t VALUES (1, 'a')")
  66. // Second CREATE IF NOT EXISTS must be a no-op and not fail on the duplicate index.
  67. execMust(t, e, "CREATE TABLE IF NOT EXISTS t (id INTEGER PRIMARY KEY, name TEXT UNIQUE)")
  68. if _, err := execSQL(e, "INSERT INTO t VALUES (2, 'a')"); err == nil {
  69. t.Fatal("expected unique violation to still be enforced after no-op recreate")
  70. }
  71. }