alter-source.td 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. # Copyright Materialize, Inc. and contributors. All rights reserved.
  2. #
  3. # Use of this software is governed by the Business Source License
  4. # included in the LICENSE file at the root of this repository.
  5. #
  6. # As of the Change Date specified in that file, in accordance with
  7. # the Business Source License, use of this software will be governed
  8. # by the Apache License, Version 2.0.
  9. $ set-sql-timeout duration=60s
  10. # IMPORTANT: The Postgres server has a custom pg_hba.conf that only
  11. # accepts connections from specific users. You will have to update
  12. # pg_hba.conf if you modify the existing user names or add new ones.
  13. > CREATE SECRET pgpass AS 'postgres'
  14. > CREATE CONNECTION pg TO POSTGRES (
  15. HOST postgres,
  16. DATABASE postgres,
  17. USER postgres,
  18. PASSWORD SECRET pgpass
  19. )
  20. $ postgres-execute connection=postgres://postgres:postgres@postgres
  21. DROP SCHEMA public CASCADE;
  22. CREATE SCHEMA public;
  23. ALTER USER postgres WITH replication;
  24. DROP SCHEMA IF EXISTS public CASCADE;
  25. DROP PUBLICATION IF EXISTS mz_source;
  26. CREATE SCHEMA public;
  27. DROP PUBLICATION IF EXISTS mz_source;
  28. CREATE PUBLICATION mz_source FOR ALL TABLES;
  29. CREATE TABLE table_a (pk INTEGER PRIMARY KEY, f2 TEXT);
  30. INSERT INTO table_a VALUES (1, 'one');
  31. ALTER TABLE table_a REPLICA IDENTITY FULL;
  32. INSERT INTO table_a VALUES (2, 'two');
  33. # Check empty publication on ALTER
  34. > CREATE SOURCE "mz_source"
  35. FROM POSTGRES CONNECTION pg (
  36. PUBLICATION 'mz_source'
  37. );
  38. > CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  39. > SELECT * FROM table_a;
  40. 1 one
  41. 2 two
  42. $ postgres-execute connection=postgres://postgres:postgres@postgres
  43. DROP TABLE table_a CASCADE;
  44. ! CREATE TABLE table_b FROM SOURCE mz_source (REFERENCE table_b);
  45. contains:PUBLICATION mz_source is empty
  46. # Adding a table with the same name as a running table does not allow you to add
  47. # the new table, even though its OID is the different.
  48. $ postgres-execute connection=postgres://postgres:postgres@postgres
  49. CREATE TABLE table_a (pk INTEGER PRIMARY KEY, f2 TEXT);
  50. ALTER TABLE table_a REPLICA IDENTITY FULL;
  51. INSERT INTO table_a VALUES (9, 'nine');
  52. ! SELECT * FROM table_a;
  53. regex:(table was dropped|incompatible schema change)
  54. # We are not aware that the new table_a is different
  55. ! CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  56. contains:catalog item 'table_a' already exists
  57. > DROP SOURCE mz_source CASCADE;
  58. # Re-populate tables for rest of test.
  59. $ postgres-execute connection=postgres://postgres:postgres@postgres
  60. DELETE FROM table_a;
  61. INSERT INTO table_a VALUES (1, 'one');
  62. INSERT INTO table_a VALUES (2, 'two');
  63. CREATE TABLE table_b (pk INTEGER PRIMARY KEY, f2 TEXT);
  64. INSERT INTO table_b VALUES (1, 'one');
  65. ALTER TABLE table_b REPLICA IDENTITY FULL;
  66. INSERT INTO table_b VALUES (2, 'two');
  67. CREATE TABLE table_c (pk INTEGER PRIMARY KEY, f2 TEXT);
  68. INSERT INTO table_c VALUES (1, 'one');
  69. ALTER TABLE table_c REPLICA IDENTITY FULL;
  70. INSERT INTO table_c VALUES (2, 'two');
  71. CREATE TABLE table_d (pk INTEGER PRIMARY KEY, f2 TEXT);
  72. INSERT INTO table_d VALUES (1, 'one');
  73. ALTER TABLE table_d REPLICA IDENTITY FULL;
  74. INSERT INTO table_d VALUES (2, 'two');
  75. CREATE TABLE table_e (pk INTEGER PRIMARY KEY, f2 TEXT);
  76. INSERT INTO table_e VALUES (1, 'one');
  77. ALTER TABLE table_e REPLICA IDENTITY FULL;
  78. INSERT INTO table_e VALUES (2, 'two');
  79. CREATE TYPE an_enum AS ENUM ('var0', 'var1');
  80. CREATE TABLE table_f (pk INTEGER PRIMARY KEY, f2 an_enum);
  81. INSERT INTO table_f VALUES (1, 'var0');
  82. ALTER TABLE table_f REPLICA IDENTITY FULL;
  83. INSERT INTO table_f VALUES (2, 'var1');
  84. CREATE TABLE table_g (pk INTEGER PRIMARY KEY, f2 TEXT);
  85. INSERT INTO table_g VALUES (1, 'one');
  86. ALTER TABLE table_g REPLICA IDENTITY FULL;
  87. INSERT INTO table_g VALUES (2, 'two');
  88. > CREATE SOURCE "mz_source"
  89. FROM POSTGRES CONNECTION pg (
  90. PUBLICATION 'mz_source'
  91. );
  92. > CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  93. > CREATE TABLE table_b FROM SOURCE mz_source (REFERENCE table_b);
  94. > CREATE TABLE table_c FROM SOURCE mz_source (REFERENCE table_c);
  95. > CREATE TABLE table_d FROM SOURCE mz_source (REFERENCE table_d);
  96. > CREATE TABLE table_e FROM SOURCE mz_source (REFERENCE table_e);
  97. > CREATE TABLE table_f FROM SOURCE mz_source (REFERENCE table_f) WITH (TEXT COLUMNS [f2]);
  98. > CREATE TABLE table_g FROM SOURCE mz_source (REFERENCE table_g);
  99. > SHOW SUBSOURCES ON mz_source
  100. mz_source_progress progress
  101. > SHOW TABLES
  102. table_a ""
  103. table_b ""
  104. table_c ""
  105. table_d ""
  106. table_e ""
  107. table_f ""
  108. table_g ""
  109. $ set-regex match="DETAILS = '[a-f0-9]+'" replacement=<DETAILS>
  110. > SHOW CREATE SOURCE mz_source;
  111. materialize.public.mz_source "CREATE SOURCE materialize.public.mz_source\nIN CLUSTER quickstart\nFROM POSTGRES CONNECTION materialize.public.pg (PUBLICATION = 'mz_source')\nEXPOSE PROGRESS AS materialize.public.mz_source_progress;"
  112. > SHOW CREATE TABLE table_a;
  113. materialize.public.table_a "CREATE TABLE materialize.public.table_a (pk pg_catalog.int4 NOT NULL, f2 pg_catalog.text, CONSTRAINT table_a_pkey PRIMARY KEY (pk)) FROM SOURCE materialize.public.mz_source (REFERENCE = postgres.public.table_a) WITH (<DETAILS>);"
  114. #
  115. # State checking
  116. #
  117. > DROP TABLE table_a
  118. > SELECT * FROM table_b;
  119. 1 one
  120. 2 two
  121. > SHOW SUBSOURCES ON mz_source
  122. mz_source_progress progress
  123. > SHOW TABLES
  124. table_b ""
  125. table_c ""
  126. table_d ""
  127. table_e ""
  128. table_f ""
  129. table_g ""
  130. ! SELECT * FROM table_a;
  131. contains: unknown catalog item 'table_a'
  132. # Makes progress after dropping subsources
  133. $ postgres-execute connection=postgres://postgres:postgres@postgres
  134. INSERT INTO table_b VALUES (3, 'three');
  135. > SELECT * FROM table_b;
  136. 1 one
  137. 2 two
  138. 3 three
  139. # IF EXISTS works
  140. > DROP TABLE IF EXISTS table_a;
  141. # Multiple, repetitive tables work
  142. > DROP TABLE table_b, table_c, table_b, table_c, table_b, table_c;
  143. # IF EXISTS works with multiple tables
  144. > DROP TABLE IF EXISTS table_c, table_d;
  145. > CREATE MATERIALIZED VIEW mv_e AS SELECT pk + 1 FROM table_e;
  146. > CREATE MATERIALIZED VIEW mv_f AS SELECT pk + 1 FROM table_f;
  147. # Makes progress after dropping subsources
  148. $ postgres-execute connection=postgres://postgres:postgres@postgres
  149. INSERT INTO table_e VALUES (3, 'three');
  150. > SELECT * FROM mv_e;
  151. 2
  152. 3
  153. 4
  154. > SHOW MATERIALIZED VIEWS
  155. mv_e quickstart ""
  156. mv_f quickstart ""
  157. # RESTRICT works
  158. ! DROP TABLE table_e RESTRICT;
  159. contains:cannot drop table "table_e": still depended upon by materialized view "mv_e"
  160. # CASCADE works
  161. > DROP TABLE table_e CASCADE;
  162. # IF NOT EXISTS + CASCADE works
  163. > DROP TABLE IF EXISTS table_e, table_f CASCADE;
  164. # TEXT COLUMNS removed from table_f
  165. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  166. <null>
  167. > SHOW SUBSOURCES ON mz_source
  168. mz_source_progress progress
  169. > SHOW TABLES
  170. table_g ""
  171. > SHOW MATERIALIZED VIEWS
  172. > DROP TABLE table_g;
  173. > SHOW SUBSOURCES ON mz_source
  174. mz_source_progress progress
  175. #
  176. # Add tables
  177. > CREATE TABLE table_g FROM SOURCE mz_source (REFERENCE table_a);
  178. ! CREATE TABLE table_g FROM SOURCE mz_source (REFERENCE table_a);
  179. contains:catalog item 'table_g' already exists
  180. > CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  181. > CREATE TABLE tb FROM SOURCE mz_source (REFERENCE table_b);
  182. > SELECT * FROM table_a;
  183. 1 one
  184. 2 two
  185. ! CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  186. contains:catalog item 'table_a' already exists
  187. > SELECT * FROM tb;
  188. 1 one
  189. 2 two
  190. 3 three
  191. !SELECT * FROM table_b;
  192. contains:unknown catalog item
  193. # We can add tables that didn't exist at the time of publication
  194. $ postgres-execute connection=postgres://postgres:postgres@postgres
  195. CREATE TABLE table_h (pk INTEGER PRIMARY KEY, f2 TEXT);
  196. INSERT INTO table_h VALUES (1, 'one');
  197. ALTER TABLE table_h REPLICA IDENTITY FULL;
  198. INSERT INTO table_h VALUES (2, 'two');
  199. > CREATE TABLE table_h FROM SOURCE mz_source (REFERENCE table_a);
  200. > SELECT * FROM table_h;
  201. 1 one
  202. 2 two
  203. > SHOW SUBSOURCES ON mz_source
  204. mz_source_progress progress
  205. > SHOW TABLES
  206. table_a ""
  207. table_g ""
  208. table_h ""
  209. tb ""
  210. #
  211. # Complex subsource operations
  212. # If your schema change breaks the subsource, you can fix it.
  213. $ postgres-execute connection=postgres://postgres:postgres@postgres
  214. ALTER TABLE table_a DROP COLUMN f2;
  215. ! SELECT * FROM table_a;
  216. contains:incompatible schema change
  217. > SELECT error ~~ '%incompatible schema change%' FROM mz_internal.mz_source_statuses WHERE name = 'table_a' and type = 'table';
  218. true
  219. # Subsource errors not propagated to primary source
  220. > SELECT error IS NULL FROM mz_internal.mz_source_statuses WHERE name = 'mz_source';
  221. true
  222. > DROP TABLE table_a;
  223. > CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  224. > SELECT * FROM table_a;
  225. 1
  226. 2
  227. # If you add columns you can re-ingest them
  228. $ postgres-execute connection=postgres://postgres:postgres@postgres
  229. ALTER TABLE table_a ADD COLUMN f2 text;
  230. INSERT INTO table_a VALUES (3, 'three');
  231. > SELECT * FROM table_a;
  232. 1
  233. 2
  234. 3
  235. > DROP TABLE table_a;
  236. > CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  237. > SELECT * FROM table_a;
  238. 1 <null>
  239. 2 <null>
  240. 3 three
  241. # If you add a NOT NULL constraint, you can propagate it.
  242. $ postgres-execute connection=postgres://postgres:postgres@postgres
  243. ALTER TABLE table_a ADD COLUMN f3 int DEFAULT 1 NOT NULL;
  244. INSERT INTO table_a VALUES (4, 'four', 4);
  245. > DROP TABLE table_a;
  246. > CREATE TABLE table_a FROM SOURCE mz_source (REFERENCE table_a);
  247. > SELECT * FROM table_a;
  248. 1 <null> 1
  249. 2 <null> 1
  250. 3 three 1
  251. 4 four 4
  252. ? EXPLAIN OPTIMIZED PLAN AS VERBOSE TEXT FOR SELECT * FROM table_a WHERE f3 IS NULL;
  253. Explained Query (fast path):
  254. Constant <empty>
  255. Target cluster: quickstart
  256. # Can add tables with text columns
  257. ! CREATE TABLE table_f FROM SOURCE mz_source (REFERENCE table_f) WITH (TEXT COLUMNS [f2, f2]);
  258. contains: invalid TEXT COLUMNS option value: unexpected multiple references to postgres.public.table_f.f2
  259. > CREATE TABLE table_f FROM SOURCE mz_source (REFERENCE table_f) WITH (TEXT COLUMNS [f2]);
  260. > SELECT * FROM table_f
  261. 1 var0
  262. 2 var1
  263. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE TABLE table_f);
  264. f2
  265. # Drop a table that's in the publication, which shuffles the tables' output
  266. # indexes, then add a table to the publication and ensure it can be added.
  267. $ postgres-execute connection=postgres://postgres:postgres@postgres
  268. DROP TABLE table_c, table_d;
  269. CREATE TABLE table_i (pk INTEGER PRIMARY KEY, f2 an_enum);
  270. INSERT INTO table_i VALUES (1, 'var0');
  271. ALTER TABLE table_i REPLICA IDENTITY FULL;
  272. INSERT INTO table_i VALUES (2, 'var1');
  273. INSERT INTO table_f VALUES (3, 'var1');
  274. > CREATE TABLE table_i FROM SOURCE mz_source (REFERENCE table_i) WITH (TEXT COLUMNS [f2]);
  275. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE TABLE table_i);
  276. f2
  277. > SELECT * FROM table_f
  278. 1 var0
  279. 2 var1
  280. 3 var1
  281. > DROP TABLE table_f, table_i;
  282. ! CREATE TABLE table_e FROM SOURCE mz_source (REFERENCE table_e) WITH (TEXT COLUMNS (xyz));
  283. contains: invalid TEXT COLUMNS option value: column "table_e.xyz" does not exist
  284. # Test adding text cols w/o original text columns
  285. > CREATE SOURCE "mz_source_wo_init_text_cols"
  286. FROM POSTGRES CONNECTION pg (
  287. PUBLICATION 'mz_source'
  288. );
  289. > CREATE TABLE t_a FROM SOURCE mz_source_wo_init_text_cols (REFERENCE table_a);
  290. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE TABLE t_a);
  291. <null>
  292. > CREATE TABLE t_f FROM SOURCE mz_source_wo_init_text_cols (REFERENCE table_f) WITH (TEXT COLUMNS [f2]);
  293. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE TABLE t_f);
  294. f2
  295. # add a table after having created the source
  296. $ postgres-execute connection=postgres://postgres:postgres@postgres
  297. CREATE TABLE t2 (f1 BOOLEAN);
  298. ALTER TABLE t2 REPLICA IDENTITY FULL;
  299. ! SELECT COUNT(*) > 0 FROM t2;
  300. contains:unknown catalog item 't2'