github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/norm/testdata/rules/reject_nulls (about) 1 exec-ddl 2 CREATE TABLE a (k INT PRIMARY KEY, i INT, f FLOAT, s STRING) 3 ---- 4 5 exec-ddl 6 CREATE TABLE xy (x INT PRIMARY KEY, y INT) 7 ---- 8 9 exec-ddl 10 CREATE TABLE uv (u INT PRIMARY KEY, v INT) 11 ---- 12 13 # ---------------------------------------------------------- 14 # RejectNullsLeftJoin + RejectNullsRightJoin 15 # ---------------------------------------------------------- 16 17 norm expect=RejectNullsRightJoin 18 SELECT * FROM a FULL JOIN xy ON true WHERE a.k IS NOT NULL 19 ---- 20 left-join (cross) 21 ├── columns: k:1!null i:2 f:3 s:4 x:5 y:6 22 ├── key: (1,5) 23 ├── fd: (1)-->(2-4), (5)-->(6) 24 ├── scan a 25 │ ├── columns: k:1!null i:2 f:3 s:4 26 │ ├── key: (1) 27 │ └── fd: (1)-->(2-4) 28 ├── scan xy 29 │ ├── columns: x:5!null y:6 30 │ ├── key: (5) 31 │ └── fd: (5)-->(6) 32 └── filters (true) 33 34 norm expect=RejectNullsLeftJoin 35 SELECT * FROM a FULL JOIN xy ON true WHERE xy.x > 5 36 ---- 37 left-join (cross) 38 ├── columns: k:1 i:2 f:3 s:4 x:5!null y:6 39 ├── key: (1,5) 40 ├── fd: (5)-->(6), (1)-->(2-4) 41 ├── select 42 │ ├── columns: x:5!null y:6 43 │ ├── key: (5) 44 │ ├── fd: (5)-->(6) 45 │ ├── scan xy 46 │ │ ├── columns: x:5!null y:6 47 │ │ ├── key: (5) 48 │ │ └── fd: (5)-->(6) 49 │ └── filters 50 │ └── x:5 > 5 [outer=(5), constraints=(/5: [/6 - ]; tight)] 51 ├── scan a 52 │ ├── columns: k:1!null i:2 f:3 s:4 53 │ ├── key: (1) 54 │ └── fd: (1)-->(2-4) 55 └── filters (true) 56 57 # Inner-join operator. 58 norm expect=RejectNullsLeftJoin 59 SELECT * 60 FROM (SELECT * FROM a LEFT JOIN uv ON True) AS l 61 INNER JOIN (SELECT * FROM a LEFT JOIN uv ON True) AS r 62 ON l.u=1 AND r.v>2 63 ---- 64 inner-join (cross) 65 ├── columns: k:1!null i:2 f:3 s:4 u:5!null v:6 k:7!null i:8 f:9 s:10 u:11!null v:12!null 66 ├── key: (1,7,11) 67 ├── fd: ()-->(5,6), (1)-->(2-4), (7)-->(8-10), (11)-->(12) 68 ├── inner-join (cross) 69 │ ├── columns: k:1!null i:2 f:3 s:4 u:5!null v:6 70 │ ├── key: (1) 71 │ ├── fd: ()-->(5,6), (1)-->(2-4) 72 │ ├── scan a 73 │ │ ├── columns: k:1!null i:2 f:3 s:4 74 │ │ ├── key: (1) 75 │ │ └── fd: (1)-->(2-4) 76 │ ├── select 77 │ │ ├── columns: u:5!null v:6 78 │ │ ├── cardinality: [0 - 1] 79 │ │ ├── key: () 80 │ │ ├── fd: ()-->(5,6) 81 │ │ ├── scan uv 82 │ │ │ ├── columns: u:5!null v:6 83 │ │ │ ├── key: (5) 84 │ │ │ └── fd: (5)-->(6) 85 │ │ └── filters 86 │ │ └── u:5 = 1 [outer=(5), constraints=(/5: [/1 - /1]; tight), fd=()-->(5)] 87 │ └── filters (true) 88 ├── inner-join (cross) 89 │ ├── columns: k:7!null i:8 f:9 s:10 u:11!null v:12!null 90 │ ├── key: (7,11) 91 │ ├── fd: (7)-->(8-10), (11)-->(12) 92 │ ├── scan a 93 │ │ ├── columns: k:7!null i:8 f:9 s:10 94 │ │ ├── key: (7) 95 │ │ └── fd: (7)-->(8-10) 96 │ ├── select 97 │ │ ├── columns: u:11!null v:12!null 98 │ │ ├── key: (11) 99 │ │ ├── fd: (11)-->(12) 100 │ │ ├── scan uv 101 │ │ │ ├── columns: u:11!null v:12 102 │ │ │ ├── key: (11) 103 │ │ │ └── fd: (11)-->(12) 104 │ │ └── filters 105 │ │ └── v:12 > 2 [outer=(12), constraints=(/12: [/3 - ]; tight)] 106 │ └── filters (true) 107 └── filters (true) 108 109 # Left-join operator. 110 norm expect=RejectNullsLeftJoin 111 SELECT * FROM a LEFT JOIN xy ON true WHERE xy.x = a.k 112 ---- 113 inner-join (hash) 114 ├── columns: k:1!null i:2 f:3 s:4 x:5!null y:6 115 ├── key: (5) 116 ├── fd: (1)-->(2-4), (5)-->(6), (1)==(5), (5)==(1) 117 ├── scan a 118 │ ├── columns: k:1!null i:2 f:3 s:4 119 │ ├── key: (1) 120 │ └── fd: (1)-->(2-4) 121 ├── scan xy 122 │ ├── columns: x:5!null y:6 123 │ ├── key: (5) 124 │ └── fd: (5)-->(6) 125 └── filters 126 └── x:5 = k:1 [outer=(1,5), constraints=(/1: (/NULL - ]; /5: (/NULL - ]), fd=(1)==(5), (5)==(1)] 127 128 # Full-join operator. 129 norm expect=RejectNullsLeftJoin 130 SELECT * FROM a FULL JOIN xy ON true WHERE a.k IS NOT NULL AND xy.x > 5 131 ---- 132 inner-join (cross) 133 ├── columns: k:1!null i:2 f:3 s:4 x:5!null y:6 134 ├── key: (1,5) 135 ├── fd: (5)-->(6), (1)-->(2-4) 136 ├── select 137 │ ├── columns: x:5!null y:6 138 │ ├── key: (5) 139 │ ├── fd: (5)-->(6) 140 │ ├── scan xy 141 │ │ ├── columns: x:5!null y:6 142 │ │ ├── key: (5) 143 │ │ └── fd: (5)-->(6) 144 │ └── filters 145 │ └── x:5 > 5 [outer=(5), constraints=(/5: [/6 - ]; tight)] 146 ├── scan a 147 │ ├── columns: k:1!null i:2 f:3 s:4 148 │ ├── key: (1) 149 │ └── fd: (1)-->(2-4) 150 └── filters (true) 151 152 # Left-join-apply operator. 153 norm expect=RejectNullsLeftJoin 154 SELECT * FROM a LEFT JOIN LATERAL (SELECT * FROM (VALUES (i), (i)) v(y)) ON y>10 WHERE i=y 155 ---- 156 inner-join-apply 157 ├── columns: k:1!null i:2!null f:3 s:4 y:5 158 ├── fd: (1)-->(2-4), (2)==(5), (5)==(2) 159 ├── select 160 │ ├── columns: k:1!null i:2!null f:3 s:4 161 │ ├── key: (1) 162 │ ├── fd: (1)-->(2-4) 163 │ ├── scan a 164 │ │ ├── columns: k:1!null i:2 f:3 s:4 165 │ │ ├── key: (1) 166 │ │ └── fd: (1)-->(2-4) 167 │ └── filters 168 │ └── i:2 > 10 [outer=(2), constraints=(/2: [/11 - ]; tight)] 169 ├── values 170 │ ├── columns: column1:5 171 │ ├── outer: (2) 172 │ ├── cardinality: [2 - 2] 173 │ ├── (i:2,) 174 │ └── (i:2,) 175 └── filters 176 └── i:2 = column1:5 [outer=(2,5), constraints=(/2: (/NULL - ]; /5: (/NULL - ]), fd=(2)==(5), (5)==(2)] 177 178 # Full-join operator. 179 norm expect=RejectNullsRightJoin 180 SELECT * FROM a FULL JOIN xy ON true WHERE i IS NOT NULL 181 ---- 182 left-join (cross) 183 ├── columns: k:1!null i:2!null f:3 s:4 x:5 y:6 184 ├── key: (1,5) 185 ├── fd: (1)-->(2-4), (5)-->(6) 186 ├── select 187 │ ├── columns: k:1!null i:2!null f:3 s:4 188 │ ├── key: (1) 189 │ ├── fd: (1)-->(2-4) 190 │ ├── scan a 191 │ │ ├── columns: k:1!null i:2 f:3 s:4 192 │ │ ├── key: (1) 193 │ │ └── fd: (1)-->(2-4) 194 │ └── filters 195 │ └── i:2 IS NOT NULL [outer=(2), constraints=(/2: (/NULL - ]; tight)] 196 ├── scan xy 197 │ ├── columns: x:5!null y:6 198 │ ├── key: (5) 199 │ └── fd: (5)-->(6) 200 └── filters (true) 201 202 # ---------------------------------------------------------- 203 # RejectNullsGroupBy 204 # ---------------------------------------------------------- 205 206 # Single max aggregate function. 207 norm expect=RejectNullsGroupBy 208 SELECT max(x) 209 FROM (SELECT k FROM a) 210 LEFT JOIN (SELECT x FROM xy) 211 ON True 212 GROUP BY k 213 HAVING max(x)=1 214 ---- 215 project 216 ├── columns: max:7!null 217 ├── fd: ()-->(7) 218 └── select 219 ├── columns: k:1!null max:7!null 220 ├── key: (1) 221 ├── fd: ()-->(7) 222 ├── group-by 223 │ ├── columns: k:1!null max:7!null 224 │ ├── grouping columns: k:1!null 225 │ ├── key: (1) 226 │ ├── fd: (1)-->(7) 227 │ ├── inner-join (cross) 228 │ │ ├── columns: k:1!null x:5!null 229 │ │ ├── key: (1,5) 230 │ │ ├── scan a 231 │ │ │ ├── columns: k:1!null 232 │ │ │ └── key: (1) 233 │ │ ├── scan xy 234 │ │ │ ├── columns: x:5!null 235 │ │ │ └── key: (5) 236 │ │ └── filters (true) 237 │ └── aggregations 238 │ └── max [as=max:7, outer=(5)] 239 │ └── x:5 240 └── filters 241 └── max:7 = 1 [outer=(7), constraints=(/7: [/1 - /1]; tight), fd=()-->(7)] 242 243 # Aggregate function with DISTINCT. 244 norm expect=RejectNullsGroupBy 245 SELECT sum(DISTINCT y) 246 FROM (SELECT k FROM a) 247 LEFT JOIN (SELECT y FROM xy) 248 ON True 249 GROUP BY k 250 HAVING sum(DISTINCT y)=1 251 ---- 252 project 253 ├── columns: sum:7!null 254 ├── fd: ()-->(7) 255 └── select 256 ├── columns: k:1!null sum:7!null 257 ├── key: (1) 258 ├── fd: ()-->(7) 259 ├── group-by 260 │ ├── columns: k:1!null sum:7!null 261 │ ├── grouping columns: k:1!null 262 │ ├── key: (1) 263 │ ├── fd: (1)-->(7) 264 │ ├── inner-join (cross) 265 │ │ ├── columns: k:1!null y:6!null 266 │ │ ├── scan a 267 │ │ │ ├── columns: k:1!null 268 │ │ │ └── key: (1) 269 │ │ ├── select 270 │ │ │ ├── columns: y:6!null 271 │ │ │ ├── scan xy 272 │ │ │ │ └── columns: y:6 273 │ │ │ └── filters 274 │ │ │ └── y:6 IS NOT NULL [outer=(6), constraints=(/6: (/NULL - ]; tight)] 275 │ │ └── filters (true) 276 │ └── aggregations 277 │ └── agg-distinct [as=sum:7, outer=(6)] 278 │ └── sum 279 │ └── y:6 280 └── filters 281 └── sum:7 = 1 [outer=(7), constraints=(/7: [/1 - /1]; tight), fd=()-->(7)] 282 283 # Single max aggregate function without grouping columns. 284 norm expect=RejectNullsGroupBy 285 SELECT max(x) 286 FROM (SELECT k FROM a) 287 LEFT JOIN (SELECT x FROM xy) 288 ON True 289 HAVING max(x)=1 290 ---- 291 select 292 ├── columns: max:7!null 293 ├── cardinality: [0 - 1] 294 ├── key: () 295 ├── fd: ()-->(7) 296 ├── scalar-group-by 297 │ ├── columns: max:7 298 │ ├── cardinality: [1 - 1] 299 │ ├── key: () 300 │ ├── fd: ()-->(7) 301 │ ├── inner-join (cross) 302 │ │ ├── columns: x:5!null 303 │ │ ├── scan a 304 │ │ ├── scan xy 305 │ │ │ ├── columns: x:5!null 306 │ │ │ └── key: (5) 307 │ │ └── filters (true) 308 │ └── aggregations 309 │ └── max [as=max:7, outer=(5)] 310 │ └── x:5 311 └── filters 312 └── max:7 = 1 [outer=(7), constraints=(/7: [/1 - /1]; tight), fd=()-->(7)] 313 314 # Multiple aggregate functions on same column. 315 norm expect=RejectNullsGroupBy 316 SELECT min(x), max(x) 317 FROM a 318 LEFT JOIN xy 319 ON True 320 GROUP BY k 321 HAVING min(x)=1 322 ---- 323 project 324 ├── columns: min:7!null max:8!null 325 ├── fd: ()-->(7) 326 └── select 327 ├── columns: k:1!null min:7!null max:8!null 328 ├── key: (1) 329 ├── fd: ()-->(7), (1)-->(8) 330 ├── group-by 331 │ ├── columns: k:1!null min:7!null max:8!null 332 │ ├── grouping columns: k:1!null 333 │ ├── key: (1) 334 │ ├── fd: (1)-->(7,8) 335 │ ├── inner-join (cross) 336 │ │ ├── columns: k:1!null x:5!null 337 │ │ ├── key: (1,5) 338 │ │ ├── scan a 339 │ │ │ ├── columns: k:1!null 340 │ │ │ └── key: (1) 341 │ │ ├── scan xy 342 │ │ │ ├── columns: x:5!null 343 │ │ │ └── key: (5) 344 │ │ └── filters (true) 345 │ └── aggregations 346 │ ├── min [as=min:7, outer=(5)] 347 │ │ └── x:5 348 │ └── max [as=max:8, outer=(5)] 349 │ └── x:5 350 └── filters 351 └── min:7 = 1 [outer=(7), constraints=(/7: [/1 - /1]; tight), fd=()-->(7)] 352 353 # Multiple aggregate functions on same column, some with DISTINCT. 354 norm expect=RejectNullsGroupBy 355 SELECT sum(DISTINCT y), max(y) 356 FROM a 357 LEFT JOIN xy 358 ON True 359 GROUP BY k 360 HAVING max(y)=1 361 ---- 362 project 363 ├── columns: sum:7!null max:8!null 364 ├── fd: ()-->(8) 365 └── select 366 ├── columns: k:1!null sum:7!null max:8!null 367 ├── key: (1) 368 ├── fd: ()-->(8), (1)-->(7) 369 ├── group-by 370 │ ├── columns: k:1!null sum:7!null max:8!null 371 │ ├── grouping columns: k:1!null 372 │ ├── key: (1) 373 │ ├── fd: (1)-->(7,8) 374 │ ├── inner-join (cross) 375 │ │ ├── columns: k:1!null y:6!null 376 │ │ ├── scan a 377 │ │ │ ├── columns: k:1!null 378 │ │ │ └── key: (1) 379 │ │ ├── select 380 │ │ │ ├── columns: y:6!null 381 │ │ │ ├── scan xy 382 │ │ │ │ └── columns: y:6 383 │ │ │ └── filters 384 │ │ │ └── y:6 IS NOT NULL [outer=(6), constraints=(/6: (/NULL - ]; tight)] 385 │ │ └── filters (true) 386 │ └── aggregations 387 │ ├── agg-distinct [as=sum:7, outer=(6)] 388 │ │ └── sum 389 │ │ └── y:6 390 │ └── max [as=max:8, outer=(6)] 391 │ └── y:6 392 └── filters 393 └── max:8 = 1 [outer=(8), constraints=(/8: [/1 - /1]; tight), fd=()-->(8)] 394 395 396 # Ignore ConstAgg aggregates on other columns. 397 exprnorm expect=RejectNullsGroupBy 398 (Root 399 (Select 400 (ScalarGroupBy 401 (LeftJoin 402 (Scan [ (Table "xy") (Cols "x,y") ]) 403 (Scan [ (Table "uv") (Cols "u,v") ]) 404 [ ] 405 [ ] 406 ) 407 [ 408 (AggregationsItem (Sum (Var "v")) (NewColumn "sum" "int")) 409 (AggregationsItem (ConstAgg (Var "u")) (NewColumn "const" "int")) 410 ] 411 [ ] 412 ) 413 [ (Eq (Var "sum") (Const 10 "int")) ] 414 ) 415 (Presentation "u,v") 416 (NoOrdering) 417 ) 418 ---- 419 select 420 ├── columns: u:3 v:4 [hidden: sum:5!null const:6] 421 ├── cardinality: [0 - 1] 422 ├── key: () 423 ├── fd: ()-->(5,6) 424 ├── scalar-group-by 425 │ ├── columns: sum:5 const:6 426 │ ├── cardinality: [1 - 1] 427 │ ├── key: () 428 │ ├── fd: ()-->(5,6) 429 │ ├── inner-join (cross) 430 │ │ ├── columns: u:3!null v:4!null 431 │ │ ├── fd: (3)-->(4) 432 │ │ ├── scan xy 433 │ │ ├── select 434 │ │ │ ├── columns: u:3!null v:4!null 435 │ │ │ ├── key: (3) 436 │ │ │ ├── fd: (3)-->(4) 437 │ │ │ ├── scan uv 438 │ │ │ │ ├── columns: u:3!null v:4 439 │ │ │ │ ├── key: (3) 440 │ │ │ │ └── fd: (3)-->(4) 441 │ │ │ └── filters 442 │ │ │ └── v:4 IS NOT NULL [outer=(4), constraints=(/4: (/NULL - ]; tight)] 443 │ │ └── filters (true) 444 │ └── aggregations 445 │ ├── sum [as=sum:5, outer=(4)] 446 │ │ └── v:4 447 │ └── const-agg [as=const:6, outer=(3)] 448 │ └── u:3 449 └── filters 450 └── sum:5 = 10 [outer=(5), constraints=(/5: [/10 - /10]; tight), fd=()-->(5)] 451 452 # Don't reject nulls when multiple columns are used. 453 norm expect-not=RejectNullsGroupBy 454 SELECT min(x), max(y) 455 FROM (select k from a) 456 LEFT JOIN (select x, y from xy) 457 ON True 458 GROUP BY k 459 HAVING min(x)=1 460 ---- 461 project 462 ├── columns: min:7!null max:8 463 ├── fd: ()-->(7) 464 └── select 465 ├── columns: k:1!null min:7!null max:8 466 ├── key: (1) 467 ├── fd: ()-->(7), (1)-->(8) 468 ├── group-by 469 │ ├── columns: k:1!null min:7 max:8 470 │ ├── grouping columns: k:1!null 471 │ ├── key: (1) 472 │ ├── fd: (1)-->(7,8) 473 │ ├── left-join (cross) 474 │ │ ├── columns: k:1!null x:5 y:6 475 │ │ ├── key: (1,5) 476 │ │ ├── fd: (5)-->(6) 477 │ │ ├── scan a 478 │ │ │ ├── columns: k:1!null 479 │ │ │ └── key: (1) 480 │ │ ├── scan xy 481 │ │ │ ├── columns: x:5!null y:6 482 │ │ │ ├── key: (5) 483 │ │ │ └── fd: (5)-->(6) 484 │ │ └── filters (true) 485 │ └── aggregations 486 │ ├── min [as=min:7, outer=(5)] 487 │ │ └── x:5 488 │ └── max [as=max:8, outer=(6)] 489 │ └── y:6 490 └── filters 491 └── min:7 = 1 [outer=(7), constraints=(/7: [/1 - /1]; tight), fd=()-->(7)] 492 493 # Don't reject column when count function is used (it doesn't return nil when 494 # input is empty). 495 norm expect-not=RejectNullsGroupBy 496 SELECT count(x) 497 FROM (SELECT k FROM a) 498 LEFT JOIN (SELECT x FROM xy) 499 ON True 500 GROUP BY k 501 HAVING count(x)=1 502 ---- 503 project 504 ├── columns: count:7!null 505 ├── fd: ()-->(7) 506 └── select 507 ├── columns: k:1!null count:7!null 508 ├── key: (1) 509 ├── fd: ()-->(7) 510 ├── group-by 511 │ ├── columns: k:1!null count:7!null 512 │ ├── grouping columns: k:1!null 513 │ ├── key: (1) 514 │ ├── fd: (1)-->(7) 515 │ ├── left-join (cross) 516 │ │ ├── columns: k:1!null x:5 517 │ │ ├── key: (1,5) 518 │ │ ├── scan a 519 │ │ │ ├── columns: k:1!null 520 │ │ │ └── key: (1) 521 │ │ ├── scan xy 522 │ │ │ ├── columns: x:5!null 523 │ │ │ └── key: (5) 524 │ │ └── filters (true) 525 │ └── aggregations 526 │ └── count [as=count:7, outer=(5)] 527 │ └── x:5 528 └── filters 529 └── count:7 = 1 [outer=(7), constraints=(/7: [/1 - /1]; tight), fd=()-->(7)] 530 531 # ConstNotNullAgg rejects nulls (regression test for #28810). 532 # TODO(andyk): Removal of filter pushdown into apply join inputs means that this 533 # rule no longer triggers RejectNullsGroupBy. Find another way to decorrelate 534 # this query. 535 # opt expect=RejectNullsGroupBy 536 norm 537 SELECT 1 FROM a AS ref_0 LEFT JOIN a AS ref_1 ON EXISTS(SELECT 1 FROM a WHERE a.s = ref_0.s) 538 ---- 539 project 540 ├── columns: "?column?":17!null 541 ├── fd: ()-->(17) 542 ├── left-join-apply 543 │ ├── columns: ref_0.s:4 exists:16 544 │ ├── scan ref_0 545 │ │ └── columns: ref_0.s:4 546 │ ├── project 547 │ │ ├── columns: exists:16!null 548 │ │ ├── outer: (4) 549 │ │ ├── group-by 550 │ │ │ ├── columns: ref_1.k:5!null true_agg:15 551 │ │ │ ├── grouping columns: ref_1.k:5!null 552 │ │ │ ├── outer: (4) 553 │ │ │ ├── key: (5) 554 │ │ │ ├── fd: (5)-->(15) 555 │ │ │ ├── left-join (cross) 556 │ │ │ │ ├── columns: ref_1.k:5!null true:14 557 │ │ │ │ ├── outer: (4) 558 │ │ │ │ ├── scan ref_1 559 │ │ │ │ │ ├── columns: ref_1.k:5!null 560 │ │ │ │ │ └── key: (5) 561 │ │ │ │ ├── project 562 │ │ │ │ │ ├── columns: true:14!null 563 │ │ │ │ │ ├── outer: (4) 564 │ │ │ │ │ ├── fd: ()-->(14) 565 │ │ │ │ │ ├── select 566 │ │ │ │ │ │ ├── columns: a.s:12!null 567 │ │ │ │ │ │ ├── outer: (4) 568 │ │ │ │ │ │ ├── fd: ()-->(12) 569 │ │ │ │ │ │ ├── scan a 570 │ │ │ │ │ │ │ └── columns: a.s:12 571 │ │ │ │ │ │ └── filters 572 │ │ │ │ │ │ └── a.s:12 = ref_0.s:4 [outer=(4,12), constraints=(/4: (/NULL - ]; /12: (/NULL - ]), fd=(4)==(12), (12)==(4)] 573 │ │ │ │ │ └── projections 574 │ │ │ │ │ └── true [as=true:14] 575 │ │ │ │ └── filters (true) 576 │ │ │ └── aggregations 577 │ │ │ └── const-not-null-agg [as=true_agg:15, outer=(14)] 578 │ │ │ └── true:14 579 │ │ └── projections 580 │ │ └── true_agg:15 IS NOT NULL [as=exists:16, outer=(15)] 581 │ └── filters 582 │ └── exists:16 [outer=(16), constraints=(/16: [/true - /true]; tight), fd=()-->(16)] 583 └── projections 584 └── 1 [as="?column?":17] 585 586 # Use with multi-argument aggregate function. 587 norm expect=RejectNullsGroupBy 588 SELECT string_agg(s, ',') 589 FROM (SELECT x FROM xy) 590 LEFT JOIN (SELECT k, s FROM a) 591 ON True 592 GROUP BY k 593 HAVING string_agg(s, ',')='foo' 594 ---- 595 project 596 ├── columns: string_agg:8!null 597 ├── fd: ()-->(8) 598 └── select 599 ├── columns: k:3!null string_agg:8!null 600 ├── key: (3) 601 ├── fd: ()-->(8) 602 ├── group-by 603 │ ├── columns: k:3!null string_agg:8!null 604 │ ├── grouping columns: k:3!null 605 │ ├── key: (3) 606 │ ├── fd: (3)-->(8) 607 │ ├── project 608 │ │ ├── columns: column7:7!null k:3!null s:6!null 609 │ │ ├── fd: ()-->(7), (3)-->(6) 610 │ │ ├── inner-join (cross) 611 │ │ │ ├── columns: k:3!null s:6!null 612 │ │ │ ├── fd: (3)-->(6) 613 │ │ │ ├── scan xy 614 │ │ │ ├── select 615 │ │ │ │ ├── columns: k:3!null s:6!null 616 │ │ │ │ ├── key: (3) 617 │ │ │ │ ├── fd: (3)-->(6) 618 │ │ │ │ ├── scan a 619 │ │ │ │ │ ├── columns: k:3!null s:6 620 │ │ │ │ │ ├── key: (3) 621 │ │ │ │ │ └── fd: (3)-->(6) 622 │ │ │ │ └── filters 623 │ │ │ │ └── s:6 IS NOT NULL [outer=(6), constraints=(/6: (/NULL - ]; tight)] 624 │ │ │ └── filters (true) 625 │ │ └── projections 626 │ │ └── ',' [as=column7:7] 627 │ └── aggregations 628 │ └── string-agg [as=string_agg:8, outer=(6,7)] 629 │ ├── s:6 630 │ └── column7:7 631 └── filters 632 └── string_agg:8 = 'foo' [outer=(8), constraints=(/8: [/'foo' - /'foo']; tight), fd=()-->(8)] 633 634 # Don't reject nulls when aggregate argument is a not a Project passthrough 635 # column. 636 norm expect-not=RejectNullsGroupBy 637 SELECT string_agg(s || 'bar', ',') 638 FROM (SELECT x FROM xy) 639 LEFT JOIN (SELECT k, s FROM a) 640 ON True 641 GROUP BY k 642 HAVING string_agg(s || 'bar', ',')='foo' 643 ---- 644 project 645 ├── columns: string_agg:9!null 646 ├── fd: ()-->(9) 647 └── select 648 ├── columns: k:3 string_agg:9!null 649 ├── key: (3) 650 ├── fd: ()-->(9) 651 ├── group-by 652 │ ├── columns: k:3 string_agg:9 653 │ ├── grouping columns: k:3 654 │ ├── key: (3) 655 │ ├── fd: (3)-->(9) 656 │ ├── project 657 │ │ ├── columns: column7:7 column8:8!null k:3 658 │ │ ├── fd: ()-->(8), (3)-->(7) 659 │ │ ├── left-join (cross) 660 │ │ │ ├── columns: k:3 s:6 661 │ │ │ ├── fd: (3)-->(6) 662 │ │ │ ├── scan xy 663 │ │ │ ├── scan a 664 │ │ │ │ ├── columns: k:3!null s:6 665 │ │ │ │ ├── key: (3) 666 │ │ │ │ └── fd: (3)-->(6) 667 │ │ │ └── filters (true) 668 │ │ └── projections 669 │ │ ├── s:6 || 'bar' [as=column7:7, outer=(6)] 670 │ │ └── ',' [as=column8:8] 671 │ └── aggregations 672 │ └── string-agg [as=string_agg:9, outer=(7,8)] 673 │ ├── column7:7 674 │ └── column8:8 675 └── filters 676 └── string_agg:9 = 'foo' [outer=(9), constraints=(/9: [/'foo' - /'foo']; tight), fd=()-->(9)] 677 678 # Regression test: the not-null filter can't make it all the way down to the 679 # join that requested it, so ensure that we don't endlessly try to introduce 680 # them. 681 exprnorm 682 (Select 683 (ScalarGroupBy 684 (InnerJoinApply 685 (Scan [ (Table "xy") (Cols "x,y") ]) 686 (LeftJoinApply 687 (Scan [ (Table "uv") (Cols "u,v") ]) 688 (Select 689 (Values 690 [ (Tuple [ (Plus (Var "x") (Var "u")) ] "tuple{int}" ) ] 691 [ (Cols [ (NewColumn "z" "int") ]) ] 692 ) 693 [ (Eq (Var "x") (Const 3 "int")) ] 694 ) 695 [ ] 696 [ ] 697 ) 698 [ ] 699 [ ] 700 ) 701 [ (AggregationsItem (Sum (Var "z")) (NewColumn "sum" "int")) ] 702 [ ] 703 ) 704 [ (Eq (Var "sum") (Const 10 "int")) ] 705 ) 706 ---- 707 select 708 ├── columns: sum:6!null 709 ├── cardinality: [0 - 1] 710 ├── key: () 711 ├── fd: ()-->(6) 712 ├── scalar-group-by 713 │ ├── columns: sum:6 714 │ ├── cardinality: [1 - 1] 715 │ ├── key: () 716 │ ├── fd: ()-->(6) 717 │ ├── inner-join-apply 718 │ │ ├── columns: x:1!null u:3!null z:5 719 │ │ ├── key: (1,3) 720 │ │ ├── fd: (1,3)-->(5) 721 │ │ ├── scan xy 722 │ │ │ ├── columns: x:1!null 723 │ │ │ └── key: (1) 724 │ │ ├── left-join-apply 725 │ │ │ ├── columns: u:3!null z:5 726 │ │ │ ├── outer: (1) 727 │ │ │ ├── key: (3) 728 │ │ │ ├── fd: (3)-->(5) 729 │ │ │ ├── scan uv 730 │ │ │ │ ├── columns: u:3!null 731 │ │ │ │ └── key: (3) 732 │ │ │ ├── values 733 │ │ │ │ ├── columns: z:5 734 │ │ │ │ ├── outer: (1,3) 735 │ │ │ │ ├── cardinality: [1 - 1] 736 │ │ │ │ ├── key: () 737 │ │ │ │ ├── fd: ()-->(5) 738 │ │ │ │ └── (x:1 + u:3,) 739 │ │ │ └── filters 740 │ │ │ └── x:1 = 3 [outer=(1), constraints=(/1: [/3 - /3]; tight), fd=()-->(1)] 741 │ │ └── filters (true) 742 │ └── aggregations 743 │ └── sum [as=sum:6, outer=(5)] 744 │ └── z:5 745 └── filters 746 └── sum:6 = 10 [outer=(6), constraints=(/6: [/10 - /10]; tight), fd=()-->(6)]