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 *
44  FROM J1_TBL AS tx;
45 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 *
61  FROM J1_TBL tx;
62 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 *
78  FROM J1_TBL AS t1 (a, b, c);
79 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 *
95  FROM J1_TBL t1 (a, b, c);
96 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 *
112  FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e);
113 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 t1.a, t2.e
217  FROM J1_TBL t1 (a, b, c), J2_TBL t2 (d, e)
218  WHERE t1.a = t2.d;
219 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 *
236  FROM J1_TBL CROSS JOIN J2_TBL;
237 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 i, k, t
342  FROM J1_TBL CROSS JOIN J2_TBL;
343ERROR:  column reference "i" is ambiguous
344LINE 1: SELECT i, k, t
345               ^
346-- resolve previous ambiguity by specifying the table name
347SELECT t1.i, k, t
348  FROM J1_TBL t1 CROSS JOIN J2_TBL t2;
349 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 ii, tt, kk
453  FROM (J1_TBL CROSS JOIN J2_TBL)
454    AS tx (ii, jj, tt, ii2, kk);
455 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 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 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 *
665  FROM J1_TBL CROSS JOIN J2_TBL a CROSS JOIN J2_TBL b;
666 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 *
1573  FROM J1_TBL INNER JOIN J2_TBL USING (i);
1574 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 *
1587  FROM J1_TBL JOIN J2_TBL USING (i);
1588 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 *
1600  FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, d) USING (a)
1601  ORDER BY a, d;
1602 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 *
1614  FROM J1_TBL t1 (a, b, c) JOIN J2_TBL t2 (a, b) USING (b)
1615  ORDER BY b, t1.a;
1616 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-- test join using aliases
1625SELECT * FROM J1_TBL JOIN J2_TBL USING (i) WHERE J1_TBL.t = 'one';  -- ok
1626 i | j |  t  | k
1627---+---+-----+----
1628 1 | 4 | one | -1
1629(1 row)
1630
1631SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one';  -- ok
1632 i | j |  t  | k
1633---+---+-----+----
1634 1 | 4 | one | -1
1635(1 row)
1636
1637SELECT * FROM (J1_TBL JOIN J2_TBL USING (i)) AS x WHERE J1_TBL.t = 'one';  -- error
1638ERROR:  invalid reference to FROM-clause entry for table "j1_tbl"
1639LINE 1: ... * FROM (J1_TBL JOIN J2_TBL USING (i)) AS x WHERE J1_TBL.t =...
1640                                                             ^
1641HINT:  There is an entry for table "j1_tbl", but it cannot be referenced from this part of the query.
1642SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.i = 1;  -- ok
1643 i | j |  t  | k
1644---+---+-----+----
1645 1 | 4 | one | -1
1646(1 row)
1647
1648SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.t = 'one';  -- error
1649ERROR:  column x.t does not exist
1650LINE 1: ...CT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.t = 'one...
1651                                                             ^
1652SELECT * FROM (J1_TBL JOIN J2_TBL USING (i) AS x) AS xx WHERE x.i = 1;  -- error (XXX could use better hint)
1653ERROR:  missing FROM-clause entry for table "x"
1654LINE 1: ...ROM (J1_TBL JOIN J2_TBL USING (i) AS x) AS xx WHERE x.i = 1;
1655                                                               ^
1656SELECT * FROM J1_TBL a1 JOIN J2_TBL a2 USING (i) AS a1;  -- error
1657ERROR:  table name "a1" specified more than once
1658SELECT x.* FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one';
1659 i
1660---
1661 1
1662(1 row)
1663
1664SELECT ROW(x.*) FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one';
1665 row
1666-----
1667 (1)
1668(1 row)
1669
1670SELECT row_to_json(x.*) FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one';
1671 row_to_json
1672-------------
1673 {"i":1}
1674(1 row)
1675
1676--
1677-- NATURAL JOIN
1678-- Inner equi-join on all columns with the same name
1679--
1680SELECT *
1681  FROM J1_TBL NATURAL JOIN J2_TBL;
1682 i | j |   t   | k
1683---+---+-------+----
1684 0 |   | zero  |
1685 1 | 4 | one   | -1
1686 2 | 3 | two   |  2
1687 2 | 3 | two   |  4
1688 3 | 2 | three | -3
1689 5 | 0 | five  | -5
1690 5 | 0 | five  | -5
1691(7 rows)
1692
1693SELECT *
1694  FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (a, d);
1695 a | b |   c   | d
1696---+---+-------+----
1697 0 |   | zero  |
1698 1 | 4 | one   | -1
1699 2 | 3 | two   |  2
1700 2 | 3 | two   |  4
1701 3 | 2 | three | -3
1702 5 | 0 | five  | -5
1703 5 | 0 | five  | -5
1704(7 rows)
1705
1706SELECT *
1707  FROM J1_TBL t1 (a, b, c) NATURAL JOIN J2_TBL t2 (d, a);
1708 a | b |  c   | d
1709---+---+------+---
1710 0 |   | zero |
1711 2 | 3 | two  | 2
1712 4 | 1 | four | 2
1713(3 rows)
1714
1715-- mismatch number of columns
1716-- currently, Postgres will fill in with underlying names
1717SELECT *
1718  FROM J1_TBL t1 (a, b) NATURAL JOIN J2_TBL t2 (a);
1719 a | b |   t   | k
1720---+---+-------+----
1721 0 |   | zero  |
1722 1 | 4 | one   | -1
1723 2 | 3 | two   |  2
1724 2 | 3 | two   |  4
1725 3 | 2 | three | -3
1726 5 | 0 | five  | -5
1727 5 | 0 | five  | -5
1728(7 rows)
1729
1730--
1731-- Inner joins (equi-joins)
1732--
1733SELECT *
1734  FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.i);
1735 i | j |   t   | i | k
1736---+---+-------+---+----
1737 0 |   | zero  | 0 |
1738 1 | 4 | one   | 1 | -1
1739 2 | 3 | two   | 2 |  2
1740 2 | 3 | two   | 2 |  4
1741 3 | 2 | three | 3 | -3
1742 5 | 0 | five  | 5 | -5
1743 5 | 0 | five  | 5 | -5
1744(7 rows)
1745
1746SELECT *
1747  FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i = J2_TBL.k);
1748 i | j |  t   | i | k
1749---+---+------+---+---
1750 0 |   | zero |   | 0
1751 2 | 3 | two  | 2 | 2
1752 4 | 1 | four | 2 | 4
1753(3 rows)
1754
1755--
1756-- Non-equi-joins
1757--
1758SELECT *
1759  FROM J1_TBL JOIN J2_TBL ON (J1_TBL.i <= J2_TBL.k);
1760 i | j |   t   | i | k
1761---+---+-------+---+---
1762 1 | 4 | one   | 2 | 2
1763 2 | 3 | two   | 2 | 2
1764 0 |   | zero  | 2 | 2
1765 1 | 4 | one   | 2 | 4
1766 2 | 3 | two   | 2 | 4
1767 3 | 2 | three | 2 | 4
1768 4 | 1 | four  | 2 | 4
1769 0 |   | zero  | 2 | 4
1770 0 |   | zero  |   | 0
1771(9 rows)
1772
1773--
1774-- Outer joins
1775-- Note that OUTER is a noise word
1776--
1777SELECT *
1778  FROM J1_TBL LEFT OUTER JOIN J2_TBL USING (i)
1779  ORDER BY i, k, t;
1780 i | j |   t   | k
1781---+---+-------+----
1782 0 |   | zero  |
1783 1 | 4 | one   | -1
1784 2 | 3 | two   |  2
1785 2 | 3 | two   |  4
1786 3 | 2 | three | -3
1787 4 | 1 | four  |
1788 5 | 0 | five  | -5
1789 5 | 0 | five  | -5
1790 6 | 6 | six   |
1791 7 | 7 | seven |
1792 8 | 8 | eight |
1793   |   | null  |
1794   | 0 | zero  |
1795(13 rows)
1796
1797SELECT *
1798  FROM J1_TBL LEFT JOIN J2_TBL USING (i)
1799  ORDER BY i, k, t;
1800 i | j |   t   | k
1801---+---+-------+----
1802 0 |   | zero  |
1803 1 | 4 | one   | -1
1804 2 | 3 | two   |  2
1805 2 | 3 | two   |  4
1806 3 | 2 | three | -3
1807 4 | 1 | four  |
1808 5 | 0 | five  | -5
1809 5 | 0 | five  | -5
1810 6 | 6 | six   |
1811 7 | 7 | seven |
1812 8 | 8 | eight |
1813   |   | null  |
1814   | 0 | zero  |
1815(13 rows)
1816
1817SELECT *
1818  FROM J1_TBL RIGHT OUTER JOIN J2_TBL USING (i);
1819 i | j |   t   | k
1820---+---+-------+----
1821 0 |   | zero  |
1822 1 | 4 | one   | -1
1823 2 | 3 | two   |  2
1824 2 | 3 | two   |  4
1825 3 | 2 | three | -3
1826 5 | 0 | five  | -5
1827 5 | 0 | five  | -5
1828   |   |       |
1829   |   |       |  0
1830(9 rows)
1831
1832SELECT *
1833  FROM J1_TBL RIGHT JOIN J2_TBL USING (i);
1834 i | j |   t   | k
1835---+---+-------+----
1836 0 |   | zero  |
1837 1 | 4 | one   | -1
1838 2 | 3 | two   |  2
1839 2 | 3 | two   |  4
1840 3 | 2 | three | -3
1841 5 | 0 | five  | -5
1842 5 | 0 | five  | -5
1843   |   |       |
1844   |   |       |  0
1845(9 rows)
1846
1847SELECT *
1848  FROM J1_TBL FULL OUTER JOIN J2_TBL USING (i)
1849  ORDER BY i, k, t;
1850 i | j |   t   | k
1851---+---+-------+----
1852 0 |   | zero  |
1853 1 | 4 | one   | -1
1854 2 | 3 | two   |  2
1855 2 | 3 | two   |  4
1856 3 | 2 | three | -3
1857 4 | 1 | four  |
1858 5 | 0 | five  | -5
1859 5 | 0 | five  | -5
1860 6 | 6 | six   |
1861 7 | 7 | seven |
1862 8 | 8 | eight |
1863   |   |       |  0
1864   |   | null  |
1865   | 0 | zero  |
1866   |   |       |
1867(15 rows)
1868
1869SELECT *
1870  FROM J1_TBL FULL JOIN J2_TBL USING (i)
1871  ORDER BY i, k, t;
1872 i | j |   t   | k
1873---+---+-------+----
1874 0 |   | zero  |
1875 1 | 4 | one   | -1
1876 2 | 3 | two   |  2
1877 2 | 3 | two   |  4
1878 3 | 2 | three | -3
1879 4 | 1 | four  |
1880 5 | 0 | five  | -5
1881 5 | 0 | five  | -5
1882 6 | 6 | six   |
1883 7 | 7 | seven |
1884 8 | 8 | eight |
1885   |   |       |  0
1886   |   | null  |
1887   | 0 | zero  |
1888   |   |       |
1889(15 rows)
1890
1891SELECT *
1892  FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (k = 1);
1893 i | j | t | k
1894---+---+---+---
1895(0 rows)
1896
1897SELECT *
1898  FROM J1_TBL LEFT JOIN J2_TBL USING (i) WHERE (i = 1);
1899 i | j |  t  | k
1900---+---+-----+----
1901 1 | 4 | one | -1
1902(1 row)
1903
1904--
1905-- semijoin selectivity for <>
1906--
1907explain (costs off)
1908select * from int4_tbl i4, tenk1 a
1909where exists(select * from tenk1 b
1910             where a.twothousand = b.twothousand and a.fivethous <> b.fivethous)
1911      and i4.f1 = a.tenthous;
1912                  QUERY PLAN
1913----------------------------------------------
1914 Hash Semi Join
1915   Hash Cond: (a.twothousand = b.twothousand)
1916   Join Filter: (a.fivethous <> b.fivethous)
1917   ->  Hash Join
1918         Hash Cond: (a.tenthous = i4.f1)
1919         ->  Seq Scan on tenk1 a
1920         ->  Hash
1921               ->  Seq Scan on int4_tbl i4
1922   ->  Hash
1923         ->  Seq Scan on tenk1 b
1924(10 rows)
1925
1926--
1927-- More complicated constructs
1928--
1929--
1930-- Multiway full join
1931--
1932CREATE TABLE t1 (name TEXT, n INTEGER);
1933CREATE TABLE t2 (name TEXT, n INTEGER);
1934CREATE TABLE t3 (name TEXT, n INTEGER);
1935INSERT INTO t1 VALUES ( 'bb', 11 );
1936INSERT INTO t2 VALUES ( 'bb', 12 );
1937INSERT INTO t2 VALUES ( 'cc', 22 );
1938INSERT INTO t2 VALUES ( 'ee', 42 );
1939INSERT INTO t3 VALUES ( 'bb', 13 );
1940INSERT INTO t3 VALUES ( 'cc', 23 );
1941INSERT INTO t3 VALUES ( 'dd', 33 );
1942SELECT * FROM t1 FULL JOIN t2 USING (name) FULL JOIN t3 USING (name);
1943 name | n  | n  | n
1944------+----+----+----
1945 bb   | 11 | 12 | 13
1946 cc   |    | 22 | 23
1947 dd   |    |    | 33
1948 ee   |    | 42 |
1949(4 rows)
1950
1951--
1952-- Test interactions of join syntax and subqueries
1953--
1954-- Basic cases (we expect planner to pull up the subquery here)
1955SELECT * FROM
1956(SELECT * FROM t2) as s2
1957INNER JOIN
1958(SELECT * FROM t3) s3
1959USING (name);
1960 name | n  | n
1961------+----+----
1962 bb   | 12 | 13
1963 cc   | 22 | 23
1964(2 rows)
1965
1966SELECT * FROM
1967(SELECT * FROM t2) as s2
1968LEFT JOIN
1969(SELECT * FROM t3) s3
1970USING (name);
1971 name | n  | n
1972------+----+----
1973 bb   | 12 | 13
1974 cc   | 22 | 23
1975 ee   | 42 |
1976(3 rows)
1977
1978SELECT * FROM
1979(SELECT * FROM t2) as s2
1980FULL JOIN
1981(SELECT * FROM t3) s3
1982USING (name);
1983 name | n  | n
1984------+----+----
1985 bb   | 12 | 13
1986 cc   | 22 | 23
1987 dd   |    | 33
1988 ee   | 42 |
1989(4 rows)
1990
1991-- Cases with non-nullable expressions in subquery results;
1992-- make sure these go to null as expected
1993SELECT * FROM
1994(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2
1995NATURAL INNER JOIN
1996(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3;
1997 name | s2_n | s2_2 | s3_n | s3_2
1998------+------+------+------+------
1999 bb   |   12 |    2 |   13 |    3
2000 cc   |   22 |    2 |   23 |    3
2001(2 rows)
2002
2003SELECT * FROM
2004(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2
2005NATURAL LEFT JOIN
2006(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3;
2007 name | s2_n | s2_2 | s3_n | s3_2
2008------+------+------+------+------
2009 bb   |   12 |    2 |   13 |    3
2010 cc   |   22 |    2 |   23 |    3
2011 ee   |   42 |    2 |      |
2012(3 rows)
2013
2014SELECT * FROM
2015(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2
2016NATURAL FULL JOIN
2017(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3;
2018 name | s2_n | s2_2 | s3_n | s3_2
2019------+------+------+------+------
2020 bb   |   12 |    2 |   13 |    3
2021 cc   |   22 |    2 |   23 |    3
2022 dd   |      |      |   33 |    3
2023 ee   |   42 |    2 |      |
2024(4 rows)
2025
2026SELECT * FROM
2027(SELECT name, n as s1_n, 1 as s1_1 FROM t1) as s1
2028NATURAL INNER JOIN
2029(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2
2030NATURAL INNER JOIN
2031(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3;
2032 name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2
2033------+------+------+------+------+------+------
2034 bb   |   11 |    1 |   12 |    2 |   13 |    3
2035(1 row)
2036
2037SELECT * FROM
2038(SELECT name, n as s1_n, 1 as s1_1 FROM t1) as s1
2039NATURAL FULL JOIN
2040(SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2
2041NATURAL FULL JOIN
2042(SELECT name, n as s3_n, 3 as s3_2 FROM t3) s3;
2043 name | s1_n | s1_1 | s2_n | s2_2 | s3_n | s3_2
2044------+------+------+------+------+------+------
2045 bb   |   11 |    1 |   12 |    2 |   13 |    3
2046 cc   |      |      |   22 |    2 |   23 |    3
2047 dd   |      |      |      |      |   33 |    3
2048 ee   |      |      |   42 |    2 |      |
2049(4 rows)
2050
2051SELECT * FROM
2052(SELECT name, n as s1_n FROM t1) as s1
2053NATURAL FULL JOIN
2054  (SELECT * FROM
2055    (SELECT name, n as s2_n FROM t2) as s2
2056    NATURAL FULL JOIN
2057    (SELECT name, n as s3_n FROM t3) as s3
2058  ) ss2;
2059 name | s1_n | s2_n | s3_n
2060------+------+------+------
2061 bb   |   11 |   12 |   13
2062 cc   |      |   22 |   23
2063 dd   |      |      |   33
2064 ee   |      |   42 |
2065(4 rows)
2066
2067SELECT * FROM
2068(SELECT name, n as s1_n FROM t1) as s1
2069NATURAL FULL JOIN
2070  (SELECT * FROM
2071    (SELECT name, n as s2_n, 2 as s2_2 FROM t2) as s2
2072    NATURAL FULL JOIN
2073    (SELECT name, n as s3_n FROM t3) as s3
2074  ) ss2;
2075 name | s1_n | s2_n | s2_2 | s3_n
2076------+------+------+------+------
2077 bb   |   11 |   12 |    2 |   13
2078 cc   |      |   22 |    2 |   23
2079 dd   |      |      |      |   33
2080 ee   |      |   42 |    2 |
2081(4 rows)
2082
2083-- Constants as join keys can also be problematic
2084SELECT * FROM
2085  (SELECT name, n as s1_n FROM t1) as s1
2086FULL JOIN
2087  (SELECT name, 2 as s2_n FROM t2) as s2
2088ON (s1_n = s2_n);
2089 name | s1_n | name | s2_n
2090------+------+------+------
2091      |      | bb   |    2
2092      |      | cc   |    2
2093      |      | ee   |    2
2094 bb   |   11 |      |
2095(4 rows)
2096
2097-- Test for propagation of nullability constraints into sub-joins
2098create temp table x (x1 int, x2 int);
2099insert into x values (1,11);
2100insert into x values (2,22);
2101insert into x values (3,null);
2102insert into x values (4,44);
2103insert into x values (5,null);
2104create temp table y (y1 int, y2 int);
2105insert into y values (1,111);
2106insert into y values (2,222);
2107insert into y values (3,333);
2108insert into y values (4,null);
2109select * from x;
2110 x1 | x2
2111----+----
2112  1 | 11
2113  2 | 22
2114  3 |
2115  4 | 44
2116  5 |
2117(5 rows)
2118
2119select * from y;
2120 y1 | y2
2121----+-----
2122  1 | 111
2123  2 | 222
2124  3 | 333
2125  4 |
2126(4 rows)
2127
2128select * from x left join y on (x1 = y1 and x2 is not null);
2129 x1 | x2 | y1 | y2
2130----+----+----+-----
2131  1 | 11 |  1 | 111
2132  2 | 22 |  2 | 222
2133  3 |    |    |
2134  4 | 44 |  4 |
2135  5 |    |    |
2136(5 rows)
2137
2138select * from x left join y on (x1 = y1 and y2 is not null);
2139 x1 | x2 | y1 | y2
2140----+----+----+-----
2141  1 | 11 |  1 | 111
2142  2 | 22 |  2 | 222
2143  3 |    |  3 | 333
2144  4 | 44 |    |
2145  5 |    |    |
2146(5 rows)
2147
2148select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2149on (x1 = xx1);
2150 x1 | x2 | y1 | y2  | xx1 | xx2
2151----+----+----+-----+-----+-----
2152  1 | 11 |  1 | 111 |   1 |  11
2153  2 | 22 |  2 | 222 |   2 |  22
2154  3 |    |  3 | 333 |   3 |
2155  4 | 44 |  4 |     |   4 |  44
2156  5 |    |    |     |   5 |
2157(5 rows)
2158
2159select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2160on (x1 = xx1 and x2 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  3 |    |  3 | 333 |     |
2166  4 | 44 |  4 |     |   4 |  44
2167  5 |    |    |     |     |
2168(5 rows)
2169
2170select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2171on (x1 = xx1 and y2 is not null);
2172 x1 | x2 | y1 | y2  | xx1 | xx2
2173----+----+----+-----+-----+-----
2174  1 | 11 |  1 | 111 |   1 |  11
2175  2 | 22 |  2 | 222 |   2 |  22
2176  3 |    |  3 | 333 |   3 |
2177  4 | 44 |  4 |     |     |
2178  5 |    |    |     |     |
2179(5 rows)
2180
2181select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2182on (x1 = xx1 and xx2 is not null);
2183 x1 | x2 | y1 | y2  | xx1 | xx2
2184----+----+----+-----+-----+-----
2185  1 | 11 |  1 | 111 |   1 |  11
2186  2 | 22 |  2 | 222 |   2 |  22
2187  3 |    |  3 | 333 |     |
2188  4 | 44 |  4 |     |   4 |  44
2189  5 |    |    |     |     |
2190(5 rows)
2191
2192-- these should NOT give the same answers as above
2193select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2194on (x1 = xx1) where (x2 is not null);
2195 x1 | x2 | y1 | y2  | xx1 | xx2
2196----+----+----+-----+-----+-----
2197  1 | 11 |  1 | 111 |   1 |  11
2198  2 | 22 |  2 | 222 |   2 |  22
2199  4 | 44 |  4 |     |   4 |  44
2200(3 rows)
2201
2202select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2203on (x1 = xx1) where (y2 is not null);
2204 x1 | x2 | y1 | y2  | xx1 | xx2
2205----+----+----+-----+-----+-----
2206  1 | 11 |  1 | 111 |   1 |  11
2207  2 | 22 |  2 | 222 |   2 |  22
2208  3 |    |  3 | 333 |   3 |
2209(3 rows)
2210
2211select * from (x left join y on (x1 = y1)) left join x xx(xx1,xx2)
2212on (x1 = xx1) where (xx2 is not null);
2213 x1 | x2 | y1 | y2  | xx1 | xx2
2214----+----+----+-----+-----+-----
2215  1 | 11 |  1 | 111 |   1 |  11
2216  2 | 22 |  2 | 222 |   2 |  22
2217  4 | 44 |  4 |     |   4 |  44
2218(3 rows)
2219
2220--
2221-- regression test: check for bug with propagation of implied equality
2222-- to outside an IN
2223--
2224select count(*) from tenk1 a where unique1 in
2225  (select unique1 from tenk1 b join tenk1 c using (unique1)
2226   where b.unique2 = 42);
2227 count
2228-------
2229     1
2230(1 row)
2231
2232--
2233-- regression test: check for failure to generate a plan with multiple
2234-- degenerate IN clauses
2235--
2236select count(*) from tenk1 x where
2237  x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and
2238  x.unique1 = 0 and
2239  x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1);
2240 count
2241-------
2242     1
2243(1 row)
2244
2245-- try that with GEQO too
2246begin;
2247set geqo = on;
2248set geqo_threshold = 2;
2249select count(*) from tenk1 x where
2250  x.unique1 in (select a.f1 from int4_tbl a,float8_tbl b where a.f1=b.f1) and
2251  x.unique1 = 0 and
2252  x.unique1 in (select aa.f1 from int4_tbl aa,float8_tbl bb where aa.f1=bb.f1);
2253 count
2254-------
2255     1
2256(1 row)
2257
2258rollback;
2259--
2260-- regression test: be sure we cope with proven-dummy append rels
2261--
2262explain (costs off)
2263select aa, bb, unique1, unique1
2264  from tenk1 right join b on aa = unique1
2265  where bb < bb and bb is null;
2266        QUERY PLAN
2267--------------------------
2268 Result
2269   One-Time Filter: false
2270(2 rows)
2271
2272select aa, bb, unique1, unique1
2273  from tenk1 right join b on aa = unique1
2274  where bb < bb and bb is null;
2275 aa | bb | unique1 | unique1
2276----+----+---------+---------
2277(0 rows)
2278
2279--
2280-- regression test: check handling of empty-FROM subquery underneath outer join
2281--
2282explain (costs off)
2283select * from int8_tbl i1 left join (int8_tbl i2 join
2284  (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2
2285order by 1, 2;
2286                QUERY PLAN
2287-------------------------------------------
2288 Sort
2289   Sort Key: i1.q1, i1.q2
2290   ->  Hash Left Join
2291         Hash Cond: (i1.q2 = i2.q2)
2292         ->  Seq Scan on int8_tbl i1
2293         ->  Hash
2294               ->  Seq Scan on int8_tbl i2
2295                     Filter: (q1 = 123)
2296(8 rows)
2297
2298select * from int8_tbl i1 left join (int8_tbl i2 join
2299  (select 123 as x) ss on i2.q1 = x) on i1.q2 = i2.q2
2300order by 1, 2;
2301        q1        |        q2         | q1  |        q2        |  x
2302------------------+-------------------+-----+------------------+-----
2303              123 |               456 | 123 |              456 | 123
2304              123 |  4567890123456789 | 123 | 4567890123456789 | 123
2305 4567890123456789 | -4567890123456789 |     |                  |
2306 4567890123456789 |               123 |     |                  |
2307 4567890123456789 |  4567890123456789 | 123 | 4567890123456789 | 123
2308(5 rows)
2309
2310--
2311-- regression test: check a case where join_clause_is_movable_into() gives
2312-- an imprecise result, causing an assertion failure
2313--
2314select count(*)
2315from
2316  (select t3.tenthous as x1, coalesce(t1.stringu1, t2.stringu1) as x2
2317   from tenk1 t1
2318   left join tenk1 t2 on t1.unique1 = t2.unique1
2319   join tenk1 t3 on t1.unique2 = t3.unique2) ss,
2320  tenk1 t4,
2321  tenk1 t5
2322where t4.thousand = t5.unique1 and ss.x1 = t4.tenthous and ss.x2 = t5.stringu1;
2323 count
2324-------
2325  1000
2326(1 row)
2327
2328--
2329-- regression test: check a case where we formerly missed including an EC
2330-- enforcement clause because it was expected to be handled at scan level
2331--
2332explain (costs off)
2333select a.f1, b.f1, t.thousand, t.tenthous from
2334  tenk1 t,
2335  (select sum(f1)+1 as f1 from int4_tbl i4a) a,
2336  (select sum(f1) as f1 from int4_tbl i4b) b
2337where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous;
2338                                                      QUERY PLAN
2339-----------------------------------------------------------------------------------------------------------------------
2340 Nested Loop
2341   ->  Aggregate
2342         ->  Seq Scan on int4_tbl i4b
2343   ->  Nested Loop
2344         Join Filter: ((sum(i4b.f1)) = ((sum(i4a.f1) + 1)))
2345         ->  Aggregate
2346               ->  Seq Scan on int4_tbl i4a
2347         ->  Index Only Scan using tenk1_thous_tenthous on tenk1 t
2348               Index Cond: ((thousand = (sum(i4b.f1))) AND (tenthous = ((((sum(i4a.f1) + 1)) + (sum(i4b.f1))) + 999)))
2349(9 rows)
2350
2351select a.f1, b.f1, t.thousand, t.tenthous from
2352  tenk1 t,
2353  (select sum(f1)+1 as f1 from int4_tbl i4a) a,
2354  (select sum(f1) as f1 from int4_tbl i4b) b
2355where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous;
2356 f1 | f1 | thousand | tenthous
2357----+----+----------+----------
2358(0 rows)
2359
2360--
2361-- check a case where we formerly got confused by conflicting sort orders
2362-- in redundant merge join path keys
2363--
2364explain (costs off)
2365select * from
2366  j1_tbl full join
2367  (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl
2368  on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k;
2369                           QUERY PLAN
2370-----------------------------------------------------------------
2371 Merge Full Join
2372   Merge Cond: ((j2_tbl.i = j1_tbl.i) AND (j2_tbl.k = j1_tbl.i))
2373   ->  Sort
2374         Sort Key: j2_tbl.i DESC, j2_tbl.k
2375         ->  Seq Scan on j2_tbl
2376   ->  Sort
2377         Sort Key: j1_tbl.i DESC
2378         ->  Seq Scan on j1_tbl
2379(8 rows)
2380
2381select * from
2382  j1_tbl full join
2383  (select * from j2_tbl order by j2_tbl.i desc, j2_tbl.k asc) j2_tbl
2384  on j1_tbl.i = j2_tbl.i and j1_tbl.i = j2_tbl.k;
2385 i | j |   t   | i | k
2386---+---+-------+---+----
2387   |   |       |   |  0
2388   |   |       |   |
2389   | 0 | zero  |   |
2390   |   | null  |   |
2391 8 | 8 | eight |   |
2392 7 | 7 | seven |   |
2393 6 | 6 | six   |   |
2394   |   |       | 5 | -5
2395   |   |       | 5 | -5
2396 5 | 0 | five  |   |
2397 4 | 1 | four  |   |
2398   |   |       | 3 | -3
2399 3 | 2 | three |   |
2400 2 | 3 | two   | 2 |  2
2401   |   |       | 2 |  4
2402   |   |       | 1 | -1
2403   |   |       | 0 |
2404 1 | 4 | one   |   |
2405 0 |   | zero  |   |
2406(19 rows)
2407
2408--
2409-- a different check for handling of redundant sort keys in merge joins
2410--
2411explain (costs off)
2412select count(*) from
2413  (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x
2414  left join
2415  (select * from tenk1 y order by y.unique2) y
2416  on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2;
2417                                    QUERY PLAN
2418----------------------------------------------------------------------------------
2419 Aggregate
2420   ->  Merge Left Join
2421         Merge Cond: (x.thousand = y.unique2)
2422         Join Filter: ((x.twothousand = y.hundred) AND (x.fivethous = y.unique2))
2423         ->  Sort
2424               Sort Key: x.thousand, x.twothousand, x.fivethous
2425               ->  Seq Scan on tenk1 x
2426         ->  Materialize
2427               ->  Index Scan using tenk1_unique2 on tenk1 y
2428(9 rows)
2429
2430select count(*) from
2431  (select * from tenk1 x order by x.thousand, x.twothousand, x.fivethous) x
2432  left join
2433  (select * from tenk1 y order by y.unique2) y
2434  on x.thousand = y.unique2 and x.twothousand = y.hundred and x.fivethous = y.unique2;
2435 count
2436-------
2437 10000
2438(1 row)
2439
2440--
2441-- Clean up
2442--
2443DROP TABLE t1;
2444DROP TABLE t2;
2445DROP TABLE t3;
2446DROP TABLE J1_TBL;
2447DROP TABLE J2_TBL;
2448-- Both DELETE and UPDATE allow the specification of additional tables
2449-- to "join" against to determine which rows should be modified.
2450CREATE TEMP TABLE t1 (a int, b int);
2451CREATE TEMP TABLE t2 (a int, b int);
2452CREATE TEMP TABLE t3 (x int, y int);
2453INSERT INTO t1 VALUES (5, 10);
2454INSERT INTO t1 VALUES (15, 20);
2455INSERT INTO t1 VALUES (100, 100);
2456INSERT INTO t1 VALUES (200, 1000);
2457INSERT INTO t2 VALUES (200, 2000);
2458INSERT INTO t3 VALUES (5, 20);
2459INSERT INTO t3 VALUES (6, 7);
2460INSERT INTO t3 VALUES (7, 8);
2461INSERT INTO t3 VALUES (500, 100);
2462DELETE FROM t3 USING t1 table1 WHERE t3.x = table1.a;
2463SELECT * FROM t3;
2464  x  |  y
2465-----+-----
2466   6 |   7
2467   7 |   8
2468 500 | 100
2469(3 rows)
2470
2471DELETE FROM t3 USING t1 JOIN t2 USING (a) WHERE t3.x > t1.a;
2472SELECT * FROM t3;
2473 x | y
2474---+---
2475 6 | 7
2476 7 | 8
2477(2 rows)
2478
2479DELETE FROM t3 USING t3 t3_other WHERE t3.x = t3_other.x AND t3.y = t3_other.y;
2480SELECT * FROM t3;
2481 x | y
2482---+---
2483(0 rows)
2484
2485-- Test join against inheritance tree
2486create temp table t2a () inherits (t2);
2487insert into t2a values (200, 2001);
2488select * from t1 left join t2 on (t1.a = t2.a);
2489  a  |  b   |  a  |  b
2490-----+------+-----+------
2491   5 |   10 |     |
2492  15 |   20 |     |
2493 100 |  100 |     |
2494 200 | 1000 | 200 | 2000
2495 200 | 1000 | 200 | 2001
2496(5 rows)
2497
2498-- Test matching of column name with wrong alias
2499select t1.x from t1 join t3 on (t1.a = t3.x);
2500ERROR:  column t1.x does not exist
2501LINE 1: select t1.x from t1 join t3 on (t1.a = t3.x);
2502               ^
2503HINT:  Perhaps you meant to reference the column "t3.x".
2504--
2505-- regression test for 8.1 merge right join bug
2506--
2507CREATE TEMP TABLE tt1 ( tt1_id int4, joincol int4 );
2508INSERT INTO tt1 VALUES (1, 11);
2509INSERT INTO tt1 VALUES (2, NULL);
2510CREATE TEMP TABLE tt2 ( tt2_id int4, joincol int4 );
2511INSERT INTO tt2 VALUES (21, 11);
2512INSERT INTO tt2 VALUES (22, 11);
2513set enable_hashjoin to off;
2514set enable_nestloop to off;
2515-- these should give the same results
2516select tt1.*, tt2.* from tt1 left join tt2 on tt1.joincol = tt2.joincol;
2517 tt1_id | joincol | tt2_id | joincol
2518--------+---------+--------+---------
2519      1 |      11 |     21 |      11
2520      1 |      11 |     22 |      11
2521      2 |         |        |
2522(3 rows)
2523
2524select tt1.*, tt2.* from tt2 right join tt1 on tt1.joincol = tt2.joincol;
2525 tt1_id | joincol | tt2_id | joincol
2526--------+---------+--------+---------
2527      1 |      11 |     21 |      11
2528      1 |      11 |     22 |      11
2529      2 |         |        |
2530(3 rows)
2531
2532reset enable_hashjoin;
2533reset enable_nestloop;
2534--
2535-- regression test for bug #13908 (hash join with skew tuples & nbatch increase)
2536--
2537set work_mem to '64kB';
2538set enable_mergejoin to off;
2539set enable_memoize to off;
2540explain (costs off)
2541select count(*) from tenk1 a, tenk1 b
2542  where a.hundred = b.thousand and (b.fivethous % 10) < 10;
2543                         QUERY PLAN
2544------------------------------------------------------------
2545 Aggregate
2546   ->  Hash Join
2547         Hash Cond: (a.hundred = b.thousand)
2548         ->  Index Only Scan using tenk1_hundred on tenk1 a
2549         ->  Hash
2550               ->  Seq Scan on tenk1 b
2551                     Filter: ((fivethous % 10) < 10)
2552(7 rows)
2553
2554select count(*) from tenk1 a, tenk1 b
2555  where a.hundred = b.thousand and (b.fivethous % 10) < 10;
2556 count
2557--------
2558 100000
2559(1 row)
2560
2561reset work_mem;
2562reset enable_mergejoin;
2563reset enable_memoize;
2564--
2565-- regression test for 8.2 bug with improper re-ordering of left joins
2566--
2567create temp table tt3(f1 int, f2 text);
2568insert into tt3 select x, repeat('xyzzy', 100) from generate_series(1,10000) x;
2569create index tt3i on tt3(f1);
2570analyze tt3;
2571create temp table tt4(f1 int);
2572insert into tt4 values (0),(1),(9999);
2573analyze tt4;
2574SELECT a.f1
2575FROM tt4 a
2576LEFT JOIN (
2577        SELECT b.f1
2578        FROM tt3 b LEFT JOIN tt3 c ON (b.f1 = c.f1)
2579        WHERE c.f1 IS NULL
2580) AS d ON (a.f1 = d.f1)
2581WHERE d.f1 IS NULL;
2582  f1
2583------
2584    0
2585    1
2586 9999
2587(3 rows)
2588
2589--
2590-- regression test for proper handling of outer joins within antijoins
2591--
2592create temp table tt4x(c1 int, c2 int, c3 int);
2593explain (costs off)
2594select * from tt4x t1
2595where not exists (
2596  select 1 from tt4x t2
2597    left join tt4x t3 on t2.c3 = t3.c1
2598    left join ( select t5.c1 as c1
2599                from tt4x t4 left join tt4x t5 on t4.c2 = t5.c1
2600              ) a1 on t3.c2 = a1.c1
2601  where t1.c1 = t2.c2
2602);
2603                       QUERY PLAN
2604---------------------------------------------------------
2605 Hash Anti Join
2606   Hash Cond: (t1.c1 = t2.c2)
2607   ->  Seq Scan on tt4x t1
2608   ->  Hash
2609         ->  Merge Right Join
2610               Merge Cond: (t5.c1 = t3.c2)
2611               ->  Merge Join
2612                     Merge Cond: (t4.c2 = t5.c1)
2613                     ->  Sort
2614                           Sort Key: t4.c2
2615                           ->  Seq Scan on tt4x t4
2616                     ->  Sort
2617                           Sort Key: t5.c1
2618                           ->  Seq Scan on tt4x t5
2619               ->  Sort
2620                     Sort Key: t3.c2
2621                     ->  Merge Left Join
2622                           Merge Cond: (t2.c3 = t3.c1)
2623                           ->  Sort
2624                                 Sort Key: t2.c3
2625                                 ->  Seq Scan on tt4x t2
2626                           ->  Sort
2627                                 Sort Key: t3.c1
2628                                 ->  Seq Scan on tt4x t3
2629(24 rows)
2630
2631--
2632-- regression test for problems of the sort depicted in bug #3494
2633--
2634create temp table tt5(f1 int, f2 int);
2635create temp table tt6(f1 int, f2 int);
2636insert into tt5 values(1, 10);
2637insert into tt5 values(1, 11);
2638insert into tt6 values(1, 9);
2639insert into tt6 values(1, 2);
2640insert into tt6 values(2, 9);
2641select * from tt5,tt6 where tt5.f1 = tt6.f1 and tt5.f1 = tt5.f2 - tt6.f2;
2642 f1 | f2 | f1 | f2
2643----+----+----+----
2644  1 | 10 |  1 |  9
2645(1 row)
2646
2647--
2648-- regression test for problems of the sort depicted in bug #3588
2649--
2650create temp table xx (pkxx int);
2651create temp table yy (pkyy int, pkxx int);
2652insert into xx values (1);
2653insert into xx values (2);
2654insert into xx values (3);
2655insert into yy values (101, 1);
2656insert into yy values (201, 2);
2657insert into yy values (301, NULL);
2658select yy.pkyy as yy_pkyy, yy.pkxx as yy_pkxx, yya.pkyy as yya_pkyy,
2659       xxa.pkxx as xxa_pkxx, xxb.pkxx as xxb_pkxx
2660from yy
2661     left join (SELECT * FROM yy where pkyy = 101) as yya ON yy.pkyy = yya.pkyy
2662     left join xx xxa on yya.pkxx = xxa.pkxx
2663     left join xx xxb on coalesce (xxa.pkxx, 1) = xxb.pkxx;
2664 yy_pkyy | yy_pkxx | yya_pkyy | xxa_pkxx | xxb_pkxx
2665---------+---------+----------+----------+----------
2666     101 |       1 |      101 |        1 |        1
2667     201 |       2 |          |          |        1
2668     301 |         |          |          |        1
2669(3 rows)
2670
2671--
2672-- regression test for improper pushing of constants across outer-join clauses
2673-- (as seen in early 8.2.x releases)
2674--
2675create temp table zt1 (f1 int primary key);
2676create temp table zt2 (f2 int primary key);
2677create temp table zt3 (f3 int primary key);
2678insert into zt1 values(53);
2679insert into zt2 values(53);
2680select * from
2681  zt2 left join zt3 on (f2 = f3)
2682      left join zt1 on (f3 = f1)
2683where f2 = 53;
2684 f2 | f3 | f1
2685----+----+----
2686 53 |    |
2687(1 row)
2688
2689create temp view zv1 as select *,'dummy'::text AS junk from zt1;
2690select * from
2691  zt2 left join zt3 on (f2 = f3)
2692      left join zv1 on (f3 = f1)
2693where f2 = 53;
2694 f2 | f3 | f1 | junk
2695----+----+----+------
2696 53 |    |    |
2697(1 row)
2698
2699--
2700-- regression test for improper extraction of OR indexqual conditions
2701-- (as seen in early 8.3.x releases)
2702--
2703select a.unique2, a.ten, b.tenthous, b.unique2, b.hundred
2704from tenk1 a left join tenk1 b on a.unique2 = b.tenthous
2705where a.unique1 = 42 and
2706      ((b.unique2 is null and a.ten = 2) or b.hundred = 3);
2707 unique2 | ten | tenthous | unique2 | hundred
2708---------+-----+----------+---------+---------
2709(0 rows)
2710
2711--
2712-- test proper positioning of one-time quals in EXISTS (8.4devel bug)
2713--
2714prepare foo(bool) as
2715  select count(*) from tenk1 a left join tenk1 b
2716    on (a.unique2 = b.unique1 and exists
2717        (select 1 from tenk1 c where c.thousand = b.unique2 and $1));
2718execute foo(true);
2719 count
2720-------
2721 10000
2722(1 row)
2723
2724execute foo(false);
2725 count
2726-------
2727 10000
2728(1 row)
2729
2730--
2731-- test for sane behavior with noncanonical merge clauses, per bug #4926
2732--
2733begin;
2734set enable_mergejoin = 1;
2735set enable_hashjoin = 0;
2736set enable_nestloop = 0;
2737create temp table a (i integer);
2738create temp table b (x integer, y integer);
2739select * from a left join b on i = x and i = y and x = i;
2740 i | x | y
2741---+---+---
2742(0 rows)
2743
2744rollback;
2745--
2746-- test handling of merge clauses using record_ops
2747--
2748begin;
2749create type mycomptype as (id int, v bigint);
2750create temp table tidv (idv mycomptype);
2751create index on tidv (idv);
2752explain (costs off)
2753select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv;
2754                        QUERY PLAN
2755----------------------------------------------------------
2756 Merge Join
2757   Merge Cond: (a.idv = b.idv)
2758   ->  Index Only Scan using tidv_idv_idx on tidv a
2759   ->  Materialize
2760         ->  Index Only Scan using tidv_idv_idx on tidv b
2761(5 rows)
2762
2763set enable_mergejoin = 0;
2764set enable_hashjoin = 0;
2765explain (costs off)
2766select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv;
2767                     QUERY PLAN
2768----------------------------------------------------
2769 Nested Loop
2770   ->  Seq Scan on tidv a
2771   ->  Index Only Scan using tidv_idv_idx on tidv b
2772         Index Cond: (idv = a.idv)
2773(4 rows)
2774
2775rollback;
2776--
2777-- test NULL behavior of whole-row Vars, per bug #5025
2778--
2779select t1.q2, count(t2.*)
2780from int8_tbl t1 left join int8_tbl t2 on (t1.q2 = t2.q1)
2781group by t1.q2 order by 1;
2782        q2         | count
2783-------------------+-------
2784 -4567890123456789 |     0
2785               123 |     2
2786               456 |     0
2787  4567890123456789 |     6
2788(4 rows)
2789
2790select t1.q2, count(t2.*)
2791from int8_tbl t1 left join (select * from int8_tbl) t2 on (t1.q2 = t2.q1)
2792group by t1.q2 order by 1;
2793        q2         | count
2794-------------------+-------
2795 -4567890123456789 |     0
2796               123 |     2
2797               456 |     0
2798  4567890123456789 |     6
2799(4 rows)
2800
2801select t1.q2, count(t2.*)
2802from int8_tbl t1 left join (select * from int8_tbl offset 0) t2 on (t1.q2 = t2.q1)
2803group by t1.q2 order by 1;
2804        q2         | count
2805-------------------+-------
2806 -4567890123456789 |     0
2807               123 |     2
2808               456 |     0
2809  4567890123456789 |     6
2810(4 rows)
2811
2812select t1.q2, count(t2.*)
2813from int8_tbl t1 left join
2814  (select q1, case when q2=1 then 1 else q2 end as q2 from int8_tbl) t2
2815  on (t1.q2 = t2.q1)
2816group by t1.q2 order by 1;
2817        q2         | count
2818-------------------+-------
2819 -4567890123456789 |     0
2820               123 |     2
2821               456 |     0
2822  4567890123456789 |     6
2823(4 rows)
2824
2825--
2826-- test incorrect failure to NULL pulled-up subexpressions
2827--
2828begin;
2829create temp table a (
2830     code char not null,
2831     constraint a_pk primary key (code)
2832);
2833create temp table b (
2834     a char not null,
2835     num integer not null,
2836     constraint b_pk primary key (a, num)
2837);
2838create temp table c (
2839     name char not null,
2840     a char,
2841     constraint c_pk primary key (name)
2842);
2843insert into a (code) values ('p');
2844insert into a (code) values ('q');
2845insert into b (a, num) values ('p', 1);
2846insert into b (a, num) values ('p', 2);
2847insert into c (name, a) values ('A', 'p');
2848insert into c (name, a) values ('B', 'q');
2849insert into c (name, a) values ('C', null);
2850select c.name, ss.code, ss.b_cnt, ss.const
2851from c left join
2852  (select a.code, coalesce(b_grp.cnt, 0) as b_cnt, -1 as const
2853   from a left join
2854     (select count(1) as cnt, b.a from b group by b.a) as b_grp
2855     on a.code = b_grp.a
2856  ) as ss
2857  on (c.a = ss.code)
2858order by c.name;
2859 name | code | b_cnt | const
2860------+------+-------+-------
2861 A    | p    |     2 |    -1
2862 B    | q    |     0 |    -1
2863 C    |      |       |
2864(3 rows)
2865
2866rollback;
2867--
2868-- test incorrect handling of placeholders that only appear in targetlists,
2869-- per bug #6154
2870--
2871SELECT * FROM
2872( SELECT 1 as key1 ) sub1
2873LEFT JOIN
2874( SELECT sub3.key3, sub4.value2, COALESCE(sub4.value2, 66) as value3 FROM
2875    ( SELECT 1 as key3 ) sub3
2876    LEFT JOIN
2877    ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM
2878        ( SELECT 1 as key5 ) sub5
2879        LEFT JOIN
2880        ( SELECT 2 as key6, 42 as value1 ) sub6
2881        ON sub5.key5 = sub6.key6
2882    ) sub4
2883    ON sub4.key5 = sub3.key3
2884) sub2
2885ON sub1.key1 = sub2.key3;
2886 key1 | key3 | value2 | value3
2887------+------+--------+--------
2888    1 |    1 |      1 |      1
2889(1 row)
2890
2891-- test the path using join aliases, too
2892SELECT * FROM
2893( SELECT 1 as key1 ) sub1
2894LEFT JOIN
2895( SELECT sub3.key3, value2, COALESCE(value2, 66) as value3 FROM
2896    ( SELECT 1 as key3 ) sub3
2897    LEFT JOIN
2898    ( SELECT sub5.key5, COALESCE(sub6.value1, 1) as value2 FROM
2899        ( SELECT 1 as key5 ) sub5
2900        LEFT JOIN
2901        ( SELECT 2 as key6, 42 as value1 ) sub6
2902        ON sub5.key5 = sub6.key6
2903    ) sub4
2904    ON sub4.key5 = sub3.key3
2905) sub2
2906ON sub1.key1 = sub2.key3;
2907 key1 | key3 | value2 | value3
2908------+------+--------+--------
2909    1 |    1 |      1 |      1
2910(1 row)
2911
2912--
2913-- test case where a PlaceHolderVar is used as a nestloop parameter
2914--
2915EXPLAIN (COSTS OFF)
2916SELECT qq, unique1
2917  FROM
2918  ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1
2919  FULL OUTER JOIN
2920  ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2
2921  USING (qq)
2922  INNER JOIN tenk1 c ON qq = unique2;
2923                                               QUERY PLAN
2924---------------------------------------------------------------------------------------------------------
2925 Nested Loop
2926   ->  Hash Full Join
2927         Hash Cond: ((COALESCE(a.q1, '0'::bigint)) = (COALESCE(b.q2, '-1'::bigint)))
2928         ->  Seq Scan on int8_tbl a
2929         ->  Hash
2930               ->  Seq Scan on int8_tbl b
2931   ->  Index Scan using tenk1_unique2 on tenk1 c
2932         Index Cond: (unique2 = COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint))))
2933(8 rows)
2934
2935SELECT qq, unique1
2936  FROM
2937  ( SELECT COALESCE(q1, 0) AS qq FROM int8_tbl a ) AS ss1
2938  FULL OUTER JOIN
2939  ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2
2940  USING (qq)
2941  INNER JOIN tenk1 c ON qq = unique2;
2942 qq  | unique1
2943-----+---------
2944 123 |    4596
2945 123 |    4596
2946 456 |    7318
2947(3 rows)
2948
2949--
2950-- nested nestloops can require nested PlaceHolderVars
2951--
2952create temp table nt1 (
2953  id int primary key,
2954  a1 boolean,
2955  a2 boolean
2956);
2957create temp table nt2 (
2958  id int primary key,
2959  nt1_id int,
2960  b1 boolean,
2961  b2 boolean,
2962  foreign key (nt1_id) references nt1(id)
2963);
2964create temp table nt3 (
2965  id int primary key,
2966  nt2_id int,
2967  c1 boolean,
2968  foreign key (nt2_id) references nt2(id)
2969);
2970insert into nt1 values (1,true,true);
2971insert into nt1 values (2,true,false);
2972insert into nt1 values (3,false,false);
2973insert into nt2 values (1,1,true,true);
2974insert into nt2 values (2,2,true,false);
2975insert into nt2 values (3,3,false,false);
2976insert into nt3 values (1,1,true);
2977insert into nt3 values (2,2,false);
2978insert into nt3 values (3,3,true);
2979explain (costs off)
2980select nt3.id
2981from nt3 as nt3
2982  left join
2983    (select nt2.*, (nt2.b1 and ss1.a3) AS b3
2984     from nt2 as nt2
2985       left join
2986         (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1
2987         on ss1.id = nt2.nt1_id
2988    ) as ss2
2989    on ss2.id = nt3.nt2_id
2990where nt3.id = 1 and ss2.b3;
2991                  QUERY PLAN
2992-----------------------------------------------
2993 Nested Loop
2994   ->  Nested Loop
2995         ->  Index Scan using nt3_pkey on nt3
2996               Index Cond: (id = 1)
2997         ->  Index Scan using nt2_pkey on nt2
2998               Index Cond: (id = nt3.nt2_id)
2999   ->  Index Only Scan using nt1_pkey on nt1
3000         Index Cond: (id = nt2.nt1_id)
3001         Filter: (nt2.b1 AND (id IS NOT NULL))
3002(9 rows)
3003
3004select nt3.id
3005from nt3 as nt3
3006  left join
3007    (select nt2.*, (nt2.b1 and ss1.a3) AS b3
3008     from nt2 as nt2
3009       left join
3010         (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1
3011         on ss1.id = nt2.nt1_id
3012    ) as ss2
3013    on ss2.id = nt3.nt2_id
3014where nt3.id = 1 and ss2.b3;
3015 id
3016----
3017  1
3018(1 row)
3019
3020--
3021-- test case where a PlaceHolderVar is propagated into a subquery
3022--
3023explain (costs off)
3024select * from
3025  int8_tbl t1 left join
3026  (select q1 as x, 42 as y from int8_tbl t2) ss
3027  on t1.q2 = ss.x
3028where
3029  1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1)
3030order by 1,2;
3031                        QUERY PLAN
3032-----------------------------------------------------------
3033 Sort
3034   Sort Key: t1.q1, t1.q2
3035   ->  Hash Left Join
3036         Hash Cond: (t1.q2 = t2.q1)
3037         Filter: (1 = (SubPlan 1))
3038         ->  Seq Scan on int8_tbl t1
3039         ->  Hash
3040               ->  Seq Scan on int8_tbl t2
3041         SubPlan 1
3042           ->  Limit
3043                 ->  Result
3044                       One-Time Filter: ((42) IS NOT NULL)
3045                       ->  Seq Scan on int8_tbl t3
3046(13 rows)
3047
3048select * from
3049  int8_tbl t1 left join
3050  (select q1 as x, 42 as y from int8_tbl t2) ss
3051  on t1.q2 = ss.x
3052where
3053  1 = (select 1 from int8_tbl t3 where ss.y is not null limit 1)
3054order by 1,2;
3055        q1        |        q2        |        x         | y
3056------------------+------------------+------------------+----
3057              123 | 4567890123456789 | 4567890123456789 | 42
3058              123 | 4567890123456789 | 4567890123456789 | 42
3059              123 | 4567890123456789 | 4567890123456789 | 42
3060 4567890123456789 |              123 |              123 | 42
3061 4567890123456789 |              123 |              123 | 42
3062 4567890123456789 | 4567890123456789 | 4567890123456789 | 42
3063 4567890123456789 | 4567890123456789 | 4567890123456789 | 42
3064 4567890123456789 | 4567890123456789 | 4567890123456789 | 42
3065(8 rows)
3066
3067--
3068-- variant where a PlaceHolderVar is needed at a join, but not above the join
3069--
3070explain (costs off)
3071select * from
3072  int4_tbl as i41,
3073  lateral
3074    (select 1 as x from
3075      (select i41.f1 as lat,
3076              i42.f1 as loc from
3077         int8_tbl as i81, int4_tbl as i42) as ss1
3078      right join int4_tbl as i43 on (i43.f1 > 1)
3079      where ss1.loc = ss1.lat) as ss2
3080where i41.f1 > 0;
3081                    QUERY PLAN
3082--------------------------------------------------
3083 Nested Loop
3084   ->  Nested Loop
3085         ->  Seq Scan on int4_tbl i41
3086               Filter: (f1 > 0)
3087         ->  Nested Loop
3088               Join Filter: (i41.f1 = i42.f1)
3089               ->  Seq Scan on int8_tbl i81
3090               ->  Materialize
3091                     ->  Seq Scan on int4_tbl i42
3092   ->  Materialize
3093         ->  Seq Scan on int4_tbl i43
3094               Filter: (f1 > 1)
3095(12 rows)
3096
3097select * from
3098  int4_tbl as i41,
3099  lateral
3100    (select 1 as x from
3101      (select i41.f1 as lat,
3102              i42.f1 as loc from
3103         int8_tbl as i81, int4_tbl as i42) as ss1
3104      right join int4_tbl as i43 on (i43.f1 > 1)
3105      where ss1.loc = ss1.lat) as ss2
3106where i41.f1 > 0;
3107     f1     | x
3108------------+---
3109     123456 | 1
3110     123456 | 1
3111     123456 | 1
3112     123456 | 1
3113     123456 | 1
3114     123456 | 1
3115     123456 | 1
3116     123456 | 1
3117     123456 | 1
3118     123456 | 1
3119 2147483647 | 1
3120 2147483647 | 1
3121 2147483647 | 1
3122 2147483647 | 1
3123 2147483647 | 1
3124 2147483647 | 1
3125 2147483647 | 1
3126 2147483647 | 1
3127 2147483647 | 1
3128 2147483647 | 1
3129(20 rows)
3130
3131--
3132-- test the corner cases FULL JOIN ON TRUE and FULL JOIN ON FALSE
3133--
3134select * from int4_tbl a full join int4_tbl b on true;
3135     f1      |     f1
3136-------------+-------------
3137           0 |           0
3138           0 |      123456
3139           0 |     -123456
3140           0 |  2147483647
3141           0 | -2147483647
3142      123456 |           0
3143      123456 |      123456
3144      123456 |     -123456
3145      123456 |  2147483647
3146      123456 | -2147483647
3147     -123456 |           0
3148     -123456 |      123456
3149     -123456 |     -123456
3150     -123456 |  2147483647
3151     -123456 | -2147483647
3152  2147483647 |           0
3153  2147483647 |      123456
3154  2147483647 |     -123456
3155  2147483647 |  2147483647
3156  2147483647 | -2147483647
3157 -2147483647 |           0
3158 -2147483647 |      123456
3159 -2147483647 |     -123456
3160 -2147483647 |  2147483647
3161 -2147483647 | -2147483647
3162(25 rows)
3163
3164select * from int4_tbl a full join int4_tbl b on false;
3165     f1      |     f1
3166-------------+-------------
3167             |           0
3168             |      123456
3169             |     -123456
3170             |  2147483647
3171             | -2147483647
3172           0 |
3173      123456 |
3174     -123456 |
3175  2147483647 |
3176 -2147483647 |
3177(10 rows)
3178
3179--
3180-- test for ability to use a cartesian join when necessary
3181--
3182create temp table q1 as select 1 as q1;
3183create temp table q2 as select 0 as q2;
3184analyze q1;
3185analyze q2;
3186explain (costs off)
3187select * from
3188  tenk1 join int4_tbl on f1 = twothousand,
3189  q1, q2
3190where q1 = thousand or q2 = thousand;
3191                               QUERY PLAN
3192------------------------------------------------------------------------
3193 Hash Join
3194   Hash Cond: (tenk1.twothousand = int4_tbl.f1)
3195   ->  Nested Loop
3196         ->  Nested Loop
3197               ->  Seq Scan on q1
3198               ->  Seq Scan on q2
3199         ->  Bitmap Heap Scan on tenk1
3200               Recheck Cond: ((q1.q1 = thousand) OR (q2.q2 = thousand))
3201               ->  BitmapOr
3202                     ->  Bitmap Index Scan on tenk1_thous_tenthous
3203                           Index Cond: (thousand = q1.q1)
3204                     ->  Bitmap Index Scan on tenk1_thous_tenthous
3205                           Index Cond: (thousand = q2.q2)
3206   ->  Hash
3207         ->  Seq Scan on int4_tbl
3208(15 rows)
3209
3210explain (costs off)
3211select * from
3212  tenk1 join int4_tbl on f1 = twothousand,
3213  q1, q2
3214where thousand = (q1 + q2);
3215                          QUERY PLAN
3216--------------------------------------------------------------
3217 Hash Join
3218   Hash Cond: (tenk1.twothousand = int4_tbl.f1)
3219   ->  Nested Loop
3220         ->  Nested Loop
3221               ->  Seq Scan on q1
3222               ->  Seq Scan on q2
3223         ->  Bitmap Heap Scan on tenk1
3224               Recheck Cond: (thousand = (q1.q1 + q2.q2))
3225               ->  Bitmap Index Scan on tenk1_thous_tenthous
3226                     Index Cond: (thousand = (q1.q1 + q2.q2))
3227   ->  Hash
3228         ->  Seq Scan on int4_tbl
3229(12 rows)
3230
3231--
3232-- test ability to generate a suitable plan for a star-schema query
3233--
3234explain (costs off)
3235select * from
3236  tenk1, int8_tbl a, int8_tbl b
3237where thousand = a.q1 and tenthous = b.q1 and a.q2 = 1 and b.q2 = 2;
3238                             QUERY PLAN
3239---------------------------------------------------------------------
3240 Nested Loop
3241   ->  Seq Scan on int8_tbl b
3242         Filter: (q2 = 2)
3243   ->  Nested Loop
3244         ->  Seq Scan on int8_tbl a
3245               Filter: (q2 = 1)
3246         ->  Index Scan using tenk1_thous_tenthous on tenk1
3247               Index Cond: ((thousand = a.q1) AND (tenthous = b.q1))
3248(8 rows)
3249
3250--
3251-- test a corner case in which we shouldn't apply the star-schema optimization
3252--
3253explain (costs off)
3254select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
3255  tenk1 t1
3256  inner join int4_tbl i1
3257    left join (select v1.x2, v2.y1, 11 AS d1
3258               from (select 1,0 from onerow) v1(x1,x2)
3259               left join (select 3,1 from onerow) v2(y1,y2)
3260               on v1.x1 = v2.y2) subq1
3261    on (i1.f1 = subq1.x2)
3262  on (t1.unique2 = subq1.d1)
3263  left join tenk1 t2
3264  on (subq1.y1 = t2.unique1)
3265where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
3266                              QUERY PLAN
3267-----------------------------------------------------------------------
3268 Nested Loop
3269   ->  Nested Loop
3270         Join Filter: (t1.stringu1 > t2.stringu2)
3271         ->  Nested Loop
3272               ->  Nested Loop
3273                     ->  Seq Scan on onerow
3274                     ->  Seq Scan on onerow onerow_1
3275               ->  Index Scan using tenk1_unique2 on tenk1 t1
3276                     Index Cond: ((unique2 = (11)) AND (unique2 < 42))
3277         ->  Index Scan using tenk1_unique1 on tenk1 t2
3278               Index Cond: (unique1 = (3))
3279   ->  Seq Scan on int4_tbl i1
3280         Filter: (f1 = 0)
3281(13 rows)
3282
3283select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
3284  tenk1 t1
3285  inner join int4_tbl i1
3286    left join (select v1.x2, v2.y1, 11 AS d1
3287               from (select 1,0 from onerow) v1(x1,x2)
3288               left join (select 3,1 from onerow) v2(y1,y2)
3289               on v1.x1 = v2.y2) subq1
3290    on (i1.f1 = subq1.x2)
3291  on (t1.unique2 = subq1.d1)
3292  left join tenk1 t2
3293  on (subq1.y1 = t2.unique1)
3294where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
3295 unique2 | stringu1 | unique1 | stringu2
3296---------+----------+---------+----------
3297      11 | WFAAAA   |       3 | LKIAAA
3298(1 row)
3299
3300-- variant that isn't quite a star-schema case
3301select ss1.d1 from
3302  tenk1 as t1
3303  inner join tenk1 as t2
3304  on t1.tenthous = t2.ten
3305  inner join
3306    int8_tbl as i8
3307    left join int4_tbl as i4
3308      inner join (select 64::information_schema.cardinal_number as d1
3309                  from tenk1 t3,
3310                       lateral (select abs(t3.unique1) + random()) ss0(x)
3311                  where t3.fivethous < 0) as ss1
3312      on i4.f1 = ss1.d1
3313    on i8.q1 = i4.f1
3314  on t1.tenthous = ss1.d1
3315where t1.unique1 < i4.f1;
3316 d1
3317----
3318(0 rows)
3319
3320-- this variant is foldable by the remove-useless-RESULT-RTEs code
3321explain (costs off)
3322select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
3323  tenk1 t1
3324  inner join int4_tbl i1
3325    left join (select v1.x2, v2.y1, 11 AS d1
3326               from (values(1,0)) v1(x1,x2)
3327               left join (values(3,1)) v2(y1,y2)
3328               on v1.x1 = v2.y2) subq1
3329    on (i1.f1 = subq1.x2)
3330  on (t1.unique2 = subq1.d1)
3331  left join tenk1 t2
3332  on (subq1.y1 = t2.unique1)
3333where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
3334                           QUERY PLAN
3335-----------------------------------------------------------------
3336 Nested Loop
3337   Join Filter: (t1.stringu1 > t2.stringu2)
3338   ->  Nested Loop
3339         ->  Seq Scan on int4_tbl i1
3340               Filter: (f1 = 0)
3341         ->  Index Scan using tenk1_unique2 on tenk1 t1
3342               Index Cond: ((unique2 = (11)) AND (unique2 < 42))
3343   ->  Index Scan using tenk1_unique1 on tenk1 t2
3344         Index Cond: (unique1 = (3))
3345(9 rows)
3346
3347select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
3348  tenk1 t1
3349  inner join int4_tbl i1
3350    left join (select v1.x2, v2.y1, 11 AS d1
3351               from (values(1,0)) v1(x1,x2)
3352               left join (values(3,1)) v2(y1,y2)
3353               on v1.x1 = v2.y2) subq1
3354    on (i1.f1 = subq1.x2)
3355  on (t1.unique2 = subq1.d1)
3356  left join tenk1 t2
3357  on (subq1.y1 = t2.unique1)
3358where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
3359 unique2 | stringu1 | unique1 | stringu2
3360---------+----------+---------+----------
3361      11 | WFAAAA   |       3 | LKIAAA
3362(1 row)
3363
3364-- Here's a variant that we can't fold too aggressively, though,
3365-- or we end up with noplace to evaluate the lateral PHV
3366explain (verbose, costs off)
3367select * from
3368  (select 1 as x) ss1 left join (select 2 as y) ss2 on (true),
3369  lateral (select ss2.y as z limit 1) ss3;
3370        QUERY PLAN
3371---------------------------
3372 Nested Loop
3373   Output: 1, (2), ((2))
3374   ->  Result
3375         Output: 2
3376   ->  Limit
3377         Output: ((2))
3378         ->  Result
3379               Output: (2)
3380(8 rows)
3381
3382select * from
3383  (select 1 as x) ss1 left join (select 2 as y) ss2 on (true),
3384  lateral (select ss2.y as z limit 1) ss3;
3385 x | y | z
3386---+---+---
3387 1 | 2 | 2
3388(1 row)
3389
3390-- Test proper handling of appendrel PHVs during useless-RTE removal
3391explain (costs off)
3392select * from
3393  (select 0 as z) as t1
3394  left join
3395  (select true as a) as t2
3396  on true,
3397  lateral (select true as b
3398           union all
3399           select a as b) as t3
3400where b;
3401              QUERY PLAN
3402---------------------------------------
3403 Nested Loop
3404   ->  Result
3405   ->  Append
3406         ->  Result
3407         ->  Result
3408               One-Time Filter: (true)
3409(6 rows)
3410
3411select * from
3412  (select 0 as z) as t1
3413  left join
3414  (select true as a) as t2
3415  on true,
3416  lateral (select true as b
3417           union all
3418           select a as b) as t3
3419where b;
3420 z | a | b
3421---+---+---
3422 0 | t | t
3423 0 | t | t
3424(2 rows)
3425
3426--
3427-- test inlining of immutable functions
3428--
3429create function f_immutable_int4(i integer) returns integer as
3430$$ begin return i; end; $$ language plpgsql immutable;
3431-- check optimization of function scan with join
3432explain (costs off)
3433select unique1 from tenk1, (select * from f_immutable_int4(1) x) x
3434where x = unique1;
3435                  QUERY PLAN
3436----------------------------------------------
3437 Index Only Scan using tenk1_unique1 on tenk1
3438   Index Cond: (unique1 = 1)
3439(2 rows)
3440
3441explain (verbose, costs off)
3442select unique1, x.*
3443from tenk1, (select *, random() from f_immutable_int4(1) x) x
3444where x = unique1;
3445                        QUERY PLAN
3446-----------------------------------------------------------
3447 Nested Loop
3448   Output: tenk1.unique1, (1), (random())
3449   ->  Result
3450         Output: 1, random()
3451   ->  Index Only Scan using tenk1_unique1 on public.tenk1
3452         Output: tenk1.unique1
3453         Index Cond: (tenk1.unique1 = (1))
3454(7 rows)
3455
3456explain (costs off)
3457select unique1 from tenk1, f_immutable_int4(1) x where x = unique1;
3458                  QUERY PLAN
3459----------------------------------------------
3460 Index Only Scan using tenk1_unique1 on tenk1
3461   Index Cond: (unique1 = 1)
3462(2 rows)
3463
3464explain (costs off)
3465select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1;
3466                  QUERY PLAN
3467----------------------------------------------
3468 Index Only Scan using tenk1_unique1 on tenk1
3469   Index Cond: (unique1 = 1)
3470(2 rows)
3471
3472explain (costs off)
3473select unique1 from tenk1, lateral f_immutable_int4(1) x where x in (select 17);
3474        QUERY PLAN
3475--------------------------
3476 Result
3477   One-Time Filter: false
3478(2 rows)
3479
3480explain (costs off)
3481select unique1, x from tenk1 join f_immutable_int4(1) x on unique1 = x;
3482                  QUERY PLAN
3483----------------------------------------------
3484 Index Only Scan using tenk1_unique1 on tenk1
3485   Index Cond: (unique1 = 1)
3486(2 rows)
3487
3488explain (costs off)
3489select unique1, x from tenk1 left join f_immutable_int4(1) x on unique1 = x;
3490                     QUERY PLAN
3491----------------------------------------------------
3492 Nested Loop Left Join
3493   Join Filter: (tenk1.unique1 = 1)
3494   ->  Index Only Scan using tenk1_unique1 on tenk1
3495   ->  Materialize
3496         ->  Result
3497(5 rows)
3498
3499explain (costs off)
3500select unique1, x from tenk1 right join f_immutable_int4(1) x on unique1 = x;
3501                     QUERY PLAN
3502----------------------------------------------------
3503 Nested Loop Left Join
3504   ->  Result
3505   ->  Index Only Scan using tenk1_unique1 on tenk1
3506         Index Cond: (unique1 = 1)
3507(4 rows)
3508
3509explain (costs off)
3510select unique1, x from tenk1 full join f_immutable_int4(1) x on unique1 = x;
3511                     QUERY PLAN
3512----------------------------------------------------
3513 Merge Full Join
3514   Merge Cond: (tenk1.unique1 = (1))
3515   ->  Index Only Scan using tenk1_unique1 on tenk1
3516   ->  Sort
3517         Sort Key: (1)
3518         ->  Result
3519(6 rows)
3520
3521-- check that pullup of a const function allows further const-folding
3522explain (costs off)
3523select unique1 from tenk1, f_immutable_int4(1) x where x = 42;
3524        QUERY PLAN
3525--------------------------
3526 Result
3527   One-Time Filter: false
3528(2 rows)
3529
3530-- test inlining of immutable functions with PlaceHolderVars
3531explain (costs off)
3532select nt3.id
3533from nt3 as nt3
3534  left join
3535    (select nt2.*, (nt2.b1 or i4 = 42) AS b3
3536     from nt2 as nt2
3537       left join
3538         f_immutable_int4(0) i4
3539         on i4 = nt2.nt1_id
3540    ) as ss2
3541    on ss2.id = nt3.nt2_id
3542where nt3.id = 1 and ss2.b3;
3543                  QUERY PLAN
3544----------------------------------------------
3545 Nested Loop Left Join
3546   Filter: ((nt2.b1 OR ((0) = 42)))
3547   ->  Index Scan using nt3_pkey on nt3
3548         Index Cond: (id = 1)
3549   ->  Nested Loop Left Join
3550         Join Filter: (0 = nt2.nt1_id)
3551         ->  Index Scan using nt2_pkey on nt2
3552               Index Cond: (id = nt3.nt2_id)
3553         ->  Result
3554(9 rows)
3555
3556drop function f_immutable_int4(int);
3557-- test inlining when function returns composite
3558create function mki8(bigint, bigint) returns int8_tbl as
3559$$select row($1,$2)::int8_tbl$$ language sql;
3560create function mki4(int) returns int4_tbl as
3561$$select row($1)::int4_tbl$$ language sql;
3562explain (verbose, costs off)
3563select * from mki8(1,2);
3564             QUERY PLAN
3565------------------------------------
3566 Function Scan on mki8
3567   Output: q1, q2
3568   Function Call: '(1,2)'::int8_tbl
3569(3 rows)
3570
3571select * from mki8(1,2);
3572 q1 | q2
3573----+----
3574  1 |  2
3575(1 row)
3576
3577explain (verbose, costs off)
3578select * from mki4(42);
3579            QUERY PLAN
3580-----------------------------------
3581 Function Scan on mki4
3582   Output: f1
3583   Function Call: '(42)'::int4_tbl
3584(3 rows)
3585
3586select * from mki4(42);
3587 f1
3588----
3589 42
3590(1 row)
3591
3592drop function mki8(bigint, bigint);
3593drop function mki4(int);
3594--
3595-- test extraction of restriction OR clauses from join OR clause
3596-- (we used to only do this for indexable clauses)
3597--
3598explain (costs off)
3599select * from tenk1 a join tenk1 b on
3600  (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.hundred = 4);
3601                                           QUERY PLAN
3602-------------------------------------------------------------------------------------------------
3603 Nested Loop
3604   Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.hundred = 4)))
3605   ->  Bitmap Heap Scan on tenk1 b
3606         Recheck Cond: ((unique1 = 2) OR (hundred = 4))
3607         ->  BitmapOr
3608               ->  Bitmap Index Scan on tenk1_unique1
3609                     Index Cond: (unique1 = 2)
3610               ->  Bitmap Index Scan on tenk1_hundred
3611                     Index Cond: (hundred = 4)
3612   ->  Materialize
3613         ->  Bitmap Heap Scan on tenk1 a
3614               Recheck Cond: ((unique1 = 1) OR (unique2 = 3))
3615               ->  BitmapOr
3616                     ->  Bitmap Index Scan on tenk1_unique1
3617                           Index Cond: (unique1 = 1)
3618                     ->  Bitmap Index Scan on tenk1_unique2
3619                           Index Cond: (unique2 = 3)
3620(17 rows)
3621
3622explain (costs off)
3623select * from tenk1 a join tenk1 b on
3624  (a.unique1 = 1 and b.unique1 = 2) or (a.unique2 = 3 and b.ten = 4);
3625                                         QUERY PLAN
3626---------------------------------------------------------------------------------------------
3627 Nested Loop
3628   Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR ((a.unique2 = 3) AND (b.ten = 4)))
3629   ->  Seq Scan on tenk1 b
3630         Filter: ((unique1 = 2) OR (ten = 4))
3631   ->  Materialize
3632         ->  Bitmap Heap Scan on tenk1 a
3633               Recheck Cond: ((unique1 = 1) OR (unique2 = 3))
3634               ->  BitmapOr
3635                     ->  Bitmap Index Scan on tenk1_unique1
3636                           Index Cond: (unique1 = 1)
3637                     ->  Bitmap Index Scan on tenk1_unique2
3638                           Index Cond: (unique2 = 3)
3639(12 rows)
3640
3641explain (costs off)
3642select * from tenk1 a join tenk1 b on
3643  (a.unique1 = 1 and b.unique1 = 2) or
3644  ((a.unique2 = 3 or a.unique2 = 7) and b.hundred = 4);
3645                                                      QUERY PLAN
3646----------------------------------------------------------------------------------------------------------------------
3647 Nested Loop
3648   Join Filter: (((a.unique1 = 1) AND (b.unique1 = 2)) OR (((a.unique2 = 3) OR (a.unique2 = 7)) AND (b.hundred = 4)))
3649   ->  Bitmap Heap Scan on tenk1 b
3650         Recheck Cond: ((unique1 = 2) OR (hundred = 4))
3651         ->  BitmapOr
3652               ->  Bitmap Index Scan on tenk1_unique1
3653                     Index Cond: (unique1 = 2)
3654               ->  Bitmap Index Scan on tenk1_hundred
3655                     Index Cond: (hundred = 4)
3656   ->  Materialize
3657         ->  Bitmap Heap Scan on tenk1 a
3658               Recheck Cond: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7))
3659               ->  BitmapOr
3660                     ->  Bitmap Index Scan on tenk1_unique1
3661                           Index Cond: (unique1 = 1)
3662                     ->  Bitmap Index Scan on tenk1_unique2
3663                           Index Cond: (unique2 = 3)
3664                     ->  Bitmap Index Scan on tenk1_unique2
3665                           Index Cond: (unique2 = 7)
3666(19 rows)
3667
3668--
3669-- test placement of movable quals in a parameterized join tree
3670--
3671explain (costs off)
3672select * from tenk1 t1 left join
3673  (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
3674  on t1.hundred = t2.hundred and t1.ten = t3.ten
3675where t1.unique1 = 1;
3676                          QUERY PLAN
3677--------------------------------------------------------------
3678 Nested Loop Left Join
3679   ->  Index Scan using tenk1_unique1 on tenk1 t1
3680         Index Cond: (unique1 = 1)
3681   ->  Nested Loop
3682         Join Filter: (t1.ten = t3.ten)
3683         ->  Bitmap Heap Scan on tenk1 t2
3684               Recheck Cond: (t1.hundred = hundred)
3685               ->  Bitmap Index Scan on tenk1_hundred
3686                     Index Cond: (hundred = t1.hundred)
3687         ->  Memoize
3688               Cache Key: t2.thousand
3689               ->  Index Scan using tenk1_unique2 on tenk1 t3
3690                     Index Cond: (unique2 = t2.thousand)
3691(13 rows)
3692
3693explain (costs off)
3694select * from tenk1 t1 left join
3695  (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
3696  on t1.hundred = t2.hundred and t1.ten + t2.ten = t3.ten
3697where t1.unique1 = 1;
3698                          QUERY PLAN
3699--------------------------------------------------------------
3700 Nested Loop Left Join
3701   ->  Index Scan using tenk1_unique1 on tenk1 t1
3702         Index Cond: (unique1 = 1)
3703   ->  Nested Loop
3704         Join Filter: ((t1.ten + t2.ten) = t3.ten)
3705         ->  Bitmap Heap Scan on tenk1 t2
3706               Recheck Cond: (t1.hundred = hundred)
3707               ->  Bitmap Index Scan on tenk1_hundred
3708                     Index Cond: (hundred = t1.hundred)
3709         ->  Memoize
3710               Cache Key: t2.thousand
3711               ->  Index Scan using tenk1_unique2 on tenk1 t3
3712                     Index Cond: (unique2 = t2.thousand)
3713(13 rows)
3714
3715explain (costs off)
3716select count(*) from
3717  tenk1 a join tenk1 b on a.unique1 = b.unique2
3718  left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand
3719  join int4_tbl on b.thousand = f1;
3720                               QUERY PLAN
3721-------------------------------------------------------------------------
3722 Aggregate
3723   ->  Nested Loop Left Join
3724         Join Filter: (a.unique2 = b.unique1)
3725         ->  Nested Loop
3726               ->  Nested Loop
3727                     ->  Seq Scan on int4_tbl
3728                     ->  Bitmap Heap Scan on tenk1 b
3729                           Recheck Cond: (thousand = int4_tbl.f1)
3730                           ->  Bitmap Index Scan on tenk1_thous_tenthous
3731                                 Index Cond: (thousand = int4_tbl.f1)
3732               ->  Index Scan using tenk1_unique1 on tenk1 a
3733                     Index Cond: (unique1 = b.unique2)
3734         ->  Index Only Scan using tenk1_thous_tenthous on tenk1 c
3735               Index Cond: (thousand = a.thousand)
3736(14 rows)
3737
3738select count(*) from
3739  tenk1 a join tenk1 b on a.unique1 = b.unique2
3740  left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand
3741  join int4_tbl on b.thousand = f1;
3742 count
3743-------
3744    10
3745(1 row)
3746
3747explain (costs off)
3748select b.unique1 from
3749  tenk1 a join tenk1 b on a.unique1 = b.unique2
3750  left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand
3751  join int4_tbl i1 on b.thousand = f1
3752  right join int4_tbl i2 on i2.f1 = b.tenthous
3753  order by 1;
3754                                       QUERY PLAN
3755-----------------------------------------------------------------------------------------
3756 Sort
3757   Sort Key: b.unique1
3758   ->  Nested Loop Left Join
3759         ->  Seq Scan on int4_tbl i2
3760         ->  Nested Loop Left Join
3761               Join Filter: (b.unique1 = 42)
3762               ->  Nested Loop
3763                     ->  Nested Loop
3764                           ->  Seq Scan on int4_tbl i1
3765                           ->  Index Scan using tenk1_thous_tenthous on tenk1 b
3766                                 Index Cond: ((thousand = i1.f1) AND (tenthous = i2.f1))
3767                     ->  Index Scan using tenk1_unique1 on tenk1 a
3768                           Index Cond: (unique1 = b.unique2)
3769               ->  Index Only Scan using tenk1_thous_tenthous on tenk1 c
3770                     Index Cond: (thousand = a.thousand)
3771(15 rows)
3772
3773select b.unique1 from
3774  tenk1 a join tenk1 b on a.unique1 = b.unique2
3775  left join tenk1 c on b.unique1 = 42 and c.thousand = a.thousand
3776  join int4_tbl i1 on b.thousand = f1
3777  right join int4_tbl i2 on i2.f1 = b.tenthous
3778  order by 1;
3779 unique1
3780---------
3781       0
3782
3783
3784
3785
3786(5 rows)
3787
3788explain (costs off)
3789select * from
3790(
3791  select unique1, q1, coalesce(unique1, -1) + q1 as fault
3792  from int8_tbl left join tenk1 on (q2 = unique2)
3793) ss
3794where fault = 122
3795order by fault;
3796                                QUERY PLAN
3797--------------------------------------------------------------------------
3798 Nested Loop Left Join
3799   Filter: ((COALESCE(tenk1.unique1, '-1'::integer) + int8_tbl.q1) = 122)
3800   ->  Seq Scan on int8_tbl
3801   ->  Index Scan using tenk1_unique2 on tenk1
3802         Index Cond: (unique2 = int8_tbl.q2)
3803(5 rows)
3804
3805select * from
3806(
3807  select unique1, q1, coalesce(unique1, -1) + q1 as fault
3808  from int8_tbl left join tenk1 on (q2 = unique2)
3809) ss
3810where fault = 122
3811order by fault;
3812 unique1 | q1  | fault
3813---------+-----+-------
3814         | 123 |   122
3815(1 row)
3816
3817explain (costs off)
3818select * from
3819(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys)
3820left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x
3821left join unnest(v1ys) as u1(u1y) on u1y = v2y;
3822                         QUERY PLAN
3823-------------------------------------------------------------
3824 Nested Loop Left Join
3825   ->  Values Scan on "*VALUES*"
3826   ->  Hash Right Join
3827         Hash Cond: (u1.u1y = "*VALUES*_1".column2)
3828         Filter: ("*VALUES*_1".column1 = "*VALUES*".column1)
3829         ->  Function Scan on unnest u1
3830         ->  Hash
3831               ->  Values Scan on "*VALUES*_1"
3832(8 rows)
3833
3834select * from
3835(values (1, array[10,20]), (2, array[20,30])) as v1(v1x,v1ys)
3836left join (values (1, 10), (2, 20)) as v2(v2x,v2y) on v2x = v1x
3837left join unnest(v1ys) as u1(u1y) on u1y = v2y;
3838 v1x |  v1ys   | v2x | v2y | u1y
3839-----+---------+-----+-----+-----
3840   1 | {10,20} |   1 |  10 |  10
3841   2 | {20,30} |   2 |  20 |  20
3842(2 rows)
3843
3844--
3845-- test handling of potential equivalence clauses above outer joins
3846--
3847explain (costs off)
3848select q1, unique2, thousand, hundred
3849  from int8_tbl a left join tenk1 b on q1 = unique2
3850  where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123);
3851                                      QUERY PLAN
3852--------------------------------------------------------------------------------------
3853 Nested Loop Left Join
3854   Filter: ((COALESCE(b.thousand, 123) = a.q1) AND (a.q1 = COALESCE(b.hundred, 123)))
3855   ->  Seq Scan on int8_tbl a
3856   ->  Index Scan using tenk1_unique2 on tenk1 b
3857         Index Cond: (unique2 = a.q1)
3858(5 rows)
3859
3860select q1, unique2, thousand, hundred
3861  from int8_tbl a left join tenk1 b on q1 = unique2
3862  where coalesce(thousand,123) = q1 and q1 = coalesce(hundred,123);
3863 q1 | unique2 | thousand | hundred
3864----+---------+----------+---------
3865(0 rows)
3866
3867explain (costs off)
3868select f1, unique2, case when unique2 is null then f1 else 0 end
3869  from int4_tbl a left join tenk1 b on f1 = unique2
3870  where (case when unique2 is null then f1 else 0 end) = 0;
3871                             QUERY PLAN
3872--------------------------------------------------------------------
3873 Nested Loop Left Join
3874   Filter: (CASE WHEN (b.unique2 IS NULL) THEN a.f1 ELSE 0 END = 0)
3875   ->  Seq Scan on int4_tbl a
3876   ->  Index Only Scan using tenk1_unique2 on tenk1 b
3877         Index Cond: (unique2 = a.f1)
3878(5 rows)
3879
3880select f1, unique2, case when unique2 is null then f1 else 0 end
3881  from int4_tbl a left join tenk1 b on f1 = unique2
3882  where (case when unique2 is null then f1 else 0 end) = 0;
3883 f1 | unique2 | case
3884----+---------+------
3885  0 |       0 |    0
3886(1 row)
3887
3888--
3889-- another case with equivalence clauses above outer joins (bug #8591)
3890--
3891explain (costs off)
3892select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand)
3893  from tenk1 a left join tenk1 b on b.thousand = a.unique1                        left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand)
3894  where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44;
3895                                         QUERY PLAN
3896---------------------------------------------------------------------------------------------
3897 Nested Loop Left Join
3898   ->  Nested Loop Left Join
3899         Filter: (COALESCE(b.twothousand, a.twothousand) = 44)
3900         ->  Index Scan using tenk1_unique2 on tenk1 a
3901               Index Cond: (unique2 < 10)
3902         ->  Bitmap Heap Scan on tenk1 b
3903               Recheck Cond: (thousand = a.unique1)
3904               ->  Bitmap Index Scan on tenk1_thous_tenthous
3905                     Index Cond: (thousand = a.unique1)
3906   ->  Index Scan using tenk1_unique2 on tenk1 c
3907         Index Cond: ((unique2 = COALESCE(b.twothousand, a.twothousand)) AND (unique2 = 44))
3908(11 rows)
3909
3910select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand)
3911  from tenk1 a left join tenk1 b on b.thousand = a.unique1                        left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand)
3912  where a.unique2 < 10 and coalesce(b.twothousand, a.twothousand) = 44;
3913 unique1 | unique1 | unique1 | coalesce
3914---------+---------+---------+----------
3915(0 rows)
3916
3917--
3918-- check handling of join aliases when flattening multiple levels of subquery
3919--
3920explain (verbose, costs off)
3921select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from
3922  (values (0),(1)) foo1(join_key)
3923left join
3924  (select join_key, bug_field from
3925    (select ss1.join_key, ss1.bug_field from
3926      (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1
3927    ) foo2
3928   left join
3929    (select unique2 as join_key from tenk1 i2) ss2
3930   using (join_key)
3931  ) foo3
3932using (join_key);
3933                                QUERY PLAN
3934--------------------------------------------------------------------------
3935 Nested Loop Left Join
3936   Output: "*VALUES*".column1, i1.f1, (666)
3937   Join Filter: ("*VALUES*".column1 = i1.f1)
3938   ->  Values Scan on "*VALUES*"
3939         Output: "*VALUES*".column1
3940   ->  Materialize
3941         Output: i1.f1, (666)
3942         ->  Nested Loop Left Join
3943               Output: i1.f1, 666
3944               ->  Seq Scan on public.int4_tbl i1
3945                     Output: i1.f1
3946               ->  Index Only Scan using tenk1_unique2 on public.tenk1 i2
3947                     Output: i2.unique2
3948                     Index Cond: (i2.unique2 = i1.f1)
3949(14 rows)
3950
3951select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from
3952  (values (0),(1)) foo1(join_key)
3953left join
3954  (select join_key, bug_field from
3955    (select ss1.join_key, ss1.bug_field from
3956      (select f1 as join_key, 666 as bug_field from int4_tbl i1) ss1
3957    ) foo2
3958   left join
3959    (select unique2 as join_key from tenk1 i2) ss2
3960   using (join_key)
3961  ) foo3
3962using (join_key);
3963 foo1_id | foo3_id | bug_field
3964---------+---------+-----------
3965       0 |       0 |       666
3966       1 |         |
3967(2 rows)
3968
3969--
3970-- test successful handling of nested outer joins with degenerate join quals
3971--
3972explain (verbose, costs off)
3973select t1.* from
3974  text_tbl t1
3975  left join (select *, '***'::text as d1 from int8_tbl i8b1) b1
3976    left join int8_tbl i8
3977      left join (select *, null::int as d2 from int8_tbl i8b2) b2
3978      on (i8.q1 = b2.q1)
3979    on (b2.d2 = b1.q2)
3980  on (t1.f1 = b1.d1)
3981  left join int4_tbl i4
3982  on (i8.q2 = i4.f1);
3983                              QUERY PLAN
3984----------------------------------------------------------------------
3985 Hash Left Join
3986   Output: t1.f1
3987   Hash Cond: (i8.q2 = i4.f1)
3988   ->  Nested Loop Left Join
3989         Output: t1.f1, i8.q2
3990         Join Filter: (t1.f1 = '***'::text)
3991         ->  Seq Scan on public.text_tbl t1
3992               Output: t1.f1
3993         ->  Materialize
3994               Output: i8.q2
3995               ->  Hash Right Join
3996                     Output: i8.q2
3997                     Hash Cond: ((NULL::integer) = i8b1.q2)
3998                     ->  Hash Join
3999                           Output: i8.q2, (NULL::integer)
4000                           Hash Cond: (i8.q1 = i8b2.q1)
4001                           ->  Seq Scan on public.int8_tbl i8
4002                                 Output: i8.q1, i8.q2
4003                           ->  Hash
4004                                 Output: i8b2.q1, (NULL::integer)
4005                                 ->  Seq Scan on public.int8_tbl i8b2
4006                                       Output: i8b2.q1, NULL::integer
4007                     ->  Hash
4008                           Output: i8b1.q2
4009                           ->  Seq Scan on public.int8_tbl i8b1
4010                                 Output: i8b1.q2
4011   ->  Hash
4012         Output: i4.f1
4013         ->  Seq Scan on public.int4_tbl i4
4014               Output: i4.f1
4015(30 rows)
4016
4017select t1.* from
4018  text_tbl t1
4019  left join (select *, '***'::text as d1 from int8_tbl i8b1) b1
4020    left join int8_tbl i8
4021      left join (select *, null::int as d2 from int8_tbl i8b2) b2
4022      on (i8.q1 = b2.q1)
4023    on (b2.d2 = b1.q2)
4024  on (t1.f1 = b1.d1)
4025  left join int4_tbl i4
4026  on (i8.q2 = i4.f1);
4027        f1
4028-------------------
4029 doh!
4030 hi de ho neighbor
4031(2 rows)
4032
4033explain (verbose, costs off)
4034select t1.* from
4035  text_tbl t1
4036  left join (select *, '***'::text as d1 from int8_tbl i8b1) b1
4037    left join int8_tbl i8
4038      left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2
4039      on (i8.q1 = b2.q1)
4040    on (b2.d2 = b1.q2)
4041  on (t1.f1 = b1.d1)
4042  left join int4_tbl i4
4043  on (i8.q2 = i4.f1);
4044                                 QUERY PLAN
4045----------------------------------------------------------------------------
4046 Hash Left Join
4047   Output: t1.f1
4048   Hash Cond: (i8.q2 = i4.f1)
4049   ->  Nested Loop Left Join
4050         Output: t1.f1, i8.q2
4051         Join Filter: (t1.f1 = '***'::text)
4052         ->  Seq Scan on public.text_tbl t1
4053               Output: t1.f1
4054         ->  Materialize
4055               Output: i8.q2
4056               ->  Hash Right Join
4057                     Output: i8.q2
4058                     Hash Cond: ((NULL::integer) = i8b1.q2)
4059                     ->  Hash Right Join
4060                           Output: i8.q2, (NULL::integer)
4061                           Hash Cond: (i8b2.q1 = i8.q1)
4062                           ->  Nested Loop
4063                                 Output: i8b2.q1, NULL::integer
4064                                 ->  Seq Scan on public.int8_tbl i8b2
4065                                       Output: i8b2.q1, i8b2.q2
4066                                 ->  Materialize
4067                                       ->  Seq Scan on public.int4_tbl i4b2
4068                           ->  Hash
4069                                 Output: i8.q1, i8.q2
4070                                 ->  Seq Scan on public.int8_tbl i8
4071                                       Output: i8.q1, i8.q2
4072                     ->  Hash
4073                           Output: i8b1.q2
4074                           ->  Seq Scan on public.int8_tbl i8b1
4075                                 Output: i8b1.q2
4076   ->  Hash
4077         Output: i4.f1
4078         ->  Seq Scan on public.int4_tbl i4
4079               Output: i4.f1
4080(34 rows)
4081
4082select t1.* from
4083  text_tbl t1
4084  left join (select *, '***'::text as d1 from int8_tbl i8b1) b1
4085    left join int8_tbl i8
4086      left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2) b2
4087      on (i8.q1 = b2.q1)
4088    on (b2.d2 = b1.q2)
4089  on (t1.f1 = b1.d1)
4090  left join int4_tbl i4
4091  on (i8.q2 = i4.f1);
4092        f1
4093-------------------
4094 doh!
4095 hi de ho neighbor
4096(2 rows)
4097
4098explain (verbose, costs off)
4099select t1.* from
4100  text_tbl t1
4101  left join (select *, '***'::text as d1 from int8_tbl i8b1) b1
4102    left join int8_tbl i8
4103      left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2
4104                 where q1 = f1) b2
4105      on (i8.q1 = b2.q1)
4106    on (b2.d2 = b1.q2)
4107  on (t1.f1 = b1.d1)
4108  left join int4_tbl i4
4109  on (i8.q2 = i4.f1);
4110                                 QUERY PLAN
4111----------------------------------------------------------------------------
4112 Hash Left Join
4113   Output: t1.f1
4114   Hash Cond: (i8.q2 = i4.f1)
4115   ->  Nested Loop Left Join
4116         Output: t1.f1, i8.q2
4117         Join Filter: (t1.f1 = '***'::text)
4118         ->  Seq Scan on public.text_tbl t1
4119               Output: t1.f1
4120         ->  Materialize
4121               Output: i8.q2
4122               ->  Hash Right Join
4123                     Output: i8.q2
4124                     Hash Cond: ((NULL::integer) = i8b1.q2)
4125                     ->  Hash Right Join
4126                           Output: i8.q2, (NULL::integer)
4127                           Hash Cond: (i8b2.q1 = i8.q1)
4128                           ->  Hash Join
4129                                 Output: i8b2.q1, NULL::integer
4130                                 Hash Cond: (i8b2.q1 = i4b2.f1)
4131                                 ->  Seq Scan on public.int8_tbl i8b2
4132                                       Output: i8b2.q1, i8b2.q2
4133                                 ->  Hash
4134                                       Output: i4b2.f1
4135                                       ->  Seq Scan on public.int4_tbl i4b2
4136                                             Output: i4b2.f1
4137                           ->  Hash
4138                                 Output: i8.q1, i8.q2
4139                                 ->  Seq Scan on public.int8_tbl i8
4140                                       Output: i8.q1, i8.q2
4141                     ->  Hash
4142                           Output: i8b1.q2
4143                           ->  Seq Scan on public.int8_tbl i8b1
4144                                 Output: i8b1.q2
4145   ->  Hash
4146         Output: i4.f1
4147         ->  Seq Scan on public.int4_tbl i4
4148               Output: i4.f1
4149(37 rows)
4150
4151select t1.* from
4152  text_tbl t1
4153  left join (select *, '***'::text as d1 from int8_tbl i8b1) b1
4154    left join int8_tbl i8
4155      left join (select *, null::int as d2 from int8_tbl i8b2, int4_tbl i4b2
4156                 where q1 = f1) b2
4157      on (i8.q1 = b2.q1)
4158    on (b2.d2 = b1.q2)
4159  on (t1.f1 = b1.d1)
4160  left join int4_tbl i4
4161  on (i8.q2 = i4.f1);
4162        f1
4163-------------------
4164 doh!
4165 hi de ho neighbor
4166(2 rows)
4167
4168explain (verbose, costs off)
4169select * from
4170  text_tbl t1
4171  inner join int8_tbl i8
4172  on i8.q2 = 456
4173  right join text_tbl t2
4174  on t1.f1 = 'doh!'
4175  left join int4_tbl i4
4176  on i8.q1 = i4.f1;
4177                       QUERY PLAN
4178--------------------------------------------------------
4179 Nested Loop Left Join
4180   Output: t1.f1, i8.q1, i8.q2, t2.f1, i4.f1
4181   ->  Seq Scan on public.text_tbl t2
4182         Output: t2.f1
4183   ->  Materialize
4184         Output: i8.q1, i8.q2, i4.f1, t1.f1
4185         ->  Nested Loop
4186               Output: i8.q1, i8.q2, i4.f1, t1.f1
4187               ->  Nested Loop Left Join
4188                     Output: i8.q1, i8.q2, i4.f1
4189                     Join Filter: (i8.q1 = i4.f1)
4190                     ->  Seq Scan on public.int8_tbl i8
4191                           Output: i8.q1, i8.q2
4192                           Filter: (i8.q2 = 456)
4193                     ->  Seq Scan on public.int4_tbl i4
4194                           Output: i4.f1
4195               ->  Seq Scan on public.text_tbl t1
4196                     Output: t1.f1
4197                     Filter: (t1.f1 = 'doh!'::text)
4198(19 rows)
4199
4200select * from
4201  text_tbl t1
4202  inner join int8_tbl i8
4203  on i8.q2 = 456
4204  right join text_tbl t2
4205  on t1.f1 = 'doh!'
4206  left join int4_tbl i4
4207  on i8.q1 = i4.f1;
4208  f1  | q1  | q2  |        f1         | f1
4209------+-----+-----+-------------------+----
4210 doh! | 123 | 456 | doh!              |
4211 doh! | 123 | 456 | hi de ho neighbor |
4212(2 rows)
4213
4214--
4215-- test for appropriate join order in the presence of lateral references
4216--
4217explain (verbose, costs off)
4218select * from
4219  text_tbl t1
4220  left join int8_tbl i8
4221  on i8.q2 = 123,
4222  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss
4223where t1.f1 = ss.f1;
4224                    QUERY PLAN
4225--------------------------------------------------
4226 Nested Loop
4227   Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1
4228   Join Filter: (t1.f1 = t2.f1)
4229   ->  Nested Loop Left Join
4230         Output: t1.f1, i8.q1, i8.q2
4231         ->  Seq Scan on public.text_tbl t1
4232               Output: t1.f1
4233         ->  Materialize
4234               Output: i8.q1, i8.q2
4235               ->  Seq Scan on public.int8_tbl i8
4236                     Output: i8.q1, i8.q2
4237                     Filter: (i8.q2 = 123)
4238   ->  Memoize
4239         Output: (i8.q1), t2.f1
4240         Cache Key: i8.q1
4241         ->  Limit
4242               Output: (i8.q1), t2.f1
4243               ->  Seq Scan on public.text_tbl t2
4244                     Output: i8.q1, t2.f1
4245(19 rows)
4246
4247select * from
4248  text_tbl t1
4249  left join int8_tbl i8
4250  on i8.q2 = 123,
4251  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss
4252where t1.f1 = ss.f1;
4253  f1  |        q1        | q2  |        q1        |  f1
4254------+------------------+-----+------------------+------
4255 doh! | 4567890123456789 | 123 | 4567890123456789 | doh!
4256(1 row)
4257
4258explain (verbose, costs off)
4259select * from
4260  text_tbl t1
4261  left join int8_tbl i8
4262  on i8.q2 = 123,
4263  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1,
4264  lateral (select ss1.* from text_tbl t3 limit 1) as ss2
4265where t1.f1 = ss2.f1;
4266                            QUERY PLAN
4267-------------------------------------------------------------------
4268 Nested Loop
4269   Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1, ((i8.q1)), (t2.f1)
4270   Join Filter: (t1.f1 = (t2.f1))
4271   ->  Nested Loop
4272         Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1
4273         ->  Nested Loop Left Join
4274               Output: t1.f1, i8.q1, i8.q2
4275               ->  Seq Scan on public.text_tbl t1
4276                     Output: t1.f1
4277               ->  Materialize
4278                     Output: i8.q1, i8.q2
4279                     ->  Seq Scan on public.int8_tbl i8
4280                           Output: i8.q1, i8.q2
4281                           Filter: (i8.q2 = 123)
4282         ->  Memoize
4283               Output: (i8.q1), t2.f1
4284               Cache Key: i8.q1
4285               ->  Limit
4286                     Output: (i8.q1), t2.f1
4287                     ->  Seq Scan on public.text_tbl t2
4288                           Output: i8.q1, t2.f1
4289   ->  Memoize
4290         Output: ((i8.q1)), (t2.f1)
4291         Cache Key: (i8.q1), t2.f1
4292         ->  Limit
4293               Output: ((i8.q1)), (t2.f1)
4294               ->  Seq Scan on public.text_tbl t3
4295                     Output: (i8.q1), t2.f1
4296(28 rows)
4297
4298select * from
4299  text_tbl t1
4300  left join int8_tbl i8
4301  on i8.q2 = 123,
4302  lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1,
4303  lateral (select ss1.* from text_tbl t3 limit 1) as ss2
4304where t1.f1 = ss2.f1;
4305  f1  |        q1        | q2  |        q1        |  f1  |        q1        |  f1
4306------+------------------+-----+------------------+------+------------------+------
4307 doh! | 4567890123456789 | 123 | 4567890123456789 | doh! | 4567890123456789 | doh!
4308(1 row)
4309
4310explain (verbose, costs off)
4311select 1 from
4312  text_tbl as tt1
4313  inner join text_tbl as tt2 on (tt1.f1 = 'foo')
4314  left join text_tbl as tt3 on (tt3.f1 = 'foo')
4315  left join text_tbl as tt4 on (tt3.f1 = tt4.f1),
4316  lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1
4317where tt1.f1 = ss1.c0;
4318                        QUERY PLAN
4319----------------------------------------------------------
4320 Nested Loop
4321   Output: 1
4322   ->  Nested Loop Left Join
4323         Output: tt1.f1, tt4.f1
4324         ->  Nested Loop
4325               Output: tt1.f1
4326               ->  Seq Scan on public.text_tbl tt1
4327                     Output: tt1.f1
4328                     Filter: (tt1.f1 = 'foo'::text)
4329               ->  Seq Scan on public.text_tbl tt2
4330                     Output: tt2.f1
4331         ->  Materialize
4332               Output: tt4.f1
4333               ->  Nested Loop Left Join
4334                     Output: tt4.f1
4335                     Join Filter: (tt3.f1 = tt4.f1)
4336                     ->  Seq Scan on public.text_tbl tt3
4337                           Output: tt3.f1
4338                           Filter: (tt3.f1 = 'foo'::text)
4339                     ->  Seq Scan on public.text_tbl tt4
4340                           Output: tt4.f1
4341                           Filter: (tt4.f1 = 'foo'::text)
4342   ->  Memoize
4343         Output: ss1.c0
4344         Cache Key: tt4.f1
4345         ->  Subquery Scan on ss1
4346               Output: ss1.c0
4347               Filter: (ss1.c0 = 'foo'::text)
4348               ->  Limit
4349                     Output: (tt4.f1)
4350                     ->  Seq Scan on public.text_tbl tt5
4351                           Output: tt4.f1
4352(32 rows)
4353
4354select 1 from
4355  text_tbl as tt1
4356  inner join text_tbl as tt2 on (tt1.f1 = 'foo')
4357  left join text_tbl as tt3 on (tt3.f1 = 'foo')
4358  left join text_tbl as tt4 on (tt3.f1 = tt4.f1),
4359  lateral (select tt4.f1 as c0 from text_tbl as tt5 limit 1) as ss1
4360where tt1.f1 = ss1.c0;
4361 ?column?
4362----------
4363(0 rows)
4364
4365--
4366-- check a case in which a PlaceHolderVar forces join order
4367--
4368explain (verbose, costs off)
4369select ss2.* from
4370  int4_tbl i41
4371  left join int8_tbl i8
4372    join (select i42.f1 as c1, i43.f1 as c2, 42 as c3
4373          from int4_tbl i42, int4_tbl i43) ss1
4374    on i8.q1 = ss1.c2
4375  on i41.f1 = ss1.c1,
4376  lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2
4377where ss1.c2 = 0;
4378                               QUERY PLAN
4379------------------------------------------------------------------------
4380 Nested Loop
4381   Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42))
4382   ->  Hash Join
4383         Output: i41.f1, i42.f1, i8.q1, i8.q2, i43.f1, 42
4384         Hash Cond: (i41.f1 = i42.f1)
4385         ->  Nested Loop
4386               Output: i8.q1, i8.q2, i43.f1, i41.f1
4387               ->  Nested Loop
4388                     Output: i8.q1, i8.q2, i43.f1
4389                     ->  Seq Scan on public.int8_tbl i8
4390                           Output: i8.q1, i8.q2
4391                           Filter: (i8.q1 = 0)
4392                     ->  Seq Scan on public.int4_tbl i43
4393                           Output: i43.f1
4394                           Filter: (i43.f1 = 0)
4395               ->  Seq Scan on public.int4_tbl i41
4396                     Output: i41.f1
4397         ->  Hash
4398               Output: i42.f1
4399               ->  Seq Scan on public.int4_tbl i42
4400                     Output: i42.f1
4401   ->  Limit
4402         Output: (i41.f1), (i8.q1), (i8.q2), (i42.f1), (i43.f1), ((42))
4403         ->  Seq Scan on public.text_tbl
4404               Output: i41.f1, i8.q1, i8.q2, i42.f1, i43.f1, (42)
4405(25 rows)
4406
4407select ss2.* from
4408  int4_tbl i41
4409  left join int8_tbl i8
4410    join (select i42.f1 as c1, i43.f1 as c2, 42 as c3
4411          from int4_tbl i42, int4_tbl i43) ss1
4412    on i8.q1 = ss1.c2
4413  on i41.f1 = ss1.c1,
4414  lateral (select i41.*, i8.*, ss1.* from text_tbl limit 1) ss2
4415where ss1.c2 = 0;
4416 f1 | q1 | q2 | c1 | c2 | c3
4417----+----+----+----+----+----
4418(0 rows)
4419
4420--
4421-- test successful handling of full join underneath left join (bug #14105)
4422--
4423explain (costs off)
4424select * from
4425  (select 1 as id) as xx
4426  left join
4427    (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id))
4428  on (xx.id = coalesce(yy.id));
4429              QUERY PLAN
4430---------------------------------------
4431 Nested Loop Left Join
4432   ->  Result
4433   ->  Hash Full Join
4434         Hash Cond: (a1.unique1 = (1))
4435         Filter: (1 = COALESCE((1)))
4436         ->  Seq Scan on tenk1 a1
4437         ->  Hash
4438               ->  Result
4439(8 rows)
4440
4441select * from
4442  (select 1 as id) as xx
4443  left join
4444    (tenk1 as a1 full join (select 1 as id) as yy on (a1.unique1 = yy.id))
4445  on (xx.id = coalesce(yy.id));
4446 id | unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | id
4447----+---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+----
4448  1 |       1 |    2838 |   1 |    1 |   1 |      1 |       1 |        1 |           1 |         1 |        1 |   2 |    3 | BAAAAA   | EFEAAA   | OOOOxx  |  1
4449(1 row)
4450
4451--
4452-- test ability to push constants through outer join clauses
4453--
4454explain (costs off)
4455  select * from int4_tbl a left join tenk1 b on f1 = unique2 where f1 = 0;
4456                   QUERY PLAN
4457-------------------------------------------------
4458 Nested Loop Left Join
4459   Join Filter: (a.f1 = b.unique2)
4460   ->  Seq Scan on int4_tbl a
4461         Filter: (f1 = 0)
4462   ->  Index Scan using tenk1_unique2 on tenk1 b
4463         Index Cond: (unique2 = 0)
4464(6 rows)
4465
4466explain (costs off)
4467  select * from tenk1 a full join tenk1 b using(unique2) where unique2 = 42;
4468                   QUERY PLAN
4469-------------------------------------------------
4470 Merge Full Join
4471   Merge Cond: (a.unique2 = b.unique2)
4472   ->  Index Scan using tenk1_unique2 on tenk1 a
4473         Index Cond: (unique2 = 42)
4474   ->  Index Scan using tenk1_unique2 on tenk1 b
4475         Index Cond: (unique2 = 42)
4476(6 rows)
4477
4478--
4479-- test that quals attached to an outer join have correct semantics,
4480-- specifically that they don't re-use expressions computed below the join;
4481-- we force a mergejoin so that coalesce(b.q1, 1) appears as a join input
4482--
4483set enable_hashjoin to off;
4484set enable_nestloop to off;
4485explain (verbose, costs off)
4486  select a.q2, b.q1
4487    from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1)
4488    where coalesce(b.q1, 1) > 0;
4489                       QUERY PLAN
4490---------------------------------------------------------
4491 Merge Left Join
4492   Output: a.q2, b.q1
4493   Merge Cond: (a.q2 = (COALESCE(b.q1, '1'::bigint)))
4494   Filter: (COALESCE(b.q1, '1'::bigint) > 0)
4495   ->  Sort
4496         Output: a.q2
4497         Sort Key: a.q2
4498         ->  Seq Scan on public.int8_tbl a
4499               Output: a.q2
4500   ->  Sort
4501         Output: b.q1, (COALESCE(b.q1, '1'::bigint))
4502         Sort Key: (COALESCE(b.q1, '1'::bigint))
4503         ->  Seq Scan on public.int8_tbl b
4504               Output: b.q1, COALESCE(b.q1, '1'::bigint)
4505(14 rows)
4506
4507select a.q2, b.q1
4508  from int8_tbl a left join int8_tbl b on a.q2 = coalesce(b.q1, 1)
4509  where coalesce(b.q1, 1) > 0;
4510        q2         |        q1
4511-------------------+------------------
4512 -4567890123456789 |
4513               123 |              123
4514               123 |              123
4515               456 |
4516  4567890123456789 | 4567890123456789
4517  4567890123456789 | 4567890123456789
4518  4567890123456789 | 4567890123456789
4519  4567890123456789 | 4567890123456789
4520  4567890123456789 | 4567890123456789
4521  4567890123456789 | 4567890123456789
4522(10 rows)
4523
4524reset enable_hashjoin;
4525reset enable_nestloop;
4526--
4527-- test join removal
4528--
4529begin;
4530CREATE TEMP TABLE a (id int PRIMARY KEY, b_id int);
4531CREATE TEMP TABLE b (id int PRIMARY KEY, c_id int);
4532CREATE TEMP TABLE c (id int PRIMARY KEY);
4533CREATE TEMP TABLE d (a int, b int);
4534INSERT INTO a VALUES (0, 0), (1, NULL);
4535INSERT INTO b VALUES (0, 0), (1, NULL);
4536INSERT INTO c VALUES (0), (1);
4537INSERT INTO d VALUES (1,3), (2,2), (3,1);
4538-- all three cases should be optimizable into a simple seqscan
4539explain (costs off) SELECT a.* FROM a LEFT JOIN b ON a.b_id = b.id;
4540  QUERY PLAN
4541---------------
4542 Seq Scan on a
4543(1 row)
4544
4545explain (costs off) SELECT b.* FROM b LEFT JOIN c ON b.c_id = c.id;
4546  QUERY PLAN
4547---------------
4548 Seq Scan on b
4549(1 row)
4550
4551explain (costs off)
4552  SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id = c.id)
4553  ON (a.b_id = b.id);
4554  QUERY PLAN
4555---------------
4556 Seq Scan on a
4557(1 row)
4558
4559-- check optimization of outer join within another special join
4560explain (costs off)
4561select id from a where id in (
4562	select b.id from b left join c on b.id = c.id
4563);
4564         QUERY PLAN
4565----------------------------
4566 Hash Join
4567   Hash Cond: (a.id = b.id)
4568   ->  Seq Scan on a
4569   ->  Hash
4570         ->  Seq Scan on b
4571(5 rows)
4572
4573-- check that join removal works for a left join when joining a subquery
4574-- that is guaranteed to be unique by its GROUP BY clause
4575explain (costs off)
4576select d.* from d left join (select * from b group by b.id, b.c_id) s
4577  on d.a = s.id and d.b = s.c_id;
4578  QUERY PLAN
4579---------------
4580 Seq Scan on d
4581(1 row)
4582
4583-- similarly, but keying off a DISTINCT clause
4584explain (costs off)
4585select d.* from d left join (select distinct * from b) s
4586  on d.a = s.id and d.b = s.c_id;
4587  QUERY PLAN
4588---------------
4589 Seq Scan on d
4590(1 row)
4591
4592-- join removal is not possible when the GROUP BY contains a column that is
4593-- not in the join condition.  (Note: as of 9.6, we notice that b.id is a
4594-- primary key and so drop b.c_id from the GROUP BY of the resulting plan;
4595-- but this happens too late for join removal in the outer plan level.)
4596explain (costs off)
4597select d.* from d left join (select * from b group by b.id, b.c_id) s
4598  on d.a = s.id;
4599                QUERY PLAN
4600------------------------------------------
4601 Merge Right Join
4602   Merge Cond: (b.id = d.a)
4603   ->  Group
4604         Group Key: b.id
4605         ->  Index Scan using b_pkey on b
4606   ->  Sort
4607         Sort Key: d.a
4608         ->  Seq Scan on d
4609(8 rows)
4610
4611-- similarly, but keying off a DISTINCT clause
4612explain (costs off)
4613select d.* from d left join (select distinct * from b) s
4614  on d.a = s.id;
4615              QUERY PLAN
4616--------------------------------------
4617 Merge Right Join
4618   Merge Cond: (b.id = d.a)
4619   ->  Unique
4620         ->  Sort
4621               Sort Key: b.id, b.c_id
4622               ->  Seq Scan on b
4623   ->  Sort
4624         Sort Key: d.a
4625         ->  Seq Scan on d
4626(9 rows)
4627
4628-- check join removal works when uniqueness of the join condition is enforced
4629-- by a UNION
4630explain (costs off)
4631select d.* from d left join (select id from a union select id from b) s
4632  on d.a = s.id;
4633  QUERY PLAN
4634---------------
4635 Seq Scan on d
4636(1 row)
4637
4638-- check join removal with a cross-type comparison operator
4639explain (costs off)
4640select i8.* from int8_tbl i8 left join (select f1 from int4_tbl group by f1) i4
4641  on i8.q1 = i4.f1;
4642       QUERY PLAN
4643-------------------------
4644 Seq Scan on int8_tbl i8
4645(1 row)
4646
4647-- check join removal with lateral references
4648explain (costs off)
4649select 1 from (select a.id FROM a left join b on a.b_id = b.id) q,
4650			  lateral generate_series(1, q.id) gs(i) where q.id = gs.i;
4651                QUERY PLAN
4652-------------------------------------------
4653 Nested Loop
4654   ->  Seq Scan on a
4655   ->  Function Scan on generate_series gs
4656         Filter: (a.id = i)
4657(4 rows)
4658
4659rollback;
4660create temp table parent (k int primary key, pd int);
4661create temp table child (k int unique, cd int);
4662insert into parent values (1, 10), (2, 20), (3, 30);
4663insert into child values (1, 100), (4, 400);
4664-- this case is optimizable
4665select p.* from parent p left join child c on (p.k = c.k);
4666 k | pd
4667---+----
4668 1 | 10
4669 2 | 20
4670 3 | 30
4671(3 rows)
4672
4673explain (costs off)
4674  select p.* from parent p left join child c on (p.k = c.k);
4675      QUERY PLAN
4676----------------------
4677 Seq Scan on parent p
4678(1 row)
4679
4680-- this case is not
4681select p.*, linked from parent p
4682  left join (select c.*, true as linked from child c) as ss
4683  on (p.k = ss.k);
4684 k | pd | linked
4685---+----+--------
4686 1 | 10 | t
4687 2 | 20 |
4688 3 | 30 |
4689(3 rows)
4690
4691explain (costs off)
4692  select p.*, linked from parent p
4693    left join (select c.*, true as linked from child c) as ss
4694    on (p.k = ss.k);
4695           QUERY PLAN
4696---------------------------------
4697 Hash Left Join
4698   Hash Cond: (p.k = c.k)
4699   ->  Seq Scan on parent p
4700   ->  Hash
4701         ->  Seq Scan on child c
4702(5 rows)
4703
4704-- check for a 9.0rc1 bug: join removal breaks pseudoconstant qual handling
4705select p.* from
4706  parent p left join child c on (p.k = c.k)
4707  where p.k = 1 and p.k = 2;
4708 k | pd
4709---+----
4710(0 rows)
4711
4712explain (costs off)
4713select p.* from
4714  parent p left join child c on (p.k = c.k)
4715  where p.k = 1 and p.k = 2;
4716                   QUERY PLAN
4717------------------------------------------------
4718 Result
4719   One-Time Filter: false
4720   ->  Index Scan using parent_pkey on parent p
4721         Index Cond: (k = 1)
4722(4 rows)
4723
4724select p.* from
4725  (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k
4726  where p.k = 1 and p.k = 2;
4727 k | pd
4728---+----
4729(0 rows)
4730
4731explain (costs off)
4732select p.* from
4733  (parent p left join child c on (p.k = c.k)) join parent x on p.k = x.k
4734  where p.k = 1 and p.k = 2;
4735        QUERY PLAN
4736--------------------------
4737 Result
4738   One-Time Filter: false
4739(2 rows)
4740
4741-- bug 5255: this is not optimizable by join removal
4742begin;
4743CREATE TEMP TABLE a (id int PRIMARY KEY);
4744CREATE TEMP TABLE b (id int PRIMARY KEY, a_id int);
4745INSERT INTO a VALUES (0), (1);
4746INSERT INTO b VALUES (0, 0), (1, NULL);
4747SELECT * FROM b LEFT JOIN a ON (b.a_id = a.id) WHERE (a.id IS NULL OR a.id > 0);
4748 id | a_id | id
4749----+------+----
4750  1 |      |
4751(1 row)
4752
4753SELECT b.* FROM b LEFT JOIN a ON (b.a_id = a.id) WHERE (a.id IS NULL OR a.id > 0);
4754 id | a_id
4755----+------
4756  1 |
4757(1 row)
4758
4759rollback;
4760-- another join removal bug: this is not optimizable, either
4761begin;
4762create temp table innertab (id int8 primary key, dat1 int8);
4763insert into innertab values(123, 42);
4764SELECT * FROM
4765    (SELECT 1 AS x) ss1
4766  LEFT JOIN
4767    (SELECT q1, q2, COALESCE(dat1, q1) AS y
4768     FROM int8_tbl LEFT JOIN innertab ON q2 = id) ss2
4769  ON true;
4770 x |        q1        |        q2         |        y
4771---+------------------+-------------------+------------------
4772 1 |              123 |               456 |              123
4773 1 |              123 |  4567890123456789 |              123
4774 1 | 4567890123456789 |               123 |               42
4775 1 | 4567890123456789 |  4567890123456789 | 4567890123456789
4776 1 | 4567890123456789 | -4567890123456789 | 4567890123456789
4777(5 rows)
4778
4779rollback;
4780-- another join removal bug: we must clean up correctly when removing a PHV
4781begin;
4782create temp table uniquetbl (f1 text unique);
4783explain (costs off)
4784select t1.* from
4785  uniquetbl as t1
4786  left join (select *, '***'::text as d1 from uniquetbl) t2
4787  on t1.f1 = t2.f1
4788  left join uniquetbl t3
4789  on t2.d1 = t3.f1;
4790        QUERY PLAN
4791--------------------------
4792 Seq Scan on uniquetbl t1
4793(1 row)
4794
4795explain (costs off)
4796select t0.*
4797from
4798 text_tbl t0
4799 left join
4800   (select case t1.ten when 0 then 'doh!'::text else null::text end as case1,
4801           t1.stringu2
4802     from tenk1 t1
4803     join int4_tbl i4 ON i4.f1 = t1.unique2
4804     left join uniquetbl u1 ON u1.f1 = t1.string4) ss
4805  on t0.f1 = ss.case1
4806where ss.stringu2 !~* ss.case1;
4807                                         QUERY PLAN
4808--------------------------------------------------------------------------------------------
4809 Nested Loop
4810   Join Filter: (CASE t1.ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END = t0.f1)
4811   ->  Nested Loop
4812         ->  Seq Scan on int4_tbl i4
4813         ->  Index Scan using tenk1_unique2 on tenk1 t1
4814               Index Cond: (unique2 = i4.f1)
4815               Filter: (stringu2 !~* CASE ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END)
4816   ->  Materialize
4817         ->  Seq Scan on text_tbl t0
4818(9 rows)
4819
4820select t0.*
4821from
4822 text_tbl t0
4823 left join
4824   (select case t1.ten when 0 then 'doh!'::text else null::text end as case1,
4825           t1.stringu2
4826     from tenk1 t1
4827     join int4_tbl i4 ON i4.f1 = t1.unique2
4828     left join uniquetbl u1 ON u1.f1 = t1.string4) ss
4829  on t0.f1 = ss.case1
4830where ss.stringu2 !~* ss.case1;
4831  f1
4832------
4833 doh!
4834(1 row)
4835
4836rollback;
4837-- test case to expose miscomputation of required relid set for a PHV
4838explain (verbose, costs off)
4839select i8.*, ss.v, t.unique2
4840  from int8_tbl i8
4841    left join int4_tbl i4 on i4.f1 = 1
4842    left join lateral (select i4.f1 + 1 as v) as ss on true
4843    left join tenk1 t on t.unique2 = ss.v
4844where q2 = 456;
4845                         QUERY PLAN
4846-------------------------------------------------------------
4847 Nested Loop Left Join
4848   Output: i8.q1, i8.q2, ((i4.f1 + 1)), t.unique2
4849   ->  Nested Loop Left Join
4850         Output: i8.q1, i8.q2, (i4.f1 + 1)
4851         ->  Seq Scan on public.int8_tbl i8
4852               Output: i8.q1, i8.q2
4853               Filter: (i8.q2 = 456)
4854         ->  Seq Scan on public.int4_tbl i4
4855               Output: i4.f1
4856               Filter: (i4.f1 = 1)
4857   ->  Index Only Scan using tenk1_unique2 on public.tenk1 t
4858         Output: t.unique2
4859         Index Cond: (t.unique2 = ((i4.f1 + 1)))
4860(13 rows)
4861
4862select i8.*, ss.v, t.unique2
4863  from int8_tbl i8
4864    left join int4_tbl i4 on i4.f1 = 1
4865    left join lateral (select i4.f1 + 1 as v) as ss on true
4866    left join tenk1 t on t.unique2 = ss.v
4867where q2 = 456;
4868 q1  | q2  | v | unique2
4869-----+-----+---+---------
4870 123 | 456 |   |
4871(1 row)
4872
4873-- and check a related issue where we miscompute required relids for
4874-- a PHV that's been translated to a child rel
4875create temp table parttbl (a integer primary key) partition by range (a);
4876create temp table parttbl1 partition of parttbl for values from (1) to (100);
4877insert into parttbl values (11), (12);
4878explain (costs off)
4879select * from
4880  (select *, 12 as phv from parttbl) as ss
4881  right join int4_tbl on true
4882where ss.a = ss.phv and f1 = 0;
4883             QUERY PLAN
4884------------------------------------
4885 Nested Loop
4886   ->  Seq Scan on int4_tbl
4887         Filter: (f1 = 0)
4888   ->  Seq Scan on parttbl1 parttbl
4889         Filter: (a = 12)
4890(5 rows)
4891
4892select * from
4893  (select *, 12 as phv from parttbl) as ss
4894  right join int4_tbl on true
4895where ss.a = ss.phv and f1 = 0;
4896 a  | phv | f1
4897----+-----+----
4898 12 |  12 |  0
4899(1 row)
4900
4901-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs
4902select * from
4903  int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; -- error
4904ERROR:  column reference "f1" is ambiguous
4905LINE 2: ..._tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1;
4906                                                                    ^
4907select * from
4908  int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1; -- error
4909ERROR:  invalid reference to FROM-clause entry for table "y"
4910LINE 2: ...bl x join (int4_tbl x cross join int4_tbl y) j on q1 = y.f1;
4911                                                                  ^
4912HINT:  There is an entry for table "y", but it cannot be referenced from this part of the query.
4913select * from
4914  int8_tbl x join (int4_tbl x cross join int4_tbl y(ff)) j on q1 = f1; -- ok
4915 q1 | q2 | f1 | ff
4916----+----+----+----
4917(0 rows)
4918
4919--
4920-- Test hints given on incorrect column references are useful
4921--
4922select t1.uunique1 from
4923  tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t1" suggestion
4924ERROR:  column t1.uunique1 does not exist
4925LINE 1: select t1.uunique1 from
4926               ^
4927HINT:  Perhaps you meant to reference the column "t1.unique1".
4928select t2.uunique1 from
4929  tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, prefer "t2" suggestion
4930ERROR:  column t2.uunique1 does not exist
4931LINE 1: select t2.uunique1 from
4932               ^
4933HINT:  Perhaps you meant to reference the column "t2.unique1".
4934select uunique1 from
4935  tenk1 t1 join tenk2 t2 on t1.two = t2.two; -- error, suggest both at once
4936ERROR:  column "uunique1" does not exist
4937LINE 1: select uunique1 from
4938               ^
4939HINT:  Perhaps you meant to reference the column "t1.unique1" or the column "t2.unique1".
4940--
4941-- Take care to reference the correct RTE
4942--
4943select atts.relid::regclass, s.* from pg_stats s join
4944    pg_attribute a on s.attname = a.attname and s.tablename =
4945    a.attrelid::regclass::text join (select unnest(indkey) attnum,
4946    indexrelid from pg_index i) atts on atts.attnum = a.attnum where
4947    schemaname != 'pg_catalog';
4948ERROR:  column atts.relid does not exist
4949LINE 1: select atts.relid::regclass, s.* from pg_stats s join
4950               ^
4951--
4952-- Test LATERAL
4953--
4954select unique2, x.*
4955from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x;
4956 unique2 | f1
4957---------+----
4958    9998 |  0
4959(1 row)
4960
4961explain (costs off)
4962  select unique2, x.*
4963  from tenk1 a, lateral (select * from int4_tbl b where f1 = a.unique1) x;
4964                   QUERY PLAN
4965-------------------------------------------------
4966 Nested Loop
4967   ->  Seq Scan on int4_tbl b
4968   ->  Index Scan using tenk1_unique1 on tenk1 a
4969         Index Cond: (unique1 = b.f1)
4970(4 rows)
4971
4972select unique2, x.*
4973from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss;
4974 unique2 | f1
4975---------+----
4976    9998 |  0
4977(1 row)
4978
4979explain (costs off)
4980  select unique2, x.*
4981  from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss;
4982                  QUERY PLAN
4983-----------------------------------------------
4984 Nested Loop
4985   ->  Seq Scan on int4_tbl x
4986   ->  Index Scan using tenk1_unique1 on tenk1
4987         Index Cond: (unique1 = x.f1)
4988(4 rows)
4989
4990explain (costs off)
4991  select unique2, x.*
4992  from int4_tbl x cross join lateral (select unique2 from tenk1 where f1 = unique1) ss;
4993                  QUERY PLAN
4994-----------------------------------------------
4995 Nested Loop
4996   ->  Seq Scan on int4_tbl x
4997   ->  Index Scan using tenk1_unique1 on tenk1
4998         Index Cond: (unique1 = x.f1)
4999(4 rows)
5000
5001select unique2, x.*
5002from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true;
5003 unique2 |     f1
5004---------+-------------
5005    9998 |           0
5006         |      123456
5007         |     -123456
5008         |  2147483647
5009         | -2147483647
5010(5 rows)
5011
5012explain (costs off)
5013  select unique2, x.*
5014  from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true;
5015                  QUERY PLAN
5016-----------------------------------------------
5017 Nested Loop Left Join
5018   ->  Seq Scan on int4_tbl x
5019   ->  Index Scan using tenk1_unique1 on tenk1
5020         Index Cond: (unique1 = x.f1)
5021(4 rows)
5022
5023-- check scoping of lateral versus parent references
5024-- the first of these should return int8_tbl.q2, the second int8_tbl.q1
5025select *, (select r from (select q1 as q2) x, (select q2 as r) y) from int8_tbl;
5026        q1        |        q2         |         r
5027------------------+-------------------+-------------------
5028              123 |               456 |               456
5029              123 |  4567890123456789 |  4567890123456789
5030 4567890123456789 |               123 |               123
5031 4567890123456789 |  4567890123456789 |  4567890123456789
5032 4567890123456789 | -4567890123456789 | -4567890123456789
5033(5 rows)
5034
5035select *, (select r from (select q1 as q2) x, lateral (select q2 as r) y) from int8_tbl;
5036        q1        |        q2         |        r
5037------------------+-------------------+------------------
5038              123 |               456 |              123
5039              123 |  4567890123456789 |              123
5040 4567890123456789 |               123 | 4567890123456789
5041 4567890123456789 |  4567890123456789 | 4567890123456789
5042 4567890123456789 | -4567890123456789 | 4567890123456789
5043(5 rows)
5044
5045-- lateral with function in FROM
5046select count(*) from tenk1 a, lateral generate_series(1,two) g;
5047 count
5048-------
5049  5000
5050(1 row)
5051
5052explain (costs off)
5053  select count(*) from tenk1 a, lateral generate_series(1,two) g;
5054                      QUERY PLAN
5055------------------------------------------------------
5056 Aggregate
5057   ->  Nested Loop
5058         ->  Seq Scan on tenk1 a
5059         ->  Memoize
5060               Cache Key: a.two
5061               ->  Function Scan on generate_series g
5062(6 rows)
5063
5064explain (costs off)
5065  select count(*) from tenk1 a cross join lateral generate_series(1,two) g;
5066                      QUERY PLAN
5067------------------------------------------------------
5068 Aggregate
5069   ->  Nested Loop
5070         ->  Seq Scan on tenk1 a
5071         ->  Memoize
5072               Cache Key: a.two
5073               ->  Function Scan on generate_series g
5074(6 rows)
5075
5076-- don't need the explicit LATERAL keyword for functions
5077explain (costs off)
5078  select count(*) from tenk1 a, generate_series(1,two) g;
5079                      QUERY PLAN
5080------------------------------------------------------
5081 Aggregate
5082   ->  Nested Loop
5083         ->  Seq Scan on tenk1 a
5084         ->  Memoize
5085               Cache Key: a.two
5086               ->  Function Scan on generate_series g
5087(6 rows)
5088
5089-- lateral with UNION ALL subselect
5090explain (costs off)
5091  select * from generate_series(100,200) g,
5092    lateral (select * from int8_tbl a where g = q1 union all
5093             select * from int8_tbl b where g = q2) ss;
5094                QUERY PLAN
5095------------------------------------------
5096 Nested Loop
5097   ->  Function Scan on generate_series g
5098   ->  Append
5099         ->  Seq Scan on int8_tbl a
5100               Filter: (g.g = q1)
5101         ->  Seq Scan on int8_tbl b
5102               Filter: (g.g = q2)
5103(7 rows)
5104
5105select * from generate_series(100,200) g,
5106  lateral (select * from int8_tbl a where g = q1 union all
5107           select * from int8_tbl b where g = q2) ss;
5108  g  |        q1        |        q2
5109-----+------------------+------------------
5110 123 |              123 |              456
5111 123 |              123 | 4567890123456789
5112 123 | 4567890123456789 |              123
5113(3 rows)
5114
5115-- lateral with VALUES
5116explain (costs off)
5117  select count(*) from tenk1 a,
5118    tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x;
5119                         QUERY PLAN
5120------------------------------------------------------------
5121 Aggregate
5122   ->  Merge Join
5123         Merge Cond: (a.unique1 = b.unique2)
5124         ->  Index Only Scan using tenk1_unique1 on tenk1 a
5125         ->  Index Only Scan using tenk1_unique2 on tenk1 b
5126(5 rows)
5127
5128select count(*) from tenk1 a,
5129  tenk1 b join lateral (values(a.unique1)) ss(x) on b.unique2 = ss.x;
5130 count
5131-------
5132 10000
5133(1 row)
5134
5135-- lateral with VALUES, no flattening possible
5136explain (costs off)
5137  select count(*) from tenk1 a,
5138    tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x;
5139                            QUERY PLAN
5140------------------------------------------------------------------
5141 Aggregate
5142   ->  Nested Loop
5143         ->  Nested Loop
5144               ->  Index Only Scan using tenk1_unique1 on tenk1 a
5145               ->  Values Scan on "*VALUES*"
5146         ->  Memoize
5147               Cache Key: "*VALUES*".column1
5148               ->  Index Only Scan using tenk1_unique2 on tenk1 b
5149                     Index Cond: (unique2 = "*VALUES*".column1)
5150(9 rows)
5151
5152select count(*) from tenk1 a,
5153  tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x;
5154 count
5155-------
5156 10000
5157(1 row)
5158
5159-- lateral injecting a strange outer join condition
5160explain (costs off)
5161  select * from int8_tbl a,
5162    int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z)
5163      on x.q2 = ss.z
5164  order by a.q1, a.q2, x.q1, x.q2, ss.z;
5165                   QUERY PLAN
5166------------------------------------------------
5167 Sort
5168   Sort Key: a.q1, a.q2, x.q1, x.q2, (a.q1)
5169   ->  Nested Loop
5170         ->  Seq Scan on int8_tbl a
5171         ->  Hash Right Join
5172               Hash Cond: ((a.q1) = x.q2)
5173               ->  Seq Scan on int4_tbl y
5174               ->  Hash
5175                     ->  Seq Scan on int8_tbl x
5176(9 rows)
5177
5178select * from int8_tbl a,
5179  int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z)
5180    on x.q2 = ss.z
5181  order by a.q1, a.q2, x.q1, x.q2, ss.z;
5182        q1        |        q2         |        q1        |        q2         |        z
5183------------------+-------------------+------------------+-------------------+------------------
5184              123 |               456 |              123 |               456 |
5185              123 |               456 |              123 |  4567890123456789 |
5186              123 |               456 | 4567890123456789 | -4567890123456789 |
5187              123 |               456 | 4567890123456789 |               123 |              123
5188              123 |               456 | 4567890123456789 |               123 |              123
5189              123 |               456 | 4567890123456789 |               123 |              123
5190              123 |               456 | 4567890123456789 |               123 |              123
5191              123 |               456 | 4567890123456789 |               123 |              123
5192              123 |               456 | 4567890123456789 |  4567890123456789 |
5193              123 |  4567890123456789 |              123 |               456 |
5194              123 |  4567890123456789 |              123 |  4567890123456789 |
5195              123 |  4567890123456789 | 4567890123456789 | -4567890123456789 |
5196              123 |  4567890123456789 | 4567890123456789 |               123 |              123
5197              123 |  4567890123456789 | 4567890123456789 |               123 |              123
5198              123 |  4567890123456789 | 4567890123456789 |               123 |              123
5199              123 |  4567890123456789 | 4567890123456789 |               123 |              123
5200              123 |  4567890123456789 | 4567890123456789 |               123 |              123
5201              123 |  4567890123456789 | 4567890123456789 |  4567890123456789 |
5202 4567890123456789 | -4567890123456789 |              123 |               456 |
5203 4567890123456789 | -4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5204 4567890123456789 | -4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5205 4567890123456789 | -4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5206 4567890123456789 | -4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5207 4567890123456789 | -4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5208 4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 |
5209 4567890123456789 | -4567890123456789 | 4567890123456789 |               123 |
5210 4567890123456789 | -4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5211 4567890123456789 | -4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5212 4567890123456789 | -4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5213 4567890123456789 | -4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5214 4567890123456789 | -4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5215 4567890123456789 |               123 |              123 |               456 |
5216 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789
5217 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789
5218 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789
5219 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789
5220 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789
5221 4567890123456789 |               123 | 4567890123456789 | -4567890123456789 |
5222 4567890123456789 |               123 | 4567890123456789 |               123 |
5223 4567890123456789 |               123 | 4567890123456789 |  4567890123456789 | 4567890123456789
5224 4567890123456789 |               123 | 4567890123456789 |  4567890123456789 | 4567890123456789
5225 4567890123456789 |               123 | 4567890123456789 |  4567890123456789 | 4567890123456789
5226 4567890123456789 |               123 | 4567890123456789 |  4567890123456789 | 4567890123456789
5227 4567890123456789 |               123 | 4567890123456789 |  4567890123456789 | 4567890123456789
5228 4567890123456789 |  4567890123456789 |              123 |               456 |
5229 4567890123456789 |  4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5230 4567890123456789 |  4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5231 4567890123456789 |  4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5232 4567890123456789 |  4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5233 4567890123456789 |  4567890123456789 |              123 |  4567890123456789 | 4567890123456789
5234 4567890123456789 |  4567890123456789 | 4567890123456789 | -4567890123456789 |
5235 4567890123456789 |  4567890123456789 | 4567890123456789 |               123 |
5236 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5237 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5238 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5239 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5240 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5241(57 rows)
5242
5243-- lateral reference to a join alias variable
5244select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
5245  lateral (select x) ss2(y);
5246 x | f1 | y
5247---+----+---
5248 0 |  0 | 0
5249(1 row)
5250
5251select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
5252  lateral (values(x)) ss2(y);
5253      x      |     f1      |      y
5254-------------+-------------+-------------
5255           0 |           0 |           0
5256      123456 |      123456 |      123456
5257     -123456 |     -123456 |     -123456
5258  2147483647 |  2147483647 |  2147483647
5259 -2147483647 | -2147483647 | -2147483647
5260(5 rows)
5261
5262select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j,
5263  lateral (select x) ss2(y);
5264 x | f1 | y
5265---+----+---
5266 0 |  0 | 0
5267(1 row)
5268
5269-- lateral references requiring pullup
5270select * from (values(1)) x(lb),
5271  lateral generate_series(lb,4) x4;
5272 lb | x4
5273----+----
5274  1 |  1
5275  1 |  2
5276  1 |  3
5277  1 |  4
5278(4 rows)
5279
5280select * from (select f1/1000000000 from int4_tbl) x(lb),
5281  lateral generate_series(lb,4) x4;
5282 lb | x4
5283----+----
5284  0 |  0
5285  0 |  1
5286  0 |  2
5287  0 |  3
5288  0 |  4
5289  0 |  0
5290  0 |  1
5291  0 |  2
5292  0 |  3
5293  0 |  4
5294  0 |  0
5295  0 |  1
5296  0 |  2
5297  0 |  3
5298  0 |  4
5299  2 |  2
5300  2 |  3
5301  2 |  4
5302 -2 | -2
5303 -2 | -1
5304 -2 |  0
5305 -2 |  1
5306 -2 |  2
5307 -2 |  3
5308 -2 |  4
5309(25 rows)
5310
5311select * from (values(1)) x(lb),
5312  lateral (values(lb)) y(lbcopy);
5313 lb | lbcopy
5314----+--------
5315  1 |      1
5316(1 row)
5317
5318select * from (values(1)) x(lb),
5319  lateral (select lb from int4_tbl) y(lbcopy);
5320 lb | lbcopy
5321----+--------
5322  1 |      1
5323  1 |      1
5324  1 |      1
5325  1 |      1
5326  1 |      1
5327(5 rows)
5328
5329select * from
5330  int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1,
5331  lateral (values(x.q1,y.q1,y.q2)) v(xq1,yq1,yq2);
5332        q1        |        q2         |        q1        |        q2         |       xq1        |       yq1        |        yq2
5333------------------+-------------------+------------------+-------------------+------------------+------------------+-------------------
5334              123 |               456 |                  |                   |              123 |                  |
5335              123 |  4567890123456789 | 4567890123456789 | -4567890123456789 |              123 | 4567890123456789 | -4567890123456789
5336              123 |  4567890123456789 | 4567890123456789 |  4567890123456789 |              123 | 4567890123456789 |  4567890123456789
5337              123 |  4567890123456789 | 4567890123456789 |               123 |              123 | 4567890123456789 |               123
5338 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789 |              123 |  4567890123456789
5339 4567890123456789 |               123 |              123 |               456 | 4567890123456789 |              123 |               456
5340 4567890123456789 |  4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789
5341 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 |  4567890123456789
5342 4567890123456789 |  4567890123456789 | 4567890123456789 |               123 | 4567890123456789 | 4567890123456789 |               123
5343 4567890123456789 | -4567890123456789 |                  |                   | 4567890123456789 |                  |
5344(10 rows)
5345
5346select * from
5347  int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1,
5348  lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2);
5349        q1        |        q2         |        q1        |        q2         |       xq1        |       yq1        |        yq2
5350------------------+-------------------+------------------+-------------------+------------------+------------------+-------------------
5351              123 |               456 |                  |                   |              123 |                  |
5352              123 |  4567890123456789 | 4567890123456789 | -4567890123456789 |              123 | 4567890123456789 | -4567890123456789
5353              123 |  4567890123456789 | 4567890123456789 |  4567890123456789 |              123 | 4567890123456789 |  4567890123456789
5354              123 |  4567890123456789 | 4567890123456789 |               123 |              123 | 4567890123456789 |               123
5355 4567890123456789 |               123 |              123 |  4567890123456789 | 4567890123456789 |              123 |  4567890123456789
5356 4567890123456789 |               123 |              123 |               456 | 4567890123456789 |              123 |               456
5357 4567890123456789 |  4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789 | -4567890123456789
5358 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 |  4567890123456789
5359 4567890123456789 |  4567890123456789 | 4567890123456789 |               123 | 4567890123456789 | 4567890123456789 |               123
5360 4567890123456789 | -4567890123456789 |                  |                   | 4567890123456789 |                  |
5361(10 rows)
5362
5363select x.* from
5364  int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1,
5365  lateral (select x.q1,y.q1,y.q2) v(xq1,yq1,yq2);
5366        q1        |        q2
5367------------------+-------------------
5368              123 |               456
5369              123 |  4567890123456789
5370              123 |  4567890123456789
5371              123 |  4567890123456789
5372 4567890123456789 |               123
5373 4567890123456789 |               123
5374 4567890123456789 |  4567890123456789
5375 4567890123456789 |  4567890123456789
5376 4567890123456789 |  4567890123456789
5377 4567890123456789 | -4567890123456789
5378(10 rows)
5379
5380select v.* from
5381  (int8_tbl x left join (select q1,coalesce(q2,0) q2 from int8_tbl) y on x.q2 = y.q1)
5382  left join int4_tbl z on z.f1 = x.q2,
5383  lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy);
5384        vx         |        vy
5385-------------------+-------------------
5386               123 |
5387               456 |
5388               123 |  4567890123456789
5389  4567890123456789 | -4567890123456789
5390               123 |  4567890123456789
5391  4567890123456789 |  4567890123456789
5392               123 |  4567890123456789
5393  4567890123456789 |               123
5394  4567890123456789 |               123
5395               123 |  4567890123456789
5396  4567890123456789 |               123
5397               123 |               456
5398  4567890123456789 |  4567890123456789
5399  4567890123456789 | -4567890123456789
5400  4567890123456789 |  4567890123456789
5401  4567890123456789 |  4567890123456789
5402  4567890123456789 |  4567890123456789
5403  4567890123456789 |               123
5404  4567890123456789 |
5405 -4567890123456789 |
5406(20 rows)
5407
5408select v.* from
5409  (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1)
5410  left join int4_tbl z on z.f1 = x.q2,
5411  lateral (select x.q1,y.q1 union all select x.q2,y.q2) v(vx,vy);
5412        vx         |        vy
5413-------------------+-------------------
5414  4567890123456789 |               123
5415               123 |               456
5416  4567890123456789 |               123
5417               123 |  4567890123456789
5418  4567890123456789 |  4567890123456789
5419  4567890123456789 |               123
5420               123 |  4567890123456789
5421  4567890123456789 |               123
5422  4567890123456789 |  4567890123456789
5423  4567890123456789 |  4567890123456789
5424               123 |  4567890123456789
5425  4567890123456789 |  4567890123456789
5426  4567890123456789 |  4567890123456789
5427  4567890123456789 | -4567890123456789
5428               123 |  4567890123456789
5429  4567890123456789 | -4567890123456789
5430               123 |
5431               456 |
5432  4567890123456789 |
5433 -4567890123456789 |
5434(20 rows)
5435
5436select v.* from
5437  (int8_tbl x left join (select q1,(select coalesce(q2,0)) q2 from int8_tbl) y on x.q2 = y.q1)
5438  left join int4_tbl z on z.f1 = x.q2,
5439  lateral (select x.q1,y.q1 from onerow union all select x.q2,y.q2 from onerow) v(vx,vy);
5440        vx         |        vy
5441-------------------+-------------------
5442  4567890123456789 |               123
5443               123 |               456
5444  4567890123456789 |               123
5445               123 |  4567890123456789
5446  4567890123456789 |  4567890123456789
5447  4567890123456789 |               123
5448               123 |  4567890123456789
5449  4567890123456789 |               123
5450  4567890123456789 |  4567890123456789
5451  4567890123456789 |  4567890123456789
5452               123 |  4567890123456789
5453  4567890123456789 |  4567890123456789
5454  4567890123456789 |  4567890123456789
5455  4567890123456789 | -4567890123456789
5456               123 |  4567890123456789
5457  4567890123456789 | -4567890123456789
5458               123 |
5459               456 |
5460  4567890123456789 |
5461 -4567890123456789 |
5462(20 rows)
5463
5464explain (verbose, costs off)
5465select * from
5466  int8_tbl a left join
5467  lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1;
5468                QUERY PLAN
5469------------------------------------------
5470 Nested Loop Left Join
5471   Output: a.q1, a.q2, b.q1, b.q2, (a.q2)
5472   ->  Seq Scan on public.int8_tbl a
5473         Output: a.q1, a.q2
5474   ->  Seq Scan on public.int8_tbl b
5475         Output: b.q1, b.q2, a.q2
5476         Filter: (a.q2 = b.q1)
5477(7 rows)
5478
5479select * from
5480  int8_tbl a left join
5481  lateral (select *, a.q2 as x from int8_tbl b) ss on a.q2 = ss.q1;
5482        q1        |        q2         |        q1        |        q2         |        x
5483------------------+-------------------+------------------+-------------------+------------------
5484              123 |               456 |                  |                   |
5485              123 |  4567890123456789 | 4567890123456789 |               123 | 4567890123456789
5486              123 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5487              123 |  4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789
5488 4567890123456789 |               123 |              123 |               456 |              123
5489 4567890123456789 |               123 |              123 |  4567890123456789 |              123
5490 4567890123456789 |  4567890123456789 | 4567890123456789 |               123 | 4567890123456789
5491 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5492 4567890123456789 |  4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789
5493 4567890123456789 | -4567890123456789 |                  |                   |
5494(10 rows)
5495
5496explain (verbose, costs off)
5497select * from
5498  int8_tbl a left join
5499  lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1;
5500                            QUERY PLAN
5501------------------------------------------------------------------
5502 Nested Loop Left Join
5503   Output: a.q1, a.q2, b.q1, b.q2, (COALESCE(a.q2, '42'::bigint))
5504   ->  Seq Scan on public.int8_tbl a
5505         Output: a.q1, a.q2
5506   ->  Seq Scan on public.int8_tbl b
5507         Output: b.q1, b.q2, COALESCE(a.q2, '42'::bigint)
5508         Filter: (a.q2 = b.q1)
5509(7 rows)
5510
5511select * from
5512  int8_tbl a left join
5513  lateral (select *, coalesce(a.q2, 42) as x from int8_tbl b) ss on a.q2 = ss.q1;
5514        q1        |        q2         |        q1        |        q2         |        x
5515------------------+-------------------+------------------+-------------------+------------------
5516              123 |               456 |                  |                   |
5517              123 |  4567890123456789 | 4567890123456789 |               123 | 4567890123456789
5518              123 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5519              123 |  4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789
5520 4567890123456789 |               123 |              123 |               456 |              123
5521 4567890123456789 |               123 |              123 |  4567890123456789 |              123
5522 4567890123456789 |  4567890123456789 | 4567890123456789 |               123 | 4567890123456789
5523 4567890123456789 |  4567890123456789 | 4567890123456789 |  4567890123456789 | 4567890123456789
5524 4567890123456789 |  4567890123456789 | 4567890123456789 | -4567890123456789 | 4567890123456789
5525 4567890123456789 | -4567890123456789 |                  |                   |
5526(10 rows)
5527
5528-- lateral can result in join conditions appearing below their
5529-- real semantic level
5530explain (verbose, costs off)
5531select * from int4_tbl i left join
5532  lateral (select * from int2_tbl j where i.f1 = j.f1) k on true;
5533                QUERY PLAN
5534-------------------------------------------
5535 Hash Left Join
5536   Output: i.f1, j.f1
5537   Hash Cond: (i.f1 = j.f1)
5538   ->  Seq Scan on public.int4_tbl i
5539         Output: i.f1
5540   ->  Hash
5541         Output: j.f1
5542         ->  Seq Scan on public.int2_tbl j
5543               Output: j.f1
5544(9 rows)
5545
5546select * from int4_tbl i left join
5547  lateral (select * from int2_tbl j where i.f1 = j.f1) k on true;
5548     f1      | f1
5549-------------+----
5550           0 |  0
5551      123456 |
5552     -123456 |
5553  2147483647 |
5554 -2147483647 |
5555(5 rows)
5556
5557explain (verbose, costs off)
5558select * from int4_tbl i left join
5559  lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true;
5560             QUERY PLAN
5561-------------------------------------
5562 Nested Loop Left Join
5563   Output: i.f1, (COALESCE(i.*))
5564   ->  Seq Scan on public.int4_tbl i
5565         Output: i.f1, i.*
5566   ->  Seq Scan on public.int2_tbl j
5567         Output: j.f1, COALESCE(i.*)
5568         Filter: (i.f1 = j.f1)
5569(7 rows)
5570
5571select * from int4_tbl i left join
5572  lateral (select coalesce(i) from int2_tbl j where i.f1 = j.f1) k on true;
5573     f1      | coalesce
5574-------------+----------
5575           0 | (0)
5576      123456 |
5577     -123456 |
5578  2147483647 |
5579 -2147483647 |
5580(5 rows)
5581
5582explain (verbose, costs off)
5583select * from int4_tbl a,
5584  lateral (
5585    select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2)
5586  ) ss;
5587                   QUERY PLAN
5588-------------------------------------------------
5589 Nested Loop
5590   Output: a.f1, b.f1, c.q1, c.q2
5591   ->  Seq Scan on public.int4_tbl a
5592         Output: a.f1
5593   ->  Hash Left Join
5594         Output: b.f1, c.q1, c.q2
5595         Hash Cond: (b.f1 = c.q1)
5596         ->  Seq Scan on public.int4_tbl b
5597               Output: b.f1
5598         ->  Hash
5599               Output: c.q1, c.q2
5600               ->  Seq Scan on public.int8_tbl c
5601                     Output: c.q1, c.q2
5602                     Filter: (a.f1 = c.q2)
5603(14 rows)
5604
5605select * from int4_tbl a,
5606  lateral (
5607    select * from int4_tbl b left join int8_tbl c on (b.f1 = q1 and a.f1 = q2)
5608  ) ss;
5609     f1      |     f1      | q1 | q2
5610-------------+-------------+----+----
5611           0 |           0 |    |
5612           0 |      123456 |    |
5613           0 |     -123456 |    |
5614           0 |  2147483647 |    |
5615           0 | -2147483647 |    |
5616      123456 |           0 |    |
5617      123456 |      123456 |    |
5618      123456 |     -123456 |    |
5619      123456 |  2147483647 |    |
5620      123456 | -2147483647 |    |
5621     -123456 |           0 |    |
5622     -123456 |      123456 |    |
5623     -123456 |     -123456 |    |
5624     -123456 |  2147483647 |    |
5625     -123456 | -2147483647 |    |
5626  2147483647 |           0 |    |
5627  2147483647 |      123456 |    |
5628  2147483647 |     -123456 |    |
5629  2147483647 |  2147483647 |    |
5630  2147483647 | -2147483647 |    |
5631 -2147483647 |           0 |    |
5632 -2147483647 |      123456 |    |
5633 -2147483647 |     -123456 |    |
5634 -2147483647 |  2147483647 |    |
5635 -2147483647 | -2147483647 |    |
5636(25 rows)
5637
5638-- lateral reference in a PlaceHolderVar evaluated at join level
5639explain (verbose, costs off)
5640select * from
5641  int8_tbl a left join lateral
5642  (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from
5643   int8_tbl b cross join int8_tbl c) ss
5644  on a.q2 = ss.bq1;
5645                         QUERY PLAN
5646-------------------------------------------------------------
5647 Nested Loop Left Join
5648   Output: a.q1, a.q2, b.q1, c.q1, (LEAST(a.q1, b.q1, c.q1))
5649   ->  Seq Scan on public.int8_tbl a
5650         Output: a.q1, a.q2
5651   ->  Nested Loop
5652         Output: b.q1, c.q1, LEAST(a.q1, b.q1, c.q1)
5653         ->  Seq Scan on public.int8_tbl b
5654               Output: b.q1, b.q2
5655               Filter: (a.q2 = b.q1)
5656         ->  Seq Scan on public.int8_tbl c
5657               Output: c.q1, c.q2
5658(11 rows)
5659
5660select * from
5661  int8_tbl a left join lateral
5662  (select b.q1 as bq1, c.q1 as cq1, least(a.q1,b.q1,c.q1) from
5663   int8_tbl b cross join int8_tbl c) ss
5664  on a.q2 = ss.bq1;
5665        q1        |        q2         |       bq1        |       cq1        |      least
5666------------------+-------------------+------------------+------------------+------------------
5667              123 |               456 |                  |                  |
5668              123 |  4567890123456789 | 4567890123456789 |              123 |              123
5669              123 |  4567890123456789 | 4567890123456789 |              123 |              123
5670              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5671              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5672              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5673              123 |  4567890123456789 | 4567890123456789 |              123 |              123
5674              123 |  4567890123456789 | 4567890123456789 |              123 |              123
5675              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5676              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5677              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5678              123 |  4567890123456789 | 4567890123456789 |              123 |              123
5679              123 |  4567890123456789 | 4567890123456789 |              123 |              123
5680              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5681              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5682              123 |  4567890123456789 | 4567890123456789 | 4567890123456789 |              123
5683 4567890123456789 |               123 |              123 |              123 |              123
5684 4567890123456789 |               123 |              123 |              123 |              123
5685 4567890123456789 |               123 |              123 | 4567890123456789 |              123
5686 4567890123456789 |               123 |              123 | 4567890123456789 |              123
5687 4567890123456789 |               123 |              123 | 4567890123456789 |              123
5688 4567890123456789 |               123 |              123 |              123 |              123
5689 4567890123456789 |               123 |              123 |              123 |              123
5690 4567890123456789 |               123 |              123 | 4567890123456789 |              123
5691 4567890123456789 |               123 |              123 | 4567890123456789 |              123
5692 4567890123456789 |               123 |              123 | 4567890123456789 |              123
5693 4567890123456789 |  4567890123456789 | 4567890123456789 |              123 |              123
5694 4567890123456789 |  4567890123456789 | 4567890123456789 |              123 |              123
5695 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5696 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5697 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5698 4567890123456789 |  4567890123456789 | 4567890123456789 |              123 |              123
5699 4567890123456789 |  4567890123456789 | 4567890123456789 |              123 |              123
5700 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5701 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5702 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5703 4567890123456789 |  4567890123456789 | 4567890123456789 |              123 |              123
5704 4567890123456789 |  4567890123456789 | 4567890123456789 |              123 |              123
5705 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5706 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5707 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789 | 4567890123456789
5708 4567890123456789 | -4567890123456789 |                  |                  |
5709(42 rows)
5710
5711-- case requiring nested PlaceHolderVars
5712explain (verbose, costs off)
5713select * from
5714  int8_tbl c left join (
5715    int8_tbl a left join (select q1, coalesce(q2,42) as x from int8_tbl b) ss1
5716      on a.q2 = ss1.q1
5717    cross join
5718    lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2
5719  ) on c.q2 = ss2.q1,
5720  lateral (select ss2.y offset 0) ss3;
5721                                                                                     QUERY PLAN
5722------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5723 Nested Loop
5724   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)))
5725   ->  Hash Right Join
5726         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))
5727         Hash Cond: (d.q1 = c.q2)
5728         ->  Nested Loop
5729               Output: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
5730               ->  Hash Left Join
5731                     Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint))
5732                     Hash Cond: (a.q2 = b.q1)
5733                     ->  Seq Scan on public.int8_tbl a
5734                           Output: a.q1, a.q2
5735                     ->  Hash
5736                           Output: b.q1, (COALESCE(b.q2, '42'::bigint))
5737                           ->  Seq Scan on public.int8_tbl b
5738                                 Output: b.q1, COALESCE(b.q2, '42'::bigint)
5739               ->  Seq Scan on public.int8_tbl d
5740                     Output: d.q1, COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)
5741         ->  Hash
5742               Output: c.q1, c.q2
5743               ->  Seq Scan on public.int8_tbl c
5744                     Output: c.q1, c.q2
5745   ->  Result
5746         Output: (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
5747(24 rows)
5748
5749-- case that breaks the old ph_may_need optimization
5750explain (verbose, costs off)
5751select c.*,a.*,ss1.q1,ss2.q1,ss3.* from
5752  int8_tbl c left join (
5753    int8_tbl a left join
5754      (select q1, coalesce(q2,f1) as x from int8_tbl b, int4_tbl b2
5755       where q1 < f1) ss1
5756      on a.q2 = ss1.q1
5757    cross join
5758    lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2
5759  ) on c.q2 = ss2.q1,
5760  lateral (select * from int4_tbl i where ss2.y > f1) ss3;
5761                                               QUERY PLAN
5762---------------------------------------------------------------------------------------------------------
5763 Nested Loop
5764   Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, i.f1
5765   Join Filter: ((COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)) > i.f1)
5766   ->  Hash Right Join
5767         Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2))
5768         Hash Cond: (d.q1 = c.q2)
5769         ->  Nested Loop
5770               Output: a.q1, a.q2, b.q1, d.q1, (COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2))
5771               ->  Hash Right Join
5772                     Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, (b2.f1)::bigint))
5773                     Hash Cond: (b.q1 = a.q2)
5774                     ->  Nested Loop
5775                           Output: b.q1, COALESCE(b.q2, (b2.f1)::bigint)
5776                           Join Filter: (b.q1 < b2.f1)
5777                           ->  Seq Scan on public.int8_tbl b
5778                                 Output: b.q1, b.q2
5779                           ->  Materialize
5780                                 Output: b2.f1
5781                                 ->  Seq Scan on public.int4_tbl b2
5782                                       Output: b2.f1
5783                     ->  Hash
5784                           Output: a.q1, a.q2
5785                           ->  Seq Scan on public.int8_tbl a
5786                                 Output: a.q1, a.q2
5787               ->  Seq Scan on public.int8_tbl d
5788                     Output: d.q1, COALESCE((COALESCE(b.q2, (b2.f1)::bigint)), d.q2)
5789         ->  Hash
5790               Output: c.q1, c.q2
5791               ->  Seq Scan on public.int8_tbl c
5792                     Output: c.q1, c.q2
5793   ->  Materialize
5794         Output: i.f1
5795         ->  Seq Scan on public.int4_tbl i
5796               Output: i.f1
5797(34 rows)
5798
5799-- check processing of postponed quals (bug #9041)
5800explain (verbose, costs off)
5801select * from
5802  (select 1 as x offset 0) x cross join (select 2 as y offset 0) y
5803  left join lateral (
5804    select * from (select 3 as z offset 0) z where z.z = x.x
5805  ) zz on zz.z = y.y;
5806                  QUERY PLAN
5807----------------------------------------------
5808 Nested Loop Left Join
5809   Output: (1), (2), (3)
5810   Join Filter: (((3) = (1)) AND ((3) = (2)))
5811   ->  Nested Loop
5812         Output: (1), (2)
5813         ->  Result
5814               Output: 1
5815         ->  Result
5816               Output: 2
5817   ->  Result
5818         Output: 3
5819(11 rows)
5820
5821-- check dummy rels with lateral references (bug #15694)
5822explain (verbose, costs off)
5823select * from int8_tbl i8 left join lateral
5824  (select *, i8.q2 from int4_tbl where false) ss on true;
5825              QUERY PLAN
5826--------------------------------------
5827 Nested Loop Left Join
5828   Output: i8.q1, i8.q2, f1, (i8.q2)
5829   ->  Seq Scan on public.int8_tbl i8
5830         Output: i8.q1, i8.q2
5831   ->  Result
5832         Output: f1, i8.q2
5833         One-Time Filter: false
5834(7 rows)
5835
5836explain (verbose, costs off)
5837select * from int8_tbl i8 left join lateral
5838  (select *, i8.q2 from int4_tbl i1, int4_tbl i2 where false) ss on true;
5839               QUERY PLAN
5840-----------------------------------------
5841 Nested Loop Left Join
5842   Output: i8.q1, i8.q2, f1, f1, (i8.q2)
5843   ->  Seq Scan on public.int8_tbl i8
5844         Output: i8.q1, i8.q2
5845   ->  Result
5846         Output: f1, f1, i8.q2
5847         One-Time Filter: false
5848(7 rows)
5849
5850-- check handling of nested appendrels inside LATERAL
5851select * from
5852  ((select 2 as v) union all (select 3 as v)) as q1
5853  cross join lateral
5854  ((select * from
5855      ((select 4 as v) union all (select 5 as v)) as q3)
5856   union all
5857   (select q1.v)
5858  ) as q2;
5859 v | v
5860---+---
5861 2 | 4
5862 2 | 5
5863 2 | 2
5864 3 | 4
5865 3 | 5
5866 3 | 3
5867(6 rows)
5868
5869-- check we don't try to do a unique-ified semijoin with LATERAL
5870explain (verbose, costs off)
5871select * from
5872  (values (0,9998), (1,1000)) v(id,x),
5873  lateral (select f1 from int4_tbl
5874           where f1 = any (select unique1 from tenk1
5875                           where unique2 = v.x offset 0)) ss;
5876                              QUERY PLAN
5877----------------------------------------------------------------------
5878 Nested Loop
5879   Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1
5880   ->  Values Scan on "*VALUES*"
5881         Output: "*VALUES*".column1, "*VALUES*".column2
5882   ->  Nested Loop Semi Join
5883         Output: int4_tbl.f1
5884         Join Filter: (int4_tbl.f1 = tenk1.unique1)
5885         ->  Seq Scan on public.int4_tbl
5886               Output: int4_tbl.f1
5887         ->  Materialize
5888               Output: tenk1.unique1
5889               ->  Index Scan using tenk1_unique2 on public.tenk1
5890                     Output: tenk1.unique1
5891                     Index Cond: (tenk1.unique2 = "*VALUES*".column2)
5892(14 rows)
5893
5894select * from
5895  (values (0,9998), (1,1000)) v(id,x),
5896  lateral (select f1 from int4_tbl
5897           where f1 = any (select unique1 from tenk1
5898                           where unique2 = v.x offset 0)) ss;
5899 id |  x   | f1
5900----+------+----
5901  0 | 9998 |  0
5902(1 row)
5903
5904-- check proper extParam/allParam handling (this isn't exactly a LATERAL issue,
5905-- but we can make the test case much more compact with LATERAL)
5906explain (verbose, costs off)
5907select * from (values (0), (1)) v(id),
5908lateral (select * from int8_tbl t1,
5909         lateral (select * from
5910                    (select * from int8_tbl t2
5911                     where q1 = any (select q2 from int8_tbl t3
5912                                     where q2 = (select greatest(t1.q1,t2.q2))
5913                                       and (select v.id=0)) offset 0) ss2) ss
5914         where t1.q1 = ss.q2) ss0;
5915                           QUERY PLAN
5916-----------------------------------------------------------------
5917 Nested Loop
5918   Output: "*VALUES*".column1, t1.q1, t1.q2, ss2.q1, ss2.q2
5919   ->  Seq Scan on public.int8_tbl t1
5920         Output: t1.q1, t1.q2
5921   ->  Nested Loop
5922         Output: "*VALUES*".column1, ss2.q1, ss2.q2
5923         ->  Values Scan on "*VALUES*"
5924               Output: "*VALUES*".column1
5925         ->  Subquery Scan on ss2
5926               Output: ss2.q1, ss2.q2
5927               Filter: (t1.q1 = ss2.q2)
5928               ->  Seq Scan on public.int8_tbl t2
5929                     Output: t2.q1, t2.q2
5930                     Filter: (SubPlan 3)
5931                     SubPlan 3
5932                       ->  Result
5933                             Output: t3.q2
5934                             One-Time Filter: $4
5935                             InitPlan 1 (returns $2)
5936                               ->  Result
5937                                     Output: GREATEST($0, t2.q2)
5938                             InitPlan 2 (returns $4)
5939                               ->  Result
5940                                     Output: ($3 = 0)
5941                             ->  Seq Scan on public.int8_tbl t3
5942                                   Output: t3.q1, t3.q2
5943                                   Filter: (t3.q2 = $2)
5944(27 rows)
5945
5946select * from (values (0), (1)) v(id),
5947lateral (select * from int8_tbl t1,
5948         lateral (select * from
5949                    (select * from int8_tbl t2
5950                     where q1 = any (select q2 from int8_tbl t3
5951                                     where q2 = (select greatest(t1.q1,t2.q2))
5952                                       and (select v.id=0)) offset 0) ss2) ss
5953         where t1.q1 = ss.q2) ss0;
5954 id |        q1        |        q2         |        q1        |        q2
5955----+------------------+-------------------+------------------+------------------
5956  0 | 4567890123456789 |               123 | 4567890123456789 | 4567890123456789
5957  0 | 4567890123456789 |  4567890123456789 | 4567890123456789 | 4567890123456789
5958  0 | 4567890123456789 | -4567890123456789 | 4567890123456789 | 4567890123456789
5959(3 rows)
5960
5961-- test some error cases where LATERAL should have been used but wasn't
5962select f1,g from int4_tbl a, (select f1 as g) ss;
5963ERROR:  column "f1" does not exist
5964LINE 1: select f1,g from int4_tbl a, (select f1 as g) ss;
5965                                             ^
5966HINT:  There is a column named "f1" in table "a", but it cannot be referenced from this part of the query.
5967select f1,g from int4_tbl a, (select a.f1 as g) ss;
5968ERROR:  invalid reference to FROM-clause entry for table "a"
5969LINE 1: select f1,g from int4_tbl a, (select a.f1 as g) ss;
5970                                             ^
5971HINT:  There is an entry for table "a", but it cannot be referenced from this part of the query.
5972select f1,g from int4_tbl a cross join (select f1 as g) ss;
5973ERROR:  column "f1" does not exist
5974LINE 1: select f1,g from int4_tbl a cross join (select f1 as g) ss;
5975                                                       ^
5976HINT:  There is a column named "f1" in table "a", but it cannot be referenced from this part of the query.
5977select f1,g from int4_tbl a cross join (select a.f1 as g) ss;
5978ERROR:  invalid reference to FROM-clause entry for table "a"
5979LINE 1: select f1,g from int4_tbl a cross join (select a.f1 as g) ss...
5980                                                       ^
5981HINT:  There is an entry for table "a", but it cannot be referenced from this part of the query.
5982-- SQL:2008 says the left table is in scope but illegal to access here
5983select f1,g from int4_tbl a right join lateral generate_series(0, a.f1) g on true;
5984ERROR:  invalid reference to FROM-clause entry for table "a"
5985LINE 1: ... int4_tbl a right join lateral generate_series(0, a.f1) g on...
5986                                                             ^
5987DETAIL:  The combining JOIN type must be INNER or LEFT for a LATERAL reference.
5988select f1,g from int4_tbl a full join lateral generate_series(0, a.f1) g on true;
5989ERROR:  invalid reference to FROM-clause entry for table "a"
5990LINE 1: ...m int4_tbl a full join lateral generate_series(0, a.f1) g on...
5991                                                             ^
5992DETAIL:  The combining JOIN type must be INNER or LEFT for a LATERAL reference.
5993-- check we complain about ambiguous table references
5994select * from
5995  int8_tbl x cross join (int4_tbl x cross join lateral (select x.f1) ss);
5996ERROR:  table reference "x" is ambiguous
5997LINE 2: ...cross join (int4_tbl x cross join lateral (select x.f1) ss);
5998                                                             ^
5999-- LATERAL can be used to put an aggregate into the FROM clause of its query
6000select 1 from tenk1 a, lateral (select max(a.unique1) from int4_tbl b) ss;
6001ERROR:  aggregate functions are not allowed in FROM clause of their own query level
6002LINE 1: select 1 from tenk1 a, lateral (select max(a.unique1) from i...
6003                                               ^
6004-- check behavior of LATERAL in UPDATE/DELETE
6005create temp table xx1 as select f1 as x1, -f1 as x2 from int4_tbl;
6006-- error, can't do this:
6007update xx1 set x2 = f1 from (select * from int4_tbl where f1 = x1) ss;
6008ERROR:  column "x1" does not exist
6009LINE 1: ... set x2 = f1 from (select * from int4_tbl where f1 = x1) ss;
6010                                                                ^
6011HINT:  There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query.
6012update xx1 set x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss;
6013ERROR:  invalid reference to FROM-clause entry for table "xx1"
6014LINE 1: ...t x2 = f1 from (select * from int4_tbl where f1 = xx1.x1) ss...
6015                                                             ^
6016HINT:  There is an entry for table "xx1", but it cannot be referenced from this part of the query.
6017-- can't do it even with LATERAL:
6018update xx1 set x2 = f1 from lateral (select * from int4_tbl where f1 = x1) ss;
6019ERROR:  invalid reference to FROM-clause entry for table "xx1"
6020LINE 1: ...= f1 from lateral (select * from int4_tbl where f1 = x1) ss;
6021                                                                ^
6022HINT:  There is an entry for table "xx1", but it cannot be referenced from this part of the query.
6023-- we might in future allow something like this, but for now it's an error:
6024update xx1 set x2 = f1 from xx1, lateral (select * from int4_tbl where f1 = x1) ss;
6025ERROR:  table name "xx1" specified more than once
6026-- also errors:
6027delete from xx1 using (select * from int4_tbl where f1 = x1) ss;
6028ERROR:  column "x1" does not exist
6029LINE 1: ...te from xx1 using (select * from int4_tbl where f1 = x1) ss;
6030                                                                ^
6031HINT:  There is a column named "x1" in table "xx1", but it cannot be referenced from this part of the query.
6032delete from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss;
6033ERROR:  invalid reference to FROM-clause entry for table "xx1"
6034LINE 1: ...from xx1 using (select * from int4_tbl where f1 = xx1.x1) ss...
6035                                                             ^
6036HINT:  There is an entry for table "xx1", but it cannot be referenced from this part of the query.
6037delete from xx1 using lateral (select * from int4_tbl where f1 = x1) ss;
6038ERROR:  invalid reference to FROM-clause entry for table "xx1"
6039LINE 1: ...xx1 using lateral (select * from int4_tbl where f1 = x1) ss;
6040                                                                ^
6041HINT:  There is an entry for table "xx1", but it cannot be referenced from this part of the query.
6042--
6043-- test LATERAL reference propagation down a multi-level inheritance hierarchy
6044-- produced for a multi-level partitioned table hierarchy.
6045--
6046create table join_pt1 (a int, b int, c varchar) partition by range(a);
6047create table join_pt1p1 partition of join_pt1 for values from (0) to (100) partition by range(b);
6048create table join_pt1p2 partition of join_pt1 for values from (100) to (200);
6049create table join_pt1p1p1 partition of join_pt1p1 for values from (0) to (100);
6050insert into join_pt1 values (1, 1, 'x'), (101, 101, 'y');
6051create table join_ut1 (a int, b int, c varchar);
6052insert into join_ut1 values (101, 101, 'y'), (2, 2, 'z');
6053explain (verbose, costs off)
6054select t1.b, ss.phv from join_ut1 t1 left join lateral
6055              (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv
6056					  from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss
6057              on t1.a = ss.t2a order by t1.a;
6058                             QUERY PLAN
6059--------------------------------------------------------------------
6060 Sort
6061   Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a
6062   Sort Key: t1.a
6063   ->  Nested Loop Left Join
6064         Output: t1.b, (LEAST(t1.a, t2.a, t3.a)), t1.a
6065         ->  Seq Scan on public.join_ut1 t1
6066               Output: t1.a, t1.b, t1.c
6067         ->  Hash Join
6068               Output: t2.a, LEAST(t1.a, t2.a, t3.a)
6069               Hash Cond: (t3.b = t2.a)
6070               ->  Seq Scan on public.join_ut1 t3
6071                     Output: t3.a, t3.b, t3.c
6072               ->  Hash
6073                     Output: t2.a
6074                     ->  Append
6075                           ->  Seq Scan on public.join_pt1p1p1 t2_1
6076                                 Output: t2_1.a
6077                                 Filter: (t1.a = t2_1.a)
6078                           ->  Seq Scan on public.join_pt1p2 t2_2
6079                                 Output: t2_2.a
6080                                 Filter: (t1.a = t2_2.a)
6081(21 rows)
6082
6083select t1.b, ss.phv from join_ut1 t1 left join lateral
6084              (select t2.a as t2a, t3.a t3a, least(t1.a, t2.a, t3.a) phv
6085					  from join_pt1 t2 join join_ut1 t3 on t2.a = t3.b) ss
6086              on t1.a = ss.t2a order by t1.a;
6087  b  | phv
6088-----+-----
6089   2 |
6090 101 | 101
6091(2 rows)
6092
6093drop table join_pt1;
6094drop table join_ut1;
6095--
6096-- test estimation behavior with multi-column foreign key and constant qual
6097--
6098begin;
6099create table fkest (x integer, x10 integer, x10b integer, x100 integer);
6100insert into fkest select x, x/10, x/10, x/100 from generate_series(1,1000) x;
6101create unique index on fkest(x, x10, x100);
6102analyze fkest;
6103explain (costs off)
6104select * from fkest f1
6105  join fkest f2 on (f1.x = f2.x and f1.x10 = f2.x10b and f1.x100 = f2.x100)
6106  join fkest f3 on f1.x = f3.x
6107  where f1.x100 = 2;
6108                        QUERY PLAN
6109-----------------------------------------------------------
6110 Nested Loop
6111   ->  Hash Join
6112         Hash Cond: ((f2.x = f1.x) AND (f2.x10b = f1.x10))
6113         ->  Seq Scan on fkest f2
6114               Filter: (x100 = 2)
6115         ->  Hash
6116               ->  Seq Scan on fkest f1
6117                     Filter: (x100 = 2)
6118   ->  Index Scan using fkest_x_x10_x100_idx on fkest f3
6119         Index Cond: (x = f1.x)
6120(10 rows)
6121
6122alter table fkest add constraint fk
6123  foreign key (x, x10b, x100) references fkest (x, x10, x100);
6124explain (costs off)
6125select * from fkest f1
6126  join fkest f2 on (f1.x = f2.x and f1.x10 = f2.x10b and f1.x100 = f2.x100)
6127  join fkest f3 on f1.x = f3.x
6128  where f1.x100 = 2;
6129                     QUERY PLAN
6130-----------------------------------------------------
6131 Hash Join
6132   Hash Cond: ((f2.x = f1.x) AND (f2.x10b = f1.x10))
6133   ->  Hash Join
6134         Hash Cond: (f3.x = f2.x)
6135         ->  Seq Scan on fkest f3
6136         ->  Hash
6137               ->  Seq Scan on fkest f2
6138                     Filter: (x100 = 2)
6139   ->  Hash
6140         ->  Seq Scan on fkest f1
6141               Filter: (x100 = 2)
6142(11 rows)
6143
6144rollback;
6145--
6146-- test that foreign key join estimation performs sanely for outer joins
6147--
6148begin;
6149create table fkest (a int, b int, c int unique, primary key(a,b));
6150create table fkest1 (a int, b int, primary key(a,b));
6151insert into fkest select x/10, x%10, x from generate_series(1,1000) x;
6152insert into fkest1 select x/10, x%10 from generate_series(1,1000) x;
6153alter table fkest1
6154  add constraint fkest1_a_b_fkey foreign key (a,b) references fkest;
6155analyze fkest;
6156analyze fkest1;
6157explain (costs off)
6158select *
6159from fkest f
6160  left join fkest1 f1 on f.a = f1.a and f.b = f1.b
6161  left join fkest1 f2 on f.a = f2.a and f.b = f2.b
6162  left join fkest1 f3 on f.a = f3.a and f.b = f3.b
6163where f.c = 1;
6164                            QUERY PLAN
6165------------------------------------------------------------------
6166 Nested Loop Left Join
6167   ->  Nested Loop Left Join
6168         ->  Nested Loop Left Join
6169               ->  Index Scan using fkest_c_key on fkest f
6170                     Index Cond: (c = 1)
6171               ->  Index Only Scan using fkest1_pkey on fkest1 f1
6172                     Index Cond: ((a = f.a) AND (b = f.b))
6173         ->  Index Only Scan using fkest1_pkey on fkest1 f2
6174               Index Cond: ((a = f.a) AND (b = f.b))
6175   ->  Index Only Scan using fkest1_pkey on fkest1 f3
6176         Index Cond: ((a = f.a) AND (b = f.b))
6177(11 rows)
6178
6179rollback;
6180--
6181-- test planner's ability to mark joins as unique
6182--
6183create table j1 (id int primary key);
6184create table j2 (id int primary key);
6185create table j3 (id int);
6186insert into j1 values(1),(2),(3);
6187insert into j2 values(1),(2),(3);
6188insert into j3 values(1),(1);
6189analyze j1;
6190analyze j2;
6191analyze j3;
6192-- ensure join is properly marked as unique
6193explain (verbose, costs off)
6194select * from j1 inner join j2 on j1.id = j2.id;
6195            QUERY PLAN
6196-----------------------------------
6197 Hash Join
6198   Output: j1.id, j2.id
6199   Inner Unique: true
6200   Hash Cond: (j1.id = j2.id)
6201   ->  Seq Scan on public.j1
6202         Output: j1.id
6203   ->  Hash
6204         Output: j2.id
6205         ->  Seq Scan on public.j2
6206               Output: j2.id
6207(10 rows)
6208
6209-- ensure join is not unique when not an equi-join
6210explain (verbose, costs off)
6211select * from j1 inner join j2 on j1.id > j2.id;
6212            QUERY PLAN
6213-----------------------------------
6214 Nested Loop
6215   Output: j1.id, j2.id
6216   Join Filter: (j1.id > j2.id)
6217   ->  Seq Scan on public.j1
6218         Output: j1.id
6219   ->  Materialize
6220         Output: j2.id
6221         ->  Seq Scan on public.j2
6222               Output: j2.id
6223(9 rows)
6224
6225-- ensure non-unique rel is not chosen as inner
6226explain (verbose, costs off)
6227select * from j1 inner join j3 on j1.id = j3.id;
6228            QUERY PLAN
6229-----------------------------------
6230 Hash Join
6231   Output: j1.id, j3.id
6232   Inner Unique: true
6233   Hash Cond: (j3.id = j1.id)
6234   ->  Seq Scan on public.j3
6235         Output: j3.id
6236   ->  Hash
6237         Output: j1.id
6238         ->  Seq Scan on public.j1
6239               Output: j1.id
6240(10 rows)
6241
6242-- ensure left join is marked as unique
6243explain (verbose, costs off)
6244select * from j1 left join j2 on j1.id = j2.id;
6245            QUERY PLAN
6246-----------------------------------
6247 Hash Left Join
6248   Output: j1.id, j2.id
6249   Inner Unique: true
6250   Hash Cond: (j1.id = j2.id)
6251   ->  Seq Scan on public.j1
6252         Output: j1.id
6253   ->  Hash
6254         Output: j2.id
6255         ->  Seq Scan on public.j2
6256               Output: j2.id
6257(10 rows)
6258
6259-- ensure right join is marked as unique
6260explain (verbose, costs off)
6261select * from j1 right join j2 on j1.id = j2.id;
6262            QUERY PLAN
6263-----------------------------------
6264 Hash Left Join
6265   Output: j1.id, j2.id
6266   Inner Unique: true
6267   Hash Cond: (j2.id = j1.id)
6268   ->  Seq Scan on public.j2
6269         Output: j2.id
6270   ->  Hash
6271         Output: j1.id
6272         ->  Seq Scan on public.j1
6273               Output: j1.id
6274(10 rows)
6275
6276-- ensure full join is marked as unique
6277explain (verbose, costs off)
6278select * from j1 full join j2 on j1.id = j2.id;
6279            QUERY PLAN
6280-----------------------------------
6281 Hash Full Join
6282   Output: j1.id, j2.id
6283   Inner Unique: true
6284   Hash Cond: (j1.id = j2.id)
6285   ->  Seq Scan on public.j1
6286         Output: j1.id
6287   ->  Hash
6288         Output: j2.id
6289         ->  Seq Scan on public.j2
6290               Output: j2.id
6291(10 rows)
6292
6293-- a clauseless (cross) join can't be unique
6294explain (verbose, costs off)
6295select * from j1 cross join j2;
6296            QUERY PLAN
6297-----------------------------------
6298 Nested Loop
6299   Output: j1.id, j2.id
6300   ->  Seq Scan on public.j1
6301         Output: j1.id
6302   ->  Materialize
6303         Output: j2.id
6304         ->  Seq Scan on public.j2
6305               Output: j2.id
6306(8 rows)
6307
6308-- ensure a natural join is marked as unique
6309explain (verbose, costs off)
6310select * from j1 natural join j2;
6311            QUERY PLAN
6312-----------------------------------
6313 Hash Join
6314   Output: j1.id
6315   Inner Unique: true
6316   Hash Cond: (j1.id = j2.id)
6317   ->  Seq Scan on public.j1
6318         Output: j1.id
6319   ->  Hash
6320         Output: j2.id
6321         ->  Seq Scan on public.j2
6322               Output: j2.id
6323(10 rows)
6324
6325-- ensure a distinct clause allows the inner to become unique
6326explain (verbose, costs off)
6327select * from j1
6328inner join (select distinct id from j3) j3 on j1.id = j3.id;
6329               QUERY PLAN
6330-----------------------------------------
6331 Nested Loop
6332   Output: j1.id, j3.id
6333   Inner Unique: true
6334   Join Filter: (j1.id = j3.id)
6335   ->  Unique
6336         Output: j3.id
6337         ->  Sort
6338               Output: j3.id
6339               Sort Key: j3.id
6340               ->  Seq Scan on public.j3
6341                     Output: j3.id
6342   ->  Seq Scan on public.j1
6343         Output: j1.id
6344(13 rows)
6345
6346-- ensure group by clause allows the inner to become unique
6347explain (verbose, costs off)
6348select * from j1
6349inner join (select id from j3 group by id) j3 on j1.id = j3.id;
6350               QUERY PLAN
6351-----------------------------------------
6352 Nested Loop
6353   Output: j1.id, j3.id
6354   Inner Unique: true
6355   Join Filter: (j1.id = j3.id)
6356   ->  Group
6357         Output: j3.id
6358         Group Key: j3.id
6359         ->  Sort
6360               Output: j3.id
6361               Sort Key: j3.id
6362               ->  Seq Scan on public.j3
6363                     Output: j3.id
6364   ->  Seq Scan on public.j1
6365         Output: j1.id
6366(14 rows)
6367
6368drop table j1;
6369drop table j2;
6370drop table j3;
6371-- test more complex permutations of unique joins
6372create table j1 (id1 int, id2 int, primary key(id1,id2));
6373create table j2 (id1 int, id2 int, primary key(id1,id2));
6374create table j3 (id1 int, id2 int, primary key(id1,id2));
6375insert into j1 values(1,1),(1,2);
6376insert into j2 values(1,1);
6377insert into j3 values(1,1);
6378analyze j1;
6379analyze j2;
6380analyze j3;
6381-- ensure there's no unique join when not all columns which are part of the
6382-- unique index are seen in the join clause
6383explain (verbose, costs off)
6384select * from j1
6385inner join j2 on j1.id1 = j2.id1;
6386                QUERY PLAN
6387------------------------------------------
6388 Nested Loop
6389   Output: j1.id1, j1.id2, j2.id1, j2.id2
6390   Join Filter: (j1.id1 = j2.id1)
6391   ->  Seq Scan on public.j2
6392         Output: j2.id1, j2.id2
6393   ->  Seq Scan on public.j1
6394         Output: j1.id1, j1.id2
6395(7 rows)
6396
6397-- ensure proper unique detection with multiple join quals
6398explain (verbose, costs off)
6399select * from j1
6400inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2;
6401                        QUERY PLAN
6402----------------------------------------------------------
6403 Nested Loop
6404   Output: j1.id1, j1.id2, j2.id1, j2.id2
6405   Inner Unique: true
6406   Join Filter: ((j1.id1 = j2.id1) AND (j1.id2 = j2.id2))
6407   ->  Seq Scan on public.j2
6408         Output: j2.id1, j2.id2
6409   ->  Seq Scan on public.j1
6410         Output: j1.id1, j1.id2
6411(8 rows)
6412
6413-- ensure we don't detect the join to be unique when quals are not part of the
6414-- join condition
6415explain (verbose, costs off)
6416select * from j1
6417inner join j2 on j1.id1 = j2.id1 where j1.id2 = 1;
6418                QUERY PLAN
6419------------------------------------------
6420 Nested Loop
6421   Output: j1.id1, j1.id2, j2.id1, j2.id2
6422   Join Filter: (j1.id1 = j2.id1)
6423   ->  Seq Scan on public.j1
6424         Output: j1.id1, j1.id2
6425         Filter: (j1.id2 = 1)
6426   ->  Seq Scan on public.j2
6427         Output: j2.id1, j2.id2
6428(8 rows)
6429
6430-- as above, but for left joins.
6431explain (verbose, costs off)
6432select * from j1
6433left join j2 on j1.id1 = j2.id1 where j1.id2 = 1;
6434                QUERY PLAN
6435------------------------------------------
6436 Nested Loop Left Join
6437   Output: j1.id1, j1.id2, j2.id1, j2.id2
6438   Join Filter: (j1.id1 = j2.id1)
6439   ->  Seq Scan on public.j1
6440         Output: j1.id1, j1.id2
6441         Filter: (j1.id2 = 1)
6442   ->  Seq Scan on public.j2
6443         Output: j2.id1, j2.id2
6444(8 rows)
6445
6446-- validate logic in merge joins which skips mark and restore.
6447-- it should only do this if all quals which were used to detect the unique
6448-- are present as join quals, and not plain quals.
6449set enable_nestloop to 0;
6450set enable_hashjoin to 0;
6451set enable_sort to 0;
6452-- create indexes that will be preferred over the PKs to perform the join
6453create index j1_id1_idx on j1 (id1) where id1 % 1000 = 1;
6454create index j2_id1_idx on j2 (id1) where id1 % 1000 = 1;
6455-- need an additional row in j2, if we want j2_id1_idx to be preferred
6456insert into j2 values(1,2);
6457analyze j2;
6458explain (costs off) select * from j1
6459inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
6460where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1;
6461               QUERY PLAN
6462-----------------------------------------
6463 Merge Join
6464   Merge Cond: (j1.id1 = j2.id1)
6465   Join Filter: (j1.id2 = j2.id2)
6466   ->  Index Scan using j1_id1_idx on j1
6467   ->  Index Scan using j2_id1_idx on j2
6468(5 rows)
6469
6470select * from j1
6471inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
6472where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1;
6473 id1 | id2 | id1 | id2
6474-----+-----+-----+-----
6475   1 |   1 |   1 |   1
6476   1 |   2 |   1 |   2
6477(2 rows)
6478
6479-- Exercise array keys mark/restore B-Tree code
6480explain (costs off) select * from j1
6481inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
6482where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 = any (array[1]);
6483                     QUERY PLAN
6484----------------------------------------------------
6485 Merge Join
6486   Merge Cond: (j1.id1 = j2.id1)
6487   Join Filter: (j1.id2 = j2.id2)
6488   ->  Index Scan using j1_id1_idx on j1
6489   ->  Index Scan using j2_id1_idx on j2
6490         Index Cond: (id1 = ANY ('{1}'::integer[]))
6491(6 rows)
6492
6493select * from j1
6494inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
6495where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 = any (array[1]);
6496 id1 | id2 | id1 | id2
6497-----+-----+-----+-----
6498   1 |   1 |   1 |   1
6499   1 |   2 |   1 |   2
6500(2 rows)
6501
6502-- Exercise array keys "find extreme element" B-Tree code
6503explain (costs off) select * from j1
6504inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
6505where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 >= any (array[1,5]);
6506                      QUERY PLAN
6507-------------------------------------------------------
6508 Merge Join
6509   Merge Cond: (j1.id1 = j2.id1)
6510   Join Filter: (j1.id2 = j2.id2)
6511   ->  Index Scan using j1_id1_idx on j1
6512   ->  Index Only Scan using j2_pkey on j2
6513         Index Cond: (id1 >= ANY ('{1,5}'::integer[]))
6514         Filter: ((id1 % 1000) = 1)
6515(7 rows)
6516
6517select * from j1
6518inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
6519where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 >= any (array[1,5]);
6520 id1 | id2 | id1 | id2
6521-----+-----+-----+-----
6522   1 |   1 |   1 |   1
6523   1 |   2 |   1 |   2
6524(2 rows)
6525
6526reset enable_nestloop;
6527reset enable_hashjoin;
6528reset enable_sort;
6529drop table j1;
6530drop table j2;
6531drop table j3;
6532-- check that semijoin inner is not seen as unique for a portion of the outerrel
6533explain (verbose, costs off)
6534select t1.unique1, t2.hundred
6535from onek t1, tenk1 t2
6536where exists (select 1 from tenk1 t3
6537              where t3.thousand = t1.unique1 and t3.tenthous = t2.hundred)
6538      and t1.unique1 < 1;
6539                                   QUERY PLAN
6540---------------------------------------------------------------------------------
6541 Nested Loop
6542   Output: t1.unique1, t2.hundred
6543   ->  Hash Join
6544         Output: t1.unique1, t3.tenthous
6545         Hash Cond: (t3.thousand = t1.unique1)
6546         ->  HashAggregate
6547               Output: t3.thousand, t3.tenthous
6548               Group Key: t3.thousand, t3.tenthous
6549               ->  Index Only Scan using tenk1_thous_tenthous on public.tenk1 t3
6550                     Output: t3.thousand, t3.tenthous
6551         ->  Hash
6552               Output: t1.unique1
6553               ->  Index Only Scan using onek_unique1 on public.onek t1
6554                     Output: t1.unique1
6555                     Index Cond: (t1.unique1 < 1)
6556   ->  Index Only Scan using tenk1_hundred on public.tenk1 t2
6557         Output: t2.hundred
6558         Index Cond: (t2.hundred = t3.tenthous)
6559(18 rows)
6560
6561-- ... unless it actually is unique
6562create table j3 as select unique1, tenthous from onek;
6563vacuum analyze j3;
6564create unique index on j3(unique1, tenthous);
6565explain (verbose, costs off)
6566select t1.unique1, t2.hundred
6567from onek t1, tenk1 t2
6568where exists (select 1 from j3
6569              where j3.unique1 = t1.unique1 and j3.tenthous = t2.hundred)
6570      and t1.unique1 < 1;
6571                               QUERY PLAN
6572------------------------------------------------------------------------
6573 Nested Loop
6574   Output: t1.unique1, t2.hundred
6575   ->  Nested Loop
6576         Output: t1.unique1, j3.tenthous
6577         ->  Index Only Scan using onek_unique1 on public.onek t1
6578               Output: t1.unique1
6579               Index Cond: (t1.unique1 < 1)
6580         ->  Index Only Scan using j3_unique1_tenthous_idx on public.j3
6581               Output: j3.unique1, j3.tenthous
6582               Index Cond: (j3.unique1 = t1.unique1)
6583   ->  Index Only Scan using tenk1_hundred on public.tenk1 t2
6584         Output: t2.hundred
6585         Index Cond: (t2.hundred = j3.tenthous)
6586(13 rows)
6587
6588drop table j3;
6589