Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/parser/analyze.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * analyze.c
4
 *    transform the raw parse tree into a query tree
5
 *
6
 * For optimizable statements, we are careful to obtain a suitable lock on
7
 * each referenced table, and other modules of the backend preserve or
8
 * re-obtain these locks before depending on the results.  It is therefore
9
 * okay to do significant semantic analysis of these statements.  For
10
 * utility commands, no locks are obtained here (and if they were, we could
11
 * not be sure we'd still have them at execution).  Hence the general rule
12
 * for utility commands is to just dump them into a Query node untransformed.
13
 * DECLARE CURSOR, EXPLAIN, and CREATE TABLE AS are exceptions because they
14
 * contain optimizable statements, which we should transform.
15
 *
16
 *
17
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
18
 * Portions Copyright (c) 1994, Regents of the University of California
19
 *
20
 *  src/backend/parser/analyze.c
21
 *
22
 *-------------------------------------------------------------------------
23
 */
24
25
#include "postgres.h"
26
27
#include "access/stratnum.h"
28
#include "access/sysattr.h"
29
#include "catalog/dependency.h"
30
#include "catalog/pg_am.h"
31
#include "catalog/pg_operator.h"
32
#include "catalog/pg_proc.h"
33
#include "catalog/pg_type.h"
34
#include "commands/defrem.h"
35
#include "miscadmin.h"
36
#include "nodes/makefuncs.h"
37
#include "nodes/nodeFuncs.h"
38
#include "nodes/queryjumble.h"
39
#include "optimizer/optimizer.h"
40
#include "parser/analyze.h"
41
#include "parser/parse_agg.h"
42
#include "parser/parse_clause.h"
43
#include "parser/parse_coerce.h"
44
#include "parser/parse_collate.h"
45
#include "parser/parse_cte.h"
46
#include "parser/parse_expr.h"
47
#include "parser/parse_func.h"
48
#include "parser/parse_merge.h"
49
#include "parser/parse_oper.h"
50
#include "parser/parse_param.h"
51
#include "parser/parse_relation.h"
52
#include "parser/parse_target.h"
53
#include "parser/parse_type.h"
54
#include "parser/parsetree.h"
55
#include "utils/backend_status.h"
56
#include "utils/builtins.h"
57
#include "utils/fmgroids.h"
58
#include "utils/guc.h"
59
#include "utils/lsyscache.h"
60
#include "utils/rangetypes.h"
61
#include "utils/rel.h"
62
#include "utils/syscache.h"
63
64
65
/* Passthrough data for transformPLAssignStmtTarget */
66
typedef struct SelectStmtPassthrough
67
{
68
  PLAssignStmt *stmt;     /* the assignment statement */
69
  Node     *target;     /* node representing the target variable */
70
  List     *indirection;  /* indirection yet to be applied to target */
71
} SelectStmtPassthrough;
72
73
/* Hook for plugins to get control at end of parse analysis */
74
post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
75
76
static Query *transformOptionalSelectInto(ParseState *pstate, Node *parseTree);
77
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
78
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
79
static OnConflictExpr *transformOnConflictClause(ParseState *pstate,
80
                         OnConflictClause *onConflictClause);
81
static ForPortionOfExpr *transformForPortionOfClause(ParseState *pstate,
82
                           int rtindex,
83
                           const ForPortionOfClause *forPortionOf,
84
                           const Node *whereClause,
85
                           bool isUpdate);
86
static int  count_rowexpr_columns(ParseState *pstate, Node *expr);
87
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt,
88
                  SelectStmtPassthrough *passthru);
89
static Query *transformValuesClause(ParseState *pstate, SelectStmt *stmt);
90
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
91
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
92
                     bool isTopLevel, List **targetlist);
93
static void determineRecursiveColTypes(ParseState *pstate,
94
                     Node *larg, List *nrtargetlist);
95
static Query *transformReturnStmt(ParseState *pstate, ReturnStmt *stmt);
96
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
97
static Query *transformPLAssignStmt(ParseState *pstate,
98
                  PLAssignStmt *stmt);
99
static List *transformPLAssignStmtTarget(ParseState *pstate, List *tlist,
100
                     SelectStmtPassthrough *passthru);
101
static Query *transformDeclareCursorStmt(ParseState *pstate,
102
                     DeclareCursorStmt *stmt);
103
static Query *transformExplainStmt(ParseState *pstate,
104
                   ExplainStmt *stmt);
105
static Query *transformCreateTableAsStmt(ParseState *pstate,
106
                     CreateTableAsStmt *stmt);
107
static Query *transformCallStmt(ParseState *pstate,
108
                CallStmt *stmt);
109
static void transformLockingClause(ParseState *pstate, Query *qry,
110
                   LockingClause *lc, bool pushedDown);
111
#ifdef DEBUG_NODE_TESTS_ENABLED
112
static bool test_raw_expression_coverage(Node *node, void *context);
113
#endif
114
115
116
/*
117
 * parse_analyze_fixedparams
118
 *    Analyze a raw parse tree and transform it to Query form.
119
 *
120
 * Optionally, information about $n parameter types can be supplied.
121
 * References to $n indexes not defined by paramTypes[] are disallowed.
122
 *
123
 * The result is a Query node.  Optimizable statements require considerable
124
 * transformation, while utility-type statements are simply hung off
125
 * a dummy CMD_UTILITY Query node.
126
 */
127
Query *
128
parse_analyze_fixedparams(RawStmt *parseTree, const char *sourceText,
129
              const Oid *paramTypes, int numParams,
130
              QueryEnvironment *queryEnv)
131
439
{
132
439
  ParseState *pstate = make_parsestate(NULL);
133
439
  Query    *query;
134
439
  JumbleState *jstate = NULL;
135
136
439
  Assert(sourceText != NULL); /* required as of 8.4 */
137
138
439
  pstate->p_sourcetext = sourceText;
139
140
439
  if (numParams > 0)
141
0
    setup_parse_fixed_parameters(pstate, paramTypes, numParams);
142
143
439
  pstate->p_queryEnv = queryEnv;
144
145
439
  query = transformTopLevelStmt(pstate, parseTree);
146
147
439
  if (IsQueryIdEnabled())
148
0
    jstate = JumbleQuery(query);
149
150
439
  if (post_parse_analyze_hook)
151
0
    (*post_parse_analyze_hook) (pstate, query, jstate);
152
153
439
  free_parsestate(pstate);
154
155
439
  pgstat_report_query_id(query->queryId, false);
156
157
439
  return query;
158
439
}
159
160
/*
161
 * parse_analyze_varparams
162
 *
163
 * This variant is used when it's okay to deduce information about $n
164
 * symbol datatypes from context.  The passed-in paramTypes[] array can
165
 * be modified or enlarged (via repalloc).
166
 */
167
Query *
168
parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
169
            Oid **paramTypes, int *numParams,
170
            QueryEnvironment *queryEnv)
171
0
{
172
0
  ParseState *pstate = make_parsestate(NULL);
173
0
  Query    *query;
174
0
  JumbleState *jstate = NULL;
175
176
0
  Assert(sourceText != NULL); /* required as of 8.4 */
177
178
0
  pstate->p_sourcetext = sourceText;
179
180
0
  setup_parse_variable_parameters(pstate, paramTypes, numParams);
181
182
0
  pstate->p_queryEnv = queryEnv;
183
184
0
  query = transformTopLevelStmt(pstate, parseTree);
185
186
  /* make sure all is well with parameter types */
187
0
  check_variable_parameters(pstate, query);
188
189
0
  if (IsQueryIdEnabled())
190
0
    jstate = JumbleQuery(query);
191
192
0
  if (post_parse_analyze_hook)
193
0
    (*post_parse_analyze_hook) (pstate, query, jstate);
194
195
0
  free_parsestate(pstate);
196
197
0
  pgstat_report_query_id(query->queryId, false);
198
199
0
  return query;
200
0
}
201
202
/*
203
 * parse_analyze_withcb
204
 *
205
 * This variant is used when the caller supplies their own parser callback to
206
 * resolve parameters and possibly other things.
207
 */
208
Query *
209
parse_analyze_withcb(RawStmt *parseTree, const char *sourceText,
210
           ParserSetupHook parserSetup,
211
           void *parserSetupArg,
212
           QueryEnvironment *queryEnv)
213
0
{
214
0
  ParseState *pstate = make_parsestate(NULL);
215
0
  Query    *query;
216
0
  JumbleState *jstate = NULL;
217
218
0
  Assert(sourceText != NULL); /* required as of 8.4 */
219
220
0
  pstate->p_sourcetext = sourceText;
221
0
  pstate->p_queryEnv = queryEnv;
222
0
  (*parserSetup) (pstate, parserSetupArg);
223
224
0
  query = transformTopLevelStmt(pstate, parseTree);
225
226
0
  if (IsQueryIdEnabled())
227
0
    jstate = JumbleQuery(query);
228
229
0
  if (post_parse_analyze_hook)
230
0
    (*post_parse_analyze_hook) (pstate, query, jstate);
231
232
0
  free_parsestate(pstate);
233
234
0
  pgstat_report_query_id(query->queryId, false);
235
236
0
  return query;
237
0
}
238
239
240
/*
241
 * parse_sub_analyze
242
 *    Entry point for recursively analyzing a sub-statement.
243
 */
244
Query *
245
parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
246
          CommonTableExpr *parentCTE,
247
          bool locked_from_parent,
248
          bool resolve_unknowns)
249
0
{
250
0
  ParseState *pstate = make_parsestate(parentParseState);
251
0
  Query    *query;
252
253
0
  pstate->p_parent_cte = parentCTE;
254
0
  pstate->p_locked_from_parent = locked_from_parent;
255
0
  pstate->p_resolve_unknowns = resolve_unknowns;
256
257
0
  query = transformStmt(pstate, parseTree);
258
259
0
  free_parsestate(pstate);
260
261
0
  return query;
262
0
}
263
264
/*
265
 * transformTopLevelStmt -
266
 *    transform a Parse tree into a Query tree.
267
 *
268
 * This function is just responsible for transferring statement location data
269
 * from the RawStmt into the finished Query.
270
 */
271
Query *
272
transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
273
439
{
274
439
  Query    *result;
275
276
  /* We're at top level, so allow SELECT INTO */
277
439
  result = transformOptionalSelectInto(pstate, parseTree->stmt);
278
279
439
  result->stmt_location = parseTree->stmt_location;
280
439
  result->stmt_len = parseTree->stmt_len;
281
282
439
  return result;
283
439
}
284
285
/*
286
 * transformOptionalSelectInto -
287
 *    If SELECT has INTO, convert it to CREATE TABLE AS.
288
 *
289
 * The only thing we do here that we don't do in transformStmt() is to
290
 * convert SELECT ... INTO into CREATE TABLE AS.  Since utility statements
291
 * aren't allowed within larger statements, this is only allowed at the top
292
 * of the parse tree, and so we only try it before entering the recursive
293
 * transformStmt() processing.
294
 */
295
static Query *
296
transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
297
439
{
298
439
  if (IsA(parseTree, SelectStmt))
299
0
  {
300
0
    SelectStmt *stmt = (SelectStmt *) parseTree;
301
302
    /* If it's a set-operation tree, drill down to leftmost SelectStmt */
303
0
    while (stmt && stmt->op != SETOP_NONE)
304
0
      stmt = stmt->larg;
305
0
    Assert(stmt && IsA(stmt, SelectStmt) && stmt->larg == NULL);
306
307
0
    if (stmt->intoClause)
308
0
    {
309
0
      CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
310
311
0
      ctas->query = parseTree;
312
0
      ctas->into = stmt->intoClause;
313
0
      ctas->objtype = OBJECT_TABLE;
314
0
      ctas->is_select_into = true;
315
316
      /*
317
       * Remove the intoClause from the SelectStmt.  This makes it safe
318
       * for transformSelectStmt to complain if it finds intoClause set
319
       * (implying that the INTO appeared in a disallowed place).
320
       */
321
0
      stmt->intoClause = NULL;
322
323
0
      parseTree = (Node *) ctas;
324
0
    }
325
0
  }
326
327
439
  return transformStmt(pstate, parseTree);
328
439
}
329
330
/*
331
 * transformStmt -
332
 *    recursively transform a Parse tree into a Query tree.
333
 */
334
Query *
335
transformStmt(ParseState *pstate, Node *parseTree)
336
439
{
337
439
  Query    *result;
338
339
#ifdef DEBUG_NODE_TESTS_ENABLED
340
341
  /*
342
   * We apply debug_raw_expression_coverage_test testing to basic DML
343
   * statements; we can't just run it on everything because
344
   * raw_expression_tree_walker() doesn't claim to handle utility
345
   * statements.
346
   */
347
  if (Debug_raw_expression_coverage_test)
348
  {
349
    switch (nodeTag(parseTree))
350
    {
351
      case T_SelectStmt:
352
      case T_InsertStmt:
353
      case T_UpdateStmt:
354
      case T_DeleteStmt:
355
      case T_MergeStmt:
356
        (void) test_raw_expression_coverage(parseTree, NULL);
357
        break;
358
      default:
359
        break;
360
    }
361
  }
362
#endif              /* DEBUG_NODE_TESTS_ENABLED */
363
364
  /*
365
   * Caution: when changing the set of statement types that have non-default
366
   * processing here, see also stmt_requires_parse_analysis() and
367
   * analyze_requires_snapshot().
368
   */
369
439
  switch (nodeTag(parseTree))
370
439
  {
371
      /*
372
       * Optimizable statements
373
       */
374
0
    case T_InsertStmt:
375
0
      result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
376
0
      break;
377
378
0
    case T_DeleteStmt:
379
0
      result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
380
0
      break;
381
382
0
    case T_UpdateStmt:
383
0
      result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
384
0
      break;
385
386
0
    case T_MergeStmt:
387
0
      result = transformMergeStmt(pstate, (MergeStmt *) parseTree);
388
0
      break;
389
390
0
    case T_SelectStmt:
391
0
      {
392
0
        SelectStmt *n = (SelectStmt *) parseTree;
393
394
0
        if (n->valuesLists)
395
0
          result = transformValuesClause(pstate, n);
396
0
        else if (n->op == SETOP_NONE)
397
0
          result = transformSelectStmt(pstate, n, NULL);
398
0
        else
399
0
          result = transformSetOperationStmt(pstate, n);
400
0
      }
401
0
      break;
402
403
0
    case T_ReturnStmt:
404
0
      result = transformReturnStmt(pstate, (ReturnStmt *) parseTree);
405
0
      break;
406
407
0
    case T_PLAssignStmt:
408
0
      result = transformPLAssignStmt(pstate,
409
0
                       (PLAssignStmt *) parseTree);
410
0
      break;
411
412
      /*
413
       * Special cases
414
       */
415
0
    case T_DeclareCursorStmt:
416
0
      result = transformDeclareCursorStmt(pstate,
417
0
                        (DeclareCursorStmt *) parseTree);
418
0
      break;
419
420
0
    case T_ExplainStmt:
421
0
      result = transformExplainStmt(pstate,
422
0
                      (ExplainStmt *) parseTree);
423
0
      break;
424
425
0
    case T_CreateTableAsStmt:
426
0
      result = transformCreateTableAsStmt(pstate,
427
0
                        (CreateTableAsStmt *) parseTree);
428
0
      break;
429
430
0
    case T_CallStmt:
431
0
      result = transformCallStmt(pstate,
432
0
                     (CallStmt *) parseTree);
433
0
      break;
434
435
439
    default:
436
437
      /*
438
       * other statements don't require any transformation; just return
439
       * the original parsetree with a Query node plastered on top.
440
       */
441
439
      result = makeNode(Query);
442
439
      result->commandType = CMD_UTILITY;
443
439
      result->utilityStmt = parseTree;
444
439
      break;
445
439
  }
446
447
  /* Mark as original query until we learn differently */
448
439
  result->querySource = QSRC_ORIGINAL;
449
439
  result->canSetTag = true;
450
451
439
  return result;
452
439
}
453
454
/*
455
 * stmt_requires_parse_analysis
456
 *    Returns true if parse analysis will do anything non-trivial
457
 *    with the given raw parse tree.
458
 *
459
 * Generally, this should return true for any statement type for which
460
 * transformStmt() does more than wrap a CMD_UTILITY Query around it.
461
 * When it returns false, the caller can assume that there is no situation
462
 * in which parse analysis of the raw statement could need to be re-done.
463
 *
464
 * Currently, since the rewriter and planner do nothing for CMD_UTILITY
465
 * Queries, a false result means that the entire parse analysis/rewrite/plan
466
 * pipeline will never need to be re-done.  If that ever changes, callers
467
 * will likely need adjustment.
468
 */
469
bool
470
stmt_requires_parse_analysis(RawStmt *parseTree)
471
0
{
472
0
  bool    result;
473
474
0
  switch (nodeTag(parseTree->stmt))
475
0
  {
476
      /*
477
       * Optimizable statements
478
       */
479
0
    case T_InsertStmt:
480
0
    case T_DeleteStmt:
481
0
    case T_UpdateStmt:
482
0
    case T_MergeStmt:
483
0
    case T_SelectStmt:
484
0
    case T_ReturnStmt:
485
0
    case T_PLAssignStmt:
486
0
      result = true;
487
0
      break;
488
489
      /*
490
       * Special cases
491
       */
492
0
    case T_DeclareCursorStmt:
493
0
    case T_ExplainStmt:
494
0
    case T_CreateTableAsStmt:
495
0
    case T_CallStmt:
496
0
      result = true;
497
0
      break;
498
499
0
    default:
500
      /* all other statements just get wrapped in a CMD_UTILITY Query */
501
0
      result = false;
502
0
      break;
503
0
  }
504
505
0
  return result;
506
0
}
507
508
/*
509
 * analyze_requires_snapshot
510
 *    Returns true if a snapshot must be set before doing parse analysis
511
 *    on the given raw parse tree.
512
 */
513
bool
514
analyze_requires_snapshot(RawStmt *parseTree)
515
0
{
516
  /*
517
   * Currently, this should return true in exactly the same cases that
518
   * stmt_requires_parse_analysis() does, so we just invoke that function
519
   * rather than duplicating it.  We keep the two entry points separate for
520
   * clarity of callers, since from the callers' standpoint these are
521
   * different conditions.
522
   *
523
   * While there may someday be a statement type for which transformStmt()
524
   * does something nontrivial and yet no snapshot is needed for that
525
   * processing, it seems likely that making such a choice would be fragile.
526
   * If you want to install an exception, document the reasoning for it in a
527
   * comment.
528
   */
529
0
  return stmt_requires_parse_analysis(parseTree);
530
0
}
531
532
/*
533
 * query_requires_rewrite_plan()
534
 *    Returns true if rewriting or planning is non-trivial for this Query.
535
 *
536
 * This is much like stmt_requires_parse_analysis(), but applies one step
537
 * further down the pipeline.
538
 *
539
 * We do not provide an equivalent of analyze_requires_snapshot(): callers
540
 * can assume that any rewriting or planning activity needs a snapshot.
541
 */
542
bool
543
query_requires_rewrite_plan(Query *query)
544
0
{
545
0
  bool    result;
546
547
0
  if (query->commandType != CMD_UTILITY)
548
0
  {
549
    /* All optimizable statements require rewriting/planning */
550
0
    result = true;
551
0
  }
552
0
  else
553
0
  {
554
    /* This list should match stmt_requires_parse_analysis() */
555
0
    switch (nodeTag(query->utilityStmt))
556
0
    {
557
0
      case T_DeclareCursorStmt:
558
0
      case T_ExplainStmt:
559
0
      case T_CreateTableAsStmt:
560
0
      case T_CallStmt:
561
0
        result = true;
562
0
        break;
563
0
      default:
564
0
        result = false;
565
0
        break;
566
0
    }
567
0
  }
568
0
  return result;
569
0
}
570
571
/*
572
 * transformDeleteStmt -
573
 *    transforms a Delete Statement
574
 */
575
static Query *
576
transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
577
0
{
578
0
  Query    *qry = makeNode(Query);
579
0
  ParseNamespaceItem *nsitem;
580
0
  Node     *qual;
581
582
0
  qry->commandType = CMD_DELETE;
583
584
  /* process the WITH clause independently of all else */
585
0
  if (stmt->withClause)
586
0
  {
587
0
    qry->hasRecursive = stmt->withClause->recursive;
588
0
    qry->cteList = transformWithClause(pstate, stmt->withClause);
589
0
    qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
590
0
  }
591
592
  /* set up range table with just the result rel */
593
0
  qry->resultRelation = setTargetTable(pstate, stmt->relation,
594
0
                     stmt->relation->inh,
595
0
                     true,
596
0
                     ACL_DELETE);
597
0
  nsitem = pstate->p_target_nsitem;
598
599
  /* disallow DELETE ... WHERE CURRENT OF on a view */
600
0
  if (stmt->whereClause &&
601
0
    IsA(stmt->whereClause, CurrentOfExpr) &&
602
0
    pstate->p_target_relation->rd_rel->relkind == RELKIND_VIEW)
603
0
    ereport(ERROR,
604
0
        errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
605
0
        errmsg("WHERE CURRENT OF on a view is not implemented"));
606
607
  /* there's no DISTINCT in DELETE */
608
0
  qry->distinctClause = NIL;
609
610
  /* subqueries in USING cannot access the result relation */
611
0
  nsitem->p_lateral_only = true;
612
0
  nsitem->p_lateral_ok = false;
613
614
  /*
615
   * The USING clause is non-standard SQL syntax, and is equivalent in
616
   * functionality to the FROM list that can be specified for UPDATE. The
617
   * USING keyword is used rather than FROM because FROM is already a
618
   * keyword in the DELETE syntax.
619
   */
620
0
  transformFromClause(pstate, stmt->usingClause);
621
622
  /* remaining clauses can reference the result relation normally */
623
0
  nsitem->p_lateral_only = false;
624
0
  nsitem->p_lateral_ok = true;
625
626
0
  if (stmt->forPortionOf)
627
0
    qry->forPortionOf = transformForPortionOfClause(pstate,
628
0
                            qry->resultRelation,
629
0
                            stmt->forPortionOf,
630
0
                            stmt->whereClause,
631
0
                            false);
632
633
0
  qual = transformWhereClause(pstate, stmt->whereClause,
634
0
                EXPR_KIND_WHERE, "WHERE");
635
636
0
  transformReturningClause(pstate, qry, stmt->returningClause,
637
0
               EXPR_KIND_RETURNING);
638
639
  /* done building the range table and jointree */
640
0
  qry->rtable = pstate->p_rtable;
641
0
  qry->rteperminfos = pstate->p_rteperminfos;
642
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
643
644
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
645
0
  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
646
0
  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
647
0
  qry->hasAggs = pstate->p_hasAggs;
648
649
0
  assign_query_collations(pstate, qry);
650
651
  /* this must be done after collations, for reliable comparison of exprs */
652
0
  if (pstate->p_hasAggs)
653
0
    parseCheckAggregates(pstate, qry);
654
655
0
  return qry;
656
0
}
657
658
/*
659
 * transformInsertStmt -
660
 *    transform an Insert Statement
661
 */
662
static Query *
663
transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
664
0
{
665
0
  Query    *qry = makeNode(Query);
666
0
  SelectStmt *selectStmt = (SelectStmt *) stmt->selectStmt;
667
0
  List     *exprList = NIL;
668
0
  bool    isGeneralSelect;
669
0
  List     *sub_rtable;
670
0
  List     *sub_rteperminfos;
671
0
  List     *sub_namespace;
672
0
  List     *icolumns;
673
0
  List     *attrnos;
674
0
  ParseNamespaceItem *nsitem;
675
0
  RTEPermissionInfo *perminfo;
676
0
  ListCell   *icols;
677
0
  ListCell   *attnos;
678
0
  ListCell   *lc;
679
0
  bool    requiresUpdatePerm;
680
0
  AclMode   targetPerms;
681
682
  /* There can't be any outer WITH to worry about */
683
0
  Assert(pstate->p_ctenamespace == NIL);
684
685
0
  qry->commandType = CMD_INSERT;
686
687
  /* process the WITH clause independently of all else */
688
0
  if (stmt->withClause)
689
0
  {
690
0
    qry->hasRecursive = stmt->withClause->recursive;
691
0
    qry->cteList = transformWithClause(pstate, stmt->withClause);
692
0
    qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
693
0
  }
694
695
0
  qry->override = stmt->override;
696
697
  /*
698
   * ON CONFLICT DO UPDATE and ON CONFLICT DO SELECT FOR UPDATE/SHARE
699
   * require UPDATE permission on the target relation.
700
   */
701
0
  requiresUpdatePerm = (stmt->onConflictClause &&
702
0
              (stmt->onConflictClause->action == ONCONFLICT_UPDATE ||
703
0
               (stmt->onConflictClause->action == ONCONFLICT_SELECT &&
704
0
              stmt->onConflictClause->lockStrength != LCS_NONE)));
705
706
  /*
707
   * We have three cases to deal with: DEFAULT VALUES (selectStmt == NULL),
708
   * VALUES list, or general SELECT input.  We special-case VALUES, both for
709
   * efficiency and so we can handle DEFAULT specifications.
710
   *
711
   * The grammar allows attaching ORDER BY, LIMIT, FOR UPDATE, or WITH to a
712
   * VALUES clause.  If we have any of those, treat it as a general SELECT;
713
   * so it will work, but you can't use DEFAULT items together with those.
714
   */
715
0
  isGeneralSelect = (selectStmt && (selectStmt->valuesLists == NIL ||
716
0
                    selectStmt->sortClause != NIL ||
717
0
                    selectStmt->limitOffset != NULL ||
718
0
                    selectStmt->limitCount != NULL ||
719
0
                    selectStmt->lockingClause != NIL ||
720
0
                    selectStmt->withClause != NULL));
721
722
  /*
723
   * If a non-nil rangetable/namespace was passed in, and we are doing
724
   * INSERT/SELECT, arrange to pass the rangetable/rteperminfos/namespace
725
   * down to the SELECT.  This can only happen if we are inside a CREATE
726
   * RULE, and in that case we want the rule's OLD and NEW rtable entries to
727
   * appear as part of the SELECT's rtable, not as outer references for it.
728
   * (Kluge!) The SELECT's joinlist is not affected however.  We must do
729
   * this before adding the target table to the INSERT's rtable.
730
   */
731
0
  if (isGeneralSelect)
732
0
  {
733
0
    sub_rtable = pstate->p_rtable;
734
0
    pstate->p_rtable = NIL;
735
0
    sub_rteperminfos = pstate->p_rteperminfos;
736
0
    pstate->p_rteperminfos = NIL;
737
0
    sub_namespace = pstate->p_namespace;
738
0
    pstate->p_namespace = NIL;
739
0
  }
740
0
  else
741
0
  {
742
0
    sub_rtable = NIL;   /* not used, but keep compiler quiet */
743
0
    sub_rteperminfos = NIL;
744
0
    sub_namespace = NIL;
745
0
  }
746
747
  /*
748
   * Must get write lock on INSERT target table before scanning SELECT, else
749
   * we will grab the wrong kind of initial lock if the target table is also
750
   * mentioned in the SELECT part.  Note that the target table is not added
751
   * to the joinlist or namespace.
752
   */
753
0
  targetPerms = ACL_INSERT;
754
0
  if (requiresUpdatePerm)
755
0
    targetPerms |= ACL_UPDATE;
756
0
  qry->resultRelation = setTargetTable(pstate, stmt->relation,
757
0
                     false, false, targetPerms);
758
759
  /* Validate stmt->cols list, or build default list if no list given */
760
0
  icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
761
0
  Assert(list_length(icolumns) == list_length(attrnos));
762
763
  /*
764
   * Determine which variant of INSERT we have.
765
   */
766
0
  if (selectStmt == NULL)
767
0
  {
768
    /*
769
     * We have INSERT ... DEFAULT VALUES.  We can handle this case by
770
     * emitting an empty targetlist --- all columns will be defaulted when
771
     * the planner expands the targetlist.
772
     */
773
0
    exprList = NIL;
774
0
  }
775
0
  else if (isGeneralSelect)
776
0
  {
777
    /*
778
     * We make the sub-pstate a child of the outer pstate so that it can
779
     * see any Param definitions supplied from above.  Since the outer
780
     * pstate's rtable and namespace are presently empty, there are no
781
     * side-effects of exposing names the sub-SELECT shouldn't be able to
782
     * see.
783
     */
784
0
    ParseState *sub_pstate = make_parsestate(pstate);
785
0
    Query    *selectQuery;
786
787
    /*
788
     * Process the source SELECT.
789
     *
790
     * It is important that this be handled just like a standalone SELECT;
791
     * otherwise the behavior of SELECT within INSERT might be different
792
     * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
793
     * bugs of just that nature...)
794
     *
795
     * The sole exception is that we prevent resolving unknown-type
796
     * outputs as TEXT.  This does not change the semantics since if the
797
     * column type matters semantically, it would have been resolved to
798
     * something else anyway.  Doing this lets us resolve such outputs as
799
     * the target column's type, which we handle below.
800
     */
801
0
    sub_pstate->p_rtable = sub_rtable;
802
0
    sub_pstate->p_rteperminfos = sub_rteperminfos;
803
0
    sub_pstate->p_joinexprs = NIL; /* sub_rtable has no joins */
804
0
    sub_pstate->p_nullingrels = NIL;
805
0
    sub_pstate->p_namespace = sub_namespace;
806
0
    sub_pstate->p_resolve_unknowns = false;
807
808
0
    selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
809
810
0
    free_parsestate(sub_pstate);
811
812
    /* The grammar should have produced a SELECT */
813
0
    if (!IsA(selectQuery, Query) ||
814
0
      selectQuery->commandType != CMD_SELECT)
815
0
      elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT");
816
817
    /*
818
     * Make the source be a subquery in the INSERT's rangetable, and add
819
     * it to the INSERT's joinlist (but not the namespace).
820
     */
821
0
    nsitem = addRangeTableEntryForSubquery(pstate,
822
0
                         selectQuery,
823
0
                         NULL,
824
0
                         false,
825
0
                         false);
826
0
    addNSItemToQuery(pstate, nsitem, true, false, false);
827
828
    /*----------
829
     * Generate an expression list for the INSERT that selects all the
830
     * non-resjunk columns from the subquery.  (INSERT's tlist must be
831
     * separate from the subquery's tlist because we may add columns,
832
     * insert datatype coercions, etc.)
833
     *
834
     * HACK: unknown-type constants and params in the SELECT's targetlist
835
     * are copied up as-is rather than being referenced as subquery
836
     * outputs.  This is to ensure that when we try to coerce them to
837
     * the target column's datatype, the right things happen (see
838
     * special cases in coerce_type).  Otherwise, this fails:
839
     *    INSERT INTO foo SELECT 'bar', ... FROM baz
840
     *----------
841
     */
842
0
    exprList = NIL;
843
0
    foreach(lc, selectQuery->targetList)
844
0
    {
845
0
      TargetEntry *tle = (TargetEntry *) lfirst(lc);
846
0
      Expr     *expr;
847
848
0
      if (tle->resjunk)
849
0
        continue;
850
0
      if (tle->expr &&
851
0
        (IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
852
0
        exprType((Node *) tle->expr) == UNKNOWNOID)
853
0
        expr = tle->expr;
854
0
      else
855
0
      {
856
0
        Var      *var = makeVarFromTargetEntry(nsitem->p_rtindex, tle);
857
858
0
        var->location = exprLocation((Node *) tle->expr);
859
0
        expr = (Expr *) var;
860
0
      }
861
0
      exprList = lappend(exprList, expr);
862
0
    }
863
864
    /* Prepare row for assignment to target table */
865
0
    exprList = transformInsertRow(pstate, exprList,
866
0
                    stmt->cols,
867
0
                    icolumns, attrnos,
868
0
                    false);
869
0
  }
870
0
  else if (list_length(selectStmt->valuesLists) > 1)
871
0
  {
872
    /*
873
     * Process INSERT ... VALUES with multiple VALUES sublists. We
874
     * generate a VALUES RTE holding the transformed expression lists, and
875
     * build up a targetlist containing Vars that reference the VALUES
876
     * RTE.
877
     */
878
0
    List     *exprsLists = NIL;
879
0
    List     *coltypes = NIL;
880
0
    List     *coltypmods = NIL;
881
0
    List     *colcollations = NIL;
882
0
    int     sublist_length = -1;
883
0
    bool    lateral = false;
884
885
0
    Assert(selectStmt->intoClause == NULL);
886
887
0
    foreach(lc, selectStmt->valuesLists)
888
0
    {
889
0
      List     *sublist = (List *) lfirst(lc);
890
891
      /*
892
       * Do basic expression transformation (same as a ROW() expr, but
893
       * allow SetToDefault at top level)
894
       */
895
0
      sublist = transformExpressionList(pstate, sublist,
896
0
                        EXPR_KIND_VALUES, true);
897
898
      /*
899
       * All the sublists must be the same length, *after*
900
       * transformation (which might expand '*' into multiple items).
901
       * The VALUES RTE can't handle anything different.
902
       */
903
0
      if (sublist_length < 0)
904
0
      {
905
        /* Remember post-transformation length of first sublist */
906
0
        sublist_length = list_length(sublist);
907
0
      }
908
0
      else if (sublist_length != list_length(sublist))
909
0
      {
910
0
        ereport(ERROR,
911
0
            (errcode(ERRCODE_SYNTAX_ERROR),
912
0
             errmsg("VALUES lists must all be the same length"),
913
0
             parser_errposition(pstate,
914
0
                      exprLocation((Node *) sublist))));
915
0
      }
916
917
      /*
918
       * Prepare row for assignment to target table.  We process any
919
       * indirection on the target column specs normally but then strip
920
       * off the resulting field/array assignment nodes, since we don't
921
       * want the parsed statement to contain copies of those in each
922
       * VALUES row.  (It's annoying to have to transform the
923
       * indirection specs over and over like this, but avoiding it
924
       * would take some really messy refactoring of
925
       * transformAssignmentIndirection.)
926
       */
927
0
      sublist = transformInsertRow(pstate, sublist,
928
0
                     stmt->cols,
929
0
                     icolumns, attrnos,
930
0
                     true);
931
932
      /*
933
       * We must assign collations now because assign_query_collations
934
       * doesn't process rangetable entries.  We just assign all the
935
       * collations independently in each row, and don't worry about
936
       * whether they are consistent vertically.  The outer INSERT query
937
       * isn't going to care about the collations of the VALUES columns,
938
       * so it's not worth the effort to identify a common collation for
939
       * each one here.  (But note this does have one user-visible
940
       * consequence: INSERT ... VALUES won't complain about conflicting
941
       * explicit COLLATEs in a column, whereas the same VALUES
942
       * construct in another context would complain.)
943
       */
944
0
      assign_list_collations(pstate, sublist);
945
946
0
      exprsLists = lappend(exprsLists, sublist);
947
0
    }
948
949
    /*
950
     * Construct column type/typmod/collation lists for the VALUES RTE.
951
     * Every expression in each column has been coerced to the type/typmod
952
     * of the corresponding target column or subfield, so it's sufficient
953
     * to look at the exprType/exprTypmod of the first row.  We don't care
954
     * about the collation labeling, so just fill in InvalidOid for that.
955
     */
956
0
    foreach(lc, (List *) linitial(exprsLists))
957
0
    {
958
0
      Node     *val = (Node *) lfirst(lc);
959
960
0
      coltypes = lappend_oid(coltypes, exprType(val));
961
0
      coltypmods = lappend_int(coltypmods, exprTypmod(val));
962
0
      colcollations = lappend_oid(colcollations, InvalidOid);
963
0
    }
964
965
    /*
966
     * Ordinarily there can't be any current-level Vars in the expression
967
     * lists, because the namespace was empty ... but if we're inside
968
     * CREATE RULE, then NEW/OLD references might appear.  In that case we
969
     * have to mark the VALUES RTE as LATERAL.
970
     */
971
0
    if (list_length(pstate->p_rtable) != 1 &&
972
0
      contain_vars_of_level((Node *) exprsLists, 0))
973
0
      lateral = true;
974
975
    /*
976
     * Generate the VALUES RTE
977
     */
978
0
    nsitem = addRangeTableEntryForValues(pstate, exprsLists,
979
0
                       coltypes, coltypmods, colcollations,
980
0
                       NULL, lateral, true);
981
0
    addNSItemToQuery(pstate, nsitem, true, false, false);
982
983
    /*
984
     * Generate list of Vars referencing the RTE
985
     */
986
0
    exprList = expandNSItemVars(pstate, nsitem, 0, -1, NULL);
987
988
    /*
989
     * Re-apply any indirection on the target column specs to the Vars
990
     */
991
0
    exprList = transformInsertRow(pstate, exprList,
992
0
                    stmt->cols,
993
0
                    icolumns, attrnos,
994
0
                    false);
995
0
  }
996
0
  else
997
0
  {
998
    /*
999
     * Process INSERT ... VALUES with a single VALUES sublist.  We treat
1000
     * this case separately for efficiency.  The sublist is just computed
1001
     * directly as the Query's targetlist, with no VALUES RTE.  So it
1002
     * works just like a SELECT without any FROM.
1003
     */
1004
0
    List     *valuesLists = selectStmt->valuesLists;
1005
1006
0
    Assert(list_length(valuesLists) == 1);
1007
0
    Assert(selectStmt->intoClause == NULL);
1008
1009
    /*
1010
     * Do basic expression transformation (same as a ROW() expr, but allow
1011
     * SetToDefault at top level)
1012
     */
1013
0
    exprList = transformExpressionList(pstate,
1014
0
                       (List *) linitial(valuesLists),
1015
0
                       EXPR_KIND_VALUES_SINGLE,
1016
0
                       true);
1017
1018
    /* Prepare row for assignment to target table */
1019
0
    exprList = transformInsertRow(pstate, exprList,
1020
0
                    stmt->cols,
1021
0
                    icolumns, attrnos,
1022
0
                    false);
1023
0
  }
1024
1025
  /*
1026
   * Generate query's target list using the computed list of expressions.
1027
   * Also, mark all the target columns as needing insert permissions.
1028
   */
1029
0
  perminfo = pstate->p_target_nsitem->p_perminfo;
1030
0
  qry->targetList = NIL;
1031
0
  Assert(list_length(exprList) <= list_length(icolumns));
1032
0
  forthree(lc, exprList, icols, icolumns, attnos, attrnos)
1033
0
  {
1034
0
    Expr     *expr = (Expr *) lfirst(lc);
1035
0
    ResTarget  *col = lfirst_node(ResTarget, icols);
1036
0
    AttrNumber  attr_num = (AttrNumber) lfirst_int(attnos);
1037
0
    TargetEntry *tle;
1038
1039
0
    tle = makeTargetEntry(expr,
1040
0
                attr_num,
1041
0
                col->name,
1042
0
                false);
1043
0
    qry->targetList = lappend(qry->targetList, tle);
1044
1045
0
    perminfo->insertedCols = bms_add_member(perminfo->insertedCols,
1046
0
                        attr_num - FirstLowInvalidHeapAttributeNumber);
1047
0
  }
1048
1049
  /*
1050
   * If we have any clauses yet to process, set the query namespace to
1051
   * contain only the target relation, removing any entries added in a
1052
   * sub-SELECT or VALUES list.
1053
   */
1054
0
  if (stmt->onConflictClause || stmt->returningClause)
1055
0
  {
1056
0
    pstate->p_namespace = NIL;
1057
0
    addNSItemToQuery(pstate, pstate->p_target_nsitem,
1058
0
             false, true, true);
1059
0
  }
1060
1061
  /* ON CONFLICT DO SELECT requires a RETURNING clause */
1062
0
  if (stmt->onConflictClause &&
1063
0
    stmt->onConflictClause->action == ONCONFLICT_SELECT &&
1064
0
    !stmt->returningClause)
1065
0
    ereport(ERROR,
1066
0
        errcode(ERRCODE_SYNTAX_ERROR),
1067
0
        errmsg("ON CONFLICT DO SELECT requires a RETURNING clause"),
1068
0
        parser_errposition(pstate, stmt->onConflictClause->location));
1069
1070
  /* Process ON CONFLICT, if any. */
1071
0
  if (stmt->onConflictClause)
1072
0
    qry->onConflict = transformOnConflictClause(pstate,
1073
0
                          stmt->onConflictClause);
1074
1075
  /* Process RETURNING, if any. */
1076
0
  if (stmt->returningClause)
1077
0
    transformReturningClause(pstate, qry, stmt->returningClause,
1078
0
                 EXPR_KIND_RETURNING);
1079
1080
  /* done building the range table and jointree */
1081
0
  qry->rtable = pstate->p_rtable;
1082
0
  qry->rteperminfos = pstate->p_rteperminfos;
1083
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
1084
1085
0
  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1086
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
1087
1088
0
  assign_query_collations(pstate, qry);
1089
1090
0
  return qry;
1091
0
}
1092
1093
/*
1094
 * Prepare an INSERT row for assignment to the target table.
1095
 *
1096
 * exprlist: transformed expressions for source values; these might come from
1097
 * a VALUES row, or be Vars referencing a sub-SELECT or VALUES RTE output.
1098
 * stmtcols: original target-columns spec for INSERT (we just test for NIL)
1099
 * icolumns: effective target-columns spec (list of ResTarget)
1100
 * attrnos: integer column numbers (must be same length as icolumns)
1101
 * strip_indirection: if true, remove any field/array assignment nodes
1102
 */
1103
List *
1104
transformInsertRow(ParseState *pstate, List *exprlist,
1105
           List *stmtcols, List *icolumns, List *attrnos,
1106
           bool strip_indirection)
1107
0
{
1108
0
  List     *result;
1109
0
  ListCell   *lc;
1110
0
  ListCell   *icols;
1111
0
  ListCell   *attnos;
1112
1113
  /*
1114
   * Check length of expr list.  It must not have more expressions than
1115
   * there are target columns.  We allow fewer, but only if no explicit
1116
   * columns list was given (the remaining columns are implicitly
1117
   * defaulted).  Note we must check this *after* transformation because
1118
   * that could expand '*' into multiple items.
1119
   */
1120
0
  if (list_length(exprlist) > list_length(icolumns))
1121
0
    ereport(ERROR,
1122
0
        (errcode(ERRCODE_SYNTAX_ERROR),
1123
0
         errmsg("INSERT has more expressions than target columns"),
1124
0
         parser_errposition(pstate,
1125
0
                  exprLocation(list_nth(exprlist,
1126
0
                              list_length(icolumns))))));
1127
0
  if (stmtcols != NIL &&
1128
0
    list_length(exprlist) < list_length(icolumns))
1129
0
  {
1130
    /*
1131
     * We can get here for cases like INSERT ... SELECT (a,b,c) FROM ...
1132
     * where the user accidentally created a RowExpr instead of separate
1133
     * columns.  Add a suitable hint if that seems to be the problem,
1134
     * because the main error message is quite misleading for this case.
1135
     * (If there's no stmtcols, you'll get something about data type
1136
     * mismatch, which is less misleading so we don't worry about giving a
1137
     * hint in that case.)
1138
     */
1139
0
    ereport(ERROR,
1140
0
        (errcode(ERRCODE_SYNTAX_ERROR),
1141
0
         errmsg("INSERT has more target columns than expressions"),
1142
0
         ((list_length(exprlist) == 1 &&
1143
0
           count_rowexpr_columns(pstate, linitial(exprlist)) ==
1144
0
           list_length(icolumns)) ?
1145
0
          errhint("The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?") : 0),
1146
0
         parser_errposition(pstate,
1147
0
                  exprLocation(list_nth(icolumns,
1148
0
                              list_length(exprlist))))));
1149
0
  }
1150
1151
  /*
1152
   * Prepare columns for assignment to target table.
1153
   */
1154
0
  result = NIL;
1155
0
  forthree(lc, exprlist, icols, icolumns, attnos, attrnos)
1156
0
  {
1157
0
    Expr     *expr = (Expr *) lfirst(lc);
1158
0
    ResTarget  *col = lfirst_node(ResTarget, icols);
1159
0
    int     attno = lfirst_int(attnos);
1160
1161
0
    expr = transformAssignedExpr(pstate, expr,
1162
0
                   EXPR_KIND_INSERT_TARGET,
1163
0
                   col->name,
1164
0
                   attno,
1165
0
                   col->indirection,
1166
0
                   col->location);
1167
1168
0
    if (strip_indirection)
1169
0
    {
1170
      /*
1171
       * We need to remove top-level FieldStores and SubscriptingRefs,
1172
       * as well as any CoerceToDomain appearing above one of those ---
1173
       * but not a CoerceToDomain that isn't above one of those.
1174
       */
1175
0
      while (expr)
1176
0
      {
1177
0
        Expr     *subexpr = expr;
1178
1179
0
        while (IsA(subexpr, CoerceToDomain))
1180
0
        {
1181
0
          subexpr = ((CoerceToDomain *) subexpr)->arg;
1182
0
        }
1183
0
        if (IsA(subexpr, FieldStore))
1184
0
        {
1185
0
          FieldStore *fstore = (FieldStore *) subexpr;
1186
1187
0
          expr = (Expr *) linitial(fstore->newvals);
1188
0
        }
1189
0
        else if (IsA(subexpr, SubscriptingRef))
1190
0
        {
1191
0
          SubscriptingRef *sbsref = (SubscriptingRef *) subexpr;
1192
1193
0
          if (sbsref->refassgnexpr == NULL)
1194
0
            break;
1195
1196
0
          expr = sbsref->refassgnexpr;
1197
0
        }
1198
0
        else
1199
0
          break;
1200
0
      }
1201
0
    }
1202
1203
0
    result = lappend(result, expr);
1204
0
  }
1205
1206
0
  return result;
1207
0
}
1208
1209
/*
1210
 * transformOnConflictClause -
1211
 *    transforms an OnConflictClause in an INSERT
1212
 */
1213
static OnConflictExpr *
1214
transformOnConflictClause(ParseState *pstate,
1215
              OnConflictClause *onConflictClause)
1216
0
{
1217
0
  ParseNamespaceItem *exclNSItem = NULL;
1218
0
  List     *arbiterElems;
1219
0
  Node     *arbiterWhere;
1220
0
  Oid     arbiterConstraint;
1221
0
  List     *onConflictSet = NIL;
1222
0
  Node     *onConflictWhere = NULL;
1223
0
  int     exclRelIndex = 0;
1224
0
  List     *exclRelTlist = NIL;
1225
0
  OnConflictExpr *result;
1226
1227
  /*
1228
   * If this is ON CONFLICT DO SELECT/UPDATE, first create the range table
1229
   * entry for the EXCLUDED pseudo relation, so that that will be present
1230
   * while processing arbiter expressions.  (You can't actually reference it
1231
   * from there, but this provides a useful error message if you try.)
1232
   */
1233
0
  if (onConflictClause->action == ONCONFLICT_UPDATE ||
1234
0
    onConflictClause->action == ONCONFLICT_SELECT)
1235
0
  {
1236
0
    Relation  targetrel = pstate->p_target_relation;
1237
0
    RangeTblEntry *exclRte;
1238
1239
0
    exclNSItem = addRangeTableEntryForRelation(pstate,
1240
0
                           targetrel,
1241
0
                           RowExclusiveLock,
1242
0
                           makeAlias("excluded", NIL),
1243
0
                           false, false);
1244
0
    exclRte = exclNSItem->p_rte;
1245
0
    exclRelIndex = exclNSItem->p_rtindex;
1246
1247
    /*
1248
     * relkind is set to composite to signal that we're not dealing with
1249
     * an actual relation, and no permission checks are required on it.
1250
     * (We'll check the actual target relation, instead.)
1251
     */
1252
0
    exclRte->relkind = RELKIND_COMPOSITE_TYPE;
1253
1254
    /* Create EXCLUDED rel's targetlist for use by EXPLAIN */
1255
0
    exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
1256
0
                             exclRelIndex);
1257
0
  }
1258
1259
  /* Process the arbiter clause, ON CONFLICT ON (...) */
1260
0
  transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
1261
0
                 &arbiterWhere, &arbiterConstraint);
1262
1263
  /* Process DO SELECT/UPDATE */
1264
0
  if (onConflictClause->action == ONCONFLICT_UPDATE ||
1265
0
    onConflictClause->action == ONCONFLICT_SELECT)
1266
0
  {
1267
    /*
1268
     * Add the EXCLUDED pseudo relation to the query namespace, making it
1269
     * available in SET and WHERE subexpressions.
1270
     */
1271
0
    addNSItemToQuery(pstate, exclNSItem, false, true, true);
1272
1273
    /* Process the UPDATE SET clause */
1274
0
    if (onConflictClause->action == ONCONFLICT_UPDATE)
1275
0
      onConflictSet =
1276
0
        transformUpdateTargetList(pstate, onConflictClause->targetList, NULL);
1277
1278
    /* Process the SELECT/UPDATE WHERE clause */
1279
0
    onConflictWhere = transformWhereClause(pstate,
1280
0
                         onConflictClause->whereClause,
1281
0
                         EXPR_KIND_WHERE, "WHERE");
1282
1283
    /*
1284
     * Remove the EXCLUDED pseudo relation from the query namespace, since
1285
     * it's not supposed to be available in RETURNING.  (Maybe someday we
1286
     * could allow that, and drop this step.)
1287
     */
1288
0
    Assert((ParseNamespaceItem *) llast(pstate->p_namespace) == exclNSItem);
1289
0
    pstate->p_namespace = list_delete_last(pstate->p_namespace);
1290
0
  }
1291
1292
  /* Finally, build ON CONFLICT DO [NOTHING | SELECT | UPDATE] expression */
1293
0
  result = makeNode(OnConflictExpr);
1294
1295
0
  result->action = onConflictClause->action;
1296
0
  result->arbiterElems = arbiterElems;
1297
0
  result->arbiterWhere = arbiterWhere;
1298
0
  result->constraint = arbiterConstraint;
1299
0
  result->lockStrength = onConflictClause->lockStrength;
1300
0
  result->onConflictSet = onConflictSet;
1301
0
  result->onConflictWhere = onConflictWhere;
1302
0
  result->exclRelIndex = exclRelIndex;
1303
0
  result->exclRelTlist = exclRelTlist;
1304
1305
0
  return result;
1306
0
}
1307
1308
/*
1309
 * transformForPortionOfClause
1310
 *
1311
 *    Transforms a ForPortionOfClause in an UPDATE/DELETE statement.
1312
 *
1313
 *    - Look up the range/period requested.
1314
 *    - Build a compatible range value from the FROM and TO expressions.
1315
 *    - Build an "overlaps" expression for filtering, used later by the
1316
 *    rewriter.
1317
 *    - For UPDATEs, build an "intersects" expression the rewriter can add
1318
 *    to the targetList to change the temporal bounds.
1319
 */
1320
static ForPortionOfExpr *
1321
transformForPortionOfClause(ParseState *pstate,
1322
              int rtindex,
1323
              const ForPortionOfClause *forPortionOf,
1324
              const Node *whereClause,
1325
              bool isUpdate)
1326
0
{
1327
0
  Relation  targetrel = pstate->p_target_relation;
1328
0
  int     range_attno = InvalidAttrNumber;
1329
0
  Form_pg_attribute attr;
1330
0
  Oid     attbasetype;
1331
0
  Oid     opclass;
1332
0
  Oid     opfamily;
1333
0
  Oid     opcintype;
1334
0
  Oid     funcid = InvalidOid;
1335
0
  StrategyNumber strat;
1336
0
  Oid     opid;
1337
0
  OpExpr     *op;
1338
0
  ForPortionOfExpr *result;
1339
0
  Var      *rangeVar;
1340
1341
  /* disallow FOR PORTION OF ... WHERE CURRENT OF */
1342
0
  if (whereClause && IsA(whereClause, CurrentOfExpr))
1343
0
    ereport(ERROR,
1344
0
        errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1345
0
        errmsg("WHERE CURRENT OF with FOR PORTION OF is not implemented"));
1346
1347
0
  result = makeNode(ForPortionOfExpr);
1348
1349
  /* Look up the FOR PORTION OF name requested. */
1350
0
  range_attno = attnameAttNum(targetrel, forPortionOf->range_name, false);
1351
0
  if (range_attno == InvalidAttrNumber)
1352
0
    ereport(ERROR,
1353
0
        (errcode(ERRCODE_UNDEFINED_COLUMN),
1354
0
         errmsg("column \"%s\" of relation \"%s\" does not exist",
1355
0
            forPortionOf->range_name,
1356
0
            RelationGetRelationName(targetrel)),
1357
0
         parser_errposition(pstate, forPortionOf->location)));
1358
0
  attr = TupleDescAttr(targetrel->rd_att, range_attno - 1);
1359
1360
0
  attbasetype = getBaseType(attr->atttypid);
1361
1362
0
  rangeVar = makeVar(rtindex,
1363
0
             range_attno,
1364
0
             attr->atttypid,
1365
0
             attr->atttypmod,
1366
0
             attr->attcollation,
1367
0
             0);
1368
0
  rangeVar->location = forPortionOf->location;
1369
0
  result->rangeVar = rangeVar;
1370
1371
  /* Require SELECT privilege on the application-time column. */
1372
0
  markVarForSelectPriv(pstate, rangeVar);
1373
1374
  /*
1375
   * Use the basetype for the target, which shouldn't be required to follow
1376
   * domain rules. The table's column type is in the Var if we need it.
1377
   */
1378
0
  result->rangeType = attbasetype;
1379
0
  result->isDomain = attbasetype != attr->atttypid;
1380
1381
0
  if (forPortionOf->target)
1382
0
  {
1383
0
    Oid     declared_target_type = attbasetype;
1384
0
    Oid     actual_target_type;
1385
1386
    /*
1387
     * We were already given an expression for the target, so we don't
1388
     * have to build anything. We still have to make sure we got the right
1389
     * type. NULL will be caught be the executor.
1390
     */
1391
1392
0
    result->targetRange = transformExpr(pstate,
1393
0
                      forPortionOf->target,
1394
0
                      EXPR_KIND_FOR_PORTION);
1395
1396
0
    actual_target_type = exprType(result->targetRange);
1397
1398
0
    if (!can_coerce_type(1, &actual_target_type, &declared_target_type, COERCION_IMPLICIT))
1399
0
      ereport(ERROR,
1400
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
1401
0
           errmsg("could not coerce FOR PORTION OF target from %s to %s",
1402
0
              format_type_be(actual_target_type),
1403
0
              format_type_be(declared_target_type)),
1404
0
           parser_errposition(pstate, exprLocation(forPortionOf->target))));
1405
1406
0
    result->targetRange = coerce_type(pstate,
1407
0
                      result->targetRange,
1408
0
                      actual_target_type,
1409
0
                      declared_target_type,
1410
0
                      -1,
1411
0
                      COERCION_IMPLICIT,
1412
0
                      COERCE_IMPLICIT_CAST,
1413
0
                      exprLocation(forPortionOf->target));
1414
1415
    /*
1416
     * XXX: For now we only support ranges and multiranges, so we fail on
1417
     * anything else.
1418
     */
1419
0
    if (!type_is_range(attbasetype) && !type_is_multirange(attbasetype))
1420
0
      ereport(ERROR,
1421
0
          (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1422
0
           errmsg("column \"%s\" of relation \"%s\" is not a range or multirange type",
1423
0
              forPortionOf->range_name,
1424
0
              RelationGetRelationName(targetrel)),
1425
0
           parser_errposition(pstate, forPortionOf->location)));
1426
1427
0
  }
1428
0
  else
1429
0
  {
1430
0
    Oid     rngsubtype;
1431
0
    Oid     declared_arg_types[2];
1432
0
    Oid     actual_arg_types[2];
1433
0
    List     *args;
1434
1435
    /*
1436
     * Make sure it's a range column. XXX: We could support this syntax on
1437
     * multirange columns too, if we just built a one-range multirange
1438
     * from the FROM/TO phrases.
1439
     */
1440
0
    if (!type_is_range(attbasetype))
1441
0
      ereport(ERROR,
1442
0
          (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1443
0
           errmsg("column \"%s\" of relation \"%s\" is not a range type",
1444
0
              forPortionOf->range_name,
1445
0
              RelationGetRelationName(targetrel)),
1446
0
           parser_errposition(pstate, forPortionOf->location)));
1447
1448
0
    rngsubtype = get_range_subtype(attbasetype);
1449
0
    declared_arg_types[0] = rngsubtype;
1450
0
    declared_arg_types[1] = rngsubtype;
1451
1452
    /*
1453
     * Build a range from the FROM ... TO ... bounds. This should give a
1454
     * constant result, so we accept functions like NOW() but not column
1455
     * references, subqueries, etc.
1456
     */
1457
0
    result->targetFrom = transformExpr(pstate,
1458
0
                       forPortionOf->target_start,
1459
0
                       EXPR_KIND_FOR_PORTION);
1460
0
    result->targetTo = transformExpr(pstate,
1461
0
                     forPortionOf->target_end,
1462
0
                     EXPR_KIND_FOR_PORTION);
1463
0
    actual_arg_types[0] = exprType(result->targetFrom);
1464
0
    actual_arg_types[1] = exprType(result->targetTo);
1465
0
    args = list_make2(copyObject(result->targetFrom),
1466
0
              copyObject(result->targetTo));
1467
1468
    /*
1469
     * Check the bound types separately, for better error message and
1470
     * location
1471
     */
1472
0
    if (!can_coerce_type(1, actual_arg_types, declared_arg_types, COERCION_IMPLICIT))
1473
0
      ereport(ERROR,
1474
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
1475
0
           errmsg("could not coerce FOR PORTION OF %s bound from %s to %s",
1476
0
              "FROM",
1477
0
              format_type_be(actual_arg_types[0]),
1478
0
              format_type_be(declared_arg_types[0])),
1479
0
           parser_errposition(pstate, exprLocation(forPortionOf->target_start))));
1480
0
    if (!can_coerce_type(1, &actual_arg_types[1], &declared_arg_types[1], COERCION_IMPLICIT))
1481
0
      ereport(ERROR,
1482
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
1483
0
           errmsg("could not coerce FOR PORTION OF %s bound from %s to %s",
1484
0
              "TO",
1485
0
              format_type_be(actual_arg_types[1]),
1486
0
              format_type_be(declared_arg_types[1])),
1487
0
           parser_errposition(pstate, exprLocation(forPortionOf->target_end))));
1488
1489
0
    make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
1490
0
    result->targetRange = (Node *) makeFuncExpr(get_range_constructor2(attbasetype),
1491
0
                          attbasetype,
1492
0
                          args,
1493
0
                          InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
1494
0
  }
1495
1496
  /*
1497
   * Build overlapsExpr to use as an extra qual. This means we only hit rows
1498
   * matching the FROM & TO bounds. We must look up the overlaps operator
1499
   * (usually "&&").
1500
   */
1501
0
  opclass = GetDefaultOpClass(attr->atttypid, GIST_AM_OID);
1502
0
  if (!OidIsValid(opclass))
1503
0
    ereport(ERROR,
1504
0
        (errcode(ERRCODE_UNDEFINED_OBJECT),
1505
0
         errmsg("data type %s has no default operator class for access method \"%s\"",
1506
0
            format_type_be(attr->atttypid), "gist"),
1507
0
         errhint("You must define a default operator class for the data type.")));
1508
1509
  /* Look up the operators and functions we need. */
1510
0
  GetOperatorFromCompareType(opclass, InvalidOid, COMPARE_OVERLAP, &opid, &strat);
1511
0
  op = makeNode(OpExpr);
1512
0
  op->opno = opid;
1513
0
  op->opfuncid = get_opcode(opid);
1514
0
  op->opresulttype = BOOLOID;
1515
0
  op->args = list_make2(copyObject(rangeVar), copyObject(result->targetRange));
1516
0
  result->overlapsExpr = (Node *) op;
1517
1518
  /*
1519
   * Look up the without_portion func. This computes the bounds of temporal
1520
   * leftovers.
1521
   *
1522
   * XXX: Find a more extensible way to look up the function, permitting
1523
   * user-defined types. An opclass support function doesn't make sense,
1524
   * since there is no index involved. Perhaps a type support function.
1525
   */
1526
0
  if (get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
1527
0
    switch (opcintype)
1528
0
    {
1529
0
      case ANYRANGEOID:
1530
0
        result->withoutPortionProc = F_RANGE_MINUS_MULTI;
1531
0
        break;
1532
0
      case ANYMULTIRANGEOID:
1533
0
        result->withoutPortionProc = F_MULTIRANGE_MINUS_MULTI;
1534
0
        break;
1535
0
      default:
1536
0
        elog(ERROR, "unexpected opcintype: %u", opcintype);
1537
0
    }
1538
0
  else
1539
0
    elog(ERROR, "unexpected opclass: %u", opclass);
1540
1541
0
  if (isUpdate)
1542
0
  {
1543
    /*
1544
     * Now make sure we update the start/end time of the record. For a
1545
     * range col (r) this is `r = r * targetRange` (where * is the
1546
     * intersect operator).
1547
     */
1548
0
    Oid     intersectoperoid;
1549
0
    List     *funcArgs;
1550
0
    Node     *rangeTLEExpr;
1551
0
    TargetEntry *tle;
1552
0
    RTEPermissionInfo *target_perminfo = pstate->p_target_nsitem->p_perminfo;
1553
1554
    /*
1555
     * Whatever operator is used for intersect by temporal foreign keys,
1556
     * we can use its backing procedure for intersects in FOR PORTION OF.
1557
     * XXX: Share code with FindFKPeriodOpers?
1558
     */
1559
0
    switch (opcintype)
1560
0
    {
1561
0
      case ANYRANGEOID:
1562
0
        intersectoperoid = OID_RANGE_INTERSECT_RANGE_OP;
1563
0
        break;
1564
0
      case ANYMULTIRANGEOID:
1565
0
        intersectoperoid = OID_MULTIRANGE_INTERSECT_MULTIRANGE_OP;
1566
0
        break;
1567
0
      default:
1568
0
        elog(ERROR, "unexpected opcintype: %u", opcintype);
1569
0
    }
1570
0
    funcid = get_opcode(intersectoperoid);
1571
0
    if (!OidIsValid(funcid))
1572
0
      ereport(ERROR,
1573
0
          errcode(ERRCODE_UNDEFINED_OBJECT),
1574
0
          errmsg("could not identify an intersect function for type %s",
1575
0
               format_type_be(opcintype)));
1576
1577
0
    funcArgs = list_make2(copyObject(rangeVar),
1578
0
                copyObject(result->targetRange));
1579
0
    rangeTLEExpr = (Node *) makeFuncExpr(funcid, attbasetype, funcArgs,
1580
0
                       InvalidOid, InvalidOid,
1581
0
                       COERCE_EXPLICIT_CALL);
1582
1583
    /*
1584
     * Coerce to domain if necessary. If we skip this, we will allow
1585
     * updating to forbidden values.
1586
     */
1587
0
    rangeTLEExpr = coerce_type(pstate,
1588
0
                   rangeTLEExpr,
1589
0
                   attbasetype,
1590
0
                   attr->atttypid,
1591
0
                   -1,
1592
0
                   COERCION_IMPLICIT,
1593
0
                   COERCE_IMPLICIT_CAST,
1594
0
                   exprLocation(forPortionOf->target));
1595
1596
    /* Make a TLE to set the range column */
1597
0
    result->rangeTargetList = NIL;
1598
0
    tle = makeTargetEntry((Expr *) rangeTLEExpr, range_attno,
1599
0
                forPortionOf->range_name, false);
1600
0
    result->rangeTargetList = lappend(result->rangeTargetList, tle);
1601
1602
    /* Mark the range column as requiring update permissions */
1603
0
    target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
1604
0
                            range_attno - FirstLowInvalidHeapAttributeNumber);
1605
0
  }
1606
0
  else
1607
0
    result->rangeTargetList = NIL;
1608
1609
0
  result->location = forPortionOf->location;
1610
0
  result->targetLocation = forPortionOf->target_location;
1611
1612
0
  return result;
1613
0
}
1614
1615
/*
1616
 * BuildOnConflictExcludedTargetlist
1617
 *    Create target list for the EXCLUDED pseudo-relation of ON CONFLICT,
1618
 *    representing the columns of targetrel with varno exclRelIndex.
1619
 *
1620
 * Note: Exported for use in the rewriter.
1621
 */
1622
List *
1623
BuildOnConflictExcludedTargetlist(Relation targetrel,
1624
                  Index exclRelIndex)
1625
0
{
1626
0
  List     *result = NIL;
1627
0
  int     attno;
1628
0
  Var      *var;
1629
0
  TargetEntry *te;
1630
1631
  /*
1632
   * Note that resnos of the tlist must correspond to attnos of the
1633
   * underlying relation, hence we need entries for dropped columns too.
1634
   */
1635
0
  for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
1636
0
  {
1637
0
    Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1638
0
    char     *name;
1639
1640
0
    if (attr->attisdropped)
1641
0
    {
1642
      /*
1643
       * can't use atttypid here, but it doesn't really matter what type
1644
       * the Const claims to be.
1645
       */
1646
0
      var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1647
0
      name = NULL;
1648
0
    }
1649
0
    else
1650
0
    {
1651
0
      var = makeVar(exclRelIndex, attno + 1,
1652
0
              attr->atttypid, attr->atttypmod,
1653
0
              attr->attcollation,
1654
0
              0);
1655
0
      name = pstrdup(NameStr(attr->attname));
1656
0
    }
1657
1658
0
    te = makeTargetEntry((Expr *) var,
1659
0
               attno + 1,
1660
0
               name,
1661
0
               false);
1662
1663
0
    result = lappend(result, te);
1664
0
  }
1665
1666
  /*
1667
   * Add a whole-row-Var entry to support references to "EXCLUDED.*".  Like
1668
   * the other entries in the EXCLUDED tlist, its resno must match the Var's
1669
   * varattno, else the wrong things happen while resolving references in
1670
   * setrefs.c.  This is against normal conventions for targetlists, but
1671
   * it's okay since we don't use this as a real tlist.
1672
   */
1673
0
  var = makeVar(exclRelIndex, InvalidAttrNumber,
1674
0
          targetrel->rd_rel->reltype,
1675
0
          -1, InvalidOid, 0);
1676
0
  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1677
0
  result = lappend(result, te);
1678
1679
0
  return result;
1680
0
}
1681
1682
1683
/*
1684
 * count_rowexpr_columns -
1685
 *    get number of columns contained in a ROW() expression;
1686
 *    return -1 if expression isn't a RowExpr or a Var referencing one.
1687
 *
1688
 * This is currently used only for hint purposes, so we aren't terribly
1689
 * tense about recognizing all possible cases.  The Var case is interesting
1690
 * because that's what we'll get in the INSERT ... SELECT (...) case.
1691
 */
1692
static int
1693
count_rowexpr_columns(ParseState *pstate, Node *expr)
1694
0
{
1695
0
  if (expr == NULL)
1696
0
    return -1;
1697
0
  if (IsA(expr, RowExpr))
1698
0
    return list_length(((RowExpr *) expr)->args);
1699
0
  if (IsA(expr, Var))
1700
0
  {
1701
0
    Var      *var = (Var *) expr;
1702
0
    AttrNumber  attnum = var->varattno;
1703
1704
0
    if (attnum > 0 && var->vartype == RECORDOID)
1705
0
    {
1706
0
      RangeTblEntry *rte;
1707
1708
0
      rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1709
0
      if (rte->rtekind == RTE_SUBQUERY)
1710
0
      {
1711
        /* Subselect-in-FROM: examine sub-select's output expr */
1712
0
        TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
1713
0
                          attnum);
1714
1715
0
        if (ste == NULL || ste->resjunk)
1716
0
          return -1;
1717
0
        expr = (Node *) ste->expr;
1718
0
        if (IsA(expr, RowExpr))
1719
0
          return list_length(((RowExpr *) expr)->args);
1720
0
      }
1721
0
    }
1722
0
  }
1723
0
  return -1;
1724
0
}
1725
1726
1727
/*
1728
 * transformSelectStmt -
1729
 *    transforms a Select Statement
1730
 *
1731
 * This function is also used to transform the source expression of a
1732
 * PLAssignStmt.  In that usage, passthru is non-NULL and we need to
1733
 * call transformPLAssignStmtTarget after the initial transformation of the
1734
 * SELECT's targetlist.  (We could generalize this into an arbitrary callback
1735
 * function, but for now that would just be more notation with no benefit.)
1736
 * All the rest is the same as a regular SelectStmt.
1737
 *
1738
 * Note: this covers only cases with no set operations and no VALUES lists;
1739
 * see below for the other cases.
1740
 */
1741
static Query *
1742
transformSelectStmt(ParseState *pstate, SelectStmt *stmt,
1743
          SelectStmtPassthrough *passthru)
1744
0
{
1745
0
  Query    *qry = makeNode(Query);
1746
0
  Node     *qual;
1747
0
  ListCell   *l;
1748
1749
0
  qry->commandType = CMD_SELECT;
1750
1751
  /* process the WITH clause independently of all else */
1752
0
  if (stmt->withClause)
1753
0
  {
1754
0
    qry->hasRecursive = stmt->withClause->recursive;
1755
0
    qry->cteList = transformWithClause(pstate, stmt->withClause);
1756
0
    qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1757
0
  }
1758
1759
  /* Complain if we get called from someplace where INTO is not allowed */
1760
0
  if (stmt->intoClause)
1761
0
    ereport(ERROR,
1762
0
        (errcode(ERRCODE_SYNTAX_ERROR),
1763
0
         errmsg("SELECT ... INTO is not allowed here"),
1764
0
         parser_errposition(pstate,
1765
0
                  exprLocation((Node *) stmt->intoClause))));
1766
1767
  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
1768
0
  pstate->p_locking_clause = stmt->lockingClause;
1769
1770
  /* make WINDOW info available for window functions, too */
1771
0
  pstate->p_windowdefs = stmt->windowClause;
1772
1773
  /* process the FROM clause */
1774
0
  transformFromClause(pstate, stmt->fromClause);
1775
1776
  /* transform targetlist */
1777
0
  qry->targetList = transformTargetList(pstate, stmt->targetList,
1778
0
                      EXPR_KIND_SELECT_TARGET);
1779
1780
  /*
1781
   * If we're within a PLAssignStmt, do further transformation of the
1782
   * targetlist; that has to happen before we consider sorting or grouping.
1783
   * Otherwise, mark column origins (which are useless in a PLAssignStmt).
1784
   */
1785
0
  if (passthru)
1786
0
    qry->targetList = transformPLAssignStmtTarget(pstate, qry->targetList,
1787
0
                            passthru);
1788
0
  else
1789
0
    markTargetListOrigins(pstate, qry->targetList);
1790
1791
  /* transform WHERE */
1792
0
  qual = transformWhereClause(pstate, stmt->whereClause,
1793
0
                EXPR_KIND_WHERE, "WHERE");
1794
1795
  /* initial processing of HAVING clause is much like WHERE clause */
1796
0
  qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
1797
0
                       EXPR_KIND_HAVING, "HAVING");
1798
1799
  /*
1800
   * Transform sorting/grouping stuff.  Do ORDER BY first because both
1801
   * transformGroupClause and transformDistinctClause need the results. Note
1802
   * that these functions can also change the targetList, so it's passed to
1803
   * them by reference.
1804
   */
1805
0
  qry->sortClause = transformSortClause(pstate,
1806
0
                      stmt->sortClause,
1807
0
                      &qry->targetList,
1808
0
                      EXPR_KIND_ORDER_BY,
1809
0
                      false /* allow SQL92 rules */ );
1810
1811
0
  qry->groupClause = transformGroupClause(pstate,
1812
0
                      stmt->groupClause,
1813
0
                      &qry->groupingSets,
1814
0
                      &qry->targetList,
1815
0
                      qry->sortClause,
1816
0
                      EXPR_KIND_GROUP_BY,
1817
0
                      false /* allow SQL92 rules */ );
1818
0
  qry->groupDistinct = stmt->groupDistinct;
1819
1820
0
  if (stmt->distinctClause == NIL)
1821
0
  {
1822
0
    qry->distinctClause = NIL;
1823
0
    qry->hasDistinctOn = false;
1824
0
  }
1825
0
  else if (linitial(stmt->distinctClause) == NULL)
1826
0
  {
1827
    /* We had SELECT DISTINCT */
1828
0
    qry->distinctClause = transformDistinctClause(pstate,
1829
0
                            &qry->targetList,
1830
0
                            qry->sortClause,
1831
0
                            false);
1832
0
    qry->hasDistinctOn = false;
1833
0
  }
1834
0
  else
1835
0
  {
1836
    /* We had SELECT DISTINCT ON */
1837
0
    qry->distinctClause = transformDistinctOnClause(pstate,
1838
0
                            stmt->distinctClause,
1839
0
                            &qry->targetList,
1840
0
                            qry->sortClause);
1841
0
    qry->hasDistinctOn = true;
1842
0
  }
1843
1844
  /* transform LIMIT */
1845
0
  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1846
0
                      EXPR_KIND_OFFSET, "OFFSET",
1847
0
                      stmt->limitOption);
1848
0
  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1849
0
                       EXPR_KIND_LIMIT, "LIMIT",
1850
0
                       stmt->limitOption);
1851
0
  qry->limitOption = stmt->limitOption;
1852
1853
  /* transform window clauses after we have seen all window functions */
1854
0
  qry->windowClause = transformWindowDefinitions(pstate,
1855
0
                           pstate->p_windowdefs,
1856
0
                           &qry->targetList);
1857
1858
  /* resolve any still-unresolved output columns as being type text */
1859
0
  if (pstate->p_resolve_unknowns)
1860
0
    resolveTargetListUnknowns(pstate, qry->targetList);
1861
1862
0
  qry->rtable = pstate->p_rtable;
1863
0
  qry->rteperminfos = pstate->p_rteperminfos;
1864
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
1865
1866
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
1867
0
  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1868
0
  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1869
0
  qry->hasAggs = pstate->p_hasAggs;
1870
1871
0
  foreach(l, stmt->lockingClause)
1872
0
  {
1873
0
    transformLockingClause(pstate, qry,
1874
0
                 (LockingClause *) lfirst(l), false);
1875
0
  }
1876
1877
0
  assign_query_collations(pstate, qry);
1878
1879
  /* this must be done after collations, for reliable comparison of exprs */
1880
0
  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1881
0
    parseCheckAggregates(pstate, qry);
1882
1883
0
  return qry;
1884
0
}
1885
1886
/*
1887
 * transformValuesClause -
1888
 *    transforms a VALUES clause that's being used as a standalone SELECT
1889
 *
1890
 * We build a Query containing a VALUES RTE, rather as if one had written
1891
 *      SELECT * FROM (VALUES ...) AS "*VALUES*"
1892
 */
1893
static Query *
1894
transformValuesClause(ParseState *pstate, SelectStmt *stmt)
1895
0
{
1896
0
  Query    *qry = makeNode(Query);
1897
0
  List     *exprsLists = NIL;
1898
0
  List     *coltypes = NIL;
1899
0
  List     *coltypmods = NIL;
1900
0
  List     *colcollations = NIL;
1901
0
  List    **colexprs = NULL;
1902
0
  int     sublist_length = -1;
1903
0
  bool    lateral = false;
1904
0
  ParseNamespaceItem *nsitem;
1905
0
  ListCell   *lc;
1906
0
  ListCell   *lc2;
1907
0
  int     i;
1908
1909
0
  qry->commandType = CMD_SELECT;
1910
1911
  /* Most SELECT stuff doesn't apply in a VALUES clause */
1912
0
  Assert(stmt->distinctClause == NIL);
1913
0
  Assert(stmt->intoClause == NULL);
1914
0
  Assert(stmt->targetList == NIL);
1915
0
  Assert(stmt->fromClause == NIL);
1916
0
  Assert(stmt->whereClause == NULL);
1917
0
  Assert(stmt->groupClause == NIL);
1918
0
  Assert(stmt->havingClause == NULL);
1919
0
  Assert(stmt->windowClause == NIL);
1920
0
  Assert(stmt->op == SETOP_NONE);
1921
1922
  /* process the WITH clause independently of all else */
1923
0
  if (stmt->withClause)
1924
0
  {
1925
0
    qry->hasRecursive = stmt->withClause->recursive;
1926
0
    qry->cteList = transformWithClause(pstate, stmt->withClause);
1927
0
    qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1928
0
  }
1929
1930
  /*
1931
   * For each row of VALUES, transform the raw expressions.
1932
   *
1933
   * Note that the intermediate representation we build is column-organized
1934
   * not row-organized.  That simplifies the type and collation processing
1935
   * below.
1936
   */
1937
0
  foreach(lc, stmt->valuesLists)
1938
0
  {
1939
0
    List     *sublist = (List *) lfirst(lc);
1940
1941
    /*
1942
     * Do basic expression transformation (same as a ROW() expr, but here
1943
     * we disallow SetToDefault)
1944
     */
1945
0
    sublist = transformExpressionList(pstate, sublist,
1946
0
                      EXPR_KIND_VALUES, false);
1947
1948
    /*
1949
     * All the sublists must be the same length, *after* transformation
1950
     * (which might expand '*' into multiple items).  The VALUES RTE can't
1951
     * handle anything different.
1952
     */
1953
0
    if (sublist_length < 0)
1954
0
    {
1955
      /* Remember post-transformation length of first sublist */
1956
0
      sublist_length = list_length(sublist);
1957
      /* and allocate array for per-column lists */
1958
0
      colexprs = (List **) palloc0(sublist_length * sizeof(List *));
1959
0
    }
1960
0
    else if (sublist_length != list_length(sublist))
1961
0
    {
1962
0
      ereport(ERROR,
1963
0
          (errcode(ERRCODE_SYNTAX_ERROR),
1964
0
           errmsg("VALUES lists must all be the same length"),
1965
0
           parser_errposition(pstate,
1966
0
                    exprLocation((Node *) sublist))));
1967
0
    }
1968
1969
    /* Build per-column expression lists */
1970
0
    i = 0;
1971
0
    foreach(lc2, sublist)
1972
0
    {
1973
0
      Node     *col = (Node *) lfirst(lc2);
1974
1975
0
      colexprs[i] = lappend(colexprs[i], col);
1976
0
      i++;
1977
0
    }
1978
1979
    /* Release sub-list's cells to save memory */
1980
0
    list_free(sublist);
1981
1982
    /* Prepare an exprsLists element for this row */
1983
0
    exprsLists = lappend(exprsLists, NIL);
1984
0
  }
1985
1986
  /*
1987
   * Now resolve the common types of the columns, and coerce everything to
1988
   * those types.  Then identify the common typmod and common collation, if
1989
   * any, of each column.
1990
   *
1991
   * We must do collation processing now because (1) assign_query_collations
1992
   * doesn't process rangetable entries, and (2) we need to label the VALUES
1993
   * RTE with column collations for use in the outer query.  We don't
1994
   * consider conflict of implicit collations to be an error here; instead
1995
   * the column will just show InvalidOid as its collation, and you'll get a
1996
   * failure later if that results in failure to resolve a collation.
1997
   *
1998
   * Note we modify the per-column expression lists in-place.
1999
   */
2000
0
  for (i = 0; i < sublist_length; i++)
2001
0
  {
2002
0
    Oid     coltype;
2003
0
    int32   coltypmod;
2004
0
    Oid     colcoll;
2005
2006
0
    coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
2007
2008
0
    foreach(lc, colexprs[i])
2009
0
    {
2010
0
      Node     *col = (Node *) lfirst(lc);
2011
2012
0
      col = coerce_to_common_type(pstate, col, coltype, "VALUES");
2013
0
      lfirst(lc) = col;
2014
0
    }
2015
2016
0
    coltypmod = select_common_typmod(pstate, colexprs[i], coltype);
2017
0
    colcoll = select_common_collation(pstate, colexprs[i], true);
2018
2019
0
    coltypes = lappend_oid(coltypes, coltype);
2020
0
    coltypmods = lappend_int(coltypmods, coltypmod);
2021
0
    colcollations = lappend_oid(colcollations, colcoll);
2022
0
  }
2023
2024
  /*
2025
   * Finally, rearrange the coerced expressions into row-organized lists.
2026
   */
2027
0
  for (i = 0; i < sublist_length; i++)
2028
0
  {
2029
0
    forboth(lc, colexprs[i], lc2, exprsLists)
2030
0
    {
2031
0
      Node     *col = (Node *) lfirst(lc);
2032
0
      List     *sublist = lfirst(lc2);
2033
2034
0
      sublist = lappend(sublist, col);
2035
0
      lfirst(lc2) = sublist;
2036
0
    }
2037
0
    list_free(colexprs[i]);
2038
0
  }
2039
2040
  /*
2041
   * Ordinarily there can't be any current-level Vars in the expression
2042
   * lists, because the namespace was empty ... but if we're inside CREATE
2043
   * RULE, then NEW/OLD references might appear.  In that case we have to
2044
   * mark the VALUES RTE as LATERAL.
2045
   */
2046
0
  if (pstate->p_rtable != NIL &&
2047
0
    contain_vars_of_level((Node *) exprsLists, 0))
2048
0
    lateral = true;
2049
2050
  /*
2051
   * Generate the VALUES RTE
2052
   */
2053
0
  nsitem = addRangeTableEntryForValues(pstate, exprsLists,
2054
0
                     coltypes, coltypmods, colcollations,
2055
0
                     NULL, lateral, true);
2056
0
  addNSItemToQuery(pstate, nsitem, true, true, true);
2057
2058
  /*
2059
   * Generate a targetlist as though expanding "*"
2060
   */
2061
0
  Assert(pstate->p_next_resno == 1);
2062
0
  qry->targetList = expandNSItemAttrs(pstate, nsitem, 0, true, -1);
2063
2064
  /*
2065
   * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a
2066
   * VALUES, so cope.
2067
   */
2068
0
  qry->sortClause = transformSortClause(pstate,
2069
0
                      stmt->sortClause,
2070
0
                      &qry->targetList,
2071
0
                      EXPR_KIND_ORDER_BY,
2072
0
                      false /* allow SQL92 rules */ );
2073
2074
0
  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
2075
0
                      EXPR_KIND_OFFSET, "OFFSET",
2076
0
                      stmt->limitOption);
2077
0
  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
2078
0
                       EXPR_KIND_LIMIT, "LIMIT",
2079
0
                       stmt->limitOption);
2080
0
  qry->limitOption = stmt->limitOption;
2081
2082
0
  if (stmt->lockingClause)
2083
0
    ereport(ERROR,
2084
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2085
    /*------
2086
      translator: %s is a SQL row locking clause such as FOR UPDATE */
2087
0
         errmsg("%s cannot be applied to VALUES",
2088
0
            LCS_asString(((LockingClause *)
2089
0
                    linitial(stmt->lockingClause))->strength))));
2090
2091
0
  qry->rtable = pstate->p_rtable;
2092
0
  qry->rteperminfos = pstate->p_rteperminfos;
2093
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2094
2095
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
2096
2097
0
  assign_query_collations(pstate, qry);
2098
2099
0
  return qry;
2100
0
}
2101
2102
/*
2103
 * transformSetOperationStmt -
2104
 *    transforms a set-operations tree
2105
 *
2106
 * A set-operation tree is just a SELECT, but with UNION/INTERSECT/EXCEPT
2107
 * structure to it.  We must transform each leaf SELECT and build up a top-
2108
 * level Query that contains the leaf SELECTs as subqueries in its rangetable.
2109
 * The tree of set operations is converted into the setOperations field of
2110
 * the top-level Query.
2111
 */
2112
static Query *
2113
transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2114
0
{
2115
0
  Query    *qry = makeNode(Query);
2116
0
  SelectStmt *leftmostSelect;
2117
0
  int     leftmostRTI;
2118
0
  Query    *leftmostQuery;
2119
0
  SetOperationStmt *sostmt;
2120
0
  List     *sortClause;
2121
0
  Node     *limitOffset;
2122
0
  Node     *limitCount;
2123
0
  List     *lockingClause;
2124
0
  WithClause *withClause;
2125
0
  Node     *node;
2126
0
  ListCell   *left_tlist,
2127
0
         *lct,
2128
0
         *lcm,
2129
0
         *lcc,
2130
0
         *l;
2131
0
  List     *targetvars,
2132
0
         *targetnames,
2133
0
         *sv_namespace;
2134
0
  int     sv_rtable_length;
2135
0
  ParseNamespaceItem *jnsitem;
2136
0
  ParseNamespaceColumn *sortnscolumns;
2137
0
  int     sortcolindex;
2138
0
  int     tllen;
2139
2140
0
  qry->commandType = CMD_SELECT;
2141
2142
  /*
2143
   * Find leftmost leaf SelectStmt.  We currently only need to do this in
2144
   * order to deliver a suitable error message if there's an INTO clause
2145
   * there, implying the set-op tree is in a context that doesn't allow
2146
   * INTO.  (transformSetOperationTree would throw error anyway, but it
2147
   * seems worth the trouble to throw a different error for non-leftmost
2148
   * INTO, so we produce that error in transformSetOperationTree.)
2149
   */
2150
0
  leftmostSelect = stmt->larg;
2151
0
  while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
2152
0
    leftmostSelect = leftmostSelect->larg;
2153
0
  Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
2154
0
       leftmostSelect->larg == NULL);
2155
0
  if (leftmostSelect->intoClause)
2156
0
    ereport(ERROR,
2157
0
        (errcode(ERRCODE_SYNTAX_ERROR),
2158
0
         errmsg("SELECT ... INTO is not allowed here"),
2159
0
         parser_errposition(pstate,
2160
0
                  exprLocation((Node *) leftmostSelect->intoClause))));
2161
2162
  /*
2163
   * We need to extract ORDER BY and other top-level clauses here and not
2164
   * let transformSetOperationTree() see them --- else it'll just recurse
2165
   * right back here!
2166
   */
2167
0
  sortClause = stmt->sortClause;
2168
0
  limitOffset = stmt->limitOffset;
2169
0
  limitCount = stmt->limitCount;
2170
0
  lockingClause = stmt->lockingClause;
2171
0
  withClause = stmt->withClause;
2172
2173
0
  stmt->sortClause = NIL;
2174
0
  stmt->limitOffset = NULL;
2175
0
  stmt->limitCount = NULL;
2176
0
  stmt->lockingClause = NIL;
2177
0
  stmt->withClause = NULL;
2178
2179
  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
2180
0
  if (lockingClause)
2181
0
    ereport(ERROR,
2182
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2183
    /*------
2184
      translator: %s is a SQL row locking clause such as FOR UPDATE */
2185
0
         errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2186
0
            LCS_asString(((LockingClause *)
2187
0
                    linitial(lockingClause))->strength))));
2188
2189
  /* Process the WITH clause independently of all else */
2190
0
  if (withClause)
2191
0
  {
2192
0
    qry->hasRecursive = withClause->recursive;
2193
0
    qry->cteList = transformWithClause(pstate, withClause);
2194
0
    qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2195
0
  }
2196
2197
  /*
2198
   * Recursively transform the components of the tree.
2199
   */
2200
0
  sostmt = castNode(SetOperationStmt,
2201
0
            transformSetOperationTree(pstate, stmt, true, NULL));
2202
0
  Assert(sostmt);
2203
0
  qry->setOperations = (Node *) sostmt;
2204
2205
  /*
2206
   * Re-find leftmost SELECT (now it's a sub-query in rangetable)
2207
   */
2208
0
  node = sostmt->larg;
2209
0
  while (node && IsA(node, SetOperationStmt))
2210
0
    node = ((SetOperationStmt *) node)->larg;
2211
0
  Assert(node && IsA(node, RangeTblRef));
2212
0
  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2213
0
  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2214
0
  Assert(leftmostQuery != NULL);
2215
2216
  /*
2217
   * Generate dummy targetlist for outer query using column names of
2218
   * leftmost select and common datatypes/collations of topmost set
2219
   * operation.  Also make lists of the dummy vars and their names for use
2220
   * in parsing ORDER BY.
2221
   *
2222
   * Note: we use leftmostRTI as the varno of the dummy variables. It
2223
   * shouldn't matter too much which RT index they have, as long as they
2224
   * have one that corresponds to a real RT entry; else funny things may
2225
   * happen when the tree is mashed by rule rewriting.
2226
   */
2227
0
  qry->targetList = NIL;
2228
0
  targetvars = NIL;
2229
0
  targetnames = NIL;
2230
0
  sortnscolumns = (ParseNamespaceColumn *)
2231
0
    palloc0(list_length(sostmt->colTypes) * sizeof(ParseNamespaceColumn));
2232
0
  sortcolindex = 0;
2233
2234
0
  forfour(lct, sostmt->colTypes,
2235
0
      lcm, sostmt->colTypmods,
2236
0
      lcc, sostmt->colCollations,
2237
0
      left_tlist, leftmostQuery->targetList)
2238
0
  {
2239
0
    Oid     colType = lfirst_oid(lct);
2240
0
    int32   colTypmod = lfirst_int(lcm);
2241
0
    Oid     colCollation = lfirst_oid(lcc);
2242
0
    TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2243
0
    char     *colName;
2244
0
    TargetEntry *tle;
2245
0
    Var      *var;
2246
2247
0
    Assert(!lefttle->resjunk);
2248
0
    colName = pstrdup(lefttle->resname);
2249
0
    var = makeVar(leftmostRTI,
2250
0
            lefttle->resno,
2251
0
            colType,
2252
0
            colTypmod,
2253
0
            colCollation,
2254
0
            0);
2255
0
    var->location = exprLocation((Node *) lefttle->expr);
2256
0
    tle = makeTargetEntry((Expr *) var,
2257
0
                (AttrNumber) pstate->p_next_resno++,
2258
0
                colName,
2259
0
                false);
2260
0
    qry->targetList = lappend(qry->targetList, tle);
2261
0
    targetvars = lappend(targetvars, var);
2262
0
    targetnames = lappend(targetnames, makeString(colName));
2263
0
    sortnscolumns[sortcolindex].p_varno = leftmostRTI;
2264
0
    sortnscolumns[sortcolindex].p_varattno = lefttle->resno;
2265
0
    sortnscolumns[sortcolindex].p_vartype = colType;
2266
0
    sortnscolumns[sortcolindex].p_vartypmod = colTypmod;
2267
0
    sortnscolumns[sortcolindex].p_varcollid = colCollation;
2268
0
    sortnscolumns[sortcolindex].p_varnosyn = leftmostRTI;
2269
0
    sortnscolumns[sortcolindex].p_varattnosyn = lefttle->resno;
2270
0
    sortcolindex++;
2271
0
  }
2272
2273
  /*
2274
   * As a first step towards supporting sort clauses that are expressions
2275
   * using the output columns, generate a namespace entry that makes the
2276
   * output columns visible.  A Join RTE node is handy for this, since we
2277
   * can easily control the Vars generated upon matches.
2278
   *
2279
   * Note: we don't yet do anything useful with such cases, but at least
2280
   * "ORDER BY upper(foo)" will draw the right error message rather than
2281
   * "foo not found".
2282
   */
2283
0
  sv_rtable_length = list_length(pstate->p_rtable);
2284
2285
0
  jnsitem = addRangeTableEntryForJoin(pstate,
2286
0
                    targetnames,
2287
0
                    sortnscolumns,
2288
0
                    JOIN_INNER,
2289
0
                    0,
2290
0
                    targetvars,
2291
0
                    NIL,
2292
0
                    NIL,
2293
0
                    NULL,
2294
0
                    NULL,
2295
0
                    false);
2296
2297
0
  sv_namespace = pstate->p_namespace;
2298
0
  pstate->p_namespace = NIL;
2299
2300
  /* add jnsitem to column namespace only */
2301
0
  addNSItemToQuery(pstate, jnsitem, false, false, true);
2302
2303
  /*
2304
   * For now, we don't support resjunk sort clauses on the output of a
2305
   * setOperation tree --- you can only use the SQL92-spec options of
2306
   * selecting an output column by name or number.  Enforce by checking that
2307
   * transformSortClause doesn't add any items to tlist.  Note, if changing
2308
   * this, add_setop_child_rel_equivalences() will need to be updated.
2309
   */
2310
0
  tllen = list_length(qry->targetList);
2311
2312
0
  qry->sortClause = transformSortClause(pstate,
2313
0
                      sortClause,
2314
0
                      &qry->targetList,
2315
0
                      EXPR_KIND_ORDER_BY,
2316
0
                      false /* allow SQL92 rules */ );
2317
2318
  /* restore namespace, remove join RTE from rtable */
2319
0
  pstate->p_namespace = sv_namespace;
2320
0
  pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
2321
2322
0
  if (tllen != list_length(qry->targetList))
2323
0
    ereport(ERROR,
2324
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2325
0
         errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"),
2326
0
         errdetail("Only result column names can be used, not expressions or functions."),
2327
0
         errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."),
2328
0
         parser_errposition(pstate,
2329
0
                  exprLocation(list_nth(qry->targetList, tllen)))));
2330
2331
0
  qry->limitOffset = transformLimitClause(pstate, limitOffset,
2332
0
                      EXPR_KIND_OFFSET, "OFFSET",
2333
0
                      stmt->limitOption);
2334
0
  qry->limitCount = transformLimitClause(pstate, limitCount,
2335
0
                       EXPR_KIND_LIMIT, "LIMIT",
2336
0
                       stmt->limitOption);
2337
0
  qry->limitOption = stmt->limitOption;
2338
2339
0
  qry->rtable = pstate->p_rtable;
2340
0
  qry->rteperminfos = pstate->p_rteperminfos;
2341
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2342
2343
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
2344
0
  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2345
0
  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2346
0
  qry->hasAggs = pstate->p_hasAggs;
2347
2348
0
  foreach(l, lockingClause)
2349
0
  {
2350
0
    transformLockingClause(pstate, qry,
2351
0
                 (LockingClause *) lfirst(l), false);
2352
0
  }
2353
2354
0
  assign_query_collations(pstate, qry);
2355
2356
  /* this must be done after collations, for reliable comparison of exprs */
2357
0
  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
2358
0
    parseCheckAggregates(pstate, qry);
2359
2360
0
  return qry;
2361
0
}
2362
2363
/*
2364
 * Make a SortGroupClause node for a SetOperationStmt's groupClauses
2365
 *
2366
 * If require_hash is true, the caller is indicating that they need hash
2367
 * support or they will fail.  So look extra hard for hash support.
2368
 */
2369
SortGroupClause *
2370
makeSortGroupClauseForSetOp(Oid rescoltype, bool require_hash)
2371
0
{
2372
0
  SortGroupClause *grpcl = makeNode(SortGroupClause);
2373
0
  Oid     sortop;
2374
0
  Oid     eqop;
2375
0
  bool    hashable;
2376
2377
  /* determine the eqop and optional sortop */
2378
0
  get_sort_group_operators(rescoltype,
2379
0
               false, true, false,
2380
0
               &sortop, &eqop, NULL,
2381
0
               &hashable);
2382
2383
  /*
2384
   * The type cache doesn't believe that record is hashable (see
2385
   * cache_record_field_properties()), but if the caller really needs hash
2386
   * support, we can assume it does.  Worst case, if any components of the
2387
   * record don't support hashing, we will fail at execution.
2388
   */
2389
0
  if (require_hash && (rescoltype == RECORDOID || rescoltype == RECORDARRAYOID))
2390
0
    hashable = true;
2391
2392
  /* we don't have a tlist yet, so can't assign sortgrouprefs */
2393
0
  grpcl->tleSortGroupRef = 0;
2394
0
  grpcl->eqop = eqop;
2395
0
  grpcl->sortop = sortop;
2396
0
  grpcl->reverse_sort = false;  /* Sort-op is "less than", or InvalidOid */
2397
0
  grpcl->nulls_first = false; /* OK with or without sortop */
2398
0
  grpcl->hashable = hashable;
2399
2400
0
  return grpcl;
2401
0
}
2402
2403
/*
2404
 * transformSetOperationTree
2405
 *    Recursively transform leaves and internal nodes of a set-op tree
2406
 *
2407
 * In addition to returning the transformed node, if targetlist isn't NULL
2408
 * then we return a list of its non-resjunk TargetEntry nodes.  For a leaf
2409
 * set-op node these are the actual targetlist entries; otherwise they are
2410
 * dummy entries created to carry the type, typmod, collation, and location
2411
 * (for error messages) of each output column of the set-op node.  This info
2412
 * is needed only during the internal recursion of this function, so outside
2413
 * callers pass NULL for targetlist.  Note: the reason for passing the
2414
 * actual targetlist entries of a leaf node is so that upper levels can
2415
 * replace UNKNOWN Consts with properly-coerced constants.
2416
 */
2417
static Node *
2418
transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
2419
              bool isTopLevel, List **targetlist)
2420
0
{
2421
0
  bool    isLeaf;
2422
2423
0
  Assert(stmt && IsA(stmt, SelectStmt));
2424
2425
  /* Guard against stack overflow due to overly complex set-expressions */
2426
0
  check_stack_depth();
2427
2428
  /*
2429
   * Validity-check both leaf and internal SELECTs for disallowed ops.
2430
   */
2431
0
  if (stmt->intoClause)
2432
0
    ereport(ERROR,
2433
0
        (errcode(ERRCODE_SYNTAX_ERROR),
2434
0
         errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"),
2435
0
         parser_errposition(pstate,
2436
0
                  exprLocation((Node *) stmt->intoClause))));
2437
2438
  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
2439
0
  if (stmt->lockingClause)
2440
0
    ereport(ERROR,
2441
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2442
    /*------
2443
      translator: %s is a SQL row locking clause such as FOR UPDATE */
2444
0
         errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2445
0
            LCS_asString(((LockingClause *)
2446
0
                    linitial(stmt->lockingClause))->strength))));
2447
2448
  /*
2449
   * If an internal node of a set-op tree has ORDER BY, LIMIT, FOR UPDATE,
2450
   * or WITH clauses attached, we need to treat it like a leaf node to
2451
   * generate an independent sub-Query tree.  Otherwise, it can be
2452
   * represented by a SetOperationStmt node underneath the parent Query.
2453
   */
2454
0
  if (stmt->op == SETOP_NONE)
2455
0
  {
2456
0
    Assert(stmt->larg == NULL && stmt->rarg == NULL);
2457
0
    isLeaf = true;
2458
0
  }
2459
0
  else
2460
0
  {
2461
0
    Assert(stmt->larg != NULL && stmt->rarg != NULL);
2462
0
    if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
2463
0
      stmt->lockingClause || stmt->withClause)
2464
0
      isLeaf = true;
2465
0
    else
2466
0
      isLeaf = false;
2467
0
  }
2468
2469
0
  if (isLeaf)
2470
0
  {
2471
    /* Process leaf SELECT */
2472
0
    Query    *selectQuery;
2473
0
    ParseNamespaceItem *nsitem;
2474
0
    RangeTblRef *rtr;
2475
2476
    /*
2477
     * Transform SelectStmt into a Query.
2478
     *
2479
     * This works the same as SELECT transformation normally would, except
2480
     * that we prevent resolving unknown-type outputs as TEXT.  This does
2481
     * not change the subquery's semantics since if the column type
2482
     * matters semantically, it would have been resolved to something else
2483
     * anyway.  Doing this lets us resolve such outputs using
2484
     * select_common_type(), below.
2485
     *
2486
     * Note: previously transformed sub-queries don't affect the parsing
2487
     * of this sub-query, because they are not in the toplevel pstate's
2488
     * namespace list.
2489
     */
2490
0
    selectQuery = parse_sub_analyze((Node *) stmt, pstate,
2491
0
                    NULL, false, false);
2492
2493
    /*
2494
     * Check for bogus references to Vars on the current query level (but
2495
     * upper-level references are okay). Normally this can't happen
2496
     * because the namespace will be empty, but it could happen if we are
2497
     * inside a rule.
2498
     */
2499
0
    if (pstate->p_namespace)
2500
0
    {
2501
0
      if (contain_vars_of_level((Node *) selectQuery, 1))
2502
0
        ereport(ERROR,
2503
0
            (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2504
0
             errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"),
2505
0
             parser_errposition(pstate,
2506
0
                      locate_var_of_level((Node *) selectQuery, 1))));
2507
0
    }
2508
2509
    /*
2510
     * Extract a list of the non-junk TLEs for upper-level processing.
2511
     */
2512
0
    if (targetlist)
2513
0
    {
2514
0
      ListCell   *tl;
2515
2516
0
      *targetlist = NIL;
2517
0
      foreach(tl, selectQuery->targetList)
2518
0
      {
2519
0
        TargetEntry *tle = (TargetEntry *) lfirst(tl);
2520
2521
0
        if (!tle->resjunk)
2522
0
          *targetlist = lappend(*targetlist, tle);
2523
0
      }
2524
0
    }
2525
2526
    /*
2527
     * Make the leaf query be a subquery in the top-level rangetable.
2528
     */
2529
0
    nsitem = addRangeTableEntryForSubquery(pstate,
2530
0
                         selectQuery,
2531
0
                         NULL,
2532
0
                         false,
2533
0
                         false);
2534
2535
    /*
2536
     * Return a RangeTblRef to replace the SelectStmt in the set-op tree.
2537
     */
2538
0
    rtr = makeNode(RangeTblRef);
2539
0
    rtr->rtindex = nsitem->p_rtindex;
2540
0
    return (Node *) rtr;
2541
0
  }
2542
0
  else
2543
0
  {
2544
    /* Process an internal node (set operation node) */
2545
0
    SetOperationStmt *op = makeNode(SetOperationStmt);
2546
0
    List     *ltargetlist;
2547
0
    List     *rtargetlist;
2548
0
    const char *context;
2549
0
    bool    recursive = (pstate->p_parent_cte &&
2550
0
                 pstate->p_parent_cte->cterecursive);
2551
2552
0
    context = (stmt->op == SETOP_UNION ? "UNION" :
2553
0
           (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
2554
0
          "EXCEPT"));
2555
2556
0
    op->op = stmt->op;
2557
0
    op->all = stmt->all;
2558
2559
    /*
2560
     * Recursively transform the left child node.
2561
     */
2562
0
    op->larg = transformSetOperationTree(pstate, stmt->larg,
2563
0
                       false,
2564
0
                       &ltargetlist);
2565
2566
    /*
2567
     * If we are processing a recursive union query, now is the time to
2568
     * examine the non-recursive term's output columns and mark the
2569
     * containing CTE as having those result columns.  We should do this
2570
     * only at the topmost setop of the CTE, of course.
2571
     */
2572
0
    if (isTopLevel && recursive)
2573
0
      determineRecursiveColTypes(pstate, op->larg, ltargetlist);
2574
2575
    /*
2576
     * Recursively transform the right child node.
2577
     */
2578
0
    op->rarg = transformSetOperationTree(pstate, stmt->rarg,
2579
0
                       false,
2580
0
                       &rtargetlist);
2581
2582
0
    constructSetOpTargetlist(pstate, op, ltargetlist, rtargetlist, targetlist,
2583
0
                 context, recursive);
2584
2585
0
    return (Node *) op;
2586
0
  }
2587
0
}
2588
2589
/*
2590
 * constructSetOpTargetlist
2591
 *    Compute the types, typmods and collations of the columns in the target
2592
 *    list of the given set operation.
2593
 *
2594
 * For every pair of columns in the targetlists of the children, compute the
2595
 * common type, typmod, and collation representing the output (UNION) column.
2596
 * If targetlist is not NULL, also build the dummy output targetlist
2597
 * containing non-resjunk output columns.  The values are stored into the
2598
 * given SetOperationStmt node.  context is a string for error messages
2599
 * ("UNION" etc.).  recursive is true if it is a recursive union.
2600
 */
2601
void
2602
constructSetOpTargetlist(ParseState *pstate, SetOperationStmt *op,
2603
             const List *ltargetlist, const List *rtargetlist,
2604
             List **targetlist, const char *context, bool recursive)
2605
0
{
2606
0
  ListCell   *ltl;
2607
0
  ListCell   *rtl;
2608
2609
  /*
2610
   * Verify that the two children have the same number of non-junk columns,
2611
   * and determine the types of the merged output columns.
2612
   */
2613
0
  if (list_length(ltargetlist) != list_length(rtargetlist))
2614
0
    ereport(ERROR,
2615
0
        (errcode(ERRCODE_SYNTAX_ERROR),
2616
0
         errmsg("each %s query must have the same number of columns",
2617
0
            context),
2618
0
         parser_errposition(pstate,
2619
0
                  exprLocation((const Node *) rtargetlist))));
2620
2621
0
  if (targetlist)
2622
0
    *targetlist = NIL;
2623
0
  op->colTypes = NIL;
2624
0
  op->colTypmods = NIL;
2625
0
  op->colCollations = NIL;
2626
0
  op->groupClauses = NIL;
2627
2628
0
  forboth(ltl, ltargetlist, rtl, rtargetlist)
2629
0
  {
2630
0
    TargetEntry *ltle = (TargetEntry *) lfirst(ltl);
2631
0
    TargetEntry *rtle = (TargetEntry *) lfirst(rtl);
2632
0
    Node     *lcolnode = (Node *) ltle->expr;
2633
0
    Node     *rcolnode = (Node *) rtle->expr;
2634
0
    Oid     lcoltype = exprType(lcolnode);
2635
0
    Oid     rcoltype = exprType(rcolnode);
2636
0
    Node     *bestexpr;
2637
0
    int     bestlocation;
2638
0
    Oid     rescoltype;
2639
0
    int32   rescoltypmod;
2640
0
    Oid     rescolcoll;
2641
2642
    /* select common type, same as CASE et al */
2643
0
    rescoltype = select_common_type(pstate,
2644
0
                    list_make2(lcolnode, rcolnode),
2645
0
                    context,
2646
0
                    &bestexpr);
2647
0
    bestlocation = exprLocation(bestexpr);
2648
2649
    /*
2650
     * Verify the coercions are actually possible.  If not, we'd fail
2651
     * later anyway, but we want to fail now while we have sufficient
2652
     * context to produce an error cursor position.
2653
     *
2654
     * For all non-UNKNOWN-type cases, we verify coercibility but we don't
2655
     * modify the child's expression, for fear of changing the child
2656
     * query's semantics.
2657
     *
2658
     * If a child expression is an UNKNOWN-type Const or Param, we want to
2659
     * replace it with the coerced expression.  This can only happen when
2660
     * the child is a leaf set-op node.  It's safe to replace the
2661
     * expression because if the child query's semantics depended on the
2662
     * type of this output column, it'd have already coerced the UNKNOWN
2663
     * to something else.  We want to do this because (a) we want to
2664
     * verify that a Const is valid for the target type, or resolve the
2665
     * actual type of an UNKNOWN Param, and (b) we want to avoid
2666
     * unnecessary discrepancies between the output type of the child
2667
     * query and the resolved target type. Such a discrepancy would
2668
     * disable optimization in the planner.
2669
     *
2670
     * If it's some other UNKNOWN-type node, eg a Var, we do nothing
2671
     * (knowing that coerce_to_common_type would fail).  The planner is
2672
     * sometimes able to fold an UNKNOWN Var to a constant before it has
2673
     * to coerce the type, so failing now would just break cases that
2674
     * might work.
2675
     */
2676
0
    if (lcoltype != UNKNOWNOID)
2677
0
      lcolnode = coerce_to_common_type(pstate, lcolnode,
2678
0
                       rescoltype, context);
2679
0
    else if (IsA(lcolnode, Const) ||
2680
0
         IsA(lcolnode, Param))
2681
0
    {
2682
0
      lcolnode = coerce_to_common_type(pstate, lcolnode,
2683
0
                       rescoltype, context);
2684
0
      ltle->expr = (Expr *) lcolnode;
2685
0
    }
2686
2687
0
    if (rcoltype != UNKNOWNOID)
2688
0
      rcolnode = coerce_to_common_type(pstate, rcolnode,
2689
0
                       rescoltype, context);
2690
0
    else if (IsA(rcolnode, Const) ||
2691
0
         IsA(rcolnode, Param))
2692
0
    {
2693
0
      rcolnode = coerce_to_common_type(pstate, rcolnode,
2694
0
                       rescoltype, context);
2695
0
      rtle->expr = (Expr *) rcolnode;
2696
0
    }
2697
2698
0
    rescoltypmod = select_common_typmod(pstate,
2699
0
                      list_make2(lcolnode, rcolnode),
2700
0
                      rescoltype);
2701
2702
    /*
2703
     * Select common collation.  A common collation is required for all
2704
     * set operators except UNION ALL; see SQL:2008 7.13 <query
2705
     * expression> Syntax Rule 15c.  (If we fail to identify a common
2706
     * collation for a UNION ALL column, the colCollations element will be
2707
     * set to InvalidOid, which may result in a runtime error if something
2708
     * at a higher query level wants to use the column's collation.)
2709
     */
2710
0
    rescolcoll = select_common_collation(pstate,
2711
0
                       list_make2(lcolnode, rcolnode),
2712
0
                       (op->op == SETOP_UNION && op->all));
2713
2714
    /* emit results */
2715
0
    op->colTypes = lappend_oid(op->colTypes, rescoltype);
2716
0
    op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
2717
0
    op->colCollations = lappend_oid(op->colCollations, rescolcoll);
2718
2719
    /*
2720
     * For all cases except UNION ALL, identify the grouping operators
2721
     * (and, if available, sorting operators) that will be used to
2722
     * eliminate duplicates.
2723
     */
2724
0
    if (op->op != SETOP_UNION || !op->all)
2725
0
    {
2726
0
      ParseCallbackState pcbstate;
2727
2728
0
      setup_parser_errposition_callback(&pcbstate, pstate,
2729
0
                        bestlocation);
2730
2731
      /* If it's a recursive union, we need to require hashing support. */
2732
0
      op->groupClauses = lappend(op->groupClauses,
2733
0
                     makeSortGroupClauseForSetOp(rescoltype, recursive));
2734
2735
0
      cancel_parser_errposition_callback(&pcbstate);
2736
0
    }
2737
2738
    /*
2739
     * Construct a dummy tlist entry to return.  We use a SetToDefault
2740
     * node for the expression, since it carries exactly the fields
2741
     * needed, but any other expression node type would do as well.
2742
     */
2743
0
    if (targetlist)
2744
0
    {
2745
0
      SetToDefault *rescolnode = makeNode(SetToDefault);
2746
0
      TargetEntry *restle;
2747
2748
0
      rescolnode->typeId = rescoltype;
2749
0
      rescolnode->typeMod = rescoltypmod;
2750
0
      rescolnode->collation = rescolcoll;
2751
0
      rescolnode->location = bestlocation;
2752
0
      restle = makeTargetEntry((Expr *) rescolnode,
2753
0
                   0, /* no need to set resno */
2754
0
                   NULL,
2755
0
                   false);
2756
0
      *targetlist = lappend(*targetlist, restle);
2757
0
    }
2758
0
  }
2759
0
}
2760
2761
/*
2762
 * Process the outputs of the non-recursive term of a recursive union
2763
 * to set up the parent CTE's columns
2764
 */
2765
static void
2766
determineRecursiveColTypes(ParseState *pstate, Node *larg, List *nrtargetlist)
2767
0
{
2768
0
  Node     *node;
2769
0
  int     leftmostRTI;
2770
0
  Query    *leftmostQuery;
2771
0
  List     *targetList;
2772
0
  ListCell   *left_tlist;
2773
0
  ListCell   *nrtl;
2774
0
  int     next_resno;
2775
2776
  /*
2777
   * Find leftmost leaf SELECT
2778
   */
2779
0
  node = larg;
2780
0
  while (node && IsA(node, SetOperationStmt))
2781
0
    node = ((SetOperationStmt *) node)->larg;
2782
0
  Assert(node && IsA(node, RangeTblRef));
2783
0
  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2784
0
  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2785
0
  Assert(leftmostQuery != NULL);
2786
2787
  /*
2788
   * Generate dummy targetlist using column names of leftmost select and
2789
   * dummy result expressions of the non-recursive term.
2790
   */
2791
0
  targetList = NIL;
2792
0
  next_resno = 1;
2793
2794
0
  forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
2795
0
  {
2796
0
    TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2797
0
    TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2798
0
    char     *colName;
2799
0
    TargetEntry *tle;
2800
2801
0
    Assert(!lefttle->resjunk);
2802
0
    colName = pstrdup(lefttle->resname);
2803
0
    tle = makeTargetEntry(nrtle->expr,
2804
0
                next_resno++,
2805
0
                colName,
2806
0
                false);
2807
0
    targetList = lappend(targetList, tle);
2808
0
  }
2809
2810
  /* Now build CTE's output column info using dummy targetlist */
2811
0
  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2812
0
}
2813
2814
2815
/*
2816
 * transformReturnStmt -
2817
 *    transforms a return statement
2818
 */
2819
static Query *
2820
transformReturnStmt(ParseState *pstate, ReturnStmt *stmt)
2821
0
{
2822
0
  Query    *qry = makeNode(Query);
2823
2824
0
  qry->commandType = CMD_SELECT;
2825
0
  qry->isReturn = true;
2826
2827
0
  qry->targetList = list_make1(makeTargetEntry((Expr *) transformExpr(pstate, stmt->returnval, EXPR_KIND_SELECT_TARGET),
2828
0
                         1, NULL, false));
2829
2830
0
  if (pstate->p_resolve_unknowns)
2831
0
    resolveTargetListUnknowns(pstate, qry->targetList);
2832
0
  qry->rtable = pstate->p_rtable;
2833
0
  qry->rteperminfos = pstate->p_rteperminfos;
2834
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2835
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
2836
0
  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2837
0
  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2838
0
  qry->hasAggs = pstate->p_hasAggs;
2839
2840
0
  assign_query_collations(pstate, qry);
2841
2842
0
  return qry;
2843
0
}
2844
2845
2846
/*
2847
 * transformUpdateStmt -
2848
 *    transforms an update statement
2849
 */
2850
static Query *
2851
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
2852
0
{
2853
0
  Query    *qry = makeNode(Query);
2854
0
  ParseNamespaceItem *nsitem;
2855
0
  Node     *qual;
2856
2857
0
  qry->commandType = CMD_UPDATE;
2858
2859
  /* process the WITH clause independently of all else */
2860
0
  if (stmt->withClause)
2861
0
  {
2862
0
    qry->hasRecursive = stmt->withClause->recursive;
2863
0
    qry->cteList = transformWithClause(pstate, stmt->withClause);
2864
0
    qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2865
0
  }
2866
2867
0
  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2868
0
                     stmt->relation->inh,
2869
0
                     true,
2870
0
                     ACL_UPDATE);
2871
2872
  /* disallow UPDATE ... WHERE CURRENT OF on a view */
2873
0
  if (stmt->whereClause &&
2874
0
    IsA(stmt->whereClause, CurrentOfExpr) &&
2875
0
    pstate->p_target_relation->rd_rel->relkind == RELKIND_VIEW)
2876
0
    ereport(ERROR,
2877
0
        errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2878
0
        errmsg("WHERE CURRENT OF on a view is not implemented"));
2879
2880
0
  if (stmt->forPortionOf)
2881
0
    qry->forPortionOf = transformForPortionOfClause(pstate,
2882
0
                            qry->resultRelation,
2883
0
                            stmt->forPortionOf,
2884
0
                            stmt->whereClause,
2885
0
                            true);
2886
2887
0
  nsitem = pstate->p_target_nsitem;
2888
2889
  /* subqueries in FROM cannot access the result relation */
2890
0
  nsitem->p_lateral_only = true;
2891
0
  nsitem->p_lateral_ok = false;
2892
2893
  /*
2894
   * the FROM clause is non-standard SQL syntax. We used to be able to do
2895
   * this with REPLACE in POSTQUEL so we keep the feature.
2896
   */
2897
0
  transformFromClause(pstate, stmt->fromClause);
2898
2899
  /* remaining clauses can reference the result relation normally */
2900
0
  nsitem->p_lateral_only = false;
2901
0
  nsitem->p_lateral_ok = true;
2902
2903
0
  qual = transformWhereClause(pstate, stmt->whereClause,
2904
0
                EXPR_KIND_WHERE, "WHERE");
2905
2906
0
  transformReturningClause(pstate, qry, stmt->returningClause,
2907
0
               EXPR_KIND_RETURNING);
2908
2909
  /*
2910
   * Now we are done with SELECT-like processing, and can get on with
2911
   * transforming the target list to match the UPDATE target columns.
2912
   */
2913
0
  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList,
2914
0
                        qry->forPortionOf);
2915
2916
0
  qry->rtable = pstate->p_rtable;
2917
0
  qry->rteperminfos = pstate->p_rteperminfos;
2918
0
  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2919
2920
0
  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2921
0
  qry->hasSubLinks = pstate->p_hasSubLinks;
2922
2923
0
  assign_query_collations(pstate, qry);
2924
2925
0
  return qry;
2926
0
}
2927
2928
/*
2929
 * transformUpdateTargetList -
2930
 *  handle SET clause in UPDATE/MERGE/INSERT ... ON CONFLICT UPDATE
2931
 */
2932
List *
2933
transformUpdateTargetList(ParseState *pstate, List *origTlist, ForPortionOfExpr *forPortionOf)
2934
0
{
2935
0
  List     *tlist = NIL;
2936
0
  RTEPermissionInfo *target_perminfo;
2937
0
  ListCell   *orig_tl;
2938
0
  ListCell   *tl;
2939
2940
0
  tlist = transformTargetList(pstate, origTlist,
2941
0
                EXPR_KIND_UPDATE_SOURCE);
2942
2943
  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2944
0
  if (pstate->p_next_resno <= RelationGetNumberOfAttributes(pstate->p_target_relation))
2945
0
    pstate->p_next_resno = RelationGetNumberOfAttributes(pstate->p_target_relation) + 1;
2946
2947
  /* Prepare non-junk columns for assignment to target table */
2948
0
  target_perminfo = pstate->p_target_nsitem->p_perminfo;
2949
0
  orig_tl = list_head(origTlist);
2950
2951
0
  foreach(tl, tlist)
2952
0
  {
2953
0
    TargetEntry *tle = (TargetEntry *) lfirst(tl);
2954
0
    ResTarget  *origTarget;
2955
0
    int     attrno;
2956
2957
0
    if (tle->resjunk)
2958
0
    {
2959
      /*
2960
       * Resjunk nodes need no additional processing, but be sure they
2961
       * have resnos that do not match any target columns; else rewriter
2962
       * or planner might get confused.  They don't need a resname
2963
       * either.
2964
       */
2965
0
      tle->resno = (AttrNumber) pstate->p_next_resno++;
2966
0
      tle->resname = NULL;
2967
0
      continue;
2968
0
    }
2969
0
    if (orig_tl == NULL)
2970
0
      elog(ERROR, "UPDATE target count mismatch --- internal error");
2971
0
    origTarget = lfirst_node(ResTarget, orig_tl);
2972
2973
0
    attrno = attnameAttNum(pstate->p_target_relation,
2974
0
                 origTarget->name, true);
2975
0
    if (attrno == InvalidAttrNumber)
2976
0
      ereport(ERROR,
2977
0
          (errcode(ERRCODE_UNDEFINED_COLUMN),
2978
0
           errmsg("column \"%s\" of relation \"%s\" does not exist",
2979
0
              origTarget->name,
2980
0
              RelationGetRelationName(pstate->p_target_relation)),
2981
0
           (origTarget->indirection != NIL &&
2982
0
            strcmp(origTarget->name, pstate->p_target_nsitem->p_names->aliasname) == 0) ?
2983
0
           errhint("SET target columns cannot be qualified with the relation name.") : 0,
2984
0
           parser_errposition(pstate, origTarget->location)));
2985
2986
    /*
2987
     * If this is a FOR PORTION OF update, forbid directly setting the
2988
     * range column, since that would conflict with the implicit updates.
2989
     */
2990
0
    if (forPortionOf != NULL)
2991
0
    {
2992
0
      if (attrno == forPortionOf->rangeVar->varattno)
2993
0
        ereport(ERROR,
2994
0
            (errcode(ERRCODE_SYNTAX_ERROR),
2995
0
             errmsg("cannot update column \"%s\" because it is used in FOR PORTION OF",
2996
0
                origTarget->name),
2997
0
             parser_errposition(pstate, origTarget->location)));
2998
0
    }
2999
3000
0
    updateTargetListEntry(pstate, tle, origTarget->name,
3001
0
                attrno,
3002
0
                origTarget->indirection,
3003
0
                origTarget->location);
3004
3005
    /* Mark the target column as requiring update permissions */
3006
0
    target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
3007
0
                            attrno - FirstLowInvalidHeapAttributeNumber);
3008
3009
0
    orig_tl = lnext(origTlist, orig_tl);
3010
0
  }
3011
0
  if (orig_tl != NULL)
3012
0
    elog(ERROR, "UPDATE target count mismatch --- internal error");
3013
3014
0
  return tlist;
3015
0
}
3016
3017
/*
3018
 * addNSItemForReturning -
3019
 *  add a ParseNamespaceItem for the OLD or NEW alias in RETURNING.
3020
 */
3021
static void
3022
addNSItemForReturning(ParseState *pstate, const char *aliasname,
3023
            VarReturningType returning_type)
3024
0
{
3025
0
  List     *colnames;
3026
0
  int     numattrs;
3027
0
  ParseNamespaceColumn *nscolumns;
3028
0
  ParseNamespaceItem *nsitem;
3029
3030
  /* copy per-column data from the target relation */
3031
0
  colnames = pstate->p_target_nsitem->p_rte->eref->colnames;
3032
0
  numattrs = list_length(colnames);
3033
3034
0
  nscolumns = palloc_array(ParseNamespaceColumn, numattrs);
3035
3036
0
  memcpy(nscolumns, pstate->p_target_nsitem->p_nscolumns,
3037
0
       numattrs * sizeof(ParseNamespaceColumn));
3038
3039
  /* mark all columns as returning OLD/NEW */
3040
0
  for (int i = 0; i < numattrs; i++)
3041
0
    nscolumns[i].p_varreturningtype = returning_type;
3042
3043
  /* build the nsitem, copying most fields from the target relation */
3044
0
  nsitem = palloc_object(ParseNamespaceItem);
3045
0
  nsitem->p_names = makeAlias(aliasname, colnames);
3046
0
  nsitem->p_rte = pstate->p_target_nsitem->p_rte;
3047
0
  nsitem->p_rtindex = pstate->p_target_nsitem->p_rtindex;
3048
0
  nsitem->p_perminfo = pstate->p_target_nsitem->p_perminfo;
3049
0
  nsitem->p_nscolumns = nscolumns;
3050
0
  nsitem->p_returning_type = returning_type;
3051
3052
  /* add it to the query namespace as a table-only item */
3053
0
  addNSItemToQuery(pstate, nsitem, false, true, false);
3054
0
}
3055
3056
/*
3057
 * transformReturningClause -
3058
 *  handle a RETURNING clause in INSERT/UPDATE/DELETE/MERGE
3059
 */
3060
void
3061
transformReturningClause(ParseState *pstate, Query *qry,
3062
             ReturningClause *returningClause,
3063
             ParseExprKind exprKind)
3064
0
{
3065
0
  int     save_nslen = list_length(pstate->p_namespace);
3066
0
  int     save_next_resno;
3067
3068
0
  if (returningClause == NULL)
3069
0
    return;         /* nothing to do */
3070
3071
  /*
3072
   * Scan RETURNING WITH(...) options for OLD/NEW alias names.  Complain if
3073
   * there is any conflict with existing relations.
3074
   */
3075
0
  foreach_node(ReturningOption, option, returningClause->options)
3076
0
  {
3077
0
    switch (option->option)
3078
0
    {
3079
0
      case RETURNING_OPTION_OLD:
3080
0
        if (qry->returningOldAlias != NULL)
3081
0
          ereport(ERROR,
3082
0
              errcode(ERRCODE_SYNTAX_ERROR),
3083
          /* translator: %s is OLD or NEW */
3084
0
              errmsg("%s cannot be specified multiple times", "OLD"),
3085
0
              parser_errposition(pstate, option->location));
3086
0
        qry->returningOldAlias = option->value;
3087
0
        break;
3088
3089
0
      case RETURNING_OPTION_NEW:
3090
0
        if (qry->returningNewAlias != NULL)
3091
0
          ereport(ERROR,
3092
0
              errcode(ERRCODE_SYNTAX_ERROR),
3093
          /* translator: %s is OLD or NEW */
3094
0
              errmsg("%s cannot be specified multiple times", "NEW"),
3095
0
              parser_errposition(pstate, option->location));
3096
0
        qry->returningNewAlias = option->value;
3097
0
        break;
3098
3099
0
      default:
3100
0
        elog(ERROR, "unrecognized returning option: %d", option->option);
3101
0
    }
3102
3103
0
    if (refnameNamespaceItem(pstate, NULL, option->value, -1, NULL) != NULL)
3104
0
      ereport(ERROR,
3105
0
          errcode(ERRCODE_DUPLICATE_ALIAS),
3106
0
          errmsg("table name \"%s\" specified more than once",
3107
0
               option->value),
3108
0
          parser_errposition(pstate, option->location));
3109
3110
0
    addNSItemForReturning(pstate, option->value,
3111
0
                option->option == RETURNING_OPTION_OLD ?
3112
0
                VAR_RETURNING_OLD : VAR_RETURNING_NEW);
3113
0
  }
3114
3115
  /*
3116
   * If OLD/NEW alias names weren't explicitly specified, use "old"/"new"
3117
   * unless masked by existing relations.
3118
   */
3119
0
  if (qry->returningOldAlias == NULL &&
3120
0
    refnameNamespaceItem(pstate, NULL, "old", -1, NULL) == NULL)
3121
0
  {
3122
0
    qry->returningOldAlias = "old";
3123
0
    addNSItemForReturning(pstate, "old", VAR_RETURNING_OLD);
3124
0
  }
3125
0
  if (qry->returningNewAlias == NULL &&
3126
0
    refnameNamespaceItem(pstate, NULL, "new", -1, NULL) == NULL)
3127
0
  {
3128
0
    qry->returningNewAlias = "new";
3129
0
    addNSItemForReturning(pstate, "new", VAR_RETURNING_NEW);
3130
0
  }
3131
3132
  /*
3133
   * We need to assign resnos starting at one in the RETURNING list. Save
3134
   * and restore the main tlist's value of p_next_resno, just in case
3135
   * someone looks at it later (probably won't happen).
3136
   */
3137
0
  save_next_resno = pstate->p_next_resno;
3138
0
  pstate->p_next_resno = 1;
3139
3140
  /* transform RETURNING expressions identically to a SELECT targetlist */
3141
0
  qry->returningList = transformTargetList(pstate,
3142
0
                       returningClause->exprs,
3143
0
                       exprKind);
3144
3145
  /*
3146
   * Complain if the nonempty tlist expanded to nothing (which is possible
3147
   * if it contains only a star-expansion of a zero-column table).  If we
3148
   * allow this, the parsed Query will look like it didn't have RETURNING,
3149
   * with results that would probably surprise the user.
3150
   */
3151
0
  if (qry->returningList == NIL)
3152
0
    ereport(ERROR,
3153
0
        (errcode(ERRCODE_SYNTAX_ERROR),
3154
0
         errmsg("RETURNING must have at least one column"),
3155
0
         parser_errposition(pstate,
3156
0
                  exprLocation(linitial(returningClause->exprs)))));
3157
3158
  /* mark column origins */
3159
0
  markTargetListOrigins(pstate, qry->returningList);
3160
3161
  /* resolve any still-unresolved output columns as being type text */
3162
0
  if (pstate->p_resolve_unknowns)
3163
0
    resolveTargetListUnknowns(pstate, qry->returningList);
3164
3165
  /* restore state */
3166
0
  pstate->p_namespace = list_truncate(pstate->p_namespace, save_nslen);
3167
0
  pstate->p_next_resno = save_next_resno;
3168
0
}
3169
3170
3171
/*
3172
 * transformPLAssignStmt -
3173
 *    transform a PL/pgSQL assignment statement
3174
 *
3175
 * If there is no opt_indirection, the transformed statement looks like
3176
 * "SELECT a_expr ...", except the expression has been cast to the type of
3177
 * the target.  With indirection, it's still a SELECT, but the expression will
3178
 * incorporate FieldStore and/or assignment SubscriptingRef nodes to compute a
3179
 * new value for a container-type variable represented by the target.  The
3180
 * expression references the target as the container source.
3181
 */
3182
static Query *
3183
transformPLAssignStmt(ParseState *pstate, PLAssignStmt *stmt)
3184
0
{
3185
0
  Query    *qry;
3186
0
  ColumnRef  *cref = makeNode(ColumnRef);
3187
0
  List     *indirection = stmt->indirection;
3188
0
  int     nnames = stmt->nnames;
3189
0
  Node     *target;
3190
0
  SelectStmtPassthrough passthru;
3191
0
  bool    save_resolve_unknowns;
3192
3193
  /*
3194
   * First, construct a ColumnRef for the target variable.  If the target
3195
   * has more than one dotted name, we have to pull the extra names out of
3196
   * the indirection list.
3197
   */
3198
0
  cref->fields = list_make1(makeString(stmt->name));
3199
0
  cref->location = stmt->location;
3200
0
  if (nnames > 1)
3201
0
  {
3202
    /* avoid munging the raw parsetree */
3203
0
    indirection = list_copy(indirection);
3204
0
    while (--nnames > 0 && indirection != NIL)
3205
0
    {
3206
0
      Node     *ind = (Node *) linitial(indirection);
3207
3208
0
      if (!IsA(ind, String))
3209
0
        elog(ERROR, "invalid name count in PLAssignStmt");
3210
0
      cref->fields = lappend(cref->fields, ind);
3211
0
      indirection = list_delete_first(indirection);
3212
0
    }
3213
0
  }
3214
3215
  /*
3216
   * Transform the target reference.  Typically we will get back a Param
3217
   * node, but there's no reason to be too picky about its type.  (Note that
3218
   * we must do this before calling transformSelectStmt.  It's tempting to
3219
   * do it inside transformPLAssignStmtTarget, but we need to do it before
3220
   * adding any FROM tables to the pstate's namespace, else we might wrongly
3221
   * resolve the target as a table column.)
3222
   */
3223
0
  target = transformExpr(pstate, (Node *) cref,
3224
0
               EXPR_KIND_UPDATE_TARGET);
3225
3226
  /* Set up passthrough data for transformPLAssignStmtTarget */
3227
0
  passthru.stmt = stmt;
3228
0
  passthru.target = target;
3229
0
  passthru.indirection = indirection;
3230
3231
  /*
3232
   * To avoid duplicating a lot of code, we use transformSelectStmt to do
3233
   * almost all of the work.  However, we need to do additional processing
3234
   * on the SELECT's targetlist after it's been transformed, but before
3235
   * possible addition of targetlist items for ORDER BY or GROUP BY.
3236
   * transformSelectStmt knows it should call transformPLAssignStmtTarget if
3237
   * it's passed a passthru argument.
3238
   *
3239
   * Also, disable resolution of unknown-type tlist items; PL/pgSQL wants to
3240
   * deal with that itself.
3241
   */
3242
0
  save_resolve_unknowns = pstate->p_resolve_unknowns;
3243
0
  pstate->p_resolve_unknowns = false;
3244
0
  qry = transformSelectStmt(pstate, stmt->val, &passthru);
3245
0
  pstate->p_resolve_unknowns = save_resolve_unknowns;
3246
3247
0
  return qry;
3248
0
}
3249
3250
/*
3251
 * Callback function to adjust a SELECT's tlist to make the output suitable
3252
 * for assignment to a PLAssignStmt's target variable.
3253
 *
3254
 * Note: we actually modify the tle->expr in-place, but the function's API
3255
 * is set up to not presume that.
3256
 */
3257
static List *
3258
transformPLAssignStmtTarget(ParseState *pstate, List *tlist,
3259
              SelectStmtPassthrough *passthru)
3260
0
{
3261
0
  PLAssignStmt *stmt = passthru->stmt;
3262
0
  Node     *target = passthru->target;
3263
0
  List     *indirection = passthru->indirection;
3264
0
  Oid     targettype;
3265
0
  int32   targettypmod;
3266
0
  Oid     targetcollation;
3267
0
  TargetEntry *tle;
3268
0
  Oid     type_id;
3269
3270
0
  targettype = exprType(target);
3271
0
  targettypmod = exprTypmod(target);
3272
0
  targetcollation = exprCollation(target);
3273
3274
  /* we should have exactly one targetlist item */
3275
0
  if (list_length(tlist) != 1)
3276
0
    ereport(ERROR,
3277
0
        (errcode(ERRCODE_SYNTAX_ERROR),
3278
0
         errmsg_plural("assignment source returned %d column",
3279
0
                 "assignment source returned %d columns",
3280
0
                 list_length(tlist),
3281
0
                 list_length(tlist))));
3282
3283
0
  tle = linitial_node(TargetEntry, tlist);
3284
3285
  /*
3286
   * This next bit is similar to transformAssignedExpr; the key difference
3287
   * is we use COERCION_PLPGSQL not COERCION_ASSIGNMENT.
3288
   */
3289
0
  type_id = exprType((Node *) tle->expr);
3290
3291
0
  pstate->p_expr_kind = EXPR_KIND_UPDATE_TARGET;
3292
3293
0
  if (indirection)
3294
0
  {
3295
0
    tle->expr = (Expr *)
3296
0
      transformAssignmentIndirection(pstate,
3297
0
                       target,
3298
0
                       stmt->name,
3299
0
                       false,
3300
0
                       targettype,
3301
0
                       targettypmod,
3302
0
                       targetcollation,
3303
0
                       indirection,
3304
0
                       list_head(indirection),
3305
0
                       (Node *) tle->expr,
3306
0
                       COERCION_PLPGSQL,
3307
0
                       exprLocation(target));
3308
0
  }
3309
0
  else if (targettype != type_id &&
3310
0
       (targettype == RECORDOID || ISCOMPLEX(targettype)) &&
3311
0
       (type_id == RECORDOID || ISCOMPLEX(type_id)))
3312
0
  {
3313
    /*
3314
     * Hack: do not let coerce_to_target_type() deal with inconsistent
3315
     * composite types.  Just pass the expression result through as-is,
3316
     * and let the PL/pgSQL executor do the conversion its way.  This is
3317
     * rather bogus, but it's needed for backwards compatibility.
3318
     */
3319
0
  }
3320
0
  else
3321
0
  {
3322
    /*
3323
     * For normal non-qualified target column, do type checking and
3324
     * coercion.
3325
     */
3326
0
    Node     *orig_expr = (Node *) tle->expr;
3327
3328
0
    tle->expr = (Expr *)
3329
0
      coerce_to_target_type(pstate,
3330
0
                  orig_expr, type_id,
3331
0
                  targettype, targettypmod,
3332
0
                  COERCION_PLPGSQL,
3333
0
                  COERCE_IMPLICIT_CAST,
3334
0
                  -1);
3335
    /* With COERCION_PLPGSQL, this error is probably unreachable */
3336
0
    if (tle->expr == NULL)
3337
0
      ereport(ERROR,
3338
0
          (errcode(ERRCODE_DATATYPE_MISMATCH),
3339
0
           errmsg("variable \"%s\" is of type %s"
3340
0
              " but expression is of type %s",
3341
0
              stmt->name,
3342
0
              format_type_be(targettype),
3343
0
              format_type_be(type_id)),
3344
0
           errhint("You will need to rewrite or cast the expression."),
3345
0
           parser_errposition(pstate, exprLocation(orig_expr))));
3346
0
  }
3347
3348
0
  pstate->p_expr_kind = EXPR_KIND_NONE;
3349
3350
0
  return list_make1(tle);
3351
0
}
3352
3353
3354
/*
3355
 * transformDeclareCursorStmt -
3356
 *  transform a DECLARE CURSOR Statement
3357
 *
3358
 * DECLARE CURSOR is like other utility statements in that we emit it as a
3359
 * CMD_UTILITY Query node; however, we must first transform the contained
3360
 * query.  We used to postpone that until execution, but it's really necessary
3361
 * to do it during the normal parse analysis phase to ensure that side effects
3362
 * of parser hooks happen at the expected time.
3363
 */
3364
static Query *
3365
transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
3366
0
{
3367
0
  Query    *result;
3368
0
  Query    *query;
3369
3370
0
  if ((stmt->options & CURSOR_OPT_SCROLL) &&
3371
0
    (stmt->options & CURSOR_OPT_NO_SCROLL))
3372
0
    ereport(ERROR,
3373
0
        (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
3374
    /* translator: %s is a SQL keyword */
3375
0
         errmsg("cannot specify both %s and %s",
3376
0
            "SCROLL", "NO SCROLL")));
3377
3378
0
  if ((stmt->options & CURSOR_OPT_ASENSITIVE) &&
3379
0
    (stmt->options & CURSOR_OPT_INSENSITIVE))
3380
0
    ereport(ERROR,
3381
0
        (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
3382
    /* translator: %s is a SQL keyword */
3383
0
         errmsg("cannot specify both %s and %s",
3384
0
            "ASENSITIVE", "INSENSITIVE")));
3385
3386
  /* Transform contained query, not allowing SELECT INTO */
3387
0
  query = transformStmt(pstate, stmt->query);
3388
0
  stmt->query = (Node *) query;
3389
3390
  /* Grammar should not have allowed anything but SELECT */
3391
0
  if (!IsA(query, Query) ||
3392
0
    query->commandType != CMD_SELECT)
3393
0
    elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
3394
3395
  /*
3396
   * We also disallow data-modifying WITH in a cursor.  (This could be
3397
   * allowed, but the semantics of when the updates occur might be
3398
   * surprising.)
3399
   */
3400
0
  if (query->hasModifyingCTE)
3401
0
    ereport(ERROR,
3402
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3403
0
         errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
3404
3405
  /* FOR UPDATE and WITH HOLD are not compatible */
3406
0
  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
3407
0
    ereport(ERROR,
3408
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3409
    /*------
3410
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3411
0
         errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
3412
0
            LCS_asString(((RowMarkClause *)
3413
0
                    linitial(query->rowMarks))->strength)),
3414
0
         errdetail("Holdable cursors must be READ ONLY.")));
3415
3416
  /* FOR UPDATE and SCROLL are not compatible */
3417
0
  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
3418
0
    ereport(ERROR,
3419
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3420
    /*------
3421
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3422
0
         errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
3423
0
            LCS_asString(((RowMarkClause *)
3424
0
                    linitial(query->rowMarks))->strength)),
3425
0
         errdetail("Scrollable cursors must be READ ONLY.")));
3426
3427
  /* FOR UPDATE and INSENSITIVE are not compatible */
3428
0
  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
3429
0
    ereport(ERROR,
3430
0
        (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
3431
    /*------
3432
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3433
0
         errmsg("DECLARE INSENSITIVE CURSOR ... %s is not valid",
3434
0
            LCS_asString(((RowMarkClause *)
3435
0
                    linitial(query->rowMarks))->strength)),
3436
0
         errdetail("Insensitive cursors must be READ ONLY.")));
3437
3438
  /* represent the command as a utility Query */
3439
0
  result = makeNode(Query);
3440
0
  result->commandType = CMD_UTILITY;
3441
0
  result->utilityStmt = (Node *) stmt;
3442
3443
0
  return result;
3444
0
}
3445
3446
3447
/*
3448
 * transformExplainStmt -
3449
 *  transform an EXPLAIN Statement
3450
 *
3451
 * EXPLAIN is like other utility statements in that we emit it as a
3452
 * CMD_UTILITY Query node; however, we must first transform the contained
3453
 * query.  We used to postpone that until execution, but it's really necessary
3454
 * to do it during the normal parse analysis phase to ensure that side effects
3455
 * of parser hooks happen at the expected time.
3456
 */
3457
static Query *
3458
transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
3459
0
{
3460
0
  Query    *result;
3461
0
  bool    generic_plan = false;
3462
0
  Oid      *paramTypes = NULL;
3463
0
  int     numParams = 0;
3464
3465
  /*
3466
   * If we have no external source of parameter definitions, and the
3467
   * GENERIC_PLAN option is specified, then accept variable parameter
3468
   * definitions (similarly to PREPARE, for example).
3469
   */
3470
0
  if (pstate->p_paramref_hook == NULL)
3471
0
  {
3472
0
    ListCell   *lc;
3473
3474
0
    foreach(lc, stmt->options)
3475
0
    {
3476
0
      DefElem    *opt = (DefElem *) lfirst(lc);
3477
3478
0
      if (strcmp(opt->defname, "generic_plan") == 0)
3479
0
        generic_plan = defGetBoolean(opt);
3480
      /* don't "break", as we want the last value */
3481
0
    }
3482
0
    if (generic_plan)
3483
0
      setup_parse_variable_parameters(pstate, &paramTypes, &numParams);
3484
0
  }
3485
3486
  /* transform contained query, allowing SELECT INTO */
3487
0
  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
3488
3489
  /* make sure all is well with parameter types */
3490
0
  if (generic_plan)
3491
0
    check_variable_parameters(pstate, (Query *) stmt->query);
3492
3493
  /* represent the command as a utility Query */
3494
0
  result = makeNode(Query);
3495
0
  result->commandType = CMD_UTILITY;
3496
0
  result->utilityStmt = (Node *) stmt;
3497
3498
0
  return result;
3499
0
}
3500
3501
3502
/*
3503
 * transformCreateTableAsStmt -
3504
 *  transform a CREATE TABLE AS, SELECT ... INTO, or CREATE MATERIALIZED VIEW
3505
 *  Statement
3506
 *
3507
 * As with DECLARE CURSOR and EXPLAIN, transform the contained statement now.
3508
 */
3509
static Query *
3510
transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
3511
0
{
3512
0
  Query    *result;
3513
0
  Query    *query;
3514
3515
  /* transform contained query, not allowing SELECT INTO */
3516
0
  query = transformStmt(pstate, stmt->query);
3517
0
  stmt->query = (Node *) query;
3518
3519
  /* additional work needed for CREATE MATERIALIZED VIEW */
3520
0
  if (stmt->objtype == OBJECT_MATVIEW)
3521
0
  {
3522
0
    ObjectAddress temp_object;
3523
3524
    /*
3525
     * Prohibit a data-modifying CTE in the query used to create a
3526
     * materialized view. It's not sufficiently clear what the user would
3527
     * want to happen if the MV is refreshed or incrementally maintained.
3528
     */
3529
0
    if (query->hasModifyingCTE)
3530
0
      ereport(ERROR,
3531
0
          (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3532
0
           errmsg("materialized views must not use data-modifying statements in WITH")));
3533
3534
    /*
3535
     * Check whether any temporary database objects are used in the
3536
     * creation query. It would be hard to refresh data or incrementally
3537
     * maintain it if a source disappeared.
3538
     */
3539
0
    if (query_uses_temp_object(query, &temp_object))
3540
0
      ereport(ERROR,
3541
0
          (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3542
0
           errmsg("materialized views must not use temporary objects"),
3543
0
           errdetail("This view depends on temporary %s.",
3544
0
                 getObjectDescription(&temp_object, false))));
3545
3546
    /*
3547
     * A materialized view would either need to save parameters for use in
3548
     * maintaining/loading the data or prohibit them entirely.  The latter
3549
     * seems safer and more sane.
3550
     */
3551
0
    if (query_contains_extern_params(query))
3552
0
      ereport(ERROR,
3553
0
          (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3554
0
           errmsg("materialized views may not be defined using bound parameters")));
3555
3556
    /*
3557
     * For now, we disallow unlogged materialized views, because it seems
3558
     * like a bad idea for them to just go to empty after a crash. (If we
3559
     * could mark them as unpopulated, that would be better, but that
3560
     * requires catalog changes which crash recovery can't presently
3561
     * handle.)
3562
     */
3563
0
    if (stmt->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED)
3564
0
      ereport(ERROR,
3565
0
          (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3566
0
           errmsg("materialized views cannot be unlogged")));
3567
3568
    /*
3569
     * At runtime, we'll need a copy of the parsed-but-not-rewritten Query
3570
     * for purposes of creating the view's ON SELECT rule.  We stash that
3571
     * in the IntoClause because that's where intorel_startup() can
3572
     * conveniently get it from.
3573
     */
3574
0
    stmt->into->viewQuery = copyObject(query);
3575
0
  }
3576
3577
  /* represent the command as a utility Query */
3578
0
  result = makeNode(Query);
3579
0
  result->commandType = CMD_UTILITY;
3580
0
  result->utilityStmt = (Node *) stmt;
3581
3582
0
  return result;
3583
0
}
3584
3585
/*
3586
 * transform a CallStmt
3587
 */
3588
static Query *
3589
transformCallStmt(ParseState *pstate, CallStmt *stmt)
3590
0
{
3591
0
  List     *targs;
3592
0
  ListCell   *lc;
3593
0
  Node     *node;
3594
0
  FuncExpr   *fexpr;
3595
0
  HeapTuple proctup;
3596
0
  Datum   proargmodes;
3597
0
  bool    isNull;
3598
0
  List     *outargs = NIL;
3599
0
  Query    *result;
3600
3601
  /*
3602
   * First, do standard parse analysis on the procedure call and its
3603
   * arguments, allowing us to identify the called procedure.
3604
   */
3605
0
  targs = NIL;
3606
0
  foreach(lc, stmt->funccall->args)
3607
0
  {
3608
0
    targs = lappend(targs, transformExpr(pstate,
3609
0
                       (Node *) lfirst(lc),
3610
0
                       EXPR_KIND_CALL_ARGUMENT));
3611
0
  }
3612
3613
0
  node = ParseFuncOrColumn(pstate,
3614
0
               stmt->funccall->funcname,
3615
0
               targs,
3616
0
               pstate->p_last_srf,
3617
0
               stmt->funccall,
3618
0
               true,
3619
0
               stmt->funccall->location);
3620
3621
0
  assign_expr_collations(pstate, node);
3622
3623
0
  fexpr = castNode(FuncExpr, node);
3624
3625
0
  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
3626
0
  if (!HeapTupleIsValid(proctup))
3627
0
    elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
3628
3629
  /*
3630
   * Expand the argument list to deal with named-argument notation and
3631
   * default arguments.  For ordinary FuncExprs this'd be done during
3632
   * planning, but a CallStmt doesn't go through planning, and there seems
3633
   * no good reason not to do it here.
3634
   */
3635
0
  fexpr->args = expand_function_arguments(fexpr->args,
3636
0
                      true,
3637
0
                      fexpr->funcresulttype,
3638
0
                      proctup);
3639
3640
  /* Fetch proargmodes; if it's null, there are no output args */
3641
0
  proargmodes = SysCacheGetAttr(PROCOID, proctup,
3642
0
                  Anum_pg_proc_proargmodes,
3643
0
                  &isNull);
3644
0
  if (!isNull)
3645
0
  {
3646
    /*
3647
     * Split the list into input arguments in fexpr->args and output
3648
     * arguments in stmt->outargs.  INOUT arguments appear in both lists.
3649
     */
3650
0
    ArrayType  *arr;
3651
0
    int     numargs;
3652
0
    char     *argmodes;
3653
0
    List     *inargs;
3654
0
    int     i;
3655
3656
0
    arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
3657
0
    numargs = list_length(fexpr->args);
3658
0
    if (ARR_NDIM(arr) != 1 ||
3659
0
      ARR_DIMS(arr)[0] != numargs ||
3660
0
      ARR_HASNULL(arr) ||
3661
0
      ARR_ELEMTYPE(arr) != CHAROID)
3662
0
      elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
3663
0
         numargs);
3664
0
    argmodes = (char *) ARR_DATA_PTR(arr);
3665
3666
0
    inargs = NIL;
3667
0
    i = 0;
3668
0
    foreach(lc, fexpr->args)
3669
0
    {
3670
0
      Node     *n = lfirst(lc);
3671
3672
0
      switch (argmodes[i])
3673
0
      {
3674
0
        case PROARGMODE_IN:
3675
0
        case PROARGMODE_VARIADIC:
3676
0
          inargs = lappend(inargs, n);
3677
0
          break;
3678
0
        case PROARGMODE_OUT:
3679
0
          outargs = lappend(outargs, n);
3680
0
          break;
3681
0
        case PROARGMODE_INOUT:
3682
0
          inargs = lappend(inargs, n);
3683
0
          outargs = lappend(outargs, copyObject(n));
3684
0
          break;
3685
0
        default:
3686
          /* note we don't support PROARGMODE_TABLE */
3687
0
          elog(ERROR, "invalid argmode %c for procedure",
3688
0
             argmodes[i]);
3689
0
          break;
3690
0
      }
3691
0
      i++;
3692
0
    }
3693
0
    fexpr->args = inargs;
3694
0
  }
3695
3696
0
  stmt->funcexpr = fexpr;
3697
0
  stmt->outargs = outargs;
3698
3699
0
  ReleaseSysCache(proctup);
3700
3701
  /* represent the command as a utility Query */
3702
0
  result = makeNode(Query);
3703
0
  result->commandType = CMD_UTILITY;
3704
0
  result->utilityStmt = (Node *) stmt;
3705
3706
0
  return result;
3707
0
}
3708
3709
/*
3710
 * Produce a string representation of a LockClauseStrength value.
3711
 * This should only be applied to valid values (not LCS_NONE).
3712
 */
3713
const char *
3714
LCS_asString(LockClauseStrength strength)
3715
0
{
3716
0
  switch (strength)
3717
0
  {
3718
0
    case LCS_NONE:
3719
0
      Assert(false);
3720
0
      break;
3721
0
    case LCS_FORKEYSHARE:
3722
0
      return "FOR KEY SHARE";
3723
0
    case LCS_FORSHARE:
3724
0
      return "FOR SHARE";
3725
0
    case LCS_FORNOKEYUPDATE:
3726
0
      return "FOR NO KEY UPDATE";
3727
0
    case LCS_FORUPDATE:
3728
0
      return "FOR UPDATE";
3729
0
  }
3730
0
  return "FOR some";     /* shouldn't happen */
3731
0
}
3732
3733
/*
3734
 * Check for features that are not supported with FOR [KEY] UPDATE/SHARE.
3735
 *
3736
 * exported so planner can check again after rewriting, query pullup, etc
3737
 */
3738
void
3739
CheckSelectLocking(Query *qry, LockClauseStrength strength)
3740
0
{
3741
0
  Assert(strength != LCS_NONE); /* else caller error */
3742
3743
0
  if (qry->setOperations)
3744
0
    ereport(ERROR,
3745
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3746
    /*------
3747
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3748
0
         errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
3749
0
            LCS_asString(strength))));
3750
0
  if (qry->distinctClause != NIL)
3751
0
    ereport(ERROR,
3752
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3753
    /*------
3754
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3755
0
         errmsg("%s is not allowed with DISTINCT clause",
3756
0
            LCS_asString(strength))));
3757
0
  if (qry->groupClause != NIL || qry->groupingSets != NIL)
3758
0
    ereport(ERROR,
3759
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3760
    /*------
3761
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3762
0
         errmsg("%s is not allowed with GROUP BY clause",
3763
0
            LCS_asString(strength))));
3764
0
  if (qry->havingQual != NULL)
3765
0
    ereport(ERROR,
3766
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3767
    /*------
3768
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3769
0
         errmsg("%s is not allowed with HAVING clause",
3770
0
            LCS_asString(strength))));
3771
0
  if (qry->hasAggs)
3772
0
    ereport(ERROR,
3773
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3774
    /*------
3775
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3776
0
         errmsg("%s is not allowed with aggregate functions",
3777
0
            LCS_asString(strength))));
3778
0
  if (qry->hasWindowFuncs)
3779
0
    ereport(ERROR,
3780
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3781
    /*------
3782
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3783
0
         errmsg("%s is not allowed with window functions",
3784
0
            LCS_asString(strength))));
3785
0
  if (qry->hasTargetSRFs)
3786
0
    ereport(ERROR,
3787
0
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3788
    /*------
3789
      translator: %s is a SQL row locking clause such as FOR UPDATE */
3790
0
         errmsg("%s is not allowed with set-returning functions in the target list",
3791
0
            LCS_asString(strength))));
3792
0
}
3793
3794
/*
3795
 * Transform a FOR [KEY] UPDATE/SHARE clause
3796
 *
3797
 * This basically involves replacing names by integer relids.
3798
 *
3799
 * NB: if you need to change this, see also markQueryForLocking()
3800
 * in rewriteHandler.c, and isLockedRefname() in parse_relation.c.
3801
 */
3802
static void
3803
transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
3804
             bool pushedDown)
3805
0
{
3806
0
  List     *lockedRels = lc->lockedRels;
3807
0
  ListCell   *l;
3808
0
  ListCell   *rt;
3809
0
  Index   i;
3810
0
  LockingClause *allrels;
3811
3812
0
  CheckSelectLocking(qry, lc->strength);
3813
3814
  /* make a clause we can pass down to subqueries to select all rels */
3815
0
  allrels = makeNode(LockingClause);
3816
0
  allrels->lockedRels = NIL; /* indicates all rels */
3817
0
  allrels->strength = lc->strength;
3818
0
  allrels->waitPolicy = lc->waitPolicy;
3819
3820
0
  if (lockedRels == NIL)
3821
0
  {
3822
    /*
3823
     * Lock all regular tables used in query and its subqueries.  We
3824
     * examine inFromCl to exclude auto-added RTEs, particularly NEW/OLD
3825
     * in rules.  This is a bit of an abuse of a mostly-obsolete flag, but
3826
     * it's convenient.  We can't rely on the namespace mechanism that has
3827
     * largely replaced inFromCl, since for example we need to lock
3828
     * base-relation RTEs even if they are masked by upper joins.
3829
     */
3830
0
    i = 0;
3831
0
    foreach(rt, qry->rtable)
3832
0
    {
3833
0
      RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
3834
3835
0
      ++i;
3836
0
      if (!rte->inFromCl)
3837
0
        continue;
3838
0
      switch (rte->rtekind)
3839
0
      {
3840
0
        case RTE_RELATION:
3841
0
          {
3842
0
            RTEPermissionInfo *perminfo;
3843
3844
0
            applyLockingClause(qry, i,
3845
0
                       lc->strength,
3846
0
                       lc->waitPolicy,
3847
0
                       pushedDown);
3848
0
            perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
3849
0
            perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
3850
0
          }
3851
0
          break;
3852
0
        case RTE_SUBQUERY:
3853
0
          applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
3854
0
                     pushedDown);
3855
3856
          /*
3857
           * FOR UPDATE/SHARE of subquery is propagated to all of
3858
           * subquery's rels, too.  We could do this later (based on
3859
           * the marking of the subquery RTE) but it is convenient
3860
           * to have local knowledge in each query level about which
3861
           * rels need to be opened with RowShareLock.
3862
           */
3863
0
          transformLockingClause(pstate, rte->subquery,
3864
0
                       allrels, true);
3865
0
          break;
3866
0
        default:
3867
          /* ignore all other RTE kinds */
3868
0
          break;
3869
0
      }
3870
0
    }
3871
0
  }
3872
0
  else
3873
0
  {
3874
    /*
3875
     * Lock just the named tables.  As above, we allow locking any base
3876
     * relation regardless of alias-visibility rules, so we need to
3877
     * examine inFromCl to exclude OLD/NEW.
3878
     */
3879
0
    foreach(l, lockedRels)
3880
0
    {
3881
0
      RangeVar   *thisrel = (RangeVar *) lfirst(l);
3882
3883
      /* For simplicity we insist on unqualified alias names here */
3884
0
      if (thisrel->catalogname || thisrel->schemaname)
3885
0
        ereport(ERROR,
3886
0
            (errcode(ERRCODE_SYNTAX_ERROR),
3887
        /*------
3888
          translator: %s is a SQL row locking clause such as FOR UPDATE */
3889
0
             errmsg("%s must specify unqualified relation names",
3890
0
                LCS_asString(lc->strength)),
3891
0
             parser_errposition(pstate, thisrel->location)));
3892
3893
0
      i = 0;
3894
0
      foreach(rt, qry->rtable)
3895
0
      {
3896
0
        RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
3897
0
        char     *rtename = rte->eref->aliasname;
3898
3899
0
        ++i;
3900
0
        if (!rte->inFromCl)
3901
0
          continue;
3902
3903
        /*
3904
         * A join RTE without an alias is not visible as a relation
3905
         * name and needs to be skipped (otherwise it might hide a
3906
         * base relation with the same name), except if it has a USING
3907
         * alias, which *is* visible.
3908
         *
3909
         * Subquery and values RTEs without aliases are never visible
3910
         * as relation names and must always be skipped.
3911
         */
3912
0
        if (rte->alias == NULL)
3913
0
        {
3914
0
          if (rte->rtekind == RTE_JOIN)
3915
0
          {
3916
0
            if (rte->join_using_alias == NULL)
3917
0
              continue;
3918
0
            rtename = rte->join_using_alias->aliasname;
3919
0
          }
3920
0
          else if (rte->rtekind == RTE_SUBQUERY ||
3921
0
               rte->rtekind == RTE_VALUES)
3922
0
            continue;
3923
0
        }
3924
3925
0
        if (strcmp(rtename, thisrel->relname) == 0)
3926
0
        {
3927
0
          switch (rte->rtekind)
3928
0
          {
3929
0
            case RTE_RELATION:
3930
0
              {
3931
0
                RTEPermissionInfo *perminfo;
3932
3933
0
                applyLockingClause(qry, i,
3934
0
                           lc->strength,
3935
0
                           lc->waitPolicy,
3936
0
                           pushedDown);
3937
0
                perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
3938
0
                perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
3939
0
              }
3940
0
              break;
3941
0
            case RTE_SUBQUERY:
3942
0
              applyLockingClause(qry, i, lc->strength,
3943
0
                         lc->waitPolicy, pushedDown);
3944
              /* see comment above */
3945
0
              transformLockingClause(pstate, rte->subquery,
3946
0
                           allrels, true);
3947
0
              break;
3948
0
            case RTE_JOIN:
3949
0
              ereport(ERROR,
3950
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3951
              /*------
3952
                translator: %s is a SQL row locking clause such as FOR UPDATE */
3953
0
                   errmsg("%s cannot be applied to a join",
3954
0
                      LCS_asString(lc->strength)),
3955
0
                   parser_errposition(pstate, thisrel->location)));
3956
0
              break;
3957
0
            case RTE_FUNCTION:
3958
0
              ereport(ERROR,
3959
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3960
              /*------
3961
                translator: %s is a SQL row locking clause such as FOR UPDATE */
3962
0
                   errmsg("%s cannot be applied to a function",
3963
0
                      LCS_asString(lc->strength)),
3964
0
                   parser_errposition(pstate, thisrel->location)));
3965
0
              break;
3966
0
            case RTE_TABLEFUNC:
3967
0
              ereport(ERROR,
3968
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3969
              /*------
3970
                translator: %s is a SQL row locking clause such as FOR UPDATE */
3971
0
                   errmsg("%s cannot be applied to a table function",
3972
0
                      LCS_asString(lc->strength)),
3973
0
                   parser_errposition(pstate, thisrel->location)));
3974
0
              break;
3975
0
            case RTE_VALUES:
3976
0
              ereport(ERROR,
3977
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3978
              /*------
3979
                translator: %s is a SQL row locking clause such as FOR UPDATE */
3980
0
                   errmsg("%s cannot be applied to VALUES",
3981
0
                      LCS_asString(lc->strength)),
3982
0
                   parser_errposition(pstate, thisrel->location)));
3983
0
              break;
3984
0
            case RTE_CTE:
3985
0
              ereport(ERROR,
3986
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3987
              /*------
3988
                translator: %s is a SQL row locking clause such as FOR UPDATE */
3989
0
                   errmsg("%s cannot be applied to a WITH query",
3990
0
                      LCS_asString(lc->strength)),
3991
0
                   parser_errposition(pstate, thisrel->location)));
3992
0
              break;
3993
0
            case RTE_NAMEDTUPLESTORE:
3994
0
              ereport(ERROR,
3995
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3996
              /*------
3997
                translator: %s is a SQL row locking clause such as FOR UPDATE */
3998
0
                   errmsg("%s cannot be applied to a named tuplestore",
3999
0
                      LCS_asString(lc->strength)),
4000
0
                   parser_errposition(pstate, thisrel->location)));
4001
0
              break;
4002
0
            case RTE_GRAPH_TABLE:
4003
0
              ereport(ERROR,
4004
0
                  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4005
              /*------
4006
                translator: %s is a SQL row locking clause such as FOR UPDATE */
4007
0
                   errmsg("%s cannot be applied to GRAPH_TABLE",
4008
0
                      LCS_asString(lc->strength)),
4009
0
                   parser_errposition(pstate, thisrel->location)));
4010
0
              break;
4011
4012
              /* Shouldn't be possible to see RTE_RESULT here */
4013
4014
0
            default:
4015
0
              elog(ERROR, "unrecognized RTE type: %d",
4016
0
                 (int) rte->rtekind);
4017
0
              break;
4018
0
          }
4019
0
          break;   /* out of foreach loop */
4020
0
        }
4021
0
      }
4022
0
      if (rt == NULL)
4023
0
        ereport(ERROR,
4024
0
            (errcode(ERRCODE_UNDEFINED_TABLE),
4025
        /*------
4026
          translator: %s is a SQL row locking clause such as FOR UPDATE */
4027
0
             errmsg("relation \"%s\" in %s clause not found in FROM clause",
4028
0
                thisrel->relname,
4029
0
                LCS_asString(lc->strength)),
4030
0
             parser_errposition(pstate, thisrel->location)));
4031
0
    }
4032
0
  }
4033
0
}
4034
4035
/*
4036
 * Record locking info for a single rangetable item
4037
 */
4038
void
4039
applyLockingClause(Query *qry, Index rtindex,
4040
           LockClauseStrength strength, LockWaitPolicy waitPolicy,
4041
           bool pushedDown)
4042
0
{
4043
0
  RowMarkClause *rc;
4044
4045
0
  Assert(strength != LCS_NONE); /* else caller error */
4046
4047
  /* If it's an explicit clause, make sure hasForUpdate gets set */
4048
0
  if (!pushedDown)
4049
0
    qry->hasForUpdate = true;
4050
4051
  /* Check for pre-existing entry for same rtindex */
4052
0
  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
4053
0
  {
4054
    /*
4055
     * If the same RTE is specified with more than one locking strength,
4056
     * use the strongest.  (Reasonable, since you can't take both a shared
4057
     * and exclusive lock at the same time; it'll end up being exclusive
4058
     * anyway.)
4059
     *
4060
     * Similarly, if the same RTE is specified with more than one lock
4061
     * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
4062
     * turn wins over waiting for the lock (the default).  This is a bit
4063
     * more debatable but raising an error doesn't seem helpful. (Consider
4064
     * for instance SELECT FOR UPDATE NOWAIT from a view that internally
4065
     * contains a plain FOR UPDATE spec.)  Having NOWAIT win over SKIP
4066
     * LOCKED is reasonable since the former throws an error in case of
4067
     * coming across a locked tuple, which may be undesirable in some
4068
     * cases but it seems better than silently returning inconsistent
4069
     * results.
4070
     *
4071
     * And of course pushedDown becomes false if any clause is explicit.
4072
     */
4073
0
    rc->strength = Max(rc->strength, strength);
4074
0
    rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
4075
0
    rc->pushedDown &= pushedDown;
4076
0
    return;
4077
0
  }
4078
4079
  /* Make a new RowMarkClause */
4080
0
  rc = makeNode(RowMarkClause);
4081
0
  rc->rti = rtindex;
4082
0
  rc->strength = strength;
4083
0
  rc->waitPolicy = waitPolicy;
4084
0
  rc->pushedDown = pushedDown;
4085
0
  qry->rowMarks = lappend(qry->rowMarks, rc);
4086
0
}
4087
4088
#ifdef DEBUG_NODE_TESTS_ENABLED
4089
/*
4090
 * Coverage testing for raw_expression_tree_walker().
4091
 *
4092
 * When enabled, we run raw_expression_tree_walker() over every DML statement
4093
 * submitted to parse analysis.  Without this provision, that function is only
4094
 * applied in limited cases involving CTEs, and we don't really want to have
4095
 * to test everything inside as well as outside a CTE.
4096
 */
4097
static bool
4098
test_raw_expression_coverage(Node *node, void *context)
4099
{
4100
  if (node == NULL)
4101
    return false;
4102
  return raw_expression_tree_walker(node,
4103
                    test_raw_expression_coverage,
4104
                    context);
4105
}
4106
#endif              /* DEBUG_NODE_TESTS_ENABLED */