alter-source.td 14 KB

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