1-- 2-- JOIN 3-- Test JOIN clauses 4-- 5CREATE TABLE J1_TBL ( 6 i integer, 7 j integer, 8 t text 9); 10CREATE TABLE J2_TBL ( 11 i integer, 12 k integer 13); 14INSERT INTO J1_TBL VALUES (1, 4, 'one'); 15INSERT INTO J1_TBL VALUES (2, 3, 'two'); 16INSERT INTO J1_TBL VALUES (3, 2, 'three'); 17INSERT INTO J1_TBL VALUES (4, 1, 'four'); 18INSERT INTO J1_TBL VALUES (5, 0, 'five'); 19INSERT INTO J1_TBL VALUES (6, 6, 'six'); 20INSERT INTO J1_TBL VALUES (7, 7, 'seven'); 21INSERT INTO J1_TBL VALUES (8, 8, 'eight'); 22INSERT INTO J1_TBL VALUES (0, NULL, 'zero'); 23INSERT INTO J1_TBL VALUES (NULL, NULL, 'null'); 24INSERT INTO J1_TBL VALUES (NULL, 0, 'zero'); 25INSERT INTO J2_TBL VALUES (1, -1); 26INSERT INTO J2_TBL VALUES (2, 2); 27INSERT INTO J2_TBL VALUES (3, -3); 28INSERT INTO J2_TBL VALUES (2, 4); 29INSERT INTO J2_TBL VALUES (5, -5); 30INSERT INTO J2_TBL VALUES (5, -5); 31INSERT INTO J2_TBL VALUES (0, NULL); 32INSERT INTO J2_TBL VALUES (NULL, NULL); 33INSERT INTO J2_TBL VALUES (NULL, 0); 34-- useful in some tests below 35create temp table onerow(); 36insert into onerow default values; 37analyze onerow; 38-- 39-- CORRELATION NAMES 40-- Make sure that table/column aliases are supported 41-- before diving into more complex join syntax. 42-- 43SELECT '' AS "xxx", * 44 FROM J1_TBL AS tx; 45 xxx | i | j | t 46-----+---+---+------- 47 | 1 | 4 | one 48 | 2 | 3 | two 49 | 3 | 2 | three 50 | 4 | 1 | four 51 | 5 | 0 | five 52 | 6 | 6 | six 53 | 7 | 7 | seven 54 | 8 | 8 | eight 55 | 0 | | zero 56 | | | null 57 | | 0 | zero 58(11 rows) 59 60SELECT '' AS "xxx", * 61 FROM J1_TBL tx; 62 xxx | i | j | t 63-----+---+---+------- 64 | 1 | 4 | one 65 | 2 | 3 | two 66 | 3 | 2 | three 67 | 4 | 1 | four 68 | 5 | 0 | five 69 | 6 | 6 | six 70 | 7 | 7 | seven 71 | 8 | 8 | eight 72 | 0 | | zero 73 | | | null 74 | | 0 | zero 75(11 rows) 76 77SELECT '' AS "xxx", * 78 FROM J1_TBL AS t1 (a, b, c); 79 xxx | a | b | c 80-----+---+---+------- 81 | 1 | 4 | one 82 | 2 | 3 | two 83 | 3 | 2 | three 84 | 4 | 1 | four 85 | 5 | 0 | five 86 | 6 | 6 | six 87 | 7 | 7 | seven 88 | 8 | 8 | eight 89 | 0 | | zero 90 | | | null 91 | | 0 | zero 92(11 rows) 93 94SELECT '' AS "xxx", * 95 FROM J1_TBL t1 (a, b, c); 96 xxx | a | b | c 97-----+---+---+------- 98 | 1 | 4 | one 99 | 2 | 3 | two 100 | 3 | 2 | three 101 | 4 | 1 | four 102 | 5 | 0 | five 103 | 6 | 6 | six 104 | 7 | 7 | seven 105 | 8 | 8 | eight 106 | 0 | | zero 107 | | | null 108 | | 0 | zero 109(11 rows) 110 111SELECT '' AS "xxx", * 112 FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e); 113 xxx | a | b | c | d | e 114-----+---+---+-------+---+---- 115 | 1 | 4 | one | 1 | -1 116 | 2 | 3 | two | 1 | -1 117 | 3 | 2 | three | 1 | -1 118 | 4 | 1 | four | 1 | -1 119 | 5 | 0 | five | 1 | -1 120 | 6 | 6 | six | 1 | -1 121 | 7 | 7 | seven | 1 | -1 122 | 8 | 8 | eight | 1 | -1 123 | 0 | | zero | 1 | -1 124 | | | null | 1 | -1 125 | | 0 | zero | 1 | -1 126 | 1 | 4 | one | 2 | 2 127 | 2 | 3 | two | 2 | 2 128 | 3 | 2 | three | 2 | 2 129 | 4 | 1 | four | 2 | 2 130 | 5 | 0 | five | 2 | 2 131 | 6 | 6 | six | 2 | 2 132 | 7 | 7 | seven | 2 | 2 133 | 8 | 8 | eight | 2 | 2 134 | 0 | | zero | 2 | 2 135 | | | null | 2 | 2 136 | | 0 | zero | 2 | 2 137 | 1 | 4 | one | 3 | -3 138 | 2 | 3 | two | 3 | -3 139 | 3 | 2 | three | 3 | -3 140 | 4 | 1 | four | 3 | -3 141 | 5 | 0 | five | 3 | -3 142 | 6 | 6 | six | 3 | -3 143 | 7 | 7 | seven | 3 | -3 144 | 8 | 8 | eight | 3 | -3 145 | 0 | | zero | 3 | -3 146 | | | null | 3 | -3 147 | | 0 | zero | 3 | -3 148 | 1 | 4 | one | 2 | 4 149 | 2 | 3 | two | 2 | 4 150 | 3 | 2 | three | 2 | 4 151 | 4 | 1 | four | 2 | 4 152 | 5 | 0 | five | 2 | 4 153 | 6 | 6 | six | 2 | 4 154 | 7 | 7 | seven | 2 | 4 155 | 8 | 8 | eight | 2 | 4 156 | 0 | | zero | 2 | 4 157 | | | null | 2 | 4 158 | | 0 | zero | 2 | 4 159 | 1 | 4 | one | 5 | -5 160 | 2 | 3 | two | 5 | -5 161 | 3 | 2 | three | 5 | -5 162 | 4 | 1 | four | 5 | -5 163 | 5 | 0 | five | 5 | -5 164 | 6 | 6 | six | 5 | -5 165 | 7 | 7 | seven | 5 | -5 166 | 8 | 8 | eight | 5 | -5 167 | 0 | | zero | 5 | -5 168 | | | null | 5 | -5 169 | | 0 | zero | 5 | -5 170 | 1 | 4 | one | 5 | -5 171 | 2 | 3 | two | 5 | -5 172 | 3 | 2 | three | 5 | -5 173 | 4 | 1 | four | 5 | -5 174 | 5 | 0 | five | 5 | -5 175 | 6 | 6 | six | 5 | -5 176 | 7 | 7 | seven | 5 | -5 177 | 8 | 8 | eight | 5 | -5 178 | 0 | | zero | 5 | -5 179 | | | null | 5 | -5 180 | | 0 | zero | 5 | -5 181 | 1 | 4 | one | 0 | 182 | 2 | 3 | two | 0 | 183 | 3 | 2 | three | 0 | 184 | 4 | 1 | four | 0 | 185 | 5 | 0 | five | 0 | 186 | 6 | 6 | six | 0 | 187 | 7 | 7 | seven | 0 | 188 | 8 | 8 | eight | 0 | 189 | 0 | | zero | 0 | 190 | | | null | 0 | 191 | | 0 | zero | 0 | 192 | 1 | 4 | one | | 193 | 2 | 3 | two | | 194 | 3 | 2 | three | | 195 | 4 | 1 | four | | 196 | 5 | 0 | five | | 197 | 6 | 6 | six | | 198 | 7 | 7 | seven | | 199 | 8 | 8 | eight | | 200 | 0 | | zero | | 201 | | | null | | 202 | | 0 | zero | | 203 | 1 | 4 | one | | 0 204 | 2 | 3 | two | | 0 205 | 3 | 2 | three | | 0 206 | 4 | 1 | four | | 0 207 | 5 | 0 | five | | 0 208 | 6 | 6 | six | | 0 209 | 7 | 7 | seven | | 0 210 | 8 | 8 | eight | | 0 211 | 0 | | zero | | 0 212 | | | null | | 0 213 | | 0 | zero | | 0 214(99 rows) 215 216SELECT '' AS "xxx", t1.a, t2.e 217 FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e) 218 WHERE t1.a = t2.d; 219 xxx | a | e 220-----+---+---- 221 | 0 | 222 | 1 | -1 223 | 2 | 2 224 | 2 | 4 225 | 3 | -3 226 | 5 | -5 227 | 5 | -5 228(7 rows) 229 230-- 231-- CROSS JOIN 232-- Qualifications are not allowed on cross joins, 233-- which degenerate into a standard unqualified inner join. 234-- 235SELECT '' AS "xxx", * 236 FROM J1_TBL CROSS JOIN J2_TBL; 237 xxx | i | j | t | i | k 238-----+---+---+-------+---+---- 239 | 1 | 4 | one | 1 | -1 240 | 2 | 3 | two | 1 | -1 241 | 3 | 2 | three | 1 | -1 242 | 4 | 1 | four | 1 | -1 243 | 5 | 0 | five | 1 | -1 244 | 6 | 6 | six | 1 | -1 245 | 7 | 7 | seven | 1 | -1 246 | 8 | 8 | eight | 1 | -1 247 | 0 | | zero | 1 | -1 248 | | | null | 1 | -1 249 | | 0 | zero | 1 | -1 250 | 1 | 4 | one | 2 | 2 251 | 2 | 3 | two | 2 | 2 252 | 3 | 2 | three | 2 | 2 253 | 4 | 1 | four | 2 | 2 254 | 5 | 0 | five | 2 | 2 255 | 6 | 6 | six | 2 | 2 256 | 7 | 7 | seven | 2 | 2 257 | 8 | 8 | eight | 2 | 2 258 | 0 | | zero | 2 | 2 259 | | | null | 2 | 2 260 | | 0 | zero | 2 | 2 261 | 1 | 4 | one | 3 | -3 262 | 2 | 3 | two | 3 | -3 263 | 3 | 2 | three | 3 | -3 264 | 4 | 1 | four | 3 | -3 265 | 5 | 0 | five | 3 | -3 266 | 6 | 6 | six | 3 | -3 267 | 7 | 7 | seven | 3 | -3 268 | 8 | 8 | eight | 3 | -3 269 | 0 | | zero | 3 | -3 270 | | | null | 3 | -3 271 | | 0 | zero | 3 | -3 272 | 1 | 4 | one | 2 | 4 273 | 2 | 3 | two | 2 | 4 274 | 3 | 2 | three | 2 | 4 275 | 4 | 1 | four | 2 | 4 276 | 5 | 0 | five | 2 | 4 277 | 6 | 6 | six | 2 | 4 278 | 7 | 7 | seven | 2 | 4 279 | 8 | 8 | eight | 2 | 4 280 | 0 | | zero | 2 | 4 281 | | | null | 2 | 4 282 | | 0 | zero | 2 | 4 283 | 1 | 4 | one | 5 | -5 284 | 2 | 3 | two | 5 | -5 285 | 3 | 2 | three | 5 | -5 286 | 4 | 1 | four | 5 | -5 287 | 5 | 0 | five | 5 | -5 288 | 6 | 6 | six | 5 | -5 289 | 7 | 7 | seven | 5 | -5 290 | 8 | 8 | eight | 5 | -5 291 | 0 | | zero | 5 | -5 292 | | | null | 5 | -5 293 | | 0 | zero | 5 | -5 294 | 1 | 4 | one | 5 | -5 295 | 2 | 3 | two | 5 | -5 296 | 3 | 2 | three | 5 | -5 297 | 4 | 1 | four | 5 | -5 298 | 5 | 0 | five | 5 | -5 299 | 6 | 6 | six | 5 | -5 300 | 7 | 7 | seven | 5 | -5 301 | 8 | 8 | eight | 5 | -5 302 | 0 | | zero | 5 | -5 303 | | | null | 5 | -5 304 | | 0 | zero | 5 | -5 305 | 1 | 4 | one | 0 | 306 | 2 | 3 | two | 0 | 307 | 3 | 2 | three | 0 | 308 | 4 | 1 | four | 0 | 309 | 5 | 0 | five | 0 | 310 | 6 | 6 | six | 0 | 311 | 7 | 7 | seven | 0 | 312 | 8 | 8 | eight | 0 | 313 | 0 | | zero | 0 | 314 | | | null | 0 | 315 | | 0 | zero | 0 | 316 | 1 | 4 | one | | 317 | 2 | 3 | two | | 318 | 3 | 2 | three | | 319 | 4 | 1 | four | | 320 | 5 | 0 | five | | 321 | 6 | 6 | six | | 322 | 7 | 7 | seven | | 323 | 8 | 8 | eight | | 324 | 0 | | zero | | 325 | | | null | | 326 | | 0 | zero | | 327 | 1 | 4 | one | | 0 328 | 2 | 3 | two | | 0 329 | 3 | 2 | three | | 0 330 | 4 | 1 | four | | 0 331 | 5 | 0 | five | | 0 332 | 6 | 6 | six | | 0 333 | 7 | 7 | seven | | 0 334 | 8 | 8 | eight | | 0 335 | 0 | | zero | | 0 336 | | | null | | 0 337 | | 0 | zero | | 0 338(99 rows) 339 340-- ambiguous column 341SELECT '' AS "xxx", i, k, t 342 FROM J1_TBL CROSS JOIN J2_TBL; 343ERROR: column reference "i" is ambiguous 344LINE 1: SELECT '' AS "xxx", i, k, t 345 ^ 346-- resolve previous ambiguity by specifying the table name 347SELECT '' AS "xxx", t1.i, k, t 348 FROM J1_TBL t1 CROSS JOIN J2_TBL t2; 349 xxx | i | k | t 350-----+---+----+------- 351 | 1 | -1 | one 352 | 2 | -1 | two 353 | 3 | -1 | three 354 | 4 | -1 | four 355 | 5 | -1 | five 356 | 6 | -1 | six 357 | 7 | -1 | seven 358 | 8 | -1 | eight 359 | 0 | -1 | zero 360 | | -1 | null 361 | | -1 | zero 362 | 1 | 2 | one 363 | 2 | 2 | two 364 | 3 | 2 | three 365 | 4 | 2 | four 366 | 5 | 2 | five 367 | 6 | 2 | six 368 | 7 | 2 | seven 369 | 8 | 2 | eight 370 | 0 | 2 | zero 371 | | 2 | null 372 | | 2 | zero 373 | 1 | -3 | one 374 | 2 | -3 | two 375 | 3 | -3 | three 376 | 4 | -3 | four 377 | 5 | -3 | five 378 | 6 | -3 | six 379 | 7 | -3 | seven 380 | 8 | -3 | eight 381 | 0 | -3 | zero 382 | | -3 | null 383 | | -3 | zero 384 | 1 | 4 | one 385 | 2 | 4 | two 386 | 3 | 4 | three 387 | 4 | 4 | four 388 | 5 | 4 | five 389 | 6 | 4 | six 390 | 7 | 4 | seven 391 | 8 | 4 | eight 392 | 0 | 4 | zero 393 | | 4 | null 394 | | 4 | zero 395 | 1 | -5 | one 396 | 2 | -5 | two 397 | 3 | -5 | three 398 | 4 | -5 | four 399 | 5 | -5 | five 400 | 6 | -5 | six 401 | 7 | -5 | seven 402 | 8 | -5 | eight 403 | 0 | -5 | zero 404 | | -5 | null 405 | | -5 | zero 406 | 1 | -5 | one 407 | 2 | -5 | two 408 | 3 | -5 | three 409 | 4 | -5 | four 410 | 5 | -5 | five 411 | 6 | -5 | six 412 | 7 | -5 | seven 413 | 8 | -5 | eight 414 | 0 | -5 | zero 415 | | -5 | null 416 | | -5 | zero 417 | 1 | | one 418 | 2 | | two 419 | 3 | | three 420 | 4 | | four 421 | 5 | | five 422 | 6 | | six 423 | 7 | | seven 424 | 8 | | eight 425 | 0 | | zero 426 | | | null 427 | | | zero 428 | 1 | | one 429 | 2 | | two 430 | 3 | | three 431 | 4 | | four 432 | 5 | | five 433 | 6 | | six 434 | 7 | | seven 435 | 8 | | eight 436 | 0 | | zero 437 | | | null 438 | | | zero 439 | 1 | 0 | one 440 | 2 | 0 | two 441 | 3 | 0 | three 442 | 4 | 0 | four 443 | 5 | 0 | five 444 | 6 | 0 | six 445 | 7 | 0 | seven 446 | 8 | 0 | eight 447 | 0 | 0 | zero 448 | | 0 | null 449 | | 0 | zero 450(99 rows) 451 452SELECT '' AS "xxx", ii, tt, kk 453 FROM (J1_TBL CROSS JOIN J2_TBL) 454 AS tx (ii, jj, tt, ii2, kk); 455 xxx | ii | tt | kk 456-----+----+-------+---- 457 | 1 | one | -1 458 | 2 | two | -1 459 | 3 | three | -1 460 | 4 | four | -1 461 | 5 | five | -1 462 | 6 | six | -1 463 | 7 | seven | -1 464 | 8 | eight | -1 465 | 0 | zero | -1 466 | | null | -1 467 | | zero | -1 468 | 1 | one | 2 469 | 2 | two | 2 470 | 3 | three | 2 471 | 4 | four | 2 472 | 5 | five | 2 473 | 6 | six | 2 474 | 7 | seven | 2 475 | 8 | eight | 2 476 | 0 | zero | 2 477 | | null | 2 478 | | zero | 2 479 | 1 | one | -3 480 | 2 | two | -3 481 | 3 | three | -3 482 | 4 | four | -3 483 | 5 | five | -3 484 | 6 | six | -3 485 | 7 | seven | -3 486 | 8 | eight | -3 487 | 0 | zero | -3 488 | | null | -3 489 | | zero | -3 490 | 1 | one | 4 491 | 2 | two | 4 492 | 3 | three | 4 493 | 4 | four | 4 494 | 5 | five | 4 495 | 6 | six | 4 496 | 7 | seven | 4 497 | 8 | eight | 4 498 | 0 | zero | 4 499 | | null | 4 500 | | zero | 4 501 | 1 | one | -5 502 | 2 | two | -5 503 | 3 | three | -5 504 | 4 | four | -5 505 | 5 | five | -5 506 | 6 | six | -5 507 | 7 | seven | -5 508 | 8 | eight | -5 509 | 0 | zero | -5 510 | | null | -5 511 | | zero | -5 512 | 1 | one | -5 513 | 2 | two | -5 514 | 3 | three | -5 515 | 4 | four | -5 516 | 5 | five | -5 517 | 6 | six | -5 518 | 7 | seven | -5 519 | 8 | eight | -5 520 | 0 | zero | -5 521 | | null | -5 522 | | zero | -5 523 | 1 | one | 524 | 2 | two | 525 | 3 | three | 526 | 4 | four | 527 | 5 | five | 528 | 6 | six | 529 | 7 | seven | 530 | 8 | eight | 531 | 0 | zero | 532 | | null | 533 | | zero | 534 | 1 | one | 535 | 2 | two | 536 | 3 | three | 537 | 4 | four | 538 | 5 | five | 539 | 6 | six | 540 | 7 | seven | 541 | 8 | eight | 542 | 0 | zero | 543 | | null | 544 | | zero | 545 | 1 | one | 0 546 | 2 | two | 0 547 | 3 | three | 0 548 | 4 | four | 0 549 | 5 | five | 0 550 | 6 | six | 0 551 | 7 | seven | 0 552 | 8 | eight | 0 553 | 0 | zero | 0 554 | | null | 0 555 | | zero | 0 556(99 rows) 557 558SELECT '' AS "xxx", tx.ii, tx.jj, tx.kk 559 FROM (J1_TBL t1 (a, b, c) CROSS JOIN J2_TBL t2 (d, e)) 560 AS tx (ii, jj, tt, ii2, kk); 561 xxx | ii | jj | kk 562-----+----+----+---- 563 | 1 | 4 | -1 564 | 2 | 3 | -1 565 | 3 | 2 | -1 566 | 4 | 1 | -1 567 | 5 | 0 | -1 568 | 6 | 6 | -1 569 | 7 | 7 | -1 570 | 8 | 8 | -1 571 | 0 | | -1 572 | | | -1 573 | | 0 | -1 574 | 1 | 4 | 2 575 | 2 | 3 | 2 576 | 3 | 2 | 2 577 | 4 | 1 | 2 578 | 5 | 0 | 2 579 | 6 | 6 | 2 580 | 7 | 7 | 2 581 | 8 | 8 | 2 582 | 0 | | 2 583 | | | 2 584 | | 0 | 2 585 | 1 | 4 | -3 586 | 2 | 3 | -3 587 | 3 | 2 | -3 588 | 4 | 1 | -3 589 | 5 | 0 | -3 590 | 6 | 6 | -3 591 | 7 | 7 | -3 592 | 8 | 8 | -3 593 | 0 | | -3 594 | | | -3 595 | | 0 | -3 596 | 1 | 4 | 4 597 | 2 | 3 | 4 598 | 3 | 2 | 4 599 | 4 | 1 | 4 600 | 5 | 0 | 4 601 | 6 | 6 | 4 602 | 7 | 7 | 4 603 | 8 | 8 | 4 604 | 0 | | 4 605 | | | 4 606 | | 0 | 4 607 | 1 | 4 | -5 608 | 2 | 3 | -5 609 | 3 | 2 | -5 610 | 4 | 1 | -5 611 | 5 | 0 | -5 612 | 6 | 6 | -5 613 | 7 | 7 | -5 614 | 8 | 8 | -5 615 | 0 | | -5 616 | | | -5 617 | | 0 | -5 618 | 1 | 4 | -5 619 | 2 | 3 | -5 620 | 3 | 2 | -5 621 | 4 | 1 | -5 622 | 5 | 0 | -5 623 | 6 | 6 | -5 624 | 7 | 7 | -5 625 | 8 | 8 | -5 626 | 0 | | -5 627 | | | -5 628 | | 0 | -5 629 | 1 | 4 | 630 | 2 | 3 | 631 | 3 | 2 | 632 | 4 | 1 | 633 | 5 | 0 | 634 | 6 | 6 | 635 | 7 | 7 | 636 | 8 | 8 | 637 | 0 | | 638 | | | 639 | | 0 | 640 | 1 | 4 | 641 | 2 | 3 | 642 | 3 | 2 | 643 | 4 | 1 | 644 | 5 | 0 | 645 | 6 | 6 | 646 | 7 | 7 | 647 | 8 | 8 | 648 | 0 | | 649 | | | 650 | | 0 | 651 | 1 | 4 | 0 652 | 2 | 3 | 0 653 | 3 | 2 | 0 654 | 4 | 1 | 0 655 | 5 | 0 | 0 656 | 6 | 6 | 0 657 | 7 | 7 | 0 658 | 8 | 8 | 0 659 | 0 | | 0 660 | | | 0 661 | | 0 | 0 662(99 rows) 663 664SELECT '' AS "xxx", * 665 FROM J1_TBL CROSS JOIN J2_TBL a CROSS JOIN J2_TBL b; 666 xxx | i | j | t | i | k | i | k 667-----+---+---+-------+---+----+---+---- 668 | 1 | 4 | one | 1 | -1 | 1 | -1 669 | 1 | 4 | one | 1 | -1 | 2 | 2 670 | 1 | 4 | one | 1 | -1 | 3 | -3 671 | 1 | 4 | one | 1 | -1 | 2 | 4 672 | 1 | 4 | one | 1 | -1 | 5 | -5 673 | 1 | 4 | one | 1 | -1 | 5 | -5 674 | 1 | 4 | one | 1 | -1 | 0 | 675 | 1 | 4 | one | 1 | -1 | | 676 | 1 | 4 | one | 1 | -1 | | 0 677 | 2 | 3 | two | 1 | -1 | 1 | -1 678 | 2 | 3 | two | 1 | -1 | 2 | 2 679 | 2 | 3 | two | 1 | -1 | 3 | -3 680 | 2 | 3 | two | 1 | -1 | 2 | 4 681 | 2 | 3 | two | 1 | -1 | 5 | -5 682 | 2 | 3 | two | 1 | -1 | 5 | -5 683 | 2 | 3 | two | 1 | -1 | 0 | 684 | 2 | 3 | two | 1 | -1 | | 685 | 2 | 3 | two | 1 | -1 | | 0 686 | 3 | 2 | three | 1 | -1 | 1 | -1 687 | 3 | 2 | three | 1 | -1 | 2 | 2 688 | 3 | 2 | three | 1 | -1 | 3 | -3 689 | 3 | 2 | three | 1 | -1 | 2 | 4 690 | 3 | 2 | three | 1 | -1 | 5 | -5 691 | 3 | 2 | three | 1 | -1 | 5 | -5 692 | 3 | 2 | three | 1 | -1 | 0 | 693 | 3 | 2 | three | 1 | -1 | | 694 | 3 | 2 | three | 1 | -1 | | 0 695 | 4 | 1 | four | 1 | -1 | 1 | -1 696 | 4 | 1 | four | 1 | -1 | 2 | 2 697 | 4 | 1 | four | 1 | -1 | 3 | -3 698 | 4 | 1 | four | 1 | -1 | 2 | 4 699 | 4 | 1 | four | 1 | -1 | 5 | -5 700 | 4 | 1 | four | 1 | -1 | 5 | -5 701 | 4 | 1 | four | 1 | -1 | 0 | 702 | 4 | 1 | four | 1 | -1 | | 703 | 4 | 1 | four | 1 | -1 | | 0 704 | 5 | 0 | five | 1 | -1 | 1 | -1 705 | 5 | 0 | five | 1 | -1 | 2 | 2 706 | 5 | 0 | five | 1 | -1 | 3 | -3 707 | 5 | 0 | five | 1 | -1 | 2 | 4 708 | 5 | 0 | five | 1 | -1 | 5 | -5 709 | 5 | 0 | five | 1 | -1 | 5 | -5 710 | 5 | 0 | five | 1 | -1 | 0 | 711 | 5 | 0 | five | 1 | -1 | | 712 | 5 | 0 | five | 1 | -1 | | 0 713 | 6 | 6 | six | 1 | -1 | 1 | -1 714 | 6 | 6 | six | 1 | -1 | 2 | 2 715 | 6 | 6 | six | 1 | -1 | 3 | -3 716 | 6 | 6 | six | 1 | -1 | 2 | 4 717 | 6 | 6 | six | 1 | -1 | 5 | -5 718 | 6 | 6 | six | 1 | -1 | 5 | -5 719 | 6 | 6 | six | 1 | -1 | 0 | 720 | 6 | 6 | six | 1 | -1 | | 721 | 6 | 6 | six | 1 | -1 | | 0 722 | 7 | 7 | seven | 1 | -1 | 1 | -1 723 | 7 | 7 | seven | 1 | -1 | 2 | 2 724 | 7 | 7 | seven | 1 | -1 | 3 | -3 725 | 7 | 7 | seven | 1 | -1 | 2 | 4 726 | 7 | 7 | seven | 1 | -1 | 5 | -5 727 | 7 | 7 | seven | 1 | -1 | 5 | -5 728 | 7 | 7 | seven | 1 | -1 | 0 | 729 | 7 | 7 | seven | 1 | -1 | | 730 | 7 | 7 | seven | 1 | -1 | | 0 731 | 8 | 8 | eight | 1 | -1 | 1 | -1 732 | 8 | 8 | eight | 1 | -1 | 2 | 2 733 | 8 | 8 | eight | 1 | -1 | 3 | -3 734 | 8 | 8 | eight | 1 | -1 | 2 | 4 735 | 8 | 8 | eight | 1 | -1 | 5 | -5 736 | 8 | 8 | eight | 1 | -1 | 5 | -5 737 | 8 | 8 | eight | 1 | -1 | 0 | 738 | 8 | 8 | eight | 1 | -1 | | 739 | 8 | 8 | eight | 1 | -1 | | 0 740 | 0 | | zero | 1 | -1 | 1 | -1 741 | 0 | | zero | 1 | -1 | 2 | 2 742 | 0 | | zero | 1 | -1 | 3 | -3 743 | 0 | | zero | 1 | -1 | 2 | 4 744 | 0 | | zero | 1 | -1 | 5 | -5 745 | 0 | | zero | 1 | -1 | 5 | -5 746 | 0 | | zero | 1 | -1 | 0 | 747 | 0 | | zero | 1 | -1 | | 748 | 0 | | zero | 1 | -1 | | 0 749 | | | null | 1 | -1 | 1 | -1 750 | | | null | 1 | -1 | 2 | 2 751 | | | null | 1 | -1 | 3 | -3 752 | | | null | 1 | -1 | 2 | 4 753 | | | null | 1 | -1 | 5 | -5 754 | | | null | 1 | -1 | 5 | -5 755 | | | null | 1 | -1 | 0 | 756 | | | null | 1 | -1 | | 757 | | | null | 1 | -1 | | 0 758 | | 0 | zero | 1 | -1 | 1 | -1 759 | | 0 | zero | 1 | -1 | 2 | 2 760 | | 0 | zero | 1 | -1 | 3 | -3 761 | | 0 | zero | 1 | -1 | 2 | 4 762 | | 0 | zero | 1 | -1 | 5 | -5 763 | | 0 | zero | 1 | -1 | 5 | -5 764 | | 0 | zero | 1 | -1 | 0 | 765 | | 0 | zero | 1 | -1 | | 766 | | 0 | zero | 1 | -1 | | 0 767 | 1 | 4 | one | 2 | 2 | 1 | -1 768 | 1 | 4 | one | 2 | 2 | 2 | 2 769 | 1 | 4 | one | 2 | 2 | 3 | -3 770 | 1 | 4 | one | 2 | 2 | 2 | 4 771 | 1 | 4 | one | 2 | 2 | 5 | -5 772 | 1 | 4 | one | 2 | 2 | 5 | -5 773 | 1 | 4 | one | 2 | 2 | 0 | 774 | 1 | 4 | one | 2 | 2 | | 775 | 1 | 4 | one | 2 | 2 | | 0 776 | 2 | 3 | two | 2 | 2 | 1 | -1 777 | 2 | 3 | two | 2 | 2 | 2 | 2 778 | 2 | 3 | two | 2 | 2 | 3 | -3 779 | 2 | 3 | two | 2 | 2 | 2 | 4 780 | 2 | 3 | two | 2 | 2 | 5 | -5 781 | 2 | 3 | two | 2 | 2 | 5 | -5 782 | 2 | 3 | two | 2 | 2 | 0 | 783 | 2 | 3 | two | 2 | 2 | | 784 | 2 | 3 | two | 2 | 2 | | 0 785 | 3 | 2 | three | 2 | 2 | 1 | -1 786 | 3 | 2 | three | 2 | 2 | 2 | 2 787 | 3 | 2 | three | 2 | 2 | 3 | -3 788 | 3 | 2 | three | 2 | 2 | 2 | 4 789 | 3 | 2 | three | 2 | 2 | 5 | -5 790 | 3 | 2 | three | 2 | 2 | 5 | -5 791 | 3 | 2 | three | 2 | 2 | 0 | 792 | 3 | 2 | three | 2 | 2 | | 793 | 3 | 2 | three | 2 | 2 | | 0 794 | 4 | 1 | four | 2 | 2 | 1 | -1 795 | 4 | 1 | four | 2 | 2 | 2 | 2 796 | 4 | 1 | four | 2 | 2 | 3 | -3 797 | 4 | 1 | four | 2 | 2 | 2 | 4 798 | 4 | 1 | four | 2 | 2 | 5 | -5 799 | 4 | 1 | four | 2 | 2 | 5 | -5 800 | 4 | 1 | four | 2 | 2 | 0 | 801 | 4 | 1 | four | 2 | 2 | | 802 | 4 | 1 | four | 2 | 2 | | 0 803 | 5 | 0 | five | 2 | 2 | 1 | -1 804 | 5 | 0 | five | 2 | 2 | 2 | 2 805 | 5 | 0 | five | 2 | 2 | 3 | -3 806 | 5 | 0 | five | 2 | 2 | 2 | 4 807 | 5 | 0 | five | 2 | 2 | 5 | -5 808 | 5 | 0 | five | 2 | 2 | 5 | -5 809 | 5 | 0 | five | 2 | 2 | 0 | 810 | 5 | 0 | five | 2 | 2 | | 811 | 5 | 0 | five | 2 | 2 | | 0 812 | 6 | 6 | six | 2 | 2 | 1 | -1 813 | 6 | 6 | six | 2 | 2 | 2 | 2 814 | 6 | 6 | six | 2 | 2 | 3 | -3 815 | 6 | 6 | six | 2 | 2 | 2 | 4 816 | 6 | 6 | six | 2 | 2 | 5 | -5 817 | 6 | 6 | six | 2 | 2 | 5 | -5 818 | 6 | 6 | six | 2 | 2 | 0 | 819 | 6 | 6 | six | 2 | 2 | | 820 | 6 | 6 | six | 2 | 2 | | 0 821 | 7 | 7 | seven | 2 | 2 | 1 | -1 822 | 7 | 7 | seven | 2 | 2 | 2 | 2 823 | 7 | 7 | seven | 2 | 2 | 3 | -3 824 | 7 | 7 | seven | 2 | 2 | 2 | 4 825 | 7 | 7 | seven | 2 | 2 | 5 | -5 826 | 7 | 7 | seven | 2 | 2 | 5 | -5 827 | 7 | 7 | seven | 2 | 2 | 0 | 828 | 7 | 7 | seven | 2 | 2 | | 829 | 7 | 7 | seven | 2 | 2 | | 0 830 | 8 | 8 | eight | 2 | 2 | 1 | -1 831 | 8 | 8 | eight | 2 | 2 | 2 | 2 832 | 8 | 8 | eight | 2 | 2 | 3 | -3 833 | 8 | 8 | eight | 2 | 2 | 2 | 4 834 | 8 | 8 | eight | 2 | 2 | 5 | -5 835 | 8 | 8 | eight | 2 | 2 | 5 | -5 836 | 8 | 8 | eight | 2 | 2 | 0 | 837 | 8 | 8 | eight | 2 | 2 | | 838 | 8 | 8 | eight | 2 | 2 | | 0 839 | 0 | | zero | 2 | 2 | 1 | -1 840 | 0 | | zero | 2 | 2 | 2 | 2 841 | 0 | | zero | 2 | 2 | 3 | -3 842 | 0 | | zero | 2 | 2 | 2 | 4 843 | 0 | | zero | 2 | 2 | 5 | -5 844 | 0 | | zero | 2 | 2 | 5 | -5 845 | 0 | | zero | 2 | 2 | 0 | 846 | 0 | | zero | 2 | 2 | | 847 | 0 | | zero | 2 | 2 | | 0 848 | | | null | 2 | 2 | 1 | -1 849 | | | null | 2 | 2 | 2 | 2 850 | | | null | 2 | 2 | 3 | -3 851 | | | null | 2 | 2 | 2 | 4 852 | | | null | 2 | 2 | 5 | -5 853 | | | null | 2 | 2 | 5 | -5 854 | | | null | 2 | 2 | 0 | 855 | | | null | 2 | 2 | | 856 | | | null | 2 | 2 | | 0 857 | | 0 | zero | 2 | 2 | 1 | -1 858 | | 0 | zero | 2 | 2 | 2 | 2 859 | | 0 | zero | 2 | 2 | 3 | -3 860 | | 0 | zero | 2 | 2 | 2 | 4 861 | | 0 | zero | 2 | 2 | 5 | -5 862 | | 0 | zero | 2 | 2 | 5 | -5 863 | | 0 | zero | 2 | 2 | 0 | 864 | | 0 | zero | 2 | 2 | | 865 | | 0 | zero | 2 | 2 | | 0 866 | 1 | 4 | one | 3 | -3 | 1 | -1 867 | 1 | 4 | one | 3 | -3 | 2 | 2 868 | 1 | 4 | one | 3 | -3 | 3 | -3 869 | 1 | 4 | one | 3 | -3 | 2 | 4 870 | 1 | 4 | one | 3 | -3 | 5 | -5 871 | 1 | 4 | one | 3 | -3 | 5 | -5 872 | 1 | 4 | one | 3 | -3 | 0 | 873 | 1 | 4 | one | 3 | -3 | | 874 | 1 | 4 | one | 3 | -3 | | 0 875 | 2 | 3 | two | 3 | -3 | 1 | -1 876 | 2 | 3 | two | 3 | -3 | 2 | 2 877 | 2 | 3 | two | 3 | -3 | 3 | -3 878 | 2 | 3 | two | 3 | -3 | 2 | 4 879 | 2 | 3 | two | 3 | -3 | 5 | -5 880 | 2 | 3 | two | 3 | -3 | 5 | -5 881 | 2 | 3 | two | 3 | -3 | 0 | 882 | 2 | 3 | two | 3 | -3 | | 883 | 2 | 3 | two | 3 | -3 | | 0 884 | 3 | 2 | three | 3 | -3 | 1 | -1 885 | 3 | 2 | three | 3 | -3 | 2 | 2 886 | 3 | 2 | three | 3 | -3 | 3 | -3 887 | 3 | 2 | three | 3 | -3 | 2 | 4 888 | 3 | 2 | three | 3 | -3 | 5 | -5 889 | 3 | 2 | three | 3 | -3 | 5 | -5 890 | 3 | 2 | three | 3 | -3 | 0 | 891 | 3 | 2 | three | 3 | -3 | | 892 | 3 | 2 | three | 3 | -3 | | 0 893 | 4 | 1 | four | 3 | -3 | 1 | -1 894 | 4 | 1 | four | 3 | -3 | 2 | 2 895 | 4 | 1 | four | 3 | -3 | 3 | -3 896 | 4 | 1 | four | 3 | -3 | 2 | 4 897 | 4 | 1 | four | 3 | -3 | 5 | -5 898 | 4 | 1 | four | 3 | -3 | 5 | -5 899 | 4 | 1 | four | 3 | -3 | 0 | 900 | 4 | 1 | four | 3 | -3 | | 901 | 4 | 1 | four | 3 | -3 | | 0 902 | 5 | 0 | five | 3 | -3 | 1 | -1 903 | 5 | 0 | five | 3 | -3 | 2 | 2 904 | 5 | 0 | five | 3 | -3 | 3 | -3 905 | 5 | 0 | five | 3 | -3 | 2 | 4 906 | 5 | 0 | five | 3 | -3 | 5 | -5 907 | 5 | 0 | five | 3 | -3 | 5 | -5 908 | 5 | 0 | five | 3 | -3 | 0 | 909 | 5 | 0 | five | 3 | -3 | | 910 | 5 | 0 | five | 3 | -3 | | 0 911 | 6 | 6 | six | 3 | -3 | 1 | -1 912 | 6 | 6 | six | 3 | -3 | 2 | 2 913 | 6 | 6 | six | 3 | -3 | 3 | -3 914 | 6 | 6 | six | 3 | -3 | 2 | 4 915 | 6 | 6 | six | 3 | -3 | 5 | -5 916 | 6 | 6 | six | 3 | -3 | 5 | -5 917 | 6 | 6 | six | 3 | -3 | 0 | 918 | 6 | 6 | six | 3 | -3 | | 919 | 6 | 6 | six | 3 | -3 | | 0 920 | 7 | 7 | seven | 3 | -3 | 1 | -1 921 | 7 | 7 | seven | 3 | -3 | 2 | 2 922 | 7 | 7 | seven | 3 | -3 | 3 | -3 923 | 7 | 7 | seven | 3 | -3 | 2 | 4 924 | 7 | 7 | seven | 3 | -3 | 5 | -5 925 | 7 | 7 | seven | 3 | -3 | 5 | -5 926 | 7 | 7 | seven | 3 | -3 | 0 | 927 | 7 | 7 | seven | 3 | -3 | | 928 | 7 | 7 | seven | 3 | -3 | | 0 929 | 8 | 8 | eight | 3 | -3 | 1 | -1 930 | 8 | 8 | eight | 3 | -3 | 2 | 2 931 | 8 | 8 | eight | 3 | -3 | 3 | -3 932 | 8 | 8 | eight | 3 | -3 | 2 | 4 933 | 8 | 8 | eight | 3 | -3 | 5 | -5 934 | 8 | 8 | eight | 3 | -3 | 5 | -5 935 | 8 | 8 | eight | 3 | -3 | 0 | 936 | 8 | 8 | eight | 3 | -3 | | 937 | 8 | 8 | eight | 3 | -3 | | 0 938 | 0 | | zero | 3 | -3 | 1 | -1 939 | 0 | | zero | 3 | -3 | 2 | 2 940 | 0 | | zero | 3 | -3 | 3 | -3 941 | 0 | | zero | 3 | -3 | 2 | 4 942 | 0 | | zero | 3 | -3 | 5 | -5 943 | 0 | | zero | 3 | -3 | 5 | -5 944 | 0 | | zero | 3 | -3 | 0 | 945 | 0 | | zero | 3 | -3 | | 946 | 0 | | zero | 3 | -3 | | 0 947 | | | null | 3 | -3 | 1 | -1 948 | | | null | 3 | -3 | 2 | 2 949 | | | null | 3 | -3 | 3 | -3 950 | | | null | 3 | -3 | 2 | 4 951 | | | null | 3 | -3 | 5 | -5 952 | | | null | 3 | -3 | 5 | -5 953 | | | null | 3 | -3 | 0 | 954 | | | null | 3 | -3 | | 955 | | | null | 3 | -3 | | 0 956 | | 0 | zero | 3 | -3 | 1 | -1 957 | | 0 | zero | 3 | -3 | 2 | 2 958 | | 0 | zero | 3 | -3 | 3 | -3 959 | | 0 | zero | 3 | -3 | 2 | 4 960 | | 0 | zero | 3 | -3 | 5 | -5 961 | | 0 | zero | 3 | -3 | 5 | -5 962 | | 0 | zero | 3 | -3 | 0 | 963 | | 0 | zero | 3 | -3 | | 964 | | 0 | zero | 3 | -3 | | 0 965 | 1 | 4 | one | 2 | 4 | 1 | -1 966 | 1 | 4 | one | 2 | 4 | 2 | 2 967 | 1 | 4 | one | 2 | 4 | 3 | -3 968 | 1 | 4 | one | 2 | 4 | 2 | 4 969 | 1 | 4 | one | 2 | 4 | 5 | -5 970 | 1 | 4 | one | 2 | 4 | 5 | -5 971 | 1 | 4 | one | 2 | 4 | 0 | 972 | 1 | 4 | one | 2 | 4 | | 973 | 1 | 4 | one | 2 | 4 | | 0 974 | 2 | 3 | two | 2 | 4 | 1 | -1 975 | 2 | 3 | two | 2 | 4 | 2 | 2 976 | 2 | 3 | two | 2 | 4 | 3 | -3 977 | 2 | 3 | two | 2 | 4 | 2 | 4 978 | 2 | 3 | two | 2 | 4 | 5 | -5 979 | 2 | 3 | two | 2 | 4 | 5 | -5 980 | 2 | 3 | two | 2 | 4 | 0 | 981 | 2 | 3 | two | 2 | 4 | | 982 | 2 | 3 | two | 2 | 4 | | 0 983 | 3 | 2 | three | 2 | 4 | 1 | -1 984 | 3 | 2 | three | 2 | 4 | 2 | 2 985 | 3 | 2 | three | 2 | 4 | 3 | -3 986 | 3 | 2 | three | 2 | 4 | 2 | 4 987 | 3 | 2 | three | 2 | 4 | 5 | -5 988 | 3 | 2 | three | 2 | 4 | 5 | -5 989 | 3 | 2 | three | 2 | 4 | 0 | 990 | 3 | 2 | three | 2 | 4 | | 991 | 3 | 2 | three | 2 | 4 | | 0 992 | 4 | 1 | four | 2 | 4 | 1 | -1 993 | 4 | 1 | four | 2 | 4 | 2 | 2 994 | 4 | 1 | four | 2 | 4 | 3 | -3 995 | 4 | 1 | four | 2 | 4 | 2 | 4 996 | 4 | 1 | four | 2 | 4 | 5 | -5 997 | 4 | 1 | four | 2 | 4 | 5 | -5 998 | 4 | 1 | four | 2 | 4 | 0 | 999 | 4 | 1 | four | 2 | 4 | | 1000 | 4 | 1 | four | 2 | 4 | | 0 1001 | 5 | 0 | five | 2 | 4 | 1 | -1 1002 | 5 | 0 | five | 2 | 4 | 2 | 2 1003 | 5 | 0 | five | 2 | 4 | 3 | -3 1004 | 5 | 0 | five | 2 | 4 | 2 | 4 1005 | 5 | 0 | five | 2 | 4 | 5 | -5 1006 | 5 | 0 | five | 2 | 4 | 5 | -5 1007 | 5 | 0 | five | 2 | 4 | 0 | 1008 | 5 | 0 | five | 2 | 4 | | 1009 | 5 | 0 | five | 2 | 4 | | 0 1010 | 6 | 6 | six | 2 | 4 | 1 | -1 1011 | 6 | 6 | six | 2 | 4 | 2 | 2 1012 | 6 | 6 | six | 2 | 4 | 3 | -3 1013 | 6 | 6 | six | 2 | 4 | 2 | 4 1014 | 6 | 6 | six | 2 | 4 | 5 | -5 1015 | 6 | 6 | six | 2 | 4 | 5 | -5 1016 | 6 | 6 | six | 2 | 4 | 0 | 1017 | 6 | 6 | six | 2 | 4 | | 1018 | 6 | 6 | six | 2 | 4 | | 0 1019 | 7 | 7 | seven | 2 | 4 | 1 | -1 1020 | 7 | 7 | seven | 2 | 4 | 2 | 2 1021 | 7 | 7 | seven | 2 | 4 | 3 | -3 1022 | 7 | 7 | seven | 2 | 4 | 2 | 4 1023 | 7 | 7 | seven | 2 | 4 | 5 | -5 1024 | 7 | 7 | seven | 2 | 4 | 5 | -5 1025 | 7 | 7 | seven | 2 | 4 | 0 | 1026 | 7 | 7 | seven | 2 | 4 | | 1027 | 7 | 7 | seven | 2 | 4 | | 0 1028 | 8 | 8 | eight | 2 | 4 | 1 | -1 1029 | 8 | 8 | eight | 2 | 4 | 2 | 2 1030 | 8 | 8 | eight | 2 | 4 | 3 | -3 1031 | 8 | 8 | eight | 2 | 4 | 2 | 4 1032 | 8 | 8 | eight | 2 | 4 | 5 | -5 1033 | 8 | 8 | eight | 2 | 4 | 5 | -5 1034 | 8 | 8 | eight | 2 | 4 | 0 | 1035 | 8 | 8 | eight | 2 | 4 | | 1036 | 8 | 8 | eight | 2 | 4 | | 0 1037 | 0 | | zero | 2 | 4 | 1 | -1 1038 | 0 | | zero | 2 | 4 | 2 | 2 1039 | 0 | | zero | 2 | 4 | 3 | -3 1040 | 0 | | zero | 2 | 4 | 2 | 4 1041 | 0 | | zero | 2 | 4 | 5 | -5 1042 | 0 | | zero | 2 | 4 | 5 | -5 1043 | 0 | | zero | 2 | 4 | 0 | 1044 | 0 | | zero | 2 | 4 | | 1045 | 0 | | zero | 2 | 4 | | 0 1046 | | | null | 2 | 4 | 1 | -1 1047 | | | null | 2 | 4 | 2 | 2 1048 | | | null | 2 | 4 | 3 | -3 1049 | | | null | 2 | 4 | 2 | 4 1050 | | | null | 2 | 4 | 5 | -5 1051 | | | null | 2 | 4 | 5 | -5 1052 | | | null | 2 | 4 | 0 | 1053 | | | null | 2 | 4 | | 1054 | | | null | 2 | 4 | | 0 1055 | | 0 | zero | 2 | 4 | 1 | -1 1056 | | 0 | zero | 2 | 4 | 2 | 2 1057 | | 0 | zero | 2 | 4 | 3 | -3 1058 | | 0 | zero | 2 | 4 | 2 | 4 1059 | | 0 | zero | 2 | 4 | 5 | -5 1060 | | 0 | zero | 2 | 4 | 5 | -5 1061 | | 0 | zero | 2 | 4 | 0 | 1062 | | 0 | zero | 2 | 4 | | 1063 | | 0 | zero | 2 | 4 | | 0 1064 | 1 | 4 | one | 5 | -5 | 1 | -1 1065 | 1 | 4 | one | 5 | -5 | 2 | 2 1066 | 1 | 4 | one | 5 | -5 | 3 | -3 1067 | 1 | 4 | one | 5 | -5 | 2 | 4 1068 | 1 | 4 | one | 5 | -5 | 5 | -5 1069 | 1 | 4 | one | 5 | -5 | 5 | -5 1070 | 1 | 4 | one | 5 | -5 | 0 | 1071 | 1 | 4 | one | 5 | -5 | | 1072 | 1 | 4 | one | 5 | -5 | | 0 1073 | 2 | 3 | two | 5 | -5 | 1 | -1 1074 | 2 | 3 | two | 5 | -5 | 2 | 2 1075 | 2 | 3 | two | 5 | -5 | 3 | -3 1076 | 2 | 3 | two | 5 | -5 | 2 | 4 1077 | 2 | 3 | two | 5 | -5 | 5 | -5 1078 | 2 | 3 | two | 5 | -5 | 5 | -5 1079 | 2 | 3 | two | 5 | -5 | 0 | 1080 | 2 | 3 | two | 5 | -5 | | 1081 | 2 | 3 | two | 5 | -5 | | 0 1082 | 3 | 2 | three | 5 | -5 | 1 | -1 1083 | 3 | 2 | three | 5 | -5 | 2 | 2 1084 | 3 | 2 | three | 5 | -5 | 3 | -3 1085 | 3 | 2 | three | 5 | -5 | 2 | 4 1086 | 3 | 2 | three | 5 | -5 | 5 | -5 1087 | 3 | 2 | three | 5 | -5 | 5 | -5 1088 | 3 | 2 | three | 5 | -5 | 0 | 1089 | 3 | 2 | three | 5 | -5 | | 1090 | 3 | 2 | three | 5 | -5 | | 0 1091 | 4 | 1 | four | 5 | -5 | 1 | -1 1092 | 4 | 1 | four | 5 | -5 | 2 | 2 1093 | 4 | 1 | four | 5 | -5 | 3 | -3 1094 | 4 | 1 | four | 5 | -5 | 2 | 4 1095 | 4 | 1 | four | 5 | -5 | 5 | -5 1096 | 4 | 1 | four | 5 | -5 | 5 | -5 1097 | 4 | 1 | four | 5 | -5 | 0 | 1098 | 4 | 1 | four | 5 | -5 | | 1099 | 4 | 1 | four | 5 | -5 | | 0 1100 | 5 | 0 | five | 5 | -5 | 1 | -1 1101 | 5 | 0 | five | 5 | -5 | 2 | 2 1102 | 5 | 0 | five | 5 | -5 | 3 | -3 1103 | 5 | 0 | five | 5 | -5 | 2 | 4 1104 | 5 | 0 | five | 5 | -5 | 5 | -5 1105 | 5 | 0 | five | 5 | -5 | 5 | -5 1106 | 5 | 0 | five | 5 | -5 | 0 | 1107 | 5 | 0 | five | 5 | -5 | | 1108 | 5 | 0 | five | 5 | -5 | | 0 1109 | 6 | 6 | six | 5 | -5 | 1 | -1 1110 | 6 | 6 | six | 5 | -5 | 2 | 2 1111 | 6 | 6 | six | 5 | -5 | 3 | -3 1112 | 6 | 6 | six | 5 | -5 | 2 | 4 1113 | 6 | 6 | six | 5 | -5 | 5 | -5 1114 | 6 | 6 | six | 5 | -5 | 5 | -5 1115 | 6 | 6 | six | 5 | -5 | 0 | 1116 | 6 | 6 | six | 5 | -5 | | 1117 | 6 | 6 | six | 5 | -5 | | 0 1118 | 7 | 7 | seven | 5 | -5 | 1 | -1 1119 | 7 | 7 | seven | 5 | -5 | 2 | 2 1120 | 7 | 7 | seven | 5 | -5 | 3 | -3 1121 | 7 | 7 | seven | 5 | -5 | 2 | 4 1122 | 7 | 7 | seven | 5 | -5 | 5 | -5 1123 | 7 | 7 | seven | 5 | -5 | 5 | -5 1124 | 7 | 7 | seven | 5 | -5 | 0 | 1125 | 7 | 7 | seven | 5 | -5 | | 1126 | 7 | 7 | seven | 5 | -5 | | 0 1127 | 8 | 8 | eight | 5 | -5 | 1 | -1 1128 | 8 | 8 | eight | 5 | -5 | 2 | 2 1129 | 8 | 8 | eight | 5 | -5 | 3 | -3 1130 | 8 | 8 | eight | 5 | -5 | 2 | 4 1131 | 8 | 8 | eight | 5 | -5 | 5 | -5 1132 | 8 | 8 | eight | 5 | -5 | 5 | -5 1133 | 8 | 8 | eight | 5 | -5 | 0 | 1134 | 8 | 8 | eight | 5 | -5 | | 1135 | 8 | 8 | eight | 5 | -5 | | 0 1136 | 0 | | zero | 5 | -5 | 1 | -1 1137 | 0 | | zero | 5 | -5 | 2 | 2 1138 | 0 | | zero | 5 | -5 | 3 | -3 1139 | 0 | | zero | 5 | -5 | 2 | 4 1140 | 0 | | zero | 5 | -5 | 5 | -5 1141 | 0 | | zero | 5 | -5 | 5 | -5 1142 | 0 | | zero | 5 | -5 | 0 | 1143 | 0 | | zero | 5 | -5 | | 1144 | 0 | | zero | 5 | -5 | | 0 1145 | | | null | 5 | -5 | 1 | -1 1146 | | | null | 5 | -5 | 2 | 2 1147 | | | null | 5 | -5 | 3 | -3 1148 | | | null | 5 | -5 | 2 | 4 1149 | | | null | 5 | -5 | 5 | -5 1150 | | | null | 5 | -5 | 5 | -5 1151 | | | null | 5 | -5 | 0 | 1152 | | | null | 5 | -5 | | 1153 | | | null | 5 | -5 | | 0 1154 | | 0 | zero | 5 | -5 | 1 | -1 1155 | | 0 | zero | 5 | -5 | 2 | 2 1156 | | 0 | zero | 5 | -5 | 3 | -3 1157 | | 0 | zero | 5 | -5 | 2 | 4 1158 | | 0 | zero | 5 | -5 | 5 | -5 1159 | | 0 | zero | 5 | -5 | 5 | -5 1160 | | 0 | zero | 5 | -5 | 0 | 1161 | | 0 | zero | 5 | -5 | | 1162 | | 0 | zero | 5 | -5 | | 0 1163 | 1 | 4 | one | 5 | -5 | 1 | -1 1164 | 1 | 4 | one | 5 | -5 | 2 | 2 1165 | 1 | 4 | one | 5 | -5 | 3 | -3 1166 | 1 | 4 | one | 5 | -5 | 2 | 4 1167 | 1 | 4 | one | 5 | -5 | 5 | -5 1168 | 1 | 4 | one | 5 | -5 | 5 | -5 1169 | 1 | 4 | one | 5 | -5 | 0 | 1170 | 1 | 4 | one | 5 | -5 | | 1171 | 1 | 4 | one | 5 | -5 | | 0 1172 | 2 | 3 | two | 5 | -5 | 1 | -1 1173 | 2 | 3 | two | 5 | -5 | 2 | 2 1174 | 2 | 3 | two | 5 | -5 | 3 | -3 1175 | 2 | 3 | two | 5 | -5 | 2 | 4 1176 | 2 | 3 | two | 5 | -5 | 5 | -5 1177 | 2 | 3 | two | 5 | -5 | 5 | -5 1178 | 2 | 3 | two | 5 | -5 | 0 | 1179 | 2 | 3 | two | 5 | -5 | | 1180 | 2 | 3 | two | 5 | -5 | | 0 1181 | 3 | 2 | three | 5 | -5 | 1 | -1 1182 | 3 | 2 | three | 5 | -5 | 2 | 2 1183 | 3 | 2 | three | 5 | -5 | 3 | -3 1184 | 3 | 2 | three | 5 | -5 | 2 | 4 1185 | 3 | 2 | three | 5 | -5 | 5 | -5 1186 | 3 | 2 | three | 5 | -5 | 5 | -5 1187 | 3 | 2 | three | 5 | -5 | 0 | 1188 | 3 | 2 | three | 5 | -5 | | 1189 | 3 | 2 | three | 5 | -5 | | 0 1190 | 4 | 1 | four | 5 | -5 | 1 | -1 1191 | 4 | 1 | four | 5 | -5 | 2 | 2 1192 | 4 | 1 | four | 5 | -5 | 3 | -3 1193 | 4 | 1 | four | 5 | -5 | 2 | 4 1194 | 4 | 1 | four | 5 | -5 | 5 | -5 1195 | 4 | 1 | four | 5 | -5 | 5 | -5 1196 | 4 | 1 | four | 5 | -5 | 0 | 1197 | 4 | 1 | four | 5 | -5 | | 1198 | 4 | 1 | four | 5 | -5 | | 0 1199 | 5 | 0 | five | 5 | -5 | 1 | -1 1200 | 5 | 0 | five | 5 | -5 | 2 | 2 1201 | 5 | 0 | five | 5 | -5 | 3 | -3 1202 | 5 | 0 | five | 5 | -5 | 2 | 4 1203 | 5 | 0 | five | 5 | -5 | 5 | -5 1204 | 5 | 0 | five | 5 | -5 | 5 | -5 1205 | 5 | 0 | five | 5 | -5 | 0 | 1206 | 5 | 0 | five | 5 | -5 | | 1207 | 5 | 0 | five | 5 | -5 | | 0 1208 | 6 | 6 | six | 5 | -5 | 1 | -1 1209 | 6 | 6 | six | 5 | -5 | 2 | 2 1210 | 6 | 6 | six | 5 | -5 | 3 | -3 1211 | 6 | 6 | six | 5 | -5 | 2 | 4 1212 | 6 | 6 | six | 5 | -5 | 5 | -5 1213 | 6 | 6 | six | 5 | -5 | 5 | -5 1214 | 6 | 6 | six | 5 | -5 | 0 | 1215 | 6 | 6 | six | 5 | -5 | | 1216 | 6 | 6 | six | 5 | -5 | | 0 1217 | 7 | 7 | seven | 5 | -5 | 1 | -1 1218 | 7 | 7 | seven | 5 | -5 | 2 | 2 1219 | 7 | 7 | seven | 5 | -5 | 3 | -3 1220 | 7 | 7 | seven | 5 | -5 | 2 | 4 1221 | 7 | 7 | seven | 5 | -5 | 5 | -5 1222 | 7 | 7 | seven | 5 | -5 | 5 | -5 1223 | 7 | 7 | seven | 5 | -5 | 0 | 1224 | 7 | 7 | seven | 5 | -5 | | 1225 | 7 | 7 | seven | 5 | -5 | | 0 1226 | 8 | 8 | eight | 5 | -5 | 1 | -1 1227 | 8 | 8 | eight | 5 | -5 | 2 | 2 1228 | 8 | 8 | eight | 5 | -5 | 3 | -3 1229 | 8 | 8 | eight | 5 | -5 | 2 | 4 1230 | 8 | 8 | eight | 5 | -5 | 5 | -5 1231 | 8 | 8 | eight | 5 | -5 | 5 | -5 1232 | 8 | 8 | eight | 5 | -5 | 0 | 1233 | 8 | 8 | eight | 5 | -5 | | 1234 | 8 | 8 | eight | 5 | -5 | | 0 1235 | 0 | | zero | 5 | -5 | 1 | -1 1236 | 0 | | zero | 5 | -5 | 2 | 2 1237 | 0 | | zero | 5 | -5 | 3 | -3 1238 | 0 | | zero | 5 | -5 | 2 | 4 1239 | 0 | | zero | 5 | -5 | 5 | -5 1240 | 0 | | zero | 5 | -5 | 5 | -5 1241 | 0 | | zero | 5 | -5 | 0 | 1242 | 0 | | zero | 5 | -5 | | 1243 | 0 | | zero | 5 | -5 | | 0 1244 | | | null | 5 | -5 | 1 | -1 1245 | | | null | 5 | -5 | 2 | 2 1246 | | | null | 5 | -5 | 3 | -3 1247 | | | null | 5 | -5 | 2 | 4 1248 | | | null | 5 | -5 | 5 | -5 1249 | | | null | 5 | -5 | 5 | -5 1250 | | | null | 5 | -5 | 0 | 1251 | | | null | 5 | -5 | | 1252 | | | null | 5 | -5 | | 0 1253 | | 0 | zero | 5 | -5 | 1 | -1 1254 | | 0 | zero | 5 | -5 | 2 | 2 1255 | | 0 | zero | 5 | -5 | 3 | -3 1256 | | 0 | zero | 5 | -5 | 2 | 4 1257 | | 0 | zero | 5 | -5 | 5 | -5 1258 | | 0 | zero | 5 | -5 | 5 | -5 1259 | | 0 | zero | 5 | -5 | 0 | 1260 | | 0 | zero | 5 | -5 | | 1261 | | 0 | zero | 5 | -5 | | 0 1262 | 1 | 4 | one | 0 | | 1 | -1 1263 | 1 | 4 | one | 0 | | 2 | 2 1264 | 1 | 4 | one | 0 | | 3 | -3 1265 | 1 | 4 | one | 0 | | 2 | 4 1266 | 1 | 4 | one | 0 | | 5 | -5 1267 | 1 | 4 | one | 0 | | 5 | -5 1268 | 1 | 4 | one | 0 | | 0 | 1269 | 1 | 4 | one | 0 | | | 1270 | 1 | 4 | one | 0 | | | 0 1271 | 2 | 3 | two | 0 | | 1 | -1 1272 | 2 | 3 | two | 0 | | 2 | 2 1273 | 2 | 3 | two | 0 | | 3 | -3 1274 | 2 | 3 | two | 0 | | 2 | 4 1275 | 2 | 3 | two | 0 | | 5 | -5 1276 | 2 | 3 | two | 0 | | 5 | -5 1277 | 2 | 3 | two | 0 | | 0 | 1278 | 2 | 3 | two | 0 | | | 1279 | 2 | 3 | two | 0 | | | 0 1280 | 3 | 2 | three | 0 | | 1 | -1 1281 | 3 | 2 | three | 0 | | 2 | 2 1282 | 3 | 2 | three | 0 | | 3 | -3 1283 | 3 | 2 | three | 0 | | 2 | 4 1284 | 3 | 2 | three | 0 | | 5 | -5 1285 | 3 | 2 | three | 0 | | 5 | -5 1286 | 3 | 2 | three | 0 | | 0 | 1287 | 3 | 2 | three | 0 | | | 1288 | 3 | 2 | three | 0 | | | 0 1289 | 4 | 1 | four | 0 | | 1 | -1 1290 | 4 | 1 | four | 0 | | 2 | 2 1291 | 4 | 1 | four | 0 | | 3 | -3 1292 | 4 | 1 | four | 0 | | 2 | 4 1293 | 4 | 1 | four | 0 | | 5 | -5 1294 | 4 | 1 | four | 0 | | 5 | -5 1295 | 4 | 1 | four | 0 | | 0 | 1296 | 4 | 1 | four | 0 | | | 1297 | 4 | 1 | four | 0 | | | 0 1298 | 5 | 0 | five | 0 | | 1 | -1 1299 | 5 | 0 | five | 0 | | 2 | 2 1300 | 5 | 0 | five | 0 | | 3 | -3 1301 | 5 | 0 | five | 0 | | 2 | 4 1302 | 5 | 0 | five | 0 | | 5 | -5 1303 | 5 | 0 | five | 0 | | 5 | -5 1304 | 5 | 0 | five | 0 | | 0 | 1305 | 5 | 0 | five | 0 | | | 1306 | 5 | 0 | five | 0 | | | 0 1307 | 6 | 6 | six | 0 | | 1 | -1 1308 | 6 | 6 | six | 0 | | 2 | 2 1309 | 6 | 6 | six | 0 | | 3 | -3 1310 | 6 | 6 | six | 0 | | 2 | 4 1311 | 6 | 6 | six | 0 | | 5 | -5 1312 | 6 | 6 | six | 0 | | 5 | -5 1313 | 6 | 6 | six | 0 | | 0 | 1314 | 6 | 6 | six | 0 | | | 1315 | 6 | 6 | six | 0 | | | 0 1316 | 7 | 7 | seven | 0 | | 1 | -1 1317 | 7 | 7 | seven | 0 | | 2 | 2 1318 | 7 | 7 | seven | 0 | | 3 | -3 1319 | 7 | 7 | seven | 0 | | 2 | 4 1320 | 7 | 7 | seven | 0 | | 5 | -5 1321 | 7 | 7 | seven | 0 | | 5 | -5 1322 | 7 | 7 | seven | 0 | | 0 | 1323 | 7 | 7 | seven | 0 | | | 1324 | 7 | 7 | seven | 0 | | | 0 1325 | 8 | 8 | eight | 0 | | 1 | -1 1326 | 8 | 8 | eight | 0 | | 2 | 2 1327 | 8 | 8 | eight | 0 | | 3 | -3 1328 | 8 | 8 | eight | 0 | | 2 | 4 1329 | 8 | 8 | eight | 0 | | 5 | -5 1330 | 8 | 8 | eight | 0 | | 5 | -5 1331 | 8 | 8 | eight | 0 | | 0 | 1332 | 8 | 8 | eight | 0 | | | 1333 | 8 | 8 | eight | 0 | | | 0 1334 | 0 | | zero | 0 | | 1 | -1 1335 | 0 | | zero | 0 | | 2 | 2 1336 | 0 | | zero | 0 | | 3 | -3 1337 | 0 | | zero | 0 | | 2 | 4 1338 | 0 | | zero | 0 | | 5 | -5 1339 | 0 | | zero | 0 | | 5 | -5 1340 | 0 | | zero | 0 | | 0 | 1341 | 0 | | zero | 0 | | | 1342 | 0 | | zero | 0 | | | 0 1343 | | | null | 0 | | 1 | -1 1344 | | | null | 0 | | 2 | 2 1345 | | | null | 0 | | 3 | -3 1346 | | | null | 0 | | 2 | 4 1347 | | | null | 0 | | 5 | -5 1348 | | | null | 0 | | 5 | -5 1349 | | | null | 0 | | 0 | 1350 | | | null | 0 | | | 1351 | | | null | 0 | | | 0 1352 | | 0 | zero | 0 | | 1 | -1 1353 | | 0 | zero | 0 | | 2 | 2 1354 | | 0 | zero | 0 | | 3 | -3 1355 | | 0 | zero | 0 | | 2 | 4 1356 | | 0 | zero | 0 | | 5 | -5 1357 | | 0 | zero | 0 | | 5 | -5 1358 | | 0 | zero | 0 | | 0 | 1359 | | 0 | zero | 0 | | | 1360 | | 0 | zero | 0 | | | 0 1361 | 1 | 4 | one | | | 1 | -1 1362 | 1 | 4 | one | | | 2 | 2 1363 | 1 | 4 | one | | | 3 | -3 1364 | 1 | 4 | one | | | 2 | 4 1365 | 1 | 4 | one | | | 5 | -5 1366 | 1 | 4 | one | | | 5 | -5 1367 | 1 | 4 | one | | | 0 | 1368 | 1 | 4 | one | | | | 1369 | 1 | 4 | one | | | | 0 1370 | 2 | 3 | two | | | 1 | -1 1371 | 2 | 3 | two | | | 2 | 2 1372 | 2 | 3 | two | | | 3 | -3 1373 | 2 | 3 | two | | | 2 | 4 1374 | 2 | 3 | two | | | 5 | -5 1375 | 2 | 3 | two | | | 5 | -5 1376 | 2 | 3 | two | | | 0 | 1377 | 2 | 3 | two | | | | 1378 | 2 | 3 | two | | | | 0 1379 | 3 | 2 | three | | | 1 | -1 1380 | 3 | 2 | three | | | 2 | 2 1381 | 3 | 2 | three | | | 3 | -3 1382 | 3 | 2 | three | | | 2 | 4 1383 | 3 | 2 | three | | | 5 | -5 1384 | 3 | 2 | three | | | 5 | -5 1385 | 3 | 2 | three | | | 0 | 1386 | 3 | 2 | three | | | | 1387 | 3 | 2 | three | | | | 0 1388 | 4 | 1 | four | | | 1 | -1 1389 | 4 | 1 | four | | | 2 | 2 1390 | 4 | 1 | four | | | 3 | -3 1391 | 4 | 1 | four | | | 2 | 4 1392 | 4 | 1 | four | | | 5 | -5 1393 | 4 | 1 | four | | | 5 | -5 1394 | 4 | 1 | four | | | 0 | 1395 | 4 | 1 | four | | | | 1396 | 4 | 1 | four | | | | 0 1397 | 5 | 0 | five | | | 1 | -1 1398 | 5 | 0 | five | | | 2 | 2 1399 | 5 | 0 | five | | | 3 | -3 1400 | 5 | 0 | five | | | 2 | 4 1401 | 5 | 0 | five | | | 5 | -5 1402 | 5 | 0 | five | | | 5 | -5 1403 | 5 | 0 | five | | | 0 | 1404 | 5 | 0 | five | | | | 1405 | 5 | 0 | five | | | | 0 1406 | 6 | 6 | six | | | 1 | -1 1407 | 6 | 6 | six | | | 2 | 2 1408 | 6 | 6 | six | | | 3 | -3 1409 | 6 | 6 | six | | | 2 | 4 1410 | 6 | 6 | six | | | 5 | -5 1411 | 6 | 6 | six | | | 5 | -5 1412 | 6 | 6 | six | | | 0 | 1413 | 6 | 6 | six | | | | 1414 | 6 | 6 | six | | | | 0 1415 | 7 | 7 | seven | | | 1 | -1 1416 | 7 | 7 | seven | | | 2 | 2 1417 | 7 | 7 | seven | | | 3 | -3 1418 | 7 | 7 | seven | | | 2 | 4 1419 | 7 | 7 | seven | | | 5 | -5 1420 | 7 | 7 | seven | | | 5 | -5 1421 | 7 | 7 | seven | | | 0 | 1422 | 7 | 7 | seven | | | | 1423 | 7 | 7 | seven | | | | 0 1424 | 8 | 8 | eight | | | 1 | -1 1425 | 8 | 8 | eight | | | 2 | 2 1426 | 8 | 8 | eight | | | 3 | -3 1427 | 8 | 8 | eight | | | 2 | 4 1428 | 8 | 8 | eight | | | 5 | -5 1429 | 8 | 8 | eight | | | 5 | -5 1430 | 8 | 8 | eight | | | 0 | 1431 | 8 | 8 | eight | | | | 1432 | 8 | 8 | eight | | | | 0 1433 | 0 | | zero | | | 1 | -1 1434 | 0 | | zero | | | 2 | 2 1435 | 0 | | zero | | | 3 | -3 1436 | 0 | | zero | | | 2 | 4 1437 | 0 | | zero | | | 5 | -5 1438 | 0 | | zero | | | 5 | -5 1439 | 0 | | zero | | | 0 | 1440 | 0 | | zero | | | | 1441 | 0 | | zero | | | | 0 1442 | | | null | | | 1 | -1 1443 | | | null | | | 2 | 2 1444 | | | null | | | 3 | -3 1445 | | | null | | | 2 | 4 1446 | | | null | | | 5 | -5 1447 | | | null | | | 5 | -5 1448 | | | null | | | 0 | 1449 | | | null | | | | 1450 | | | null | | | | 0 1451 | | 0 | zero | | | 1 | -1 1452 | | 0 | zero | | | 2 | 2 1453 | | 0 | zero | | | 3 | -3 1454 | | 0 | zero | | | 2 | 4 1455 | | 0 | zero | | | 5 | -5 1456 | | 0 | zero | | | 5 | -5 1457 | | 0 | zero | | | 0 | 1458 | | 0 | zero | | | | 1459 | | 0 | zero | | | | 0 1460 | 1 | 4 | one | | 0 | 1 | -1 1461 | 1 | 4 | one | | 0 | 2 | 2 1462 | 1 | 4 | one | | 0 | 3 | -3 1463 | 1 | 4 | one | | 0 | 2 | 4 1464 | 1 | 4 | one | | 0 | 5 | -5 1465 | 1 | 4 | one | | 0 | 5 | -5 1466 | 1 | 4 | one | | 0 | 0 | 1467 | 1 | 4 | one | | 0 | | 1468 | 1 | 4 | one | | 0 | | 0 1469 | 2 | 3 | two | | 0 | 1 | -1 1470 | 2 | 3 | two | | 0 | 2 | 2 1471 | 2 | 3 | two | | 0 | 3 | -3 1472 | 2 | 3 | two | | 0 | 2 | 4 1473 | 2 | 3 | two | | 0 | 5 | -5 1474 | 2 | 3 | two | | 0 | 5 | -5 1475 | 2 | 3 | two | | 0 | 0 | 1476 | 2 | 3 | two | | 0 | | 1477 | 2 | 3 | two | | 0 | | 0 1478 | 3 | 2 | three | | 0 | 1 | -1 1479 | 3 | 2 | three | | 0 | 2 | 2 1480 | 3 | 2 | three | | 0 | 3 | -3 1481 | 3 | 2 | three | | 0 | 2 | 4 1482 | 3 | 2 | three | | 0 | 5 | -5 1483 | 3 | 2 | three | | 0 | 5 | -5 1484 | 3 | 2 | three | | 0 | 0 | 1485 | 3 | 2 | three | | 0 | | 1486 | 3 | 2 | three | | 0 | | 0 1487 | 4 | 1 | four | | 0 | 1 | -1 1488 | 4 | 1 | four | | 0 | 2 | 2 1489 | 4 | 1 | four | | 0 | 3 | -3 1490 | 4 | 1 | four | | 0 | 2 | 4 1491 | 4 | 1 | four | | 0 | 5 | -5 1492 | 4 | 1 | four | | 0 | 5 | -5 1493 | 4 | 1 | four | | 0 | 0 | 1494 | 4 | 1 | four | | 0 | | 1495 | 4 | 1 | four | | 0 | | 0 1496 | 5 | 0 | five | | 0 | 1 | -1 1497 | 5 | 0 | five | | 0 | 2 | 2 1498 | 5 | 0 | five | | 0 | 3 | -3 1499 | 5 | 0 | five | | 0 | 2 | 4 1500 | 5 | 0 | five | | 0 | 5 | -5 1501 | 5 | 0 | five | | 0 | 5 | -5 1502 | 5 | 0 | five | | 0 | 0 | 1503 | 5 | 0 | five | | 0 | | 1504 | 5 | 0 | five | | 0 | | 0 1505 | 6 | 6 | six | | 0 | 1 | -1 1506 | 6 | 6 | six | | 0 | 2 | 2 1507 | 6 | 6 | six | | 0 | 3 | -3 1508 | 6 | 6 | six | | 0 | 2 | 4 1509 | 6 | 6 | six | | 0 | 5 | -5 1510 | 6 | 6 | six | | 0 | 5 | -5 1511 | 6 | 6 | six | | 0 | 0 | 1512 | 6 | 6 | six | | 0 | | 1513 | 6 | 6 | six | | 0 | | 0 1514 | 7 | 7 | seven | | 0 | 1 | -1 1515 | 7 | 7 | seven | | 0 | 2 | 2 1516 | 7 | 7 | seven | | 0 | 3 | -3 1517 | 7 | 7 | seven | | 0 | 2 | 4 1518 | 7 | 7 | seven | | 0 | 5 | -5 1519 | 7 | 7 | seven | | 0 | 5 | -5 1520 | 7 | 7 | seven | | 0 | 0 | 1521 | 7 | 7 | seven | | 0 | | 1522 | 7 | 7 | seven | | 0 | | 0 1523 | 8 | 8 | eight | | 0 | 1 | -1 1524 | 8 | 8 | eight | | 0 | 2 | 2 1525 | 8 | 8 | eight | | 0 | 3 | -3 1526 | 8 | 8 | eight | | 0 | 2 | 4 1527 | 8 | 8 | eight | | 0 | 5 | -5 1528 | 8 | 8 | eight | | 0 | 5 | -5 1529 | 8 | 8 | eight | | 0 | 0 | 1530 | 8 | 8 | eight | | 0 | | 1531 | 8 | 8 | eight | | 0 | | 0 1532 | 0 | | zero | | 0 | 1 | -1 1533 | 0 | | zero | | 0 | 2 | 2 1534 | 0 | | zero | | 0 | 3 | -3 1535 | 0 | | zero | | 0 | 2 | 4 1536 | 0 | | zero | | 0 | 5 | -5 1537 | 0 | | zero | | 0 | 5 | -5 1538 | 0 | | zero | | 0 | 0 | 1539 | 0 | | zero | | 0 | | 1540 | 0 | | zero | | 0 | | 0 1541 | | | null | | 0 | 1 | -1 1542 | | | null | | 0 | 2 | 2 1543 | | | null | | 0 | 3 | -3 1544 | | | null | | 0 | 2 | 4 1545 | | | null | | 0 | 5 | -5 1546 | | | null | | 0 | 5 | -5 1547 | | | null | | 0 | 0 | 1548 | | | null | | 0 | | 1549 | | | null | | 0 | | 0 1550 | | 0 | zero | | 0 | 1 | -1 1551 | | 0 | zero | | 0 | 2 | 2 1552 | | 0 | zero | | 0 | 3 | -3 1553 | | 0 | zero | | 0 | 2 | 4 1554 | | 0 | zero | | 0 | 5 | -5 1555 | | 0 | zero | | 0 | 5 | -5 1556 | | 0 | zero | | 0 | 0 | 1557 | | 0 | zero | | 0 | | 1558 | | 0 | zero | | 0 | | 0 1559(891 rows) 1560 1561-- 1562-- 1563-- Inner joins (equi-joins) 1564-- 1565-- 1566-- 1567-- Inner joins (equi-joins) with USING clause 1568-- The USING syntax changes the shape of the resulting table 1569-- by including a column in the USING clause only once in the result. 1570-- 1571-- Inner equi-join on specified column 1572SELECT '' AS "xxx", * 1573 FROM J1_TBL INNER JOIN J2_TBL USING (i); 1574 xxx | i | j | t | k 1575-----+---+---+-------+---- 1576 | 0 | | zero | 1577 | 1 | 4 | one | -1 1578 | 2 | 3 | two | 2 1579 | 2 | 3 | two | 4 1580 | 3 | 2 | three | -3 1581 | 5 | 0 | five | -5 1582 | 5 | 0 | five | -5 1583(7 rows) 1584 1585-- Same as above, slightly different syntax 1586SELECT '' AS "xxx", * 1587 FROM J1_TBL JOIN J2_TBL USING (i); 1588 xxx | i | j | t | k 1589-----+---+---+-------+---- 1590 | 0 | | zero | 1591 | 1 | 4 | one | -1 1592 | 2 | 3 | two | 2 1593 | 2 | 3 | two | 4 1594 | 3 | 2 | three | -3 1595 | 5 | 0 | five | -5 1596 | 5 | 0 | five | -5 1597(7 rows) 1598 1599SELECT '' AS "xxx", * 1600 FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, d) USING (a) 1601 ORDER BY a, d; 1602 xxx | a | b | c | d 1603-----+---+---+-------+---- 1604 | 0 | | zero | 1605 | 1 | 4 | one | -1 1606 | 2 | 3 | two | 2 1607 | 2 | 3 | two | 4 1608 | 3 | 2 | three | -3 1609 | 5 | 0 | five | -5 1610 | 5 | 0 | five | -5 1611(7 rows) 1612 1613SELECT '' AS "xxx", * 1614 FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, b) USING (b) 1615 ORDER BY b, t1.a; 1616 xxx | b | a | c | a 1617-----+---+---+-------+--- 1618 | 0 | 5 | five | 1619 | 0 | | zero | 1620 | 2 | 3 | three | 2 1621 | 4 | 1 | one | 2 1622(4 rows) 1623 1624-- 1625-- NATURAL JOIN 1626-- Inner equi-join on all columns with the same name 1627-- 1628SELECT '' AS "xxx", * 1629 FROM J1_TBL NATURAL JOIN J2_TBL; 1630 xxx | i | j | t | k 1631-----+---+---+-------+---- 1632 | 0 | | zero | 1633 | 1 | 4 | one | -1 1634 | 2 | 3 | two | 2 1635 | 2 | 3 | two | 4 1636 | 3 | 2 | three | -3 1637 | 5 | 0 | five | -5 1638 | 5 | 0 | five | -5 1639(7 rows) 1640 1641SELECT '' AS "xxx", * 1642 FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (a, d); 1643 xxx | a | b | c | d 1644-----+---+---+-------+---- 1645 | 0 | | zero | 1646 | 1 | 4 | one | -1 1647 | 2 | 3 | two | 2 1648 | 2 | 3 | two | 4 1649 | 3 | 2 | three | -3 1650 | 5 | 0 | five | -5 1651 | 5 | 0 | five | -5 1652(7 rows) 1653 1654SELECT '' AS "xxx", * 1655 FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (d, a); 1656 xxx | a | b | c | d 1657-----+---+---+------+--- 1658 | 0 | | zero | 1659 | 2 | 3 | two | 2 1660 | 4 | 1 | four | 2 1661(3 rows) 1662 1663-- mismatch number of columns 1664-- currently, Postgres will fill in with underlying names 1665SELECT '' AS "xxx", * 1666 FROM J1_TBL t1 (a, b) NATURAL JOIN J2_TBL t2 (a); 1667 xxx | a | b | t | k 1668-----+---+---+-------+---- 1669 | 0 | | zero | 1670 | 1 | 4 | one | -1 1671 | 2 | 3 | two | 2 1672 | 2 | 3 | two | 4 1673 | 3 | 2 | three | -3 1674 | 5 | 0 | five | -5 1675 | 5 | 0 | five | -5 1676(7 rows) 1677 1678-- 1679-- Inner joins (equi-joins) 1680-- 1681SELECT '' AS "xxx", * 1682 FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.i); 1683 xxx | i | j | t | i | k 1684-----+---+---+-------+---+---- 1685 | 0 | | zero | 0 | 1686 | 1 | 4 | one | 1 | -1 1687 | 2 | 3 | two | 2 | 2 1688 | 2 | 3 | two | 2 | 4 1689 | 3 | 2 | three | 3 | -3 1690 | 5 | 0 | five | 5 | -5 1691 | 5 | 0 | five | 5 | -5 1692(7 rows) 1693 1694SELECT '' AS "xxx", * 1695 FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.k); 1696 xxx | i | j | t | i | k 1697-----+---+---+------+---+--- 1698 | 0 | | zero | | 0 1699 | 2 | 3 | two | 2 | 2 1700 | 4 | 1 | four | 2 | 4 1701(3 rows) 1702 1703-- 1704-- Non-equi-joins 1705-- 1706SELECT '' AS "xxx", * 1707 FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i <= J2_TBL.k); 1708 xxx | i | j | t | i | k 1709-----+---+---+-------+---+--- 1710 | 1 | 4 | one | 2 | 2 1711 | 2 | 3 | two | 2 | 2 1712 | 0 | | zero | 2 | 2 1713 | 1 | 4 | one | 2 | 4 1714 | 2 | 3 | two | 2 | 4 1715 | 3 | 2 | three | 2 | 4 1716 | 4 | 1 | four | 2 | 4 1717 | 0 | | zero | 2 | 4 1718 | 0 | | zero | | 0 1719(9 rows) 1720 1721-- 1722-- Outer joins 1723-- Note that OUTER is a noise word 1724-- 1725SELECT '' AS "xxx", * 1726 FROM J1_TBL LEFT OUTER JOIN J2_TBL USING (i) 1727 ORDER BY i, k, t; 1728 xxx | i | j | t | k 1729-----+---+---+-------+---- 1730 | 0 | | zero | 1731 | 1 | 4 | one | -1 1732 | 2 | 3 | two | 2 1733 | 2 | 3 | two | 4 1734 | 3 | 2 | three | -3 1735 | 4 | 1 | four | 1736 | 5 | 0 | five | -5 1737 | 5 | 0 | five | -5 1738 | 6 | 6 | six | 1739 | 7 | 7 | seven | 1740 | 8 | 8 | eight | 1741 | | | null | 1742 | | 0 | zero | 1743(13 rows) 1744 1745SELECT '' AS "xxx", * 1746 FROM J1_TBL LEFT JOIN J2_TBL USING (i) 1747 ORDER BY i, k, t; 1748 xxx | i | j | t | k 1749-----+---+---+-------+---- 1750 | 0 | | zero | 1751 | 1 | 4 | one | -1 1752 | 2 | 3 | two | 2 1753 | 2 | 3 | two | 4 1754 | 3 | 2 | three | -3 1755 | 4 | 1 | four | 1756 | 5 | 0 | five | -5 1757 | 5 | 0 | five | -5 1758 | 6 | 6 | six | 1759 | 7 | 7 | seven | 1760 | 8 | 8 | eight | 1761 | | | null | 1762 | | 0 | zero | 1763(13 rows) 1764 1765SELECT '' AS "xxx", * 1766 FROM J1_TBL RIGHT OUTER JOIN J2_TBL USING (i); 1767 xxx | i | j | t | k 1768-----+---+---+-------+---- 1769 | 0 | | zero | 1770 | 1 | 4 | one | -1 1771 | 2 | 3 | two | 2 1772 | 2 | 3 | two | 4 1773 | 3 | 2 | three | -3 1774 | 5 | 0 | five | -5 1775 | 5 | 0 | five | -5 1776 | | | | 1777 | | | | 0 1778(9 rows) 1779 1780SELECT '' AS "xxx", * 1781 FROM J1_TBL RIGHT JOIN J2_TBL USING (i); 1782 xxx | i | j | t | k 1783-----+---+---+-------+---- 1784 | 0 | | zero | 1785 | 1 | 4 | one | -1 1786 | 2 | 3 | two | 2 1787 | 2 | 3 | two | 4 1788 | 3 | 2 | three | -3 1789 | 5 | 0 | five | -5 1790 | 5 | 0 | five | -5 1791 | | | | 1792 | | | | 0 1793(9 rows) 1794 1795SELECT '' AS "xxx", * 1796 FROM J1_TBL FULL OUTER JOIN J2_TBL USING (i) 1797 ORDER BY i, k, t; 1798 xxx | i | j | t | k 1799-----+---+---+-------+---- 1800 | 0 | | zero | 1801 | 1 | 4 | one | -1 1802 | 2 | 3 | two | 2 1803 | 2 | 3 | two | 4 1804 | 3 | 2 | three | -3 1805 | 4 | 1 | four | 1806 | 5 | 0 | five | -5 1807 | 5 | 0 | five | -5 1808 | 6 | 6 | six | 1809 | 7 | 7 | seven | 1810 | 8 | 8 | eight | 1811 | | | | 0 1812 | | | null | 1813 | | 0 | zero | 1814 | | | | 1815(15 rows) 1816 1817SELECT '' AS "xxx", * 1818 FROM J1_TBL FULL JOIN J2_TBL USING (i) 1819 ORDER BY i, k, t; 1820 xxx | i | j | t | k 1821-----+---+---+-------+---- 1822 | 0 | | zero | 1823 | 1 | 4 | one | -1 1824 | 2 | 3 | two | 2 1825 | 2 | 3 | two | 4 1826 | 3 | 2 | three | -3 1827 | 4 | 1 | four | 1828 | 5 | 0 | five | -5 1829 | 5 | 0 | five | -5 1830 | 6 | 6 | six | 1831 | 7 | 7 | seven | 1832 | 8 | 8 | eight | 1833 | | | | 0 1834 | | | null | 1835 | | 0 | zero | 1836 | | | | 1837(15 rows) 1838 1839SELECT '' AS "xxx", * 1840 FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (k = 1); 1841 xxx | i | j | t | k 1842-----+---+---+---+--- 1843(0 rows) 1844 1845SELECT '' AS "xxx", * 1846 FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (i = 1); 1847 xxx | i | j | t | k 1848-----+---+---+-----+---- 1849 | 1 | 4 | one | -1 1850(1 row) 1851 1852-- 1853-- semijoin selectivity for <> 1854-- 1855explain (costs off) 1856select * from int4_tbl i4, tenk1 a 1857where exists(select * from tenk1 b 1858 where a.twothousand = b.twothousand and a.fivethous <> b.fivethous) 1859 and i4.f1 = a.tenthous; 1860 QUERY PLAN 1861---------------------------------------------- 1862 Hash Semi Join 1863 Hash Cond: (a.twothousand = b.twothousand) 1864 Join Filter: (a.fivethous <> b.fivethous) 1865 -> Hash Join 1866 Hash Cond: (a.tenthous = i4.f1) 1867 -> Seq Scan on tenk1 a 1868 -> Hash 1869 -> Seq Scan on int4_tbl i4 1870 -> Hash 1871 -> Seq Scan on tenk1 b 1872(10 rows) 1873 1874-- 1875-- More complicated constructs 1876-- 1877-- 1878-- Multiway full join 1879-- 1880CREATE TABLE t1 (name TEXT, n INTEGER); 1881CREATE TABLE t2 (name TEXT, n INTEGER); 1882CREATE TABLE t3 (name TEXT, n INTEGER); 1883INSERT INTO t1 VALUES ( 'bb', 11 ); 1884INSERT INTO t2 VALUES ( 'bb', 12 ); 1885INSERT INTO t2 VALUES ( 'cc', 22 ); 1886INSERT INTO t2 VALUES ( 'ee', 42 ); 1887INSERT INTO t3 VALUES ( 'bb', 13 ); 1888INSERT INTO t3 VALUES ( 'cc', 23 ); 1889INSERT INTO t3 VALUES ( 'dd', 33 ); 1890SELECT * FROM t1 FULL JOIN t2 USING (name) FULL JOIN t3 USING (name); 1891 name | n | n | n 1892------+----+----+---- 1893 bb | 11 | 12 | 13 1894 cc | | 22 | 23 1895 dd | | | 33 1896 ee | | 42 | 1897(4 rows) 1898 1899-- 1900-- Test interactions of join syntax and subqueries 1901-- 1902-- Basic cases (we expect planner to pull up the subquery here) 1903SELECT * FROM 1904(SELECT * FROM t2) as s2 1905INNER JOIN 1906(SELECT * FROM t3) s3 1907USING (name); 1908 name | n | n 1909------+----+---- 1910 bb | 12 | 13 1911 cc | 22 | 23 1912(2 rows) 1913 1914SELECT * FROM 1915(SELECT * FROM t2) as s2 1916LEFT JOIN 1917(SELECT * FROM t3) s3 1918USING (name); 1919 name | n | n 1920------+----+---- 1921 bb | 12 | 13 1922 cc | 22 | 23 1923 ee | 42 | 1924(3 rows) 1925 1926SELECT * FROM 1927(SELECT * FROM t2) as s2 1928FULL JOIN 1929(SELECT * FROM t3) s3 1930USING (name); 1931 name | n | n 1932------+----+---- 1933 bb | 12 | 13 1934 cc | 22 | 23 1935 dd | | 33 1936 ee | 42 | 1937(4 rows) 1938 1939-- Cases with non-nullable expressions in subquery results; 1940-- make sure these go to null as expected 1941SELECT * FROM 1942(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2 1943NATURAL INNER JOIN 1944(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3; 1945 name | s2_n | s2_2 | s3_n | s3_2 1946------+------+------+------+------ 1947 bb | 12 | 2 | 13 | 3 1948 cc | 22 | 2 | 23 | 3 1949(2 rows) 1950 1951SELECT * FROM 1952(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2 1953NATURAL LEFT JOIN 1954(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3; 1955 name | s2_n | s2_2 | s3_n | s3_2 1956------+------+------+------+------ 1957 bb | 12 | 2 | 13 | 3 1958 cc | 22 | 2 | 23 | 3 1959 ee | 42 | 2 | | 1960(3 rows) 1961 1962SELECT * FROM 1963(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2 1964NATURAL FULL JOIN 1965(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3; 1966 name | s2_n | s2_2 | s3_n | s3_2 1967------+------+------+------+------ 1968 bb | 12 | 2 | 13 | 3 1969 cc | 22 | 2 | 23 | 3 1970 dd | | | 33 | 3 1971 ee | 42 | 2 | | 1972(4 rows) 1973 1974SELECT * FROM 1975(SELECT name, n as s1_n, 1 as s1_1 FROM t1) as s1 1976NATURAL INNER JOIN 1977(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2 1978NATURAL INNER JOIN 1979(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3; 1980 name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2 1981------+------+------+------+------+------+------ 1982 bb | 11 | 1 | 12 | 2 | 13 | 3 1983(1 row) 1984 1985SELECT * FROM 1986(SELECT name, n as s1_n, 1 as s1_1 FROM t1) as s1 1987NATURAL FULL JOIN 1988(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2 1989NATURAL FULL JOIN 1990(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3; 1991 name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2 1992------+------+------+------+------+------+------ 1993 bb | 11 | 1 | 12 | 2 | 13 | 3 1994 cc | | | 22 | 2 | 23 | 3 1995 dd | | | | | 33 | 3 1996 ee | | | 42 | 2 | | 1997(4 rows) 1998 1999SELECT * FROM 2000(SELECT name, n as s1_n FROM t1) as s1 2001NATURAL FULL JOIN 2002 (SELECT * FROM 2003 (SELECT name, n as s2_n FROM t2) as s2 2004 NATURAL FULL JOIN 2005 (SELECT name, n as s3_n FROM t3) as s3 2006 ) ss2; 2007 name | s1_n | s2_n | s3_n 2008------+------+------+------ 2009 bb | 11 | 12 | 13 2010 cc | | 22 | 23 2011 dd | | | 33 2012 ee | | 42 | 2013(4 rows) 2014 2015SELECT * FROM 2016(SELECT name, n as s1_n FROM t1) as s1 2017NATURAL FULL JOIN 2018 (SELECT * FROM 2019 (SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2 2020 NATURAL FULL JOIN 2021 (SELECT name, n as s3_n FROM t3) as s3 2022 ) ss2; 2023 name | s1_n | s2_n | s2_2 | s3_n 2024------+------+------+------+------ 2025 bb | 11 | 12 | 2 | 13 2026 cc | | 22 | 2 | 23 2027 dd | | | | 33 2028 ee | | 42 | 2 | 2029(4 rows) 2030 2031-- Constants as join keys can also be problematic 2032SELECT * FROM 2033 (SELECT name, n as s1_n FROM t1) as s1 2034FULL JOIN 2035 (SELECT name, 2 as s2_n FROM t2) as s2 2036ON (s1_n = s2_n); 2037 name | s1_n | name | s2_n 2038------+------+------+------ 2039 | | bb | 2 2040 | | cc | 2 2041 | | ee | 2 2042 bb | 11 | | 2043(4 rows) 2044 2045-- Test for propagation of nullability constraints into sub-joins 2046create temp table x (x1 int, x2 int); 2047insert into x values (1,11); 2048insert into x values (2,22); 2049insert into x values (3,null); 2050insert into x values (4,44); 2051insert into x values (5,null); 2052create temp table y (y1 int, y2 int); 2053insert into y values (1,111); 2054insert into y values (2,222); 2055insert into y values (3,333); 2056insert into y values (4,null); 2057select * from x; 2058 x1 | x2 2059----+---- 2060 1 | 11 2061 2 | 22 2062 3 | 2063 4 | 44 2064 5 | 2065(5 rows) 2066 2067select * from y; 2068 y1 | y2 2069----+----- 2070 1 | 111 2071 2 | 222 2072 3 | 333 2073 4 | 2074(4 rows) 2075 2076select * from x left join y on (x1 = y1 and x2 is not null); 2077 x1 | x2 | y1 | y2 2078----+----+----+----- 2079 1 | 11 | 1 | 111 2080 2 | 22 | 2 | 222 2081 3 | | | 2082 4 | 44 | 4 | 2083 5 | | | 2084(5 rows) 2085 2086select * from x left join y on (x1 = y1 and y2 is not null); 2087 x1 | x2 | y1 | y2 2088----+----+----+----- 2089 1 | 11 | 1 | 111 2090 2 | 22 | 2 | 222 2091 3 | | 3 | 333 2092 4 | 44 | | 2093 5 | | | 2094(5 rows) 2095 2096select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2097on (x1 = xx1); 2098 x1 | x2 | y1 | y2 | xx1 | xx2 2099----+----+----+-----+-----+----- 2100 1 | 11 | 1 | 111 | 1 | 11 2101 2 | 22 | 2 | 222 | 2 | 22 2102 3 | | 3 | 333 | 3 | 2103 4 | 44 | 4 | | 4 | 44 2104 5 | | | | 5 | 2105(5 rows) 2106 2107select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2108on (x1 = xx1 and x2 is not null); 2109 x1 | x2 | y1 | y2 | xx1 | xx2 2110----+----+----+-----+-----+----- 2111 1 | 11 | 1 | 111 | 1 | 11 2112 2 | 22 | 2 | 222 | 2 | 22 2113 3 | | 3 | 333 | | 2114 4 | 44 | 4 | | 4 | 44 2115 5 | | | | | 2116(5 rows) 2117 2118select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2119on (x1 = xx1 and y2 is not null); 2120 x1 | x2 | y1 | y2 | xx1 | xx2 2121----+----+----+-----+-----+----- 2122 1 | 11 | 1 | 111 | 1 | 11 2123 2 | 22 | 2 | 222 | 2 | 22 2124 3 | | 3 | 333 | 3 | 2125 4 | 44 | 4 | | | 2126 5 | | | | | 2127(5 rows) 2128 2129select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2130on (x1 = xx1 and xx2 is not null); 2131 x1 | x2 | y1 | y2 | xx1 | xx2 2132----+----+----+-----+-----+----- 2133 1 | 11 | 1 | 111 | 1 | 11 2134 2 | 22 | 2 | 222 | 2 | 22 2135 3 | | 3 | 333 | | 2136 4 | 44 | 4 | | 4 | 44 2137 5 | | | | | 2138(5 rows) 2139 2140-- these should NOT give the same answers as above 2141select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2142on (x1 = xx1) where (x2 is not null); 2143 x1 | x2 | y1 | y2 | xx1 | xx2 2144----+----+----+-----+-----+----- 2145 1 | 11 | 1 | 111 | 1 | 11 2146 2 | 22 | 2 | 222 | 2 | 22 2147 4 | 44 | 4 | | 4 | 44 2148(3 rows) 2149 2150select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2151on (x1 = xx1) where (y2 is not null); 2152 x1 | x2 | y1 | y2 | xx1 | xx2 2153----+----+----+-----+-----+----- 2154 1 | 11 | 1 | 111 | 1 | 11 2155 2 | 22 | 2 | 222 | 2 | 22 2156 3 | | 3 | 333 | 3 | 2157(3 rows) 2158 2159select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2) 2160on (x1 = xx1) where (xx2 is not null); 2161 x1 | x2 | y1 | y2 | xx1 | xx2 2162----+----+----+-----+-----+----- 2163 1 | 11 | 1 | 111 | 1 | 11 2164 2 | 22 | 2 | 222 | 2 | 22 2165 4 | 44 | 4 | | 4 | 44 2166(3 rows) 2167 2168-- 2169-- regression test: check for bug with propagation of implied equality 2170-- to outside an IN 2171-- 2172select count(*) from tenk1 a where unique1 in 2173 (select unique1 from tenk1 b join tenk1 c using (unique1) 2174 where b.unique2 = 42); 2175 count 2176------- 2177 1 2178(1 row) 2179 2180-- 2181-- regression test: check for failure to generate a plan with multiple 2182-- degenerate IN clauses 2183-- 2184select count(*) from tenk1 x where 2185 x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and 2186 x.unique1 = 0 and 2187 x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1); 2188 count 2189------- 2190 1 2191(1 row) 2192 2193-- try that with GEQO too 2194begin; 2195set geqo = on; 2196set geqo_threshold = 2; 2197select count(*) from tenk1 x where 2198 x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and 2199 x.unique1 = 0 and 2200 x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1); 2201 count 2202------- 2203 1 2204(1 row) 2205 2206rollback; 2207-- 2208-- regression test: be sure we cope with proven-dummy append rels 2209-- 2210explain (costs off) 2211select aa, bb, unique1, unique1 2212 from tenk1 right join b on aa = unique1 2213 where bb < bb and bb is null; 2214 QUERY PLAN 2215-------------------------- 2216 Result 2217 One-Time Filter: false 2218(2 rows) 2219 2220select aa, bb, unique1, unique1 2221 from tenk1 right join b on aa = unique1 2222 where bb < bb and bb is null; 2223 aa | bb | unique1 | unique1 2224----+----+---------+--------- 2225(0 rows) 2226 2227-- 2228-- regression test: check handling of empty-FROM subquery underneath outer join 2229-- 2230explain (costs off) 2231select * from int8_tbl i1 left join (int8_tbl i2 join 2232 (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2 2233order by 1, 2; 2234 QUERY PLAN 2235------------------------------------------- 2236 Sort 2237 Sort Key: i1.q1, i1.q2 2238 -> Hash Left Join 2239 Hash Cond: (i1.q2 = i2.q2) 2240 -> Seq Scan on int8_tbl i1 2241 -> Hash 2242 -> Seq Scan on int8_tbl i2 2243 Filter: (q1 = 123) 2244(8 rows) 2245 2246select * from int8_tbl i1 left join (int8_tbl i2 join 2247 (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2 2248order by 1, 2; 2249 q1 | q2 | q1 | q2 | x 2250------------------+-------------------+-----+------------------+----- 2251 123 | 456 | 123 | 456 | 123 2252 123 | 4567890123456789 | 123 | 4567890123456789 | 123 2253 4567890123456789 | -4567890123456789 | | | 2254 4567890123456789 | 123 | | | 2255 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 123 2256(5 rows) 2257 2258-- 2259-- regression test: check a case where join_clause_is_movable_into() gives 2260-- an imprecise result, causing an assertion failure 2261-- 2262select count(*) 2263from 2264 (select t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2 2265 from tenk1 t1 2266 left join tenk1 t2 on t1.unique1 = t2.unique1 2267 join tenk1 t3 on t1.unique2 = t3.unique2) ss, 2268 tenk1 t4, 2269 tenk1 t5 2270where t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1; 2271 count 2272------- 2273 1000 2274(1 row) 2275 2276-- 2277-- regression test: check a case where we formerly missed including an EC 2278-- enforcement clause because it was expected to be handled at scan level 2279-- 2280explain (costs off) 2281select a.f1, b.f1, t.thousand, t.tenthous from 2282 tenk1 t, 2283 (select sum(f1)+1 as f1 from int4_tbl i4a) a, 2284 (select sum(f1) as f1 from int4_tbl i4b) b 2285where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; 2286 QUERY PLAN 2287----------------------------------------------------------------------------------------------------------------------- 2288 Nested Loop 2289 -> Aggregate 2290 -> Seq Scan on int4_tbl i4b 2291 -> Nested Loop 2292 Join Filter: ((sum(i4b.f1)) = ((sum(i4a.f1) + 1))) 2293 -> Aggregate 2294 -> Seq Scan on int4_tbl i4a 2295 -> Index Only Scan using tenk1_thous_tenthous on tenk1 t 2296 Index Cond: ((thousand = (sum(i4b.f1))) AND (tenthous = ((((sum(i4a.f1) + 1)) + (sum(i4b.f1))) + 999))) 2297(9 rows) 2298 2299select a.f1, b.f1, t.thousand, t.tenthous from 2300 tenk1 t, 2301 (select sum(f1)+1 as f1 from int4_tbl i4a) a, 2302 (select sum(f1) as f1 from int4_tbl i4b) b 2303where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous; 2304 f1 | f1 | thousand | tenthous 2305----+----+----------+---------- 2306(0 rows) 2307 2308-- 2309-- check a case where we formerly got confused by conflicting sort orders 2310-- in redundant merge join path keys 2311-- 2312explain (costs off) 2313select * from 2314 j1_tbl full join 2315 (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl 2316 on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k; 2317 QUERY PLAN 2318----------------------------------------------------------------- 2319 Merge Full Join 2320 Merge Cond: ((j2_tbl.i = j1_tbl.i) AND (j2_tbl.k = j1_tbl.i)) 2321 -> Sort 2322 Sort Key: j2_tbl.i DESC, j2_tbl.k 2323 -> Seq Scan on j2_tbl 2324 -> Sort 2325 Sort Key: j1_tbl.i DESC 2326 -> Seq Scan on j1_tbl 2327(8 rows) 2328 2329select * from 2330 j1_tbl full join 2331 (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl 2332 on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k; 2333 i | j | t | i | k 2334---+---+-------+---+---- 2335 | | | | 0 2336 | | | | 2337 | 0 | zero | | 2338 | | null | | 2339 8 | 8 | eight | | 2340 7 | 7 | seven | | 2341 6 | 6 | six | | 2342 | | | 5 | -5 2343 | | | 5 | -5 2344 5 | 0 | five | | 2345 4 | 1 | four | | 2346 | | | 3 | -3 2347 3 | 2 | three | | 2348 2 | 3 | two | 2 | 2 2349 | | | 2 | 4 2350 | | | 1 | -1 2351 | | | 0 | 2352 1 | 4 | one | | 2353 0 | | zero | | 2354(19 rows) 2355 2356-- 2357-- a different check for handling of redundant sort keys in merge joins 2358-- 2359explain (costs off) 2360select count(*) from 2361 (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x 2362 left join 2363 (select * from tenk1 y order by y.unique2) y 2364 on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; 2365 QUERY PLAN 2366---------------------------------------------------------------------------------- 2367 Aggregate 2368 -> Merge Left Join 2369 Merge Cond: (x.thousand = y.unique2) 2370 Join Filter: ((x.twothousand = y.hundred) AND (x.fivethous = y.unique2)) 2371 -> Sort 2372 Sort Key: x.thousand, x.twothousand, x.fivethous 2373 -> Seq Scan on tenk1 x 2374 -> Materialize 2375 -> Index Scan using tenk1_unique2 on tenk1 y 2376(9 rows) 2377 2378select count(*) from 2379 (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x 2380 left join 2381 (select * from tenk1 y order by y.unique2) y 2382 on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2; 2383 count 2384------- 2385 10000 2386(1 row) 2387 2388-- 2389-- Clean up 2390-- 2391DROP TABLE t1; 2392DROP TABLE t2; 2393DROP TABLE t3; 2394DROP TABLE J1_TBL; 2395DROP TABLE J2_TBL; 2396-- Both DELETE and UPDATE allow the specification of additional tables 2397-- to "join" against to determine which rows should be modified. 2398CREATE TEMP TABLE t1 (a int, b int); 2399CREATE TEMP TABLE t2 (a int, b int); 2400CREATE TEMP TABLE t3 (x int, y int); 2401INSERT INTO t1 VALUES (5, 10); 2402INSERT INTO t1 VALUES (15, 20); 2403INSERT INTO t1 VALUES (100, 100); 2404INSERT INTO t1 VALUES (200, 1000); 2405INSERT INTO t2 VALUES (200, 2000); 2406INSERT INTO t3 VALUES (5, 20); 2407INSERT INTO t3 VALUES (6, 7); 2408INSERT INTO t3 VALUES (7, 8); 2409INSERT INTO t3 VALUES (500, 100); 2410DELETE FROM t3 USING t1 table1 WHERE t3.x = table1.a; 2411SELECT * FROM t3; 2412 x | y 2413-----+----- 2414 6 | 7 2415 7 | 8 2416 500 | 100 2417(3 rows) 2418 2419DELETE FROM t3 USING t1 JOIN t2 USING (a) WHERE t3.x > t1.a; 2420SELECT * FROM t3; 2421 x | y 2422---+--- 2423 6 | 7 2424 7 | 8 2425(2 rows) 2426 2427DELETE FROM t3 USING t3 t3_other WHERE t3.x = t3_other.x AND t3.y = t3_other.y; 2428SELECT * FROM t3; 2429 x | y 2430---+--- 2431(0 rows) 2432 2433-- Test join against inheritance tree 2434create temp table t2a () inherits (t2); 2435insert into t2a values (200, 2001); 2436select * from t1 left join t2 on (t1.a = t2.a); 2437 a | b | a | b 2438-----+------+-----+------ 2439 5 | 10 | | 2440 15 | 20 | | 2441 100 | 100 | | 2442 200 | 1000 | 200 | 2000 2443 200 | 1000 | 200 | 2001 2444(5 rows) 2445 2446-- Test matching of column name with wrong alias 2447select t1.x from t1 join t3 on (t1.a = t3.x); 2448ERROR: column t1.x does not exist 2449LINE 1: select t1.x from t1 join t3 on (t1.a = t3.x); 2450 ^ 2451HINT: Perhaps you meant to reference the column "t3.x". 2452-- 2453-- regression test for 8.1 merge right join bug 2454-- 2455CREATE TEMP TABLE tt1 ( tt1_id int4, joincol int4 ); 2456INSERT INTO tt1 VALUES (1, 11); 2457INSERT INTO tt1 VALUES (2, NULL); 2458CREATE TEMP TABLE tt2 ( tt2_id int4, joincol int4 ); 2459INSERT INTO tt2 VALUES (21, 11); 2460INSERT INTO tt2 VALUES (22, 11); 2461set enable_hashjoin to off; 2462set enable_nestloop to off; 2463-- these should give the same results 2464select tt1.*, tt2.* from tt1 left join tt2 on tt1.joincol = tt2.joincol; 2465 tt1_id | joincol | tt2_id | joincol 2466--------+---------+--------+--------- 2467 1 | 11 | 21 | 11 2468 1 | 11 | 22 | 11 2469 2 | | | 2470(3 rows) 2471 2472select tt1.*, tt2.* from tt2 right join tt1 on tt1.joincol = tt2.joincol; 2473 tt1_id | joincol | tt2_id | joincol 2474--------+---------+--------+--------- 2475 1 | 11 | 21 | 11 2476 1 | 11 | 22 | 11 2477 2 | | | 2478(3 rows) 2479 2480reset enable_hashjoin; 2481reset enable_nestloop; 2482-- 2483-- regression test for bug #13908 (hash join with skew tuples & nbatch increase) 2484-- 2485set work_mem to '64kB'; 2486set enable_mergejoin to off; 2487explain (costs off) 2488select count(*) from tenk1 a, tenk1 b 2489 where a.hundred = b.thousand and (b.fivethous % 10) < 10; 2490 QUERY PLAN 2491------------------------------------------------------------ 2492 Aggregate 2493 -> Hash Join 2494 Hash Cond: (a.hundred = b.thousand) 2495 -> Index Only Scan using tenk1_hundred on tenk1 a 2496 -> Hash 2497 -> Seq Scan on tenk1 b 2498 Filter: ((fivethous % 10) < 10) 2499(7 rows) 2500 2501select count(*) from tenk1 a, tenk1 b 2502 where a.hundred = b.thousand and (b.fivethous % 10) < 10; 2503 count 2504-------- 2505 100000 2506(1 row) 2507 2508reset work_mem; 2509reset enable_mergejoin; 2510-- 2511-- regression test for 8.2 bug with improper re-ordering of left joins 2512-- 2513create temp table tt3(f1 int, f2 text); 2514insert into tt3 select x, repeat('xyzzy', 100) from generate_series(1,10000) x; 2515create index tt3i on tt3(f1); 2516analyze tt3; 2517create temp table tt4(f1 int); 2518insert into tt4 values (0),(1),(9999); 2519analyze tt4; 2520SELECT a.f1 2521FROM tt4 a 2522LEFT JOIN ( 2523 SELECT b.f1 2524 FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1) 2525 WHERE c.f1 IS NULL 2526) AS d ON (a.f1 = d.f1) 2527WHERE d.f1 IS NULL; 2528 f1 2529------ 2530 0 2531 1 2532 9999 2533(3 rows) 2534 2535-- 2536-- regression test for proper handling of outer joins within antijoins 2537-- 2538create temp table tt4x(c1 int, c2 int, c3 int); 2539explain (costs off) 2540select * from tt4x t1 2541where not exists ( 2542 select 1 from tt4x t2 2543 left join tt4x t3 on t2.c3 = t3.c1 2544 left join ( select t5.c1 as c1 2545 from tt4x t4 left join tt4x t5 on t4.c2 = t5.c1 2546 ) a1 on t3.c2 = a1.c1 2547 where t1.c1 = t2.c2 2548); 2549 QUERY PLAN 2550--------------------------------------------------------- 2551 Hash Anti Join 2552 Hash Cond: (t1.c1 = t2.c2) 2553 -> Seq Scan on tt4x t1 2554 -> Hash 2555 -> Merge Right Join 2556 Merge Cond: (t5.c1 = t3.c2) 2557 -> Merge Join 2558 Merge Cond: (t4.c2 = t5.c1) 2559 -> Sort 2560 Sort Key: t4.c2 2561 -> Seq Scan on tt4x t4 2562 -> Sort 2563 Sort Key: t5.c1 2564 -> Seq Scan on tt4x t5 2565 -> Sort 2566 Sort Key: t3.c2 2567 -> Merge Left Join 2568 Merge Cond: (t2.c3 = t3.c1) 2569 -> Sort 2570 Sort Key: t2.c3 2571 -> Seq Scan on tt4x t2 2572 -> Sort 2573 Sort Key: t3.c1 2574 -> Seq Scan on tt4x t3 2575(24 rows) 2576 2577-- 2578-- regression test for problems of the sort depicted in bug #3494 2579-- 2580create temp table tt5(f1 int, f2 int); 2581create temp table tt6(f1 int, f2 int); 2582insert into tt5 values(1, 10); 2583insert into tt5 values(1, 11); 2584insert into tt6 values(1, 9); 2585insert into tt6 values(1, 2); 2586insert into tt6 values(2, 9); 2587select * from tt5,tt6 where tt5.f1 = tt6.f1 and tt5.f1 = tt5.f2 - tt6.f2; 2588 f1 | f2 | f1 | f2 2589----+----+----+---- 2590 1 | 10 | 1 | 9 2591(1 row) 2592 2593-- 2594-- regression test for problems of the sort depicted in bug #3588 2595-- 2596create temp table xx (pkxx int); 2597create temp table yy (pkyy int, pkxx int); 2598insert into xx values (1); 2599insert into xx values (2); 2600insert into xx values (3); 2601insert into yy values (101, 1); 2602insert into yy values (201, 2); 2603insert into yy values (301, NULL); 2604select yy.pkyy as yy_pkyy, yy.pkxx as yy_pkxx, yya.pkyy as yya_pkyy, 2605 xxa.pkxx as xxa_pkxx, xxb.pkxx as xxb_pkxx 2606from yy 2607 left join (SELECT * FROM yy where pkyy = 101) as yya ON yy.pkyy = yya.pkyy 2608 left join xx xxa on yya.pkxx = xxa.pkxx 2609 left join xx xxb on coalesce (xxa.pkxx, 1) = xxb.pkxx; 2610 yy_pkyy | yy_pkxx | yya_pkyy | xxa_pkxx | xxb_pkxx 2611---------+---------+----------+----------+---------- 2612 101 | 1 | 101 | 1 | 1 2613 201 | 2 | | | 1 2614 301 | | | | 1 2615(3 rows) 2616 2617-- 2618-- regression test for improper pushing of constants across outer-join clauses 2619-- (as seen in early 8.2.x releases) 2620-- 2621create temp table zt1 (f1 int primary key); 2622create temp table zt2 (f2 int primary key); 2623create temp table zt3 (f3 int primary key); 2624insert into zt1 values(53); 2625insert into zt2 values(53); 2626select * from 2627 zt2 left join zt3 on (f2 = f3) 2628 left join zt1 on (f3 = f1) 2629where f2 = 53; 2630 f2 | f3 | f1 2631----+----+---- 2632 53 | | 2633(1 row) 2634 2635create temp view zv1 as select *,'dummy'::text AS junk from zt1; 2636select * from 2637 zt2 left join zt3 on (f2 = f3) 2638 left join zv1 on (f3 = f1) 2639where f2 = 53; 2640 f2 | f3 | f1 | junk 2641----+----+----+------ 2642 53 | | | 2643(1 row) 2644 2645-- 2646-- regression test for improper extraction of OR indexqual conditions 2647-- (as seen in early 8.3.x releases) 2648-- 2649select a.unique2, a.ten, b.tenthous, b.unique2, b.hundred 2650from tenk1 a left join tenk1 b on a.unique2 = b.tenthous 2651where a.unique1 = 42 and 2652 ((b.unique2 is null and a.ten = 2) or b.hundred = 3); 2653 unique2 | ten | tenthous | unique2 | hundred 2654---------+-----+----------+---------+--------- 2655(0 rows) 2656 2657-- 2658-- test proper positioning of one-time quals in EXISTS (8.4devel bug) 2659-- 2660prepare foo(bool) as 2661 select count(*) from tenk1 a left join tenk1 b 2662 on (a.unique2 = b.unique1 and exists 2663 (select 1 from tenk1 c where c.thousand = b.unique2 and $1)); 2664execute foo(true); 2665 count 2666------- 2667 10000 2668(1 row) 2669 2670execute foo(false); 2671 count 2672------- 2673 10000 2674(1 row) 2675 2676-- 2677-- test for sane behavior with noncanonical merge clauses, per bug #4926 2678-- 2679begin; 2680set enable_mergejoin = 1; 2681set enable_hashjoin = 0; 2682set enable_nestloop = 0; 2683create temp table a (i integer); 2684create temp table b (x integer, y integer); 2685select * from a left join b on i = x and i = y and x = i; 2686 i | x | y 2687---+---+--- 2688(0 rows) 2689 2690rollback; 2691-- 2692-- test handling of merge clauses using record_ops 2693-- 2694begin; 2695create type mycomptype as (id int, v bigint); 2696create temp table tidv (idv mycomptype); 2697create index on tidv (idv); 2698explain (costs off) 2699select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; 2700 QUERY PLAN 2701---------------------------------------------------------- 2702 Merge Join 2703 Merge Cond: (a.idv = b.idv) 2704 -> Index Only Scan using tidv_idv_idx on tidv a 2705 -> Materialize 2706 -> Index Only Scan using tidv_idv_idx on tidv b 2707(5 rows) 2708 2709set enable_mergejoin = 0; 2710explain (costs off) 2711select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv; 2712 QUERY PLAN 2713---------------------------------------------------- 2714 Nested Loop 2715 -> Seq Scan on tidv a 2716 -> Index Only Scan using tidv_idv_idx on tidv b 2717 Index Cond: (idv = a.idv) 2718(4 rows) 2719 2720rollback; 2721-- 2722-- test NULL behavior of whole-row Vars, per bug #5025 2723-- 2724select t1.q2, count(t2.*) 2725from int8_tbl t1 left join int8_tbl t2 on (t1.q2 = t2.q1) 2726group by t1.q2 order by 1; 2727 q2 | count 2728-------------------+------- 2729 -4567890123456789 | 0 2730 123 | 2 2731 456 | 0 2732 4567890123456789 | 6 2733(4 rows) 2734 2735select t1.q2, count(t2.*) 2736from int8_tbl t1 left join (select * from int8_tbl) t2 on (t1.q2 = t2.q1) 2737group by t1.q2 order by 1; 2738 q2 | count 2739-------------------+------- 2740 -4567890123456789 | 0 2741 123 | 2 2742 456 | 0 2743 4567890123456789 | 6 2744(4 rows) 2745 2746select t1.q2, count(t2.*) 2747from int8_tbl t1 left join (select * from int8_tbl offset 0) t2 on (t1.q2 = t2.q1) 2748group by t1.q2 order by 1; 2749 q2 | count 2750-------------------+------- 2751 -4567890123456789 | 0 2752 123 | 2 2753 456 | 0 2754 4567890123456789 | 6 2755(4 rows) 2756 2757select t1.q2, count(t2.*) 2758from int8_tbl t1 left join 2759 (select q1, case when q2=1 then 1 else q2 end as q2 from int8_tbl) t2 2760 on (t1.q2 = t2.q1) 2761group by t1.q2 order by 1; 2762 q2 | count 2763-------------------+------- 2764 -4567890123456789 | 0 2765 123 | 2 2766 456 | 0 2767 4567890123456789 | 6 2768(4 rows) 2769 2770-- 2771-- test incorrect failure to NULL pulled-up subexpressions 2772-- 2773begin; 2774create temp table a ( 2775 code char not null, 2776 constraint a_pk primary key (code) 2777); 2778create temp table b ( 2779 a char not null, 2780 num integer not null, 2781 constraint b_pk primary key (a, num) 2782); 2783create temp table c ( 2784 name char not null, 2785 a char, 2786 constraint c_pk primary key (name) 2787); 2788insert into a (code) values ('p'); 2789insert into a (code) values ('q'); 2790insert into b (a, num) values ('p', 1); 2791insert into b (a, num) values ('p', 2); 2792insert into c (name, a) values ('A', 'p'); 2793insert into c (name, a) values ('B', 'q'); 2794insert into c (name, a) values ('C', null); 2795select c.name, ss.code, ss.b_cnt, ss.const 2796from c left join 2797 (select a.code, coalesce(b_grp.cnt, 0) as b_cnt, -1 as const 2798 from a left join 2799 (select count(1) as cnt, b.a from b group by b.a) as b_grp 2800 on a.code = b_grp.a 2801 ) as ss 2802 on (c.a = ss.code) 2803order by c.name; 2804 name | code | b_cnt | const 2805------+------+-------+------- 2806 A | p | 2 | -1 2807 B | q | 0 | -1 2808 C | | | 2809(3 rows) 2810 2811rollback; 2812-- 2813-- test incorrect handling of placeholders that only appear in targetlists, 2814-- per bug #6154 2815-- 2816SELECT * FROM 2817( SELECT 1 as key1 ) sub1 2818LEFT JOIN 2819( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM 2820 ( SELECT 1 as key3 ) sub3 2821 LEFT JOIN 2822 ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM 2823 ( SELECT 1 as key5 ) sub5 2824 LEFT JOIN 2825 ( SELECT 2 as key6, 42 as value1 ) sub6 2826 ON sub5.key5 = sub6.key6 2827 ) sub4 2828 ON sub4.key5 = sub3.key3 2829) sub2 2830ON sub1.key1 = sub2.key3; 2831 key1 | key3 | value2 | value3 2832------+------+--------+-------- 2833 1 | 1 | 1 | 1 2834(1 row) 2835 2836-- test the path using join aliases, too 2837SELECT * FROM 2838( SELECT 1 as key1 ) sub1 2839LEFT JOIN 2840( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM 2841 ( SELECT 1 as key3 ) sub3 2842 LEFT JOIN 2843 ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM 2844 ( SELECT 1 as key5 ) sub5 2845 LEFT JOIN 2846 ( SELECT 2 as key6, 42 as value1 ) sub6 2847 ON sub5.key5 = sub6.key6 2848 ) sub4 2849 ON sub4.key5 = sub3.key3 2850) sub2 2851ON sub1.key1 = sub2.key3; 2852 key1 | key3 | value2 | value3 2853------+------+--------+-------- 2854 1 | 1 | 1 | 1 2855(1 row) 2856 2857-- 2858-- test case where a PlaceHolderVar is used as a nestloop parameter 2859-- 2860EXPLAIN (COSTS OFF) 2861SELECT qq, unique1 2862 FROM 2863 ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1 2864 FULL OUTER JOIN 2865 ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2 2866 USING (qq) 2867 INNER JOIN tenk1 c ON qq = unique2; 2868 QUERY PLAN 2869--------------------------------------------------------------------------------------------------------- 2870 Nested Loop 2871 -> Hash Full Join 2872 Hash Cond: ((COALESCE(a.q1, '0'::bigint)) = (COALESCE(b.q2, '-1'::bigint))) 2873 -> Seq Scan on int8_tbl a 2874 -> Hash 2875 -> Seq Scan on int8_tbl b 2876 -> Index Scan using tenk1_unique2 on tenk1 c 2877 Index Cond: (unique2 = COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint)))) 2878(8 rows) 2879 2880SELECT qq, unique1 2881 FROM 2882 ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1 2883 FULL OUTER JOIN 2884 ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2 2885 USING (qq) 2886 INNER JOIN tenk1 c ON qq = unique2; 2887 qq | unique1 2888-----+--------- 2889 123 | 4596 2890 123 | 4596 2891 456 | 7318 2892(3 rows) 2893 2894-- 2895-- nested nestloops can require nested PlaceHolderVars 2896-- 2897create temp table nt1 ( 2898 id int primary key, 2899 a1 boolean, 2900 a2 boolean 2901); 2902create temp table nt2 ( 2903 id int primary key, 2904 nt1_id int, 2905 b1 boolean, 2906 b2 boolean, 2907 foreign key (nt1_id) references nt1(id) 2908); 2909create temp table nt3 ( 2910 id int primary key, 2911 nt2_id int, 2912 c1 boolean, 2913 foreign key (nt2_id) references nt2(id) 2914); 2915insert into nt1 values (1,true,true); 2916insert into nt1 values (2,true,false); 2917insert into nt1 values (3,false,false); 2918insert into nt2 values (1,1,true,true); 2919insert into nt2 values (2,2,true,false); 2920insert into nt2 values (3,3,false,false); 2921insert into nt3 values (1,1,true); 2922insert into nt3 values (2,2,false); 2923insert into nt3 values (3,3,true); 2924explain (costs off) 2925select nt3.id 2926from nt3 as nt3 2927 left join 2928 (select nt2.*, (nt2.b1 and ss1.a3) AS b3 2929 from nt2 as nt2 2930 left join 2931 (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 2932 on ss1.id = nt2.nt1_id 2933 ) as ss2 2934 on ss2.id = nt3.nt2_id 2935where nt3.id = 1 and ss2.b3; 2936 QUERY PLAN 2937----------------------------------------------- 2938 Nested Loop 2939 -> Nested Loop 2940 -> Index Scan using nt3_pkey on nt3 2941 Index Cond: (id = 1) 2942 -> Index Scan using nt2_pkey on nt2 2943 Index Cond: (id = nt3.nt2_id) 2944 -> Index Only Scan using nt1_pkey on nt1 2945 Index Cond: (id = nt2.nt1_id) 2946 Filter: (nt2.b1 AND (id IS NOT NULL)) 2947(9 rows) 2948 2949select nt3.id 2950from nt3 as nt3 2951 left join 2952 (select nt2.*, (nt2.b1 and ss1.a3) AS b3 2953 from nt2 as nt2 2954 left join 2955 (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 2956 on ss1.id = nt2.nt1_id 2957 ) as ss2 2958 on ss2.id = nt3.nt2_id 2959where nt3.id = 1 and ss2.b3; 2960 id 2961---- 2962 1 2963(1 row) 2964 2965-- 2966-- test case where a PlaceHolderVar is propagated into a subquery 2967-- 2968explain (costs off) 2969select * from 2970 int8_tbl t1 left join 2971 (select q1 as x, 42 as y from int8_tbl t2) ss 2972 on t1.q2 = ss.x 2973where 2974 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) 2975order by 1,2; 2976 QUERY PLAN 2977----------------------------------------------------------- 2978 Sort 2979 Sort Key: t1.q1, t1.q2 2980 -> Hash Left Join 2981 Hash Cond: (t1.q2 = t2.q1) 2982 Filter: (1 = (SubPlan 1)) 2983 -> Seq Scan on int8_tbl t1 2984 -> Hash 2985 -> Seq Scan on int8_tbl t2 2986 SubPlan 1 2987 -> Limit 2988 -> Result 2989 One-Time Filter: ((42) IS NOT NULL) 2990 -> Seq Scan on int8_tbl t3 2991(13 rows) 2992 2993select * from 2994 int8_tbl t1 left join 2995 (select q1 as x, 42 as y from int8_tbl t2) ss 2996 on t1.q2 = ss.x 2997where 2998 1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1) 2999order by 1,2; 3000 q1 | q2 | x | y 3001------------------+------------------+------------------+---- 3002 123 | 4567890123456789 | 4567890123456789 | 42 3003 123 | 4567890123456789 | 4567890123456789 | 42 3004 123 | 4567890123456789 | 4567890123456789 | 42 3005 4567890123456789 | 123 | 123 | 42 3006 4567890123456789 | 123 | 123 | 42 3007 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 3008 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 3009 4567890123456789 | 4567890123456789 | 4567890123456789 | 42 3010(8 rows) 3011 3012-- 3013-- variant where a PlaceHolderVar is needed at a join, but not above the join 3014-- 3015explain (costs off) 3016select * from 3017 int4_tbl as i41, 3018 lateral 3019 (select 1 as x from 3020 (select i41.f1 as lat, 3021 i42.f1 as loc from 3022 int8_tbl as i81, int4_tbl as i42) as ss1 3023 right join int4_tbl as i43 on (i43.f1 > 1) 3024 where ss1.loc = ss1.lat) as ss2 3025where i41.f1 > 0; 3026 QUERY PLAN 3027-------------------------------------------------- 3028 Nested Loop 3029 -> Nested Loop 3030 -> Seq Scan on int4_tbl i41 3031 Filter: (f1 > 0) 3032 -> Nested Loop 3033 Join Filter: (i41.f1 = i42.f1) 3034 -> Seq Scan on int8_tbl i81 3035 -> Materialize 3036 -> Seq Scan on int4_tbl i42 3037 -> Materialize 3038 -> Seq Scan on int4_tbl i43 3039 Filter: (f1 > 1) 3040(12 rows) 3041 3042select * from 3043 int4_tbl as i41, 3044 lateral 3045 (select 1 as x from 3046 (select i41.f1 as lat, 3047 i42.f1 as loc from 3048 int8_tbl as i81, int4_tbl as i42) as ss1 3049 right join int4_tbl as i43 on (i43.f1 > 1) 3050 where ss1.loc = ss1.lat) as ss2 3051where i41.f1 > 0; 3052 f1 | x 3053------------+--- 3054 123456 | 1 3055 123456 | 1 3056 123456 | 1 3057 123456 | 1 3058 123456 | 1 3059 123456 | 1 3060 123456 | 1 3061 123456 | 1 3062 123456 | 1 3063 123456 | 1 3064 2147483647 | 1 3065 2147483647 | 1 3066 2147483647 | 1 3067 2147483647 | 1 3068 2147483647 | 1 3069 2147483647 | 1 3070 2147483647 | 1 3071 2147483647 | 1 3072 2147483647 | 1 3073 2147483647 | 1 3074(20 rows) 3075 3076-- 3077-- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE 3078-- 3079select * from int4_tbl a full join int4_tbl b on true; 3080 f1 | f1 3081-------------+------------- 3082 0 | 0 3083 0 | 123456 3084 0 | -123456 3085 0 | 2147483647 3086 0 | -2147483647 3087 123456 | 0 3088 123456 | 123456 3089 123456 | -123456 3090 123456 | 2147483647 3091 123456 | -2147483647 3092 -123456 | 0 3093 -123456 | 123456 3094 -123456 | -123456 3095 -123456 | 2147483647 3096 -123456 | -2147483647 3097 2147483647 | 0 3098 2147483647 | 123456 3099 2147483647 | -123456 3100 2147483647 | 2147483647 3101 2147483647 | -2147483647 3102 -2147483647 | 0 3103 -2147483647 | 123456 3104 -2147483647 | -123456 3105 -2147483647 | 2147483647 3106 -2147483647 | -2147483647 3107(25 rows) 3108 3109select * from int4_tbl a full join int4_tbl b on false; 3110 f1 | f1 3111-------------+------------- 3112 | 0 3113 | 123456 3114 | -123456 3115 | 2147483647 3116 | -2147483647 3117 0 | 3118 123456 | 3119 -123456 | 3120 2147483647 | 3121 -2147483647 | 3122(10 rows) 3123 3124-- 3125-- test for ability to use a cartesian join when necessary 3126-- 3127create temp table q1 as select 1 as q1; 3128create temp table q2 as select 0 as q2; 3129analyze q1; 3130analyze q2; 3131explain (costs off) 3132select * from 3133 tenk1 join int4_tbl on f1 = twothousand, 3134 q1, q2 3135where q1 = thousand or q2 = thousand; 3136 QUERY PLAN 3137------------------------------------------------------------------------ 3138 Hash Join 3139 Hash Cond: (tenk1.twothousand = int4_tbl.f1) 3140 -> Nested Loop 3141 -> Nested Loop 3142 -> Seq Scan on q1 3143 -> Seq Scan on q2 3144 -> Bitmap Heap Scan on tenk1 3145 Recheck Cond: ((q1.q1 = thousand) OR (q2.q2 = thousand)) 3146 -> BitmapOr 3147 -> Bitmap Index Scan on tenk1_thous_tenthous 3148 Index Cond: (thousand = q1.q1) 3149 -> Bitmap Index Scan on tenk1_thous_tenthous 3150 Index Cond: (thousand = q2.q2) 3151 -> Hash 3152 -> Seq Scan on int4_tbl 3153(15 rows) 3154 3155explain (costs off) 3156select * from 3157 tenk1 join int4_tbl on f1 = twothousand, 3158 q1, q2 3159where thousand = (q1 + q2); 3160 QUERY PLAN 3161-------------------------------------------------------------- 3162 Hash Join 3163 Hash Cond: (tenk1.twothousand = int4_tbl.f1) 3164 -> Nested Loop 3165 -> Nested Loop 3166 -> Seq Scan on q1 3167 -> Seq Scan on q2 3168 -> Bitmap Heap Scan on tenk1 3169 Recheck Cond: (thousand = (q1.q1 + q2.q2)) 3170 -> Bitmap Index Scan on tenk1_thous_tenthous 3171 Index Cond: (thousand = (q1.q1 + q2.q2)) 3172 -> Hash 3173 -> Seq Scan on int4_tbl 3174(12 rows) 3175 3176-- 3177-- test ability to generate a suitable plan for a star-schema query 3178-- 3179explain (costs off) 3180select * from 3181 tenk1, int8_tbl a, int8_tbl b 3182where thousand = a.q1 and tenthous = b.q1 and a.q2 = 1 and b.q2 = 2; 3183 QUERY PLAN 3184--------------------------------------------------------------------- 3185 Nested Loop 3186 -> Seq Scan on int8_tbl b 3187 Filter: (q2 = 2) 3188 -> Nested Loop 3189 -> Seq Scan on int8_tbl a 3190 Filter: (q2 = 1) 3191 -> Index Scan using tenk1_thous_tenthous on tenk1 3192 Index Cond: ((thousand = a.q1) AND (tenthous = b.q1)) 3193(8 rows) 3194 3195-- 3196-- test a corner case in which we shouldn't apply the star-schema optimization 3197-- 3198explain (costs off) 3199select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from 3200 tenk1 t1 3201 inner join int4_tbl i1 3202 left join (select v1.x2, v2.y1, 11 AS d1 3203 from (select 1,0 from onerow) v1(x1,x2) 3204 left join (select 3,1 from onerow) v2(y1,y2) 3205 on v1.x1 = v2.y2) subq1 3206 on (i1.f1 = subq1.x2) 3207 on (t1.unique2 = subq1.d1) 3208 left join tenk1 t2 3209 on (subq1.y1 = t2.unique1) 3210where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; 3211 QUERY PLAN 3212----------------------------------------------------------------------- 3213 Nested Loop 3214 -> Nested Loop 3215 Join Filter: (t1.stringu1 > t2.stringu2) 3216 -> Nested Loop 3217 -> Nested Loop 3218 -> Seq Scan on onerow 3219 -> Seq Scan on onerow onerow_1 3220 -> Index Scan using tenk1_unique2 on tenk1 t1 3221 Index Cond: ((unique2 = (11)) AND (unique2 < 42)) 3222 -> Index Scan using tenk1_unique1 on tenk1 t2 3223 Index Cond: (unique1 = (3)) 3224 -> Seq Scan on int4_tbl i1 3225 Filter: (f1 = 0) 3226(13 rows) 3227 3228select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from 3229 tenk1 t1 3230 inner join int4_tbl i1 3231 left join (select v1.x2, v2.y1, 11 AS d1 3232 from (select 1,0 from onerow) v1(x1,x2) 3233 left join (select 3,1 from onerow) v2(y1,y2) 3234 on v1.x1 = v2.y2) subq1 3235 on (i1.f1 = subq1.x2) 3236 on (t1.unique2 = subq1.d1) 3237 left join tenk1 t2 3238 on (subq1.y1 = t2.unique1) 3239where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; 3240 unique2 | stringu1 | unique1 | stringu2 3241---------+----------+---------+---------- 3242 11 | WFAAAA | 3 | LKIAAA 3243(1 row) 3244 3245-- variant that isn't quite a star-schema case 3246select ss1.d1 from 3247 tenk1 as t1 3248 inner join tenk1 as t2 3249 on t1.tenthous = t2.ten 3250 inner join 3251 int8_tbl as i8 3252 left join int4_tbl as i4 3253 inner join (select 64::information_schema.cardinal_number as d1 3254 from tenk1 t3, 3255 lateral (select abs(t3.unique1) + random()) ss0(x) 3256 where t3.fivethous < 0) as ss1 3257 on i4.f1 = ss1.d1 3258 on i8.q1 = i4.f1 3259 on t1.tenthous = ss1.d1 3260where t1.unique1 < i4.f1; 3261 d1 3262---- 3263(0 rows) 3264 3265-- this variant is foldable by the remove-useless-RESULT-RTEs code 3266explain (costs off) 3267select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from 3268 tenk1 t1 3269 inner join int4_tbl i1 3270 left join (select v1.x2, v2.y1, 11 AS d1 3271 from (values(1,0)) v1(x1,x2) 3272 left join (values(3,1)) v2(y1,y2) 3273 on v1.x1 = v2.y2) subq1 3274 on (i1.f1 = subq1.x2) 3275 on (t1.unique2 = subq1.d1) 3276 left join tenk1 t2 3277 on (subq1.y1 = t2.unique1) 3278where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; 3279 QUERY PLAN 3280----------------------------------------------------------------- 3281 Nested Loop 3282 Join Filter: (t1.stringu1 > t2.stringu2) 3283 -> Nested Loop 3284 -> Seq Scan on int4_tbl i1 3285 Filter: (f1 = 0) 3286 -> Index Scan using tenk1_unique2 on tenk1 t1 3287 Index Cond: ((unique2 = (11)) AND (unique2 < 42)) 3288 -> Index Scan using tenk1_unique1 on tenk1 t2 3289 Index Cond: (unique1 = (3)) 3290(9 rows) 3291 3292select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from 3293 tenk1 t1 3294 inner join int4_tbl i1 3295 left join (select v1.x2, v2.y1, 11 AS d1 3296 from (values(1,0)) v1(x1,x2) 3297 left join (values(3,1)) v2(y1,y2) 3298 on v1.x1 = v2.y2) subq1 3299 on (i1.f1 = subq1.x2) 3300 on (t1.unique2 = subq1.d1) 3301 left join tenk1 t2 3302 on (subq1.y1 = t2.unique1) 3303where t1.unique2 < 42 and t1.stringu1 > t2.stringu2; 3304 unique2 | stringu1 | unique1 | stringu2 3305---------+----------+---------+---------- 3306 11 | WFAAAA | 3 | LKIAAA 3307(1 row) 3308 3309-- Here's a variant that we can't fold too aggressively, though, 3310-- or we end up with noplace to evaluate the lateral PHV 3311explain (verbose, costs off) 3312select * from 3313 (select 1 as x) ss1 left join (select 2 as y) ss2 on (true), 3314 lateral (select ss2.y as z limit 1) ss3; 3315 QUERY PLAN 3316--------------------------- 3317 Nested Loop 3318 Output: 1, (2), ((2)) 3319 -> Result 3320 Output: 2 3321 -> Limit 3322 Output: ((2)) 3323 -> Result 3324 Output: (2) 3325(8 rows) 3326 3327select * from 3328 (select 1 as x) ss1 left join (select 2 as y) ss2 on (true), 3329 lateral (select ss2.y as z limit 1) ss3; 3330 x | y | z 3331---+---+--- 3332 1 | 2 | 2 3333(1 row) 3334 3335-- Test proper handling of appendrel PHVs during useless-RTE removal 3336explain (costs off) 3337select * from 3338 (select 0 as z) as t1 3339 left join 3340 (select true as a) as t2 3341 on true, 3342 lateral (select true as b 3343 union all 3344 select a as b) as t3 3345where b; 3346 QUERY PLAN 3347--------------------------------------- 3348 Nested Loop 3349 -> Result 3350 -> Append 3351 -> Result 3352 -> Result 3353 One-Time Filter: (true) 3354(6 rows) 3355 3356select * from 3357 (select 0 as z) as t1 3358 left join 3359 (select true as a) as t2 3360 on true, 3361 lateral (select true as b 3362 union all 3363 select a as b) as t3 3364where b; 3365 z | a | b 3366---+---+--- 3367 0 | t | t 3368 0 | t | t 3369(2 rows) 3370 3371-- 3372-- test inlining of immutable functions 3373-- 3374create function f_immutable_int4(i integer) returns integer as 3375$$ begin return i; end; $$ language plpgsql immutable; 3376-- check optimization of function scan with join 3377explain (costs off) 3378select unique1 from tenk1, (select * from f_immutable_int4(1) x) x 3379where x = unique1; 3380 QUERY PLAN 3381---------------------------------------------- 3382 Index Only Scan using tenk1_unique1 on tenk1 3383 Index Cond: (unique1 = 1) 3384(2 rows) 3385 3386explain (verbose, costs off) 3387select unique1, x.* 3388from tenk1, (select *, random() from f_immutable_int4(1) x) x 3389where x = unique1; 3390 QUERY PLAN 3391----------------------------------------------------------- 3392 Nested Loop 3393 Output: tenk1.unique1, (1), (random()) 3394 -> Result 3395 Output: 1, random() 3396 -> Index Only Scan using tenk1_unique1 on public.tenk1 3397 Output: tenk1.unique1 3398 Index Cond: (tenk1.unique1 = (1)) 3399(7 rows) 3400 3401explain (costs off) 3402select unique1 from tenk1, f_immutable_int4(1) x where x = unique1; 3403 QUERY PLAN 3404---------------------------------------------- 3405 Index Only Scan using tenk1_unique1 on tenk1 3406 Index Cond: (unique1 = 1) 3407(2 rows) 3408 3409explain (costs off) 3410select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1; 3411 QUERY PLAN 3412---------------------------------------------- 3413 Index Only Scan using tenk1_unique1 on tenk1 3414 Index Cond: (unique1 = 1) 3415(2 rows) 3416 3417explain (costs off) 3418select unique1 from tenk1, lateral f_immutable_int4(1) x where x in (select 17); 3419 QUERY PLAN 3420-------------------------- 3421 Result 3422 One-Time Filter: false 3423(2 rows) 3424 3425explain (costs off) 3426select unique1, x from tenk1 join f_immutable_int4(1) x on unique1 = x; 3427 QUERY PLAN 3428---------------------------------------------- 3429 Index Only Scan using tenk1_unique1 on tenk1 3430 Index Cond: (unique1 = 1) 3431(2 rows) 3432 3433explain (costs off) 3434select unique1, x from tenk1 left join f_immutable_int4(1) x on unique1 = x; 3435 QUERY PLAN 3436---------------------------------------------------- 3437 Nested Loop Left Join 3438 Join Filter: (tenk1.unique1 = 1) 3439 -> Index Only Scan using tenk1_unique1 on tenk1 3440 -> Materialize 3441 -> Result 3442(5 rows) 3443 3444explain (costs off) 3445select unique1, x from tenk1 right join f_immutable_int4(1) x on unique1 = x; 3446 QUERY PLAN 3447---------------------------------------------------- 3448 Nested Loop Left Join 3449 -> Result 3450 -> Index Only Scan using tenk1_unique1 on tenk1 3451 Index Cond: (unique1 = 1) 3452(4 rows) 3453 3454explain (costs off) 3455select unique1, x from tenk1 full join f_immutable_int4(1) x on unique1 = x; 3456 QUERY PLAN 3457---------------------------------------------------- 3458 Merge Full Join 3459 Merge Cond: (tenk1.unique1 = (1)) 3460 -> Index Only Scan using tenk1_unique1 on tenk1 3461 -> Sort 3462 Sort Key: (1) 3463 -> Result 3464(6 rows) 3465 3466-- check that pullup of a const function allows further const-folding 3467explain (costs off) 3468select unique1 from tenk1, f_immutable_int4(1) x where x = 42; 3469 QUERY PLAN 3470-------------------------- 3471 Result 3472 One-Time Filter: false 3473(2 rows) 3474 3475-- test inlining of immutable functions with PlaceHolderVars 3476explain (costs off) 3477select nt3.id 3478from nt3 as nt3 3479 left join 3480 (select nt2.*, (nt2.b1 or i4 = 42) AS b3 3481 from nt2 as nt2 3482 left join 3483 f_immutable_int4(0) i4 3484 on i4 = nt2.nt1_id 3485 ) as ss2 3486 on ss2.id = nt3.nt2_id 3487where nt3.id = 1 and ss2.b3; 3488 QUERY PLAN 3489---------------------------------------------- 3490 Nested Loop Left Join 3491 Filter: ((nt2.b1 OR ((0) = 42))) 3492 -> Index Scan using nt3_pkey on nt3 3493 Index Cond: (id = 1) 3494 -> Nested Loop Left Join 3495 Join Filter: (0 = nt2.nt1_id) 3496 -> Index Scan using nt2_pkey on nt2 3497 Index Cond: (id = nt3.nt2_id) 3498 -> Result 3499(9 rows) 3500 3501drop function f_immutable_int4(int); 3502-- test inlining when function returns composite 3503create function mki8(bigint, bigint) returns int8_tbl as 3504$$select row($1,$2)::int8_tbl$$ language sql; 3505create function mki4(int) returns int4_tbl as 3506$$select row($1)::int4_tbl$$ language sql; 3507explain (verbose, costs off) 3508select * from mki8(1,2); 3509 QUERY PLAN 3510------------------------------------ 3511 Function Scan on mki8 3512 Output: q1, q2 3513 Function Call: '(1,2)'::int8_tbl 3514(3 rows) 3515 3516select * from mki8(1,2); 3517 q1 | q2 3518----+---- 3519 1 | 2 3520(1 row) 3521 3522explain (verbose, costs off) 3523select * from mki4(42); 3524 QUERY PLAN 3525----------------------------------- 3526 Function Scan on mki4 3527 Output: f1 3528 Function Call: '(42)'::int4_tbl 3529(3 rows) 3530 3531select * from mki4(42); 3532 f1 3533---- 3534 42 3535(1 row) 3536 3537drop function mki8(bigint, bigint); 3538drop function mki4(int); 3539-- 3540-- test extraction of restriction OR clauses from join OR clause 3541-- (we used to only do this for indexable clauses) 3542-- 3543explain (costs off) 3544select * from tenk1 a join tenk1 b on 3545 (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.hundred = 4); 3546 QUERY PLAN 3547------------------------------------------------------------------------------------------------- 3548 Nested Loop 3549 Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.hundred = 4))) 3550 -> Bitmap Heap Scan on tenk1 b 3551 Recheck Cond: ((unique1 = 2) OR (hundred = 4)) 3552 -> BitmapOr 3553 -> Bitmap Index Scan on tenk1_unique1 3554 Index Cond: (unique1 = 2) 3555 -> Bitmap Index Scan on tenk1_hundred 3556 Index Cond: (hundred = 4) 3557 -> Materialize 3558 -> Bitmap Heap Scan on tenk1 a 3559 Recheck Cond: ((unique1 = 1) OR (unique2 = 3)) 3560 -> BitmapOr 3561 -> Bitmap Index Scan on tenk1_unique1 3562 Index Cond: (unique1 = 1) 3563 -> Bitmap Index Scan on tenk1_unique2 3564 Index Cond: (unique2 = 3) 3565(17 rows) 3566 3567explain (costs off) 3568select * from tenk1 a join tenk1 b on 3569 (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.ten = 4); 3570 QUERY PLAN 3571--------------------------------------------------------------------------------------------- 3572 Nested Loop 3573 Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.ten = 4))) 3574 -> Seq Scan on tenk1 b 3575 Filter: ((unique1 = 2) OR (ten = 4)) 3576 -> Materialize 3577 -> Bitmap Heap Scan on tenk1 a 3578 Recheck Cond: ((unique1 = 1) OR (unique2 = 3)) 3579 -> BitmapOr 3580 -> Bitmap Index Scan on tenk1_unique1 3581 Index Cond: (unique1 = 1) 3582 -> Bitmap Index Scan on tenk1_unique2 3583 Index Cond: (unique2 = 3) 3584(12 rows) 3585 3586explain (costs off) 3587select * from tenk1 a join tenk1 b on 3588 (a.unique1 = 1 and b.unique1 = 2) or 3589 ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4); 3590 QUERY PLAN 3591---------------------------------------------------------------------------------------------------------------------- 3592 Nested Loop 3593 Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4))) 3594 -> Bitmap Heap Scan on tenk1 b 3595 Recheck Cond: ((unique1 = 2) OR (hundred = 4)) 3596 -> BitmapOr 3597 -> Bitmap Index Scan on tenk1_unique1 3598 Index Cond: (unique1 = 2) 3599 -> Bitmap Index Scan on tenk1_hundred 3600 Index Cond: (hundred = 4) 3601 -> Materialize 3602 -> Bitmap Heap Scan on tenk1 a 3603 Recheck Cond: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7)) 3604 -> BitmapOr 3605 -> Bitmap Index Scan on tenk1_unique1 3606 Index Cond: (unique1 = 1) 3607 -> Bitmap Index Scan on tenk1_unique2 3608 Index Cond: (unique2 = 3) 3609 -> Bitmap Index Scan on tenk1_unique2 3610 Index Cond: (unique2 = 7) 3611(19 rows) 3612 3613-- 3614-- test placement of movable quals in a parameterized join tree 3615-- 3616explain (costs off) 3617select * from tenk1 t1 left join 3618 (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2) 3619 on t1.hundred = t2.hundred and t1.ten = t3.ten 3620where t1.unique1 = 1; 3621 QUERY PLAN 3622-------------------------------------------------------- 3623 Nested Loop Left Join 3624 -> Index Scan using tenk1_unique1 on tenk1 t1 3625 Index Cond: (unique1 = 1) 3626 -> Nested Loop 3627 Join Filter: (t1.ten = t3.ten) 3628 -> Bitmap Heap Scan on tenk1 t2 3629 Recheck Cond: (t1.hundred = hundred) 3630 -> Bitmap Index Scan on tenk1_hundred 3631 Index Cond: (hundred = t1.hundred) 3632 -> Index Scan using tenk1_unique2 on tenk1 t3 3633 Index Cond: (unique2 = t2.thousand) 3634(11 rows) 3635 3636explain (costs off) 3637select * from tenk1 t1 left join 3638 (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2) 3639 on t1.hundred = t2.hundred and t1.ten + t2.ten = t3.ten 3640where t1.unique1 = 1; 3641 QUERY PLAN 3642-------------------------------------------------------- 3643 Nested Loop Left Join 3644 -> Index Scan using tenk1_unique1 on tenk1 t1 3645 Index Cond: (unique1 = 1) 3646 -> Nested Loop 3647 Join Filter: ((t1.ten + t2.ten) = t3.ten) 3648 -> Bitmap Heap Scan on tenk1 t2 3649 Recheck Cond: (t1.hundred = hundred) 3650 -> Bitmap Index Scan on tenk1_hundred 3651 Index Cond: (hundred = t1.hundred) 3652 -> Index Scan using tenk1_unique2 on tenk1 t3 3653 Index Cond: (unique2 = t2.thousand) 3654(11 rows) 3655 3656explain (costs off) 3657select count(*) from 3658 tenk1 a join tenk1 b on a.unique1 = b.unique2 3659 left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand 3660 join int4_tbl on b.thousand = f1; 3661 QUERY PLAN 3662------------------------------------------------------------------------- 3663 Aggregate 3664 -> Nested Loop Left Join 3665 Join Filter: (a.unique2 = b.unique1) 3666 -> Nested Loop 3667 -> Nested Loop 3668 -> Seq Scan on int4_tbl 3669 -> Bitmap Heap Scan on tenk1 b 3670 Recheck Cond: (thousand = int4_tbl.f1) 3671 -> Bitmap Index Scan on tenk1_thous_tenthous 3672 Index Cond: (thousand = int4_tbl.f1) 3673 -> Index Scan using tenk1_unique1 on tenk1 a 3674 Index Cond: (unique1 = b.unique2) 3675 -> Index Only Scan using tenk1_thous_tenthous on tenk1 c 3676 Index Cond: (thousand = a.thousand) 3677(14 rows) 3678 3679select count(*) from 3680 tenk1 a join tenk1 b on a.unique1 = b.unique2 3681 left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand 3682 join int4_tbl on b.thousand = f1; 3683 count 3684------- 3685 10 3686(1 row) 3687 3688explain (costs off) 3689select b.unique1 from 3690 tenk1 a join tenk1 b on a.unique1 = b.unique2 3691 left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand 3692 join int4_tbl i1 on b.thousand = f1 3693 right join int4_tbl i2 on i2.f1 = b.tenthous 3694 order by 1; 3695 QUERY PLAN 3696----------------------------------------------------------------------------------------- 3697 Sort 3698 Sort Key: b.unique1 3699 -> Nested Loop Left Join 3700 -> Seq Scan on int4_tbl i2 3701 -> Nested Loop Left Join 3702 Join Filter: (b.unique1 = 42) 3703 -> Nested Loop 3704 -> Nested Loop 3705 -> Seq Scan on int4_tbl i1 3706 -> Index Scan using tenk1_thous_tenthous on tenk1 b 3707 Index Cond: ((thousand = i1.f1) AND (tenthous = i2.f1)) 3708 -> Index Scan using tenk1_unique1 on tenk1 a 3709 Index Cond: (unique1 = b.unique2) 3710 -> Index Only Scan using tenk1_thous_tenthous on tenk1 c 3711 Index Cond: (thousand = a.thousand) 3712(15 rows) 3713 3714select b.unique1 from 3715 tenk1 a join tenk1 b on a.unique1 = b.unique2 3716 left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand 3717 join int4_tbl i1 on b.thousand = f1 3718 right join int4_tbl i2 on i2.f1 = b.tenthous 3719 order by 1; 3720 unique1 3721--------- 3722 0 3723 3724 3725 3726 3727(5 rows) 3728 3729explain (costs off) 3730select * from 3731( 3732 select unique1, q1, coalesce(unique1, -1) + q1 as fault 3733 from int8_tbl left join tenk1 on (q2 = unique2) 3734) ss 3735where fault = 122 3736order by fault; 3737 QUERY PLAN 3738-------------------------------------------------------------------------- 3739 Nested Loop Left Join 3740 Filter: ((COALESCE(tenk1.unique1, '-1'::integer) + int8_tbl.q1) = 122) 3741 -> Seq Scan on int8_tbl 3742 -> Index Scan using tenk1_unique2 on tenk1 3743 Index Cond: (unique2 = int8_tbl.q2) 3744(5 rows) 3745 3746select * from 3747( 3748 select unique1, q1, coalesce(unique1, -1) + q1 as fault 3749 from int8_tbl left join tenk1 on (q2 = unique2) 3750) ss 3751where fault = 122 3752order by fault; 3753 unique1 | q1 | fault 3754---------+-----+------- 3755 | 123 | 122 3756(1 row) 3757 3758explain (costs off) 3759select * from 3760(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys) 3761left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x 3762left join unnest(v1ys) as u1(u1y) on u1y = v2y; 3763 QUERY PLAN 3764------------------------------------------------------------- 3765 Nested Loop Left Join 3766 -> Values Scan on "*VALUES*" 3767 -> Hash Right Join 3768 Hash Cond: (u1.u1y = "*VALUES*_1".column2) 3769 Filter: ("*VALUES*_1".column1 = "*VALUES*".column1) 3770 -> Function Scan on unnest u1 3771 -> Hash 3772 -> Values Scan on "*VALUES*_1" 3773(8 rows) 3774 3775select * from 3776(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys) 3777left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x 3778left join unnest(v1ys) as u1(u1y) on u1y = v2y; 3779 v1x | v1ys | v2x | v2y | u1y 3780-----+---------+-----+-----+----- 3781 1 | {10,20} | 1 | 10 | 10 3782 2 | {20,30} | 2 | 20 | 20 3783(2 rows) 3784 3785-- 3786-- test handling of potential equivalence clauses above outer joins 3787-- 3788explain (costs off) 3789select q1, unique2, thousand, hundred 3790 from int8_tbl a left join tenk1 b on q1 = unique2 3791 where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123); 3792 QUERY PLAN 3793-------------------------------------------------------------------------------------- 3794 Nested Loop Left Join 3795 Filter: ((COALESCE(b.thousand, 123) = a.q1) AND (a.q1 = COALESCE(b.hundred, 123))) 3796 -> Seq Scan on int8_tbl a 3797 -> Index Scan using tenk1_unique2 on tenk1 b 3798 Index Cond: (unique2 = a.q1) 3799(5 rows) 3800 3801select q1, unique2, thousand, hundred 3802 from int8_tbl a left join tenk1 b on q1 = unique2 3803 where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123); 3804 q1 | unique2 | thousand | hundred 3805----+---------+----------+--------- 3806(0 rows) 3807 3808explain (costs off) 3809select f1, unique2, case when unique2 is null then f1 else 0 end 3810 from int4_tbl a left join tenk1 b on f1 = unique2 3811 where (case when unique2 is null then f1 else 0 end) = 0; 3812 QUERY PLAN 3813-------------------------------------------------------------------- 3814 Nested Loop Left Join 3815 Filter: (CASE WHEN (b.unique2 IS NULL) THEN a.f1 ELSE 0 END = 0) 3816 -> Seq Scan on int4_tbl a 3817 -> Index Only Scan using tenk1_unique2 on tenk1 b 3818 Index Cond: (unique2 = a.f1) 3819(5 rows) 3820 3821select f1, unique2, case when unique2 is null then f1 else 0 end 3822 from int4_tbl a left join tenk1 b on f1 = unique2 3823 where (case when unique2 is null then f1 else 0 end) = 0; 3824 f1 | unique2 | case 3825----+---------+------ 3826 0 | 0 | 0 3827(1 row) 3828 3829-- 3830-- another case with equivalence clauses above outer joins (bug #8591) 3831-- 3832explain (costs off) 3833select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) 3834 from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) 3835 where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; 3836 QUERY PLAN 3837--------------------------------------------------------------------------------------------- 3838 Nested Loop Left Join 3839 -> Nested Loop Left Join 3840 Filter: (COALESCE(b.twothousand, a.twothousand) = 44) 3841 -> Index Scan using tenk1_unique2 on tenk1 a 3842 Index Cond: (unique2 < 10) 3843 -> Bitmap Heap Scan on tenk1 b 3844 Recheck Cond: (thousand = a.unique1) 3845 -> Bitmap Index Scan on tenk1_thous_tenthous 3846 Index Cond: (thousand = a.unique1) 3847 -> Index Scan using tenk1_unique2 on tenk1 c 3848 Index Cond: ((unique2 = COALESCE(b.twothousand, a.twothousand)) AND (unique2 = 44)) 3849(11 rows) 3850 3851select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand) 3852 from tenk1 a left join tenk1 b on b.thousand = a.unique1 left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand) 3853 where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44; 3854 unique1 | unique1 | unique1 | coalesce 3855---------+---------+---------+---------- 3856(0 rows) 3857 3858-- 3859-- check handling of join aliases when flattening multiple levels of subquery 3860-- 3861explain (verbose, costs off) 3862select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from 3863 (values (0),(1)) foo1(join_key) 3864left join 3865 (select join_key, bug_field from 3866 (select ss1.join_key, ss1.bug_field from 3867 (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1 3868 ) foo2 3869 left join 3870 (select unique2 as join_key from tenk1 i2) ss2 3871 using (join_key) 3872 ) foo3 3873using (join_key); 3874 QUERY PLAN 3875-------------------------------------------------------------------------- 3876 Nested Loop Left Join 3877 Output: "*VALUES*".column1, i1.f1, (666) 3878 Join Filter: ("*VALUES*".column1 = i1.f1) 3879 -> Values Scan on "*VALUES*" 3880 Output: "*VALUES*".column1 3881 -> Materialize 3882 Output: i1.f1, (666) 3883 -> Nested Loop Left Join 3884 Output: i1.f1, 666 3885 -> Seq Scan on public.int4_tbl i1 3886 Output: i1.f1 3887 -> Index Only Scan using tenk1_unique2 on public.tenk1 i2 3888 Output: i2.unique2 3889 Index Cond: (i2.unique2 = i1.f1) 3890(14 rows) 3891 3892select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from 3893 (values (0),(1)) foo1(join_key) 3894left join 3895 (select join_key, bug_field from 3896 (select ss1.join_key, ss1.bug_field from 3897 (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1 3898 ) foo2 3899 left join 3900 (select unique2 as join_key from tenk1 i2) ss2 3901 using (join_key) 3902 ) foo3 3903using (join_key); 3904 foo1_id | foo3_id | bug_field 3905---------+---------+----------- 3906 0 | 0 | 666 3907 1 | | 3908(2 rows) 3909 3910-- 3911-- test successful handling of nested outer joins with degenerate join quals 3912-- 3913explain (verbose, costs off) 3914select t1.* from 3915 text_tbl t1 3916 left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 3917 left join int8_tbl i8 3918 left join (select *, null::int as d2 from int8_tbl i8b2) b2 3919 on (i8.q1 = b2.q1) 3920 on (b2.d2 = b1.q2) 3921 on (t1.f1 = b1.d1) 3922 left join int4_tbl i4 3923 on (i8.q2 = i4.f1); 3924 QUERY PLAN 3925---------------------------------------------------------------------- 3926 Hash Left Join 3927 Output: t1.f1 3928 Hash Cond: (i8.q2 = i4.f1) 3929 -> Nested Loop Left Join 3930 Output: t1.f1, i8.q2 3931 Join Filter: (t1.f1 = '***'::text) 3932 -> Seq Scan on public.text_tbl t1 3933 Output: t1.f1 3934 -> Materialize 3935 Output: i8.q2 3936 -> Hash Right Join 3937 Output: i8.q2 3938 Hash Cond: ((NULL::integer) = i8b1.q2) 3939 -> Hash Join 3940 Output: i8.q2, (NULL::integer) 3941 Hash Cond: (i8.q1 = i8b2.q1) 3942 -> Seq Scan on public.int8_tbl i8 3943 Output: i8.q1, i8.q2 3944 -> Hash 3945 Output: i8b2.q1, (NULL::integer) 3946 -> Seq Scan on public.int8_tbl i8b2 3947 Output: i8b2.q1, NULL::integer 3948 -> Hash 3949 Output: i8b1.q2 3950 -> Seq Scan on public.int8_tbl i8b1 3951 Output: i8b1.q2 3952 -> Hash 3953 Output: i4.f1 3954 -> Seq Scan on public.int4_tbl i4 3955 Output: i4.f1 3956(30 rows) 3957 3958select t1.* from 3959 text_tbl t1 3960 left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 3961 left join int8_tbl i8 3962 left join (select *, null::int as d2 from int8_tbl i8b2) b2 3963 on (i8.q1 = b2.q1) 3964 on (b2.d2 = b1.q2) 3965 on (t1.f1 = b1.d1) 3966 left join int4_tbl i4 3967 on (i8.q2 = i4.f1); 3968 f1 3969------------------- 3970 doh! 3971 hi de ho neighbor 3972(2 rows) 3973 3974explain (verbose, costs off) 3975select t1.* from 3976 text_tbl t1 3977 left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 3978 left join int8_tbl i8 3979 left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2 3980 on (i8.q1 = b2.q1) 3981 on (b2.d2 = b1.q2) 3982 on (t1.f1 = b1.d1) 3983 left join int4_tbl i4 3984 on (i8.q2 = i4.f1); 3985 QUERY PLAN 3986---------------------------------------------------------------------------- 3987 Hash Left Join 3988 Output: t1.f1 3989 Hash Cond: (i8.q2 = i4.f1) 3990 -> Nested Loop Left Join 3991 Output: t1.f1, i8.q2 3992 Join Filter: (t1.f1 = '***'::text) 3993 -> Seq Scan on public.text_tbl t1 3994 Output: t1.f1 3995 -> Materialize 3996 Output: i8.q2 3997 -> Hash Right Join 3998 Output: i8.q2 3999 Hash Cond: ((NULL::integer) = i8b1.q2) 4000 -> Hash Right Join 4001 Output: i8.q2, (NULL::integer) 4002 Hash Cond: (i8b2.q1 = i8.q1) 4003 -> Nested Loop 4004 Output: i8b2.q1, NULL::integer 4005 -> Seq Scan on public.int8_tbl i8b2 4006 Output: i8b2.q1, i8b2.q2 4007 -> Materialize 4008 -> Seq Scan on public.int4_tbl i4b2 4009 -> Hash 4010 Output: i8.q1, i8.q2 4011 -> Seq Scan on public.int8_tbl i8 4012 Output: i8.q1, i8.q2 4013 -> Hash 4014 Output: i8b1.q2 4015 -> Seq Scan on public.int8_tbl i8b1 4016 Output: i8b1.q2 4017 -> Hash 4018 Output: i4.f1 4019 -> Seq Scan on public.int4_tbl i4 4020 Output: i4.f1 4021(34 rows) 4022 4023select t1.* from 4024 text_tbl t1 4025 left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 4026 left join int8_tbl i8 4027 left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2 4028 on (i8.q1 = b2.q1) 4029 on (b2.d2 = b1.q2) 4030 on (t1.f1 = b1.d1) 4031 left join int4_tbl i4 4032 on (i8.q2 = i4.f1); 4033 f1 4034------------------- 4035 doh! 4036 hi de ho neighbor 4037(2 rows) 4038 4039explain (verbose, costs off) 4040select t1.* from 4041 text_tbl t1 4042 left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 4043 left join int8_tbl i8 4044 left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2 4045 where q1 = f1) b2 4046 on (i8.q1 = b2.q1) 4047 on (b2.d2 = b1.q2) 4048 on (t1.f1 = b1.d1) 4049 left join int4_tbl i4 4050 on (i8.q2 = i4.f1); 4051 QUERY PLAN 4052---------------------------------------------------------------------------- 4053 Hash Left Join 4054 Output: t1.f1 4055 Hash Cond: (i8.q2 = i4.f1) 4056 -> Nested Loop Left Join 4057 Output: t1.f1, i8.q2 4058 Join Filter: (t1.f1 = '***'::text) 4059 -> Seq Scan on public.text_tbl t1 4060 Output: t1.f1 4061 -> Materialize 4062 Output: i8.q2 4063 -> Hash Right Join 4064 Output: i8.q2 4065 Hash Cond: ((NULL::integer) = i8b1.q2) 4066 -> Hash Right Join 4067 Output: i8.q2, (NULL::integer) 4068 Hash Cond: (i8b2.q1 = i8.q1) 4069 -> Hash Join 4070 Output: i8b2.q1, NULL::integer 4071 Hash Cond: (i8b2.q1 = i4b2.f1) 4072 -> Seq Scan on public.int8_tbl i8b2 4073 Output: i8b2.q1, i8b2.q2 4074 -> Hash 4075 Output: i4b2.f1 4076 -> Seq Scan on public.int4_tbl i4b2 4077 Output: i4b2.f1 4078 -> Hash 4079 Output: i8.q1, i8.q2 4080 -> Seq Scan on public.int8_tbl i8 4081 Output: i8.q1, i8.q2 4082 -> Hash 4083 Output: i8b1.q2 4084 -> Seq Scan on public.int8_tbl i8b1 4085 Output: i8b1.q2 4086 -> Hash 4087 Output: i4.f1 4088 -> Seq Scan on public.int4_tbl i4 4089 Output: i4.f1 4090(37 rows) 4091 4092select t1.* from 4093 text_tbl t1 4094 left join (select *, '***'::text as d1 from int8_tbl i8b1) b1 4095 left join int8_tbl i8 4096 left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2 4097 where q1 = f1) b2 4098 on (i8.q1 = b2.q1) 4099 on (b2.d2 = b1.q2) 4100 on (t1.f1 = b1.d1) 4101 left join int4_tbl i4 4102 on (i8.q2 = i4.f1); 4103 f1 4104------------------- 4105 doh! 4106 hi de ho neighbor 4107(2 rows) 4108 4109explain (verbose, costs off) 4110select * from 4111 text_tbl t1 4112 inner join int8_tbl i8 4113 on i8.q2 = 456 4114 right join text_tbl t2 4115 on t1.f1 = 'doh!' 4116 left join int4_tbl i4 4117 on i8.q1 = i4.f1; 4118 QUERY PLAN 4119-------------------------------------------------------- 4120 Nested Loop Left Join 4121 Output: t1.f1, i8.q1, i8.q2, t2.f1, i4.f1 4122 -> Seq Scan on public.text_tbl t2 4123 Output: t2.f1 4124 -> Materialize 4125 Output: i8.q1, i8.q2, i4.f1, t1.f1 4126 -> Nested Loop 4127 Output: i8.q1, i8.q2, i4.f1, t1.f1 4128 -> Nested Loop Left Join 4129 Output: i8.q1, i8.q2, i4.f1 4130 Join Filter: (i8.q1 = i4.f1) 4131 -> Seq Scan on public.int8_tbl i8 4132 Output: i8.q1, i8.q2 4133 Filter: (i8.q2 = 456) 4134 -> Seq Scan on public.int4_tbl i4 4135 Output: i4.f1 4136 -> Seq Scan on public.text_tbl t1 4137 Output: t1.f1 4138 Filter: (t1.f1 = 'doh!'::text) 4139(19 rows) 4140 4141select * from 4142 text_tbl t1 4143 inner join int8_tbl i8 4144 on i8.q2 = 456 4145 right join text_tbl t2 4146 on t1.f1 = 'doh!' 4147 left join int4_tbl i4 4148 on i8.q1 = i4.f1; 4149 f1 | q1 | q2 | f1 | f1 4150------+-----+-----+-------------------+---- 4151 doh! | 123 | 456 | doh! | 4152 doh! | 123 | 456 | hi de ho neighbor | 4153(2 rows) 4154 4155-- 4156-- test for appropriate join order in the presence of lateral references 4157-- 4158explain (verbose, costs off) 4159select * from 4160 text_tbl t1 4161 left join int8_tbl i8 4162 on i8.q2 = 123, 4163 lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss 4164where t1.f1 = ss.f1; 4165 QUERY PLAN 4166-------------------------------------------------- 4167 Nested Loop 4168 Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1 4169 Join Filter: (t1.f1 = t2.f1) 4170 -> Nested Loop Left Join 4171 Output: t1.f1, i8.q1, i8.q2 4172 -> Seq Scan on public.text_tbl t1 4173 Output: t1.f1 4174 -> Materialize 4175 Output: i8.q1, i8.q2 4176 -> Seq Scan on public.int8_tbl i8 4177 Output: i8.q1, i8.q2 4178 Filter: (i8.q2 = 123) 4179 -> Limit 4180 Output: (i8.q1), t2.f1 4181 -> Seq Scan on public.text_tbl t2 4182 Output: i8.q1, t2.f1 4183(16 rows) 4184 4185select * from 4186 text_tbl t1 4187 left join int8_tbl i8 4188 on i8.q2 = 123, 4189 lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss 4190where t1.f1 = ss.f1; 4191 f1 | q1 | q2 | q1 | f1 4192------+------------------+-----+------------------+------ 4193 doh! | 4567890123456789 | 123 | 4567890123456789 | doh! 4194(1 row) 4195 4196explain (verbose, costs off) 4197select * from 4198 text_tbl t1 4199 left join int8_tbl i8 4200 on i8.q2 = 123, 4201 lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1, 4202 lateral (select ss1.* from text_tbl t3 limit 1) as ss2 4203where t1.f1 = ss2.f1; 4204 QUERY PLAN 4205------------------------------------------------------------------- 4206 Nested Loop 4207 Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1, ((i8.q1)), (t2.f1) 4208 Join Filter: (t1.f1 = (t2.f1)) 4209 -> Nested Loop 4210 Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1 4211 -> Nested Loop Left Join 4212 Output: t1.f1, i8.q1, i8.q2 4213 -> Seq Scan on public.text_tbl t1 4214 Output: t1.f1 4215 -> Materialize 4216 Output: i8.q1, i8.q2 4217 -> Seq Scan on public.int8_tbl i8 4218 Output: i8.q1, i8.q2 4219 Filter: (i8.q2 = 123) 4220 -> Limit 4221 Output: (i8.q1), t2.f1 4222 -> Seq Scan on public.text_tbl t2 4223 Output: i8.q1, t2.f1 4224 -> Limit 4225 Output: ((i8.q1)), (t2.f1) 4226 -> Seq Scan on public.text_tbl t3 4227 Output: (i8.q1), t2.f1 4228(22 rows) 4229 4230select * from 4231 text_tbl t1 4232 left join int8_tbl i8 4233 on i8.q2 = 123, 4234 lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1, 4235 lateral (select ss1.* from text_tbl t3 limit 1) as ss2 4236where t1.f1 = ss2.f1; 4237 f1 | q1 | q2 | q1 | f1 | q1 | f1 4238------+------------------+-----+------------------+------+------------------+------ 4239 doh! | 4567890123456789 | 123 | 4567890123456789 | doh! | 4567890123456789 | doh! 4240(1 row) 4241 4242explain (verbose, costs off) 4243select 1 from 4244 text_tbl as tt1 4245 inner join text_tbl as tt2 on (tt1.f1 = 'foo') 4246 left join text_tbl as tt3 on (tt3.f1 = 'foo') 4247 left join text_tbl as tt4 on (tt3.f1 = tt4.f1), 4248 lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 4249where tt1.f1 = ss1.c0; 4250 QUERY PLAN 4251---------------------------------------------------------- 4252 Nested Loop 4253 Output: 1 4254 -> Nested Loop Left Join 4255 Output: tt1.f1, tt4.f1 4256 -> Nested Loop 4257 Output: tt1.f1 4258 -> Seq Scan on public.text_tbl tt1 4259 Output: tt1.f1 4260 Filter: (tt1.f1 = 'foo'::text) 4261 -> Seq Scan on public.text_tbl tt2 4262 Output: tt2.f1 4263 -> Materialize 4264 Output: tt4.f1 4265 -> Nested Loop Left Join 4266 Output: tt4.f1 4267 Join Filter: (tt3.f1 = tt4.f1) 4268 -> Seq Scan on public.text_tbl tt3 4269 Output: tt3.f1 4270 Filter: (tt3.f1 = 'foo'::text) 4271 -> Seq Scan on public.text_tbl tt4 4272 Output: tt4.f1 4273 Filter: (tt4.f1 = 'foo'::text) 4274 -> Subquery Scan on ss1 4275 Output: ss1.c0 4276 Filter: (ss1.c0 = 'foo'::text) 4277 -> Limit 4278 Output: (tt4.f1) 4279 -> Seq Scan on public.text_tbl tt5 4280 Output: tt4.f1 4281(29 rows) 4282 4283select 1 from 4284 text_tbl as tt1 4285 inner join text_tbl as tt2 on (tt1.f1 = 'foo') 4286 left join text_tbl as tt3 on (tt3.f1 = 'foo') 4287 left join text_tbl as tt4 on (tt3.f1 = tt4.f1), 4288 lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1 4289where tt1.f1 = ss1.c0; 4290 ?column? 4291---------- 4292(0 rows) 4293 4294-- 4295-- check a case in which a PlaceHolderVar forces join order 4296-- 4297explain (verbose, costs off) 4298select ss2.* from 4299 int4_tbl i41 4300 left join int8_tbl i8 4301 join (select i42.f1 as c1, i43.f1 as c2, 42 as c3 4302 from int4_tbl i42, int4_tbl i43) ss1 4303 on i8.q1 = ss1.c2 4304 on i41.f1 = ss1.c1, 4305 lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2 4306where ss1.c2 = 0; 4307 QUERY PLAN 4308------------------------------------------------------------------------ 4309 Nested Loop 4310 Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42)) 4311 -> Hash Join 4312 Output: i41.f1, i42.f1, i8.q1, i8.q2, i43.f1, 42 4313 Hash Cond: (i41.f1 = i42.f1) 4314 -> Nested Loop 4315 Output: i8.q1, i8.q2, i43.f1, i41.f1 4316 -> Nested Loop 4317 Output: i8.q1, i8.q2, i43.f1 4318 -> Seq Scan on public.int8_tbl i8 4319 Output: i8.q1, i8.q2 4320 Filter: (i8.q1 = 0) 4321 -> Seq Scan on public.int4_tbl i43 4322 Output: i43.f1 4323 Filter: (i43.f1 = 0) 4324 -> Seq Scan on public.int4_tbl i41 4325 Output: i41.f1 4326 -> Hash 4327 Output: i42.f1 4328 -> Seq Scan on public.int4_tbl i42 4329 Output: i42.f1 4330 -> Limit 4331 Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42)) 4332 -> Seq Scan on public.text_tbl 4333 Output: i41.f1, i8.q1, i8.q2, i42.f1, i43.f1, (42) 4334(25 rows) 4335 4336select ss2.* from 4337 int4_tbl i41 4338 left join int8_tbl i8 4339 join (select i42.f1 as c1, i43.f1 as c2, 42 as c3 4340 from int4_tbl i42, int4_tbl i43) ss1 4341 on i8.q1 = ss1.c2 4342 on i41.f1 = ss1.c1, 4343 lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2 4344where ss1.c2 = 0; 4345 f1 | q1 | q2 | c1 | c2 | c3 4346----+----+----+----+----+---- 4347(0 rows) 4348 4349-- 4350-- test successful handling of full join underneath left join (bug #14105) 4351-- 4352explain (costs off) 4353select * from 4354 (select 1 as id) as xx 4355 left join 4356 (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id)) 4357 on (xx.id = coalesce(yy.id)); 4358 QUERY PLAN 4359--------------------------------------- 4360 Nested Loop Left Join 4361 -> Result 4362 -> Hash Full Join 4363 Hash Cond: (a1.unique1 = (1)) 4364 Filter: (1 = COALESCE((1))) 4365 -> Seq Scan on tenk1 a1 4366 -> Hash 4367 -> Result 4368(8 rows) 4369 4370select * from 4371 (select 1 as id) as xx 4372 left join 4373 (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id)) 4374 on (xx.id = coalesce(yy.id)); 4375 id | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | id 4376----+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---- 4377 1 | 1 | 2838 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 3 | BAAAAA | EFEAAA | OOOOxx | 1 4378(1 row) 4379 4380-- 4381-- test ability to push constants through outer join clauses 4382-- 4383explain (costs off) 4384 select * from int4_tbl a left join tenk1 b on f1 = unique2 where f1 = 0; 4385 QUERY PLAN 4386------------------------------------------------- 4387 Nested Loop Left Join 4388 Join Filter: (a.f1 = b.unique2) 4389 -> Seq Scan on int4_tbl a 4390 Filter: (f1 = 0) 4391 -> Index Scan using tenk1_unique2 on tenk1 b 4392 Index Cond: (unique2 = 0) 4393(6 rows) 4394 4395explain (costs off) 4396 select * from tenk1 a full join tenk1 b using(unique2) where unique2 = 42; 4397 QUERY PLAN 4398------------------------------------------------- 4399 Merge Full Join 4400 Merge Cond: (a.unique2 = b.unique2) 4401 -> Index Scan using tenk1_unique2 on tenk1 a 4402 Index Cond: (unique2 = 42) 4403 -> Index Scan using tenk1_unique2 on tenk1 b 4404 Index Cond: (unique2 = 42) 4405(6 rows) 4406 4407-- 4408-- test that quals attached to an outer join have correct semantics, 4409-- specifically that they don't re-use expressions computed below the join; 4410-- we force a mergejoin so that coalesce(b.q1, 1) appears as a join input 4411-- 4412set enable_hashjoin to off; 4413set enable_nestloop to off; 4414explain (verbose, costs off) 4415 select a.q2, b.q1 4416 from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) 4417 where coalesce(b.q1, 1) > 0; 4418 QUERY PLAN 4419--------------------------------------------------------- 4420 Merge Left Join 4421 Output: a.q2, b.q1 4422 Merge Cond: (a.q2 = (COALESCE(b.q1, '1'::bigint))) 4423 Filter: (COALESCE(b.q1, '1'::bigint) > 0) 4424 -> Sort 4425 Output: a.q2 4426 Sort Key: a.q2 4427 -> Seq Scan on public.int8_tbl a 4428 Output: a.q2 4429 -> Sort 4430 Output: b.q1, (COALESCE(b.q1, '1'::bigint)) 4431 Sort Key: (COALESCE(b.q1, '1'::bigint)) 4432 -> Seq Scan on public.int8_tbl b 4433 Output: b.q1, COALESCE(b.q1, '1'::bigint) 4434(14 rows) 4435 4436select a.q2, b.q1 4437 from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1) 4438 where coalesce(b.q1, 1) > 0; 4439 q2 | q1 4440-------------------+------------------ 4441 -4567890123456789 | 4442 123 | 123 4443 123 | 123 4444 456 | 4445 4567890123456789 | 4567890123456789 4446 4567890123456789 | 4567890123456789 4447 4567890123456789 | 4567890123456789 4448 4567890123456789 | 4567890123456789 4449 4567890123456789 | 4567890123456789 4450 4567890123456789 | 4567890123456789 4451(10 rows) 4452 4453reset enable_hashjoin; 4454reset enable_nestloop; 4455-- 4456-- test join removal 4457-- 4458begin; 4459CREATE TEMP TABLE a (id int PRIMARY KEY, b_id int); 4460CREATE TEMP TABLE b (id int PRIMARY KEY, c_id int); 4461CREATE TEMP TABLE c (id int PRIMARY KEY); 4462CREATE TEMP TABLE d (a int, b int); 4463INSERT INTO a VALUES (0, 0), (1, NULL); 4464INSERT INTO b VALUES (0, 0), (1, NULL); 4465INSERT INTO c VALUES (0), (1); 4466INSERT INTO d VALUES (1,3), (2,2), (3,1); 4467-- all three cases should be optimizable into a simple seqscan 4468explain (costs off) SELECT a.* FROM a LEFT JOIN b ON a.b_id = b.id; 4469 QUERY PLAN 4470--------------- 4471 Seq Scan on a 4472(1 row) 4473 4474explain (costs off) SELECT b.* FROM b LEFT JOIN c ON b.c_id = c.id; 4475 QUERY PLAN 4476--------------- 4477 Seq Scan on b 4478(1 row) 4479 4480explain (costs off) 4481 SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id = c.id) 4482 ON (a.b_id = b.id); 4483 QUERY PLAN 4484--------------- 4485 Seq Scan on a 4486(1 row) 4487 4488-- check optimization of outer join within another special join 4489explain (costs off) 4490select id from a where id in ( 4491 select b.id from b left join c on b.id = c.id 4492); 4493 QUERY PLAN 4494---------------------------- 4495 Hash Join 4496 Hash Cond: (a.id = b.id) 4497 -> Seq Scan on a 4498 -> Hash 4499 -> Seq Scan on b 4500(5 rows) 4501 4502-- check that join removal works for a left join when joining a subquery 4503-- that is guaranteed to be unique by its GROUP BY clause 4504explain (costs off) 4505select d.* from d left join (select * from b group by b.id, b.c_id) s 4506 on d.a = s.id and d.b = s.c_id; 4507 QUERY PLAN 4508--------------- 4509 Seq Scan on d 4510(1 row) 4511 4512-- similarly, but keying off a DISTINCT clause 4513explain (costs off) 4514select d.* from d left join (select distinct * from b) s 4515 on d.a = s.id and d.b = s.c_id; 4516 QUERY PLAN 4517--------------- 4518 Seq Scan on d 4519(1 row) 4520 4521-- join removal is not possible when the GROUP BY contains a column that is 4522-- not in the join condition. (Note: as of 9.6, we notice that b.id is a 4523-- primary key and so drop b.c_id from the GROUP BY of the resulting plan; 4524-- but this happens too late for join removal in the outer plan level.) 4525explain (costs off) 4526select d.* from d left join (select * from b group by b.id, b.c_id) s 4527 on d.a = s.id; 4528 QUERY PLAN 4529------------------------------------------ 4530 Merge Right Join 4531 Merge Cond: (b.id = d.a) 4532 -> Group 4533 Group Key: b.id 4534 -> Index Scan using b_pkey on b 4535 -> Sort 4536 Sort Key: d.a 4537 -> Seq Scan on d 4538(8 rows) 4539 4540-- similarly, but keying off a DISTINCT clause 4541explain (costs off) 4542select d.* from d left join (select distinct * from b) s 4543 on d.a = s.id; 4544 QUERY PLAN 4545-------------------------------------- 4546 Merge Right Join 4547 Merge Cond: (b.id = d.a) 4548 -> Unique 4549 -> Sort 4550 Sort Key: b.id, b.c_id 4551 -> Seq Scan on b 4552 -> Sort 4553 Sort Key: d.a 4554 -> Seq Scan on d 4555(9 rows) 4556 4557-- check join removal works when uniqueness of the join condition is enforced 4558-- by a UNION 4559explain (costs off) 4560select d.* from d left join (select id from a union select id from b) s 4561 on d.a = s.id; 4562 QUERY PLAN 4563--------------- 4564 Seq Scan on d 4565(1 row) 4566 4567-- check join removal with a cross-type comparison operator 4568explain (costs off) 4569select i8.* from int8_tbl i8 left join (select f1 from int4_tbl group by f1) i4 4570 on i8.q1 = i4.f1; 4571 QUERY PLAN 4572------------------------- 4573 Seq Scan on int8_tbl i8 4574(1 row) 4575 4576-- check join removal with lateral references 4577explain (costs off) 4578select 1 from (select a.id FROM a left join b on a.b_id = b.id) q, 4579 lateral generate_series(1, q.id) gs(i) where q.id = gs.i; 4580 QUERY PLAN 4581------------------------------------------- 4582 Nested Loop 4583 -> Seq Scan on a 4584 -> Function Scan on generate_series gs 4585 Filter: (a.id = i) 4586(4 rows) 4587 4588rollback; 4589create temp table parent (k int primary key, pd int); 4590create temp table child (k int unique, cd int); 4591insert into parent values (1, 10), (2, 20), (3, 30); 4592insert into child values (1, 100), (4, 400); 4593-- this case is optimizable 4594select p.* from parent p left join child c on (p.k = c.k); 4595 k | pd 4596---+---- 4597 1 | 10 4598 2 | 20 4599 3 | 30 4600(3 rows) 4601 4602explain (costs off) 4603 select p.* from parent p left join child c on (p.k = c.k); 4604 QUERY PLAN 4605---------------------- 4606 Seq Scan on parent p 4607(1 row) 4608 4609-- this case is not 4610select p.*, linked from parent p 4611 left join (select c.*, true as linked from child c) as ss 4612 on (p.k = ss.k); 4613 k | pd | linked 4614---+----+-------- 4615 1 | 10 | t 4616 2 | 20 | 4617 3 | 30 | 4618(3 rows) 4619 4620explain (costs off) 4621 select p.*, linked from parent p 4622 left join (select c.*, true as linked from child c) as ss 4623 on (p.k = ss.k); 4624 QUERY PLAN 4625--------------------------------- 4626 Hash Left Join 4627 Hash Cond: (p.k = c.k) 4628 -> Seq Scan on parent p 4629 -> Hash 4630 -> Seq Scan on child c 4631(5 rows) 4632 4633-- check for a 9.0rc1 bug: join removal breaks pseudoconstant qual handling 4634select p.* from 4635 parent p left join child c on (p.k = c.k) 4636 where p.k = 1 and p.k = 2; 4637 k | pd 4638---+---- 4639(0 rows) 4640 4641explain (costs off) 4642select p.* from 4643 parent p left join child c on (p.k = c.k) 4644 where p.k = 1 and p.k = 2; 4645 QUERY PLAN 4646------------------------------------------------ 4647 Result 4648 One-Time Filter: false 4649 -> Index Scan using parent_pkey on parent p 4650 Index Cond: (k = 1) 4651(4 rows) 4652 4653select p.* from 4654 (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k 4655 where p.k = 1 and p.k = 2; 4656 k | pd 4657---+---- 4658(0 rows) 4659 4660explain (costs off) 4661select p.* from 4662 (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k 4663 where p.k = 1 and p.k = 2; 4664 QUERY PLAN 4665-------------------------- 4666 Result 4667 One-Time Filter: false 4668(2 rows) 4669 4670-- bug 5255: this is not optimizable by join removal 4671begin; 4672CREATE TEMP TABLE a (id int PRIMARY KEY); 4673CREATE TEMP TABLE b (id int PRIMARY KEY, a_id int); 4674INSERT INTO a VALUES (0), (1); 4675INSERT INTO b VALUES (0, 0), (1, NULL); 4676SELECT * FROM b LEFT JOIN a ON (b.a_id = a.id) WHERE (a.id IS NULL OR a.id > 0); 4677 id | a_id | id 4678----+------+---- 4679 1 | | 4680(1 row) 4681 4682SELECT b.* FROM b LEFT JOIN a ON (b.a_id = a.id) WHERE (a.id IS NULL OR a.id > 0); 4683 id | a_id 4684----+------ 4685 1 | 4686(1 row) 4687 4688rollback; 4689-- another join removal bug: this is not optimizable, either 4690begin; 4691create temp table innertab (id int8 primary key, dat1 int8); 4692insert into innertab values(123, 42); 4693SELECT * FROM 4694 (SELECT 1 AS x) ss1 4695 LEFT JOIN 4696 (SELECT q1, q2, COALESCE(dat1, q1) AS y 4697 FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss2 4698 ON true; 4699 x | q1 | q2 | y 4700---+------------------+-------------------+------------------ 4701 1 | 123 | 456 | 123 4702 1 | 123 | 4567890123456789 | 123 4703 1 | 4567890123456789 | 123 | 42 4704 1 | 4567890123456789 | 4567890123456789 | 4567890123456789 4705 1 | 4567890123456789 | -4567890123456789 | 4567890123456789 4706(5 rows) 4707 4708rollback; 4709-- another join removal bug: we must clean up correctly when removing a PHV 4710begin; 4711create temp table uniquetbl (f1 text unique); 4712explain (costs off) 4713select t1.* from 4714 uniquetbl as t1 4715 left join (select *, '***'::text as d1 from uniquetbl) t2 4716 on t1.f1 = t2.f1 4717 left join uniquetbl t3 4718 on t2.d1 = t3.f1; 4719 QUERY PLAN 4720-------------------------- 4721 Seq Scan on uniquetbl t1 4722(1 row) 4723 4724explain (costs off) 4725select t0.* 4726from 4727 text_tbl t0 4728 left join 4729 (select case t1.ten when 0 then 'doh!'::text else null::text end as case1, 4730 t1.stringu2 4731 from tenk1 t1 4732 join int4_tbl i4 ON i4.f1 = t1.unique2 4733 left join uniquetbl u1 ON u1.f1 = t1.string4) ss 4734 on t0.f1 = ss.case1 4735where ss.stringu2 !~* ss.case1; 4736 QUERY PLAN 4737-------------------------------------------------------------------------------------------- 4738 Nested Loop 4739 Join Filter: (CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END = t0.f1) 4740 -> Nested Loop 4741 -> Seq Scan on int4_tbl i4 4742 -> Index Scan using tenk1_unique2 on tenk1 t1 4743 Index Cond: (unique2 = i4.f1) 4744 Filter: (stringu2 !~* CASE ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END) 4745 -> Materialize 4746 -> Seq Scan on text_tbl t0 4747(9 rows) 4748 4749select t0.* 4750from 4751 text_tbl t0 4752 left join 4753 (select case t1.ten when 0 then 'doh!'::text else null::text end as case1, 4754 t1.stringu2 4755 from tenk1 t1 4756 join int4_tbl i4 ON i4.f1 = t1.unique2 4757 left join uniquetbl u1 ON u1.f1 = t1.string4) ss 4758 on t0.f1 = ss.case1 4759where ss.stringu2 !~* ss.case1; 4760 f1 4761------ 4762 doh! 4763(1 row) 4764 4765rollback; 4766-- test case to expose miscomputation of required relid set for a PHV 4767explain (verbose, costs off) 4768select i8.*, ss.v, t.unique2 4769 from int8_tbl i8 4770 left join int4_tbl i4 on i4.f1 = 1 4771 left join lateral (select i4.f1 + 1 as v) as ss on true 4772 left join tenk1 t on t.unique2 = ss.v 4773where q2 = 456; 4774 QUERY PLAN 4775------------------------------------------------------------- 4776 Nested Loop Left Join 4777 Output: i8.q1, i8.q2, ((i4.f1 + 1)), t.unique2 4778 -> Nested Loop Left Join 4779 Output: i8.q1, i8.q2, (i4.f1 + 1) 4780 -> Seq Scan on public.int8_tbl i8 4781 Output: i8.q1, i8.q2 4782 Filter: (i8.q2 = 456) 4783 -> Seq Scan on public.int4_tbl i4 4784 Output: i4.f1 4785 Filter: (i4.f1 = 1) 4786 -> Index Only Scan using tenk1_unique2 on public.tenk1 t 4787 Output: t.unique2 4788 Index Cond: (t.unique2 = ((i4.f1 + 1))) 4789(13 rows) 4790 4791select i8.*, ss.v, t.unique2 4792 from int8_tbl i8 4793 left join int4_tbl i4 on i4.f1 = 1 4794 left join lateral (select i4.f1 + 1 as v) as ss on true 4795 left join tenk1 t on t.unique2 = ss.v 4796where q2 = 456; 4797 q1 | q2 | v | unique2 4798-----+-----+---+--------- 4799 123 | 456 | | 4800(1 row) 4801 4802-- and check a related issue where we miscompute required relids for 4803-- a PHV that's been translated to a child rel 4804create temp table parttbl (a integer primary key) partition by range (a); 4805create temp table parttbl1 partition of parttbl for values from (1) to (100); 4806insert into parttbl values (11), (12); 4807explain (costs off) 4808select * from 4809 (select *, 12 as phv from parttbl) as ss 4810 right join int4_tbl on true 4811where ss.a = ss.phv and f1 = 0; 4812 QUERY PLAN 4813------------------------------------ 4814 Nested Loop 4815 -> Seq Scan on int4_tbl 4816 Filter: (f1 = 0) 4817 -> Seq Scan on parttbl1 parttbl 4818 Filter: (a = 12) 4819(5 rows) 4820 4821select * from 4822 (select *, 12 as phv from parttbl) as ss 4823 right join int4_tbl on true 4824where ss.a = ss.phv and f1 = 0; 4825 a | phv | f1 4826----+-----+---- 4827 12 | 12 | 0 4828(1 row) 4829 4830-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs 4831select * from 4832 int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; -- error 4833ERROR: column reference "f1" is ambiguous 4834LINE 2: ..._tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; 4835 ^ 4836select * from 4837 int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; -- error 4838ERROR: invalid reference to FROM-clause entry for table "y" 4839LINE 2: ...bl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; 4840 ^ 4841HINT: There is an entry for table "y", but it cannot be referenced from this part of the query. 4842select * from 4843 int8_tbl x join (int4_tbl x cross join int4_tbl y(ff)) j on q1 = f1; -- ok 4844 q1 | q2 | f1 | ff 4845----+----+----+---- 4846(0 rows) 4847 4848-- 4849-- Test hints given on incorrect column references are useful 4850-- 4851select t1.uunique1 from 4852 tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t1" suggestion 4853ERROR: column t1.uunique1 does not exist 4854LINE 1: select t1.uunique1 from 4855 ^ 4856HINT: Perhaps you meant to reference the column "t1.unique1". 4857select t2.uunique1 from 4858 tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t2" suggestion 4859ERROR: column t2.uunique1 does not exist 4860LINE 1: select t2.uunique1 from 4861 ^ 4862HINT: Perhaps you meant to reference the column "t2.unique1". 4863select uunique1 from 4864 tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once 4865ERROR: column "uunique1" does not exist 4866LINE 1: select uunique1 from 4867 ^ 4868HINT: Perhaps you meant to reference the column "t1.unique1" or the column "t2.unique1". 4869-- 4870-- Take care to reference the correct RTE 4871-- 4872select atts.relid::regclass, s.* from pg_stats s join 4873 pg_attribute a on s.attname = a.attname and s.tablename = 4874 a.attrelid::regclass::text join (select unnest(indkey) attnum, 4875 indexrelid from pg_index i) atts on atts.attnum = a.attnum where 4876 schemaname != 'pg_catalog'; 4877ERROR: column atts.relid does not exist 4878LINE 1: select atts.relid::regclass, s.* from pg_stats s join 4879 ^ 4880-- 4881-- Test LATERAL 4882-- 4883select unique2, x.* 4884from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; 4885 unique2 | f1 4886---------+---- 4887 9998 | 0 4888(1 row) 4889 4890explain (costs off) 4891 select unique2, x.* 4892 from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x; 4893 QUERY PLAN 4894------------------------------------------------- 4895 Nested Loop 4896 -> Seq Scan on int4_tbl b 4897 -> Index Scan using tenk1_unique1 on tenk1 a 4898 Index Cond: (unique1 = b.f1) 4899(4 rows) 4900 4901select unique2, x.* 4902from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; 4903 unique2 | f1 4904---------+---- 4905 9998 | 0 4906(1 row) 4907 4908explain (costs off) 4909 select unique2, x.* 4910 from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss; 4911 QUERY PLAN 4912----------------------------------------------- 4913 Nested Loop 4914 -> Seq Scan on int4_tbl x 4915 -> Index Scan using tenk1_unique1 on tenk1 4916 Index Cond: (unique1 = x.f1) 4917(4 rows) 4918 4919explain (costs off) 4920 select unique2, x.* 4921 from int4_tbl x cross join lateral (select unique2 from tenk1 where f1 = unique1) ss; 4922 QUERY PLAN 4923----------------------------------------------- 4924 Nested Loop 4925 -> Seq Scan on int4_tbl x 4926 -> Index Scan using tenk1_unique1 on tenk1 4927 Index Cond: (unique1 = x.f1) 4928(4 rows) 4929 4930select unique2, x.* 4931from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; 4932 unique2 | f1 4933---------+------------- 4934 9998 | 0 4935 | 123456 4936 | -123456 4937 | 2147483647 4938 | -2147483647 4939(5 rows) 4940 4941explain (costs off) 4942 select unique2, x.* 4943 from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true; 4944 QUERY PLAN 4945----------------------------------------------- 4946 Nested Loop Left Join 4947 -> Seq Scan on int4_tbl x 4948 -> Index Scan using tenk1_unique1 on tenk1 4949 Index Cond: (unique1 = x.f1) 4950(4 rows) 4951 4952-- check scoping of lateral versus parent references 4953-- the first of these should return int8_tbl.q2, the second int8_tbl.q1 4954select *, (select r from (select q1 as q2) x, (select q2 as r) y) from int8_tbl; 4955 q1 | q2 | r 4956------------------+-------------------+------------------- 4957 123 | 456 | 456 4958 123 | 4567890123456789 | 4567890123456789 4959 4567890123456789 | 123 | 123 4960 4567890123456789 | 4567890123456789 | 4567890123456789 4961 4567890123456789 | -4567890123456789 | -4567890123456789 4962(5 rows) 4963 4964select *, (select r from (select q1 as q2) x, lateral (select q2 as r) y) from int8_tbl; 4965 q1 | q2 | r 4966------------------+-------------------+------------------ 4967 123 | 456 | 123 4968 123 | 4567890123456789 | 123 4969 4567890123456789 | 123 | 4567890123456789 4970 4567890123456789 | 4567890123456789 | 4567890123456789 4971 4567890123456789 | -4567890123456789 | 4567890123456789 4972(5 rows) 4973 4974-- lateral with function in FROM 4975select count(*) from tenk1 a, lateral generate_series(1,two) g; 4976 count 4977------- 4978 5000 4979(1 row) 4980 4981explain (costs off) 4982 select count(*) from tenk1 a, lateral generate_series(1,two) g; 4983 QUERY PLAN 4984------------------------------------------------ 4985 Aggregate 4986 -> Nested Loop 4987 -> Seq Scan on tenk1 a 4988 -> Function Scan on generate_series g 4989(4 rows) 4990 4991explain (costs off) 4992 select count(*) from tenk1 a cross join lateral generate_series(1,two) g; 4993 QUERY PLAN 4994------------------------------------------------ 4995 Aggregate 4996 -> Nested Loop 4997 -> Seq Scan on tenk1 a 4998 -> Function Scan on generate_series g 4999(4 rows) 5000 5001-- don't need the explicit LATERAL keyword for functions 5002explain (costs off) 5003 select count(*) from tenk1 a, generate_series(1,two) g; 5004 QUERY PLAN 5005------------------------------------------------ 5006 Aggregate 5007 -> Nested Loop 5008 -> Seq Scan on tenk1 a 5009 -> Function Scan on generate_series g 5010(4 rows) 5011 5012-- lateral with UNION ALL subselect 5013explain (costs off) 5014 select * from generate_series(100,200) g, 5015 lateral (select * from int8_tbl a where g = q1 union all 5016 select * from int8_tbl b where g = q2) ss; 5017 QUERY PLAN 5018------------------------------------------ 5019 Nested Loop 5020 -> Function Scan on generate_series g 5021 -> Append 5022 -> Seq Scan on int8_tbl a 5023 Filter: (g.g = q1) 5024 -> Seq Scan on int8_tbl b 5025 Filter: (g.g = q2) 5026(7 rows) 5027 5028select * from generate_series(100,200) g, 5029 lateral (select * from int8_tbl a where g = q1 union all 5030 select * from int8_tbl b where g = q2) ss; 5031 g | q1 | q2 5032-----+------------------+------------------ 5033 123 | 123 | 456 5034 123 | 123 | 4567890123456789 5035 123 | 4567890123456789 | 123 5036(3 rows) 5037 5038-- lateral with VALUES 5039explain (costs off) 5040 select count(*) from tenk1 a, 5041 tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x; 5042 QUERY PLAN 5043------------------------------------------------------------ 5044 Aggregate 5045 -> Merge Join 5046 Merge Cond: (a.unique1 = b.unique2) 5047 -> Index Only Scan using tenk1_unique1 on tenk1 a 5048 -> Index Only Scan using tenk1_unique2 on tenk1 b 5049(5 rows) 5050 5051select count(*) from tenk1 a, 5052 tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x; 5053 count 5054------- 5055 10000 5056(1 row) 5057 5058-- lateral with VALUES, no flattening possible 5059explain (costs off) 5060 select count(*) from tenk1 a, 5061 tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x; 5062 QUERY PLAN 5063------------------------------------------------------------------ 5064 Aggregate 5065 -> Hash Join 5066 Hash Cond: ("*VALUES*".column1 = b.unique2) 5067 -> Nested Loop 5068 -> Index Only Scan using tenk1_unique1 on tenk1 a 5069 -> Values Scan on "*VALUES*" 5070 -> Hash 5071 -> Index Only Scan using tenk1_unique2 on tenk1 b 5072(8 rows) 5073 5074select count(*) from tenk1 a, 5075 tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x; 5076 count 5077------- 5078 10000 5079(1 row) 5080 5081-- lateral injecting a strange outer join condition 5082explain (costs off) 5083 select * from int8_tbl a, 5084 int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) 5085 on x.q2 = ss.z 5086 order by a.q1, a.q2, x.q1, x.q2, ss.z; 5087 QUERY PLAN 5088------------------------------------------------ 5089 Sort 5090 Sort Key: a.q1, a.q2, x.q1, x.q2, (a.q1) 5091 -> Nested Loop 5092 -> Seq Scan on int8_tbl a 5093 -> Hash Right Join 5094 Hash Cond: ((a.q1) = x.q2) 5095 -> Seq Scan on int4_tbl y 5096 -> Hash 5097 -> Seq Scan on int8_tbl x 5098(9 rows) 5099 5100select * from int8_tbl a, 5101 int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) 5102 on x.q2 = ss.z 5103 order by a.q1, a.q2, x.q1, x.q2, ss.z; 5104 q1 | q2 | q1 | q2 | z 5105------------------+-------------------+------------------+-------------------+------------------ 5106 123 | 456 | 123 | 456 | 5107 123 | 456 | 123 | 4567890123456789 | 5108 123 | 456 | 4567890123456789 | -4567890123456789 | 5109 123 | 456 | 4567890123456789 | 123 | 123 5110 123 | 456 | 4567890123456789 | 123 | 123 5111 123 | 456 | 4567890123456789 | 123 | 123 5112 123 | 456 | 4567890123456789 | 123 | 123 5113 123 | 456 | 4567890123456789 | 123 | 123 5114 123 | 456 | 4567890123456789 | 4567890123456789 | 5115 123 | 4567890123456789 | 123 | 456 | 5116 123 | 4567890123456789 | 123 | 4567890123456789 | 5117 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 5118 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5119 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5120 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5121 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5122 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5123 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 5124 4567890123456789 | -4567890123456789 | 123 | 456 | 5125 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5126 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5127 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5128 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5129 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5130 4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 | 5131 4567890123456789 | -4567890123456789 | 4567890123456789 | 123 | 5132 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5133 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5134 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5135 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5136 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5137 4567890123456789 | 123 | 123 | 456 | 5138 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 5139 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 5140 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 5141 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 5142 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 5143 4567890123456789 | 123 | 4567890123456789 | -4567890123456789 | 5144 4567890123456789 | 123 | 4567890123456789 | 123 | 5145 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 5146 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 5147 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 5148 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 5149 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 5150 4567890123456789 | 4567890123456789 | 123 | 456 | 5151 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5152 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5153 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5154 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5155 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5156 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 5157 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 5158 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5159 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5160 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5161 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5162 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5163(57 rows) 5164 5165-- lateral reference to a join alias variable 5166select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, 5167 lateral (select x) ss2(y); 5168 x | f1 | y 5169---+----+--- 5170 0 | 0 | 0 5171(1 row) 5172 5173select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, 5174 lateral (values(x)) ss2(y); 5175 x | f1 | y 5176-------------+-------------+------------- 5177 0 | 0 | 0 5178 123456 | 123456 | 123456 5179 -123456 | -123456 | -123456 5180 2147483647 | 2147483647 | 2147483647 5181 -2147483647 | -2147483647 | -2147483647 5182(5 rows) 5183 5184select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j, 5185 lateral (select x) ss2(y); 5186 x | f1 | y 5187---+----+--- 5188 0 | 0 | 0 5189(1 row) 5190 5191-- lateral references requiring pullup 5192select * from (values(1)) x(lb), 5193 lateral generate_series(lb,4) x4; 5194 lb | x4 5195----+---- 5196 1 | 1 5197 1 | 2 5198 1 | 3 5199 1 | 4 5200(4 rows) 5201 5202select * from (select f1/1000000000 from int4_tbl) x(lb), 5203 lateral generate_series(lb,4) x4; 5204 lb | x4 5205----+---- 5206 0 | 0 5207 0 | 1 5208 0 | 2 5209 0 | 3 5210 0 | 4 5211 0 | 0 5212 0 | 1 5213 0 | 2 5214 0 | 3 5215 0 | 4 5216 0 | 0 5217 0 | 1 5218 0 | 2 5219 0 | 3 5220 0 | 4 5221 2 | 2 5222 2 | 3 5223 2 | 4 5224 -2 | -2 5225 -2 | -1 5226 -2 | 0 5227 -2 | 1 5228 -2 | 2 5229 -2 | 3 5230 -2 | 4 5231(25 rows) 5232 5233select * from (values(1)) x(lb), 5234 lateral (values(lb)) y(lbcopy); 5235 lb | lbcopy 5236----+-------- 5237 1 | 1 5238(1 row) 5239 5240select * from (values(1)) x(lb), 5241 lateral (select lb from int4_tbl) y(lbcopy); 5242 lb | lbcopy 5243----+-------- 5244 1 | 1 5245 1 | 1 5246 1 | 1 5247 1 | 1 5248 1 | 1 5249(5 rows) 5250 5251select * from 5252 int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, 5253 lateral (values(x.q1,y.q1,y.q2)) v(xq1,yq1,yq2); 5254 q1 | q2 | q1 | q2 | xq1 | yq1 | yq2 5255------------------+-------------------+------------------+-------------------+------------------+------------------+------------------- 5256 123 | 456 | | | 123 | | 5257 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | -4567890123456789 5258 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5259 123 | 4567890123456789 | 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5260 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 5261 4567890123456789 | 123 | 123 | 456 | 4567890123456789 | 123 | 456 5262 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 5263 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5264 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 123 5265 4567890123456789 | -4567890123456789 | | | 4567890123456789 | | 5266(10 rows) 5267 5268select * from 5269 int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, 5270 lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2); 5271 q1 | q2 | q1 | q2 | xq1 | yq1 | yq2 5272------------------+-------------------+------------------+-------------------+------------------+------------------+------------------- 5273 123 | 456 | | | 123 | | 5274 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 123 | 4567890123456789 | -4567890123456789 5275 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5276 123 | 4567890123456789 | 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5277 4567890123456789 | 123 | 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 5278 4567890123456789 | 123 | 123 | 456 | 4567890123456789 | 123 | 456 5279 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 5280 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5281 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 | 123 5282 4567890123456789 | -4567890123456789 | | | 4567890123456789 | | 5283(10 rows) 5284 5285select x.* from 5286 int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1, 5287 lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2); 5288 q1 | q2 5289------------------+------------------- 5290 123 | 456 5291 123 | 4567890123456789 5292 123 | 4567890123456789 5293 123 | 4567890123456789 5294 4567890123456789 | 123 5295 4567890123456789 | 123 5296 4567890123456789 | 4567890123456789 5297 4567890123456789 | 4567890123456789 5298 4567890123456789 | 4567890123456789 5299 4567890123456789 | -4567890123456789 5300(10 rows) 5301 5302select v.* from 5303 (int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1) 5304 left join int4_tbl z on z.f1 = x.q2, 5305 lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy); 5306 vx | vy 5307-------------------+------------------- 5308 123 | 5309 456 | 5310 123 | 4567890123456789 5311 4567890123456789 | -4567890123456789 5312 123 | 4567890123456789 5313 4567890123456789 | 4567890123456789 5314 123 | 4567890123456789 5315 4567890123456789 | 123 5316 4567890123456789 | 123 5317 123 | 4567890123456789 5318 4567890123456789 | 123 5319 123 | 456 5320 4567890123456789 | 4567890123456789 5321 4567890123456789 | -4567890123456789 5322 4567890123456789 | 4567890123456789 5323 4567890123456789 | 4567890123456789 5324 4567890123456789 | 4567890123456789 5325 4567890123456789 | 123 5326 4567890123456789 | 5327 -4567890123456789 | 5328(20 rows) 5329 5330select v.* from 5331 (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1) 5332 left join int4_tbl z on z.f1 = x.q2, 5333 lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy); 5334 vx | vy 5335-------------------+------------------- 5336 4567890123456789 | 123 5337 123 | 456 5338 4567890123456789 | 123 5339 123 | 4567890123456789 5340 4567890123456789 | 4567890123456789 5341 4567890123456789 | 123 5342 123 | 4567890123456789 5343 4567890123456789 | 123 5344 4567890123456789 | 4567890123456789 5345 4567890123456789 | 4567890123456789 5346 123 | 4567890123456789 5347 4567890123456789 | 4567890123456789 5348 4567890123456789 | 4567890123456789 5349 4567890123456789 | -4567890123456789 5350 123 | 4567890123456789 5351 4567890123456789 | -4567890123456789 5352 123 | 5353 456 | 5354 4567890123456789 | 5355 -4567890123456789 | 5356(20 rows) 5357 5358select v.* from 5359 (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1) 5360 left join int4_tbl z on z.f1 = x.q2, 5361 lateral (select x.q1,y.q1 from onerow union all select x.q2,y.q2 from onerow) v(vx,vy); 5362 vx | vy 5363-------------------+------------------- 5364 4567890123456789 | 123 5365 123 | 456 5366 4567890123456789 | 123 5367 123 | 4567890123456789 5368 4567890123456789 | 4567890123456789 5369 4567890123456789 | 123 5370 123 | 4567890123456789 5371 4567890123456789 | 123 5372 4567890123456789 | 4567890123456789 5373 4567890123456789 | 4567890123456789 5374 123 | 4567890123456789 5375 4567890123456789 | 4567890123456789 5376 4567890123456789 | 4567890123456789 5377 4567890123456789 | -4567890123456789 5378 123 | 4567890123456789 5379 4567890123456789 | -4567890123456789 5380 123 | 5381 456 | 5382 4567890123456789 | 5383 -4567890123456789 | 5384(20 rows) 5385 5386explain (verbose, costs off) 5387select * from 5388 int8_tbl a left join 5389 lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1; 5390 QUERY PLAN 5391------------------------------------------ 5392 Nested Loop Left Join 5393 Output: a.q1, a.q2, b.q1, b.q2, (a.q2) 5394 -> Seq Scan on public.int8_tbl a 5395 Output: a.q1, a.q2 5396 -> Seq Scan on public.int8_tbl b 5397 Output: b.q1, b.q2, a.q2 5398 Filter: (a.q2 = b.q1) 5399(7 rows) 5400 5401select * from 5402 int8_tbl a left join 5403 lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1; 5404 q1 | q2 | q1 | q2 | x 5405------------------+-------------------+------------------+-------------------+------------------ 5406 123 | 456 | | | 5407 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 5408 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5409 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 5410 4567890123456789 | 123 | 123 | 456 | 123 5411 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5412 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 5413 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5414 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 5415 4567890123456789 | -4567890123456789 | | | 5416(10 rows) 5417 5418explain (verbose, costs off) 5419select * from 5420 int8_tbl a left join 5421 lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1; 5422 QUERY PLAN 5423------------------------------------------------------------------ 5424 Nested Loop Left Join 5425 Output: a.q1, a.q2, b.q1, b.q2, (COALESCE(a.q2, '42'::bigint)) 5426 -> Seq Scan on public.int8_tbl a 5427 Output: a.q1, a.q2 5428 -> Seq Scan on public.int8_tbl b 5429 Output: b.q1, b.q2, COALESCE(a.q2, '42'::bigint) 5430 Filter: (a.q2 = b.q1) 5431(7 rows) 5432 5433select * from 5434 int8_tbl a left join 5435 lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1; 5436 q1 | q2 | q1 | q2 | x 5437------------------+-------------------+------------------+-------------------+------------------ 5438 123 | 456 | | | 5439 123 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 5440 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5441 123 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 5442 4567890123456789 | 123 | 123 | 456 | 123 5443 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5444 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 4567890123456789 5445 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5446 4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 5447 4567890123456789 | -4567890123456789 | | | 5448(10 rows) 5449 5450-- lateral can result in join conditions appearing below their 5451-- real semantic level 5452explain (verbose, costs off) 5453select * from int4_tbl i left join 5454 lateral (select * from int2_tbl j where i.f1 = j.f1) k on true; 5455 QUERY PLAN 5456------------------------------------------- 5457 Hash Left Join 5458 Output: i.f1, j.f1 5459 Hash Cond: (i.f1 = j.f1) 5460 -> Seq Scan on public.int4_tbl i 5461 Output: i.f1 5462 -> Hash 5463 Output: j.f1 5464 -> Seq Scan on public.int2_tbl j 5465 Output: j.f1 5466(9 rows) 5467 5468select * from int4_tbl i left join 5469 lateral (select * from int2_tbl j where i.f1 = j.f1) k on true; 5470 f1 | f1 5471-------------+---- 5472 0 | 0 5473 123456 | 5474 -123456 | 5475 2147483647 | 5476 -2147483647 | 5477(5 rows) 5478 5479explain (verbose, costs off) 5480select * from int4_tbl i left join 5481 lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true; 5482 QUERY PLAN 5483------------------------------------- 5484 Nested Loop Left Join 5485 Output: i.f1, (COALESCE(i.*)) 5486 -> Seq Scan on public.int4_tbl i 5487 Output: i.f1, i.* 5488 -> Seq Scan on public.int2_tbl j 5489 Output: j.f1, COALESCE(i.*) 5490 Filter: (i.f1 = j.f1) 5491(7 rows) 5492 5493select * from int4_tbl i left join 5494 lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true; 5495 f1 | coalesce 5496-------------+---------- 5497 0 | (0) 5498 123456 | 5499 -123456 | 5500 2147483647 | 5501 -2147483647 | 5502(5 rows) 5503 5504explain (verbose, costs off) 5505select * from int4_tbl a, 5506 lateral ( 5507 select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2) 5508 ) ss; 5509 QUERY PLAN 5510------------------------------------------------- 5511 Nested Loop 5512 Output: a.f1, b.f1, c.q1, c.q2 5513 -> Seq Scan on public.int4_tbl a 5514 Output: a.f1 5515 -> Hash Left Join 5516 Output: b.f1, c.q1, c.q2 5517 Hash Cond: (b.f1 = c.q1) 5518 -> Seq Scan on public.int4_tbl b 5519 Output: b.f1 5520 -> Hash 5521 Output: c.q1, c.q2 5522 -> Seq Scan on public.int8_tbl c 5523 Output: c.q1, c.q2 5524 Filter: (a.f1 = c.q2) 5525(14 rows) 5526 5527select * from int4_tbl a, 5528 lateral ( 5529 select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2) 5530 ) ss; 5531 f1 | f1 | q1 | q2 5532-------------+-------------+----+---- 5533 0 | 0 | | 5534 0 | 123456 | | 5535 0 | -123456 | | 5536 0 | 2147483647 | | 5537 0 | -2147483647 | | 5538 123456 | 0 | | 5539 123456 | 123456 | | 5540 123456 | -123456 | | 5541 123456 | 2147483647 | | 5542 123456 | -2147483647 | | 5543 -123456 | 0 | | 5544 -123456 | 123456 | | 5545 -123456 | -123456 | | 5546 -123456 | 2147483647 | | 5547 -123456 | -2147483647 | | 5548 2147483647 | 0 | | 5549 2147483647 | 123456 | | 5550 2147483647 | -123456 | | 5551 2147483647 | 2147483647 | | 5552 2147483647 | -2147483647 | | 5553 -2147483647 | 0 | | 5554 -2147483647 | 123456 | | 5555 -2147483647 | -123456 | | 5556 -2147483647 | 2147483647 | | 5557 -2147483647 | -2147483647 | | 5558(25 rows) 5559 5560-- lateral reference in a PlaceHolderVar evaluated at join level 5561explain (verbose, costs off) 5562select * from 5563 int8_tbl a left join lateral 5564 (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from 5565 int8_tbl b cross join int8_tbl c) ss 5566 on a.q2 = ss.bq1; 5567 QUERY PLAN 5568------------------------------------------------------------- 5569 Nested Loop Left Join 5570 Output: a.q1, a.q2, b.q1, c.q1, (LEAST(a.q1, b.q1, c.q1)) 5571 -> Seq Scan on public.int8_tbl a 5572 Output: a.q1, a.q2 5573 -> Nested Loop 5574 Output: b.q1, c.q1, LEAST(a.q1, b.q1, c.q1) 5575 -> Seq Scan on public.int8_tbl b 5576 Output: b.q1, b.q2 5577 Filter: (a.q2 = b.q1) 5578 -> Seq Scan on public.int8_tbl c 5579 Output: c.q1, c.q2 5580(11 rows) 5581 5582select * from 5583 int8_tbl a left join lateral 5584 (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from 5585 int8_tbl b cross join int8_tbl c) ss 5586 on a.q2 = ss.bq1; 5587 q1 | q2 | bq1 | cq1 | least 5588------------------+-------------------+------------------+------------------+------------------ 5589 123 | 456 | | | 5590 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5591 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5592 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5593 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5594 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5595 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5596 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5597 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5598 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5599 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5600 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5601 123 | 4567890123456789 | 4567890123456789 | 123 | 123 5602 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5603 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5604 123 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 5605 4567890123456789 | 123 | 123 | 123 | 123 5606 4567890123456789 | 123 | 123 | 123 | 123 5607 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5608 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5609 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5610 4567890123456789 | 123 | 123 | 123 | 123 5611 4567890123456789 | 123 | 123 | 123 | 123 5612 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5613 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5614 4567890123456789 | 123 | 123 | 4567890123456789 | 123 5615 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 5616 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 5617 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5618 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5619 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5620 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 5621 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 5622 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5623 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5624 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5625 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 5626 4567890123456789 | 4567890123456789 | 4567890123456789 | 123 | 123 5627 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5628 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5629 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5630 4567890123456789 | -4567890123456789 | | | 5631(42 rows) 5632 5633-- case requiring nested PlaceHolderVars 5634explain (verbose, costs off) 5635select * from 5636 int8_tbl c left join ( 5637 int8_tbl a left join (select q1, coalesce(q2,42) as x from int8_tbl b) ss1 5638 on a.q2 = ss1.q1 5639 cross join 5640 lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2 5641 ) on c.q2 = ss2.q1, 5642 lateral (select ss2.y offset 0) ss3; 5643 QUERY PLAN 5644------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 5645 Nested Loop 5646 Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)), ((COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))) 5647 -> Hash Right Join 5648 Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) 5649 Hash Cond: (d.q1 = c.q2) 5650 -> Nested Loop 5651 Output: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) 5652 -> Hash Left Join 5653 Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)) 5654 Hash Cond: (a.q2 = b.q1) 5655 -> Seq Scan on public.int8_tbl a 5656 Output: a.q1, a.q2 5657 -> Hash 5658 Output: b.q1, (COALESCE(b.q2, '42'::bigint)) 5659 -> Seq Scan on public.int8_tbl b 5660 Output: b.q1, COALESCE(b.q2, '42'::bigint) 5661 -> Seq Scan on public.int8_tbl d 5662 Output: d.q1, COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2) 5663 -> Hash 5664 Output: c.q1, c.q2 5665 -> Seq Scan on public.int8_tbl c 5666 Output: c.q1, c.q2 5667 -> Result 5668 Output: (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)) 5669(24 rows) 5670 5671-- case that breaks the old ph_may_need optimization 5672explain (verbose, costs off) 5673select c.*,a.*,ss1.q1,ss2.q1,ss3.* from 5674 int8_tbl c left join ( 5675 int8_tbl a left join 5676 (select q1, coalesce(q2,f1) as x from int8_tbl b, int4_tbl b2 5677 where q1 < f1) ss1 5678 on a.q2 = ss1.q1 5679 cross join 5680 lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2 5681 ) on c.q2 = ss2.q1, 5682 lateral (select * from int4_tbl i where ss2.y > f1) ss3; 5683 QUERY PLAN 5684--------------------------------------------------------------------------------------------------------- 5685 Nested Loop 5686 Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, i.f1 5687 Join Filter: ((COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) > i.f1) 5688 -> Hash Right Join 5689 Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) 5690 Hash Cond: (d.q1 = c.q2) 5691 -> Nested Loop 5692 Output: a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) 5693 -> Hash Right Join 5694 Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, (b2.f1)::bigint)) 5695 Hash Cond: (b.q1 = a.q2) 5696 -> Nested Loop 5697 Output: b.q1, COALESCE(b.q2, (b2.f1)::bigint) 5698 Join Filter: (b.q1 < b2.f1) 5699 -> Seq Scan on public.int8_tbl b 5700 Output: b.q1, b.q2 5701 -> Materialize 5702 Output: b2.f1 5703 -> Seq Scan on public.int4_tbl b2 5704 Output: b2.f1 5705 -> Hash 5706 Output: a.q1, a.q2 5707 -> Seq Scan on public.int8_tbl a 5708 Output: a.q1, a.q2 5709 -> Seq Scan on public.int8_tbl d 5710 Output: d.q1, COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2) 5711 -> Hash 5712 Output: c.q1, c.q2 5713 -> Seq Scan on public.int8_tbl c 5714 Output: c.q1, c.q2 5715 -> Materialize 5716 Output: i.f1 5717 -> Seq Scan on public.int4_tbl i 5718 Output: i.f1 5719(34 rows) 5720 5721-- check processing of postponed quals (bug #9041) 5722explain (verbose, costs off) 5723select * from 5724 (select 1 as x offset 0) x cross join (select 2 as y offset 0) y 5725 left join lateral ( 5726 select * from (select 3 as z offset 0) z where z.z = x.x 5727 ) zz on zz.z = y.y; 5728 QUERY PLAN 5729---------------------------------------------- 5730 Nested Loop Left Join 5731 Output: (1), (2), (3) 5732 Join Filter: (((3) = (1)) AND ((3) = (2))) 5733 -> Nested Loop 5734 Output: (1), (2) 5735 -> Result 5736 Output: 1 5737 -> Result 5738 Output: 2 5739 -> Result 5740 Output: 3 5741(11 rows) 5742 5743-- check dummy rels with lateral references (bug #15694) 5744explain (verbose, costs off) 5745select * from int8_tbl i8 left join lateral 5746 (select *, i8.q2 from int4_tbl where false) ss on true; 5747 QUERY PLAN 5748-------------------------------------- 5749 Nested Loop Left Join 5750 Output: i8.q1, i8.q2, f1, (i8.q2) 5751 -> Seq Scan on public.int8_tbl i8 5752 Output: i8.q1, i8.q2 5753 -> Result 5754 Output: f1, i8.q2 5755 One-Time Filter: false 5756(7 rows) 5757 5758explain (verbose, costs off) 5759select * from int8_tbl i8 left join lateral 5760 (select *, i8.q2 from int4_tbl i1, int4_tbl i2 where false) ss on true; 5761 QUERY PLAN 5762----------------------------------------- 5763 Nested Loop Left Join 5764 Output: i8.q1, i8.q2, f1, f1, (i8.q2) 5765 -> Seq Scan on public.int8_tbl i8 5766 Output: i8.q1, i8.q2 5767 -> Result 5768 Output: f1, f1, i8.q2 5769 One-Time Filter: false 5770(7 rows) 5771 5772-- check handling of nested appendrels inside LATERAL 5773select * from 5774 ((select 2 as v) union all (select 3 as v)) as q1 5775 cross join lateral 5776 ((select * from 5777 ((select 4 as v) union all (select 5 as v)) as q3) 5778 union all 5779 (select q1.v) 5780 ) as q2; 5781 v | v 5782---+--- 5783 2 | 4 5784 2 | 5 5785 2 | 2 5786 3 | 4 5787 3 | 5 5788 3 | 3 5789(6 rows) 5790 5791-- check we don't try to do a unique-ified semijoin with LATERAL 5792explain (verbose, costs off) 5793select * from 5794 (values (0,9998), (1,1000)) v(id,x), 5795 lateral (select f1 from int4_tbl 5796 where f1 = any (select unique1 from tenk1 5797 where unique2 = v.x offset 0)) ss; 5798 QUERY PLAN 5799---------------------------------------------------------------------- 5800 Nested Loop 5801 Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1 5802 -> Values Scan on "*VALUES*" 5803 Output: "*VALUES*".column1, "*VALUES*".column2 5804 -> Nested Loop Semi Join 5805 Output: int4_tbl.f1 5806 Join Filter: (int4_tbl.f1 = tenk1.unique1) 5807 -> Seq Scan on public.int4_tbl 5808 Output: int4_tbl.f1 5809 -> Materialize 5810 Output: tenk1.unique1 5811 -> Index Scan using tenk1_unique2 on public.tenk1 5812 Output: tenk1.unique1 5813 Index Cond: (tenk1.unique2 = "*VALUES*".column2) 5814(14 rows) 5815 5816select * from 5817 (values (0,9998), (1,1000)) v(id,x), 5818 lateral (select f1 from int4_tbl 5819 where f1 = any (select unique1 from tenk1 5820 where unique2 = v.x offset 0)) ss; 5821 id | x | f1 5822----+------+---- 5823 0 | 9998 | 0 5824(1 row) 5825 5826-- check proper extParam/allParam handling (this isn't exactly a LATERAL issue, 5827-- but we can make the test case much more compact with LATERAL) 5828explain (verbose, costs off) 5829select * from (values (0), (1)) v(id), 5830lateral (select * from int8_tbl t1, 5831 lateral (select * from 5832 (select * from int8_tbl t2 5833 where q1 = any (select q2 from int8_tbl t3 5834 where q2 = (select greatest(t1.q1,t2.q2)) 5835 and (select v.id=0)) offset 0) ss2) ss 5836 where t1.q1 = ss.q2) ss0; 5837 QUERY PLAN 5838----------------------------------------------------------------- 5839 Nested Loop 5840 Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2 5841 -> Seq Scan on public.int8_tbl t1 5842 Output: t1.q1, t1.q2 5843 -> Nested Loop 5844 Output: "*VALUES*".column1, ss2.q1, ss2.q2 5845 -> Values Scan on "*VALUES*" 5846 Output: "*VALUES*".column1 5847 -> Subquery Scan on ss2 5848 Output: ss2.q1, ss2.q2 5849 Filter: (t1.q1 = ss2.q2) 5850 -> Seq Scan on public.int8_tbl t2 5851 Output: t2.q1, t2.q2 5852 Filter: (SubPlan 3) 5853 SubPlan 3 5854 -> Result 5855 Output: t3.q2 5856 One-Time Filter: $4 5857 InitPlan 1 (returns $2) 5858 -> Result 5859 Output: GREATEST($0, t2.q2) 5860 InitPlan 2 (returns $4) 5861 -> Result 5862 Output: ($3 = 0) 5863 -> Seq Scan on public.int8_tbl t3 5864 Output: t3.q1, t3.q2 5865 Filter: (t3.q2 = $2) 5866(27 rows) 5867 5868select * from (values (0), (1)) v(id), 5869lateral (select * from int8_tbl t1, 5870 lateral (select * from 5871 (select * from int8_tbl t2 5872 where q1 = any (select q2 from int8_tbl t3 5873 where q2 = (select greatest(t1.q1,t2.q2)) 5874 and (select v.id=0)) offset 0) ss2) ss 5875 where t1.q1 = ss.q2) ss0; 5876 id | q1 | q2 | q1 | q2 5877----+------------------+-------------------+------------------+------------------ 5878 0 | 4567890123456789 | 123 | 4567890123456789 | 4567890123456789 5879 0 | 4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789 5880 0 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 5881(3 rows) 5882 5883-- test some error cases where LATERAL should have been used but wasn't 5884select f1,g from int4_tbl a, (select f1 as g) ss; 5885ERROR: column "f1" does not exist 5886LINE 1: select f1,g from int4_tbl a, (select f1 as g) ss; 5887 ^ 5888HINT: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. 5889select f1,g from int4_tbl a, (select a.f1 as g) ss; 5890ERROR: invalid reference to FROM-clause entry for table "a" 5891LINE 1: select f1,g from int4_tbl a, (select a.f1 as g) ss; 5892 ^ 5893HINT: There is an entry for table "a", but it cannot be referenced from this part of the query. 5894select f1,g from int4_tbl a cross join (select f1 as g) ss; 5895ERROR: column "f1" does not exist 5896LINE 1: select f1,g from int4_tbl a cross join (select f1 as g) ss; 5897 ^ 5898HINT: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. 5899select f1,g from int4_tbl a cross join (select a.f1 as g) ss; 5900ERROR: invalid reference to FROM-clause entry for table "a" 5901LINE 1: select f1,g from int4_tbl a cross join (select a.f1 as g) ss... 5902 ^ 5903HINT: There is an entry for table "a", but it cannot be referenced from this part of the query. 5904-- SQL:2008 says the left table is in scope but illegal to access here 5905select f1,g from int4_tbl a right join lateral generate_series(0, a.f1) g on true; 5906ERROR: invalid reference to FROM-clause entry for table "a" 5907LINE 1: ... int4_tbl a right join lateral generate_series(0, a.f1) g on... 5908 ^ 5909DETAIL: The combining JOIN type must be INNER or LEFT for a LATERAL reference. 5910select f1,g from int4_tbl a full join lateral generate_series(0, a.f1) g on true; 5911ERROR: invalid reference to FROM-clause entry for table "a" 5912LINE 1: ...m int4_tbl a full join lateral generate_series(0, a.f1) g on... 5913 ^ 5914DETAIL: The combining JOIN type must be INNER or LEFT for a LATERAL reference. 5915-- check we complain about ambiguous table references 5916select * from 5917 int8_tbl x cross join (int4_tbl x cross join lateral (select x.f1) ss); 5918ERROR: table reference "x" is ambiguous 5919LINE 2: ...cross join (int4_tbl x cross join lateral (select x.f1) ss); 5920 ^ 5921-- LATERAL can be used to put an aggregate into the FROM clause of its query 5922select 1 from tenk1 a, lateral (select max(a.unique1) from int4_tbl b) ss; 5923ERROR: aggregate functions are not allowed in FROM clause of their own query level 5924LINE 1: select 1 from tenk1 a, lateral (select max(a.unique1) from i... 5925 ^ 5926-- check behavior of LATERAL in UPDATE/DELETE 5927create temp table xx1 as select f1 as x1, -f1 as x2 from int4_tbl; 5928-- error, can't do this: 5929update xx1 set x2 = f1 from (select * from int4_tbl where f1 = x1) ss; 5930ERROR: column "x1" does not exist 5931LINE 1: ... set x2 = f1 from (select * from int4_tbl where f1 = x1) ss; 5932 ^ 5933HINT: There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query. 5934update xx1 set x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss; 5935ERROR: invalid reference to FROM-clause entry for table "xx1" 5936LINE 1: ...t x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss... 5937 ^ 5938HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. 5939-- can't do it even with LATERAL: 5940update xx1 set x2 = f1 from lateral (select * from int4_tbl where f1 = x1) ss; 5941ERROR: invalid reference to FROM-clause entry for table "xx1" 5942LINE 1: ...= f1 from lateral (select * from int4_tbl where f1 = x1) ss; 5943 ^ 5944HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. 5945-- we might in future allow something like this, but for now it's an error: 5946update xx1 set x2 = f1 from xx1, lateral (select * from int4_tbl where f1 = x1) ss; 5947ERROR: table name "xx1" specified more than once 5948-- also errors: 5949delete from xx1 using (select * from int4_tbl where f1 = x1) ss; 5950ERROR: column "x1" does not exist 5951LINE 1: ...te from xx1 using (select * from int4_tbl where f1 = x1) ss; 5952 ^ 5953HINT: There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query. 5954delete from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss; 5955ERROR: invalid reference to FROM-clause entry for table "xx1" 5956LINE 1: ...from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss... 5957 ^ 5958HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. 5959delete from xx1 using lateral (select * from int4_tbl where f1 = x1) ss; 5960ERROR: invalid reference to FROM-clause entry for table "xx1" 5961LINE 1: ...xx1 using lateral (select * from int4_tbl where f1 = x1) ss; 5962 ^ 5963HINT: There is an entry for table "xx1", but it cannot be referenced from this part of the query. 5964-- 5965-- test LATERAL reference propagation down a multi-level inheritance hierarchy 5966-- produced for a multi-level partitioned table hierarchy. 5967-- 5968create table join_pt1 (a int, b int, c varchar) partition by range(a); 5969create table join_pt1p1 partition of join_pt1 for values from (0) to (100) partition by range(b); 5970create table join_pt1p2 partition of join_pt1 for values from (100) to (200); 5971create table join_pt1p1p1 partition of join_pt1p1 for values from (0) to (100); 5972insert into join_pt1 values (1, 1, 'x'), (101, 101, 'y'); 5973create table join_ut1 (a int, b int, c varchar); 5974insert into join_ut1 values (101, 101, 'y'), (2, 2, 'z'); 5975explain (verbose, costs off) 5976select t1.b, ss.phv from join_ut1 t1 left join lateral 5977 (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv 5978 from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss 5979 on t1.a = ss.t2a order by t1.a; 5980 QUERY PLAN 5981-------------------------------------------------------------------- 5982 Sort 5983 Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a 5984 Sort Key: t1.a 5985 -> Nested Loop Left Join 5986 Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a 5987 -> Seq Scan on public.join_ut1 t1 5988 Output: t1.a, t1.b, t1.c 5989 -> Hash Join 5990 Output: t2.a, LEAST(t1.a, t2.a, t3.a) 5991 Hash Cond: (t3.b = t2.a) 5992 -> Seq Scan on public.join_ut1 t3 5993 Output: t3.a, t3.b, t3.c 5994 -> Hash 5995 Output: t2.a 5996 -> Append 5997 -> Seq Scan on public.join_pt1p1p1 t2_1 5998 Output: t2_1.a 5999 Filter: (t1.a = t2_1.a) 6000 -> Seq Scan on public.join_pt1p2 t2_2 6001 Output: t2_2.a 6002 Filter: (t1.a = t2_2.a) 6003(21 rows) 6004 6005select t1.b, ss.phv from join_ut1 t1 left join lateral 6006 (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv 6007 from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss 6008 on t1.a = ss.t2a order by t1.a; 6009 b | phv 6010-----+----- 6011 2 | 6012 101 | 101 6013(2 rows) 6014 6015drop table join_pt1; 6016drop table join_ut1; 6017-- 6018-- test that foreign key join estimation performs sanely for outer joins 6019-- 6020begin; 6021create table fkest (a int, b int, c int unique, primary key(a,b)); 6022create table fkest1 (a int, b int, primary key(a,b)); 6023insert into fkest select x/10, x%10, x from generate_series(1,1000) x; 6024insert into fkest1 select x/10, x%10 from generate_series(1,1000) x; 6025alter table fkest1 6026 add constraint fkest1_a_b_fkey foreign key (a,b) references fkest; 6027analyze fkest; 6028analyze fkest1; 6029explain (costs off) 6030select * 6031from fkest f 6032 left join fkest1 f1 on f.a = f1.a and f.b = f1.b 6033 left join fkest1 f2 on f.a = f2.a and f.b = f2.b 6034 left join fkest1 f3 on f.a = f3.a and f.b = f3.b 6035where f.c = 1; 6036 QUERY PLAN 6037------------------------------------------------------------------ 6038 Nested Loop Left Join 6039 -> Nested Loop Left Join 6040 -> Nested Loop Left Join 6041 -> Index Scan using fkest_c_key on fkest f 6042 Index Cond: (c = 1) 6043 -> Index Only Scan using fkest1_pkey on fkest1 f1 6044 Index Cond: ((a = f.a) AND (b = f.b)) 6045 -> Index Only Scan using fkest1_pkey on fkest1 f2 6046 Index Cond: ((a = f.a) AND (b = f.b)) 6047 -> Index Only Scan using fkest1_pkey on fkest1 f3 6048 Index Cond: ((a = f.a) AND (b = f.b)) 6049(11 rows) 6050 6051rollback; 6052-- 6053-- test planner's ability to mark joins as unique 6054-- 6055create table j1 (id int primary key); 6056create table j2 (id int primary key); 6057create table j3 (id int); 6058insert into j1 values(1),(2),(3); 6059insert into j2 values(1),(2),(3); 6060insert into j3 values(1),(1); 6061analyze j1; 6062analyze j2; 6063analyze j3; 6064-- ensure join is properly marked as unique 6065explain (verbose, costs off) 6066select * from j1 inner join j2 on j1.id = j2.id; 6067 QUERY PLAN 6068----------------------------------- 6069 Hash Join 6070 Output: j1.id, j2.id 6071 Inner Unique: true 6072 Hash Cond: (j1.id = j2.id) 6073 -> Seq Scan on public.j1 6074 Output: j1.id 6075 -> Hash 6076 Output: j2.id 6077 -> Seq Scan on public.j2 6078 Output: j2.id 6079(10 rows) 6080 6081-- ensure join is not unique when not an equi-join 6082explain (verbose, costs off) 6083select * from j1 inner join j2 on j1.id > j2.id; 6084 QUERY PLAN 6085----------------------------------- 6086 Nested Loop 6087 Output: j1.id, j2.id 6088 Join Filter: (j1.id > j2.id) 6089 -> Seq Scan on public.j1 6090 Output: j1.id 6091 -> Materialize 6092 Output: j2.id 6093 -> Seq Scan on public.j2 6094 Output: j2.id 6095(9 rows) 6096 6097-- ensure non-unique rel is not chosen as inner 6098explain (verbose, costs off) 6099select * from j1 inner join j3 on j1.id = j3.id; 6100 QUERY PLAN 6101----------------------------------- 6102 Hash Join 6103 Output: j1.id, j3.id 6104 Inner Unique: true 6105 Hash Cond: (j3.id = j1.id) 6106 -> Seq Scan on public.j3 6107 Output: j3.id 6108 -> Hash 6109 Output: j1.id 6110 -> Seq Scan on public.j1 6111 Output: j1.id 6112(10 rows) 6113 6114-- ensure left join is marked as unique 6115explain (verbose, costs off) 6116select * from j1 left join j2 on j1.id = j2.id; 6117 QUERY PLAN 6118----------------------------------- 6119 Hash Left Join 6120 Output: j1.id, j2.id 6121 Inner Unique: true 6122 Hash Cond: (j1.id = j2.id) 6123 -> Seq Scan on public.j1 6124 Output: j1.id 6125 -> Hash 6126 Output: j2.id 6127 -> Seq Scan on public.j2 6128 Output: j2.id 6129(10 rows) 6130 6131-- ensure right join is marked as unique 6132explain (verbose, costs off) 6133select * from j1 right join j2 on j1.id = j2.id; 6134 QUERY PLAN 6135----------------------------------- 6136 Hash Left Join 6137 Output: j1.id, j2.id 6138 Inner Unique: true 6139 Hash Cond: (j2.id = j1.id) 6140 -> Seq Scan on public.j2 6141 Output: j2.id 6142 -> Hash 6143 Output: j1.id 6144 -> Seq Scan on public.j1 6145 Output: j1.id 6146(10 rows) 6147 6148-- ensure full join is marked as unique 6149explain (verbose, costs off) 6150select * from j1 full join j2 on j1.id = j2.id; 6151 QUERY PLAN 6152----------------------------------- 6153 Hash Full Join 6154 Output: j1.id, j2.id 6155 Inner Unique: true 6156 Hash Cond: (j1.id = j2.id) 6157 -> Seq Scan on public.j1 6158 Output: j1.id 6159 -> Hash 6160 Output: j2.id 6161 -> Seq Scan on public.j2 6162 Output: j2.id 6163(10 rows) 6164 6165-- a clauseless (cross) join can't be unique 6166explain (verbose, costs off) 6167select * from j1 cross join j2; 6168 QUERY PLAN 6169----------------------------------- 6170 Nested Loop 6171 Output: j1.id, j2.id 6172 -> Seq Scan on public.j1 6173 Output: j1.id 6174 -> Materialize 6175 Output: j2.id 6176 -> Seq Scan on public.j2 6177 Output: j2.id 6178(8 rows) 6179 6180-- ensure a natural join is marked as unique 6181explain (verbose, costs off) 6182select * from j1 natural join j2; 6183 QUERY PLAN 6184----------------------------------- 6185 Hash Join 6186 Output: j1.id 6187 Inner Unique: true 6188 Hash Cond: (j1.id = j2.id) 6189 -> Seq Scan on public.j1 6190 Output: j1.id 6191 -> Hash 6192 Output: j2.id 6193 -> Seq Scan on public.j2 6194 Output: j2.id 6195(10 rows) 6196 6197-- ensure a distinct clause allows the inner to become unique 6198explain (verbose, costs off) 6199select * from j1 6200inner join (select distinct id from j3) j3 on j1.id = j3.id; 6201 QUERY PLAN 6202----------------------------------------- 6203 Nested Loop 6204 Output: j1.id, j3.id 6205 Inner Unique: true 6206 Join Filter: (j1.id = j3.id) 6207 -> Unique 6208 Output: j3.id 6209 -> Sort 6210 Output: j3.id 6211 Sort Key: j3.id 6212 -> Seq Scan on public.j3 6213 Output: j3.id 6214 -> Seq Scan on public.j1 6215 Output: j1.id 6216(13 rows) 6217 6218-- ensure group by clause allows the inner to become unique 6219explain (verbose, costs off) 6220select * from j1 6221inner join (select id from j3 group by id) j3 on j1.id = j3.id; 6222 QUERY PLAN 6223----------------------------------------- 6224 Nested Loop 6225 Output: j1.id, j3.id 6226 Inner Unique: true 6227 Join Filter: (j1.id = j3.id) 6228 -> Group 6229 Output: j3.id 6230 Group Key: j3.id 6231 -> Sort 6232 Output: j3.id 6233 Sort Key: j3.id 6234 -> Seq Scan on public.j3 6235 Output: j3.id 6236 -> Seq Scan on public.j1 6237 Output: j1.id 6238(14 rows) 6239 6240drop table j1; 6241drop table j2; 6242drop table j3; 6243-- test more complex permutations of unique joins 6244create table j1 (id1 int, id2 int, primary key(id1,id2)); 6245create table j2 (id1 int, id2 int, primary key(id1,id2)); 6246create table j3 (id1 int, id2 int, primary key(id1,id2)); 6247insert into j1 values(1,1),(1,2); 6248insert into j2 values(1,1); 6249insert into j3 values(1,1); 6250analyze j1; 6251analyze j2; 6252analyze j3; 6253-- ensure there's no unique join when not all columns which are part of the 6254-- unique index are seen in the join clause 6255explain (verbose, costs off) 6256select * from j1 6257inner join j2 on j1.id1 = j2.id1; 6258 QUERY PLAN 6259------------------------------------------ 6260 Nested Loop 6261 Output: j1.id1, j1.id2, j2.id1, j2.id2 6262 Join Filter: (j1.id1 = j2.id1) 6263 -> Seq Scan on public.j2 6264 Output: j2.id1, j2.id2 6265 -> Seq Scan on public.j1 6266 Output: j1.id1, j1.id2 6267(7 rows) 6268 6269-- ensure proper unique detection with multiple join quals 6270explain (verbose, costs off) 6271select * from j1 6272inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2; 6273 QUERY PLAN 6274---------------------------------------------------------- 6275 Nested Loop 6276 Output: j1.id1, j1.id2, j2.id1, j2.id2 6277 Inner Unique: true 6278 Join Filter: ((j1.id1 = j2.id1) AND (j1.id2 = j2.id2)) 6279 -> Seq Scan on public.j2 6280 Output: j2.id1, j2.id2 6281 -> Seq Scan on public.j1 6282 Output: j1.id1, j1.id2 6283(8 rows) 6284 6285-- ensure we don't detect the join to be unique when quals are not part of the 6286-- join condition 6287explain (verbose, costs off) 6288select * from j1 6289inner join j2 on j1.id1 = j2.id1 where j1.id2 = 1; 6290 QUERY PLAN 6291------------------------------------------ 6292 Nested Loop 6293 Output: j1.id1, j1.id2, j2.id1, j2.id2 6294 Join Filter: (j1.id1 = j2.id1) 6295 -> Seq Scan on public.j1 6296 Output: j1.id1, j1.id2 6297 Filter: (j1.id2 = 1) 6298 -> Seq Scan on public.j2 6299 Output: j2.id1, j2.id2 6300(8 rows) 6301 6302-- as above, but for left joins. 6303explain (verbose, costs off) 6304select * from j1 6305left join j2 on j1.id1 = j2.id1 where j1.id2 = 1; 6306 QUERY PLAN 6307------------------------------------------ 6308 Nested Loop Left Join 6309 Output: j1.id1, j1.id2, j2.id1, j2.id2 6310 Join Filter: (j1.id1 = j2.id1) 6311 -> Seq Scan on public.j1 6312 Output: j1.id1, j1.id2 6313 Filter: (j1.id2 = 1) 6314 -> Seq Scan on public.j2 6315 Output: j2.id1, j2.id2 6316(8 rows) 6317 6318-- validate logic in merge joins which skips mark and restore. 6319-- it should only do this if all quals which were used to detect the unique 6320-- are present as join quals, and not plain quals. 6321set enable_nestloop to 0; 6322set enable_hashjoin to 0; 6323set enable_sort to 0; 6324-- create indexes that will be preferred over the PKs to perform the join 6325create index j1_id1_idx on j1 (id1) where id1 % 1000 = 1; 6326create index j2_id1_idx on j2 (id1) where id1 % 1000 = 1; 6327-- need an additional row in j2, if we want j2_id1_idx to be preferred 6328insert into j2 values(1,2); 6329analyze j2; 6330explain (costs off) select * from j1 6331inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 6332where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1; 6333 QUERY PLAN 6334----------------------------------------- 6335 Merge Join 6336 Merge Cond: (j1.id1 = j2.id1) 6337 Join Filter: (j1.id2 = j2.id2) 6338 -> Index Scan using j1_id1_idx on j1 6339 -> Index Scan using j2_id1_idx on j2 6340(5 rows) 6341 6342select * from j1 6343inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 6344where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1; 6345 id1 | id2 | id1 | id2 6346-----+-----+-----+----- 6347 1 | 1 | 1 | 1 6348 1 | 2 | 1 | 2 6349(2 rows) 6350 6351-- Exercise array keys mark/restore B-Tree code 6352explain (costs off) select * from j1 6353inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 6354where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 = any (array[1]); 6355 QUERY PLAN 6356---------------------------------------------------- 6357 Merge Join 6358 Merge Cond: (j1.id1 = j2.id1) 6359 Join Filter: (j1.id2 = j2.id2) 6360 -> Index Scan using j1_id1_idx on j1 6361 -> Index Scan using j2_id1_idx on j2 6362 Index Cond: (id1 = ANY ('{1}'::integer[])) 6363(6 rows) 6364 6365select * from j1 6366inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 6367where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 = any (array[1]); 6368 id1 | id2 | id1 | id2 6369-----+-----+-----+----- 6370 1 | 1 | 1 | 1 6371 1 | 2 | 1 | 2 6372(2 rows) 6373 6374-- Exercise array keys "find extreme element" B-Tree code 6375explain (costs off) select * from j1 6376inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 6377where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 >= any (array[1,5]); 6378 QUERY PLAN 6379------------------------------------------------------- 6380 Merge Join 6381 Merge Cond: (j1.id1 = j2.id1) 6382 Join Filter: (j1.id2 = j2.id2) 6383 -> Index Scan using j1_id1_idx on j1 6384 -> Index Only Scan using j2_pkey on j2 6385 Index Cond: (id1 >= ANY ('{1,5}'::integer[])) 6386 Filter: ((id1 % 1000) = 1) 6387(7 rows) 6388 6389select * from j1 6390inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2 6391where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 >= any (array[1,5]); 6392 id1 | id2 | id1 | id2 6393-----+-----+-----+----- 6394 1 | 1 | 1 | 1 6395 1 | 2 | 1 | 2 6396(2 rows) 6397 6398reset enable_nestloop; 6399reset enable_hashjoin; 6400reset enable_sort; 6401drop table j1; 6402drop table j2; 6403drop table j3; 6404-- check that semijoin inner is not seen as unique for a portion of the outerrel 6405explain (verbose, costs off) 6406select t1.unique1, t2.hundred 6407from onek t1, tenk1 t2 6408where exists (select 1 from tenk1 t3 6409 where t3.thousand = t1.unique1 and t3.tenthous = t2.hundred) 6410 and t1.unique1 < 1; 6411 QUERY PLAN 6412--------------------------------------------------------------------------------- 6413 Nested Loop 6414 Output: t1.unique1, t2.hundred 6415 -> Hash Join 6416 Output: t1.unique1, t3.tenthous 6417 Hash Cond: (t3.thousand = t1.unique1) 6418 -> HashAggregate 6419 Output: t3.thousand, t3.tenthous 6420 Group Key: t3.thousand, t3.tenthous 6421 -> Index Only Scan using tenk1_thous_tenthous on public.tenk1 t3 6422 Output: t3.thousand, t3.tenthous 6423 -> Hash 6424 Output: t1.unique1 6425 -> Index Only Scan using onek_unique1 on public.onek t1 6426 Output: t1.unique1 6427 Index Cond: (t1.unique1 < 1) 6428 -> Index Only Scan using tenk1_hundred on public.tenk1 t2 6429 Output: t2.hundred 6430 Index Cond: (t2.hundred = t3.tenthous) 6431(18 rows) 6432 6433-- ... unless it actually is unique 6434create table j3 as select unique1, tenthous from onek; 6435vacuum analyze j3; 6436create unique index on j3(unique1, tenthous); 6437explain (verbose, costs off) 6438select t1.unique1, t2.hundred 6439from onek t1, tenk1 t2 6440where exists (select 1 from j3 6441 where j3.unique1 = t1.unique1 and j3.tenthous = t2.hundred) 6442 and t1.unique1 < 1; 6443 QUERY PLAN 6444------------------------------------------------------------------------ 6445 Nested Loop 6446 Output: t1.unique1, t2.hundred 6447 -> Nested Loop 6448 Output: t1.unique1, j3.tenthous 6449 -> Index Only Scan using onek_unique1 on public.onek t1 6450 Output: t1.unique1 6451 Index Cond: (t1.unique1 < 1) 6452 -> Index Only Scan using j3_unique1_tenthous_idx on public.j3 6453 Output: j3.unique1, j3.tenthous 6454 Index Cond: (j3.unique1 = t1.unique1) 6455 -> Index Only Scan using tenk1_hundred on public.tenk1 t2 6456 Output: t2.hundred 6457 Index Cond: (t2.hundred = j3.tenthous) 6458(13 rows) 6459 6460drop table j3; 6461