alter_table_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package pgserver
  2. import (
  3. "testing"
  4. )
  5. func TestAlterTableAddColumnOverSimpleQuery(t *testing.T) {
  6. c, client := newDataConnection(t)
  7. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("CREATE TABLE t (id INTEGER PRIMARY KEY)"), 0)})
  8. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("INSERT INTO t (id) VALUES (1)"), 0)})
  9. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("ALTER TABLE t ADD COLUMN IF NOT EXISTS note TEXT DEFAULT 'later'"), 0)})
  10. // Idempotent second boot-time migration.
  11. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("ALTER TABLE t ADD COLUMN IF NOT EXISTS note TEXT DEFAULT 'later'"), 0)})
  12. msgs := runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("SELECT id, note FROM t ORDER BY id"), 0)})
  13. values := dataRowValues(t, msgs[1])
  14. if len(values) != 2 || values[0] != "1" || values[1] != "later" {
  15. t.Fatalf("existing row after ADD COLUMN = %v, want [1 later]", values)
  16. }
  17. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("INSERT INTO t (id) VALUES (2)"), 0)})
  18. msgs = runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("SELECT note FROM t WHERE id = 2"), 0)})
  19. if got := dataRowValues(t, msgs[1]); len(got) != 1 || got[0] != "later" {
  20. t.Fatalf("new row note = %v, want [later]", got)
  21. }
  22. }
  23. func TestAlterTableAddColumnErrorsOverSimpleQuery(t *testing.T) {
  24. c, client := newDataConnection(t)
  25. runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("CREATE TABLE t (id INTEGER PRIMARY KEY)\x00")})
  26. runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("INSERT INTO t (id) VALUES (1), (2)\x00")})
  27. // A required column with no default cannot be materialized for existing
  28. // rows.
  29. msgs := runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("ALTER TABLE t ADD COLUMN note TEXT NOT NULL\x00")})
  30. if code := errorCode(msgs[0]); code != "23502" {
  31. t.Fatalf("NOT NULL without default SQLSTATE = %q, want 23502", code)
  32. }
  33. // Backfilling one constant into two rows violates the declared UNIQUE
  34. // constraint.
  35. msgs = runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("ALTER TABLE t ADD COLUMN code TEXT DEFAULT 'same' UNIQUE\x00")})
  36. if code := errorCode(msgs[0]); code != "23505" {
  37. t.Fatalf("UNIQUE backfill SQLSTATE = %q, want 23505", code)
  38. }
  39. msgs = runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("ALTER TABLE t ADD COLUMN note TEXT NOT NULL DEFAULT 'kept'\x00")})
  40. if code := errorCode(msgs[0]); code != "" {
  41. t.Fatalf("NOT NULL with default SQLSTATE = %q, want success", code)
  42. }
  43. msgs = runQuery(t, c, client, &Message{Type: MsgQuery, Data: []byte("SELECT note FROM t ORDER BY id\x00")})
  44. for i, values := range []string{"kept", "kept"} {
  45. got := dataRowValues(t, msgs[1+i])
  46. if len(got) != 1 || got[0] != values {
  47. t.Fatalf("row %d note = %v, want [%s]", i, got, values)
  48. }
  49. }
  50. }
  51. func TestAlterTableDropAndRenameColumnOverSimpleQuery(t *testing.T) {
  52. c, client := newDataConnection(t)
  53. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("CREATE TABLE t (id INTEGER PRIMARY KEY, keep TEXT, dropme TEXT)"), 0)})
  54. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("INSERT INTO t (id, keep, dropme) VALUES (1, 'a', 'gone')"), 0)})
  55. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("ALTER TABLE t DROP COLUMN dropme"), 0)})
  56. runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("ALTER TABLE t RENAME COLUMN keep TO kept"), 0)})
  57. msgs := runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("SELECT kept FROM t WHERE id = 1"), 0)})
  58. if got := dataRowValues(t, msgs[1]); len(got) != 1 || got[0] != "a" {
  59. t.Fatalf("renamed column value = %v, want [a]", got)
  60. }
  61. msgs = runQuery(t, c, client, &Message{Type: MsgQuery, Data: append([]byte("SELECT dropme FROM t"), 0)})
  62. if code := errorCode(msgs[0]); code == "" {
  63. t.Fatalf("expected an error selecting a dropped column, got %v", msgs)
  64. }
  65. }