threshold_elision.slt 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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. mode cockroach
  10. simple conn=mz_system,user=mz_system
  11. ALTER SYSTEM SET unsafe_enable_table_keys = true
  12. ----
  13. COMPLETE 0
  14. statement ok
  15. DROP TABLE IF EXISTS band_members;
  16. statement ok
  17. DROP TABLE IF EXISTS people;
  18. statement ok
  19. DROP TABLE IF EXISTS bands;
  20. statement ok
  21. CREATE TABLE bands (
  22. id INT NOT NULL PRIMARY KEY,
  23. name TEXT NOT NULL
  24. )
  25. statement ok
  26. CREATE TABLE people (
  27. id INT NOT NULL PRIMARY KEY,
  28. name TEXT NOT NULL,
  29. born DATE NOT NULL,
  30. died DATE
  31. )
  32. statement ok
  33. CREATE TABLE band_members (
  34. b_id INT NOT NULL, -- REFERENCES bands(id),
  35. p_id INT NOT NULL -- REFERENCES people(id)
  36. )
  37. statement ok
  38. INSERT INTO bands VALUES
  39. (1, 'The Beatles')
  40. statement ok
  41. INSERT INTO people VALUES
  42. (1, 'John Lennon', '1940-10-09', '1980-12-08'),
  43. (2, 'George Harrison', '1943-02-25', '2001-11-29'),
  44. (3, 'Paul McCartney', '1942-06-18', NULL),
  45. (4, 'Richard Starkey', '1940-07-07', NULL)
  46. statement ok
  47. INSERT INTO band_members VALUES
  48. (1, 1),
  49. (1, 2),
  50. (1, 3),
  51. (1, 4)
  52. # Simple case: EXCEPT ALL with a const literal constraint.
  53. query T multiline
  54. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  55. (
  56. SELECT id FROM people
  57. )
  58. EXCEPT
  59. (
  60. SELECT id FROM people WHERE id = 5
  61. )
  62. ----
  63. Explained Query:
  64. Union // { non_negative: true }
  65. Project (#0{id}) // { non_negative: true }
  66. ReadStorage materialize.public.people // { non_negative: true }
  67. Negate // { non_negative: false }
  68. Project (#0{id}) // { non_negative: true }
  69. Filter (#0{id} = 5) // { non_negative: true }
  70. ReadStorage materialize.public.people // { non_negative: true }
  71. Source materialize.public.people
  72. Target cluster: quickstart
  73. EOF
  74. # Simple case: EXCEPT ALL with an IS NOT NULL filter.
  75. query T multiline
  76. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  77. (
  78. SELECT id FROM people
  79. )
  80. EXCEPT ALL
  81. (
  82. SELECT id FROM people WHERE died IS NOT NULL
  83. )
  84. ----
  85. Explained Query:
  86. Union // { non_negative: true }
  87. Project (#0{id}) // { non_negative: true }
  88. ReadStorage materialize.public.people // { non_negative: true }
  89. Negate // { non_negative: false }
  90. Project (#0{id}) // { non_negative: true }
  91. Filter (#3{died}) IS NOT NULL // { non_negative: true }
  92. ReadStorage materialize.public.people // { non_negative: true }
  93. Source materialize.public.people
  94. Target cluster: quickstart
  95. EOF
  96. # Simple case: EXCEPT.
  97. query T multiline
  98. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  99. SELECT name FROM people
  100. EXCEPT
  101. SELECT name FROM people WHERE id > 1
  102. ----
  103. Explained Query:
  104. Union // { non_negative: true }
  105. Distinct project=[#0{name}] // { non_negative: true }
  106. Project (#1{name}) // { non_negative: true }
  107. ReadStorage materialize.public.people // { non_negative: true }
  108. Negate // { non_negative: false }
  109. Distinct project=[#0{name}] // { non_negative: true }
  110. Project (#1{name}) // { non_negative: true }
  111. Filter (#0{id} > 1) // { non_negative: true }
  112. ReadStorage materialize.public.people // { non_negative: true }
  113. Source materialize.public.people
  114. Target cluster: quickstart
  115. EOF
  116. # Negative example: EXCEPT ALL that should not be confused for an EXCEPT
  117. # the two inputs have a Reduce *with aggregates*.
  118. query T multiline
  119. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  120. SELECT MAX(id) FROM people GROUP BY name
  121. EXCEPT ALL
  122. SELECT MAX(id) FROM (SELECT * FROM people WHERE id > 1) GROUP BY name
  123. ----
  124. Explained Query:
  125. Threshold // { non_negative: true }
  126. Union // { non_negative: false }
  127. Project (#1{max_id}) // { non_negative: true }
  128. Reduce group_by=[#1{name}] aggregates=[max(#0{id})] // { non_negative: true }
  129. Project (#0{id}, #1{name}) // { non_negative: true }
  130. ReadStorage materialize.public.people // { non_negative: true }
  131. Negate // { non_negative: false }
  132. Project (#1{max_id}) // { non_negative: true }
  133. Reduce group_by=[#1{name}] aggregates=[max(#0{id})] // { non_negative: true }
  134. Project (#0{id}, #1{name}) // { non_negative: true }
  135. Filter (#0{id} > 1) // { non_negative: true }
  136. ReadStorage materialize.public.people // { non_negative: true }
  137. Source materialize.public.people
  138. Target cluster: quickstart
  139. EOF
  140. # Complex example: EXCEPT ALL.
  141. # Here ThresholdElision can only match in after some prior simplifications
  142. query T multiline
  143. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  144. (
  145. SELECT
  146. id, name
  147. FROM
  148. people
  149. )
  150. EXCEPT ALL
  151. (
  152. SELECT
  153. *
  154. FROM
  155. (SELECT DISTINCT id FROM people) people_ids,
  156. LATERAL (
  157. SELECT name FROM people
  158. WHERE people.id = people_ids.id
  159. LIMIT 1
  160. )
  161. )
  162. ----
  163. Explained Query:
  164. With
  165. cte l0 =
  166. Project (#0{id}, #1{name}) // { non_negative: true }
  167. ReadStorage materialize.public.people // { non_negative: true }
  168. Return // { non_negative: true }
  169. Union // { non_negative: true }
  170. Get l0 // { non_negative: true }
  171. Negate // { non_negative: false }
  172. TopK group_by=[#0{id}] limit=1 // { non_negative: true }
  173. Get l0 // { non_negative: true }
  174. Source materialize.public.people
  175. Target cluster: quickstart
  176. EOF
  177. # Complex example: EXCEPT.
  178. # Here ThresholdElision can only match in after some prior simplifications
  179. query T multiline
  180. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  181. (
  182. SELECT
  183. id, name
  184. FROM
  185. people
  186. )
  187. EXCEPT
  188. (
  189. SELECT
  190. *
  191. FROM
  192. (SELECT DISTINCT id FROM people) people_ids,
  193. LATERAL (
  194. SELECT name FROM people
  195. WHERE people.id = people_ids.id
  196. LIMIT 1
  197. )
  198. )
  199. ----
  200. Explained Query:
  201. With
  202. cte l0 =
  203. Project (#0{id}, #1{name}) // { non_negative: true }
  204. ReadStorage materialize.public.people // { non_negative: true }
  205. Return // { non_negative: true }
  206. Union // { non_negative: true }
  207. Get l0 // { non_negative: true }
  208. Negate // { non_negative: false }
  209. TopK group_by=[#0{id}] limit=1 // { non_negative: true }
  210. Get l0 // { non_negative: true }
  211. Source materialize.public.people
  212. Target cluster: quickstart
  213. EOF
  214. # Complex example: CTE with a join.
  215. query T multiline
  216. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  217. WITH cte AS (SELECT people.id FROM people, bands)
  218. SELECT * FROM cte EXCEPT ALL SELECT * FROM cte where id > 5;
  219. ----
  220. Explained Query:
  221. With
  222. cte l0 =
  223. CrossJoin type=differential // { non_negative: true }
  224. ArrangeBy keys=[[]] // { non_negative: true }
  225. Project (#0{id}) // { non_negative: true }
  226. ReadStorage materialize.public.people // { non_negative: true }
  227. ArrangeBy keys=[[]] // { non_negative: true }
  228. Project () // { non_negative: true }
  229. ReadStorage materialize.public.bands // { non_negative: true }
  230. Return // { non_negative: true }
  231. Union // { non_negative: true }
  232. Get l0 // { non_negative: true }
  233. Negate // { non_negative: false }
  234. Filter (#0{id} > 5) // { non_negative: true }
  235. Get l0 // { non_negative: true }
  236. Source materialize.public.bands
  237. Source materialize.public.people
  238. Target cluster: quickstart
  239. EOF
  240. # Complex example: CTE with a DISTINCT.
  241. query T multiline
  242. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  243. WITH cte AS (SELECT DISTINCT name FROM people)
  244. SELECT * FROM cte EXCEPT ALL SELECT * FROM cte WHERE name LIKE 'J%'
  245. ----
  246. Explained Query:
  247. With
  248. cte l0 =
  249. Distinct project=[#0{name}] // { non_negative: true }
  250. Project (#1{name}) // { non_negative: true }
  251. ReadStorage materialize.public.people // { non_negative: true }
  252. Return // { non_negative: true }
  253. Union // { non_negative: true }
  254. Get l0 // { non_negative: true }
  255. Negate // { non_negative: false }
  256. Filter like["J%"](#0{name}) // { non_negative: true }
  257. Get l0 // { non_negative: true }
  258. Source materialize.public.people
  259. Target cluster: quickstart
  260. EOF
  261. # Complex example: CTE with a GROUP BY.
  262. query T multiline
  263. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  264. WITH a(birth_year, no_people_born) AS (
  265. SELECT EXTRACT(year from born), COUNT(*)
  266. FROM people
  267. GROUP BY EXTRACT(year from born)
  268. )
  269. SELECT * FROM a EXCEPT (SELECT * FROM a WHERE birth_year > 1940);
  270. ----
  271. Explained Query:
  272. With
  273. cte l0 =
  274. Reduce group_by=[extract_year_d(#0{born})] aggregates=[count(*)] // { non_negative: true }
  275. Project (#2{born}) // { non_negative: true }
  276. ReadStorage materialize.public.people // { non_negative: true }
  277. Return // { non_negative: true }
  278. Union // { non_negative: true }
  279. Get l0 // { non_negative: true }
  280. Negate // { non_negative: false }
  281. Filter (#0{birth_year} > 1940) // { non_negative: true }
  282. Get l0 // { non_negative: true }
  283. Source materialize.public.people
  284. Target cluster: quickstart
  285. EOF
  286. # Complex example: a chain of CTEs with:
  287. # (1) an EXCEPT ALL in cte1 (that is, a plan containing Negate),
  288. # (2) a non-pushable operation (Distinct) in the cte2,
  289. # (3) an EXCEPT in the final result,
  290. # The optimization still removes the Threshold operators in both
  291. # (1) and (3) because the non negative value inferred for cte1
  292. # prior to the rewrite is maintained for downstream rewrites.
  293. query T multiline
  294. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  295. WITH cte1 AS (
  296. SELECT * FROM people
  297. EXCEPT ALL
  298. SELECT * FROM people WHERE name LIKE 'J%'
  299. ), cte2 AS (
  300. SELECT DISTINCT * FROM cte1
  301. )
  302. SELECT * FROM cte2
  303. EXCEPT
  304. SELECT * FROM cte2 WHERE name LIKE 'P%';
  305. ----
  306. Explained Query:
  307. With
  308. cte l0 =
  309. Distinct project=[#0{id}..=#3{died}] // { non_negative: true }
  310. Union // { non_negative: true }
  311. ReadStorage materialize.public.people // { non_negative: true }
  312. Negate // { non_negative: false }
  313. Filter like["J%"](#1{name}) // { non_negative: true }
  314. ReadStorage materialize.public.people // { non_negative: true }
  315. Return // { non_negative: true }
  316. Union // { non_negative: true }
  317. Get l0 // { non_negative: true }
  318. Negate // { non_negative: false }
  319. Filter like["P%"](#1{name}) // { non_negative: true }
  320. Get l0 // { non_negative: true }
  321. Source materialize.public.people
  322. Target cluster: quickstart
  323. EOF
  324. # Complex example (unsupported): A - (σ(p)(A) ⊎ σ(q)(A)).
  325. query T multiline
  326. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  327. SELECT name FROM people
  328. EXCEPT ALL
  329. (
  330. SELECT name FROM people WHERE id = 1
  331. UNION ALL
  332. SELECT name FROM people WHERE id = 2
  333. )
  334. ----
  335. Explained Query:
  336. Threshold // { non_negative: true }
  337. Union // { non_negative: false }
  338. Project (#1{name}) // { non_negative: true }
  339. ReadStorage materialize.public.people // { non_negative: true }
  340. Negate // { non_negative: false }
  341. Project (#1{name}) // { non_negative: true }
  342. Filter (#0{id} = 1) // { non_negative: true }
  343. ReadStorage materialize.public.people // { non_negative: true }
  344. Negate // { non_negative: false }
  345. Project (#1{name}) // { non_negative: true }
  346. Filter (#0{id} = 2) // { non_negative: true }
  347. ReadStorage materialize.public.people // { non_negative: true }
  348. Source materialize.public.people
  349. Target cluster: quickstart
  350. EOF
  351. # WMR
  352. # https://github.com/MaterializeInc/database-issues/issues/5344
  353. # WMR -- Threshold in the loop-invariant part
  354. # The "Very basic" implementation from database-issues#5344 should handle this.
  355. query T multiline
  356. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  357. WITH MUTUALLY RECURSIVE
  358. c0(id int, name text) as (
  359. SELECT id, name FROM people
  360. EXCEPT
  361. SELECT id, name FROM people WHERE id > 1
  362. ),
  363. c1(id int, name text) as (
  364. (SELECT id, name || '_init' FROM c0)
  365. UNION
  366. (
  367. SELECT id, name || '_iter' FROM c1
  368. )
  369. )
  370. SELECT * FROM c1
  371. ----
  372. Explained Query:
  373. With Mutually Recursive
  374. cte l0 =
  375. Distinct project=[#0{id}, #1] // { non_negative: true }
  376. Union // { non_negative: true }
  377. Project (#0{id}, #2) // { non_negative: true }
  378. Map ((#1{name} || "_init")) // { non_negative: true }
  379. Union // { non_negative: true }
  380. Project (#0{id}, #1{name}) // { non_negative: true }
  381. ReadStorage materialize.public.people // { non_negative: true }
  382. Negate // { non_negative: false }
  383. Project (#0{id}, #1{name}) // { non_negative: true }
  384. Filter (#0{id} > 1) // { non_negative: true }
  385. ReadStorage materialize.public.people // { non_negative: true }
  386. Project (#0, #2) // { non_negative: true }
  387. Map ((#1{name} || "_iter")) // { non_negative: true }
  388. Get l0 // { non_negative: true }
  389. Return // { non_negative: true }
  390. Get l0 // { non_negative: true }
  391. Source materialize.public.people
  392. Target cluster: quickstart
  393. EOF
  394. # WMR -- Threshold inside the cycle -- Two Thresholds, the second one should be easy to eliminate, because the result of
  395. # the first one is obviously non-negative.
  396. # The "Basic" implementation from database-issues#5344 should handle this.
  397. query T multiline
  398. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  399. WITH MUTUALLY RECURSIVE
  400. c1(id int, name text) as (
  401. (SELECT id, name || '_init' FROM people)
  402. UNION
  403. (
  404. SELECT id, name || '_iter' FROM c2
  405. EXCEPT
  406. SELECT id, name || '_iter' FROM c2 WHERE id > 1
  407. )
  408. ),
  409. c2(id int, name text) as (
  410. SELECT * FROM c1
  411. EXCEPT
  412. SELECT * FROM c1 WHERE id > 2
  413. )
  414. SELECT * FROM c1
  415. ----
  416. Explained Query:
  417. With Mutually Recursive
  418. cte l0 =
  419. Distinct project=[#0{id}, #1] // { non_negative: true }
  420. Union // { non_negative: false }
  421. Project (#0{id}, #4) // { non_negative: true }
  422. Map ((#1{name} || "_init")) // { non_negative: true }
  423. ReadStorage materialize.public.people // { non_negative: true }
  424. Distinct project=[#0, (#1{name} || "_iter")] // { non_negative: true }
  425. Get l1 // { non_negative: true }
  426. Negate // { non_negative: false }
  427. Distinct project=[#0, (#1{name} || "_iter")] // { non_negative: true }
  428. Filter (#0{id} > 1) // { non_negative: true }
  429. Get l1 // { non_negative: true }
  430. cte l1 =
  431. Union // { non_negative: true }
  432. Get l0 // { non_negative: true }
  433. Negate // { non_negative: false }
  434. Filter (#0{id} > 2) // { non_negative: true }
  435. Get l0 // { non_negative: true }
  436. Return // { non_negative: true }
  437. Get l0 // { non_negative: true }
  438. Source materialize.public.people
  439. Target cluster: quickstart
  440. EOF
  441. # WMR -- Threshold inside the cycle.
  442. query T multiline
  443. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  444. WITH MUTUALLY RECURSIVE
  445. c0(id int, name text) as (
  446. (SELECT id, name || '_init' FROM people)
  447. UNION
  448. (
  449. SELECT id, name || '_iter' FROM c0
  450. EXCEPT
  451. SELECT id, name || '_iter' FROM c0 WHERE id > 1
  452. )
  453. )
  454. SELECT * FROM c0
  455. ----
  456. Explained Query:
  457. With Mutually Recursive
  458. cte l0 =
  459. Distinct project=[#0{id}, #1] // { non_negative: true }
  460. Union // { non_negative: false }
  461. Project (#0{id}, #4) // { non_negative: true }
  462. Map ((#1{name} || "_init")) // { non_negative: true }
  463. ReadStorage materialize.public.people // { non_negative: true }
  464. Distinct project=[#0{id}, (#1{name} || "_iter")] // { non_negative: true }
  465. Get l0 // { non_negative: true }
  466. Negate // { non_negative: false }
  467. Distinct project=[#0, (#1{name} || "_iter")] // { non_negative: true }
  468. Filter (#0{id} > 1) // { non_negative: true }
  469. Get l0 // { non_negative: true }
  470. Return // { non_negative: true }
  471. Get l0 // { non_negative: true }
  472. Source materialize.public.people
  473. Target cluster: quickstart
  474. EOF
  475. statement ok
  476. CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
  477. # Literal filter, which would be made unrecognizable by
  478. # ColumnKnowledge, LiteralLifting, EquivalencePropagation.
  479. query T multiline
  480. EXPLAIN OPTIMIZED PLAN WITH(non negative, humanized expressions) AS VERBOSE TEXT FOR
  481. SELECT f1 FROM t1 EXCEPT SELECT f1 FROM t1 WHERE f1 = 5;
  482. ----
  483. Explained Query:
  484. Union // { non_negative: false }
  485. Distinct project=[#0{f1}] // { non_negative: true }
  486. Project (#0{f1}) // { non_negative: true }
  487. ReadStorage materialize.public.t1 // { non_negative: true }
  488. Negate // { non_negative: false }
  489. Map (5) // { non_negative: true }
  490. Distinct project=[] // { non_negative: true }
  491. Project () // { non_negative: true }
  492. Filter (#0{f1} = 5) // { non_negative: true }
  493. ReadStorage materialize.public.t1 // { non_negative: true }
  494. Source materialize.public.t1
  495. Target cluster: quickstart
  496. EOF