subexpression-replacement.td 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. #
  10. # Tests for the optimization described in https://github.com/MaterializeInc/materialize/pull/6196/
  11. # Additional tests in test/sqllogictest/transform/predicate_reduction.slt
  12. #
  13. $ set-sql-timeout duration=125ms
  14. # Remove references to internal table identifiers and "materialize.public" strings
  15. $ set-regex match=(\s\(u\d+\)|materialize\.public\.) replacement=
  16. > CREATE TABLE t1 (col_null INTEGER, col_not_null INTEGER NOT NULL);
  17. > CREATE DEFAULT INDEX on t1
  18. > INSERT INTO t1 VALUES (1, 1);
  19. # The simplest expression there could be
  20. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null IS NULL AND (col_null IS NULL AND col_not_null = 5);
  21. Explained Query (fast path):
  22. Filter (#0{col_null}) IS NULL AND (#1{col_not_null} = 5)
  23. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  24. Used Indexes:
  25. - t1_primary_idx (*** full scan ***)
  26. Target cluster: quickstart
  27. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null = 1 AND (col_not_null = 1 AND col_null = 5);
  28. Explained Query (fast path):
  29. Project (#0, #1)
  30. ReadIndex on=t1 t1_primary_idx=[lookup value=(5, 1)]
  31. Used Indexes:
  32. - t1_primary_idx (lookup)
  33. Target cluster: quickstart
  34. # NULL-able expressions are dedupped
  35. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null = 1 AND (col_null = 1 AND col_not_null = 5);
  36. Explained Query (fast path):
  37. Project (#0, #1)
  38. ReadIndex on=t1 t1_primary_idx=[lookup value=(1, 5)]
  39. Used Indexes:
  40. - t1_primary_idx (lookup)
  41. Target cluster: quickstart
  42. # OR/disjunction at the top level
  43. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null IS NULL OR (col_null IS NULL AND col_not_null = 5);
  44. Explained Query (fast path):
  45. Filter (#0{col_null}) IS NULL
  46. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  47. Used Indexes:
  48. - t1_primary_idx (*** full scan ***)
  49. Target cluster: quickstart
  50. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null IS NULL OR col_null IS NULL OR (col_null IS NULL AND col_not_null = 5);
  51. Explained Query (fast path):
  52. Filter (#0{col_null}) IS NULL
  53. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  54. Used Indexes:
  55. - t1_primary_idx (*** full scan ***)
  56. Target cluster: quickstart
  57. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null IS NULL OR (col_null IS NULL AND col_not_null = 5) OR (col_null IS NULL AND col_not_null = 6);
  58. Explained Query (fast path):
  59. Filter (#0{col_null}) IS NULL
  60. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  61. Used Indexes:
  62. - t1_primary_idx (*** full scan ***)
  63. Target cluster: quickstart
  64. # OR/disjunction at the lower level
  65. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null IS NULL AND (col_null IS NULL OR col_not_null = 5);
  66. Explained Query (fast path):
  67. Filter (#0{col_null}) IS NULL
  68. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  69. Used Indexes:
  70. - t1_primary_idx (*** full scan ***)
  71. Target cluster: quickstart
  72. # Nested OR/disjunction
  73. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_null IS NULL OR (col_null IS NULL OR col_not_null = 5);
  74. Explained Query (fast path):
  75. Filter ((#0{col_null}) IS NULL OR (#1{col_not_null} = 5))
  76. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  77. Used Indexes:
  78. - t1_primary_idx (*** full scan ***)
  79. Target cluster: quickstart
  80. # A more complex expression
  81. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE (col_not_null + 1 / col_not_null) = 5 AND ((col_not_null + 1 / col_not_null) = 5 AND col_null = 6);
  82. Explained Query (fast path):
  83. Filter (#0{col_null} = 6) AND (5 = (#1{col_not_null} + (1 / #1{col_not_null})))
  84. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  85. Used Indexes:
  86. - t1_primary_idx (*** full scan ***)
  87. Target cluster: quickstart
  88. # More nesting
  89. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null + col_not_null + col_not_null = 5 AND (col_not_null + col_not_null + col_not_null = 5);
  90. Explained Query (fast path):
  91. Filter (5 = ((#1{col_not_null} + #1{col_not_null}) + #1{col_not_null}))
  92. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  93. Used Indexes:
  94. - t1_primary_idx (*** full scan ***)
  95. Target cluster: quickstart
  96. # The common expression contains an AND/conjunction itself
  97. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE ((col_not_null > 3) AND (col_not_null < 5)) AND ((col_not_null > 3) AND (col_not_null < 5) OR col_not_null = 10);
  98. Explained Query (fast path):
  99. Filter (#1{col_not_null} < 5) AND (#1{col_not_null} > 3)
  100. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  101. Used Indexes:
  102. - t1_primary_idx (*** full scan ***)
  103. Target cluster: quickstart
  104. # The common expression contains an OR/disjunction
  105. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE ((col_not_null > 3) OR (col_not_null < 5)) OR ((col_not_null > 3) OR (col_not_null < 5));
  106. Explained Query (fast path):
  107. Filter ((#1{col_not_null} < 5) OR (#1{col_not_null} > 3))
  108. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  109. Used Indexes:
  110. - t1_primary_idx (*** full scan ***)
  111. Target cluster: quickstart
  112. # Use of a deterministic function
  113. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null % 2 = 5 AND (col_not_null % 2 = 5 IS NULL);
  114. Explained Query (fast path):
  115. Constant <empty>
  116. Target cluster: quickstart
  117. # This is not optimized
  118. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE (col_not_null % 2) = 1 AND (((col_not_null % 2) = 1) = TRUE);
  119. Explained Query (fast path):
  120. Filter (1 = (#1{col_not_null} % 2))
  121. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  122. Used Indexes:
  123. - t1_primary_idx (*** full scan ***)
  124. Target cluster: quickstart
  125. # Column used on both sides of the expression
  126. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE (col_not_null = col_not_null + 1) AND (col_not_null = col_not_null + 1);
  127. Explained Query (fast path):
  128. Filter (#1{col_not_null} = (#1{col_not_null} + 1))
  129. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  130. Used Indexes:
  131. - t1_primary_idx (*** full scan ***)
  132. Target cluster: quickstart
  133. # TODO (https://github.com/MaterializeInc/database-issues/issues/1929): Avoid simplifying mz_sleep.
  134. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1
  135. WHERE mz_unsafe.mz_sleep(col_not_null) > mz_unsafe.mz_sleep(col_not_null)
  136. AND (mz_unsafe.mz_sleep(col_not_null) > mz_unsafe.mz_sleep(col_not_null) = true);
  137. Explained Query (fast path):
  138. Project (#0, #1)
  139. Filter (#2 > #2)
  140. Map (mz_sleep(integer_to_double(#1{col_not_null})))
  141. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  142. Used Indexes:
  143. - t1_primary_idx (*** full scan ***)
  144. Target cluster: quickstart
  145. # IN list inside the expression
  146. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null IN (2, 3) AND col_not_null IN (2, 3);
  147. Explained Query (fast path):
  148. Filter ((#1{col_not_null} = 2) OR (#1{col_not_null} = 3))
  149. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  150. Used Indexes:
  151. - t1_primary_idx (*** full scan ***)
  152. Target cluster: quickstart
  153. # Partial matches
  154. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null IN (2, 3) AND col_not_null IN (3, 4);
  155. Explained Query (fast path):
  156. Filter (#1{col_not_null} = 3)
  157. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  158. Used Indexes:
  159. - t1_primary_idx (*** full scan ***)
  160. Target cluster: quickstart
  161. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null IN (2, 3) AND col_not_null IN (4, 5);
  162. Explained Query (fast path):
  163. Constant <empty>
  164. Target cluster: quickstart
  165. # Expression inside an IN list
  166. # Optimized in AND/conjunctions
  167. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null = 1 AND TRUE IN (col_not_null = 1, col_not_null = 2);
  168. Explained Query (fast path):
  169. Filter (#1{col_not_null} = 1)
  170. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  171. Used Indexes:
  172. - t1_primary_idx (*** full scan ***)
  173. Target cluster: quickstart
  174. # Not optimized in OR/disjunctions
  175. ? EXPLAIN OPTIMIZED PLAN WITH(no notices) AS VERBOSE TEXT FOR SELECT * FROM t1 WHERE col_not_null = 1 OR TRUE IN (col_not_null = 1, col_not_null = 2);
  176. Explained Query (fast path):
  177. Project (#0, #1)
  178. Filter (#2 OR (#2 = true) OR (true = (#1{col_not_null} = 2)))
  179. Map ((#1{col_not_null} = 1))
  180. ReadIndex on=t1 t1_primary_idx=[*** full scan ***]
  181. Used Indexes:
  182. - t1_primary_idx (*** full scan ***)
  183. Target cluster: quickstart