PostgreSQL Source Code: src/backend/rewrite/rewriteSearchCycle.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
15
16#include "catalog/pg_operator_d.h"
17#include "catalog/pg_type_d.h"
26#include "utils/fmgroids.h"
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
118{
121
123 rowexpr->row_typeid = RECORDOID;
126
127 foreach(lc, col_list)
128 {
130
131 for (int i = 0; i < list_length(cte->ctecolnames); i++)
132 {
134
135 if (strcmp(colname, colname2) == 0)
136 {
137 Var *var;
138
143 0);
145 rowexpr->colnames = lappend(rowexpr->colnames, makeString(colname));
146 break;
147 }
148 }
149 }
150
151 return rowexpr;
152}
153
154
155
156
157
160{
162
164 arr->array_typeid = RECORDARRAYOID;
165 arr->element_typeid = RECORDOID;
168
169 return (Expr *) arr;
170}
171
172
173
174
175
176
177
178
181{
184
186 arr->array_typeid = RECORDARRAYOID;
187 arr->element_typeid = RECORDOID;
190
191 fexpr = makeFuncExpr(F_ARRAY_CAT, RECORDARRAYOID,
193 arr),
195
196 return (Expr *) fexpr;
197}
198
199
200
201
204{
207 int rti1,
208 rti2;
210 *rte2,
211 *newrte;
213 *newq2;
214 Query *newsubquery;
221 RowExpr *cycle_col_rowexpr = NULL;
222 RowExpr *search_col_rowexpr = NULL;
224 int cte_rtindex = -1;
225
226 Assert(cte->search_clause || cte->cycle_clause);
227
229
231
232
233
234
235
239
242
245
248
249
250
251
252 if (cte->search_clause)
253 {
254 if (cte->search_clause->search_breadth_first)
255 search_seq_type = RECORDOID;
256 else
257 search_seq_type = RECORDARRAYOID;
258 }
259
260
261
262
263 if (cte->search_clause)
264 sqc_attno = list_length(cte->ctecolnames) + 1;
265 if (cte->cycle_clause)
266 {
267 cmc_attno = list_length(cte->ctecolnames) + 1;
268 cpa_attno = list_length(cte->ctecolnames) + 2;
269 if (cte->search_clause)
270 {
271 cmc_attno++;
272 cpa_attno++;
273 }
274 }
275
276
277
278
281 newq1->canSetTag = true;
282
285 newrte->alias = makeAlias("*TLOCRN*", cte->ctecolnames);
286 newrte->eref = newrte->alias;
289 newrte->subquery = newsubquery;
290 newrte->inFromCl = true;
292
296
297
298
299
300 for (int i = 0; i < list_length(cte->ctecolnames); i++)
301 {
302 Var *var;
303
308 0);
313 }
314
315 if (cte->search_clause)
316 {
318
319 search_col_rowexpr = make_path_rowexpr(cte, cte->search_clause->search_col_list);
320 if (cte->search_clause->search_breadth_first)
321 {
324 search_col_rowexpr->args);
325 search_col_rowexpr->colnames = lcons(makeString("*DEPTH*"), search_col_rowexpr->colnames);
326 texpr = (Expr *) search_col_rowexpr;
327 }
328 else
332 cte->search_clause->search_seq_column,
333 false);
335 }
336 if (cte->cycle_clause)
337 {
340 cte->cycle_clause->cycle_mark_column,
341 false);
343 cycle_col_rowexpr = make_path_rowexpr(cte, cte->cycle_clause->cycle_col_list);
346 cte->cycle_clause->cycle_path_column,
347 false);
349 }
350
352
353 if (cte->search_clause)
354 {
355 rte1->eref->colnames = lappend(rte1->eref->colnames, makeString(cte->search_clause->search_seq_column));
356 }
357 if (cte->cycle_clause)
358 {
359 rte1->eref->colnames = lappend(rte1->eref->colnames, makeString(cte->cycle_clause->cycle_mark_column));
360 rte1->eref->colnames = lappend(rte1->eref->colnames, makeString(cte->cycle_clause->cycle_path_column));
361 }
362
363
364
365
368 newq2->canSetTag = true;
369
373 if (cte->search_clause)
374 {
375 ewcl = lappend(ewcl, makeString(cte->search_clause->search_seq_column));
376 }
377 if (cte->cycle_clause)
378 {
379 ewcl = lappend(ewcl, makeString(cte->cycle_clause->cycle_mark_column));
380 ewcl = lappend(ewcl, makeString(cte->cycle_clause->cycle_path_column));
381 }
382 newrte->alias = makeAlias("*TROCRN*", ewcl);
383 newrte->eref = newrte->alias;
384
385
386
387
388
389
390
391
392
393
394
396 {
398
400 strcmp(cte->ctename, e->ctename) == 0 &&
401 e->ctelevelsup == 2)
402 {
403 cte_rtindex = rti;
404 break;
405 }
406 }
407 if (cte_rtindex <= 0)
409 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
410 errmsg("with a SEARCH or CYCLE clause, the recursive reference to WITH query \"%s\" must be at the top level of its right-hand SELECT",
412
415
416
417
418
419 if (cte->search_clause)
420 {
421 Var *var;
422
423
424 var = makeVar(cte_rtindex, sqc_attno,
428 cte->search_clause->search_seq_column,
429 false);
431 }
432 if (cte->cycle_clause)
433 {
434 Var *var;
435
436
437 var = makeVar(cte_rtindex, cmc_attno,
438 cte->cycle_clause->cycle_mark_type,
439 cte->cycle_clause->cycle_mark_typmod,
440 cte->cycle_clause->cycle_mark_collation, 0);
443 cte->cycle_clause->cycle_mark_column,
444 false);
446
447
448 var = makeVar(cte_rtindex, cpa_attno,
452 cte->cycle_clause->cycle_path_column,
453 false);
455 }
456
457 newrte->subquery = newsubquery;
458 newrte->inFromCl = true;
460
463
464 if (cte->cycle_clause)
465 {
467
468
469
470
471 expr = make_opclause(cte->cycle_clause->cycle_mark_neop, BOOLOID, false,
473 cte->cycle_clause->cycle_mark_type,
474 cte->cycle_clause->cycle_mark_typmod,
475 cte->cycle_clause->cycle_mark_collation, 0),
476 (Expr *) cte->cycle_clause->cycle_mark_value,
478 cte->cycle_clause->cycle_mark_collation);
479
481 }
482 else
484
485
486
487
488 for (int i = 0; i < list_length(cte->ctecolnames); i++)
489 {
490 Var *var;
491
496 0);
501 }
502
503 if (cte->search_clause)
504 {
506
507 if (cte->search_clause->search_breadth_first)
508 {
511
512
513
514
515
516 search_col_rowexpr = copyObject(search_col_rowexpr);
517
519 fs->arg = (Expr *) makeVar(1, sqc_attno, RECORDOID, -1, 0, 0);
521 fs->resulttype = INT8OID;
522 fs->resulttypmod = -1;
523
525
527
528 texpr = (Expr *) search_col_rowexpr;
529 }
530 else
531 {
532
533
534
536 }
539 cte->search_clause->search_seq_column,
540 false);
542 }
543
544 if (cte->cycle_clause)
545 {
549
550
551
552
553
556 saoe->opno = RECORD_EQ_OP;
557 saoe->useOr = true;
559 makeVar(1, cpa_attno, RECORDARRAYOID, -1, 0, 0));
560
563 caseexpr->casetype = cte->cycle_clause->cycle_mark_type;
564 caseexpr->casecollid = cte->cycle_clause->cycle_mark_collation;
567 casewhen->expr = (Expr *) saoe;
568 casewhen->result = (Expr *) cte->cycle_clause->cycle_mark_value;
570 caseexpr->defresult = (Expr *) cte->cycle_clause->cycle_mark_default;
571
574 cte->cycle_clause->cycle_mark_column,
575 false);
577
578
579
580
583 cte->cycle_clause->cycle_path_column,
584 false);
586 }
587
589
590 if (cte->search_clause)
591 {
592 rte2->eref->colnames = lappend(rte2->eref->colnames, makeString(cte->search_clause->search_seq_column));
593 }
594 if (cte->cycle_clause)
595 {
596 rte2->eref->colnames = lappend(rte2->eref->colnames, makeString(cte->cycle_clause->cycle_mark_column));
597 rte2->eref->colnames = lappend(rte2->eref->colnames, makeString(cte->cycle_clause->cycle_path_column));
598 }
599
600
601
602
603 if (cte->search_clause)
604 {
605 sos->colTypes = lappend_oid(sos->colTypes, search_seq_type);
606 sos->colTypmods = lappend_int(sos->colTypmods, -1);
608 if (!sos->all)
609 sos->groupClauses = lappend(sos->groupClauses,
611 }
612 if (cte->cycle_clause)
613 {
614 sos->colTypes = lappend_oid(sos->colTypes, cte->cycle_clause->cycle_mark_type);
615 sos->colTypmods = lappend_int(sos->colTypmods, cte->cycle_clause->cycle_mark_typmod);
616 sos->colCollations = lappend_oid(sos->colCollations, cte->cycle_clause->cycle_mark_collation);
617 if (!sos->all)
618 sos->groupClauses = lappend(sos->groupClauses,
620
621 sos->colTypes = lappend_oid(sos->colTypes, RECORDARRAYOID);
622 sos->colTypmods = lappend_int(sos->colTypmods, -1);
624 if (!sos->all)
625 sos->groupClauses = lappend(sos->groupClauses,
627 }
628
629
630
631
632 if (cte->search_clause)
633 {
638 cte->search_clause->search_seq_column,
639 false));
640 }
641 if (cte->cycle_clause)
642 {
645 cte->cycle_clause->cycle_mark_type,
646 cte->cycle_clause->cycle_mark_typmod,
647 cte->cycle_clause->cycle_mark_collation, 0),
649 cte->cycle_clause->cycle_mark_column,
650 false));
655 cte->cycle_clause->cycle_path_column,
656 false));
657 }
658
659
660
661
662 cte->ctecolnames = ewcl;
663 if (cte->search_clause)
664 {
665 cte->ctecoltypes = lappend_oid(cte->ctecoltypes, search_seq_type);
666 cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, -1);
668 }
669 if (cte->cycle_clause)
670 {
671 cte->ctecoltypes = lappend_oid(cte->ctecoltypes, cte->cycle_clause->cycle_mark_type);
672 cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, cte->cycle_clause->cycle_mark_typmod);
673 cte->ctecolcollations = lappend_oid(cte->ctecolcollations, cte->cycle_clause->cycle_mark_collation);
674
675 cte->ctecoltypes = lappend_oid(cte->ctecoltypes, RECORDARRAYOID);
676 cte->ctecoltypmods = lappend_int(cte->ctecoltypmods, -1);
678 }
679
680 return cte;
681}
#define InvalidAttrNumber
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Datum Int64GetDatum(int64 X)
Assert(PointerIsAligned(start, uint64))
List * lappend(List *list, void *datum)
List * lappend_int(List *list, int datum)
List * lappend_oid(List *list, Oid datum)
List * lcons(void *datum, List *list)
Alias * makeAlias(const char *aliasname, List *colnames)
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
FuncExpr * makeFuncExpr(Oid funcid, Oid rettype, List *args, Oid funccollid, Oid inputcollid, CoercionForm fformat)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
#define castNode(_type_, nodeptr)
SortGroupClause * makeSortGroupClauseForSetOp(Oid rescoltype, bool require_hash)
#define rt_fetch(rangetable_index, rangetable)
static int list_length(const List *l)
static Oid list_nth_oid(const List *list, int n)
static void * list_nth(const List *list, int n)
#define list_nth_node(type, list, n)
#define list_make2(x1, x2)
static int list_nth_int(const List *list, int n)
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
static RowExpr * make_path_rowexpr(const CommonTableExpr *cte, const List *col_list)
static Expr * make_path_initial_array(RowExpr *rowexpr)
static Expr * make_path_cat_expr(RowExpr *rowexpr, AttrNumber path_varattno)
CommonTableExpr * rewriteSearchAndCycle(CommonTableExpr *cte)
String * makeString(char *str)