alter-source.td 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. CREATE SCHEMA public;
  26. DROP PUBLICATION IF EXISTS mz_source;
  27. CREATE PUBLICATION mz_source FOR ALL TABLES;
  28. CREATE TABLE table_a (pk INTEGER PRIMARY KEY, f2 TEXT);
  29. INSERT INTO table_a VALUES (1, 'one');
  30. ALTER TABLE table_a REPLICA IDENTITY FULL;
  31. INSERT INTO table_a VALUES (2, 'two');
  32. # Check empty publication on ALTER
  33. > CREATE SOURCE "mz_source"
  34. FROM POSTGRES CONNECTION pg (
  35. PUBLICATION 'mz_source'
  36. )
  37. FOR SCHEMAS (public);
  38. > SELECT * FROM table_a;
  39. 1 one
  40. 2 two
  41. $ postgres-execute connection=postgres://postgres:postgres@postgres
  42. DROP TABLE table_a CASCADE;
  43. !ALTER SOURCE mz_source ADD SUBSOURCE table_b;
  44. contains:PUBLICATION mz_source is empty
  45. # Adding a table with the same name as a running table does not allow you to add
  46. # the new table, even though its OID is the different.
  47. $ postgres-execute connection=postgres://postgres:postgres@postgres
  48. CREATE TABLE table_a (pk INTEGER PRIMARY KEY, f2 TEXT);
  49. ALTER TABLE table_a REPLICA IDENTITY FULL;
  50. INSERT INTO table_a VALUES (9, 'nine');
  51. # Current table_a is not new table_a. Note that this only works right now
  52. # because we are bad at detecting dropped tables.
  53. > SELECT * FROM table_a;
  54. 1 one
  55. 2 two
  56. # We are not aware that the new table_a is different
  57. !ALTER SOURCE mz_source ADD SUBSOURCE table_a;
  58. contains:catalog item 'table_a' already exists
  59. > DROP SOURCE mz_source CASCADE;
  60. # Re-populate tables for rest of test.
  61. $ postgres-execute connection=postgres://postgres:postgres@postgres
  62. DELETE FROM table_a;
  63. INSERT INTO table_a VALUES (1, 'one');
  64. INSERT INTO table_a VALUES (2, 'two');
  65. CREATE TABLE table_b (pk INTEGER PRIMARY KEY, f2 TEXT);
  66. INSERT INTO table_b VALUES (1, 'one');
  67. ALTER TABLE table_b REPLICA IDENTITY FULL;
  68. INSERT INTO table_b VALUES (2, 'two');
  69. CREATE TABLE table_c (pk INTEGER PRIMARY KEY, f2 TEXT);
  70. INSERT INTO table_c VALUES (1, 'one');
  71. ALTER TABLE table_c REPLICA IDENTITY FULL;
  72. INSERT INTO table_c VALUES (2, 'two');
  73. CREATE TABLE table_d (pk INTEGER PRIMARY KEY, f2 TEXT);
  74. INSERT INTO table_d VALUES (1, 'one');
  75. ALTER TABLE table_d REPLICA IDENTITY FULL;
  76. INSERT INTO table_d VALUES (2, 'two');
  77. CREATE TABLE table_e (pk INTEGER PRIMARY KEY, f2 TEXT);
  78. INSERT INTO table_e VALUES (1, 'one');
  79. ALTER TABLE table_e REPLICA IDENTITY FULL;
  80. INSERT INTO table_e VALUES (2, 'two');
  81. CREATE TYPE an_enum AS ENUM ('var0', 'var1');
  82. CREATE TABLE table_f (pk INTEGER PRIMARY KEY, f2 an_enum);
  83. INSERT INTO table_f VALUES (1, 'var0');
  84. ALTER TABLE table_f REPLICA IDENTITY FULL;
  85. INSERT INTO table_f VALUES (2, 'var1');
  86. CREATE TABLE table_g (pk INTEGER PRIMARY KEY, f2 TEXT);
  87. INSERT INTO table_g VALUES (1, 'one');
  88. ALTER TABLE table_g REPLICA IDENTITY FULL;
  89. INSERT INTO table_g VALUES (2, 'two');
  90. > CREATE SOURCE "mz_source"
  91. FROM POSTGRES CONNECTION pg (
  92. PUBLICATION 'mz_source',
  93. TEXT COLUMNS [table_f.f2]
  94. )
  95. FOR SCHEMAS (public);
  96. > SHOW SUBSOURCES ON mz_source
  97. mz_source_progress progress
  98. table_a subsource
  99. table_b subsource
  100. table_c subsource
  101. table_d subsource
  102. table_e subsource
  103. table_f subsource
  104. table_g subsource
  105. >[version>=14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  106. postgres.public.table_f.f2
  107. >[version<14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  108. "\"postgres\".\"public\".\"table_f\".\"f2\""
  109. >[version>=14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE table_f);
  110. "f2"
  111. >[version<14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE table_f);
  112. "\"f2\""
  113. #
  114. # State checking
  115. #
  116. > DROP SOURCE table_a
  117. > SELECT * FROM table_b;
  118. 1 one
  119. 2 two
  120. > SHOW SUBSOURCES ON mz_source
  121. mz_source_progress progress
  122. table_b subsource
  123. table_c subsource
  124. table_d subsource
  125. table_e subsource
  126. table_f subsource
  127. table_g subsource
  128. ! SELECT * FROM table_a;
  129. contains: unknown catalog item 'table_a'
  130. # Makes progress after dropping subsources
  131. $ postgres-execute connection=postgres://postgres:postgres@postgres
  132. INSERT INTO table_b VALUES (3, 'three');
  133. > SELECT * FROM table_b;
  134. 1 one
  135. 2 two
  136. 3 three
  137. # IF EXISTS works
  138. > DROP SOURCE IF EXISTS table_a;
  139. # Multiple, repetitive tables work
  140. > DROP SOURCE table_b, table_c, table_b, table_c, table_b, table_c;
  141. # IF EXISTS works with multiple tables
  142. > DROP SOURCE IF EXISTS table_c, table_d;
  143. > CREATE MATERIALIZED VIEW mv_e AS SELECT pk + 1 FROM table_e;
  144. > CREATE MATERIALIZED VIEW mv_f AS SELECT pk + 1 FROM table_f;
  145. # Makes progress after dropping subsources
  146. $ postgres-execute connection=postgres://postgres:postgres@postgres
  147. INSERT INTO table_e VALUES (3, 'three');
  148. > SELECT * FROM mv_e;
  149. 2
  150. 3
  151. 4
  152. > SHOW MATERIALIZED VIEWS
  153. mv_e quickstart ""
  154. mv_f quickstart ""
  155. # RESTRICT works
  156. ! DROP SOURCE table_e RESTRICT;
  157. contains:cannot drop source "table_e": still depended upon by materialized view "mv_e"
  158. # CASCADE works
  159. > DROP SOURCE table_e CASCADE;
  160. # IF NOT EXISTS + CASCADE works
  161. > DROP SOURCE IF EXISTS table_e, table_f CASCADE;
  162. # TEXT COLUMNS removed from table_f
  163. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  164. <null>
  165. > SHOW SUBSOURCES ON mz_source
  166. mz_source_progress progress
  167. table_g subsource
  168. > SHOW MATERIALIZED VIEWS
  169. > DROP SOURCE table_g;
  170. > SHOW SUBSOURCES ON mz_source
  171. mz_source_progress progress
  172. #
  173. # Add subsources
  174. > ALTER SOURCE mz_source ADD SUBSOURCE table_g;
  175. ! ALTER SOURCE mz_source ADD SUBSOURCE table_g;
  176. contains:catalog item 'table_g' already exists
  177. > ALTER SOURCE mz_source ADD SUBSOURCE table_a, table_b AS tb;
  178. > SELECT * FROM table_a;
  179. 1 one
  180. 2 two
  181. ! ALTER SOURCE mz_source ADD SUBSOURCE table_a;
  182. contains:catalog item 'table_a' already exists
  183. > SELECT * FROM tb;
  184. 1 one
  185. 2 two
  186. 3 three
  187. !SELECT * FROM table_b;
  188. contains:unknown catalog item
  189. # We can add tables that didn't exist at the time of publication
  190. $ postgres-execute connection=postgres://postgres:postgres@postgres
  191. CREATE TABLE table_h (pk INTEGER PRIMARY KEY, f2 TEXT);
  192. INSERT INTO table_h VALUES (1, 'one');
  193. ALTER TABLE table_h REPLICA IDENTITY FULL;
  194. INSERT INTO table_h VALUES (2, 'two');
  195. > ALTER SOURCE mz_source ADD SUBSOURCE table_h;
  196. > SELECT * FROM table_h;
  197. 1 one
  198. 2 two
  199. > SHOW SUBSOURCES ON mz_source
  200. mz_source_progress progress
  201. table_a subsource
  202. table_g subsource
  203. table_h subsource
  204. tb subsource
  205. #
  206. # Complex subsource operations
  207. # If your schema change breaks the subsource, you can fix it.
  208. $ postgres-execute connection=postgres://postgres:postgres@postgres
  209. ALTER TABLE table_a DROP COLUMN f2;
  210. ! SELECT * FROM table_a;
  211. contains:incompatible schema change
  212. > SELECT error ~~ '%incompatible schema change%' FROM mz_internal.mz_source_statuses WHERE name = 'table_a';
  213. true
  214. # Subsource errors not propagated to primary source
  215. > SELECT error IS NULL FROM mz_internal.mz_source_statuses WHERE name = 'mz_source';
  216. true
  217. > DROP SOURCE table_a;
  218. > ALTER SOURCE mz_source ADD SUBSOURCE table_a;
  219. > SELECT * FROM table_a;
  220. 1
  221. 2
  222. # If you add columns you can re-ingest them
  223. $ postgres-execute connection=postgres://postgres:postgres@postgres
  224. ALTER TABLE table_a ADD COLUMN f2 text;
  225. INSERT INTO table_a VALUES (3, 'three');
  226. > SELECT * FROM table_a;
  227. 1
  228. 2
  229. 3
  230. > DROP SOURCE table_a;
  231. > ALTER SOURCE mz_source ADD SUBSOURCE table_a;
  232. > SELECT * FROM table_a;
  233. 1 <null>
  234. 2 <null>
  235. 3 three
  236. # If you add a NOT NULL constraint, you can propagate it.
  237. $ postgres-execute connection=postgres://postgres:postgres@postgres
  238. ALTER TABLE table_a ADD COLUMN f3 int DEFAULT 1 NOT NULL;
  239. INSERT INTO table_a VALUES (4, 'four', 4);
  240. > DROP SOURCE table_a;
  241. > ALTER SOURCE mz_source ADD SUBSOURCE table_a;
  242. > SELECT * FROM table_a;
  243. 1 <null> 1
  244. 2 <null> 1
  245. 3 three 1
  246. 4 four 4
  247. ?[version>=13500] EXPLAIN OPTIMIZED PLAN AS VERBOSE TEXT FOR SELECT * FROM table_a WHERE f3 IS NULL;
  248. Explained Query (fast path):
  249. Constant <empty>
  250. Target cluster: quickstart
  251. ?[version<13500] EXPLAIN OPTIMIZED PLAN FOR SELECT * FROM table_a WHERE f3 IS NULL;
  252. Explained Query (fast path):
  253. Constant <empty>
  254. Target cluster: quickstart
  255. # Can add tables with text columns
  256. ! ALTER SOURCE mz_source ADD SUBSOURCE table_f WITH (TEXT COLUMNS [table_f.f2, table_f.f2]);
  257. contains: invalid TEXT COLUMNS option value: unexpected multiple references to postgres.public.table_f.f2
  258. > ALTER SOURCE mz_source ADD SUBSOURCE table_f WITH (TEXT COLUMNS [table_f.f2]);
  259. > SELECT * FROM table_f
  260. 1 var0
  261. 2 var1
  262. >[version>=14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  263. postgres.public.table_f.f2
  264. >[version<14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  265. "\"postgres\".\"public\".\"table_f\".\"f2\""
  266. # Drop a table that's in the publication, which shuffles the tables' output
  267. # indexes, then add a table to the publication and ensure it can be added.
  268. $ postgres-execute connection=postgres://postgres:postgres@postgres
  269. DROP TABLE table_c, table_d;
  270. CREATE TABLE table_i (pk INTEGER PRIMARY KEY, f2 an_enum);
  271. INSERT INTO table_i VALUES (1, 'var0');
  272. ALTER TABLE table_i REPLICA IDENTITY FULL;
  273. INSERT INTO table_i VALUES (2, 'var1');
  274. INSERT INTO table_f VALUES (3, 'var1');
  275. > ALTER SOURCE mz_source ADD SUBSOURCE table_i WITH (TEXT COLUMNS [table_i.f2]);
  276. >[version>=14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  277. "postgres.public.table_f.f2, postgres.public.table_i.f2"
  278. >[version<14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  279. "\"postgres\".\"public\".\"table_f\".\"f2\", \"postgres\".\"public\".\"table_i\".\"f2\""
  280. >[version>=14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE table_i);
  281. f2
  282. >[version<14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE table_i);
  283. "\"f2\""
  284. > SELECT * FROM table_f
  285. 1 var0
  286. 2 var1
  287. 3 var1
  288. > DROP SOURCE table_f, table_i;
  289. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source);
  290. <null>
  291. ! ALTER SOURCE mz_source ADD SUBSOURCE table_e WITH (TEXT COLUMNS (table_z.a));
  292. contains:reference to table_z not found in source
  293. ! ALTER SOURCE mz_source ADD SUBSOURCE table_e WITH (TEXT COLUMNS [table_f.f2]);
  294. contains:TEXT COLUMNS refers to table not currently being added
  295. detail:the following tables are referenced but not added: public.table_f
  296. # Test adding text cols w/o original text columns
  297. > CREATE SOURCE "mz_source_wo_init_text_cols"
  298. FROM POSTGRES CONNECTION pg (
  299. PUBLICATION 'mz_source'
  300. )
  301. FOR TABLES (table_a AS t_a);
  302. > SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source_wo_init_text_cols);
  303. <null>
  304. > ALTER SOURCE mz_source_wo_init_text_cols ADD SUBSOURCE table_f AS t_f WITH (TEXT COLUMNS [table_f.f2]);
  305. >[version>=14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source_wo_init_text_cols);
  306. postgres.public.table_f.f2
  307. >[version<14000] SELECT regexp_match(create_sql, 'TEXT COLUMNS = \((.*?)\)')[1] FROM (SHOW CREATE SOURCE mz_source_wo_init_text_cols);
  308. "\"postgres\".\"public\".\"table_f\".\"f2\""
  309. # add a table after having created the source
  310. $ postgres-execute connection=postgres://postgres:postgres@postgres
  311. CREATE TABLE t2 (f1 BOOLEAN);
  312. ALTER TABLE t2 REPLICA IDENTITY FULL;
  313. ! SELECT COUNT(*) > 0 FROM t2;
  314. contains:unknown catalog item 't2'