1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * parse_expr.c |
4 | * handle expressions in parser |
5 | * |
6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
7 | * Portions Copyright (c) 1994, Regents of the University of California |
8 | * |
9 | * |
10 | * IDENTIFICATION |
11 | * src/backend/parser/parse_expr.c |
12 | * |
13 | *------------------------------------------------------------------------- |
14 | */ |
15 | |
16 | #include "postgres.h" |
17 | |
18 | #include "catalog/pg_type.h" |
19 | #include "commands/dbcommands.h" |
20 | #include "miscadmin.h" |
21 | #include "nodes/makefuncs.h" |
22 | #include "nodes/nodeFuncs.h" |
23 | #include "optimizer/optimizer.h" |
24 | #include "parser/analyze.h" |
25 | #include "parser/parse_clause.h" |
26 | #include "parser/parse_coerce.h" |
27 | #include "parser/parse_collate.h" |
28 | #include "parser/parse_expr.h" |
29 | #include "parser/parse_func.h" |
30 | #include "parser/parse_oper.h" |
31 | #include "parser/parse_relation.h" |
32 | #include "parser/parse_target.h" |
33 | #include "parser/parse_type.h" |
34 | #include "parser/parse_agg.h" |
35 | #include "utils/builtins.h" |
36 | #include "utils/date.h" |
37 | #include "utils/lsyscache.h" |
38 | #include "utils/timestamp.h" |
39 | #include "utils/xml.h" |
40 | |
41 | |
42 | /* GUC parameters */ |
43 | bool operator_precedence_warning = false; |
44 | bool Transform_null_equals = false; |
45 | |
46 | /* |
47 | * Node-type groups for operator precedence warnings |
48 | * We use zero for everything not otherwise classified |
49 | */ |
50 | #define PREC_GROUP_POSTFIX_IS 1 /* postfix IS tests (NullTest, etc) */ |
51 | #define PREC_GROUP_INFIX_IS 2 /* infix IS (IS DISTINCT FROM, etc) */ |
52 | #define PREC_GROUP_LESS 3 /* < > */ |
53 | #define PREC_GROUP_EQUAL 4 /* = */ |
54 | #define PREC_GROUP_LESS_EQUAL 5 /* <= >= <> */ |
55 | #define PREC_GROUP_LIKE 6 /* LIKE ILIKE SIMILAR */ |
56 | #define PREC_GROUP_BETWEEN 7 /* BETWEEN */ |
57 | #define PREC_GROUP_IN 8 /* IN */ |
58 | #define PREC_GROUP_NOT_LIKE 9 /* NOT LIKE/ILIKE/SIMILAR */ |
59 | #define PREC_GROUP_NOT_BETWEEN 10 /* NOT BETWEEN */ |
60 | #define PREC_GROUP_NOT_IN 11 /* NOT IN */ |
61 | #define PREC_GROUP_POSTFIX_OP 12 /* generic postfix operators */ |
62 | #define PREC_GROUP_INFIX_OP 13 /* generic infix operators */ |
63 | #define PREC_GROUP_PREFIX_OP 14 /* generic prefix operators */ |
64 | |
65 | /* |
66 | * Map precedence groupings to old precedence ordering |
67 | * |
68 | * Old precedence order: |
69 | * 1. NOT |
70 | * 2. = |
71 | * 3. < > |
72 | * 4. LIKE ILIKE SIMILAR |
73 | * 5. BETWEEN |
74 | * 6. IN |
75 | * 7. generic postfix Op |
76 | * 8. generic Op, including <= => <> |
77 | * 9. generic prefix Op |
78 | * 10. IS tests (NullTest, BooleanTest, etc) |
79 | * |
80 | * NOT BETWEEN etc map to BETWEEN etc when considered as being on the left, |
81 | * but to NOT when considered as being on the right, because of the buggy |
82 | * precedence handling of those productions in the old grammar. |
83 | */ |
84 | static const int oldprecedence_l[] = { |
85 | 0, 10, 10, 3, 2, 8, 4, 5, 6, 4, 5, 6, 7, 8, 9 |
86 | }; |
87 | static const int oldprecedence_r[] = { |
88 | 0, 10, 10, 3, 2, 8, 4, 5, 6, 1, 1, 1, 7, 8, 9 |
89 | }; |
90 | |
91 | static Node *transformExprRecurse(ParseState *pstate, Node *expr); |
92 | static Node *transformParamRef(ParseState *pstate, ParamRef *pref); |
93 | static Node *transformAExprOp(ParseState *pstate, A_Expr *a); |
94 | static Node *transformAExprOpAny(ParseState *pstate, A_Expr *a); |
95 | static Node *transformAExprOpAll(ParseState *pstate, A_Expr *a); |
96 | static Node *transformAExprDistinct(ParseState *pstate, A_Expr *a); |
97 | static Node *transformAExprNullIf(ParseState *pstate, A_Expr *a); |
98 | static Node *transformAExprOf(ParseState *pstate, A_Expr *a); |
99 | static Node *transformAExprIn(ParseState *pstate, A_Expr *a); |
100 | static Node *transformAExprBetween(ParseState *pstate, A_Expr *a); |
101 | static Node *transformBoolExpr(ParseState *pstate, BoolExpr *a); |
102 | static Node *transformFuncCall(ParseState *pstate, FuncCall *fn); |
103 | static Node *transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref); |
104 | static Node *transformCaseExpr(ParseState *pstate, CaseExpr *c); |
105 | static Node *transformSubLink(ParseState *pstate, SubLink *sublink); |
106 | static Node *transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, |
107 | Oid array_type, Oid element_type, int32 typmod); |
108 | static Node *transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault); |
109 | static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c); |
110 | static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m); |
111 | static Node *transformSQLValueFunction(ParseState *pstate, |
112 | SQLValueFunction *svf); |
113 | static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x); |
114 | static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs); |
115 | static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); |
116 | static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr); |
117 | static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); |
118 | static Node *transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, |
119 | int location); |
120 | static Node *transformIndirection(ParseState *pstate, A_Indirection *ind); |
121 | static Node *transformTypeCast(ParseState *pstate, TypeCast *tc); |
122 | static Node *transformCollateClause(ParseState *pstate, CollateClause *c); |
123 | static Node *make_row_comparison_op(ParseState *pstate, List *opname, |
124 | List *largs, List *rargs, int location); |
125 | static Node *make_row_distinct_op(ParseState *pstate, List *opname, |
126 | RowExpr *lrow, RowExpr *rrow, int location); |
127 | static Expr *make_distinct_op(ParseState *pstate, List *opname, |
128 | Node *ltree, Node *rtree, int location); |
129 | static Node *make_nulltest_from_distinct(ParseState *pstate, |
130 | A_Expr *distincta, Node *arg); |
131 | static int operator_precedence_group(Node *node, const char **nodename); |
132 | static void emit_precedence_warnings(ParseState *pstate, |
133 | int opgroup, const char *opname, |
134 | Node *lchild, Node *rchild, |
135 | int location); |
136 | |
137 | |
138 | /* |
139 | * transformExpr - |
140 | * Analyze and transform expressions. Type checking and type casting is |
141 | * done here. This processing converts the raw grammar output into |
142 | * expression trees with fully determined semantics. |
143 | */ |
144 | Node * |
145 | transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind) |
146 | { |
147 | Node *result; |
148 | ParseExprKind sv_expr_kind; |
149 | |
150 | /* Save and restore identity of expression type we're parsing */ |
151 | Assert(exprKind != EXPR_KIND_NONE); |
152 | sv_expr_kind = pstate->p_expr_kind; |
153 | pstate->p_expr_kind = exprKind; |
154 | |
155 | result = transformExprRecurse(pstate, expr); |
156 | |
157 | pstate->p_expr_kind = sv_expr_kind; |
158 | |
159 | return result; |
160 | } |
161 | |
162 | static Node * |
163 | transformExprRecurse(ParseState *pstate, Node *expr) |
164 | { |
165 | Node *result; |
166 | |
167 | if (expr == NULL) |
168 | return NULL; |
169 | |
170 | /* Guard against stack overflow due to overly complex expressions */ |
171 | check_stack_depth(); |
172 | |
173 | switch (nodeTag(expr)) |
174 | { |
175 | case T_ColumnRef: |
176 | result = transformColumnRef(pstate, (ColumnRef *) expr); |
177 | break; |
178 | |
179 | case T_ParamRef: |
180 | result = transformParamRef(pstate, (ParamRef *) expr); |
181 | break; |
182 | |
183 | case T_A_Const: |
184 | { |
185 | A_Const *con = (A_Const *) expr; |
186 | Value *val = &con->val; |
187 | |
188 | result = (Node *) make_const(pstate, val, con->location); |
189 | break; |
190 | } |
191 | |
192 | case T_A_Indirection: |
193 | result = transformIndirection(pstate, (A_Indirection *) expr); |
194 | break; |
195 | |
196 | case T_A_ArrayExpr: |
197 | result = transformArrayExpr(pstate, (A_ArrayExpr *) expr, |
198 | InvalidOid, InvalidOid, -1); |
199 | break; |
200 | |
201 | case T_TypeCast: |
202 | result = transformTypeCast(pstate, (TypeCast *) expr); |
203 | break; |
204 | |
205 | case T_CollateClause: |
206 | result = transformCollateClause(pstate, (CollateClause *) expr); |
207 | break; |
208 | |
209 | case T_A_Expr: |
210 | { |
211 | A_Expr *a = (A_Expr *) expr; |
212 | |
213 | switch (a->kind) |
214 | { |
215 | case AEXPR_OP: |
216 | result = transformAExprOp(pstate, a); |
217 | break; |
218 | case AEXPR_OP_ANY: |
219 | result = transformAExprOpAny(pstate, a); |
220 | break; |
221 | case AEXPR_OP_ALL: |
222 | result = transformAExprOpAll(pstate, a); |
223 | break; |
224 | case AEXPR_DISTINCT: |
225 | case AEXPR_NOT_DISTINCT: |
226 | result = transformAExprDistinct(pstate, a); |
227 | break; |
228 | case AEXPR_NULLIF: |
229 | result = transformAExprNullIf(pstate, a); |
230 | break; |
231 | case AEXPR_OF: |
232 | result = transformAExprOf(pstate, a); |
233 | break; |
234 | case AEXPR_IN: |
235 | result = transformAExprIn(pstate, a); |
236 | break; |
237 | case AEXPR_LIKE: |
238 | case AEXPR_ILIKE: |
239 | case AEXPR_SIMILAR: |
240 | /* we can transform these just like AEXPR_OP */ |
241 | result = transformAExprOp(pstate, a); |
242 | break; |
243 | case AEXPR_BETWEEN: |
244 | case AEXPR_NOT_BETWEEN: |
245 | case AEXPR_BETWEEN_SYM: |
246 | case AEXPR_NOT_BETWEEN_SYM: |
247 | result = transformAExprBetween(pstate, a); |
248 | break; |
249 | case AEXPR_PAREN: |
250 | result = transformExprRecurse(pstate, a->lexpr); |
251 | break; |
252 | default: |
253 | elog(ERROR, "unrecognized A_Expr kind: %d" , a->kind); |
254 | result = NULL; /* keep compiler quiet */ |
255 | break; |
256 | } |
257 | break; |
258 | } |
259 | |
260 | case T_BoolExpr: |
261 | result = transformBoolExpr(pstate, (BoolExpr *) expr); |
262 | break; |
263 | |
264 | case T_FuncCall: |
265 | result = transformFuncCall(pstate, (FuncCall *) expr); |
266 | break; |
267 | |
268 | case T_MultiAssignRef: |
269 | result = transformMultiAssignRef(pstate, (MultiAssignRef *) expr); |
270 | break; |
271 | |
272 | case T_GroupingFunc: |
273 | result = transformGroupingFunc(pstate, (GroupingFunc *) expr); |
274 | break; |
275 | |
276 | case T_NamedArgExpr: |
277 | { |
278 | NamedArgExpr *na = (NamedArgExpr *) expr; |
279 | |
280 | na->arg = (Expr *) transformExprRecurse(pstate, (Node *) na->arg); |
281 | result = expr; |
282 | break; |
283 | } |
284 | |
285 | case T_SubLink: |
286 | result = transformSubLink(pstate, (SubLink *) expr); |
287 | break; |
288 | |
289 | case T_CaseExpr: |
290 | result = transformCaseExpr(pstate, (CaseExpr *) expr); |
291 | break; |
292 | |
293 | case T_RowExpr: |
294 | result = transformRowExpr(pstate, (RowExpr *) expr, false); |
295 | break; |
296 | |
297 | case T_CoalesceExpr: |
298 | result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr); |
299 | break; |
300 | |
301 | case T_MinMaxExpr: |
302 | result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr); |
303 | break; |
304 | |
305 | case T_SQLValueFunction: |
306 | result = transformSQLValueFunction(pstate, |
307 | (SQLValueFunction *) expr); |
308 | break; |
309 | |
310 | case T_XmlExpr: |
311 | result = transformXmlExpr(pstate, (XmlExpr *) expr); |
312 | break; |
313 | |
314 | case T_XmlSerialize: |
315 | result = transformXmlSerialize(pstate, (XmlSerialize *) expr); |
316 | break; |
317 | |
318 | case T_NullTest: |
319 | { |
320 | NullTest *n = (NullTest *) expr; |
321 | |
322 | if (operator_precedence_warning) |
323 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS" , |
324 | (Node *) n->arg, NULL, |
325 | n->location); |
326 | |
327 | n->arg = (Expr *) transformExprRecurse(pstate, (Node *) n->arg); |
328 | /* the argument can be any type, so don't coerce it */ |
329 | n->argisrow = type_is_rowtype(exprType((Node *) n->arg)); |
330 | result = expr; |
331 | break; |
332 | } |
333 | |
334 | case T_BooleanTest: |
335 | result = transformBooleanTest(pstate, (BooleanTest *) expr); |
336 | break; |
337 | |
338 | case T_CurrentOfExpr: |
339 | result = transformCurrentOfExpr(pstate, (CurrentOfExpr *) expr); |
340 | break; |
341 | |
342 | /* |
343 | * In all places where DEFAULT is legal, the caller should have |
344 | * processed it rather than passing it to transformExpr(). |
345 | */ |
346 | case T_SetToDefault: |
347 | ereport(ERROR, |
348 | (errcode(ERRCODE_SYNTAX_ERROR), |
349 | errmsg("DEFAULT is not allowed in this context" ), |
350 | parser_errposition(pstate, |
351 | ((SetToDefault *) expr)->location))); |
352 | break; |
353 | |
354 | /* |
355 | * CaseTestExpr doesn't require any processing; it is only |
356 | * injected into parse trees in a fully-formed state. |
357 | * |
358 | * Ordinarily we should not see a Var here, but it is convenient |
359 | * for transformJoinUsingClause() to create untransformed operator |
360 | * trees containing already-transformed Vars. The best |
361 | * alternative would be to deconstruct and reconstruct column |
362 | * references, which seems expensively pointless. So allow it. |
363 | */ |
364 | case T_CaseTestExpr: |
365 | case T_Var: |
366 | { |
367 | result = (Node *) expr; |
368 | break; |
369 | } |
370 | |
371 | default: |
372 | /* should not reach here */ |
373 | elog(ERROR, "unrecognized node type: %d" , (int) nodeTag(expr)); |
374 | result = NULL; /* keep compiler quiet */ |
375 | break; |
376 | } |
377 | |
378 | return result; |
379 | } |
380 | |
381 | /* |
382 | * helper routine for delivering "column does not exist" error message |
383 | * |
384 | * (Usually we don't have to work this hard, but the general case of field |
385 | * selection from an arbitrary node needs it.) |
386 | */ |
387 | static void |
388 | unknown_attribute(ParseState *pstate, Node *relref, const char *attname, |
389 | int location) |
390 | { |
391 | RangeTblEntry *rte; |
392 | |
393 | if (IsA(relref, Var) && |
394 | ((Var *) relref)->varattno == InvalidAttrNumber) |
395 | { |
396 | /* Reference the RTE by alias not by actual table name */ |
397 | rte = GetRTEByRangeTablePosn(pstate, |
398 | ((Var *) relref)->varno, |
399 | ((Var *) relref)->varlevelsup); |
400 | ereport(ERROR, |
401 | (errcode(ERRCODE_UNDEFINED_COLUMN), |
402 | errmsg("column %s.%s does not exist" , |
403 | rte->eref->aliasname, attname), |
404 | parser_errposition(pstate, location))); |
405 | } |
406 | else |
407 | { |
408 | /* Have to do it by reference to the type of the expression */ |
409 | Oid relTypeId = exprType(relref); |
410 | |
411 | if (ISCOMPLEX(relTypeId)) |
412 | ereport(ERROR, |
413 | (errcode(ERRCODE_UNDEFINED_COLUMN), |
414 | errmsg("column \"%s\" not found in data type %s" , |
415 | attname, format_type_be(relTypeId)), |
416 | parser_errposition(pstate, location))); |
417 | else if (relTypeId == RECORDOID) |
418 | ereport(ERROR, |
419 | (errcode(ERRCODE_UNDEFINED_COLUMN), |
420 | errmsg("could not identify column \"%s\" in record data type" , |
421 | attname), |
422 | parser_errposition(pstate, location))); |
423 | else |
424 | ereport(ERROR, |
425 | (errcode(ERRCODE_WRONG_OBJECT_TYPE), |
426 | errmsg("column notation .%s applied to type %s, " |
427 | "which is not a composite type" , |
428 | attname, format_type_be(relTypeId)), |
429 | parser_errposition(pstate, location))); |
430 | } |
431 | } |
432 | |
433 | static Node * |
434 | transformIndirection(ParseState *pstate, A_Indirection *ind) |
435 | { |
436 | Node *last_srf = pstate->p_last_srf; |
437 | Node *result = transformExprRecurse(pstate, ind->arg); |
438 | List *subscripts = NIL; |
439 | int location = exprLocation(result); |
440 | ListCell *i; |
441 | |
442 | /* |
443 | * We have to split any field-selection operations apart from |
444 | * subscripting. Adjacent A_Indices nodes have to be treated as a single |
445 | * multidimensional subscript operation. |
446 | */ |
447 | foreach(i, ind->indirection) |
448 | { |
449 | Node *n = lfirst(i); |
450 | |
451 | if (IsA(n, A_Indices)) |
452 | subscripts = lappend(subscripts, n); |
453 | else if (IsA(n, A_Star)) |
454 | { |
455 | ereport(ERROR, |
456 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
457 | errmsg("row expansion via \"*\" is not supported here" ), |
458 | parser_errposition(pstate, location))); |
459 | } |
460 | else |
461 | { |
462 | Node *newresult; |
463 | |
464 | Assert(IsA(n, String)); |
465 | |
466 | /* process subscripts before this field selection */ |
467 | if (subscripts) |
468 | result = (Node *) transformContainerSubscripts(pstate, |
469 | result, |
470 | exprType(result), |
471 | InvalidOid, |
472 | exprTypmod(result), |
473 | subscripts, |
474 | NULL); |
475 | subscripts = NIL; |
476 | |
477 | newresult = ParseFuncOrColumn(pstate, |
478 | list_make1(n), |
479 | list_make1(result), |
480 | last_srf, |
481 | NULL, |
482 | false, |
483 | location); |
484 | if (newresult == NULL) |
485 | unknown_attribute(pstate, result, strVal(n), location); |
486 | result = newresult; |
487 | } |
488 | } |
489 | /* process trailing subscripts, if any */ |
490 | if (subscripts) |
491 | result = (Node *) transformContainerSubscripts(pstate, |
492 | result, |
493 | exprType(result), |
494 | InvalidOid, |
495 | exprTypmod(result), |
496 | subscripts, |
497 | NULL); |
498 | |
499 | return result; |
500 | } |
501 | |
502 | /* |
503 | * Transform a ColumnRef. |
504 | * |
505 | * If you find yourself changing this code, see also ExpandColumnRefStar. |
506 | */ |
507 | static Node * |
508 | transformColumnRef(ParseState *pstate, ColumnRef *cref) |
509 | { |
510 | Node *node = NULL; |
511 | char *nspname = NULL; |
512 | char *relname = NULL; |
513 | char *colname = NULL; |
514 | RangeTblEntry *rte; |
515 | int levels_up; |
516 | enum |
517 | { |
518 | CRERR_NO_COLUMN, |
519 | CRERR_NO_RTE, |
520 | CRERR_WRONG_DB, |
521 | CRERR_TOO_MANY |
522 | } crerr = CRERR_NO_COLUMN; |
523 | const char *err; |
524 | |
525 | /* |
526 | * Check to see if the column reference is in an invalid place within the |
527 | * query. We allow column references in most places, except in default |
528 | * expressions and partition bound expressions. |
529 | */ |
530 | err = NULL; |
531 | switch (pstate->p_expr_kind) |
532 | { |
533 | case EXPR_KIND_NONE: |
534 | Assert(false); /* can't happen */ |
535 | break; |
536 | case EXPR_KIND_OTHER: |
537 | case EXPR_KIND_JOIN_ON: |
538 | case EXPR_KIND_JOIN_USING: |
539 | case EXPR_KIND_FROM_SUBSELECT: |
540 | case EXPR_KIND_FROM_FUNCTION: |
541 | case EXPR_KIND_WHERE: |
542 | case EXPR_KIND_POLICY: |
543 | case EXPR_KIND_HAVING: |
544 | case EXPR_KIND_FILTER: |
545 | case EXPR_KIND_WINDOW_PARTITION: |
546 | case EXPR_KIND_WINDOW_ORDER: |
547 | case EXPR_KIND_WINDOW_FRAME_RANGE: |
548 | case EXPR_KIND_WINDOW_FRAME_ROWS: |
549 | case EXPR_KIND_WINDOW_FRAME_GROUPS: |
550 | case EXPR_KIND_SELECT_TARGET: |
551 | case EXPR_KIND_INSERT_TARGET: |
552 | case EXPR_KIND_UPDATE_SOURCE: |
553 | case EXPR_KIND_UPDATE_TARGET: |
554 | case EXPR_KIND_GROUP_BY: |
555 | case EXPR_KIND_ORDER_BY: |
556 | case EXPR_KIND_DISTINCT_ON: |
557 | case EXPR_KIND_LIMIT: |
558 | case EXPR_KIND_OFFSET: |
559 | case EXPR_KIND_RETURNING: |
560 | case EXPR_KIND_VALUES: |
561 | case EXPR_KIND_VALUES_SINGLE: |
562 | case EXPR_KIND_CHECK_CONSTRAINT: |
563 | case EXPR_KIND_DOMAIN_CHECK: |
564 | case EXPR_KIND_FUNCTION_DEFAULT: |
565 | case EXPR_KIND_INDEX_EXPRESSION: |
566 | case EXPR_KIND_INDEX_PREDICATE: |
567 | case EXPR_KIND_ALTER_COL_TRANSFORM: |
568 | case EXPR_KIND_EXECUTE_PARAMETER: |
569 | case EXPR_KIND_TRIGGER_WHEN: |
570 | case EXPR_KIND_PARTITION_EXPRESSION: |
571 | case EXPR_KIND_CALL_ARGUMENT: |
572 | case EXPR_KIND_COPY_WHERE: |
573 | case EXPR_KIND_GENERATED_COLUMN: |
574 | /* okay */ |
575 | break; |
576 | |
577 | case EXPR_KIND_COLUMN_DEFAULT: |
578 | err = _("cannot use column reference in DEFAULT expression" ); |
579 | break; |
580 | case EXPR_KIND_PARTITION_BOUND: |
581 | err = _("cannot use column reference in partition bound expression" ); |
582 | break; |
583 | |
584 | /* |
585 | * There is intentionally no default: case here, so that the |
586 | * compiler will warn if we add a new ParseExprKind without |
587 | * extending this switch. If we do see an unrecognized value at |
588 | * runtime, the behavior will be the same as for EXPR_KIND_OTHER, |
589 | * which is sane anyway. |
590 | */ |
591 | } |
592 | if (err) |
593 | ereport(ERROR, |
594 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
595 | errmsg_internal("%s" , err), |
596 | parser_errposition(pstate, cref->location))); |
597 | |
598 | /* |
599 | * Give the PreParseColumnRefHook, if any, first shot. If it returns |
600 | * non-null then that's all, folks. |
601 | */ |
602 | if (pstate->p_pre_columnref_hook != NULL) |
603 | { |
604 | node = pstate->p_pre_columnref_hook(pstate, cref); |
605 | if (node != NULL) |
606 | return node; |
607 | } |
608 | |
609 | /*---------- |
610 | * The allowed syntaxes are: |
611 | * |
612 | * A First try to resolve as unqualified column name; |
613 | * if no luck, try to resolve as unqualified table name (A.*). |
614 | * A.B A is an unqualified table name; B is either a |
615 | * column or function name (trying column name first). |
616 | * A.B.C schema A, table B, col or func name C. |
617 | * A.B.C.D catalog A, schema B, table C, col or func D. |
618 | * A.* A is an unqualified table name; means whole-row value. |
619 | * A.B.* whole-row value of table B in schema A. |
620 | * A.B.C.* whole-row value of table C in schema B in catalog A. |
621 | * |
622 | * We do not need to cope with bare "*"; that will only be accepted by |
623 | * the grammar at the top level of a SELECT list, and transformTargetList |
624 | * will take care of it before it ever gets here. Also, "A.*" etc will |
625 | * be expanded by transformTargetList if they appear at SELECT top level, |
626 | * so here we are only going to see them as function or operator inputs. |
627 | * |
628 | * Currently, if a catalog name is given then it must equal the current |
629 | * database name; we check it here and then discard it. |
630 | *---------- |
631 | */ |
632 | switch (list_length(cref->fields)) |
633 | { |
634 | case 1: |
635 | { |
636 | Node *field1 = (Node *) linitial(cref->fields); |
637 | |
638 | Assert(IsA(field1, String)); |
639 | colname = strVal(field1); |
640 | |
641 | /* Try to identify as an unqualified column */ |
642 | node = colNameToVar(pstate, colname, false, cref->location); |
643 | |
644 | if (node == NULL) |
645 | { |
646 | /* |
647 | * Not known as a column of any range-table entry. |
648 | * |
649 | * Try to find the name as a relation. Note that only |
650 | * relations already entered into the rangetable will be |
651 | * recognized. |
652 | * |
653 | * This is a hack for backwards compatibility with |
654 | * PostQUEL-inspired syntax. The preferred form now is |
655 | * "rel.*". |
656 | */ |
657 | rte = refnameRangeTblEntry(pstate, NULL, colname, |
658 | cref->location, |
659 | &levels_up); |
660 | if (rte) |
661 | node = transformWholeRowRef(pstate, rte, |
662 | cref->location); |
663 | } |
664 | break; |
665 | } |
666 | case 2: |
667 | { |
668 | Node *field1 = (Node *) linitial(cref->fields); |
669 | Node *field2 = (Node *) lsecond(cref->fields); |
670 | |
671 | Assert(IsA(field1, String)); |
672 | relname = strVal(field1); |
673 | |
674 | /* Locate the referenced RTE */ |
675 | rte = refnameRangeTblEntry(pstate, nspname, relname, |
676 | cref->location, |
677 | &levels_up); |
678 | if (rte == NULL) |
679 | { |
680 | crerr = CRERR_NO_RTE; |
681 | break; |
682 | } |
683 | |
684 | /* Whole-row reference? */ |
685 | if (IsA(field2, A_Star)) |
686 | { |
687 | node = transformWholeRowRef(pstate, rte, cref->location); |
688 | break; |
689 | } |
690 | |
691 | Assert(IsA(field2, String)); |
692 | colname = strVal(field2); |
693 | |
694 | /* Try to identify as a column of the RTE */ |
695 | node = scanRTEForColumn(pstate, rte, colname, cref->location, |
696 | 0, NULL); |
697 | if (node == NULL) |
698 | { |
699 | /* Try it as a function call on the whole row */ |
700 | node = transformWholeRowRef(pstate, rte, cref->location); |
701 | node = ParseFuncOrColumn(pstate, |
702 | list_make1(makeString(colname)), |
703 | list_make1(node), |
704 | pstate->p_last_srf, |
705 | NULL, |
706 | false, |
707 | cref->location); |
708 | } |
709 | break; |
710 | } |
711 | case 3: |
712 | { |
713 | Node *field1 = (Node *) linitial(cref->fields); |
714 | Node *field2 = (Node *) lsecond(cref->fields); |
715 | Node *field3 = (Node *) lthird(cref->fields); |
716 | |
717 | Assert(IsA(field1, String)); |
718 | nspname = strVal(field1); |
719 | Assert(IsA(field2, String)); |
720 | relname = strVal(field2); |
721 | |
722 | /* Locate the referenced RTE */ |
723 | rte = refnameRangeTblEntry(pstate, nspname, relname, |
724 | cref->location, |
725 | &levels_up); |
726 | if (rte == NULL) |
727 | { |
728 | crerr = CRERR_NO_RTE; |
729 | break; |
730 | } |
731 | |
732 | /* Whole-row reference? */ |
733 | if (IsA(field3, A_Star)) |
734 | { |
735 | node = transformWholeRowRef(pstate, rte, cref->location); |
736 | break; |
737 | } |
738 | |
739 | Assert(IsA(field3, String)); |
740 | colname = strVal(field3); |
741 | |
742 | /* Try to identify as a column of the RTE */ |
743 | node = scanRTEForColumn(pstate, rte, colname, cref->location, |
744 | 0, NULL); |
745 | if (node == NULL) |
746 | { |
747 | /* Try it as a function call on the whole row */ |
748 | node = transformWholeRowRef(pstate, rte, cref->location); |
749 | node = ParseFuncOrColumn(pstate, |
750 | list_make1(makeString(colname)), |
751 | list_make1(node), |
752 | pstate->p_last_srf, |
753 | NULL, |
754 | false, |
755 | cref->location); |
756 | } |
757 | break; |
758 | } |
759 | case 4: |
760 | { |
761 | Node *field1 = (Node *) linitial(cref->fields); |
762 | Node *field2 = (Node *) lsecond(cref->fields); |
763 | Node *field3 = (Node *) lthird(cref->fields); |
764 | Node *field4 = (Node *) lfourth(cref->fields); |
765 | char *catname; |
766 | |
767 | Assert(IsA(field1, String)); |
768 | catname = strVal(field1); |
769 | Assert(IsA(field2, String)); |
770 | nspname = strVal(field2); |
771 | Assert(IsA(field3, String)); |
772 | relname = strVal(field3); |
773 | |
774 | /* |
775 | * We check the catalog name and then ignore it. |
776 | */ |
777 | if (strcmp(catname, get_database_name(MyDatabaseId)) != 0) |
778 | { |
779 | crerr = CRERR_WRONG_DB; |
780 | break; |
781 | } |
782 | |
783 | /* Locate the referenced RTE */ |
784 | rte = refnameRangeTblEntry(pstate, nspname, relname, |
785 | cref->location, |
786 | &levels_up); |
787 | if (rte == NULL) |
788 | { |
789 | crerr = CRERR_NO_RTE; |
790 | break; |
791 | } |
792 | |
793 | /* Whole-row reference? */ |
794 | if (IsA(field4, A_Star)) |
795 | { |
796 | node = transformWholeRowRef(pstate, rte, cref->location); |
797 | break; |
798 | } |
799 | |
800 | Assert(IsA(field4, String)); |
801 | colname = strVal(field4); |
802 | |
803 | /* Try to identify as a column of the RTE */ |
804 | node = scanRTEForColumn(pstate, rte, colname, cref->location, |
805 | 0, NULL); |
806 | if (node == NULL) |
807 | { |
808 | /* Try it as a function call on the whole row */ |
809 | node = transformWholeRowRef(pstate, rte, cref->location); |
810 | node = ParseFuncOrColumn(pstate, |
811 | list_make1(makeString(colname)), |
812 | list_make1(node), |
813 | pstate->p_last_srf, |
814 | NULL, |
815 | false, |
816 | cref->location); |
817 | } |
818 | break; |
819 | } |
820 | default: |
821 | crerr = CRERR_TOO_MANY; /* too many dotted names */ |
822 | break; |
823 | } |
824 | |
825 | /* |
826 | * Now give the PostParseColumnRefHook, if any, a chance. We pass the |
827 | * translation-so-far so that it can throw an error if it wishes in the |
828 | * case that it has a conflicting interpretation of the ColumnRef. (If it |
829 | * just translates anyway, we'll throw an error, because we can't undo |
830 | * whatever effects the preceding steps may have had on the pstate.) If it |
831 | * returns NULL, use the standard translation, or throw a suitable error |
832 | * if there is none. |
833 | */ |
834 | if (pstate->p_post_columnref_hook != NULL) |
835 | { |
836 | Node *hookresult; |
837 | |
838 | hookresult = pstate->p_post_columnref_hook(pstate, cref, node); |
839 | if (node == NULL) |
840 | node = hookresult; |
841 | else if (hookresult != NULL) |
842 | ereport(ERROR, |
843 | (errcode(ERRCODE_AMBIGUOUS_COLUMN), |
844 | errmsg("column reference \"%s\" is ambiguous" , |
845 | NameListToString(cref->fields)), |
846 | parser_errposition(pstate, cref->location))); |
847 | } |
848 | |
849 | /* |
850 | * Throw error if no translation found. |
851 | */ |
852 | if (node == NULL) |
853 | { |
854 | switch (crerr) |
855 | { |
856 | case CRERR_NO_COLUMN: |
857 | errorMissingColumn(pstate, relname, colname, cref->location); |
858 | break; |
859 | case CRERR_NO_RTE: |
860 | errorMissingRTE(pstate, makeRangeVar(nspname, relname, |
861 | cref->location)); |
862 | break; |
863 | case CRERR_WRONG_DB: |
864 | ereport(ERROR, |
865 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
866 | errmsg("cross-database references are not implemented: %s" , |
867 | NameListToString(cref->fields)), |
868 | parser_errposition(pstate, cref->location))); |
869 | break; |
870 | case CRERR_TOO_MANY: |
871 | ereport(ERROR, |
872 | (errcode(ERRCODE_SYNTAX_ERROR), |
873 | errmsg("improper qualified name (too many dotted names): %s" , |
874 | NameListToString(cref->fields)), |
875 | parser_errposition(pstate, cref->location))); |
876 | break; |
877 | } |
878 | } |
879 | |
880 | return node; |
881 | } |
882 | |
883 | static Node * |
884 | transformParamRef(ParseState *pstate, ParamRef *pref) |
885 | { |
886 | Node *result; |
887 | |
888 | /* |
889 | * The core parser knows nothing about Params. If a hook is supplied, |
890 | * call it. If not, or if the hook returns NULL, throw a generic error. |
891 | */ |
892 | if (pstate->p_paramref_hook != NULL) |
893 | result = pstate->p_paramref_hook(pstate, pref); |
894 | else |
895 | result = NULL; |
896 | |
897 | if (result == NULL) |
898 | ereport(ERROR, |
899 | (errcode(ERRCODE_UNDEFINED_PARAMETER), |
900 | errmsg("there is no parameter $%d" , pref->number), |
901 | parser_errposition(pstate, pref->location))); |
902 | |
903 | return result; |
904 | } |
905 | |
906 | /* Test whether an a_expr is a plain NULL constant or not */ |
907 | static bool |
908 | exprIsNullConstant(Node *arg) |
909 | { |
910 | if (arg && IsA(arg, A_Const)) |
911 | { |
912 | A_Const *con = (A_Const *) arg; |
913 | |
914 | if (con->val.type == T_Null) |
915 | return true; |
916 | } |
917 | return false; |
918 | } |
919 | |
920 | static Node * |
921 | transformAExprOp(ParseState *pstate, A_Expr *a) |
922 | { |
923 | Node *lexpr = a->lexpr; |
924 | Node *rexpr = a->rexpr; |
925 | Node *result; |
926 | |
927 | if (operator_precedence_warning) |
928 | { |
929 | int opgroup; |
930 | const char *opname; |
931 | |
932 | opgroup = operator_precedence_group((Node *) a, &opname); |
933 | if (opgroup > 0) |
934 | emit_precedence_warnings(pstate, opgroup, opname, |
935 | lexpr, rexpr, |
936 | a->location); |
937 | |
938 | /* Look through AEXPR_PAREN nodes so they don't affect tests below */ |
939 | while (lexpr && IsA(lexpr, A_Expr) && |
940 | ((A_Expr *) lexpr)->kind == AEXPR_PAREN) |
941 | lexpr = ((A_Expr *) lexpr)->lexpr; |
942 | while (rexpr && IsA(rexpr, A_Expr) && |
943 | ((A_Expr *) rexpr)->kind == AEXPR_PAREN) |
944 | rexpr = ((A_Expr *) rexpr)->lexpr; |
945 | } |
946 | |
947 | /* |
948 | * Special-case "foo = NULL" and "NULL = foo" for compatibility with |
949 | * standards-broken products (like Microsoft's). Turn these into IS NULL |
950 | * exprs. (If either side is a CaseTestExpr, then the expression was |
951 | * generated internally from a CASE-WHEN expression, and |
952 | * transform_null_equals does not apply.) |
953 | */ |
954 | if (Transform_null_equals && |
955 | list_length(a->name) == 1 && |
956 | strcmp(strVal(linitial(a->name)), "=" ) == 0 && |
957 | (exprIsNullConstant(lexpr) || exprIsNullConstant(rexpr)) && |
958 | (!IsA(lexpr, CaseTestExpr) &&!IsA(rexpr, CaseTestExpr))) |
959 | { |
960 | NullTest *n = makeNode(NullTest); |
961 | |
962 | n->nulltesttype = IS_NULL; |
963 | n->location = a->location; |
964 | |
965 | if (exprIsNullConstant(lexpr)) |
966 | n->arg = (Expr *) rexpr; |
967 | else |
968 | n->arg = (Expr *) lexpr; |
969 | |
970 | result = transformExprRecurse(pstate, (Node *) n); |
971 | } |
972 | else if (lexpr && IsA(lexpr, RowExpr) && |
973 | rexpr && IsA(rexpr, SubLink) && |
974 | ((SubLink *) rexpr)->subLinkType == EXPR_SUBLINK) |
975 | { |
976 | /* |
977 | * Convert "row op subselect" into a ROWCOMPARE sublink. Formerly the |
978 | * grammar did this, but now that a row construct is allowed anywhere |
979 | * in expressions, it's easier to do it here. |
980 | */ |
981 | SubLink *s = (SubLink *) rexpr; |
982 | |
983 | s->subLinkType = ROWCOMPARE_SUBLINK; |
984 | s->testexpr = lexpr; |
985 | s->operName = a->name; |
986 | s->location = a->location; |
987 | result = transformExprRecurse(pstate, (Node *) s); |
988 | } |
989 | else if (lexpr && IsA(lexpr, RowExpr) && |
990 | rexpr && IsA(rexpr, RowExpr)) |
991 | { |
992 | /* ROW() op ROW() is handled specially */ |
993 | lexpr = transformExprRecurse(pstate, lexpr); |
994 | rexpr = transformExprRecurse(pstate, rexpr); |
995 | |
996 | result = make_row_comparison_op(pstate, |
997 | a->name, |
998 | castNode(RowExpr, lexpr)->args, |
999 | castNode(RowExpr, rexpr)->args, |
1000 | a->location); |
1001 | } |
1002 | else |
1003 | { |
1004 | /* Ordinary scalar operator */ |
1005 | Node *last_srf = pstate->p_last_srf; |
1006 | |
1007 | lexpr = transformExprRecurse(pstate, lexpr); |
1008 | rexpr = transformExprRecurse(pstate, rexpr); |
1009 | |
1010 | result = (Node *) make_op(pstate, |
1011 | a->name, |
1012 | lexpr, |
1013 | rexpr, |
1014 | last_srf, |
1015 | a->location); |
1016 | } |
1017 | |
1018 | return result; |
1019 | } |
1020 | |
1021 | static Node * |
1022 | transformAExprOpAny(ParseState *pstate, A_Expr *a) |
1023 | { |
1024 | Node *lexpr = a->lexpr; |
1025 | Node *rexpr = a->rexpr; |
1026 | |
1027 | if (operator_precedence_warning) |
1028 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_OP, |
1029 | strVal(llast(a->name)), |
1030 | lexpr, NULL, |
1031 | a->location); |
1032 | |
1033 | lexpr = transformExprRecurse(pstate, lexpr); |
1034 | rexpr = transformExprRecurse(pstate, rexpr); |
1035 | |
1036 | return (Node *) make_scalar_array_op(pstate, |
1037 | a->name, |
1038 | true, |
1039 | lexpr, |
1040 | rexpr, |
1041 | a->location); |
1042 | } |
1043 | |
1044 | static Node * |
1045 | transformAExprOpAll(ParseState *pstate, A_Expr *a) |
1046 | { |
1047 | Node *lexpr = a->lexpr; |
1048 | Node *rexpr = a->rexpr; |
1049 | |
1050 | if (operator_precedence_warning) |
1051 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_OP, |
1052 | strVal(llast(a->name)), |
1053 | lexpr, NULL, |
1054 | a->location); |
1055 | |
1056 | lexpr = transformExprRecurse(pstate, lexpr); |
1057 | rexpr = transformExprRecurse(pstate, rexpr); |
1058 | |
1059 | return (Node *) make_scalar_array_op(pstate, |
1060 | a->name, |
1061 | false, |
1062 | lexpr, |
1063 | rexpr, |
1064 | a->location); |
1065 | } |
1066 | |
1067 | static Node * |
1068 | transformAExprDistinct(ParseState *pstate, A_Expr *a) |
1069 | { |
1070 | Node *lexpr = a->lexpr; |
1071 | Node *rexpr = a->rexpr; |
1072 | Node *result; |
1073 | |
1074 | if (operator_precedence_warning) |
1075 | emit_precedence_warnings(pstate, PREC_GROUP_INFIX_IS, "IS" , |
1076 | lexpr, rexpr, |
1077 | a->location); |
1078 | |
1079 | /* |
1080 | * If either input is an undecorated NULL literal, transform to a NullTest |
1081 | * on the other input. That's simpler to process than a full DistinctExpr, |
1082 | * and it avoids needing to require that the datatype have an = operator. |
1083 | */ |
1084 | if (exprIsNullConstant(rexpr)) |
1085 | return make_nulltest_from_distinct(pstate, a, lexpr); |
1086 | if (exprIsNullConstant(lexpr)) |
1087 | return make_nulltest_from_distinct(pstate, a, rexpr); |
1088 | |
1089 | lexpr = transformExprRecurse(pstate, lexpr); |
1090 | rexpr = transformExprRecurse(pstate, rexpr); |
1091 | |
1092 | if (lexpr && IsA(lexpr, RowExpr) && |
1093 | rexpr && IsA(rexpr, RowExpr)) |
1094 | { |
1095 | /* ROW() op ROW() is handled specially */ |
1096 | result = make_row_distinct_op(pstate, a->name, |
1097 | (RowExpr *) lexpr, |
1098 | (RowExpr *) rexpr, |
1099 | a->location); |
1100 | } |
1101 | else |
1102 | { |
1103 | /* Ordinary scalar operator */ |
1104 | result = (Node *) make_distinct_op(pstate, |
1105 | a->name, |
1106 | lexpr, |
1107 | rexpr, |
1108 | a->location); |
1109 | } |
1110 | |
1111 | /* |
1112 | * If it's NOT DISTINCT, we first build a DistinctExpr and then stick a |
1113 | * NOT on top. |
1114 | */ |
1115 | if (a->kind == AEXPR_NOT_DISTINCT) |
1116 | result = (Node *) makeBoolExpr(NOT_EXPR, |
1117 | list_make1(result), |
1118 | a->location); |
1119 | |
1120 | return result; |
1121 | } |
1122 | |
1123 | static Node * |
1124 | transformAExprNullIf(ParseState *pstate, A_Expr *a) |
1125 | { |
1126 | Node *lexpr = transformExprRecurse(pstate, a->lexpr); |
1127 | Node *rexpr = transformExprRecurse(pstate, a->rexpr); |
1128 | OpExpr *result; |
1129 | |
1130 | result = (OpExpr *) make_op(pstate, |
1131 | a->name, |
1132 | lexpr, |
1133 | rexpr, |
1134 | pstate->p_last_srf, |
1135 | a->location); |
1136 | |
1137 | /* |
1138 | * The comparison operator itself should yield boolean ... |
1139 | */ |
1140 | if (result->opresulttype != BOOLOID) |
1141 | ereport(ERROR, |
1142 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
1143 | errmsg("NULLIF requires = operator to yield boolean" ), |
1144 | parser_errposition(pstate, a->location))); |
1145 | if (result->opretset) |
1146 | ereport(ERROR, |
1147 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
1148 | /* translator: %s is name of a SQL construct, eg NULLIF */ |
1149 | errmsg("%s must not return a set" , "NULLIF" ), |
1150 | parser_errposition(pstate, a->location))); |
1151 | |
1152 | /* |
1153 | * ... but the NullIfExpr will yield the first operand's type. |
1154 | */ |
1155 | result->opresulttype = exprType((Node *) linitial(result->args)); |
1156 | |
1157 | /* |
1158 | * We rely on NullIfExpr and OpExpr being the same struct |
1159 | */ |
1160 | NodeSetTag(result, T_NullIfExpr); |
1161 | |
1162 | return (Node *) result; |
1163 | } |
1164 | |
1165 | /* |
1166 | * Checking an expression for match to a list of type names. Will result |
1167 | * in a boolean constant node. |
1168 | */ |
1169 | static Node * |
1170 | transformAExprOf(ParseState *pstate, A_Expr *a) |
1171 | { |
1172 | Node *lexpr = a->lexpr; |
1173 | Const *result; |
1174 | ListCell *telem; |
1175 | Oid ltype, |
1176 | rtype; |
1177 | bool matched = false; |
1178 | |
1179 | if (operator_precedence_warning) |
1180 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS" , |
1181 | lexpr, NULL, |
1182 | a->location); |
1183 | |
1184 | lexpr = transformExprRecurse(pstate, lexpr); |
1185 | |
1186 | ltype = exprType(lexpr); |
1187 | foreach(telem, (List *) a->rexpr) |
1188 | { |
1189 | rtype = typenameTypeId(pstate, lfirst(telem)); |
1190 | matched = (rtype == ltype); |
1191 | if (matched) |
1192 | break; |
1193 | } |
1194 | |
1195 | /* |
1196 | * We have two forms: equals or not equals. Flip the sense of the result |
1197 | * for not equals. |
1198 | */ |
1199 | if (strcmp(strVal(linitial(a->name)), "<>" ) == 0) |
1200 | matched = (!matched); |
1201 | |
1202 | result = (Const *) makeBoolConst(matched, false); |
1203 | |
1204 | /* Make the result have the original input's parse location */ |
1205 | result->location = exprLocation((Node *) a); |
1206 | |
1207 | return (Node *) result; |
1208 | } |
1209 | |
1210 | static Node * |
1211 | transformAExprIn(ParseState *pstate, A_Expr *a) |
1212 | { |
1213 | Node *result = NULL; |
1214 | Node *lexpr; |
1215 | List *rexprs; |
1216 | List *rvars; |
1217 | List *rnonvars; |
1218 | bool useOr; |
1219 | ListCell *l; |
1220 | |
1221 | /* |
1222 | * If the operator is <>, combine with AND not OR. |
1223 | */ |
1224 | if (strcmp(strVal(linitial(a->name)), "<>" ) == 0) |
1225 | useOr = false; |
1226 | else |
1227 | useOr = true; |
1228 | |
1229 | if (operator_precedence_warning) |
1230 | emit_precedence_warnings(pstate, |
1231 | useOr ? PREC_GROUP_IN : PREC_GROUP_NOT_IN, |
1232 | "IN" , |
1233 | a->lexpr, NULL, |
1234 | a->location); |
1235 | |
1236 | /* |
1237 | * We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only |
1238 | * possible if there is a suitable array type available. If not, we fall |
1239 | * back to a boolean condition tree with multiple copies of the lefthand |
1240 | * expression. Also, any IN-list items that contain Vars are handled as |
1241 | * separate boolean conditions, because that gives the planner more scope |
1242 | * for optimization on such clauses. |
1243 | * |
1244 | * First step: transform all the inputs, and detect whether any contain |
1245 | * Vars. |
1246 | */ |
1247 | lexpr = transformExprRecurse(pstate, a->lexpr); |
1248 | rexprs = rvars = rnonvars = NIL; |
1249 | foreach(l, (List *) a->rexpr) |
1250 | { |
1251 | Node *rexpr = transformExprRecurse(pstate, lfirst(l)); |
1252 | |
1253 | rexprs = lappend(rexprs, rexpr); |
1254 | if (contain_vars_of_level(rexpr, 0)) |
1255 | rvars = lappend(rvars, rexpr); |
1256 | else |
1257 | rnonvars = lappend(rnonvars, rexpr); |
1258 | } |
1259 | |
1260 | /* |
1261 | * ScalarArrayOpExpr is only going to be useful if there's more than one |
1262 | * non-Var righthand item. |
1263 | */ |
1264 | if (list_length(rnonvars) > 1) |
1265 | { |
1266 | List *allexprs; |
1267 | Oid scalar_type; |
1268 | Oid array_type; |
1269 | |
1270 | /* |
1271 | * Try to select a common type for the array elements. Note that |
1272 | * since the LHS' type is first in the list, it will be preferred when |
1273 | * there is doubt (eg, when all the RHS items are unknown literals). |
1274 | * |
1275 | * Note: use list_concat here not lcons, to avoid damaging rnonvars. |
1276 | */ |
1277 | allexprs = list_concat(list_make1(lexpr), rnonvars); |
1278 | scalar_type = select_common_type(pstate, allexprs, NULL, NULL); |
1279 | |
1280 | /* |
1281 | * Do we have an array type to use? Aside from the case where there |
1282 | * isn't one, we don't risk using ScalarArrayOpExpr when the common |
1283 | * type is RECORD, because the RowExpr comparison logic below can cope |
1284 | * with some cases of non-identical row types. |
1285 | */ |
1286 | if (OidIsValid(scalar_type) && scalar_type != RECORDOID) |
1287 | array_type = get_array_type(scalar_type); |
1288 | else |
1289 | array_type = InvalidOid; |
1290 | if (array_type != InvalidOid) |
1291 | { |
1292 | /* |
1293 | * OK: coerce all the right-hand non-Var inputs to the common type |
1294 | * and build an ArrayExpr for them. |
1295 | */ |
1296 | List *aexprs; |
1297 | ArrayExpr *newa; |
1298 | |
1299 | aexprs = NIL; |
1300 | foreach(l, rnonvars) |
1301 | { |
1302 | Node *rexpr = (Node *) lfirst(l); |
1303 | |
1304 | rexpr = coerce_to_common_type(pstate, rexpr, |
1305 | scalar_type, |
1306 | "IN" ); |
1307 | aexprs = lappend(aexprs, rexpr); |
1308 | } |
1309 | newa = makeNode(ArrayExpr); |
1310 | newa->array_typeid = array_type; |
1311 | /* array_collid will be set by parse_collate.c */ |
1312 | newa->element_typeid = scalar_type; |
1313 | newa->elements = aexprs; |
1314 | newa->multidims = false; |
1315 | newa->location = -1; |
1316 | |
1317 | result = (Node *) make_scalar_array_op(pstate, |
1318 | a->name, |
1319 | useOr, |
1320 | lexpr, |
1321 | (Node *) newa, |
1322 | a->location); |
1323 | |
1324 | /* Consider only the Vars (if any) in the loop below */ |
1325 | rexprs = rvars; |
1326 | } |
1327 | } |
1328 | |
1329 | /* |
1330 | * Must do it the hard way, ie, with a boolean expression tree. |
1331 | */ |
1332 | foreach(l, rexprs) |
1333 | { |
1334 | Node *rexpr = (Node *) lfirst(l); |
1335 | Node *cmp; |
1336 | |
1337 | if (IsA(lexpr, RowExpr) && |
1338 | IsA(rexpr, RowExpr)) |
1339 | { |
1340 | /* ROW() op ROW() is handled specially */ |
1341 | cmp = make_row_comparison_op(pstate, |
1342 | a->name, |
1343 | copyObject(((RowExpr *) lexpr)->args), |
1344 | ((RowExpr *) rexpr)->args, |
1345 | a->location); |
1346 | } |
1347 | else |
1348 | { |
1349 | /* Ordinary scalar operator */ |
1350 | cmp = (Node *) make_op(pstate, |
1351 | a->name, |
1352 | copyObject(lexpr), |
1353 | rexpr, |
1354 | pstate->p_last_srf, |
1355 | a->location); |
1356 | } |
1357 | |
1358 | cmp = coerce_to_boolean(pstate, cmp, "IN" ); |
1359 | if (result == NULL) |
1360 | result = cmp; |
1361 | else |
1362 | result = (Node *) makeBoolExpr(useOr ? OR_EXPR : AND_EXPR, |
1363 | list_make2(result, cmp), |
1364 | a->location); |
1365 | } |
1366 | |
1367 | return result; |
1368 | } |
1369 | |
1370 | static Node * |
1371 | transformAExprBetween(ParseState *pstate, A_Expr *a) |
1372 | { |
1373 | Node *aexpr; |
1374 | Node *bexpr; |
1375 | Node *cexpr; |
1376 | Node *result; |
1377 | Node *sub1; |
1378 | Node *sub2; |
1379 | List *args; |
1380 | |
1381 | /* Deconstruct A_Expr into three subexprs */ |
1382 | aexpr = a->lexpr; |
1383 | args = castNode(List, a->rexpr); |
1384 | Assert(list_length(args) == 2); |
1385 | bexpr = (Node *) linitial(args); |
1386 | cexpr = (Node *) lsecond(args); |
1387 | |
1388 | if (operator_precedence_warning) |
1389 | { |
1390 | int opgroup; |
1391 | const char *opname; |
1392 | |
1393 | opgroup = operator_precedence_group((Node *) a, &opname); |
1394 | emit_precedence_warnings(pstate, opgroup, opname, |
1395 | aexpr, cexpr, |
1396 | a->location); |
1397 | /* We can ignore bexpr thanks to syntactic restrictions */ |
1398 | /* Wrap subexpressions to prevent extra warnings */ |
1399 | aexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, aexpr, NULL, -1); |
1400 | bexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, bexpr, NULL, -1); |
1401 | cexpr = (Node *) makeA_Expr(AEXPR_PAREN, NIL, cexpr, NULL, -1); |
1402 | } |
1403 | |
1404 | /* |
1405 | * Build the equivalent comparison expression. Make copies of |
1406 | * multiply-referenced subexpressions for safety. (XXX this is really |
1407 | * wrong since it results in multiple runtime evaluations of what may be |
1408 | * volatile expressions ...) |
1409 | * |
1410 | * Ideally we would not use hard-wired operators here but instead use |
1411 | * opclasses. However, mixed data types and other issues make this |
1412 | * difficult: |
1413 | * http://archives.postgresql.org/pgsql-hackers/2008-08/msg01142.php |
1414 | */ |
1415 | switch (a->kind) |
1416 | { |
1417 | case AEXPR_BETWEEN: |
1418 | args = list_make2(makeSimpleA_Expr(AEXPR_OP, ">=" , |
1419 | aexpr, bexpr, |
1420 | a->location), |
1421 | makeSimpleA_Expr(AEXPR_OP, "<=" , |
1422 | copyObject(aexpr), cexpr, |
1423 | a->location)); |
1424 | result = (Node *) makeBoolExpr(AND_EXPR, args, a->location); |
1425 | break; |
1426 | case AEXPR_NOT_BETWEEN: |
1427 | args = list_make2(makeSimpleA_Expr(AEXPR_OP, "<" , |
1428 | aexpr, bexpr, |
1429 | a->location), |
1430 | makeSimpleA_Expr(AEXPR_OP, ">" , |
1431 | copyObject(aexpr), cexpr, |
1432 | a->location)); |
1433 | result = (Node *) makeBoolExpr(OR_EXPR, args, a->location); |
1434 | break; |
1435 | case AEXPR_BETWEEN_SYM: |
1436 | args = list_make2(makeSimpleA_Expr(AEXPR_OP, ">=" , |
1437 | aexpr, bexpr, |
1438 | a->location), |
1439 | makeSimpleA_Expr(AEXPR_OP, "<=" , |
1440 | copyObject(aexpr), cexpr, |
1441 | a->location)); |
1442 | sub1 = (Node *) makeBoolExpr(AND_EXPR, args, a->location); |
1443 | args = list_make2(makeSimpleA_Expr(AEXPR_OP, ">=" , |
1444 | copyObject(aexpr), copyObject(cexpr), |
1445 | a->location), |
1446 | makeSimpleA_Expr(AEXPR_OP, "<=" , |
1447 | copyObject(aexpr), copyObject(bexpr), |
1448 | a->location)); |
1449 | sub2 = (Node *) makeBoolExpr(AND_EXPR, args, a->location); |
1450 | args = list_make2(sub1, sub2); |
1451 | result = (Node *) makeBoolExpr(OR_EXPR, args, a->location); |
1452 | break; |
1453 | case AEXPR_NOT_BETWEEN_SYM: |
1454 | args = list_make2(makeSimpleA_Expr(AEXPR_OP, "<" , |
1455 | aexpr, bexpr, |
1456 | a->location), |
1457 | makeSimpleA_Expr(AEXPR_OP, ">" , |
1458 | copyObject(aexpr), cexpr, |
1459 | a->location)); |
1460 | sub1 = (Node *) makeBoolExpr(OR_EXPR, args, a->location); |
1461 | args = list_make2(makeSimpleA_Expr(AEXPR_OP, "<" , |
1462 | copyObject(aexpr), copyObject(cexpr), |
1463 | a->location), |
1464 | makeSimpleA_Expr(AEXPR_OP, ">" , |
1465 | copyObject(aexpr), copyObject(bexpr), |
1466 | a->location)); |
1467 | sub2 = (Node *) makeBoolExpr(OR_EXPR, args, a->location); |
1468 | args = list_make2(sub1, sub2); |
1469 | result = (Node *) makeBoolExpr(AND_EXPR, args, a->location); |
1470 | break; |
1471 | default: |
1472 | elog(ERROR, "unrecognized A_Expr kind: %d" , a->kind); |
1473 | result = NULL; /* keep compiler quiet */ |
1474 | break; |
1475 | } |
1476 | |
1477 | return transformExprRecurse(pstate, result); |
1478 | } |
1479 | |
1480 | static Node * |
1481 | transformBoolExpr(ParseState *pstate, BoolExpr *a) |
1482 | { |
1483 | List *args = NIL; |
1484 | const char *opname; |
1485 | ListCell *lc; |
1486 | |
1487 | switch (a->boolop) |
1488 | { |
1489 | case AND_EXPR: |
1490 | opname = "AND" ; |
1491 | break; |
1492 | case OR_EXPR: |
1493 | opname = "OR" ; |
1494 | break; |
1495 | case NOT_EXPR: |
1496 | opname = "NOT" ; |
1497 | break; |
1498 | default: |
1499 | elog(ERROR, "unrecognized boolop: %d" , (int) a->boolop); |
1500 | opname = NULL; /* keep compiler quiet */ |
1501 | break; |
1502 | } |
1503 | |
1504 | foreach(lc, a->args) |
1505 | { |
1506 | Node *arg = (Node *) lfirst(lc); |
1507 | |
1508 | arg = transformExprRecurse(pstate, arg); |
1509 | arg = coerce_to_boolean(pstate, arg, opname); |
1510 | args = lappend(args, arg); |
1511 | } |
1512 | |
1513 | return (Node *) makeBoolExpr(a->boolop, args, a->location); |
1514 | } |
1515 | |
1516 | static Node * |
1517 | transformFuncCall(ParseState *pstate, FuncCall *fn) |
1518 | { |
1519 | Node *last_srf = pstate->p_last_srf; |
1520 | List *targs; |
1521 | ListCell *args; |
1522 | |
1523 | /* Transform the list of arguments ... */ |
1524 | targs = NIL; |
1525 | foreach(args, fn->args) |
1526 | { |
1527 | targs = lappend(targs, transformExprRecurse(pstate, |
1528 | (Node *) lfirst(args))); |
1529 | } |
1530 | |
1531 | /* |
1532 | * When WITHIN GROUP is used, we treat its ORDER BY expressions as |
1533 | * additional arguments to the function, for purposes of function lookup |
1534 | * and argument type coercion. So, transform each such expression and add |
1535 | * them to the targs list. We don't explicitly mark where each argument |
1536 | * came from, but ParseFuncOrColumn can tell what's what by reference to |
1537 | * list_length(fn->agg_order). |
1538 | */ |
1539 | if (fn->agg_within_group) |
1540 | { |
1541 | Assert(fn->agg_order != NIL); |
1542 | foreach(args, fn->agg_order) |
1543 | { |
1544 | SortBy *arg = (SortBy *) lfirst(args); |
1545 | |
1546 | targs = lappend(targs, transformExpr(pstate, arg->node, |
1547 | EXPR_KIND_ORDER_BY)); |
1548 | } |
1549 | } |
1550 | |
1551 | /* ... and hand off to ParseFuncOrColumn */ |
1552 | return ParseFuncOrColumn(pstate, |
1553 | fn->funcname, |
1554 | targs, |
1555 | last_srf, |
1556 | fn, |
1557 | false, |
1558 | fn->location); |
1559 | } |
1560 | |
1561 | static Node * |
1562 | transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref) |
1563 | { |
1564 | SubLink *sublink; |
1565 | RowExpr *rexpr; |
1566 | Query *qtree; |
1567 | TargetEntry *tle; |
1568 | |
1569 | /* We should only see this in first-stage processing of UPDATE tlists */ |
1570 | Assert(pstate->p_expr_kind == EXPR_KIND_UPDATE_SOURCE); |
1571 | |
1572 | /* We only need to transform the source if this is the first column */ |
1573 | if (maref->colno == 1) |
1574 | { |
1575 | /* |
1576 | * For now, we only allow EXPR SubLinks and RowExprs as the source of |
1577 | * an UPDATE multiassignment. This is sufficient to cover interesting |
1578 | * cases; at worst, someone would have to write (SELECT * FROM expr) |
1579 | * to expand a composite-returning expression of another form. |
1580 | */ |
1581 | if (IsA(maref->source, SubLink) && |
1582 | ((SubLink *) maref->source)->subLinkType == EXPR_SUBLINK) |
1583 | { |
1584 | /* Relabel it as a MULTIEXPR_SUBLINK */ |
1585 | sublink = (SubLink *) maref->source; |
1586 | sublink->subLinkType = MULTIEXPR_SUBLINK; |
1587 | /* And transform it */ |
1588 | sublink = (SubLink *) transformExprRecurse(pstate, |
1589 | (Node *) sublink); |
1590 | |
1591 | qtree = castNode(Query, sublink->subselect); |
1592 | |
1593 | /* Check subquery returns required number of columns */ |
1594 | if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns) |
1595 | ereport(ERROR, |
1596 | (errcode(ERRCODE_SYNTAX_ERROR), |
1597 | errmsg("number of columns does not match number of values" ), |
1598 | parser_errposition(pstate, sublink->location))); |
1599 | |
1600 | /* |
1601 | * Build a resjunk tlist item containing the MULTIEXPR SubLink, |
1602 | * and add it to pstate->p_multiassign_exprs, whence it will later |
1603 | * get appended to the completed targetlist. We needn't worry |
1604 | * about selecting a resno for it; transformUpdateStmt will do |
1605 | * that. |
1606 | */ |
1607 | tle = makeTargetEntry((Expr *) sublink, 0, NULL, true); |
1608 | pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs, |
1609 | tle); |
1610 | |
1611 | /* |
1612 | * Assign a unique-within-this-targetlist ID to the MULTIEXPR |
1613 | * SubLink. We can just use its position in the |
1614 | * p_multiassign_exprs list. |
1615 | */ |
1616 | sublink->subLinkId = list_length(pstate->p_multiassign_exprs); |
1617 | } |
1618 | else if (IsA(maref->source, RowExpr)) |
1619 | { |
1620 | /* Transform the RowExpr, allowing SetToDefault items */ |
1621 | rexpr = (RowExpr *) transformRowExpr(pstate, |
1622 | (RowExpr *) maref->source, |
1623 | true); |
1624 | |
1625 | /* Check it returns required number of columns */ |
1626 | if (list_length(rexpr->args) != maref->ncolumns) |
1627 | ereport(ERROR, |
1628 | (errcode(ERRCODE_SYNTAX_ERROR), |
1629 | errmsg("number of columns does not match number of values" ), |
1630 | parser_errposition(pstate, rexpr->location))); |
1631 | |
1632 | /* |
1633 | * Temporarily append it to p_multiassign_exprs, so we can get it |
1634 | * back when we come back here for additional columns. |
1635 | */ |
1636 | tle = makeTargetEntry((Expr *) rexpr, 0, NULL, true); |
1637 | pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs, |
1638 | tle); |
1639 | } |
1640 | else |
1641 | ereport(ERROR, |
1642 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
1643 | errmsg("source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression" ), |
1644 | parser_errposition(pstate, exprLocation(maref->source)))); |
1645 | } |
1646 | else |
1647 | { |
1648 | /* |
1649 | * Second or later column in a multiassignment. Re-fetch the |
1650 | * transformed SubLink or RowExpr, which we assume is still the last |
1651 | * entry in p_multiassign_exprs. |
1652 | */ |
1653 | Assert(pstate->p_multiassign_exprs != NIL); |
1654 | tle = (TargetEntry *) llast(pstate->p_multiassign_exprs); |
1655 | } |
1656 | |
1657 | /* |
1658 | * Emit the appropriate output expression for the current column |
1659 | */ |
1660 | if (IsA(tle->expr, SubLink)) |
1661 | { |
1662 | Param *param; |
1663 | |
1664 | sublink = (SubLink *) tle->expr; |
1665 | Assert(sublink->subLinkType == MULTIEXPR_SUBLINK); |
1666 | qtree = castNode(Query, sublink->subselect); |
1667 | |
1668 | /* Build a Param representing the current subquery output column */ |
1669 | tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1); |
1670 | Assert(!tle->resjunk); |
1671 | |
1672 | param = makeNode(Param); |
1673 | param->paramkind = PARAM_MULTIEXPR; |
1674 | param->paramid = (sublink->subLinkId << 16) | maref->colno; |
1675 | param->paramtype = exprType((Node *) tle->expr); |
1676 | param->paramtypmod = exprTypmod((Node *) tle->expr); |
1677 | param->paramcollid = exprCollation((Node *) tle->expr); |
1678 | param->location = exprLocation((Node *) tle->expr); |
1679 | |
1680 | return (Node *) param; |
1681 | } |
1682 | |
1683 | if (IsA(tle->expr, RowExpr)) |
1684 | { |
1685 | Node *result; |
1686 | |
1687 | rexpr = (RowExpr *) tle->expr; |
1688 | |
1689 | /* Just extract and return the next element of the RowExpr */ |
1690 | result = (Node *) list_nth(rexpr->args, maref->colno - 1); |
1691 | |
1692 | /* |
1693 | * If we're at the last column, delete the RowExpr from |
1694 | * p_multiassign_exprs; we don't need it anymore, and don't want it in |
1695 | * the finished UPDATE tlist. |
1696 | */ |
1697 | if (maref->colno == maref->ncolumns) |
1698 | pstate->p_multiassign_exprs = |
1699 | list_delete_ptr(pstate->p_multiassign_exprs, tle); |
1700 | |
1701 | return result; |
1702 | } |
1703 | |
1704 | elog(ERROR, "unexpected expr type in multiassign list" ); |
1705 | return NULL; /* keep compiler quiet */ |
1706 | } |
1707 | |
1708 | static Node * |
1709 | transformCaseExpr(ParseState *pstate, CaseExpr *c) |
1710 | { |
1711 | CaseExpr *newc = makeNode(CaseExpr); |
1712 | Node *last_srf = pstate->p_last_srf; |
1713 | Node *arg; |
1714 | CaseTestExpr *placeholder; |
1715 | List *newargs; |
1716 | List *resultexprs; |
1717 | ListCell *l; |
1718 | Node *defresult; |
1719 | Oid ptype; |
1720 | |
1721 | /* transform the test expression, if any */ |
1722 | arg = transformExprRecurse(pstate, (Node *) c->arg); |
1723 | |
1724 | /* generate placeholder for test expression */ |
1725 | if (arg) |
1726 | { |
1727 | /* |
1728 | * If test expression is an untyped literal, force it to text. We have |
1729 | * to do something now because we won't be able to do this coercion on |
1730 | * the placeholder. This is not as flexible as what was done in 7.4 |
1731 | * and before, but it's good enough to handle the sort of silly coding |
1732 | * commonly seen. |
1733 | */ |
1734 | if (exprType(arg) == UNKNOWNOID) |
1735 | arg = coerce_to_common_type(pstate, arg, TEXTOID, "CASE" ); |
1736 | |
1737 | /* |
1738 | * Run collation assignment on the test expression so that we know |
1739 | * what collation to mark the placeholder with. In principle we could |
1740 | * leave it to parse_collate.c to do that later, but propagating the |
1741 | * result to the CaseTestExpr would be unnecessarily complicated. |
1742 | */ |
1743 | assign_expr_collations(pstate, arg); |
1744 | |
1745 | placeholder = makeNode(CaseTestExpr); |
1746 | placeholder->typeId = exprType(arg); |
1747 | placeholder->typeMod = exprTypmod(arg); |
1748 | placeholder->collation = exprCollation(arg); |
1749 | } |
1750 | else |
1751 | placeholder = NULL; |
1752 | |
1753 | newc->arg = (Expr *) arg; |
1754 | |
1755 | /* transform the list of arguments */ |
1756 | newargs = NIL; |
1757 | resultexprs = NIL; |
1758 | foreach(l, c->args) |
1759 | { |
1760 | CaseWhen *w = lfirst_node(CaseWhen, l); |
1761 | CaseWhen *neww = makeNode(CaseWhen); |
1762 | Node *warg; |
1763 | |
1764 | warg = (Node *) w->expr; |
1765 | if (placeholder) |
1766 | { |
1767 | /* shorthand form was specified, so expand... */ |
1768 | warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=" , |
1769 | (Node *) placeholder, |
1770 | warg, |
1771 | w->location); |
1772 | } |
1773 | neww->expr = (Expr *) transformExprRecurse(pstate, warg); |
1774 | |
1775 | neww->expr = (Expr *) coerce_to_boolean(pstate, |
1776 | (Node *) neww->expr, |
1777 | "CASE/WHEN" ); |
1778 | |
1779 | warg = (Node *) w->result; |
1780 | neww->result = (Expr *) transformExprRecurse(pstate, warg); |
1781 | neww->location = w->location; |
1782 | |
1783 | newargs = lappend(newargs, neww); |
1784 | resultexprs = lappend(resultexprs, neww->result); |
1785 | } |
1786 | |
1787 | newc->args = newargs; |
1788 | |
1789 | /* transform the default clause */ |
1790 | defresult = (Node *) c->defresult; |
1791 | if (defresult == NULL) |
1792 | { |
1793 | A_Const *n = makeNode(A_Const); |
1794 | |
1795 | n->val.type = T_Null; |
1796 | n->location = -1; |
1797 | defresult = (Node *) n; |
1798 | } |
1799 | newc->defresult = (Expr *) transformExprRecurse(pstate, defresult); |
1800 | |
1801 | /* |
1802 | * Note: default result is considered the most significant type in |
1803 | * determining preferred type. This is how the code worked before, but it |
1804 | * seems a little bogus to me --- tgl |
1805 | */ |
1806 | resultexprs = lcons(newc->defresult, resultexprs); |
1807 | |
1808 | ptype = select_common_type(pstate, resultexprs, "CASE" , NULL); |
1809 | Assert(OidIsValid(ptype)); |
1810 | newc->casetype = ptype; |
1811 | /* casecollid will be set by parse_collate.c */ |
1812 | |
1813 | /* Convert default result clause, if necessary */ |
1814 | newc->defresult = (Expr *) |
1815 | coerce_to_common_type(pstate, |
1816 | (Node *) newc->defresult, |
1817 | ptype, |
1818 | "CASE/ELSE" ); |
1819 | |
1820 | /* Convert when-clause results, if necessary */ |
1821 | foreach(l, newc->args) |
1822 | { |
1823 | CaseWhen *w = (CaseWhen *) lfirst(l); |
1824 | |
1825 | w->result = (Expr *) |
1826 | coerce_to_common_type(pstate, |
1827 | (Node *) w->result, |
1828 | ptype, |
1829 | "CASE/WHEN" ); |
1830 | } |
1831 | |
1832 | /* if any subexpression contained a SRF, complain */ |
1833 | if (pstate->p_last_srf != last_srf) |
1834 | ereport(ERROR, |
1835 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
1836 | /* translator: %s is name of a SQL construct, eg GROUP BY */ |
1837 | errmsg("set-returning functions are not allowed in %s" , |
1838 | "CASE" ), |
1839 | errhint("You might be able to move the set-returning function into a LATERAL FROM item." ), |
1840 | parser_errposition(pstate, |
1841 | exprLocation(pstate->p_last_srf)))); |
1842 | |
1843 | newc->location = c->location; |
1844 | |
1845 | return (Node *) newc; |
1846 | } |
1847 | |
1848 | static Node * |
1849 | transformSubLink(ParseState *pstate, SubLink *sublink) |
1850 | { |
1851 | Node *result = (Node *) sublink; |
1852 | Query *qtree; |
1853 | const char *err; |
1854 | |
1855 | /* |
1856 | * Check to see if the sublink is in an invalid place within the query. We |
1857 | * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE, but generally |
1858 | * not in utility statements. |
1859 | */ |
1860 | err = NULL; |
1861 | switch (pstate->p_expr_kind) |
1862 | { |
1863 | case EXPR_KIND_NONE: |
1864 | Assert(false); /* can't happen */ |
1865 | break; |
1866 | case EXPR_KIND_OTHER: |
1867 | /* Accept sublink here; caller must throw error if wanted */ |
1868 | break; |
1869 | case EXPR_KIND_JOIN_ON: |
1870 | case EXPR_KIND_JOIN_USING: |
1871 | case EXPR_KIND_FROM_SUBSELECT: |
1872 | case EXPR_KIND_FROM_FUNCTION: |
1873 | case EXPR_KIND_WHERE: |
1874 | case EXPR_KIND_POLICY: |
1875 | case EXPR_KIND_HAVING: |
1876 | case EXPR_KIND_FILTER: |
1877 | case EXPR_KIND_WINDOW_PARTITION: |
1878 | case EXPR_KIND_WINDOW_ORDER: |
1879 | case EXPR_KIND_WINDOW_FRAME_RANGE: |
1880 | case EXPR_KIND_WINDOW_FRAME_ROWS: |
1881 | case EXPR_KIND_WINDOW_FRAME_GROUPS: |
1882 | case EXPR_KIND_SELECT_TARGET: |
1883 | case EXPR_KIND_INSERT_TARGET: |
1884 | case EXPR_KIND_UPDATE_SOURCE: |
1885 | case EXPR_KIND_UPDATE_TARGET: |
1886 | case EXPR_KIND_GROUP_BY: |
1887 | case EXPR_KIND_ORDER_BY: |
1888 | case EXPR_KIND_DISTINCT_ON: |
1889 | case EXPR_KIND_LIMIT: |
1890 | case EXPR_KIND_OFFSET: |
1891 | case EXPR_KIND_RETURNING: |
1892 | case EXPR_KIND_VALUES: |
1893 | case EXPR_KIND_VALUES_SINGLE: |
1894 | /* okay */ |
1895 | break; |
1896 | case EXPR_KIND_CHECK_CONSTRAINT: |
1897 | case EXPR_KIND_DOMAIN_CHECK: |
1898 | err = _("cannot use subquery in check constraint" ); |
1899 | break; |
1900 | case EXPR_KIND_COLUMN_DEFAULT: |
1901 | case EXPR_KIND_FUNCTION_DEFAULT: |
1902 | err = _("cannot use subquery in DEFAULT expression" ); |
1903 | break; |
1904 | case EXPR_KIND_INDEX_EXPRESSION: |
1905 | err = _("cannot use subquery in index expression" ); |
1906 | break; |
1907 | case EXPR_KIND_INDEX_PREDICATE: |
1908 | err = _("cannot use subquery in index predicate" ); |
1909 | break; |
1910 | case EXPR_KIND_ALTER_COL_TRANSFORM: |
1911 | err = _("cannot use subquery in transform expression" ); |
1912 | break; |
1913 | case EXPR_KIND_EXECUTE_PARAMETER: |
1914 | err = _("cannot use subquery in EXECUTE parameter" ); |
1915 | break; |
1916 | case EXPR_KIND_TRIGGER_WHEN: |
1917 | err = _("cannot use subquery in trigger WHEN condition" ); |
1918 | break; |
1919 | case EXPR_KIND_PARTITION_BOUND: |
1920 | err = _("cannot use subquery in partition bound" ); |
1921 | break; |
1922 | case EXPR_KIND_PARTITION_EXPRESSION: |
1923 | err = _("cannot use subquery in partition key expression" ); |
1924 | break; |
1925 | case EXPR_KIND_CALL_ARGUMENT: |
1926 | err = _("cannot use subquery in CALL argument" ); |
1927 | break; |
1928 | case EXPR_KIND_COPY_WHERE: |
1929 | err = _("cannot use subquery in COPY FROM WHERE condition" ); |
1930 | break; |
1931 | case EXPR_KIND_GENERATED_COLUMN: |
1932 | err = _("cannot use subquery in column generation expression" ); |
1933 | break; |
1934 | |
1935 | /* |
1936 | * There is intentionally no default: case here, so that the |
1937 | * compiler will warn if we add a new ParseExprKind without |
1938 | * extending this switch. If we do see an unrecognized value at |
1939 | * runtime, the behavior will be the same as for EXPR_KIND_OTHER, |
1940 | * which is sane anyway. |
1941 | */ |
1942 | } |
1943 | if (err) |
1944 | ereport(ERROR, |
1945 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
1946 | errmsg_internal("%s" , err), |
1947 | parser_errposition(pstate, sublink->location))); |
1948 | |
1949 | pstate->p_hasSubLinks = true; |
1950 | |
1951 | /* |
1952 | * OK, let's transform the sub-SELECT. |
1953 | */ |
1954 | qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true); |
1955 | |
1956 | /* |
1957 | * Check that we got a SELECT. Anything else should be impossible given |
1958 | * restrictions of the grammar, but check anyway. |
1959 | */ |
1960 | if (!IsA(qtree, Query) || |
1961 | qtree->commandType != CMD_SELECT) |
1962 | elog(ERROR, "unexpected non-SELECT command in SubLink" ); |
1963 | |
1964 | sublink->subselect = (Node *) qtree; |
1965 | |
1966 | if (sublink->subLinkType == EXISTS_SUBLINK) |
1967 | { |
1968 | /* |
1969 | * EXISTS needs no test expression or combining operator. These fields |
1970 | * should be null already, but make sure. |
1971 | */ |
1972 | sublink->testexpr = NULL; |
1973 | sublink->operName = NIL; |
1974 | } |
1975 | else if (sublink->subLinkType == EXPR_SUBLINK || |
1976 | sublink->subLinkType == ARRAY_SUBLINK) |
1977 | { |
1978 | /* |
1979 | * Make sure the subselect delivers a single column (ignoring resjunk |
1980 | * targets). |
1981 | */ |
1982 | if (count_nonjunk_tlist_entries(qtree->targetList) != 1) |
1983 | ereport(ERROR, |
1984 | (errcode(ERRCODE_SYNTAX_ERROR), |
1985 | errmsg("subquery must return only one column" ), |
1986 | parser_errposition(pstate, sublink->location))); |
1987 | |
1988 | /* |
1989 | * EXPR and ARRAY need no test expression or combining operator. These |
1990 | * fields should be null already, but make sure. |
1991 | */ |
1992 | sublink->testexpr = NULL; |
1993 | sublink->operName = NIL; |
1994 | } |
1995 | else if (sublink->subLinkType == MULTIEXPR_SUBLINK) |
1996 | { |
1997 | /* Same as EXPR case, except no restriction on number of columns */ |
1998 | sublink->testexpr = NULL; |
1999 | sublink->operName = NIL; |
2000 | } |
2001 | else |
2002 | { |
2003 | /* ALL, ANY, or ROWCOMPARE: generate row-comparing expression */ |
2004 | Node *lefthand; |
2005 | List *left_list; |
2006 | List *right_list; |
2007 | ListCell *l; |
2008 | |
2009 | if (operator_precedence_warning) |
2010 | { |
2011 | if (sublink->operName == NIL) |
2012 | emit_precedence_warnings(pstate, PREC_GROUP_IN, "IN" , |
2013 | sublink->testexpr, NULL, |
2014 | sublink->location); |
2015 | else |
2016 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_OP, |
2017 | strVal(llast(sublink->operName)), |
2018 | sublink->testexpr, NULL, |
2019 | sublink->location); |
2020 | } |
2021 | |
2022 | /* |
2023 | * If the source was "x IN (select)", convert to "x = ANY (select)". |
2024 | */ |
2025 | if (sublink->operName == NIL) |
2026 | sublink->operName = list_make1(makeString("=" )); |
2027 | |
2028 | /* |
2029 | * Transform lefthand expression, and convert to a list |
2030 | */ |
2031 | lefthand = transformExprRecurse(pstate, sublink->testexpr); |
2032 | if (lefthand && IsA(lefthand, RowExpr)) |
2033 | left_list = ((RowExpr *) lefthand)->args; |
2034 | else |
2035 | left_list = list_make1(lefthand); |
2036 | |
2037 | /* |
2038 | * Build a list of PARAM_SUBLINK nodes representing the output columns |
2039 | * of the subquery. |
2040 | */ |
2041 | right_list = NIL; |
2042 | foreach(l, qtree->targetList) |
2043 | { |
2044 | TargetEntry *tent = (TargetEntry *) lfirst(l); |
2045 | Param *param; |
2046 | |
2047 | if (tent->resjunk) |
2048 | continue; |
2049 | |
2050 | param = makeNode(Param); |
2051 | param->paramkind = PARAM_SUBLINK; |
2052 | param->paramid = tent->resno; |
2053 | param->paramtype = exprType((Node *) tent->expr); |
2054 | param->paramtypmod = exprTypmod((Node *) tent->expr); |
2055 | param->paramcollid = exprCollation((Node *) tent->expr); |
2056 | param->location = -1; |
2057 | |
2058 | right_list = lappend(right_list, param); |
2059 | } |
2060 | |
2061 | /* |
2062 | * We could rely on make_row_comparison_op to complain if the list |
2063 | * lengths differ, but we prefer to generate a more specific error |
2064 | * message. |
2065 | */ |
2066 | if (list_length(left_list) < list_length(right_list)) |
2067 | ereport(ERROR, |
2068 | (errcode(ERRCODE_SYNTAX_ERROR), |
2069 | errmsg("subquery has too many columns" ), |
2070 | parser_errposition(pstate, sublink->location))); |
2071 | if (list_length(left_list) > list_length(right_list)) |
2072 | ereport(ERROR, |
2073 | (errcode(ERRCODE_SYNTAX_ERROR), |
2074 | errmsg("subquery has too few columns" ), |
2075 | parser_errposition(pstate, sublink->location))); |
2076 | |
2077 | /* |
2078 | * Identify the combining operator(s) and generate a suitable |
2079 | * row-comparison expression. |
2080 | */ |
2081 | sublink->testexpr = make_row_comparison_op(pstate, |
2082 | sublink->operName, |
2083 | left_list, |
2084 | right_list, |
2085 | sublink->location); |
2086 | } |
2087 | |
2088 | return result; |
2089 | } |
2090 | |
2091 | /* |
2092 | * transformArrayExpr |
2093 | * |
2094 | * If the caller specifies the target type, the resulting array will |
2095 | * be of exactly that type. Otherwise we try to infer a common type |
2096 | * for the elements using select_common_type(). |
2097 | */ |
2098 | static Node * |
2099 | transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, |
2100 | Oid array_type, Oid element_type, int32 typmod) |
2101 | { |
2102 | ArrayExpr *newa = makeNode(ArrayExpr); |
2103 | List *newelems = NIL; |
2104 | List *newcoercedelems = NIL; |
2105 | ListCell *element; |
2106 | Oid coerce_type; |
2107 | bool coerce_hard; |
2108 | |
2109 | /* |
2110 | * Transform the element expressions |
2111 | * |
2112 | * Assume that the array is one-dimensional unless we find an array-type |
2113 | * element expression. |
2114 | */ |
2115 | newa->multidims = false; |
2116 | foreach(element, a->elements) |
2117 | { |
2118 | Node *e = (Node *) lfirst(element); |
2119 | Node *newe; |
2120 | |
2121 | /* Look through AEXPR_PAREN nodes so they don't affect test below */ |
2122 | while (e && IsA(e, A_Expr) && |
2123 | ((A_Expr *) e)->kind == AEXPR_PAREN) |
2124 | e = ((A_Expr *) e)->lexpr; |
2125 | |
2126 | /* |
2127 | * If an element is itself an A_ArrayExpr, recurse directly so that we |
2128 | * can pass down any target type we were given. |
2129 | */ |
2130 | if (IsA(e, A_ArrayExpr)) |
2131 | { |
2132 | newe = transformArrayExpr(pstate, |
2133 | (A_ArrayExpr *) e, |
2134 | array_type, |
2135 | element_type, |
2136 | typmod); |
2137 | /* we certainly have an array here */ |
2138 | Assert(array_type == InvalidOid || array_type == exprType(newe)); |
2139 | newa->multidims = true; |
2140 | } |
2141 | else |
2142 | { |
2143 | newe = transformExprRecurse(pstate, e); |
2144 | |
2145 | /* |
2146 | * Check for sub-array expressions, if we haven't already found |
2147 | * one. |
2148 | */ |
2149 | if (!newa->multidims && type_is_array(exprType(newe))) |
2150 | newa->multidims = true; |
2151 | } |
2152 | |
2153 | newelems = lappend(newelems, newe); |
2154 | } |
2155 | |
2156 | /* |
2157 | * Select a target type for the elements. |
2158 | * |
2159 | * If we haven't been given a target array type, we must try to deduce a |
2160 | * common type based on the types of the individual elements present. |
2161 | */ |
2162 | if (OidIsValid(array_type)) |
2163 | { |
2164 | /* Caller must ensure array_type matches element_type */ |
2165 | Assert(OidIsValid(element_type)); |
2166 | coerce_type = (newa->multidims ? array_type : element_type); |
2167 | coerce_hard = true; |
2168 | } |
2169 | else |
2170 | { |
2171 | /* Can't handle an empty array without a target type */ |
2172 | if (newelems == NIL) |
2173 | ereport(ERROR, |
2174 | (errcode(ERRCODE_INDETERMINATE_DATATYPE), |
2175 | errmsg("cannot determine type of empty array" ), |
2176 | errhint("Explicitly cast to the desired type, " |
2177 | "for example ARRAY[]::integer[]." ), |
2178 | parser_errposition(pstate, a->location))); |
2179 | |
2180 | /* Select a common type for the elements */ |
2181 | coerce_type = select_common_type(pstate, newelems, "ARRAY" , NULL); |
2182 | |
2183 | if (newa->multidims) |
2184 | { |
2185 | array_type = coerce_type; |
2186 | element_type = get_element_type(array_type); |
2187 | if (!OidIsValid(element_type)) |
2188 | ereport(ERROR, |
2189 | (errcode(ERRCODE_UNDEFINED_OBJECT), |
2190 | errmsg("could not find element type for data type %s" , |
2191 | format_type_be(array_type)), |
2192 | parser_errposition(pstate, a->location))); |
2193 | } |
2194 | else |
2195 | { |
2196 | element_type = coerce_type; |
2197 | array_type = get_array_type(element_type); |
2198 | if (!OidIsValid(array_type)) |
2199 | ereport(ERROR, |
2200 | (errcode(ERRCODE_UNDEFINED_OBJECT), |
2201 | errmsg("could not find array type for data type %s" , |
2202 | format_type_be(element_type)), |
2203 | parser_errposition(pstate, a->location))); |
2204 | } |
2205 | coerce_hard = false; |
2206 | } |
2207 | |
2208 | /* |
2209 | * Coerce elements to target type |
2210 | * |
2211 | * If the array has been explicitly cast, then the elements are in turn |
2212 | * explicitly coerced. |
2213 | * |
2214 | * If the array's type was merely derived from the common type of its |
2215 | * elements, then the elements are implicitly coerced to the common type. |
2216 | * This is consistent with other uses of select_common_type(). |
2217 | */ |
2218 | foreach(element, newelems) |
2219 | { |
2220 | Node *e = (Node *) lfirst(element); |
2221 | Node *newe; |
2222 | |
2223 | if (coerce_hard) |
2224 | { |
2225 | newe = coerce_to_target_type(pstate, e, |
2226 | exprType(e), |
2227 | coerce_type, |
2228 | typmod, |
2229 | COERCION_EXPLICIT, |
2230 | COERCE_EXPLICIT_CAST, |
2231 | -1); |
2232 | if (newe == NULL) |
2233 | ereport(ERROR, |
2234 | (errcode(ERRCODE_CANNOT_COERCE), |
2235 | errmsg("cannot cast type %s to %s" , |
2236 | format_type_be(exprType(e)), |
2237 | format_type_be(coerce_type)), |
2238 | parser_errposition(pstate, exprLocation(e)))); |
2239 | } |
2240 | else |
2241 | newe = coerce_to_common_type(pstate, e, |
2242 | coerce_type, |
2243 | "ARRAY" ); |
2244 | newcoercedelems = lappend(newcoercedelems, newe); |
2245 | } |
2246 | |
2247 | newa->array_typeid = array_type; |
2248 | /* array_collid will be set by parse_collate.c */ |
2249 | newa->element_typeid = element_type; |
2250 | newa->elements = newcoercedelems; |
2251 | newa->location = a->location; |
2252 | |
2253 | return (Node *) newa; |
2254 | } |
2255 | |
2256 | static Node * |
2257 | transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault) |
2258 | { |
2259 | RowExpr *newr; |
2260 | char fname[16]; |
2261 | int fnum; |
2262 | ListCell *lc; |
2263 | |
2264 | newr = makeNode(RowExpr); |
2265 | |
2266 | /* Transform the field expressions */ |
2267 | newr->args = transformExpressionList(pstate, r->args, |
2268 | pstate->p_expr_kind, allowDefault); |
2269 | |
2270 | /* Barring later casting, we consider the type RECORD */ |
2271 | newr->row_typeid = RECORDOID; |
2272 | newr->row_format = COERCE_IMPLICIT_CAST; |
2273 | |
2274 | /* ROW() has anonymous columns, so invent some field names */ |
2275 | newr->colnames = NIL; |
2276 | fnum = 1; |
2277 | foreach(lc, newr->args) |
2278 | { |
2279 | snprintf(fname, sizeof(fname), "f%d" , fnum++); |
2280 | newr->colnames = lappend(newr->colnames, makeString(pstrdup(fname))); |
2281 | } |
2282 | |
2283 | newr->location = r->location; |
2284 | |
2285 | return (Node *) newr; |
2286 | } |
2287 | |
2288 | static Node * |
2289 | transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c) |
2290 | { |
2291 | CoalesceExpr *newc = makeNode(CoalesceExpr); |
2292 | Node *last_srf = pstate->p_last_srf; |
2293 | List *newargs = NIL; |
2294 | List *newcoercedargs = NIL; |
2295 | ListCell *args; |
2296 | |
2297 | foreach(args, c->args) |
2298 | { |
2299 | Node *e = (Node *) lfirst(args); |
2300 | Node *newe; |
2301 | |
2302 | newe = transformExprRecurse(pstate, e); |
2303 | newargs = lappend(newargs, newe); |
2304 | } |
2305 | |
2306 | newc->coalescetype = select_common_type(pstate, newargs, "COALESCE" , NULL); |
2307 | /* coalescecollid will be set by parse_collate.c */ |
2308 | |
2309 | /* Convert arguments if necessary */ |
2310 | foreach(args, newargs) |
2311 | { |
2312 | Node *e = (Node *) lfirst(args); |
2313 | Node *newe; |
2314 | |
2315 | newe = coerce_to_common_type(pstate, e, |
2316 | newc->coalescetype, |
2317 | "COALESCE" ); |
2318 | newcoercedargs = lappend(newcoercedargs, newe); |
2319 | } |
2320 | |
2321 | /* if any subexpression contained a SRF, complain */ |
2322 | if (pstate->p_last_srf != last_srf) |
2323 | ereport(ERROR, |
2324 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
2325 | /* translator: %s is name of a SQL construct, eg GROUP BY */ |
2326 | errmsg("set-returning functions are not allowed in %s" , |
2327 | "COALESCE" ), |
2328 | errhint("You might be able to move the set-returning function into a LATERAL FROM item." ), |
2329 | parser_errposition(pstate, |
2330 | exprLocation(pstate->p_last_srf)))); |
2331 | |
2332 | newc->args = newcoercedargs; |
2333 | newc->location = c->location; |
2334 | return (Node *) newc; |
2335 | } |
2336 | |
2337 | static Node * |
2338 | transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m) |
2339 | { |
2340 | MinMaxExpr *newm = makeNode(MinMaxExpr); |
2341 | List *newargs = NIL; |
2342 | List *newcoercedargs = NIL; |
2343 | const char *funcname = (m->op == IS_GREATEST) ? "GREATEST" : "LEAST" ; |
2344 | ListCell *args; |
2345 | |
2346 | newm->op = m->op; |
2347 | foreach(args, m->args) |
2348 | { |
2349 | Node *e = (Node *) lfirst(args); |
2350 | Node *newe; |
2351 | |
2352 | newe = transformExprRecurse(pstate, e); |
2353 | newargs = lappend(newargs, newe); |
2354 | } |
2355 | |
2356 | newm->minmaxtype = select_common_type(pstate, newargs, funcname, NULL); |
2357 | /* minmaxcollid and inputcollid will be set by parse_collate.c */ |
2358 | |
2359 | /* Convert arguments if necessary */ |
2360 | foreach(args, newargs) |
2361 | { |
2362 | Node *e = (Node *) lfirst(args); |
2363 | Node *newe; |
2364 | |
2365 | newe = coerce_to_common_type(pstate, e, |
2366 | newm->minmaxtype, |
2367 | funcname); |
2368 | newcoercedargs = lappend(newcoercedargs, newe); |
2369 | } |
2370 | |
2371 | newm->args = newcoercedargs; |
2372 | newm->location = m->location; |
2373 | return (Node *) newm; |
2374 | } |
2375 | |
2376 | static Node * |
2377 | transformSQLValueFunction(ParseState *pstate, SQLValueFunction *svf) |
2378 | { |
2379 | /* |
2380 | * All we need to do is insert the correct result type and (where needed) |
2381 | * validate the typmod, so we just modify the node in-place. |
2382 | */ |
2383 | switch (svf->op) |
2384 | { |
2385 | case SVFOP_CURRENT_DATE: |
2386 | svf->type = DATEOID; |
2387 | break; |
2388 | case SVFOP_CURRENT_TIME: |
2389 | svf->type = TIMETZOID; |
2390 | break; |
2391 | case SVFOP_CURRENT_TIME_N: |
2392 | svf->type = TIMETZOID; |
2393 | svf->typmod = anytime_typmod_check(true, svf->typmod); |
2394 | break; |
2395 | case SVFOP_CURRENT_TIMESTAMP: |
2396 | svf->type = TIMESTAMPTZOID; |
2397 | break; |
2398 | case SVFOP_CURRENT_TIMESTAMP_N: |
2399 | svf->type = TIMESTAMPTZOID; |
2400 | svf->typmod = anytimestamp_typmod_check(true, svf->typmod); |
2401 | break; |
2402 | case SVFOP_LOCALTIME: |
2403 | svf->type = TIMEOID; |
2404 | break; |
2405 | case SVFOP_LOCALTIME_N: |
2406 | svf->type = TIMEOID; |
2407 | svf->typmod = anytime_typmod_check(false, svf->typmod); |
2408 | break; |
2409 | case SVFOP_LOCALTIMESTAMP: |
2410 | svf->type = TIMESTAMPOID; |
2411 | break; |
2412 | case SVFOP_LOCALTIMESTAMP_N: |
2413 | svf->type = TIMESTAMPOID; |
2414 | svf->typmod = anytimestamp_typmod_check(false, svf->typmod); |
2415 | break; |
2416 | case SVFOP_CURRENT_ROLE: |
2417 | case SVFOP_CURRENT_USER: |
2418 | case SVFOP_USER: |
2419 | case SVFOP_SESSION_USER: |
2420 | case SVFOP_CURRENT_CATALOG: |
2421 | case SVFOP_CURRENT_SCHEMA: |
2422 | svf->type = NAMEOID; |
2423 | break; |
2424 | } |
2425 | |
2426 | return (Node *) svf; |
2427 | } |
2428 | |
2429 | static Node * |
2430 | transformXmlExpr(ParseState *pstate, XmlExpr *x) |
2431 | { |
2432 | XmlExpr *newx; |
2433 | ListCell *lc; |
2434 | int i; |
2435 | |
2436 | if (operator_precedence_warning && x->op == IS_DOCUMENT) |
2437 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS" , |
2438 | (Node *) linitial(x->args), NULL, |
2439 | x->location); |
2440 | |
2441 | newx = makeNode(XmlExpr); |
2442 | newx->op = x->op; |
2443 | if (x->name) |
2444 | newx->name = map_sql_identifier_to_xml_name(x->name, false, false); |
2445 | else |
2446 | newx->name = NULL; |
2447 | newx->xmloption = x->xmloption; |
2448 | newx->type = XMLOID; /* this just marks the node as transformed */ |
2449 | newx->typmod = -1; |
2450 | newx->location = x->location; |
2451 | |
2452 | /* |
2453 | * gram.y built the named args as a list of ResTarget. Transform each, |
2454 | * and break the names out as a separate list. |
2455 | */ |
2456 | newx->named_args = NIL; |
2457 | newx->arg_names = NIL; |
2458 | |
2459 | foreach(lc, x->named_args) |
2460 | { |
2461 | ResTarget *r = lfirst_node(ResTarget, lc); |
2462 | Node *expr; |
2463 | char *argname; |
2464 | |
2465 | expr = transformExprRecurse(pstate, r->val); |
2466 | |
2467 | if (r->name) |
2468 | argname = map_sql_identifier_to_xml_name(r->name, false, false); |
2469 | else if (IsA(r->val, ColumnRef)) |
2470 | argname = map_sql_identifier_to_xml_name(FigureColname(r->val), |
2471 | true, false); |
2472 | else |
2473 | { |
2474 | ereport(ERROR, |
2475 | (errcode(ERRCODE_SYNTAX_ERROR), |
2476 | x->op == IS_XMLELEMENT |
2477 | ? errmsg("unnamed XML attribute value must be a column reference" ) |
2478 | : errmsg("unnamed XML element value must be a column reference" ), |
2479 | parser_errposition(pstate, r->location))); |
2480 | argname = NULL; /* keep compiler quiet */ |
2481 | } |
2482 | |
2483 | /* reject duplicate argnames in XMLELEMENT only */ |
2484 | if (x->op == IS_XMLELEMENT) |
2485 | { |
2486 | ListCell *lc2; |
2487 | |
2488 | foreach(lc2, newx->arg_names) |
2489 | { |
2490 | if (strcmp(argname, strVal(lfirst(lc2))) == 0) |
2491 | ereport(ERROR, |
2492 | (errcode(ERRCODE_SYNTAX_ERROR), |
2493 | errmsg("XML attribute name \"%s\" appears more than once" , |
2494 | argname), |
2495 | parser_errposition(pstate, r->location))); |
2496 | } |
2497 | } |
2498 | |
2499 | newx->named_args = lappend(newx->named_args, expr); |
2500 | newx->arg_names = lappend(newx->arg_names, makeString(argname)); |
2501 | } |
2502 | |
2503 | /* The other arguments are of varying types depending on the function */ |
2504 | newx->args = NIL; |
2505 | i = 0; |
2506 | foreach(lc, x->args) |
2507 | { |
2508 | Node *e = (Node *) lfirst(lc); |
2509 | Node *newe; |
2510 | |
2511 | newe = transformExprRecurse(pstate, e); |
2512 | switch (x->op) |
2513 | { |
2514 | case IS_XMLCONCAT: |
2515 | newe = coerce_to_specific_type(pstate, newe, XMLOID, |
2516 | "XMLCONCAT" ); |
2517 | break; |
2518 | case IS_XMLELEMENT: |
2519 | /* no coercion necessary */ |
2520 | break; |
2521 | case IS_XMLFOREST: |
2522 | newe = coerce_to_specific_type(pstate, newe, XMLOID, |
2523 | "XMLFOREST" ); |
2524 | break; |
2525 | case IS_XMLPARSE: |
2526 | if (i == 0) |
2527 | newe = coerce_to_specific_type(pstate, newe, TEXTOID, |
2528 | "XMLPARSE" ); |
2529 | else |
2530 | newe = coerce_to_boolean(pstate, newe, "XMLPARSE" ); |
2531 | break; |
2532 | case IS_XMLPI: |
2533 | newe = coerce_to_specific_type(pstate, newe, TEXTOID, |
2534 | "XMLPI" ); |
2535 | break; |
2536 | case IS_XMLROOT: |
2537 | if (i == 0) |
2538 | newe = coerce_to_specific_type(pstate, newe, XMLOID, |
2539 | "XMLROOT" ); |
2540 | else if (i == 1) |
2541 | newe = coerce_to_specific_type(pstate, newe, TEXTOID, |
2542 | "XMLROOT" ); |
2543 | else |
2544 | newe = coerce_to_specific_type(pstate, newe, INT4OID, |
2545 | "XMLROOT" ); |
2546 | break; |
2547 | case IS_XMLSERIALIZE: |
2548 | /* not handled here */ |
2549 | Assert(false); |
2550 | break; |
2551 | case IS_DOCUMENT: |
2552 | newe = coerce_to_specific_type(pstate, newe, XMLOID, |
2553 | "IS DOCUMENT" ); |
2554 | break; |
2555 | } |
2556 | newx->args = lappend(newx->args, newe); |
2557 | i++; |
2558 | } |
2559 | |
2560 | return (Node *) newx; |
2561 | } |
2562 | |
2563 | static Node * |
2564 | transformXmlSerialize(ParseState *pstate, XmlSerialize *xs) |
2565 | { |
2566 | Node *result; |
2567 | XmlExpr *xexpr; |
2568 | Oid targetType; |
2569 | int32 targetTypmod; |
2570 | |
2571 | xexpr = makeNode(XmlExpr); |
2572 | xexpr->op = IS_XMLSERIALIZE; |
2573 | xexpr->args = list_make1(coerce_to_specific_type(pstate, |
2574 | transformExprRecurse(pstate, xs->expr), |
2575 | XMLOID, |
2576 | "XMLSERIALIZE" )); |
2577 | |
2578 | typenameTypeIdAndMod(pstate, xs->typeName, &targetType, &targetTypmod); |
2579 | |
2580 | xexpr->xmloption = xs->xmloption; |
2581 | xexpr->location = xs->location; |
2582 | /* We actually only need these to be able to parse back the expression. */ |
2583 | xexpr->type = targetType; |
2584 | xexpr->typmod = targetTypmod; |
2585 | |
2586 | /* |
2587 | * The actual target type is determined this way. SQL allows char and |
2588 | * varchar as target types. We allow anything that can be cast implicitly |
2589 | * from text. This way, user-defined text-like data types automatically |
2590 | * fit in. |
2591 | */ |
2592 | result = coerce_to_target_type(pstate, (Node *) xexpr, |
2593 | TEXTOID, targetType, targetTypmod, |
2594 | COERCION_IMPLICIT, |
2595 | COERCE_IMPLICIT_CAST, |
2596 | -1); |
2597 | if (result == NULL) |
2598 | ereport(ERROR, |
2599 | (errcode(ERRCODE_CANNOT_COERCE), |
2600 | errmsg("cannot cast XMLSERIALIZE result to %s" , |
2601 | format_type_be(targetType)), |
2602 | parser_errposition(pstate, xexpr->location))); |
2603 | return result; |
2604 | } |
2605 | |
2606 | static Node * |
2607 | transformBooleanTest(ParseState *pstate, BooleanTest *b) |
2608 | { |
2609 | const char *clausename; |
2610 | |
2611 | if (operator_precedence_warning) |
2612 | emit_precedence_warnings(pstate, PREC_GROUP_POSTFIX_IS, "IS" , |
2613 | (Node *) b->arg, NULL, |
2614 | b->location); |
2615 | |
2616 | switch (b->booltesttype) |
2617 | { |
2618 | case IS_TRUE: |
2619 | clausename = "IS TRUE" ; |
2620 | break; |
2621 | case IS_NOT_TRUE: |
2622 | clausename = "IS NOT TRUE" ; |
2623 | break; |
2624 | case IS_FALSE: |
2625 | clausename = "IS FALSE" ; |
2626 | break; |
2627 | case IS_NOT_FALSE: |
2628 | clausename = "IS NOT FALSE" ; |
2629 | break; |
2630 | case IS_UNKNOWN: |
2631 | clausename = "IS UNKNOWN" ; |
2632 | break; |
2633 | case IS_NOT_UNKNOWN: |
2634 | clausename = "IS NOT UNKNOWN" ; |
2635 | break; |
2636 | default: |
2637 | elog(ERROR, "unrecognized booltesttype: %d" , |
2638 | (int) b->booltesttype); |
2639 | clausename = NULL; /* keep compiler quiet */ |
2640 | } |
2641 | |
2642 | b->arg = (Expr *) transformExprRecurse(pstate, (Node *) b->arg); |
2643 | |
2644 | b->arg = (Expr *) coerce_to_boolean(pstate, |
2645 | (Node *) b->arg, |
2646 | clausename); |
2647 | |
2648 | return (Node *) b; |
2649 | } |
2650 | |
2651 | static Node * |
2652 | transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr) |
2653 | { |
2654 | int sublevels_up; |
2655 | |
2656 | /* CURRENT OF can only appear at top level of UPDATE/DELETE */ |
2657 | Assert(pstate->p_target_rangetblentry != NULL); |
2658 | cexpr->cvarno = RTERangeTablePosn(pstate, |
2659 | pstate->p_target_rangetblentry, |
2660 | &sublevels_up); |
2661 | Assert(sublevels_up == 0); |
2662 | |
2663 | /* |
2664 | * Check to see if the cursor name matches a parameter of type REFCURSOR. |
2665 | * If so, replace the raw name reference with a parameter reference. (This |
2666 | * is a hack for the convenience of plpgsql.) |
2667 | */ |
2668 | if (cexpr->cursor_name != NULL) /* in case already transformed */ |
2669 | { |
2670 | ColumnRef *cref = makeNode(ColumnRef); |
2671 | Node *node = NULL; |
2672 | |
2673 | /* Build an unqualified ColumnRef with the given name */ |
2674 | cref->fields = list_make1(makeString(cexpr->cursor_name)); |
2675 | cref->location = -1; |
2676 | |
2677 | /* See if there is a translation available from a parser hook */ |
2678 | if (pstate->p_pre_columnref_hook != NULL) |
2679 | node = pstate->p_pre_columnref_hook(pstate, cref); |
2680 | if (node == NULL && pstate->p_post_columnref_hook != NULL) |
2681 | node = pstate->p_post_columnref_hook(pstate, cref, NULL); |
2682 | |
2683 | /* |
2684 | * XXX Should we throw an error if we get a translation that isn't a |
2685 | * refcursor Param? For now it seems best to silently ignore false |
2686 | * matches. |
2687 | */ |
2688 | if (node != NULL && IsA(node, Param)) |
2689 | { |
2690 | Param *p = (Param *) node; |
2691 | |
2692 | if (p->paramkind == PARAM_EXTERN && |
2693 | p->paramtype == REFCURSOROID) |
2694 | { |
2695 | /* Matches, so convert CURRENT OF to a param reference */ |
2696 | cexpr->cursor_name = NULL; |
2697 | cexpr->cursor_param = p->paramid; |
2698 | } |
2699 | } |
2700 | } |
2701 | |
2702 | return (Node *) cexpr; |
2703 | } |
2704 | |
2705 | /* |
2706 | * Construct a whole-row reference to represent the notation "relation.*". |
2707 | */ |
2708 | static Node * |
2709 | transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location) |
2710 | { |
2711 | Var *result; |
2712 | int vnum; |
2713 | int sublevels_up; |
2714 | |
2715 | /* Find the RTE's rangetable location */ |
2716 | vnum = RTERangeTablePosn(pstate, rte, &sublevels_up); |
2717 | |
2718 | /* |
2719 | * Build the appropriate referencing node. Note that if the RTE is a |
2720 | * function returning scalar, we create just a plain reference to the |
2721 | * function value, not a composite containing a single column. This is |
2722 | * pretty inconsistent at first sight, but it's what we've done |
2723 | * historically. One argument for it is that "rel" and "rel.*" mean the |
2724 | * same thing for composite relations, so why not for scalar functions... |
2725 | */ |
2726 | result = makeWholeRowVar(rte, vnum, sublevels_up, true); |
2727 | |
2728 | /* location is not filled in by makeWholeRowVar */ |
2729 | result->location = location; |
2730 | |
2731 | /* mark relation as requiring whole-row SELECT access */ |
2732 | markVarForSelectPriv(pstate, result, rte); |
2733 | |
2734 | return (Node *) result; |
2735 | } |
2736 | |
2737 | /* |
2738 | * Handle an explicit CAST construct. |
2739 | * |
2740 | * Transform the argument, look up the type name, and apply any necessary |
2741 | * coercion function(s). |
2742 | */ |
2743 | static Node * |
2744 | transformTypeCast(ParseState *pstate, TypeCast *tc) |
2745 | { |
2746 | Node *result; |
2747 | Node *arg = tc->arg; |
2748 | Node *expr; |
2749 | Oid inputType; |
2750 | Oid targetType; |
2751 | int32 targetTypmod; |
2752 | int location; |
2753 | |
2754 | /* Look up the type name first */ |
2755 | typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod); |
2756 | |
2757 | /* |
2758 | * Look through any AEXPR_PAREN nodes that may have been inserted thanks |
2759 | * to operator_precedence_warning. Otherwise, ARRAY[]::foo[] behaves |
2760 | * differently from (ARRAY[])::foo[]. |
2761 | */ |
2762 | while (arg && IsA(arg, A_Expr) && |
2763 | ((A_Expr *) arg)->kind == AEXPR_PAREN) |
2764 | arg = ((A_Expr *) arg)->lexpr; |
2765 | |
2766 | /* |
2767 | * If the subject of the typecast is an ARRAY[] construct and the target |
2768 | * type is an array type, we invoke transformArrayExpr() directly so that |
2769 | * we can pass down the type information. This avoids some cases where |
2770 | * transformArrayExpr() might not infer the correct type. Otherwise, just |
2771 | * transform the argument normally. |
2772 | */ |
2773 | if (IsA(arg, A_ArrayExpr)) |
2774 | { |
2775 | Oid targetBaseType; |
2776 | int32 targetBaseTypmod; |
2777 | Oid elementType; |
2778 | |
2779 | /* |
2780 | * If target is a domain over array, work with the base array type |
2781 | * here. Below, we'll cast the array type to the domain. In the |
2782 | * usual case that the target is not a domain, the remaining steps |
2783 | * will be a no-op. |
2784 | */ |
2785 | targetBaseTypmod = targetTypmod; |
2786 | targetBaseType = getBaseTypeAndTypmod(targetType, &targetBaseTypmod); |
2787 | elementType = get_element_type(targetBaseType); |
2788 | if (OidIsValid(elementType)) |
2789 | { |
2790 | expr = transformArrayExpr(pstate, |
2791 | (A_ArrayExpr *) arg, |
2792 | targetBaseType, |
2793 | elementType, |
2794 | targetBaseTypmod); |
2795 | } |
2796 | else |
2797 | expr = transformExprRecurse(pstate, arg); |
2798 | } |
2799 | else |
2800 | expr = transformExprRecurse(pstate, arg); |
2801 | |
2802 | inputType = exprType(expr); |
2803 | if (inputType == InvalidOid) |
2804 | return expr; /* do nothing if NULL input */ |
2805 | |
2806 | /* |
2807 | * Location of the coercion is preferentially the location of the :: or |
2808 | * CAST symbol, but if there is none then use the location of the type |
2809 | * name (this can happen in TypeName 'string' syntax, for instance). |
2810 | */ |
2811 | location = tc->location; |
2812 | if (location < 0) |
2813 | location = tc->typeName->location; |
2814 | |
2815 | result = coerce_to_target_type(pstate, expr, inputType, |
2816 | targetType, targetTypmod, |
2817 | COERCION_EXPLICIT, |
2818 | COERCE_EXPLICIT_CAST, |
2819 | location); |
2820 | if (result == NULL) |
2821 | ereport(ERROR, |
2822 | (errcode(ERRCODE_CANNOT_COERCE), |
2823 | errmsg("cannot cast type %s to %s" , |
2824 | format_type_be(inputType), |
2825 | format_type_be(targetType)), |
2826 | parser_coercion_errposition(pstate, location, expr))); |
2827 | |
2828 | return result; |
2829 | } |
2830 | |
2831 | /* |
2832 | * Handle an explicit COLLATE clause. |
2833 | * |
2834 | * Transform the argument, and look up the collation name. |
2835 | */ |
2836 | static Node * |
2837 | transformCollateClause(ParseState *pstate, CollateClause *c) |
2838 | { |
2839 | CollateExpr *newc; |
2840 | Oid argtype; |
2841 | |
2842 | newc = makeNode(CollateExpr); |
2843 | newc->arg = (Expr *) transformExprRecurse(pstate, c->arg); |
2844 | |
2845 | argtype = exprType((Node *) newc->arg); |
2846 | |
2847 | /* |
2848 | * The unknown type is not collatable, but coerce_type() takes care of it |
2849 | * separately, so we'll let it go here. |
2850 | */ |
2851 | if (!type_is_collatable(argtype) && argtype != UNKNOWNOID) |
2852 | ereport(ERROR, |
2853 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
2854 | errmsg("collations are not supported by type %s" , |
2855 | format_type_be(argtype)), |
2856 | parser_errposition(pstate, c->location))); |
2857 | |
2858 | newc->collOid = LookupCollation(pstate, c->collname, c->location); |
2859 | newc->location = c->location; |
2860 | |
2861 | return (Node *) newc; |
2862 | } |
2863 | |
2864 | /* |
2865 | * Transform a "row compare-op row" construct |
2866 | * |
2867 | * The inputs are lists of already-transformed expressions. |
2868 | * As with coerce_type, pstate may be NULL if no special unknown-Param |
2869 | * processing is wanted. |
2870 | * |
2871 | * The output may be a single OpExpr, an AND or OR combination of OpExprs, |
2872 | * or a RowCompareExpr. In all cases it is guaranteed to return boolean. |
2873 | * The AND, OR, and RowCompareExpr cases further imply things about the |
2874 | * behavior of the operators (ie, they behave as =, <>, or < <= > >=). |
2875 | */ |
2876 | static Node * |
2877 | make_row_comparison_op(ParseState *pstate, List *opname, |
2878 | List *largs, List *rargs, int location) |
2879 | { |
2880 | RowCompareExpr *rcexpr; |
2881 | RowCompareType rctype; |
2882 | List *opexprs; |
2883 | List *opnos; |
2884 | List *opfamilies; |
2885 | ListCell *l, |
2886 | *r; |
2887 | List **opinfo_lists; |
2888 | Bitmapset *strats; |
2889 | int nopers; |
2890 | int i; |
2891 | |
2892 | nopers = list_length(largs); |
2893 | if (nopers != list_length(rargs)) |
2894 | ereport(ERROR, |
2895 | (errcode(ERRCODE_SYNTAX_ERROR), |
2896 | errmsg("unequal number of entries in row expressions" ), |
2897 | parser_errposition(pstate, location))); |
2898 | |
2899 | /* |
2900 | * We can't compare zero-length rows because there is no principled basis |
2901 | * for figuring out what the operator is. |
2902 | */ |
2903 | if (nopers == 0) |
2904 | ereport(ERROR, |
2905 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
2906 | errmsg("cannot compare rows of zero length" ), |
2907 | parser_errposition(pstate, location))); |
2908 | |
2909 | /* |
2910 | * Identify all the pairwise operators, using make_op so that behavior is |
2911 | * the same as in the simple scalar case. |
2912 | */ |
2913 | opexprs = NIL; |
2914 | forboth(l, largs, r, rargs) |
2915 | { |
2916 | Node *larg = (Node *) lfirst(l); |
2917 | Node *rarg = (Node *) lfirst(r); |
2918 | OpExpr *cmp; |
2919 | |
2920 | cmp = castNode(OpExpr, make_op(pstate, opname, larg, rarg, |
2921 | pstate->p_last_srf, location)); |
2922 | |
2923 | /* |
2924 | * We don't use coerce_to_boolean here because we insist on the |
2925 | * operator yielding boolean directly, not via coercion. If it |
2926 | * doesn't yield bool it won't be in any index opfamilies... |
2927 | */ |
2928 | if (cmp->opresulttype != BOOLOID) |
2929 | ereport(ERROR, |
2930 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
2931 | errmsg("row comparison operator must yield type boolean, " |
2932 | "not type %s" , |
2933 | format_type_be(cmp->opresulttype)), |
2934 | parser_errposition(pstate, location))); |
2935 | if (expression_returns_set((Node *) cmp)) |
2936 | ereport(ERROR, |
2937 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
2938 | errmsg("row comparison operator must not return a set" ), |
2939 | parser_errposition(pstate, location))); |
2940 | opexprs = lappend(opexprs, cmp); |
2941 | } |
2942 | |
2943 | /* |
2944 | * If rows are length 1, just return the single operator. In this case we |
2945 | * don't insist on identifying btree semantics for the operator (but we |
2946 | * still require it to return boolean). |
2947 | */ |
2948 | if (nopers == 1) |
2949 | return (Node *) linitial(opexprs); |
2950 | |
2951 | /* |
2952 | * Now we must determine which row comparison semantics (= <> < <= > >=) |
2953 | * apply to this set of operators. We look for btree opfamilies |
2954 | * containing the operators, and see which interpretations (strategy |
2955 | * numbers) exist for each operator. |
2956 | */ |
2957 | opinfo_lists = (List **) palloc(nopers * sizeof(List *)); |
2958 | strats = NULL; |
2959 | i = 0; |
2960 | foreach(l, opexprs) |
2961 | { |
2962 | Oid opno = ((OpExpr *) lfirst(l))->opno; |
2963 | Bitmapset *this_strats; |
2964 | ListCell *j; |
2965 | |
2966 | opinfo_lists[i] = get_op_btree_interpretation(opno); |
2967 | |
2968 | /* |
2969 | * convert strategy numbers into a Bitmapset to make the intersection |
2970 | * calculation easy. |
2971 | */ |
2972 | this_strats = NULL; |
2973 | foreach(j, opinfo_lists[i]) |
2974 | { |
2975 | OpBtreeInterpretation *opinfo = lfirst(j); |
2976 | |
2977 | this_strats = bms_add_member(this_strats, opinfo->strategy); |
2978 | } |
2979 | if (i == 0) |
2980 | strats = this_strats; |
2981 | else |
2982 | strats = bms_int_members(strats, this_strats); |
2983 | i++; |
2984 | } |
2985 | |
2986 | /* |
2987 | * If there are multiple common interpretations, we may use any one of |
2988 | * them ... this coding arbitrarily picks the lowest btree strategy |
2989 | * number. |
2990 | */ |
2991 | i = bms_first_member(strats); |
2992 | if (i < 0) |
2993 | { |
2994 | /* No common interpretation, so fail */ |
2995 | ereport(ERROR, |
2996 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
2997 | errmsg("could not determine interpretation of row comparison operator %s" , |
2998 | strVal(llast(opname))), |
2999 | errhint("Row comparison operators must be associated with btree operator families." ), |
3000 | parser_errposition(pstate, location))); |
3001 | } |
3002 | rctype = (RowCompareType) i; |
3003 | |
3004 | /* |
3005 | * For = and <> cases, we just combine the pairwise operators with AND or |
3006 | * OR respectively. |
3007 | */ |
3008 | if (rctype == ROWCOMPARE_EQ) |
3009 | return (Node *) makeBoolExpr(AND_EXPR, opexprs, location); |
3010 | if (rctype == ROWCOMPARE_NE) |
3011 | return (Node *) makeBoolExpr(OR_EXPR, opexprs, location); |
3012 | |
3013 | /* |
3014 | * Otherwise we need to choose exactly which opfamily to associate with |
3015 | * each operator. |
3016 | */ |
3017 | opfamilies = NIL; |
3018 | for (i = 0; i < nopers; i++) |
3019 | { |
3020 | Oid opfamily = InvalidOid; |
3021 | ListCell *j; |
3022 | |
3023 | foreach(j, opinfo_lists[i]) |
3024 | { |
3025 | OpBtreeInterpretation *opinfo = lfirst(j); |
3026 | |
3027 | if (opinfo->strategy == rctype) |
3028 | { |
3029 | opfamily = opinfo->opfamily_id; |
3030 | break; |
3031 | } |
3032 | } |
3033 | if (OidIsValid(opfamily)) |
3034 | opfamilies = lappend_oid(opfamilies, opfamily); |
3035 | else /* should not happen */ |
3036 | ereport(ERROR, |
3037 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
3038 | errmsg("could not determine interpretation of row comparison operator %s" , |
3039 | strVal(llast(opname))), |
3040 | errdetail("There are multiple equally-plausible candidates." ), |
3041 | parser_errposition(pstate, location))); |
3042 | } |
3043 | |
3044 | /* |
3045 | * Now deconstruct the OpExprs and create a RowCompareExpr. |
3046 | * |
3047 | * Note: can't just reuse the passed largs/rargs lists, because of |
3048 | * possibility that make_op inserted coercion operations. |
3049 | */ |
3050 | opnos = NIL; |
3051 | largs = NIL; |
3052 | rargs = NIL; |
3053 | foreach(l, opexprs) |
3054 | { |
3055 | OpExpr *cmp = (OpExpr *) lfirst(l); |
3056 | |
3057 | opnos = lappend_oid(opnos, cmp->opno); |
3058 | largs = lappend(largs, linitial(cmp->args)); |
3059 | rargs = lappend(rargs, lsecond(cmp->args)); |
3060 | } |
3061 | |
3062 | rcexpr = makeNode(RowCompareExpr); |
3063 | rcexpr->rctype = rctype; |
3064 | rcexpr->opnos = opnos; |
3065 | rcexpr->opfamilies = opfamilies; |
3066 | rcexpr->inputcollids = NIL; /* assign_expr_collations will fix this */ |
3067 | rcexpr->largs = largs; |
3068 | rcexpr->rargs = rargs; |
3069 | |
3070 | return (Node *) rcexpr; |
3071 | } |
3072 | |
3073 | /* |
3074 | * Transform a "row IS DISTINCT FROM row" construct |
3075 | * |
3076 | * The input RowExprs are already transformed |
3077 | */ |
3078 | static Node * |
3079 | make_row_distinct_op(ParseState *pstate, List *opname, |
3080 | RowExpr *lrow, RowExpr *rrow, |
3081 | int location) |
3082 | { |
3083 | Node *result = NULL; |
3084 | List *largs = lrow->args; |
3085 | List *rargs = rrow->args; |
3086 | ListCell *l, |
3087 | *r; |
3088 | |
3089 | if (list_length(largs) != list_length(rargs)) |
3090 | ereport(ERROR, |
3091 | (errcode(ERRCODE_SYNTAX_ERROR), |
3092 | errmsg("unequal number of entries in row expressions" ), |
3093 | parser_errposition(pstate, location))); |
3094 | |
3095 | forboth(l, largs, r, rargs) |
3096 | { |
3097 | Node *larg = (Node *) lfirst(l); |
3098 | Node *rarg = (Node *) lfirst(r); |
3099 | Node *cmp; |
3100 | |
3101 | cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location); |
3102 | if (result == NULL) |
3103 | result = cmp; |
3104 | else |
3105 | result = (Node *) makeBoolExpr(OR_EXPR, |
3106 | list_make2(result, cmp), |
3107 | location); |
3108 | } |
3109 | |
3110 | if (result == NULL) |
3111 | { |
3112 | /* zero-length rows? Generate constant FALSE */ |
3113 | result = makeBoolConst(false, false); |
3114 | } |
3115 | |
3116 | return result; |
3117 | } |
3118 | |
3119 | /* |
3120 | * make the node for an IS DISTINCT FROM operator |
3121 | */ |
3122 | static Expr * |
3123 | make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, |
3124 | int location) |
3125 | { |
3126 | Expr *result; |
3127 | |
3128 | result = make_op(pstate, opname, ltree, rtree, |
3129 | pstate->p_last_srf, location); |
3130 | if (((OpExpr *) result)->opresulttype != BOOLOID) |
3131 | ereport(ERROR, |
3132 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
3133 | errmsg("IS DISTINCT FROM requires = operator to yield boolean" ), |
3134 | parser_errposition(pstate, location))); |
3135 | if (((OpExpr *) result)->opretset) |
3136 | ereport(ERROR, |
3137 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
3138 | /* translator: %s is name of a SQL construct, eg NULLIF */ |
3139 | errmsg("%s must not return a set" , "IS DISTINCT FROM" ), |
3140 | parser_errposition(pstate, location))); |
3141 | |
3142 | /* |
3143 | * We rely on DistinctExpr and OpExpr being same struct |
3144 | */ |
3145 | NodeSetTag(result, T_DistinctExpr); |
3146 | |
3147 | return result; |
3148 | } |
3149 | |
3150 | /* |
3151 | * Produce a NullTest node from an IS [NOT] DISTINCT FROM NULL construct |
3152 | * |
3153 | * "arg" is the untransformed other argument |
3154 | */ |
3155 | static Node * |
3156 | make_nulltest_from_distinct(ParseState *pstate, A_Expr *distincta, Node *arg) |
3157 | { |
3158 | NullTest *nt = makeNode(NullTest); |
3159 | |
3160 | nt->arg = (Expr *) transformExprRecurse(pstate, arg); |
3161 | /* the argument can be any type, so don't coerce it */ |
3162 | if (distincta->kind == AEXPR_NOT_DISTINCT) |
3163 | nt->nulltesttype = IS_NULL; |
3164 | else |
3165 | nt->nulltesttype = IS_NOT_NULL; |
3166 | /* argisrow = false is correct whether or not arg is composite */ |
3167 | nt->argisrow = false; |
3168 | nt->location = distincta->location; |
3169 | return (Node *) nt; |
3170 | } |
3171 | |
3172 | /* |
3173 | * Identify node's group for operator precedence warnings |
3174 | * |
3175 | * For items in nonzero groups, also return a suitable node name into *nodename |
3176 | * |
3177 | * Note: group zero is used for nodes that are higher or lower precedence |
3178 | * than everything that changed precedence; we need never issue warnings |
3179 | * related to such nodes. |
3180 | */ |
3181 | static int |
3182 | operator_precedence_group(Node *node, const char **nodename) |
3183 | { |
3184 | int group = 0; |
3185 | |
3186 | *nodename = NULL; |
3187 | if (node == NULL) |
3188 | return 0; |
3189 | |
3190 | if (IsA(node, A_Expr)) |
3191 | { |
3192 | A_Expr *aexpr = (A_Expr *) node; |
3193 | |
3194 | if (aexpr->kind == AEXPR_OP && |
3195 | aexpr->lexpr != NULL && |
3196 | aexpr->rexpr != NULL) |
3197 | { |
3198 | /* binary operator */ |
3199 | if (list_length(aexpr->name) == 1) |
3200 | { |
3201 | *nodename = strVal(linitial(aexpr->name)); |
3202 | /* Ignore if op was always higher priority than IS-tests */ |
3203 | if (strcmp(*nodename, "+" ) == 0 || |
3204 | strcmp(*nodename, "-" ) == 0 || |
3205 | strcmp(*nodename, "*" ) == 0 || |
3206 | strcmp(*nodename, "/" ) == 0 || |
3207 | strcmp(*nodename, "%" ) == 0 || |
3208 | strcmp(*nodename, "^" ) == 0) |
3209 | group = 0; |
3210 | else if (strcmp(*nodename, "<" ) == 0 || |
3211 | strcmp(*nodename, ">" ) == 0) |
3212 | group = PREC_GROUP_LESS; |
3213 | else if (strcmp(*nodename, "=" ) == 0) |
3214 | group = PREC_GROUP_EQUAL; |
3215 | else if (strcmp(*nodename, "<=" ) == 0 || |
3216 | strcmp(*nodename, ">=" ) == 0 || |
3217 | strcmp(*nodename, "<>" ) == 0) |
3218 | group = PREC_GROUP_LESS_EQUAL; |
3219 | else |
3220 | group = PREC_GROUP_INFIX_OP; |
3221 | } |
3222 | else |
3223 | { |
3224 | /* schema-qualified operator syntax */ |
3225 | *nodename = "OPERATOR()" ; |
3226 | group = PREC_GROUP_INFIX_OP; |
3227 | } |
3228 | } |
3229 | else if (aexpr->kind == AEXPR_OP && |
3230 | aexpr->lexpr == NULL && |
3231 | aexpr->rexpr != NULL) |
3232 | { |
3233 | /* prefix operator */ |
3234 | if (list_length(aexpr->name) == 1) |
3235 | { |
3236 | *nodename = strVal(linitial(aexpr->name)); |
3237 | /* Ignore if op was always higher priority than IS-tests */ |
3238 | if (strcmp(*nodename, "+" ) == 0 || |
3239 | strcmp(*nodename, "-" ) == 0) |
3240 | group = 0; |
3241 | else |
3242 | group = PREC_GROUP_PREFIX_OP; |
3243 | } |
3244 | else |
3245 | { |
3246 | /* schema-qualified operator syntax */ |
3247 | *nodename = "OPERATOR()" ; |
3248 | group = PREC_GROUP_PREFIX_OP; |
3249 | } |
3250 | } |
3251 | else if (aexpr->kind == AEXPR_OP && |
3252 | aexpr->lexpr != NULL && |
3253 | aexpr->rexpr == NULL) |
3254 | { |
3255 | /* postfix operator */ |
3256 | if (list_length(aexpr->name) == 1) |
3257 | { |
3258 | *nodename = strVal(linitial(aexpr->name)); |
3259 | group = PREC_GROUP_POSTFIX_OP; |
3260 | } |
3261 | else |
3262 | { |
3263 | /* schema-qualified operator syntax */ |
3264 | *nodename = "OPERATOR()" ; |
3265 | group = PREC_GROUP_POSTFIX_OP; |
3266 | } |
3267 | } |
3268 | else if (aexpr->kind == AEXPR_OP_ANY || |
3269 | aexpr->kind == AEXPR_OP_ALL) |
3270 | { |
3271 | *nodename = strVal(llast(aexpr->name)); |
3272 | group = PREC_GROUP_POSTFIX_OP; |
3273 | } |
3274 | else if (aexpr->kind == AEXPR_DISTINCT || |
3275 | aexpr->kind == AEXPR_NOT_DISTINCT) |
3276 | { |
3277 | *nodename = "IS" ; |
3278 | group = PREC_GROUP_INFIX_IS; |
3279 | } |
3280 | else if (aexpr->kind == AEXPR_OF) |
3281 | { |
3282 | *nodename = "IS" ; |
3283 | group = PREC_GROUP_POSTFIX_IS; |
3284 | } |
3285 | else if (aexpr->kind == AEXPR_IN) |
3286 | { |
3287 | *nodename = "IN" ; |
3288 | if (strcmp(strVal(linitial(aexpr->name)), "=" ) == 0) |
3289 | group = PREC_GROUP_IN; |
3290 | else |
3291 | group = PREC_GROUP_NOT_IN; |
3292 | } |
3293 | else if (aexpr->kind == AEXPR_LIKE) |
3294 | { |
3295 | *nodename = "LIKE" ; |
3296 | if (strcmp(strVal(linitial(aexpr->name)), "~~" ) == 0) |
3297 | group = PREC_GROUP_LIKE; |
3298 | else |
3299 | group = PREC_GROUP_NOT_LIKE; |
3300 | } |
3301 | else if (aexpr->kind == AEXPR_ILIKE) |
3302 | { |
3303 | *nodename = "ILIKE" ; |
3304 | if (strcmp(strVal(linitial(aexpr->name)), "~~*" ) == 0) |
3305 | group = PREC_GROUP_LIKE; |
3306 | else |
3307 | group = PREC_GROUP_NOT_LIKE; |
3308 | } |
3309 | else if (aexpr->kind == AEXPR_SIMILAR) |
3310 | { |
3311 | *nodename = "SIMILAR" ; |
3312 | if (strcmp(strVal(linitial(aexpr->name)), "~" ) == 0) |
3313 | group = PREC_GROUP_LIKE; |
3314 | else |
3315 | group = PREC_GROUP_NOT_LIKE; |
3316 | } |
3317 | else if (aexpr->kind == AEXPR_BETWEEN || |
3318 | aexpr->kind == AEXPR_BETWEEN_SYM) |
3319 | { |
3320 | Assert(list_length(aexpr->name) == 1); |
3321 | *nodename = strVal(linitial(aexpr->name)); |
3322 | group = PREC_GROUP_BETWEEN; |
3323 | } |
3324 | else if (aexpr->kind == AEXPR_NOT_BETWEEN || |
3325 | aexpr->kind == AEXPR_NOT_BETWEEN_SYM) |
3326 | { |
3327 | Assert(list_length(aexpr->name) == 1); |
3328 | *nodename = strVal(linitial(aexpr->name)); |
3329 | group = PREC_GROUP_NOT_BETWEEN; |
3330 | } |
3331 | } |
3332 | else if (IsA(node, NullTest) || |
3333 | IsA(node, BooleanTest)) |
3334 | { |
3335 | *nodename = "IS" ; |
3336 | group = PREC_GROUP_POSTFIX_IS; |
3337 | } |
3338 | else if (IsA(node, XmlExpr)) |
3339 | { |
3340 | XmlExpr *x = (XmlExpr *) node; |
3341 | |
3342 | if (x->op == IS_DOCUMENT) |
3343 | { |
3344 | *nodename = "IS" ; |
3345 | group = PREC_GROUP_POSTFIX_IS; |
3346 | } |
3347 | } |
3348 | else if (IsA(node, SubLink)) |
3349 | { |
3350 | SubLink *s = (SubLink *) node; |
3351 | |
3352 | if (s->subLinkType == ANY_SUBLINK || |
3353 | s->subLinkType == ALL_SUBLINK) |
3354 | { |
3355 | if (s->operName == NIL) |
3356 | { |
3357 | *nodename = "IN" ; |
3358 | group = PREC_GROUP_IN; |
3359 | } |
3360 | else |
3361 | { |
3362 | *nodename = strVal(llast(s->operName)); |
3363 | group = PREC_GROUP_POSTFIX_OP; |
3364 | } |
3365 | } |
3366 | } |
3367 | else if (IsA(node, BoolExpr)) |
3368 | { |
3369 | /* |
3370 | * Must dig into NOTs to see if it's IS NOT DOCUMENT or NOT IN. This |
3371 | * opens us to possibly misrecognizing, eg, NOT (x IS DOCUMENT) as a |
3372 | * problematic construct. We can tell the difference by checking |
3373 | * whether the parse locations of the two nodes are identical. |
3374 | * |
3375 | * Note that when we are comparing the child node to its own children, |
3376 | * we will not know that it was a NOT. Fortunately, that doesn't |
3377 | * matter for these cases. |
3378 | */ |
3379 | BoolExpr *b = (BoolExpr *) node; |
3380 | |
3381 | if (b->boolop == NOT_EXPR) |
3382 | { |
3383 | Node *child = (Node *) linitial(b->args); |
3384 | |
3385 | if (IsA(child, XmlExpr)) |
3386 | { |
3387 | XmlExpr *x = (XmlExpr *) child; |
3388 | |
3389 | if (x->op == IS_DOCUMENT && |
3390 | x->location == b->location) |
3391 | { |
3392 | *nodename = "IS" ; |
3393 | group = PREC_GROUP_POSTFIX_IS; |
3394 | } |
3395 | } |
3396 | else if (IsA(child, SubLink)) |
3397 | { |
3398 | SubLink *s = (SubLink *) child; |
3399 | |
3400 | if (s->subLinkType == ANY_SUBLINK && s->operName == NIL && |
3401 | s->location == b->location) |
3402 | { |
3403 | *nodename = "IN" ; |
3404 | group = PREC_GROUP_NOT_IN; |
3405 | } |
3406 | } |
3407 | } |
3408 | } |
3409 | return group; |
3410 | } |
3411 | |
3412 | /* |
3413 | * helper routine for delivering 9.4-to-9.5 operator precedence warnings |
3414 | * |
3415 | * opgroup/opname/location represent some parent node |
3416 | * lchild, rchild are its left and right children (either could be NULL) |
3417 | * |
3418 | * This should be called before transforming the child nodes, since if a |
3419 | * precedence-driven parsing change has occurred in a query that used to work, |
3420 | * it's quite possible that we'll get a semantic failure while analyzing the |
3421 | * child expression. We want to produce the warning before that happens. |
3422 | * In any case, operator_precedence_group() expects untransformed input. |
3423 | */ |
3424 | static void |
3425 | emit_precedence_warnings(ParseState *pstate, |
3426 | int opgroup, const char *opname, |
3427 | Node *lchild, Node *rchild, |
3428 | int location) |
3429 | { |
3430 | int cgroup; |
3431 | const char *copname; |
3432 | |
3433 | Assert(opgroup > 0); |
3434 | |
3435 | /* |
3436 | * Complain if left child, which should be same or higher precedence |
3437 | * according to current rules, used to be lower precedence. |
3438 | * |
3439 | * Exception to precedence rules: if left child is IN or NOT IN or a |
3440 | * postfix operator, the grouping is syntactically forced regardless of |
3441 | * precedence. |
3442 | */ |
3443 | cgroup = operator_precedence_group(lchild, &copname); |
3444 | if (cgroup > 0) |
3445 | { |
3446 | if (oldprecedence_l[cgroup] < oldprecedence_r[opgroup] && |
3447 | cgroup != PREC_GROUP_IN && |
3448 | cgroup != PREC_GROUP_NOT_IN && |
3449 | cgroup != PREC_GROUP_POSTFIX_OP && |
3450 | cgroup != PREC_GROUP_POSTFIX_IS) |
3451 | ereport(WARNING, |
3452 | (errmsg("operator precedence change: %s is now lower precedence than %s" , |
3453 | opname, copname), |
3454 | parser_errposition(pstate, location))); |
3455 | } |
3456 | |
3457 | /* |
3458 | * Complain if right child, which should be higher precedence according to |
3459 | * current rules, used to be same or lower precedence. |
3460 | * |
3461 | * Exception to precedence rules: if right child is a prefix operator, the |
3462 | * grouping is syntactically forced regardless of precedence. |
3463 | */ |
3464 | cgroup = operator_precedence_group(rchild, &copname); |
3465 | if (cgroup > 0) |
3466 | { |
3467 | if (oldprecedence_r[cgroup] <= oldprecedence_l[opgroup] && |
3468 | cgroup != PREC_GROUP_PREFIX_OP) |
3469 | ereport(WARNING, |
3470 | (errmsg("operator precedence change: %s is now lower precedence than %s" , |
3471 | opname, copname), |
3472 | parser_errposition(pstate, location))); |
3473 | } |
3474 | } |
3475 | |
3476 | /* |
3477 | * Produce a string identifying an expression by kind. |
3478 | * |
3479 | * Note: when practical, use a simple SQL keyword for the result. If that |
3480 | * doesn't work well, check call sites to see whether custom error message |
3481 | * strings are required. |
3482 | */ |
3483 | const char * |
3484 | ParseExprKindName(ParseExprKind exprKind) |
3485 | { |
3486 | switch (exprKind) |
3487 | { |
3488 | case EXPR_KIND_NONE: |
3489 | return "invalid expression context" ; |
3490 | case EXPR_KIND_OTHER: |
3491 | return "extension expression" ; |
3492 | case EXPR_KIND_JOIN_ON: |
3493 | return "JOIN/ON" ; |
3494 | case EXPR_KIND_JOIN_USING: |
3495 | return "JOIN/USING" ; |
3496 | case EXPR_KIND_FROM_SUBSELECT: |
3497 | return "sub-SELECT in FROM" ; |
3498 | case EXPR_KIND_FROM_FUNCTION: |
3499 | return "function in FROM" ; |
3500 | case EXPR_KIND_WHERE: |
3501 | return "WHERE" ; |
3502 | case EXPR_KIND_POLICY: |
3503 | return "POLICY" ; |
3504 | case EXPR_KIND_HAVING: |
3505 | return "HAVING" ; |
3506 | case EXPR_KIND_FILTER: |
3507 | return "FILTER" ; |
3508 | case EXPR_KIND_WINDOW_PARTITION: |
3509 | return "window PARTITION BY" ; |
3510 | case EXPR_KIND_WINDOW_ORDER: |
3511 | return "window ORDER BY" ; |
3512 | case EXPR_KIND_WINDOW_FRAME_RANGE: |
3513 | return "window RANGE" ; |
3514 | case EXPR_KIND_WINDOW_FRAME_ROWS: |
3515 | return "window ROWS" ; |
3516 | case EXPR_KIND_WINDOW_FRAME_GROUPS: |
3517 | return "window GROUPS" ; |
3518 | case EXPR_KIND_SELECT_TARGET: |
3519 | return "SELECT" ; |
3520 | case EXPR_KIND_INSERT_TARGET: |
3521 | return "INSERT" ; |
3522 | case EXPR_KIND_UPDATE_SOURCE: |
3523 | case EXPR_KIND_UPDATE_TARGET: |
3524 | return "UPDATE" ; |
3525 | case EXPR_KIND_GROUP_BY: |
3526 | return "GROUP BY" ; |
3527 | case EXPR_KIND_ORDER_BY: |
3528 | return "ORDER BY" ; |
3529 | case EXPR_KIND_DISTINCT_ON: |
3530 | return "DISTINCT ON" ; |
3531 | case EXPR_KIND_LIMIT: |
3532 | return "LIMIT" ; |
3533 | case EXPR_KIND_OFFSET: |
3534 | return "OFFSET" ; |
3535 | case EXPR_KIND_RETURNING: |
3536 | return "RETURNING" ; |
3537 | case EXPR_KIND_VALUES: |
3538 | case EXPR_KIND_VALUES_SINGLE: |
3539 | return "VALUES" ; |
3540 | case EXPR_KIND_CHECK_CONSTRAINT: |
3541 | case EXPR_KIND_DOMAIN_CHECK: |
3542 | return "CHECK" ; |
3543 | case EXPR_KIND_COLUMN_DEFAULT: |
3544 | case EXPR_KIND_FUNCTION_DEFAULT: |
3545 | return "DEFAULT" ; |
3546 | case EXPR_KIND_INDEX_EXPRESSION: |
3547 | return "index expression" ; |
3548 | case EXPR_KIND_INDEX_PREDICATE: |
3549 | return "index predicate" ; |
3550 | case EXPR_KIND_ALTER_COL_TRANSFORM: |
3551 | return "USING" ; |
3552 | case EXPR_KIND_EXECUTE_PARAMETER: |
3553 | return "EXECUTE" ; |
3554 | case EXPR_KIND_TRIGGER_WHEN: |
3555 | return "WHEN" ; |
3556 | case EXPR_KIND_PARTITION_BOUND: |
3557 | return "partition bound" ; |
3558 | case EXPR_KIND_PARTITION_EXPRESSION: |
3559 | return "PARTITION BY" ; |
3560 | case EXPR_KIND_CALL_ARGUMENT: |
3561 | return "CALL" ; |
3562 | case EXPR_KIND_COPY_WHERE: |
3563 | return "WHERE" ; |
3564 | case EXPR_KIND_GENERATED_COLUMN: |
3565 | return "GENERATED AS" ; |
3566 | |
3567 | /* |
3568 | * There is intentionally no default: case here, so that the |
3569 | * compiler will warn if we add a new ParseExprKind without |
3570 | * extending this switch. If we do see an unrecognized value at |
3571 | * runtime, we'll fall through to the "unrecognized" return. |
3572 | */ |
3573 | } |
3574 | return "unrecognized expression kind" ; |
3575 | } |
3576 | |