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