PostgreSQL Source Code git master
Loading...
Searching...
No Matches
parse_expr.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "parser/analyze.h"
#include "parser/parse_agg.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/timestamp.h"
#include "utils/typcache.h"
#include "utils/xml.h"
Include dependency graph for parse_expr.c:

Go to the source code of this file.

Functions

static NodetransformExprRecurse (ParseState *pstate, Node *expr)
 
static NodetransformParamRef (ParseState *pstate, ParamRef *pref)
 
static NodetransformAExprOp (ParseState *pstate, A_Expr *a)
 
static NodetransformAExprOpAny (ParseState *pstate, A_Expr *a)
 
static NodetransformAExprOpAll (ParseState *pstate, A_Expr *a)
 
static NodetransformAExprDistinct (ParseState *pstate, A_Expr *a)
 
static NodetransformAExprNullIf (ParseState *pstate, A_Expr *a)
 
static NodetransformAExprIn (ParseState *pstate, A_Expr *a)
 
static NodetransformAExprBetween (ParseState *pstate, A_Expr *a)
 
static NodetransformMergeSupportFunc (ParseState *pstate, MergeSupportFunc *f)
 
static NodetransformBoolExpr (ParseState *pstate, BoolExpr *a)
 
static NodetransformFuncCall (ParseState *pstate, FuncCall *fn)
 
static NodetransformMultiAssignRef (ParseState *pstate, MultiAssignRef *maref)
 
static NodetransformCaseExpr (ParseState *pstate, CaseExpr *c)
 
static NodetransformSubLink (ParseState *pstate, SubLink *sublink)
 
static NodetransformArrayExpr (ParseState *pstate, A_ArrayExpr *a, Oid array_type, Oid element_type, int32 typmod)
 
static NodetransformRowExpr (ParseState *pstate, RowExpr *r, bool allowDefault)
 
static NodetransformCoalesceExpr (ParseState *pstate, CoalesceExpr *c)
 
static NodetransformMinMaxExpr (ParseState *pstate, MinMaxExpr *m)
 
static NodetransformSQLValueFunction (ParseState *pstate, SQLValueFunction *svf)
 
static NodetransformXmlExpr (ParseState *pstate, XmlExpr *x)
 
static NodetransformXmlSerialize (ParseState *pstate, XmlSerialize *xs)
 
static NodetransformBooleanTest (ParseState *pstate, BooleanTest *b)
 
static NodetransformCurrentOfExpr (ParseState *pstate, CurrentOfExpr *cexpr)
 
static NodetransformColumnRef (ParseState *pstate, ColumnRef *cref)
 
static NodetransformWholeRowRef (ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location)
 
static NodetransformIndirection (ParseState *pstate, A_Indirection *ind)
 
static NodetransformTypeCast (ParseState *pstate, TypeCast *tc)
 
static NodetransformCollateClause (ParseState *pstate, CollateClause *c)
 
static NodetransformJsonObjectConstructor (ParseState *pstate, JsonObjectConstructor *ctor)
 
static NodetransformJsonArrayConstructor (ParseState *pstate, JsonArrayConstructor *ctor)
 
static NodetransformJsonArrayQueryConstructor (ParseState *pstate, JsonArrayQueryConstructor *ctor)
 
static NodetransformJsonObjectAgg (ParseState *pstate, JsonObjectAgg *agg)
 
static NodetransformJsonArrayAgg (ParseState *pstate, JsonArrayAgg *agg)
 
static NodetransformJsonIsPredicate (ParseState *pstate, JsonIsPredicate *pred)
 
static NodetransformJsonParseExpr (ParseState *pstate, JsonParseExpr *jsexpr)
 
static NodetransformJsonScalarExpr (ParseState *pstate, JsonScalarExpr *jsexpr)
 
static NodetransformJsonSerializeExpr (ParseState *pstate, JsonSerializeExpr *expr)
 
static NodetransformJsonFuncExpr (ParseState *pstate, JsonFuncExpr *func)
 
static void transformJsonPassingArgs (ParseState *pstate, const char *constructName, JsonFormatType format, List *args, List **passing_values, List **passing_names)
 
static JsonBehaviortransformJsonBehavior (ParseState *pstate, JsonExpr *jsexpr, JsonBehavior *behavior, JsonBehaviorType default_behavior, JsonReturning *returning)
 
static NodeGetJsonBehaviorConst (JsonBehaviorType btype, int location)
 
static Nodemake_row_comparison_op (ParseState *pstate, List *opname, List *largs, List *rargs, int location)
 
static Nodemake_row_distinct_op (ParseState *pstate, List *opname, RowExpr *lrow, RowExpr *rrow, int location)
 
static Exprmake_distinct_op (ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location)
 
static Nodemake_nulltest_from_distinct (ParseState *pstate, A_Expr *distincta, Node *arg)
 
NodetransformExpr (ParseState *pstate, Node *expr, ParseExprKind exprKind)
 
static void unknown_attribute (ParseState *pstate, Node *relref, const char *attname, int location)
 
static bool exprIsNullConstant (Node *arg)
 
const charParseExprKindName (ParseExprKind exprKind)
 
static ConstgetJsonEncodingConst (JsonFormat *format)
 
static NodemakeJsonByteaToTextConversion (Node *expr, JsonFormat *format, int location)
 
static NodetransformJsonValueExpr (ParseState *pstate, const char *constructName, JsonValueExpr *ve, JsonFormatType default_format, Oid targettype, bool isarg)
 
static void checkJsonOutputFormat (ParseState *pstate, const JsonFormat *format, Oid targettype, bool allow_format_for_non_strings)
 
static JsonReturningtransformJsonOutput (ParseState *pstate, const JsonOutput *output, bool allow_format)
 
static JsonReturningtransformJsonConstructorOutput (ParseState *pstate, JsonOutput *output, List *args)
 
static NodecoerceJsonFuncExpr (ParseState *pstate, Node *expr, const JsonReturning *returning, bool report_error)
 
static NodemakeJsonConstructorExpr (ParseState *pstate, JsonConstructorType type, List *args, Expr *fexpr, JsonReturning *returning, bool unique, bool absent_on_null, int location)
 
static NodetransformJsonAggConstructor (ParseState *pstate, JsonAggConstructor *agg_ctor, JsonReturning *returning, List *args, Oid aggfnoid, Oid aggtype, JsonConstructorType ctor_type, bool unique, bool absent_on_null)
 
static NodetransformJsonParseArg (ParseState *pstate, Node *jsexpr, JsonFormat *format, Oid *exprtype)
 
static JsonReturningtransformJsonReturning (ParseState *pstate, JsonOutput *output, const char *fname)
 
static bool ValidJsonBehaviorDefaultExpr (Node *expr, void *context)
 

Variables

bool Transform_null_equals = false
 

Function Documentation

◆ checkJsonOutputFormat()

static void checkJsonOutputFormat ( ParseState pstate,
const JsonFormat format,
Oid  targettype,
bool  allow_format_for_non_strings 
)
static

Definition at line 3473 of file parse_expr.c.

3475{
3477 format->format_type != JS_FORMAT_DEFAULT &&
3478 (targettype != BYTEAOID &&
3479 targettype != JSONOID &&
3480 targettype != JSONBOID))
3481 {
3482 char typcategory;
3483 bool typispreferred;
3484
3486
3488 ereport(ERROR,
3490 parser_errposition(pstate, format->location),
3491 errmsg("cannot use JSON format with non-string output types"));
3492 }
3493
3494 if (format->format_type == JS_FORMAT_JSON)
3495 {
3496 JsonEncoding enc = format->encoding != JS_ENC_DEFAULT ?
3497 format->encoding : JS_ENC_UTF8;
3498
3499 if (targettype != BYTEAOID &&
3500 format->encoding != JS_ENC_DEFAULT)
3501 ereport(ERROR,
3503 parser_errposition(pstate, format->location),
3504 errmsg("cannot set JSON encoding for non-bytea output types"));
3505
3506 if (enc != JS_ENC_UTF8)
3507 ereport(ERROR,
3509 errmsg("unsupported JSON encoding"),
3510 errhint("Only UTF8 JSON encoding is supported."),
3511 parser_errposition(pstate, format->location));
3512 }
3513}
int errhint(const char *fmt,...)
Definition elog.c:1330
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
Definition lsyscache.c:2860
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
static char format
static int fb(int x)
@ JS_FORMAT_DEFAULT
Definition primnodes.h:1663
@ JS_FORMAT_JSON
Definition primnodes.h:1664
JsonEncoding
Definition primnodes.h:1650
@ JS_ENC_DEFAULT
Definition primnodes.h:1651
@ JS_ENC_UTF8
Definition primnodes.h:1652

References enc, ereport, errcode(), errhint(), errmsg(), ERROR, fb(), format, get_type_category_preferred(), JS_ENC_DEFAULT, JS_ENC_UTF8, JS_FORMAT_DEFAULT, JS_FORMAT_JSON, and parser_errposition().

Referenced by transformJsonOutput().

◆ coerceJsonFuncExpr()

static Node * coerceJsonFuncExpr ( ParseState pstate,
Node expr,
const JsonReturning returning,
bool  report_error 
)
static

Definition at line 3613 of file parse_expr.c.

3615{
3616 Node *res;
3617 int location;
3618 Oid exprtype = exprType(expr);
3619
3620 /* if output type is not specified or equals to function type, return */
3621 if (!OidIsValid(returning->typid) || returning->typid == exprtype)
3622 return expr;
3623
3624 location = exprLocation(expr);
3625
3626 if (location < 0)
3627 location = returning->format->location;
3628
3629 /* special case for RETURNING bytea FORMAT json */
3630 if (returning->format->format_type == JS_FORMAT_JSON &&
3631 returning->typid == BYTEAOID)
3632 {
3633 /* encode json text into bytea using pg_convert_to() */
3634 Node *texpr = coerce_to_specific_type(pstate, expr, TEXTOID,
3635 "JSON_FUNCTION");
3636 Const *enc = getJsonEncodingConst(returning->format);
3641
3642 fexpr->location = location;
3643
3644 return (Node *) fexpr;
3645 }
3646
3647 /*
3648 * For other cases, try to coerce expression to the output type using
3649 * assignment-level casts, erroring out if none available. This basically
3650 * allows coercing the jsonb value to any string type (typcategory = 'S').
3651 *
3652 * Requesting assignment-level here means that typmod / length coercion
3653 * assumes implicit coercion which is the behavior we want; see
3654 * build_coercion_expression().
3655 */
3656 res = coerce_to_target_type(pstate, expr, exprtype,
3657 returning->typid, returning->typmod,
3660 location);
3661
3662 if (!res && report_error)
3663 ereport(ERROR,
3665 errmsg("cannot cast type %s to %s",
3666 format_type_be(exprtype),
3667 format_type_be(returning->typid)),
3668 parser_coercion_errposition(pstate, location, expr));
3669
3670 return res;
3671}
#define OidIsValid(objectId)
Definition c.h:788
char * format_type_be(Oid type_oid)
FuncExpr * makeFuncExpr(Oid funcid, Oid rettype, List *args, Oid funccollid, Oid inputcollid, CoercionForm fformat)
Definition makefuncs.c:594
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1384
int parser_coercion_errposition(ParseState *pstate, int coerce_location, Node *input_expr)
Node * coerce_to_specific_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *constructName)
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
static Const * getJsonEncodingConst(JsonFormat *format)
#define list_make2(x1, x2)
Definition pg_list.h:214
#define InvalidOid
unsigned int Oid
@ COERCE_IMPLICIT_CAST
Definition primnodes.h:768
@ COERCE_EXPLICIT_CALL
Definition primnodes.h:766
@ COERCION_ASSIGNMENT
Definition primnodes.h:747
ParseLoc location
Definition primnodes.h:1678
JsonFormatType format_type
Definition primnodes.h:1676
JsonFormat * format
Definition primnodes.h:1688
Definition nodes.h:135

References COERCE_EXPLICIT_CALL, COERCE_IMPLICIT_CAST, coerce_to_specific_type(), coerce_to_target_type(), COERCION_ASSIGNMENT, enc, ereport, errcode(), errmsg(), ERROR, exprLocation(), exprType(), fb(), JsonReturning::format, JsonFormat::format_type, format_type_be(), getJsonEncodingConst(), InvalidOid, JS_FORMAT_JSON, list_make2, JsonFormat::location, makeFuncExpr(), OidIsValid, parser_coercion_errposition(), JsonReturning::typid, and JsonReturning::typmod.

Referenced by makeJsonConstructorExpr().

◆ exprIsNullConstant()

static bool exprIsNullConstant ( Node arg)
static

Definition at line 910 of file parse_expr.c.

911{
912 if (arg && IsA(arg, A_Const))
913 {
914 A_Const *con = (A_Const *) arg;
915
916 if (con->isnull)
917 return true;
918 }
919 return false;
920}
#define IsA(nodeptr, _type_)
Definition nodes.h:164
void * arg
bool isnull
Definition parsenodes.h:388

References arg, IsA, and A_Const::isnull.

Referenced by transformAExprDistinct(), and transformAExprOp().

◆ GetJsonBehaviorConst()

static Node * GetJsonBehaviorConst ( JsonBehaviorType  btype,
int  location 
)
static

Definition at line 4905 of file parse_expr.c.

4906{
4907 Datum val = (Datum) 0;
4908 Oid typid = JSONBOID;
4909 int len = -1;
4910 bool isbyval = false;
4911 bool isnull = false;
4912 Const *con;
4913
4914 switch (btype)
4915 {
4918 break;
4919
4922 break;
4923
4924 case JSON_BEHAVIOR_TRUE:
4925 val = BoolGetDatum(true);
4926 typid = BOOLOID;
4927 len = sizeof(bool);
4928 isbyval = true;
4929 break;
4930
4932 val = BoolGetDatum(false);
4933 typid = BOOLOID;
4934 len = sizeof(bool);
4935 isbyval = true;
4936 break;
4937
4938 case JSON_BEHAVIOR_NULL:
4941 val = (Datum) 0;
4942 isnull = true;
4943 typid = INT4OID;
4944 len = sizeof(int32);
4945 isbyval = true;
4946 break;
4947
4948 /* These two behavior types are handled by the caller. */
4951 Assert(false);
4952 break;
4953
4954 default:
4955 elog(ERROR, "unrecognized SQL/JSON behavior %d", btype);
4956 break;
4957 }
4958
4959 con = makeConst(typid, -1, InvalidOid, len, val, isnull, isbyval);
4960 con->location = location;
4961
4962 return (Node *) con;
4963}
#define Assert(condition)
Definition c.h:873
int32_t int32
Definition c.h:542
#define elog(elevel,...)
Definition elog.h:226
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
long val
Definition informix.c:689
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition jsonb.c:65
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
const void size_t len
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
@ JSON_BEHAVIOR_ERROR
Definition primnodes.h:1791
@ JSON_BEHAVIOR_TRUE
Definition primnodes.h:1793
@ JSON_BEHAVIOR_DEFAULT
Definition primnodes.h:1798
@ JSON_BEHAVIOR_EMPTY
Definition primnodes.h:1792
@ JSON_BEHAVIOR_FALSE
Definition primnodes.h:1794
@ JSON_BEHAVIOR_NULL
Definition primnodes.h:1790
@ JSON_BEHAVIOR_EMPTY_OBJECT
Definition primnodes.h:1797
@ JSON_BEHAVIOR_UNKNOWN
Definition primnodes.h:1795
@ JSON_BEHAVIOR_EMPTY_ARRAY
Definition primnodes.h:1796

References Assert, BoolGetDatum(), CStringGetDatum(), DirectFunctionCall1, elog, ERROR, fb(), InvalidOid, JSON_BEHAVIOR_DEFAULT, JSON_BEHAVIOR_EMPTY, JSON_BEHAVIOR_EMPTY_ARRAY, JSON_BEHAVIOR_EMPTY_OBJECT, JSON_BEHAVIOR_ERROR, JSON_BEHAVIOR_FALSE, JSON_BEHAVIOR_NULL, JSON_BEHAVIOR_TRUE, JSON_BEHAVIOR_UNKNOWN, jsonb_in(), len, makeConst(), and val.

Referenced by transformJsonBehavior().

◆ getJsonEncodingConst()

static Const * getJsonEncodingConst ( JsonFormat format)
static

Definition at line 3250 of file parse_expr.c.

3251{
3253 const char *enc;
3255
3256 if (!format ||
3257 format->format_type == JS_FORMAT_DEFAULT ||
3258 format->encoding == JS_ENC_DEFAULT)
3260 else
3261 encoding = format->encoding;
3262
3263 switch (encoding)
3264 {
3265 case JS_ENC_UTF16:
3266 enc = "UTF16";
3267 break;
3268 case JS_ENC_UTF32:
3269 enc = "UTF32";
3270 break;
3271 case JS_ENC_UTF8:
3272 enc = "UTF8";
3273 break;
3274 default:
3275 elog(ERROR, "invalid JSON encoding: %d", encoding);
3276 break;
3277 }
3278
3280
3282 NameGetDatum(encname), false, false);
3283}
#define palloc_object(type)
Definition fe_memutils.h:74
static char * encoding
Definition initdb.c:139
void namestrcpy(Name name, const char *str)
Definition name.c:233
#define NAMEDATALEN
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:403
@ JS_ENC_UTF32
Definition primnodes.h:1654
@ JS_ENC_UTF16
Definition primnodes.h:1653
Definition c.h:760

References elog, enc, encoding, ERROR, fb(), format, InvalidOid, JS_ENC_DEFAULT, JS_ENC_UTF16, JS_ENC_UTF32, JS_ENC_UTF8, JS_FORMAT_DEFAULT, makeConst(), NAMEDATALEN, NameGetDatum(), namestrcpy(), and palloc_object.

Referenced by coerceJsonFuncExpr(), and makeJsonByteaToTextConversion().

◆ make_distinct_op()

static Expr * make_distinct_op ( ParseState pstate,
List opname,
Node ltree,
Node rtree,
int  location 
)
static

Definition at line 3085 of file parse_expr.c.

3087{
3088 Expr *result;
3089
3090 result = make_op(pstate, opname, ltree, rtree,
3091 pstate->p_last_srf, location);
3092 if (((OpExpr *) result)->opresulttype != BOOLOID)
3093 ereport(ERROR,
3095 /* translator: %s is name of a SQL construct, eg NULLIF */
3096 errmsg("%s requires = operator to yield boolean",
3097 "IS DISTINCT FROM"),
3098 parser_errposition(pstate, location)));
3099 if (((OpExpr *) result)->opretset)
3100 ereport(ERROR,
3102 /* translator: %s is name of a SQL construct, eg NULLIF */
3103 errmsg("%s must not return a set", "IS DISTINCT FROM"),
3104 parser_errposition(pstate, location)));
3105
3106 /*
3107 * We rely on DistinctExpr and OpExpr being same struct
3108 */
3109 NodeSetTag(result, T_DistinctExpr);
3110
3111 return result;
3112}
#define NodeSetTag(nodeptr, t)
Definition nodes.h:162
Expr * make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, Node *last_srf, int location)
Definition parse_oper.c:703
Node * p_last_srf
Definition parse_node.h:232
Definition ltree.h:43

References ereport, errcode(), errmsg(), ERROR, fb(), make_op(), NodeSetTag, ParseState::p_last_srf, and parser_errposition().

Referenced by make_row_distinct_op(), and transformAExprDistinct().

◆ make_nulltest_from_distinct()

static Node * make_nulltest_from_distinct ( ParseState pstate,
A_Expr distincta,
Node arg 
)
static

Definition at line 3120 of file parse_expr.c.

3121{
3123
3124 nt->arg = (Expr *) transformExprRecurse(pstate, arg);
3125 /* the argument can be any type, so don't coerce it */
3126 if (distincta->kind == AEXPR_NOT_DISTINCT)
3127 nt->nulltesttype = IS_NULL;
3128 else
3129 nt->nulltesttype = IS_NOT_NULL;
3130 /* argisrow = false is correct whether or not arg is composite */
3131 nt->argisrow = false;
3132 nt->location = distincta->location;
3133 return (Node *) nt;
3134}
#define makeNode(_type_)
Definition nodes.h:161
static Node * transformExprRecurse(ParseState *pstate, Node *expr)
Definition parse_expr.c:138
@ AEXPR_NOT_DISTINCT
Definition parsenodes.h:334
@ IS_NULL
Definition primnodes.h:1977
@ IS_NOT_NULL
Definition primnodes.h:1977

References AEXPR_NOT_DISTINCT, arg, fb(), IS_NOT_NULL, IS_NULL, makeNode, and transformExprRecurse().

Referenced by transformAExprDistinct().

◆ make_row_comparison_op()

static Node * make_row_comparison_op ( ParseState pstate,
List opname,
List largs,
List rargs,
int  location 
)
static

Definition at line 2839 of file parse_expr.c.

2841{
2843 CompareType cmptype;
2844 List *opexprs;
2845 List *opnos;
2847 ListCell *l,
2848 *r;
2851 int nopers;
2852 int i;
2853
2854 nopers = list_length(largs);
2855 if (nopers != list_length(rargs))
2856 ereport(ERROR,
2858 errmsg("unequal number of entries in row expressions"),
2859 parser_errposition(pstate, location)));
2860
2861 /*
2862 * We can't compare zero-length rows because there is no principled basis
2863 * for figuring out what the operator is.
2864 */
2865 if (nopers == 0)
2866 ereport(ERROR,
2868 errmsg("cannot compare rows of zero length"),
2869 parser_errposition(pstate, location)));
2870
2871 /*
2872 * Identify all the pairwise operators, using make_op so that behavior is
2873 * the same as in the simple scalar case.
2874 */
2875 opexprs = NIL;
2876 forboth(l, largs, r, rargs)
2877 {
2878 Node *larg = (Node *) lfirst(l);
2879 Node *rarg = (Node *) lfirst(r);
2880 OpExpr *cmp;
2881
2882 cmp = castNode(OpExpr, make_op(pstate, opname, larg, rarg,
2883 pstate->p_last_srf, location));
2884
2885 /*
2886 * We don't use coerce_to_boolean here because we insist on the
2887 * operator yielding boolean directly, not via coercion. If it
2888 * doesn't yield bool it won't be in any index opfamilies...
2889 */
2890 if (cmp->opresulttype != BOOLOID)
2891 ereport(ERROR,
2893 errmsg("row comparison operator must yield type boolean, "
2894 "not type %s",
2895 format_type_be(cmp->opresulttype)),
2896 parser_errposition(pstate, location)));
2898 ereport(ERROR,
2900 errmsg("row comparison operator must not return a set"),
2901 parser_errposition(pstate, location)));
2903 }
2904
2905 /*
2906 * If rows are length 1, just return the single operator. In this case we
2907 * don't insist on identifying btree semantics for the operator (but we
2908 * still require it to return boolean).
2909 */
2910 if (nopers == 1)
2911 return (Node *) linitial(opexprs);
2912
2913 /*
2914 * Now we must determine which row comparison semantics (= <> < <= > >=)
2915 * apply to this set of operators. We look for opfamilies containing the
2916 * operators, and see which interpretations (cmptypes) exist for each
2917 * operator.
2918 */
2920 cmptypes = NULL;
2921 i = 0;
2922 foreach(l, opexprs)
2923 {
2924 Oid opno = ((OpExpr *) lfirst(l))->opno;
2926 ListCell *j;
2927
2929
2930 /*
2931 * convert comparison types into a Bitmapset to make the intersection
2932 * calculation easy.
2933 */
2935 foreach(j, opinfo_lists[i])
2936 {
2938
2940 }
2941 if (i == 0)
2943 else
2945 i++;
2946 }
2947
2948 /*
2949 * If there are multiple common interpretations, we may use any one of
2950 * them ... this coding arbitrarily picks the lowest comparison type
2951 * number.
2952 */
2953 i = bms_next_member(cmptypes, -1);
2954 if (i < 0)
2955 {
2956 /* No common interpretation, so fail */
2957 ereport(ERROR,
2959 errmsg("could not determine interpretation of row comparison operator %s",
2960 strVal(llast(opname))),
2961 errhint("Row comparison operators must be associated with btree operator families."),
2962 parser_errposition(pstate, location)));
2963 }
2964 cmptype = (CompareType) i;
2965
2966 /*
2967 * For = and <> cases, we just combine the pairwise operators with AND or
2968 * OR respectively.
2969 */
2970 if (cmptype == COMPARE_EQ)
2971 return (Node *) makeBoolExpr(AND_EXPR, opexprs, location);
2972 if (cmptype == COMPARE_NE)
2973 return (Node *) makeBoolExpr(OR_EXPR, opexprs, location);
2974
2975 /*
2976 * Otherwise we need to choose exactly which opfamily to associate with
2977 * each operator.
2978 */
2979 opfamilies = NIL;
2980 for (i = 0; i < nopers; i++)
2981 {
2982 Oid opfamily = InvalidOid;
2983 ListCell *j;
2984
2985 foreach(j, opinfo_lists[i])
2986 {
2988
2989 if (opinfo->cmptype == cmptype)
2990 {
2991 opfamily = opinfo->opfamily_id;
2992 break;
2993 }
2994 }
2995 if (OidIsValid(opfamily))
2996 opfamilies = lappend_oid(opfamilies, opfamily);
2997 else /* should not happen */
2998 ereport(ERROR,
3000 errmsg("could not determine interpretation of row comparison operator %s",
3001 strVal(llast(opname))),
3002 errdetail("There are multiple equally-plausible candidates."),
3003 parser_errposition(pstate, location)));
3004 }
3005
3006 /*
3007 * Now deconstruct the OpExprs and create a RowCompareExpr.
3008 *
3009 * Note: can't just reuse the passed largs/rargs lists, because of
3010 * possibility that make_op inserted coercion operations.
3011 */
3012 opnos = NIL;
3013 largs = NIL;
3014 rargs = NIL;
3015 foreach(l, opexprs)
3016 {
3017 OpExpr *cmp = (OpExpr *) lfirst(l);
3018
3019 opnos = lappend_oid(opnos, cmp->opno);
3020 largs = lappend(largs, linitial(cmp->args));
3021 rargs = lappend(rargs, lsecond(cmp->args));
3022 }
3023
3025 rcexpr->cmptype = cmptype;
3026 rcexpr->opnos = opnos;
3027 rcexpr->opfamilies = opfamilies;
3028 rcexpr->inputcollids = NIL; /* assign_expr_collations will fix this */
3029 rcexpr->largs = largs;
3030 rcexpr->rargs = rargs;
3031
3032 return (Node *) rcexpr;
3033}
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1108
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1305
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
CompareType
Definition cmptype.h:32
@ COMPARE_EQ
Definition cmptype.h:36
@ COMPARE_NE
Definition cmptype.h:39
int errdetail(const char *fmt,...)
Definition elog.c:1216
#define palloc_array(type, count)
Definition fe_memutils.h:76
int j
Definition isn.c:78
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
List * get_op_index_interpretation(Oid opno)
Definition lsyscache.c:666
Expr * makeBoolExpr(BoolExprType boolop, List *args, int location)
Definition makefuncs.c:420
bool expression_returns_set(Node *clause)
Definition nodeFuncs.c:763
#define castNode(_type_, nodeptr)
Definition nodes.h:182
#define lfirst(lc)
Definition pg_list.h:172
#define llast(l)
Definition pg_list.h:198
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:518
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183
@ AND_EXPR
Definition primnodes.h:963
@ OR_EXPR
Definition primnodes.h:963
static int cmp(const chr *x, const chr *y, size_t len)
Definition pg_list.h:54
#define strVal(v)
Definition value.h:82

References AND_EXPR, bms_add_member(), bms_int_members(), bms_next_member(), castNode, cmp(), COMPARE_EQ, COMPARE_NE, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, expression_returns_set(), fb(), forboth, format_type_be(), get_op_index_interpretation(), i, InvalidOid, j, lappend(), lappend_oid(), lfirst, linitial, list_length(), llast, lsecond, make_op(), makeBoolExpr(), makeNode, NIL, OidIsValid, OR_EXPR, ParseState::p_last_srf, palloc_array, parser_errposition(), and strVal.

Referenced by transformAExprIn(), transformAExprOp(), and transformSubLink().

◆ make_row_distinct_op()

static Node * make_row_distinct_op ( ParseState pstate,
List opname,
RowExpr lrow,
RowExpr rrow,
int  location 
)
static

Definition at line 3041 of file parse_expr.c.

3044{
3045 Node *result = NULL;
3046 List *largs = lrow->args;
3047 List *rargs = rrow->args;
3048 ListCell *l,
3049 *r;
3050
3051 if (list_length(largs) != list_length(rargs))
3052 ereport(ERROR,
3054 errmsg("unequal number of entries in row expressions"),
3055 parser_errposition(pstate, location)));
3056
3057 forboth(l, largs, r, rargs)
3058 {
3059 Node *larg = (Node *) lfirst(l);
3060 Node *rarg = (Node *) lfirst(r);
3061 Node *cmp;
3062
3063 cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location);
3064 if (result == NULL)
3065 result = cmp;
3066 else
3067 result = (Node *) makeBoolExpr(OR_EXPR,
3068 list_make2(result, cmp),
3069 location);
3070 }
3071
3072 if (result == NULL)
3073 {
3074 /* zero-length rows? Generate constant FALSE */
3075 result = makeBoolConst(false, false);
3076 }
3077
3078 return result;
3079}
Node * makeBoolConst(bool value, bool isnull)
Definition makefuncs.c:408
static Expr * make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location)

References cmp(), ereport, errcode(), errmsg(), ERROR, fb(), forboth, lfirst, list_length(), list_make2, make_distinct_op(), makeBoolConst(), makeBoolExpr(), OR_EXPR, and parser_errposition().

Referenced by transformAExprDistinct().

◆ makeJsonByteaToTextConversion()

static Node * makeJsonByteaToTextConversion ( Node expr,
JsonFormat format,
int  location 
)
static

Definition at line 3289 of file parse_expr.c.

3290{
3293 list_make2(expr, encoding),
3296
3297 fexpr->location = location;
3298
3299 return (Node *) fexpr;
3300}

References COERCE_EXPLICIT_CALL, encoding, fb(), format, getJsonEncodingConst(), InvalidOid, list_make2, and makeFuncExpr().

Referenced by transformJsonParseArg(), and transformJsonValueExpr().

◆ makeJsonConstructorExpr()

static Node * makeJsonConstructorExpr ( ParseState pstate,
JsonConstructorType  type,
List args,
Expr fexpr,
JsonReturning returning,
bool  unique,
bool  absent_on_null,
int  location 
)
static

Definition at line 3677 of file parse_expr.c.

3680{
3683 Node *coercion;
3684
3685 jsctor->args = args;
3686 jsctor->func = fexpr;
3687 jsctor->type = type;
3688 jsctor->returning = returning;
3689 jsctor->unique = unique;
3690 jsctor->absent_on_null = absent_on_null;
3691 jsctor->location = location;
3692
3693 /*
3694 * Coerce to the RETURNING type and format, if needed. We abuse
3695 * CaseTestExpr here as placeholder to pass the result of either
3696 * evaluating 'fexpr' or whatever is produced by ExecEvalJsonConstructor()
3697 * that is of type JSON or JSONB to the coercion function.
3698 */
3699 if (fexpr)
3700 {
3702
3703 cte->typeId = exprType((Node *) fexpr);
3704 cte->typeMod = exprTypmod((Node *) fexpr);
3705 cte->collation = exprCollation((Node *) fexpr);
3706
3707 placeholder = (Node *) cte;
3708 }
3709 else
3710 {
3712
3713 cte->typeId = returning->format->format_type == JS_FORMAT_JSONB ?
3714 JSONBOID : JSONOID;
3715 cte->typeMod = -1;
3716 cte->collation = InvalidOid;
3717
3718 placeholder = (Node *) cte;
3719 }
3720
3721 coercion = coerceJsonFuncExpr(pstate, placeholder, returning, true);
3722
3723 if (coercion != placeholder)
3724 jsctor->coercion = (Expr *) coercion;
3725
3726 return (Node *) jsctor;
3727}
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:301
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:821
static Node * coerceJsonFuncExpr(ParseState *pstate, Node *expr, const JsonReturning *returning, bool report_error)
@ JS_FORMAT_JSONB
Definition primnodes.h:1665
const char * type

References coerceJsonFuncExpr(), exprCollation(), exprType(), exprTypmod(), fb(), JsonReturning::format, JsonFormat::format_type, InvalidOid, JS_FORMAT_JSONB, makeNode, type, and CaseTestExpr::typeId.

Referenced by transformJsonAggConstructor(), transformJsonArrayConstructor(), transformJsonObjectConstructor(), transformJsonParseExpr(), transformJsonScalarExpr(), and transformJsonSerializeExpr().

◆ ParseExprKindName()

const char * ParseExprKindName ( ParseExprKind  exprKind)

Definition at line 3144 of file parse_expr.c.

3145{
3146 switch (exprKind)
3147 {
3148 case EXPR_KIND_NONE:
3149 return "invalid expression context";
3150 case EXPR_KIND_OTHER:
3151 return "extension expression";
3152 case EXPR_KIND_JOIN_ON:
3153 return "JOIN/ON";
3155 return "JOIN/USING";
3157 return "sub-SELECT in FROM";
3159 return "function in FROM";
3160 case EXPR_KIND_WHERE:
3161 return "WHERE";
3162 case EXPR_KIND_POLICY:
3163 return "POLICY";
3164 case EXPR_KIND_HAVING:
3165 return "HAVING";
3166 case EXPR_KIND_FILTER:
3167 return "FILTER";
3169 return "window PARTITION BY";
3171 return "window ORDER BY";
3173 return "window RANGE";
3175 return "window ROWS";
3177 return "window GROUPS";
3179 return "SELECT";
3181 return "INSERT";
3184 return "UPDATE";
3186 return "MERGE WHEN";
3187 case EXPR_KIND_GROUP_BY:
3188 return "GROUP BY";
3189 case EXPR_KIND_ORDER_BY:
3190 return "ORDER BY";
3192 return "DISTINCT ON";
3193 case EXPR_KIND_LIMIT:
3194 return "LIMIT";
3195 case EXPR_KIND_OFFSET:
3196 return "OFFSET";
3199 return "RETURNING";
3200 case EXPR_KIND_VALUES:
3202 return "VALUES";
3205 return "CHECK";
3208 return "DEFAULT";
3210 return "index expression";
3212 return "index predicate";
3214 return "statistics expression";
3216 return "USING";
3218 return "EXECUTE";
3220 return "WHEN";
3222 return "partition bound";
3224 return "PARTITION BY";
3226 return "CALL";
3228 return "WHERE";
3230 return "GENERATED AS";
3232 return "CYCLE";
3233
3234 /*
3235 * There is intentionally no default: case here, so that the
3236 * compiler will warn if we add a new ParseExprKind without
3237 * extending this switch. If we do see an unrecognized value at
3238 * runtime, we'll fall through to the "unrecognized" return.
3239 */
3240 }
3241 return "unrecognized expression kind";
3242}
@ EXPR_KIND_EXECUTE_PARAMETER
Definition parse_node.h:76
@ EXPR_KIND_DOMAIN_CHECK
Definition parse_node.h:69
@ EXPR_KIND_COPY_WHERE
Definition parse_node.h:82
@ EXPR_KIND_COLUMN_DEFAULT
Definition parse_node.h:70
@ EXPR_KIND_DISTINCT_ON
Definition parse_node.h:61
@ EXPR_KIND_MERGE_WHEN
Definition parse_node.h:58
@ EXPR_KIND_STATS_EXPRESSION
Definition parse_node.h:74
@ EXPR_KIND_INDEX_EXPRESSION
Definition parse_node.h:72
@ EXPR_KIND_MERGE_RETURNING
Definition parse_node.h:65
@ EXPR_KIND_PARTITION_BOUND
Definition parse_node.h:79
@ EXPR_KIND_FUNCTION_DEFAULT
Definition parse_node.h:71
@ EXPR_KIND_WINDOW_FRAME_RANGE
Definition parse_node.h:51
@ EXPR_KIND_VALUES
Definition parse_node.h:66
@ EXPR_KIND_FROM_SUBSELECT
Definition parse_node.h:44
@ EXPR_KIND_POLICY
Definition parse_node.h:78
@ EXPR_KIND_WINDOW_FRAME_GROUPS
Definition parse_node.h:53
@ EXPR_KIND_PARTITION_EXPRESSION
Definition parse_node.h:80
@ EXPR_KIND_JOIN_USING
Definition parse_node.h:43
@ EXPR_KIND_INDEX_PREDICATE
Definition parse_node.h:73
@ EXPR_KIND_ORDER_BY
Definition parse_node.h:60
@ EXPR_KIND_OFFSET
Definition parse_node.h:63
@ EXPR_KIND_JOIN_ON
Definition parse_node.h:42
@ EXPR_KIND_HAVING
Definition parse_node.h:47
@ EXPR_KIND_INSERT_TARGET
Definition parse_node.h:55
@ EXPR_KIND_ALTER_COL_TRANSFORM
Definition parse_node.h:75
@ EXPR_KIND_LIMIT
Definition parse_node.h:62
@ EXPR_KIND_WHERE
Definition parse_node.h:46
@ EXPR_KIND_UPDATE_TARGET
Definition parse_node.h:57
@ EXPR_KIND_SELECT_TARGET
Definition parse_node.h:54
@ EXPR_KIND_RETURNING
Definition parse_node.h:64
@ EXPR_KIND_GENERATED_COLUMN
Definition parse_node.h:83
@ EXPR_KIND_NONE
Definition parse_node.h:40
@ EXPR_KIND_CALL_ARGUMENT
Definition parse_node.h:81
@ EXPR_KIND_GROUP_BY
Definition parse_node.h:59
@ EXPR_KIND_OTHER
Definition parse_node.h:41
@ EXPR_KIND_FROM_FUNCTION
Definition parse_node.h:45
@ EXPR_KIND_TRIGGER_WHEN
Definition parse_node.h:77
@ EXPR_KIND_FILTER
Definition parse_node.h:48
@ EXPR_KIND_UPDATE_SOURCE
Definition parse_node.h:56
@ EXPR_KIND_CHECK_CONSTRAINT
Definition parse_node.h:68
@ EXPR_KIND_WINDOW_PARTITION
Definition parse_node.h:49
@ EXPR_KIND_CYCLE_MARK
Definition parse_node.h:84
@ EXPR_KIND_WINDOW_FRAME_ROWS
Definition parse_node.h:52
@ EXPR_KIND_WINDOW_ORDER
Definition parse_node.h:50
@ EXPR_KIND_VALUES_SINGLE
Definition parse_node.h:67

References EXPR_KIND_ALTER_COL_TRANSFORM, EXPR_KIND_CALL_ARGUMENT, EXPR_KIND_CHECK_CONSTRAINT, EXPR_KIND_COLUMN_DEFAULT, EXPR_KIND_COPY_WHERE, EXPR_KIND_CYCLE_MARK, EXPR_KIND_DISTINCT_ON, EXPR_KIND_DOMAIN_CHECK, EXPR_KIND_EXECUTE_PARAMETER, EXPR_KIND_FILTER, EXPR_KIND_FROM_FUNCTION, EXPR_KIND_FROM_SUBSELECT, EXPR_KIND_FUNCTION_DEFAULT, EXPR_KIND_GENERATED_COLUMN, EXPR_KIND_GROUP_BY, EXPR_KIND_HAVING, EXPR_KIND_INDEX_EXPRESSION, EXPR_KIND_INDEX_PREDICATE, EXPR_KIND_INSERT_TARGET, EXPR_KIND_JOIN_ON, EXPR_KIND_JOIN_USING, EXPR_KIND_LIMIT, EXPR_KIND_MERGE_RETURNING, EXPR_KIND_MERGE_WHEN, EXPR_KIND_NONE, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_OTHER, EXPR_KIND_PARTITION_BOUND, EXPR_KIND_PARTITION_EXPRESSION, EXPR_KIND_POLICY, EXPR_KIND_RETURNING, EXPR_KIND_SELECT_TARGET, EXPR_KIND_STATS_EXPRESSION, EXPR_KIND_TRIGGER_WHEN, EXPR_KIND_UPDATE_SOURCE, EXPR_KIND_UPDATE_TARGET, EXPR_KIND_VALUES, EXPR_KIND_VALUES_SINGLE, EXPR_KIND_WHERE, EXPR_KIND_WINDOW_FRAME_GROUPS, EXPR_KIND_WINDOW_FRAME_RANGE, EXPR_KIND_WINDOW_FRAME_ROWS, EXPR_KIND_WINDOW_ORDER, EXPR_KIND_WINDOW_PARTITION, and fb().

Referenced by check_agglevels_and_constraints(), check_srf_call_placement(), checkTargetlistEntrySQL92(), findTargetlistEntrySQL92(), and transformWindowFuncCall().

◆ transformAExprBetween()

static Node * transformAExprBetween ( ParseState pstate,
A_Expr a 
)
static

Definition at line 1295 of file parse_expr.c.

1296{
1297 Node *aexpr;
1298 Node *bexpr;
1299 Node *cexpr;
1300 Node *result;
1301 Node *sub1;
1302 Node *sub2;
1303 List *args;
1304
1305 /* Deconstruct A_Expr into three subexprs */
1306 aexpr = a->lexpr;
1307 args = castNode(List, a->rexpr);
1308 Assert(list_length(args) == 2);
1309 bexpr = (Node *) linitial(args);
1310 cexpr = (Node *) lsecond(args);
1311
1312 /*
1313 * Build the equivalent comparison expression. Make copies of
1314 * multiply-referenced subexpressions for safety. (XXX this is really
1315 * wrong since it results in multiple runtime evaluations of what may be
1316 * volatile expressions ...)
1317 *
1318 * Ideally we would not use hard-wired operators here but instead use
1319 * opclasses. However, mixed data types and other issues make this
1320 * difficult:
1321 * http://archives.postgresql.org/pgsql-hackers/2008-08/msg01142.php
1322 */
1323 switch (a->kind)
1324 {
1325 case AEXPR_BETWEEN:
1327 aexpr, bexpr,
1328 a->location),
1330 copyObject(aexpr), cexpr,
1331 a->location));
1332 result = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
1333 break;
1334 case AEXPR_NOT_BETWEEN:
1336 aexpr, bexpr,
1337 a->location),
1339 copyObject(aexpr), cexpr,
1340 a->location));
1341 result = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
1342 break;
1343 case AEXPR_BETWEEN_SYM:
1345 aexpr, bexpr,
1346 a->location),
1348 copyObject(aexpr), cexpr,
1349 a->location));
1350 sub1 = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
1352 copyObject(aexpr), copyObject(cexpr),
1353 a->location),
1356 a->location));
1357 sub2 = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
1359 result = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
1360 break;
1363 aexpr, bexpr,
1364 a->location),
1366 copyObject(aexpr), cexpr,
1367 a->location));
1368 sub1 = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
1370 copyObject(aexpr), copyObject(cexpr),
1371 a->location),
1374 a->location));
1375 sub2 = (Node *) makeBoolExpr(OR_EXPR, args, a->location);
1377 result = (Node *) makeBoolExpr(AND_EXPR, args, a->location);
1378 break;
1379 default:
1380 elog(ERROR, "unrecognized A_Expr kind: %d", a->kind);
1381 result = NULL; /* keep compiler quiet */
1382 break;
1383 }
1384
1385 return transformExprRecurse(pstate, result);
1386}
int a
Definition isn.c:73
A_Expr * makeSimpleA_Expr(A_Expr_Kind kind, char *name, Node *lexpr, Node *rexpr, int location)
Definition makefuncs.c:48
#define copyObject(obj)
Definition nodes.h:232
@ AEXPR_BETWEEN
Definition parsenodes.h:340
@ AEXPR_BETWEEN_SYM
Definition parsenodes.h:342
@ AEXPR_NOT_BETWEEN_SYM
Definition parsenodes.h:343
@ AEXPR_NOT_BETWEEN
Definition parsenodes.h:341
@ AEXPR_OP
Definition parsenodes.h:330

References a, AEXPR_BETWEEN, AEXPR_BETWEEN_SYM, AEXPR_NOT_BETWEEN, AEXPR_NOT_BETWEEN_SYM, AEXPR_OP, AND_EXPR, Assert, castNode, copyObject, elog, ERROR, fb(), linitial, list_length(), list_make2, lsecond, makeBoolExpr(), makeSimpleA_Expr(), OR_EXPR, and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformAExprDistinct()

static Node * transformAExprDistinct ( ParseState pstate,
A_Expr a 
)
static

Definition at line 1032 of file parse_expr.c.

1033{
1034 Node *lexpr = a->lexpr;
1035 Node *rexpr = a->rexpr;
1036 Node *result;
1037
1038 /*
1039 * If either input is an undecorated NULL literal, transform to a NullTest
1040 * on the other input. That's simpler to process than a full DistinctExpr,
1041 * and it avoids needing to require that the datatype have an = operator.
1042 */
1043 if (exprIsNullConstant(rexpr))
1044 return make_nulltest_from_distinct(pstate, a, lexpr);
1045 if (exprIsNullConstant(lexpr))
1046 return make_nulltest_from_distinct(pstate, a, rexpr);
1047
1048 lexpr = transformExprRecurse(pstate, lexpr);
1049 rexpr = transformExprRecurse(pstate, rexpr);
1050
1051 if (lexpr && IsA(lexpr, RowExpr) &&
1052 rexpr && IsA(rexpr, RowExpr))
1053 {
1054 /* ROW() op ROW() is handled specially */
1055 result = make_row_distinct_op(pstate, a->name,
1056 (RowExpr *) lexpr,
1057 (RowExpr *) rexpr,
1058 a->location);
1059 }
1060 else
1061 {
1062 /* Ordinary scalar operator */
1063 result = (Node *) make_distinct_op(pstate,
1064 a->name,
1065 lexpr,
1066 rexpr,
1067 a->location);
1068 }
1069
1070 /*
1071 * If it's NOT DISTINCT, we first build a DistinctExpr and then stick a
1072 * NOT on top.
1073 */
1074 if (a->kind == AEXPR_NOT_DISTINCT)
1075 result = (Node *) makeBoolExpr(NOT_EXPR,
1076 list_make1(result),
1077 a->location);
1078
1079 return result;
1080}
static Node * make_nulltest_from_distinct(ParseState *pstate, A_Expr *distincta, Node *arg)
static bool exprIsNullConstant(Node *arg)
Definition parse_expr.c:910
static Node * make_row_distinct_op(ParseState *pstate, List *opname, RowExpr *lrow, RowExpr *rrow, int location)
#define list_make1(x1)
Definition pg_list.h:212
@ NOT_EXPR
Definition primnodes.h:963

References a, AEXPR_NOT_DISTINCT, exprIsNullConstant(), IsA, list_make1, make_distinct_op(), make_nulltest_from_distinct(), make_row_distinct_op(), makeBoolExpr(), NOT_EXPR, and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformAExprIn()

static Node * transformAExprIn ( ParseState pstate,
A_Expr a 
)
static

Definition at line 1126 of file parse_expr.c.

1127{
1128 Node *result = NULL;
1129 Node *lexpr;
1130 List *rexprs;
1131 List *rvars;
1132 List *rnonvars;
1133 bool useOr;
1134 ListCell *l;
1135 bool has_rvars = false;
1136
1137 /*
1138 * If the operator is <>, combine with AND not OR.
1139 */
1140 if (strcmp(strVal(linitial(a->name)), "<>") == 0)
1141 useOr = false;
1142 else
1143 useOr = true;
1144
1145 /*
1146 * We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
1147 * possible if there is a suitable array type available. If not, we fall
1148 * back to a boolean condition tree with multiple copies of the lefthand
1149 * expression. Also, any IN-list items that contain Vars are handled as
1150 * separate boolean conditions, because that gives the planner more scope
1151 * for optimization on such clauses.
1152 *
1153 * First step: transform all the inputs, and detect whether any contain
1154 * Vars.
1155 */
1156 lexpr = transformExprRecurse(pstate, a->lexpr);
1157 rexprs = rvars = rnonvars = NIL;
1158 foreach(l, (List *) a->rexpr)
1159 {
1160 Node *rexpr = transformExprRecurse(pstate, lfirst(l));
1161
1162 rexprs = lappend(rexprs, rexpr);
1163 if (contain_vars_of_level(rexpr, 0))
1164 {
1165 rvars = lappend(rvars, rexpr);
1166 has_rvars = true;
1167 }
1168 else
1169 rnonvars = lappend(rnonvars, rexpr);
1170 }
1171
1172 /*
1173 * ScalarArrayOpExpr is only going to be useful if there's more than one
1174 * non-Var righthand item.
1175 */
1176 if (list_length(rnonvars) > 1)
1177 {
1178 List *allexprs;
1180 Oid array_type;
1181
1182 /*
1183 * Try to select a common type for the array elements. Note that
1184 * since the LHS' type is first in the list, it will be preferred when
1185 * there is doubt (eg, when all the RHS items are unknown literals).
1186 *
1187 * Note: use list_concat here not lcons, to avoid damaging rnonvars.
1188 */
1191
1192 /* We have to verify that the selected type actually works */
1193 if (OidIsValid(scalar_type) &&
1196
1197 /*
1198 * Do we have an array type to use? Aside from the case where there
1199 * isn't one, we don't risk using ScalarArrayOpExpr when the common
1200 * type is RECORD, because the RowExpr comparison logic below can cope
1201 * with some cases of non-identical row types.
1202 */
1204 array_type = get_array_type(scalar_type);
1205 else
1206 array_type = InvalidOid;
1207 if (array_type != InvalidOid)
1208 {
1209 /*
1210 * OK: coerce all the right-hand non-Var inputs to the common type
1211 * and build an ArrayExpr for them.
1212 */
1213 List *aexprs;
1214 ArrayExpr *newa;
1215
1216 aexprs = NIL;
1217 foreach(l, rnonvars)
1218 {
1219 Node *rexpr = (Node *) lfirst(l);
1220
1221 rexpr = coerce_to_common_type(pstate, rexpr,
1223 "IN");
1224 aexprs = lappend(aexprs, rexpr);
1225 }
1227 newa->array_typeid = array_type;
1228 /* array_collid will be set by parse_collate.c */
1229 newa->element_typeid = scalar_type;
1230 newa->elements = aexprs;
1231 newa->multidims = false;
1232 newa->location = -1;
1233
1234 /*
1235 * If the IN expression contains Vars, disable query jumbling
1236 * squashing. Vars cannot be safely jumbled.
1237 */
1238 newa->list_start = has_rvars ? -1 : a->rexpr_list_start;
1239 newa->list_end = has_rvars ? -1 : a->rexpr_list_end;
1240
1241 result = (Node *) make_scalar_array_op(pstate,
1242 a->name,
1243 useOr,
1244 lexpr,
1245 (Node *) newa,
1246 a->location);
1247
1248 /* Consider only the Vars (if any) in the loop below */
1249 rexprs = rvars;
1250 }
1251 }
1252
1253 /*
1254 * Must do it the hard way, ie, with a boolean expression tree.
1255 */
1256 foreach(l, rexprs)
1257 {
1258 Node *rexpr = (Node *) lfirst(l);
1259 Node *cmp;
1260
1261 if (IsA(lexpr, RowExpr) &&
1262 IsA(rexpr, RowExpr))
1263 {
1264 /* ROW() op ROW() is handled specially */
1265 cmp = make_row_comparison_op(pstate,
1266 a->name,
1267 copyObject(((RowExpr *) lexpr)->args),
1268 ((RowExpr *) rexpr)->args,
1269 a->location);
1270 }
1271 else
1272 {
1273 /* Ordinary scalar operator */
1274 cmp = (Node *) make_op(pstate,
1275 a->name,
1276 copyObject(lexpr),
1277 rexpr,
1278 pstate->p_last_srf,
1279 a->location);
1280 }
1281
1282 cmp = coerce_to_boolean(pstate, cmp, "IN");
1283 if (result == NULL)
1284 result = cmp;
1285 else
1286 result = (Node *) makeBoolExpr(useOr ? OR_EXPR : AND_EXPR,
1287 list_make2(result, cmp),
1288 a->location);
1289 }
1290
1291 return result;
1292}
List * list_concat(List *list1, const List *list2)
Definition list.c:561
Oid get_array_type(Oid typid)
Definition lsyscache.c:2937
Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)
bool verify_common_type(Oid common_type, List *exprs)
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)
Oid select_common_type(ParseState *pstate, List *exprs, const char *context, Node **which_expr)
static Node * make_row_comparison_op(ParseState *pstate, List *opname, List *largs, List *rargs, int location)
Expr * make_scalar_array_op(ParseState *pstate, List *opname, bool useOr, Node *ltree, Node *rtree, int location)
Definition parse_oper.c:813
bool contain_vars_of_level(Node *node, int levelsup)
Definition var.c:444

References a, AND_EXPR, cmp(), coerce_to_boolean(), coerce_to_common_type(), contain_vars_of_level(), copyObject, fb(), get_array_type(), InvalidOid, IsA, lappend(), lfirst, linitial, list_concat(), list_length(), list_make1, list_make2, make_op(), make_row_comparison_op(), make_scalar_array_op(), makeBoolExpr(), makeNode, NIL, OidIsValid, OR_EXPR, ParseState::p_last_srf, select_common_type(), strVal, transformExprRecurse(), and verify_common_type().

Referenced by transformExprRecurse().

◆ transformAExprNullIf()

static Node * transformAExprNullIf ( ParseState pstate,
A_Expr a 
)
static

Definition at line 1083 of file parse_expr.c.

1084{
1085 Node *lexpr = transformExprRecurse(pstate, a->lexpr);
1086 Node *rexpr = transformExprRecurse(pstate, a->rexpr);
1087 OpExpr *result;
1088
1089 result = (OpExpr *) make_op(pstate,
1090 a->name,
1091 lexpr,
1092 rexpr,
1093 pstate->p_last_srf,
1094 a->location);
1095
1096 /*
1097 * The comparison operator itself should yield boolean ...
1098 */
1099 if (result->opresulttype != BOOLOID)
1100 ereport(ERROR,
1102 /* translator: %s is name of a SQL construct, eg NULLIF */
1103 errmsg("%s requires = operator to yield boolean", "NULLIF"),
1104 parser_errposition(pstate, a->location)));
1105 if (result->opretset)
1106 ereport(ERROR,
1108 /* translator: %s is name of a SQL construct, eg NULLIF */
1109 errmsg("%s must not return a set", "NULLIF"),
1110 parser_errposition(pstate, a->location)));
1111
1112 /*
1113 * ... but the NullIfExpr will yield the first operand's type.
1114 */
1115 result->opresulttype = exprType((Node *) linitial(result->args));
1116
1117 /*
1118 * We rely on NullIfExpr and OpExpr being the same struct
1119 */
1120 NodeSetTag(result, T_NullIfExpr);
1121
1122 return (Node *) result;
1123}
List * args
Definition primnodes.h:868

References a, OpExpr::args, ereport, errcode(), errmsg(), ERROR, exprType(), fb(), linitial, make_op(), NodeSetTag, ParseState::p_last_srf, parser_errposition(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformAExprOp()

static Node * transformAExprOp ( ParseState pstate,
A_Expr a 
)
static

Definition at line 923 of file parse_expr.c.

924{
925 Node *lexpr = a->lexpr;
926 Node *rexpr = a->rexpr;
927 Node *result;
928
929 /*
930 * Special-case "foo = NULL" and "NULL = foo" for compatibility with
931 * standards-broken products (like Microsoft's). Turn these into IS NULL
932 * exprs. (If either side is a CaseTestExpr, then the expression was
933 * generated internally from a CASE-WHEN expression, and
934 * transform_null_equals does not apply.)
935 */
937 list_length(a->name) == 1 &&
938 strcmp(strVal(linitial(a->name)), "=") == 0 &&
939 (exprIsNullConstant(lexpr) || exprIsNullConstant(rexpr)) &&
940 (!IsA(lexpr, CaseTestExpr) && !IsA(rexpr, CaseTestExpr)))
941 {
943
945 n->location = a->location;
946
947 if (exprIsNullConstant(lexpr))
948 n->arg = (Expr *) rexpr;
949 else
950 n->arg = (Expr *) lexpr;
951
952 result = transformExprRecurse(pstate, (Node *) n);
953 }
954 else if (lexpr && IsA(lexpr, RowExpr) &&
955 rexpr && IsA(rexpr, SubLink) &&
956 ((SubLink *) rexpr)->subLinkType == EXPR_SUBLINK)
957 {
958 /*
959 * Convert "row op subselect" into a ROWCOMPARE sublink. Formerly the
960 * grammar did this, but now that a row construct is allowed anywhere
961 * in expressions, it's easier to do it here.
962 */
963 SubLink *s = (SubLink *) rexpr;
964
966 s->testexpr = lexpr;
967 s->operName = a->name;
968 s->location = a->location;
969 result = transformExprRecurse(pstate, (Node *) s);
970 }
971 else if (lexpr && IsA(lexpr, RowExpr) &&
972 rexpr && IsA(rexpr, RowExpr))
973 {
974 /* ROW() op ROW() is handled specially */
975 lexpr = transformExprRecurse(pstate, lexpr);
976 rexpr = transformExprRecurse(pstate, rexpr);
977
978 result = make_row_comparison_op(pstate,
979 a->name,
980 castNode(RowExpr, lexpr)->args,
981 castNode(RowExpr, rexpr)->args,
982 a->location);
983 }
984 else
985 {
986 /* Ordinary scalar operator */
987 Node *last_srf = pstate->p_last_srf;
988
989 lexpr = transformExprRecurse(pstate, lexpr);
990 rexpr = transformExprRecurse(pstate, rexpr);
991
992 result = (Node *) make_op(pstate,
993 a->name,
994 lexpr,
995 rexpr,
996 last_srf,
997 a->location);
998 }
999
1000 return result;
1001}
bool Transform_null_equals
Definition parse_expr.c:45
@ EXPR_SUBLINK
Definition primnodes.h:1033
@ ROWCOMPARE_SUBLINK
Definition primnodes.h:1032
NullTestType nulltesttype
Definition primnodes.h:1984
ParseLoc location
Definition primnodes.h:1987
Expr * arg
Definition primnodes.h:1983

References a, NullTest::arg, castNode, EXPR_SUBLINK, exprIsNullConstant(), fb(), IS_NULL, IsA, linitial, list_length(), SubLink::location, NullTest::location, make_op(), make_row_comparison_op(), makeNode, NullTest::nulltesttype, ParseState::p_last_srf, ROWCOMPARE_SUBLINK, strVal, SubLink::subLinkType, SubLink::testexpr, Transform_null_equals, and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformAExprOpAll()

static Node * transformAExprOpAll ( ParseState pstate,
A_Expr a 
)
static

Definition at line 1018 of file parse_expr.c.

1019{
1020 Node *lexpr = transformExprRecurse(pstate, a->lexpr);
1021 Node *rexpr = transformExprRecurse(pstate, a->rexpr);
1022
1023 return (Node *) make_scalar_array_op(pstate,
1024 a->name,
1025 false,
1026 lexpr,
1027 rexpr,
1028 a->location);
1029}

References a, make_scalar_array_op(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformAExprOpAny()

static Node * transformAExprOpAny ( ParseState pstate,
A_Expr a 
)
static

Definition at line 1004 of file parse_expr.c.

1005{
1006 Node *lexpr = transformExprRecurse(pstate, a->lexpr);
1007 Node *rexpr = transformExprRecurse(pstate, a->rexpr);
1008
1009 return (Node *) make_scalar_array_op(pstate,
1010 a->name,
1011 true,
1012 lexpr,
1013 rexpr,
1014 a->location);
1015}

References a, make_scalar_array_op(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformArrayExpr()

static Node * transformArrayExpr ( ParseState pstate,
A_ArrayExpr a,
Oid  array_type,
Oid  element_type,
int32  typmod 
)
static

Definition at line 2026 of file parse_expr.c.

2028{
2030 List *newelems = NIL;
2034 bool coerce_hard;
2035
2036 /*
2037 * Transform the element expressions
2038 *
2039 * Assume that the array is one-dimensional unless we find an array-type
2040 * element expression.
2041 */
2042 newa->multidims = false;
2043 foreach(element, a->elements)
2044 {
2045 Node *e = (Node *) lfirst(element);
2046 Node *newe;
2047
2048 /*
2049 * If an element is itself an A_ArrayExpr, recurse directly so that we
2050 * can pass down any target type we were given.
2051 */
2052 if (IsA(e, A_ArrayExpr))
2053 {
2054 newe = transformArrayExpr(pstate,
2055 (A_ArrayExpr *) e,
2056 array_type,
2057 element_type,
2058 typmod);
2059 /* we certainly have an array here */
2060 Assert(array_type == InvalidOid || array_type == exprType(newe));
2061 newa->multidims = true;
2062 }
2063 else
2064 {
2065 newe = transformExprRecurse(pstate, e);
2066
2067 /*
2068 * Check for sub-array expressions, if we haven't already found
2069 * one. Note we don't accept domain-over-array as a sub-array,
2070 * nor int2vector nor oidvector; those have constraints that don't
2071 * map well to being treated as a sub-array.
2072 */
2073 if (!newa->multidims)
2074 {
2076
2079 newa->multidims = true;
2080 }
2081 }
2082
2084 }
2085
2086 /*
2087 * Select a target type for the elements.
2088 *
2089 * If we haven't been given a target array type, we must try to deduce a
2090 * common type based on the types of the individual elements present.
2091 */
2092 if (OidIsValid(array_type))
2093 {
2094 /* Caller must ensure array_type matches element_type */
2095 Assert(OidIsValid(element_type));
2096 coerce_type = (newa->multidims ? array_type : element_type);
2097 coerce_hard = true;
2098 }
2099 else
2100 {
2101 /* Can't handle an empty array without a target type */
2102 if (newelems == NIL)
2103 ereport(ERROR,
2105 errmsg("cannot determine type of empty array"),
2106 errhint("Explicitly cast to the desired type, "
2107 "for example ARRAY[]::integer[]."),
2108 parser_errposition(pstate, a->location)));
2109
2110 /* Select a common type for the elements */
2111 coerce_type = select_common_type(pstate, newelems, "ARRAY", NULL);
2112
2113 if (newa->multidims)
2114 {
2115 array_type = coerce_type;
2116 element_type = get_element_type(array_type);
2117 if (!OidIsValid(element_type))
2118 ereport(ERROR,
2120 errmsg("could not find element type for data type %s",
2121 format_type_be(array_type)),
2122 parser_errposition(pstate, a->location)));
2123 }
2124 else
2125 {
2126 element_type = coerce_type;
2127 array_type = get_array_type(element_type);
2128 if (!OidIsValid(array_type))
2129 ereport(ERROR,
2131 errmsg("could not find array type for data type %s",
2132 format_type_be(element_type)),
2133 parser_errposition(pstate, a->location)));
2134 }
2135 coerce_hard = false;
2136 }
2137
2138 /*
2139 * Coerce elements to target type
2140 *
2141 * If the array has been explicitly cast, then the elements are in turn
2142 * explicitly coerced.
2143 *
2144 * If the array's type was merely derived from the common type of its
2145 * elements, then the elements are implicitly coerced to the common type.
2146 * This is consistent with other uses of select_common_type().
2147 */
2148 foreach(element, newelems)
2149 {
2150 Node *e = (Node *) lfirst(element);
2151 Node *newe;
2152
2153 if (coerce_hard)
2154 {
2155 newe = coerce_to_target_type(pstate, e,
2156 exprType(e),
2158 typmod,
2161 -1);
2162 if (newe == NULL)
2163 ereport(ERROR,
2165 errmsg("cannot cast type %s to %s",
2168 parser_errposition(pstate, exprLocation(e))));
2169 }
2170 else
2171 newe = coerce_to_common_type(pstate, e,
2173 "ARRAY");
2175 }
2176
2177 newa->array_typeid = array_type;
2178 /* array_collid will be set by parse_collate.c */
2179 newa->element_typeid = element_type;
2180 newa->elements = newcoercedelems;
2181 newa->list_start = a->list_start;
2182 newa->list_end = a->list_end;
2183 newa->location = a->location;
2184
2185 return (Node *) newa;
2186}
Oid get_element_type(Oid typid)
Definition lsyscache.c:2909
#define type_is_array(typid)
Definition lsyscache.h:214
Node * coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod, CoercionContext ccontext, CoercionForm cformat, int location)
static Node * transformArrayExpr(ParseState *pstate, A_ArrayExpr *a, Oid array_type, Oid element_type, int32 typmod)
e
@ COERCE_EXPLICIT_CAST
Definition primnodes.h:767
@ COERCION_EXPLICIT
Definition primnodes.h:749
static chr element(struct vars *v, const chr *startp, const chr *endp)

References a, Assert, COERCE_EXPLICIT_CAST, coerce_to_common_type(), coerce_to_target_type(), coerce_type(), COERCION_EXPLICIT, element(), ereport, errcode(), errhint(), errmsg(), ERROR, exprLocation(), exprType(), fb(), format_type_be(), get_array_type(), get_element_type(), InvalidOid, IsA, lappend(), lfirst, makeNode, NIL, OidIsValid, parser_errposition(), select_common_type(), transformArrayExpr(), transformExprRecurse(), and type_is_array.

Referenced by transformArrayExpr(), transformExprRecurse(), and transformTypeCast().

◆ transformBooleanTest()

static Node * transformBooleanTest ( ParseState pstate,
BooleanTest b 
)
static

Definition at line 2541 of file parse_expr.c.

2542{
2543 const char *clausename;
2544
2545 switch (b->booltesttype)
2546 {
2547 case IS_TRUE:
2548 clausename = "IS TRUE";
2549 break;
2550 case IS_NOT_TRUE:
2551 clausename = "IS NOT TRUE";
2552 break;
2553 case IS_FALSE:
2554 clausename = "IS FALSE";
2555 break;
2556 case IS_NOT_FALSE:
2557 clausename = "IS NOT FALSE";
2558 break;
2559 case IS_UNKNOWN:
2560 clausename = "IS UNKNOWN";
2561 break;
2562 case IS_NOT_UNKNOWN:
2563 clausename = "IS NOT UNKNOWN";
2564 break;
2565 default:
2566 elog(ERROR, "unrecognized booltesttype: %d",
2567 (int) b->booltesttype);
2568 clausename = NULL; /* keep compiler quiet */
2569 }
2570
2571 b->arg = (Expr *) transformExprRecurse(pstate, (Node *) b->arg);
2572
2573 b->arg = (Expr *) coerce_to_boolean(pstate,
2574 (Node *) b->arg,
2575 clausename);
2576
2577 return (Node *) b;
2578}
int b
Definition isn.c:74
@ IS_NOT_TRUE
Definition primnodes.h:2001
@ IS_NOT_FALSE
Definition primnodes.h:2001
@ IS_NOT_UNKNOWN
Definition primnodes.h:2001
@ IS_TRUE
Definition primnodes.h:2001
@ IS_UNKNOWN
Definition primnodes.h:2001
@ IS_FALSE
Definition primnodes.h:2001

References b, coerce_to_boolean(), elog, ERROR, fb(), IS_FALSE, IS_NOT_FALSE, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_TRUE, IS_UNKNOWN, and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformBoolExpr()

static Node * transformBoolExpr ( ParseState pstate,
BoolExpr a 
)
static

Definition at line 1414 of file parse_expr.c.

1415{
1416 List *args = NIL;
1417 const char *opname;
1418 ListCell *lc;
1419
1420 switch (a->boolop)
1421 {
1422 case AND_EXPR:
1423 opname = "AND";
1424 break;
1425 case OR_EXPR:
1426 opname = "OR";
1427 break;
1428 case NOT_EXPR:
1429 opname = "NOT";
1430 break;
1431 default:
1432 elog(ERROR, "unrecognized boolop: %d", (int) a->boolop);
1433 opname = NULL; /* keep compiler quiet */
1434 break;
1435 }
1436
1437 foreach(lc, a->args)
1438 {
1439 Node *arg = (Node *) lfirst(lc);
1440
1441 arg = transformExprRecurse(pstate, arg);
1442 arg = coerce_to_boolean(pstate, arg, opname);
1443 args = lappend(args, arg);
1444 }
1445
1446 return (Node *) makeBoolExpr(a->boolop, args, a->location);
1447}

References a, AND_EXPR, arg, coerce_to_boolean(), elog, ERROR, fb(), lappend(), lfirst, makeBoolExpr(), NIL, NOT_EXPR, OR_EXPR, and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformCaseExpr()

static Node * transformCaseExpr ( ParseState pstate,
CaseExpr c 
)
static

Definition at line 1643 of file parse_expr.c.

1644{
1646 Node *last_srf = pstate->p_last_srf;
1647 Node *arg;
1649 List *newargs;
1651 ListCell *l;
1652 Node *defresult;
1653 Oid ptype;
1654
1655 /* transform the test expression, if any */
1656 arg = transformExprRecurse(pstate, (Node *) c->arg);
1657
1658 /* generate placeholder for test expression */
1659 if (arg)
1660 {
1661 /*
1662 * If test expression is an untyped literal, force it to text. We have
1663 * to do something now because we won't be able to do this coercion on
1664 * the placeholder. This is not as flexible as what was done in 7.4
1665 * and before, but it's good enough to handle the sort of silly coding
1666 * commonly seen.
1667 */
1668 if (exprType(arg) == UNKNOWNOID)
1669 arg = coerce_to_common_type(pstate, arg, TEXTOID, "CASE");
1670
1671 /*
1672 * Run collation assignment on the test expression so that we know
1673 * what collation to mark the placeholder with. In principle we could
1674 * leave it to parse_collate.c to do that later, but propagating the
1675 * result to the CaseTestExpr would be unnecessarily complicated.
1676 */
1677 assign_expr_collations(pstate, arg);
1678
1680 placeholder->typeId = exprType(arg);
1681 placeholder->typeMod = exprTypmod(arg);
1682 placeholder->collation = exprCollation(arg);
1683 }
1684 else
1685 placeholder = NULL;
1686
1687 newc->arg = (Expr *) arg;
1688
1689 /* transform the list of arguments */
1690 newargs = NIL;
1691 resultexprs = NIL;
1692 foreach(l, c->args)
1693 {
1694 CaseWhen *w = lfirst_node(CaseWhen, l);
1696 Node *warg;
1697
1698 warg = (Node *) w->expr;
1699 if (placeholder)
1700 {
1701 /* shorthand form was specified, so expand... */
1703 (Node *) placeholder,
1704 warg,
1705 w->location);
1706 }
1707 neww->expr = (Expr *) transformExprRecurse(pstate, warg);
1708
1709 neww->expr = (Expr *) coerce_to_boolean(pstate,
1710 (Node *) neww->expr,
1711 "CASE/WHEN");
1712
1713 warg = (Node *) w->result;
1714 neww->result = (Expr *) transformExprRecurse(pstate, warg);
1715 neww->location = w->location;
1716
1718 resultexprs = lappend(resultexprs, neww->result);
1719 }
1720
1721 newc->args = newargs;
1722
1723 /* transform the default clause */
1724 defresult = (Node *) c->defresult;
1725 if (defresult == NULL)
1726 {
1727 A_Const *n = makeNode(A_Const);
1728
1729 n->isnull = true;
1730 n->location = -1;
1731 defresult = (Node *) n;
1732 }
1733 newc->defresult = (Expr *) transformExprRecurse(pstate, defresult);
1734
1735 /*
1736 * Note: default result is considered the most significant type in
1737 * determining preferred type. This is how the code worked before, but it
1738 * seems a little bogus to me --- tgl
1739 */
1740 resultexprs = lcons(newc->defresult, resultexprs);
1741
1742 ptype = select_common_type(pstate, resultexprs, "CASE", NULL);
1743 Assert(OidIsValid(ptype));
1744 newc->casetype = ptype;
1745 /* casecollid will be set by parse_collate.c */
1746
1747 /* Convert default result clause, if necessary */
1748 newc->defresult = (Expr *)
1749 coerce_to_common_type(pstate,
1750 (Node *) newc->defresult,
1751 ptype,
1752 "CASE/ELSE");
1753
1754 /* Convert when-clause results, if necessary */
1755 foreach(l, newc->args)
1756 {
1757 CaseWhen *w = (CaseWhen *) lfirst(l);
1758
1759 w->result = (Expr *)
1760 coerce_to_common_type(pstate,
1761 (Node *) w->result,
1762 ptype,
1763 "CASE/WHEN");
1764 }
1765
1766 /* if any subexpression contained a SRF, complain */
1767 if (pstate->p_last_srf != last_srf)
1768 ereport(ERROR,
1770 /* translator: %s is name of a SQL construct, eg GROUP BY */
1771 errmsg("set-returning functions are not allowed in %s",
1772 "CASE"),
1773 errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
1774 parser_errposition(pstate,
1775 exprLocation(pstate->p_last_srf))));
1776
1777 newc->location = c->location;
1778
1779 return (Node *) newc;
1780}
List * lcons(void *datum, List *list)
Definition list.c:495
void assign_expr_collations(ParseState *pstate, Node *expr)
#define lfirst_node(type, lc)
Definition pg_list.h:176
char * c
ParseLoc location
Definition parsenodes.h:389
Expr * result
Definition primnodes.h:1359
Expr * expr
Definition primnodes.h:1358

References AEXPR_OP, arg, Assert, assign_expr_collations(), coerce_to_boolean(), coerce_to_common_type(), ereport, errcode(), errhint(), errmsg(), ERROR, CaseWhen::expr, exprCollation(), exprLocation(), exprType(), exprTypmod(), fb(), A_Const::isnull, lappend(), lcons(), lfirst, lfirst_node, A_Const::location, CaseWhen::location, makeNode, makeSimpleA_Expr(), NIL, OidIsValid, ParseState::p_last_srf, parser_errposition(), CaseWhen::result, select_common_type(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformCoalesceExpr()

static Node * transformCoalesceExpr ( ParseState pstate,
CoalesceExpr c 
)
static

Definition at line 2227 of file parse_expr.c.

2228{
2230 Node *last_srf = pstate->p_last_srf;
2231 List *newargs = NIL;
2233 ListCell *args;
2234
2235 foreach(args, c->args)
2236 {
2237 Node *e = (Node *) lfirst(args);
2238 Node *newe;
2239
2240 newe = transformExprRecurse(pstate, e);
2242 }
2243
2244 newc->coalescetype = select_common_type(pstate, newargs, "COALESCE", NULL);
2245 /* coalescecollid will be set by parse_collate.c */
2246
2247 /* Convert arguments if necessary */
2248 foreach(args, newargs)
2249 {
2250 Node *e = (Node *) lfirst(args);
2251 Node *newe;
2252
2253 newe = coerce_to_common_type(pstate, e,
2254 newc->coalescetype,
2255 "COALESCE");
2257 }
2258
2259 /* if any subexpression contained a SRF, complain */
2260 if (pstate->p_last_srf != last_srf)
2261 ereport(ERROR,
2263 /* translator: %s is name of a SQL construct, eg GROUP BY */
2264 errmsg("set-returning functions are not allowed in %s",
2265 "COALESCE"),
2266 errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
2267 parser_errposition(pstate,
2268 exprLocation(pstate->p_last_srf))));
2269
2270 newc->args = newcoercedargs;
2271 newc->location = c->location;
2272 return (Node *) newc;
2273}

References coerce_to_common_type(), ereport, errcode(), errhint(), errmsg(), ERROR, exprLocation(), fb(), lappend(), lfirst, makeNode, NIL, ParseState::p_last_srf, parser_errposition(), select_common_type(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformCollateClause()

static Node * transformCollateClause ( ParseState pstate,
CollateClause c 
)
static

Definition at line 2799 of file parse_expr.c.

2800{
2802 Oid argtype;
2803
2805 newc->arg = (Expr *) transformExprRecurse(pstate, c->arg);
2806
2807 argtype = exprType((Node *) newc->arg);
2808
2809 /*
2810 * The unknown type is not collatable, but coerce_type() takes care of it
2811 * separately, so we'll let it go here.
2812 */
2813 if (!type_is_collatable(argtype) && argtype != UNKNOWNOID)
2814 ereport(ERROR,
2816 errmsg("collations are not supported by type %s",
2817 format_type_be(argtype)),
2818 parser_errposition(pstate, c->location)));
2819
2820 newc->collOid = LookupCollation(pstate, c->collname, c->location);
2821 newc->location = c->location;
2822
2823 return (Node *) newc;
2824}
bool type_is_collatable(Oid typid)
Definition lsyscache.c:3231
Oid LookupCollation(ParseState *pstate, List *collnames, int location)
Definition parse_type.c:515

References ereport, errcode(), errmsg(), ERROR, exprType(), fb(), format_type_be(), LookupCollation(), makeNode, parser_errposition(), transformExprRecurse(), and type_is_collatable().

Referenced by transformExprRecurse().

◆ transformColumnRef()

static Node * transformColumnRef ( ParseState pstate,
ColumnRef cref 
)
static

Definition at line 510 of file parse_expr.c.

511{
512 Node *node = NULL;
513 char *nspname = NULL;
514 char *relname = NULL;
515 char *colname = NULL;
517 int levels_up;
518 enum
519 {
525 const char *err;
526
527 /*
528 * Check to see if the column reference is in an invalid place within the
529 * query. We allow column references in most places, except in default
530 * expressions and partition bound expressions.
531 */
532 err = NULL;
533 switch (pstate->p_expr_kind)
534 {
535 case EXPR_KIND_NONE:
536 Assert(false); /* can't happen */
537 break;
538 case EXPR_KIND_OTHER:
543 case EXPR_KIND_WHERE:
544 case EXPR_KIND_POLICY:
545 case EXPR_KIND_HAVING:
546 case EXPR_KIND_FILTER:
560 case EXPR_KIND_LIMIT:
561 case EXPR_KIND_OFFSET:
564 case EXPR_KIND_VALUES:
580 /* okay */
581 break;
582
584 err = _("cannot use column reference in DEFAULT expression");
585 break;
587 err = _("cannot use column reference in partition bound expression");
588 break;
589
590 /*
591 * There is intentionally no default: case here, so that the
592 * compiler will warn if we add a new ParseExprKind without
593 * extending this switch. If we do see an unrecognized value at
594 * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
595 * which is sane anyway.
596 */
597 }
598 if (err)
601 errmsg_internal("%s", err),
602 parser_errposition(pstate, cref->location)));
603
604 /*
605 * Give the PreParseColumnRefHook, if any, first shot. If it returns
606 * non-null then that's all, folks.
607 */
608 if (pstate->p_pre_columnref_hook != NULL)
609 {
610 node = pstate->p_pre_columnref_hook(pstate, cref);
611 if (node != NULL)
612 return node;
613 }
614
615 /*----------
616 * The allowed syntaxes are:
617 *
618 * A First try to resolve as unqualified column name;
619 * if no luck, try to resolve as unqualified table name (A.*).
620 * A.B A is an unqualified table name; B is either a
621 * column or function name (trying column name first).
622 * A.B.C schema A, table B, col or func name C.
623 * A.B.C.D catalog A, schema B, table C, col or func D.
624 * A.* A is an unqualified table name; means whole-row value.
625 * A.B.* whole-row value of table B in schema A.
626 * A.B.C.* whole-row value of table C in schema B in catalog A.
627 *
628 * We do not need to cope with bare "*"; that will only be accepted by
629 * the grammar at the top level of a SELECT list, and transformTargetList
630 * will take care of it before it ever gets here. Also, "A.*" etc will
631 * be expanded by transformTargetList if they appear at SELECT top level,
632 * so here we are only going to see them as function or operator inputs.
633 *
634 * Currently, if a catalog name is given then it must equal the current
635 * database name; we check it here and then discard it.
636 *----------
637 */
638 switch (list_length(cref->fields))
639 {
640 case 1:
641 {
642 Node *field1 = (Node *) linitial(cref->fields);
643
644 colname = strVal(field1);
645
646 /* Try to identify as an unqualified column */
647 node = colNameToVar(pstate, colname, false, cref->location);
648
649 if (node == NULL)
650 {
651 /*
652 * Not known as a column of any range-table entry.
653 *
654 * Try to find the name as a relation. Note that only
655 * relations already entered into the rangetable will be
656 * recognized.
657 *
658 * This is a hack for backwards compatibility with
659 * PostQUEL-inspired syntax. The preferred form now is
660 * "rel.*".
661 */
662 nsitem = refnameNamespaceItem(pstate, NULL, colname,
663 cref->location,
664 &levels_up);
665 if (nsitem)
666 node = transformWholeRowRef(pstate, nsitem, levels_up,
667 cref->location);
668 }
669 break;
670 }
671 case 2:
672 {
673 Node *field1 = (Node *) linitial(cref->fields);
674 Node *field2 = (Node *) lsecond(cref->fields);
675
677
678 /* Locate the referenced nsitem */
679 nsitem = refnameNamespaceItem(pstate, nspname, relname,
680 cref->location,
681 &levels_up);
682 if (nsitem == NULL)
683 {
685 break;
686 }
687
688 /* Whole-row reference? */
689 if (IsA(field2, A_Star))
690 {
691 node = transformWholeRowRef(pstate, nsitem, levels_up,
692 cref->location);
693 break;
694 }
695
696 colname = strVal(field2);
697
698 /* Try to identify as a column of the nsitem */
699 node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
700 cref->location);
701 if (node == NULL)
702 {
703 /* Try it as a function call on the whole row */
704 node = transformWholeRowRef(pstate, nsitem, levels_up,
705 cref->location);
706 node = ParseFuncOrColumn(pstate,
707 list_make1(makeString(colname)),
708 list_make1(node),
709 pstate->p_last_srf,
710 NULL,
711 false,
712 cref->location);
713 }
714 break;
715 }
716 case 3:
717 {
718 Node *field1 = (Node *) linitial(cref->fields);
719 Node *field2 = (Node *) lsecond(cref->fields);
720 Node *field3 = (Node *) lthird(cref->fields);
721
722 nspname = strVal(field1);
724
725 /* Locate the referenced nsitem */
726 nsitem = refnameNamespaceItem(pstate, nspname, relname,
727 cref->location,
728 &levels_up);
729 if (nsitem == NULL)
730 {
732 break;
733 }
734
735 /* Whole-row reference? */
736 if (IsA(field3, A_Star))
737 {
738 node = transformWholeRowRef(pstate, nsitem, levels_up,
739 cref->location);
740 break;
741 }
742
743 colname = strVal(field3);
744
745 /* Try to identify as a column of the nsitem */
746 node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
747 cref->location);
748 if (node == NULL)
749 {
750 /* Try it as a function call on the whole row */
751 node = transformWholeRowRef(pstate, nsitem, levels_up,
752 cref->location);
753 node = ParseFuncOrColumn(pstate,
754 list_make1(makeString(colname)),
755 list_make1(node),
756 pstate->p_last_srf,
757 NULL,
758 false,
759 cref->location);
760 }
761 break;
762 }
763 case 4:
764 {
765 Node *field1 = (Node *) linitial(cref->fields);
766 Node *field2 = (Node *) lsecond(cref->fields);
767 Node *field3 = (Node *) lthird(cref->fields);
768 Node *field4 = (Node *) lfourth(cref->fields);
769 char *catname;
770
771 catname = strVal(field1);
772 nspname = strVal(field2);
774
775 /*
776 * We check the catalog name and then ignore it.
777 */
778 if (strcmp(catname, get_database_name(MyDatabaseId)) != 0)
779 {
781 break;
782 }
783
784 /* Locate the referenced nsitem */
785 nsitem = refnameNamespaceItem(pstate, nspname, relname,
786 cref->location,
787 &levels_up);
788 if (nsitem == NULL)
789 {
791 break;
792 }
793
794 /* Whole-row reference? */
795 if (IsA(field4, A_Star))
796 {
797 node = transformWholeRowRef(pstate, nsitem, levels_up,
798 cref->location);
799 break;
800 }
801
802 colname = strVal(field4);
803
804 /* Try to identify as a column of the nsitem */
805 node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
806 cref->location);
807 if (node == NULL)
808 {
809 /* Try it as a function call on the whole row */
810 node = transformWholeRowRef(pstate, nsitem, levels_up,
811 cref->location);
812 node = ParseFuncOrColumn(pstate,
813 list_make1(makeString(colname)),
814 list_make1(node),
815 pstate->p_last_srf,
816 NULL,
817 false,
818 cref->location);
819 }
820 break;
821 }
822 default:
823 crerr = CRERR_TOO_MANY; /* too many dotted names */
824 break;
825 }
826
827 /*
828 * Now give the PostParseColumnRefHook, if any, a chance. We pass the
829 * translation-so-far so that it can throw an error if it wishes in the
830 * case that it has a conflicting interpretation of the ColumnRef. (If it
831 * just translates anyway, we'll throw an error, because we can't undo
832 * whatever effects the preceding steps may have had on the pstate.) If it
833 * returns NULL, use the standard translation, or throw a suitable error
834 * if there is none.
835 */
836 if (pstate->p_post_columnref_hook != NULL)
837 {
839
840 hookresult = pstate->p_post_columnref_hook(pstate, cref, node);
841 if (node == NULL)
842 node = hookresult;
843 else if (hookresult != NULL)
846 errmsg("column reference \"%s\" is ambiguous",
847 NameListToString(cref->fields)),
848 parser_errposition(pstate, cref->location)));
849 }
850
851 /*
852 * Throw error if no translation found.
853 */
854 if (node == NULL)
855 {
856 switch (crerr)
857 {
858 case CRERR_NO_COLUMN:
859 errorMissingColumn(pstate, relname, colname, cref->location);
860 break;
861 case CRERR_NO_RTE:
862 errorMissingRTE(pstate, makeRangeVar(nspname, relname,
863 cref->location));
864 break;
865 case CRERR_WRONG_DB:
868 errmsg("cross-database references are not implemented: %s",
869 NameListToString(cref->fields)),
870 parser_errposition(pstate, cref->location)));
871 break;
872 case CRERR_TOO_MANY:
875 errmsg("improper qualified name (too many dotted names): %s",
876 NameListToString(cref->fields)),
877 parser_errposition(pstate, cref->location)));
878 break;
879 }
880 }
881
882 return node;
883}
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
#define _(x)
Definition elog.c:91
void err(int eval, const char *fmt,...)
Definition err.c:43
Oid MyDatabaseId
Definition globals.c:94
char * get_database_name(Oid dbid)
Definition lsyscache.c:1242
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition makefuncs.c:473
char * NameListToString(const List *names)
Definition namespace.c:3664
static Node * transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location)
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition parse_func.c:92
void errorMissingColumn(ParseState *pstate, const char *relname, const char *colname, int location)
Node * colNameToVar(ParseState *pstate, const char *colname, bool localonly, int location)
void errorMissingRTE(ParseState *pstate, RangeVar *relation)
Node * scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, const char *colname, int location)
ParseNamespaceItem * refnameNamespaceItem(ParseState *pstate, const char *schemaname, const char *refname, int location, int *sublevels_up)
NameData relname
Definition pg_class.h:38
#define lthird(l)
Definition pg_list.h:188
#define lfourth(l)
Definition pg_list.h:193
ParseExprKind p_expr_kind
Definition parse_node.h:214
PreParseColumnRefHook p_pre_columnref_hook
Definition parse_node.h:238
PostParseColumnRefHook p_post_columnref_hook
Definition parse_node.h:239
String * makeString(char *str)
Definition value.c:63

References _, Assert, colNameToVar(), ereport, err(), errcode(), errmsg(), errmsg_internal(), ERROR, errorMissingColumn(), errorMissingRTE(), EXPR_KIND_ALTER_COL_TRANSFORM, EXPR_KIND_CALL_ARGUMENT, EXPR_KIND_CHECK_CONSTRAINT, EXPR_KIND_COLUMN_DEFAULT, EXPR_KIND_COPY_WHERE, EXPR_KIND_CYCLE_MARK, EXPR_KIND_DISTINCT_ON, EXPR_KIND_DOMAIN_CHECK, EXPR_KIND_EXECUTE_PARAMETER, EXPR_KIND_FILTER, EXPR_KIND_FROM_FUNCTION, EXPR_KIND_FROM_SUBSELECT, EXPR_KIND_FUNCTION_DEFAULT, EXPR_KIND_GENERATED_COLUMN, EXPR_KIND_GROUP_BY, EXPR_KIND_HAVING, EXPR_KIND_INDEX_EXPRESSION, EXPR_KIND_INDEX_PREDICATE, EXPR_KIND_INSERT_TARGET, EXPR_KIND_JOIN_ON, EXPR_KIND_JOIN_USING, EXPR_KIND_LIMIT, EXPR_KIND_MERGE_RETURNING, EXPR_KIND_MERGE_WHEN, EXPR_KIND_NONE, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_OTHER, EXPR_KIND_PARTITION_BOUND, EXPR_KIND_PARTITION_EXPRESSION, EXPR_KIND_POLICY, EXPR_KIND_RETURNING, EXPR_KIND_SELECT_TARGET, EXPR_KIND_STATS_EXPRESSION, EXPR_KIND_TRIGGER_WHEN, EXPR_KIND_UPDATE_SOURCE, EXPR_KIND_UPDATE_TARGET, EXPR_KIND_VALUES, EXPR_KIND_VALUES_SINGLE, EXPR_KIND_WHERE, EXPR_KIND_WINDOW_FRAME_GROUPS, EXPR_KIND_WINDOW_FRAME_RANGE, EXPR_KIND_WINDOW_FRAME_ROWS, EXPR_KIND_WINDOW_ORDER, EXPR_KIND_WINDOW_PARTITION, fb(), get_database_name(), IsA, lfourth, linitial, list_length(), list_make1, lsecond, lthird, makeRangeVar(), makeString(), MyDatabaseId, NameListToString(), ParseState::p_expr_kind, ParseState::p_last_srf, ParseState::p_post_columnref_hook, ParseState::p_pre_columnref_hook, ParseFuncOrColumn(), parser_errposition(), refnameNamespaceItem(), relname, scanNSItemForColumn(), strVal, and transformWholeRowRef().

Referenced by transformExprRecurse().

◆ transformCurrentOfExpr()

static Node * transformCurrentOfExpr ( ParseState pstate,
CurrentOfExpr cexpr 
)
static

Definition at line 2581 of file parse_expr.c.

2582{
2583 /* CURRENT OF can only appear at top level of UPDATE/DELETE */
2584 Assert(pstate->p_target_nsitem != NULL);
2585 cexpr->cvarno = pstate->p_target_nsitem->p_rtindex;
2586
2587 /*
2588 * Check to see if the cursor name matches a parameter of type REFCURSOR.
2589 * If so, replace the raw name reference with a parameter reference. (This
2590 * is a hack for the convenience of plpgsql.)
2591 */
2592 if (cexpr->cursor_name != NULL) /* in case already transformed */
2593 {
2595 Node *node = NULL;
2596
2597 /* Build an unqualified ColumnRef with the given name */
2598 cref->fields = list_make1(makeString(cexpr->cursor_name));
2599 cref->location = -1;
2600
2601 /* See if there is a translation available from a parser hook */
2602 if (pstate->p_pre_columnref_hook != NULL)
2603 node = pstate->p_pre_columnref_hook(pstate, cref);
2604 if (node == NULL && pstate->p_post_columnref_hook != NULL)
2605 node = pstate->p_post_columnref_hook(pstate, cref, NULL);
2606
2607 /*
2608 * XXX Should we throw an error if we get a translation that isn't a
2609 * refcursor Param? For now it seems best to silently ignore false
2610 * matches.
2611 */
2612 if (node != NULL && IsA(node, Param))
2613 {
2614 Param *p = (Param *) node;
2615
2616 if (p->paramkind == PARAM_EXTERN &&
2617 p->paramtype == REFCURSOROID)
2618 {
2619 /* Matches, so convert CURRENT OF to a param reference */
2620 cexpr->cursor_name = NULL;
2621 cexpr->cursor_param = p->paramid;
2622 }
2623 }
2624 }
2625
2626 return (Node *) cexpr;
2627}
@ PARAM_EXTERN
Definition primnodes.h:384
char * cursor_name
Definition primnodes.h:2123
int paramid
Definition primnodes.h:396
Oid paramtype
Definition primnodes.h:397
ParamKind paramkind
Definition primnodes.h:395
ParseNamespaceItem * p_target_nsitem
Definition parse_node.h:210

References Assert, CurrentOfExpr::cursor_name, CurrentOfExpr::cursor_param, CurrentOfExpr::cvarno, fb(), IsA, list_make1, makeNode, makeString(), ParseState::p_post_columnref_hook, ParseState::p_pre_columnref_hook, ParseNamespaceItem::p_rtindex, ParseState::p_target_nsitem, PARAM_EXTERN, Param::paramid, Param::paramkind, and Param::paramtype.

Referenced by transformExprRecurse().

◆ transformExpr()

Node * transformExpr ( ParseState pstate,
Node expr,
ParseExprKind  exprKind 
)

◆ transformExprRecurse()

static Node * transformExprRecurse ( ParseState pstate,
Node expr 
)
static

Definition at line 138 of file parse_expr.c.

139{
140 Node *result;
141
142 if (expr == NULL)
143 return NULL;
144
145 /* Guard against stack overflow due to overly complex expressions */
147
148 switch (nodeTag(expr))
149 {
150 case T_ColumnRef:
151 result = transformColumnRef(pstate, (ColumnRef *) expr);
152 break;
153
154 case T_ParamRef:
155 result = transformParamRef(pstate, (ParamRef *) expr);
156 break;
157
158 case T_A_Const:
159 result = (Node *) make_const(pstate, (A_Const *) expr);
160 break;
161
162 case T_A_Indirection:
163 result = transformIndirection(pstate, (A_Indirection *) expr);
164 break;
165
166 case T_A_ArrayExpr:
167 result = transformArrayExpr(pstate, (A_ArrayExpr *) expr,
169 break;
170
171 case T_TypeCast:
172 result = transformTypeCast(pstate, (TypeCast *) expr);
173 break;
174
175 case T_CollateClause:
176 result = transformCollateClause(pstate, (CollateClause *) expr);
177 break;
178
179 case T_A_Expr:
180 {
181 A_Expr *a = (A_Expr *) expr;
182
183 switch (a->kind)
184 {
185 case AEXPR_OP:
186 result = transformAExprOp(pstate, a);
187 break;
188 case AEXPR_OP_ANY:
189 result = transformAExprOpAny(pstate, a);
190 break;
191 case AEXPR_OP_ALL:
192 result = transformAExprOpAll(pstate, a);
193 break;
194 case AEXPR_DISTINCT:
196 result = transformAExprDistinct(pstate, a);
197 break;
198 case AEXPR_NULLIF:
199 result = transformAExprNullIf(pstate, a);
200 break;
201 case AEXPR_IN:
202 result = transformAExprIn(pstate, a);
203 break;
204 case AEXPR_LIKE:
205 case AEXPR_ILIKE:
206 case AEXPR_SIMILAR:
207 /* we can transform these just like AEXPR_OP */
208 result = transformAExprOp(pstate, a);
209 break;
210 case AEXPR_BETWEEN:
214 result = transformAExprBetween(pstate, a);
215 break;
216 default:
217 elog(ERROR, "unrecognized A_Expr kind: %d", a->kind);
218 result = NULL; /* keep compiler quiet */
219 break;
220 }
221 break;
222 }
223
224 case T_BoolExpr:
225 result = transformBoolExpr(pstate, (BoolExpr *) expr);
226 break;
227
228 case T_FuncCall:
229 result = transformFuncCall(pstate, (FuncCall *) expr);
230 break;
231
232 case T_MultiAssignRef:
233 result = transformMultiAssignRef(pstate, (MultiAssignRef *) expr);
234 break;
235
236 case T_GroupingFunc:
237 result = transformGroupingFunc(pstate, (GroupingFunc *) expr);
238 break;
239
241 result = transformMergeSupportFunc(pstate,
242 (MergeSupportFunc *) expr);
243 break;
244
245 case T_NamedArgExpr:
246 {
247 NamedArgExpr *na = (NamedArgExpr *) expr;
248
249 na->arg = (Expr *) transformExprRecurse(pstate, (Node *) na->arg);
250 result = expr;
251 break;
252 }
253
254 case T_SubLink:
255 result = transformSubLink(pstate, (SubLink *) expr);
256 break;
257
258 case T_CaseExpr:
259 result = transformCaseExpr(pstate, (CaseExpr *) expr);
260 break;
261
262 case T_RowExpr:
263 result = transformRowExpr(pstate, (RowExpr *) expr, false);
264 break;
265
266 case T_CoalesceExpr:
267 result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr);
268 break;
269
270 case T_MinMaxExpr:
271 result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
272 break;
273
275 result = transformSQLValueFunction(pstate,
276 (SQLValueFunction *) expr);
277 break;
278
279 case T_XmlExpr:
280 result = transformXmlExpr(pstate, (XmlExpr *) expr);
281 break;
282
283 case T_XmlSerialize:
284 result = transformXmlSerialize(pstate, (XmlSerialize *) expr);
285 break;
286
287 case T_NullTest:
288 {
289 NullTest *n = (NullTest *) expr;
290
291 n->arg = (Expr *) transformExprRecurse(pstate, (Node *) n->arg);
292 /* the argument can be any type, so don't coerce it */
293 n->argisrow = type_is_rowtype(exprType((Node *) n->arg));
294 result = expr;
295 break;
296 }
297
298 case T_BooleanTest:
299 result = transformBooleanTest(pstate, (BooleanTest *) expr);
300 break;
301
302 case T_CurrentOfExpr:
303 result = transformCurrentOfExpr(pstate, (CurrentOfExpr *) expr);
304 break;
305
306 /*
307 * In all places where DEFAULT is legal, the caller should have
308 * processed it rather than passing it to transformExpr().
309 */
310 case T_SetToDefault:
313 errmsg("DEFAULT is not allowed in this context"),
314 parser_errposition(pstate,
315 ((SetToDefault *) expr)->location)));
316 break;
317
318 /*
319 * CaseTestExpr doesn't require any processing; it is only
320 * injected into parse trees in a fully-formed state.
321 *
322 * Ordinarily we should not see a Var here, but it is convenient
323 * for transformJoinUsingClause() to create untransformed operator
324 * trees containing already-transformed Vars. The best
325 * alternative would be to deconstruct and reconstruct column
326 * references, which seems expensively pointless. So allow it.
327 */
328 case T_CaseTestExpr:
329 case T_Var:
330 {
331 result = expr;
332 break;
333 }
334
336 result = transformJsonObjectConstructor(pstate, (JsonObjectConstructor *) expr);
337 break;
338
340 result = transformJsonArrayConstructor(pstate, (JsonArrayConstructor *) expr);
341 break;
342
345 break;
346
347 case T_JsonObjectAgg:
348 result = transformJsonObjectAgg(pstate, (JsonObjectAgg *) expr);
349 break;
350
351 case T_JsonArrayAgg:
352 result = transformJsonArrayAgg(pstate, (JsonArrayAgg *) expr);
353 break;
354
356 result = transformJsonIsPredicate(pstate, (JsonIsPredicate *) expr);
357 break;
358
359 case T_JsonParseExpr:
360 result = transformJsonParseExpr(pstate, (JsonParseExpr *) expr);
361 break;
362
363 case T_JsonScalarExpr:
364 result = transformJsonScalarExpr(pstate, (JsonScalarExpr *) expr);
365 break;
366
368 result = transformJsonSerializeExpr(pstate, (JsonSerializeExpr *) expr);
369 break;
370
371 case T_JsonFuncExpr:
372 result = transformJsonFuncExpr(pstate, (JsonFuncExpr *) expr);
373 break;
374
375 default:
376 /* should not reach here */
377 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
378 result = NULL; /* keep compiler quiet */
379 break;
380 }
381
382 return result;
383}
bool type_is_rowtype(Oid typid)
Definition lsyscache.c:2805
#define nodeTag(nodeptr)
Definition nodes.h:139
Node * transformGroupingFunc(ParseState *pstate, GroupingFunc *p)
Definition parse_agg.c:268
static Node * transformMergeSupportFunc(ParseState *pstate, MergeSupportFunc *f)
static Node * transformJsonArrayConstructor(ParseState *pstate, JsonArrayConstructor *ctor)
static Node * transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
static Node * transformAExprOpAll(ParseState *pstate, A_Expr *a)
static Node * transformJsonParseExpr(ParseState *pstate, JsonParseExpr *jsexpr)
static Node * transformAExprIn(ParseState *pstate, A_Expr *a)
static Node * transformAExprOpAny(ParseState *pstate, A_Expr *a)
static Node * transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
static Node * transformAExprNullIf(ParseState *pstate, A_Expr *a)
static Node * transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *jsexpr)
static Node * transformJsonArrayQueryConstructor(ParseState *pstate, JsonArrayQueryConstructor *ctor)
static Node * transformSQLValueFunction(ParseState *pstate, SQLValueFunction *svf)
static Node * transformColumnRef(ParseState *pstate, ColumnRef *cref)
Definition parse_expr.c:510
static Node * transformCollateClause(ParseState *pstate, CollateClause *c)
static Node * transformBoolExpr(ParseState *pstate, BoolExpr *a)
static Node * transformFuncCall(ParseState *pstate, FuncCall *fn)
static Node * transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
static Node * transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
static Node * transformSubLink(ParseState *pstate, SubLink *sublink)
static Node * transformJsonObjectConstructor(ParseState *pstate, JsonObjectConstructor *ctor)
static Node * transformAExprOp(ParseState *pstate, A_Expr *a)
Definition parse_expr.c:923
static Node * transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg)
static Node * transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
static Node * transformBooleanTest(ParseState *pstate, BooleanTest *b)
static Node * transformTypeCast(ParseState *pstate, TypeCast *tc)
static Node * transformParamRef(ParseState *pstate, ParamRef *pref)
Definition parse_expr.c:886
static Node * transformCaseExpr(ParseState *pstate, CaseExpr *c)
static Node * transformIndirection(ParseState *pstate, A_Indirection *ind)
Definition parse_expr.c:438
static Node * transformJsonSerializeExpr(ParseState *pstate, JsonSerializeExpr *expr)
static Node * transformRowExpr(ParseState *pstate, RowExpr *r, bool allowDefault)
static Node * transformXmlExpr(ParseState *pstate, XmlExpr *x)
static Node * transformAExprBetween(ParseState *pstate, A_Expr *a)
static Node * transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
static Node * transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *pred)
static Node * transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg)
static Node * transformAExprDistinct(ParseState *pstate, A_Expr *a)
Const * make_const(ParseState *pstate, A_Const *aconst)
Definition parse_node.c:347
@ AEXPR_NULLIF
Definition parsenodes.h:335
@ AEXPR_ILIKE
Definition parsenodes.h:338
@ AEXPR_IN
Definition parsenodes.h:336
@ AEXPR_DISTINCT
Definition parsenodes.h:333
@ AEXPR_SIMILAR
Definition parsenodes.h:339
@ AEXPR_LIKE
Definition parsenodes.h:337
@ AEXPR_OP_ANY
Definition parsenodes.h:331
@ AEXPR_OP_ALL
Definition parsenodes.h:332
void check_stack_depth(void)
Definition stack_depth.c:95

References a, AEXPR_BETWEEN, AEXPR_BETWEEN_SYM, AEXPR_DISTINCT, AEXPR_ILIKE, AEXPR_IN, AEXPR_LIKE, AEXPR_NOT_BETWEEN, AEXPR_NOT_BETWEEN_SYM, AEXPR_NOT_DISTINCT, AEXPR_NULLIF, AEXPR_OP, AEXPR_OP_ALL, AEXPR_OP_ANY, AEXPR_SIMILAR, NullTest::arg, check_stack_depth(), elog, ereport, errcode(), errmsg(), ERROR, exprType(), fb(), InvalidOid, make_const(), nodeTag, parser_errposition(), transformAExprBetween(), transformAExprDistinct(), transformAExprIn(), transformAExprNullIf(), transformAExprOp(), transformAExprOpAll(), transformAExprOpAny(), transformArrayExpr(), transformBooleanTest(), transformBoolExpr(), transformCaseExpr(), transformCoalesceExpr(), transformCollateClause(), transformColumnRef(), transformCurrentOfExpr(), transformExprRecurse(), transformFuncCall(), transformGroupingFunc(), transformIndirection(), transformJsonArrayAgg(), transformJsonArrayConstructor(), transformJsonArrayQueryConstructor(), transformJsonFuncExpr(), transformJsonIsPredicate(), transformJsonObjectAgg(), transformJsonObjectConstructor(), transformJsonParseExpr(), transformJsonScalarExpr(), transformJsonSerializeExpr(), transformMergeSupportFunc(), transformMinMaxExpr(), transformMultiAssignRef(), transformParamRef(), transformRowExpr(), transformSQLValueFunction(), transformSubLink(), transformTypeCast(), transformXmlExpr(), transformXmlSerialize(), and type_is_rowtype().

Referenced by make_nulltest_from_distinct(), transformAExprBetween(), transformAExprDistinct(), transformAExprIn(), transformAExprNullIf(), transformAExprOp(), transformAExprOpAll(), transformAExprOpAny(), transformArrayExpr(), transformBooleanTest(), transformBoolExpr(), transformCaseExpr(), transformCoalesceExpr(), transformCollateClause(), transformExpr(), transformExprRecurse(), transformFuncCall(), transformIndirection(), transformJsonArrayQueryConstructor(), transformJsonBehavior(), transformJsonFuncExpr(), transformJsonObjectAgg(), transformJsonObjectConstructor(), transformJsonParseArg(), transformJsonScalarExpr(), transformJsonValueExpr(), transformMinMaxExpr(), transformMultiAssignRef(), transformSubLink(), transformTypeCast(), transformXmlExpr(), and transformXmlSerialize().

◆ transformFuncCall()

static Node * transformFuncCall ( ParseState pstate,
FuncCall fn 
)
static

Definition at line 1450 of file parse_expr.c.

1451{
1452 Node *last_srf = pstate->p_last_srf;
1453 List *targs;
1454 ListCell *args;
1455
1456 /* Transform the list of arguments ... */
1457 targs = NIL;
1458 foreach(args, fn->args)
1459 {
1461 (Node *) lfirst(args)));
1462 }
1463
1464 /*
1465 * When WITHIN GROUP is used, we treat its ORDER BY expressions as
1466 * additional arguments to the function, for purposes of function lookup
1467 * and argument type coercion. So, transform each such expression and add
1468 * them to the targs list. We don't explicitly mark where each argument
1469 * came from, but ParseFuncOrColumn can tell what's what by reference to
1470 * list_length(fn->agg_order).
1471 */
1472 if (fn->agg_within_group)
1473 {
1474 Assert(fn->agg_order != NIL);
1475 foreach(args, fn->agg_order)
1476 {
1477 SortBy *arg = (SortBy *) lfirst(args);
1478
1479 targs = lappend(targs, transformExpr(pstate, arg->node,
1481 }
1482 }
1483
1484 /* ... and hand off to ParseFuncOrColumn */
1485 return ParseFuncOrColumn(pstate,
1486 fn->funcname,
1487 targs,
1488 last_srf,
1489 fn,
1490 false,
1491 fn->location);
1492}
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:120
static void * fn(void *arg)

References arg, Assert, EXPR_KIND_ORDER_BY, fb(), fn(), lappend(), lfirst, NIL, ParseState::p_last_srf, ParseFuncOrColumn(), transformExpr(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformIndirection()

static Node * transformIndirection ( ParseState pstate,
A_Indirection ind 
)
static

Definition at line 438 of file parse_expr.c.

439{
440 Node *last_srf = pstate->p_last_srf;
441 Node *result = transformExprRecurse(pstate, ind->arg);
443 int location = exprLocation(result);
444 ListCell *i;
445
446 /*
447 * We have to split any field-selection operations apart from
448 * subscripting. Adjacent A_Indices nodes have to be treated as a single
449 * multidimensional subscript operation.
450 */
451 foreach(i, ind->indirection)
452 {
453 Node *n = lfirst(i);
454
455 if (IsA(n, A_Indices))
457 else if (IsA(n, A_Star))
458 {
461 errmsg("row expansion via \"*\" is not supported here"),
462 parser_errposition(pstate, location)));
463 }
464 else
465 {
467
468 Assert(IsA(n, String));
469
470 /* process subscripts before this field selection */
471 if (subscripts)
472 result = (Node *) transformContainerSubscripts(pstate,
473 result,
474 exprType(result),
475 exprTypmod(result),
477 false);
478 subscripts = NIL;
479
481 list_make1(n),
482 list_make1(result),
483 last_srf,
484 NULL,
485 false,
486 location);
487 if (newresult == NULL)
488 unknown_attribute(pstate, result, strVal(n), location);
489 result = newresult;
490 }
491 }
492 /* process trailing subscripts, if any */
493 if (subscripts)
494 result = (Node *) transformContainerSubscripts(pstate,
495 result,
496 exprType(result),
497 exprTypmod(result),
499 false);
500
501 return result;
502}
static void unknown_attribute(ParseState *pstate, Node *relref, const char *attname, int location)
Definition parse_expr.c:392
SubscriptingRef * transformContainerSubscripts(ParseState *pstate, Node *containerBase, Oid containerType, int32 containerTypMod, List *indirection, bool isAssignment)
Definition parse_node.c:243
Definition value.h:64

References Assert, ereport, errcode(), errmsg(), ERROR, exprLocation(), exprType(), exprTypmod(), fb(), i, IsA, lappend(), lfirst, list_make1, NIL, ParseState::p_last_srf, ParseFuncOrColumn(), parser_errposition(), strVal, transformContainerSubscripts(), transformExprRecurse(), and unknown_attribute().

Referenced by transformExprRecurse().

◆ transformJsonAggConstructor()

static Node * transformJsonAggConstructor ( ParseState pstate,
JsonAggConstructor agg_ctor,
JsonReturning returning,
List args,
Oid  aggfnoid,
Oid  aggtype,
JsonConstructorType  ctor_type,
bool  unique,
bool  absent_on_null 
)
static

Definition at line 3845 of file parse_expr.c.

3850{
3851 Node *node;
3852 Expr *aggfilter;
3853
3854 aggfilter = agg_ctor->agg_filter ? (Expr *)
3855 transformWhereClause(pstate, agg_ctor->agg_filter,
3856 EXPR_KIND_FILTER, "FILTER") : NULL;
3857
3858 if (agg_ctor->over)
3859 {
3860 /* window function */
3861 WindowFunc *wfunc = makeNode(WindowFunc);
3862
3863 wfunc->winfnoid = aggfnoid;
3864 wfunc->wintype = aggtype;
3865 /* wincollid and inputcollid will be set by parse_collate.c */
3866 wfunc->args = args;
3867 wfunc->aggfilter = aggfilter;
3868 wfunc->runCondition = NIL;
3869 /* winref will be set by transformWindowFuncCall */
3870 wfunc->winstar = false;
3871 wfunc->winagg = true;
3872 wfunc->location = agg_ctor->location;
3873
3874 /*
3875 * ordered aggs not allowed in windows yet
3876 */
3877 if (agg_ctor->agg_order != NIL)
3878 ereport(ERROR,
3880 errmsg("aggregate ORDER BY is not implemented for window functions"),
3881 parser_errposition(pstate, agg_ctor->location));
3882
3883 /* parse_agg.c does additional window-func-specific processing */
3884 transformWindowFuncCall(pstate, wfunc, agg_ctor->over);
3885
3886 node = (Node *) wfunc;
3887 }
3888 else
3889 {
3890 Aggref *aggref = makeNode(Aggref);
3891
3892 aggref->aggfnoid = aggfnoid;
3893 aggref->aggtype = aggtype;
3894
3895 /* aggcollid and inputcollid will be set by parse_collate.c */
3896 /* aggtranstype will be set by planner */
3897 /* aggargtypes will be set by transformAggregateCall */
3898 /* aggdirectargs and args will be set by transformAggregateCall */
3899 /* aggorder and aggdistinct will be set by transformAggregateCall */
3900 aggref->aggfilter = aggfilter;
3901 aggref->aggstar = false;
3902 aggref->aggvariadic = false;
3903 aggref->aggkind = AGGKIND_NORMAL;
3904 aggref->aggpresorted = false;
3905 /* agglevelsup will be set by transformAggregateCall */
3906 aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */
3907 aggref->aggno = -1; /* planner will set aggno and aggtransno */
3908 aggref->aggtransno = -1;
3909 aggref->location = agg_ctor->location;
3910
3911 transformAggregateCall(pstate, aggref, args, agg_ctor->agg_order, false);
3912
3913 node = (Node *) aggref;
3914 }
3915
3916 return makeJsonConstructorExpr(pstate, ctor_type, NIL, (Expr *) node,
3917 returning, unique, absent_on_null,
3918 agg_ctor->location);
3919}
@ AGGSPLIT_SIMPLE
Definition nodes.h:387
void transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc, WindowDef *windef)
Definition parse_agg.c:878
void transformAggregateCall(ParseState *pstate, Aggref *agg, List *args, List *aggorder, bool agg_distinct)
Definition parse_agg.c:112
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
static Node * makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type, List *args, Expr *fexpr, JsonReturning *returning, bool unique, bool absent_on_null, int location)
Oid aggfnoid
Definition primnodes.h:463
Expr * aggfilter
Definition primnodes.h:496
ParseLoc location
Definition primnodes.h:526
List * args
Definition primnodes.h:605
Expr * aggfilter
Definition primnodes.h:607
ParseLoc location
Definition primnodes.h:619

References Aggref::aggfilter, WindowFunc::aggfilter, Aggref::aggfnoid, AGGSPLIT_SIMPLE, WindowFunc::args, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_FILTER, fb(), Aggref::location, WindowFunc::location, makeJsonConstructorExpr(), makeNode, NIL, parser_errposition(), transformAggregateCall(), transformWhereClause(), transformWindowFuncCall(), and WindowFunc::winfnoid.

Referenced by transformJsonArrayAgg(), and transformJsonObjectAgg().

◆ transformJsonArrayAgg()

static Node * transformJsonArrayAgg ( ParseState pstate,
JsonArrayAgg agg 
)
static

Definition at line 3995 of file parse_expr.c.

3996{
3997 JsonReturning *returning;
3998 Node *arg;
3999 Oid aggfnoid;
4000 Oid aggtype;
4001
4002 arg = transformJsonValueExpr(pstate, "JSON_ARRAYAGG()", agg->arg,
4004
4005 returning = transformJsonConstructorOutput(pstate, agg->constructor->output,
4006 list_make1(arg));
4007
4008 if (returning->format->format_type == JS_FORMAT_JSONB)
4009 {
4010 aggfnoid = agg->absent_on_null ? F_JSONB_AGG_STRICT : F_JSONB_AGG;
4011 aggtype = JSONBOID;
4012 }
4013 else
4014 {
4015 aggfnoid = agg->absent_on_null ? F_JSON_AGG_STRICT : F_JSON_AGG;
4016 aggtype = JSONOID;
4017 }
4018
4019 return transformJsonAggConstructor(pstate, agg->constructor, returning,
4020 list_make1(arg), aggfnoid, aggtype,
4022 false, agg->absent_on_null);
4023}
static JsonReturning * transformJsonConstructorOutput(ParseState *pstate, JsonOutput *output, List *args)
static Node * transformJsonAggConstructor(ParseState *pstate, JsonAggConstructor *agg_ctor, JsonReturning *returning, List *args, Oid aggfnoid, Oid aggtype, JsonConstructorType ctor_type, bool unique, bool absent_on_null)
static Node * transformJsonValueExpr(ParseState *pstate, const char *constructName, JsonValueExpr *ve, JsonFormatType default_format, Oid targettype, bool isarg)
@ JSCTOR_JSON_ARRAYAGG
Definition primnodes.h:1718

References arg, fb(), JsonReturning::format, JsonFormat::format_type, InvalidOid, JS_FORMAT_DEFAULT, JS_FORMAT_JSONB, JSCTOR_JSON_ARRAYAGG, list_make1, transformJsonAggConstructor(), transformJsonConstructorOutput(), and transformJsonValueExpr().

Referenced by transformExprRecurse().

◆ transformJsonArrayConstructor()

static Node * transformJsonArrayConstructor ( ParseState pstate,
JsonArrayConstructor ctor 
)
static

Definition at line 4033 of file parse_expr.c.

4034{
4035 JsonReturning *returning;
4036 List *args = NIL;
4037
4038 /* transform element expressions, if any */
4039 if (ctor->exprs)
4040 {
4041 ListCell *lc;
4042
4043 /* transform and append element arguments */
4044 foreach(lc, ctor->exprs)
4045 {
4047 Node *val = transformJsonValueExpr(pstate, "JSON_ARRAY()",
4049 InvalidOid, false);
4050
4051 args = lappend(args, val);
4052 }
4053 }
4054
4055 returning = transformJsonConstructorOutput(pstate, ctor->output, args);
4056
4057 return makeJsonConstructorExpr(pstate, JSCTOR_JSON_ARRAY, args, NULL,
4058 returning, false, ctor->absent_on_null,
4059 ctor->location);
4060}
@ JSCTOR_JSON_ARRAY
Definition primnodes.h:1716

References castNode, fb(), InvalidOid, JS_FORMAT_DEFAULT, JSCTOR_JSON_ARRAY, lappend(), lfirst, makeJsonConstructorExpr(), NIL, transformJsonConstructorOutput(), transformJsonValueExpr(), and val.

Referenced by transformExprRecurse().

◆ transformJsonArrayQueryConstructor()

static Node * transformJsonArrayQueryConstructor ( ParseState pstate,
JsonArrayQueryConstructor ctor 
)
static

Definition at line 3774 of file parse_expr.c.

3776{
3780 Alias *alias = makeNode(Alias);
3781 ResTarget *target = makeNode(ResTarget);
3784 Query *query;
3786
3787 /* Transform query only for counting target list entries. */
3788 qpstate = make_parsestate(pstate);
3789
3790 query = transformStmt(qpstate, copyObject(ctor->query));
3791
3792 if (count_nonjunk_tlist_entries(query->targetList) != 1)
3793 ereport(ERROR,
3795 errmsg("subquery must return only one column"),
3796 parser_errposition(pstate, ctor->location));
3797
3799
3800 colref->fields = list_make2(makeString(pstrdup("q")),
3801 makeString(pstrdup("a")));
3802 colref->location = ctor->location;
3803
3804 /*
3805 * No formatting necessary, so set formatted_expr to be the same as
3806 * raw_expr.
3807 */
3808 agg->arg = makeJsonValueExpr((Expr *) colref, (Expr *) colref,
3809 ctor->format);
3810 agg->absent_on_null = ctor->absent_on_null;
3811 agg->constructor = makeNode(JsonAggConstructor);
3812 agg->constructor->agg_order = NIL;
3813 agg->constructor->output = ctor->output;
3814 agg->constructor->location = ctor->location;
3815
3816 target->name = NULL;
3817 target->indirection = NIL;
3818 target->val = (Node *) agg;
3819 target->location = ctor->location;
3820
3821 alias->aliasname = pstrdup("q");
3822 alias->colnames = list_make1(makeString(pstrdup("a")));
3823
3824 range->lateral = false;
3825 range->subquery = ctor->query;
3826 range->alias = alias;
3827
3828 select->targetList = list_make1(target);
3829 select->fromClause = list_make1(range);
3830
3831 sublink->subLinkType = EXPR_SUBLINK;
3832 sublink->subLinkId = 0;
3833 sublink->testexpr = NULL;
3834 sublink->operName = NIL;
3835 sublink->subselect = (Node *) select;
3836 sublink->location = ctor->location;
3837
3838 return transformExprRecurse(pstate, (Node *) sublink);
3839}
JsonValueExpr * makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, JsonFormat *format)
Definition makefuncs.c:938
char * pstrdup(const char *in)
Definition mcxt.c:1781
void free_parsestate(ParseState *pstate)
Definition parse_node.c:72
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition analyze.c:324
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
char * aliasname
Definition primnodes.h:51
List * colnames
Definition primnodes.h:52
List * targetList
Definition parsenodes.h:198
Node * val
Definition parsenodes.h:547
ParseLoc location
Definition parsenodes.h:548
List * indirection
Definition parsenodes.h:546
char * name
Definition parsenodes.h:545
int count_nonjunk_tlist_entries(List *tlist)
Definition tlist.c:195
#define select(n, r, w, e, timeout)
Definition win32_port.h:500

References Alias::aliasname, Alias::colnames, copyObject, count_nonjunk_tlist_entries(), ereport, errcode(), errmsg(), ERROR, EXPR_SUBLINK, fb(), free_parsestate(), ResTarget::indirection, list_make1, list_make2, ResTarget::location, make_parsestate(), makeJsonValueExpr(), makeNode, makeString(), ResTarget::name, NIL, parser_errposition(), pstrdup(), range(), select, Query::targetList, transformExprRecurse(), transformStmt(), and ResTarget::val.

Referenced by transformExprRecurse().

◆ transformJsonBehavior()

static JsonBehavior * transformJsonBehavior ( ParseState pstate,
JsonExpr jsexpr,
JsonBehavior behavior,
JsonBehaviorType  default_behavior,
JsonReturning returning 
)
static

Definition at line 4743 of file parse_expr.c.

4747{
4749 Node *expr = NULL;
4750 bool coerce_at_runtime = false;
4751 int location = -1;
4752
4753 if (behavior)
4754 {
4755 btype = behavior->btype;
4756 location = behavior->location;
4757 if (btype == JSON_BEHAVIOR_DEFAULT)
4758 {
4759 Oid targetcoll = jsexpr->collation;
4760 Oid exprcoll;
4761
4762 expr = transformExprRecurse(pstate, behavior->expr);
4763
4765 ereport(ERROR,
4767 errmsg("can only specify a constant, non-aggregate function, or operator expression for DEFAULT"),
4768 parser_errposition(pstate, exprLocation(expr))));
4769 if (contain_var_clause(expr))
4770 ereport(ERROR,
4772 errmsg("DEFAULT expression must not contain column references"),
4773 parser_errposition(pstate, exprLocation(expr))));
4774 if (expression_returns_set(expr))
4775 ereport(ERROR,
4777 errmsg("DEFAULT expression must not return a set"),
4778 parser_errposition(pstate, exprLocation(expr))));
4779
4780 /*
4781 * Reject a DEFAULT expression whose collation differs from the
4782 * enclosing JSON expression's result collation
4783 * (jsexpr->collation), as chosen by the RETURNING clause.
4784 */
4785 exprcoll = exprCollation(expr);
4786 if (!OidIsValid(exprcoll))
4790 ereport(ERROR,
4792 errmsg("collation of DEFAULT expression conflicts with RETURNING clause"),
4793 errdetail("\"%s\" versus \"%s\"",
4796 parser_errposition(pstate, exprLocation(expr)));
4797 }
4798 }
4799
4800 if (expr == NULL && btype != JSON_BEHAVIOR_ERROR)
4801 expr = GetJsonBehaviorConst(btype, location);
4802
4803 /*
4804 * Try to coerce the expression if needed.
4805 *
4806 * Use runtime coercion using json_populate_type() if the expression is
4807 * NULL, jsonb-valued, or boolean-valued (unless the target type is
4808 * integer or domain over integer, in which case use the
4809 * boolean-to-integer cast function).
4810 *
4811 * For other non-NULL expressions, try to find a cast and error out if one
4812 * is not found.
4813 */
4814 if (expr && exprType(expr) != returning->typid)
4815 {
4816 bool isnull = (IsA(expr, Const) && ((Const *) expr)->constisnull);
4817
4818 if (isnull ||
4819 exprType(expr) == JSONBOID ||
4820 (exprType(expr) == BOOLOID &&
4821 getBaseType(returning->typid) != INT4OID))
4822 {
4823 coerce_at_runtime = true;
4824
4825 /*
4826 * json_populate_type() expects to be passed a jsonb value, so gin
4827 * up a Const containing the appropriate boolean value represented
4828 * as jsonb, discarding the original Const containing a plain
4829 * boolean.
4830 */
4831 if (exprType(expr) == BOOLOID)
4832 {
4833 char *val = btype == JSON_BEHAVIOR_TRUE ? "true" : "false";
4834
4835 expr = (Node *) makeConst(JSONBOID, -1, InvalidOid, -1,
4838 false, false);
4839 }
4840 }
4841 else
4842 {
4844 char typcategory = TypeCategory(returning->typid);
4845
4846 /*
4847 * Use an assignment cast if coercing to a string type so that
4848 * build_coercion_expression() assumes implicit coercion when
4849 * coercing the typmod, so that inputs exceeding length cause an
4850 * error instead of silent truncation.
4851 */
4852 coerced_expr =
4853 coerce_to_target_type(pstate, expr, exprType(expr),
4854 returning->typid, returning->typmod,
4860 exprLocation((Node *) behavior));
4861
4862 if (coerced_expr == NULL)
4863 {
4864 /*
4865 * Provide a HINT if the expression comes from a DEFAULT
4866 * clause.
4867 */
4868 if (btype == JSON_BEHAVIOR_DEFAULT)
4869 ereport(ERROR,
4871 errmsg("cannot cast behavior expression of type %s to %s",
4872 format_type_be(exprType(expr)),
4873 format_type_be(returning->typid)),
4874 errhint("You will need to explicitly cast the expression to type %s.",
4875 format_type_be(returning->typid)),
4876 parser_errposition(pstate, exprLocation(expr)));
4877 else
4878 ereport(ERROR,
4880 errmsg("cannot cast behavior expression of type %s to %s",
4881 format_type_be(exprType(expr)),
4882 format_type_be(returning->typid)),
4883 parser_errposition(pstate, exprLocation(expr)));
4884 }
4885
4886 expr = coerced_expr;
4887 }
4888 }
4889
4890 if (behavior)
4891 behavior->expr = expr;
4892 else
4893 behavior = makeJsonBehavior(btype, expr, location);
4894
4895 behavior->coerce = coerce_at_runtime;
4896
4897 return behavior;
4898}
Oid get_typcollation(Oid typid)
Definition lsyscache.c:3206
char * get_collation_name(Oid colloid)
Definition lsyscache.c:1111
Oid getBaseType(Oid typid)
Definition lsyscache.c:2671
JsonBehavior * makeJsonBehavior(JsonBehaviorType btype, Node *expr, int location)
Definition makefuncs.c:955
TYPCATEGORY TypeCategory(Oid type)
static bool ValidJsonBehaviorDefaultExpr(Node *expr, void *context)
static Node * GetJsonBehaviorConst(JsonBehaviorType btype, int location)
JsonBehaviorType
Definition primnodes.h:1789
ParseLoc location
Definition primnodes.h:1818
JsonBehaviorType btype
Definition primnodes.h:1815
Oid collation
Definition primnodes.h:1881
bool contain_var_clause(Node *node)
Definition var.c:406

References JsonBehavior::btype, JsonBehavior::coerce, COERCE_EXPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, COERCION_EXPLICIT, JsonExpr::collation, contain_var_clause(), CStringGetDatum(), DirectFunctionCall1, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, JsonBehavior::expr, exprCollation(), expression_returns_set(), exprLocation(), exprType(), fb(), format_type_be(), get_collation_name(), get_typcollation(), getBaseType(), GetJsonBehaviorConst(), InvalidOid, IsA, JSON_BEHAVIOR_DEFAULT, JSON_BEHAVIOR_ERROR, JSON_BEHAVIOR_TRUE, jsonb_in(), JsonBehavior::location, makeConst(), makeJsonBehavior(), OidIsValid, parser_errposition(), transformExprRecurse(), TypeCategory(), JsonReturning::typid, JsonReturning::typmod, val, and ValidJsonBehaviorDefaultExpr().

Referenced by transformJsonFuncExpr().

◆ transformJsonConstructorOutput()

static JsonReturning * transformJsonConstructorOutput ( ParseState pstate,
JsonOutput output,
List args 
)
static

Definition at line 3570 of file parse_expr.c.

3572{
3573 JsonReturning *returning = transformJsonOutput(pstate, output, true);
3574
3575 if (!OidIsValid(returning->typid))
3576 {
3577 ListCell *lc;
3578 bool have_jsonb = false;
3579
3580 foreach(lc, args)
3581 {
3582 Node *expr = lfirst(lc);
3583 Oid typid = exprType(expr);
3584
3585 have_jsonb |= typid == JSONBOID;
3586
3587 if (have_jsonb)
3588 break;
3589 }
3590
3591 if (have_jsonb)
3592 {
3593 returning->typid = JSONBOID;
3594 returning->format->format_type = JS_FORMAT_JSONB;
3595 }
3596 else
3597 {
3598 /* XXX TEXT is default by the standard, but we return JSON */
3599 returning->typid = JSONOID;
3600 returning->format->format_type = JS_FORMAT_JSON;
3601 }
3602
3603 returning->typmod = -1;
3604 }
3605
3606 return returning;
3607}
FILE * output
static JsonReturning * transformJsonOutput(ParseState *pstate, const JsonOutput *output, bool allow_format)

References exprType(), fb(), JsonReturning::format, JsonFormat::format_type, JS_FORMAT_JSON, JS_FORMAT_JSONB, lfirst, OidIsValid, output, transformJsonOutput(), JsonReturning::typid, and JsonReturning::typmod.

Referenced by transformJsonArrayAgg(), transformJsonArrayConstructor(), transformJsonObjectAgg(), and transformJsonObjectConstructor().

◆ transformJsonFuncExpr()

static Node * transformJsonFuncExpr ( ParseState pstate,
JsonFuncExpr func 
)
static

Definition at line 4294 of file parse_expr.c.

4295{
4296 JsonExpr *jsexpr;
4297 Node *path_spec;
4299 int pathspec_loc;
4301 const char *func_name = NULL;
4303
4304 switch (func->op)
4305 {
4306 case JSON_EXISTS_OP:
4307 func_name = "JSON_EXISTS";
4309 break;
4310 case JSON_QUERY_OP:
4311 func_name = "JSON_QUERY";
4313 break;
4314 case JSON_VALUE_OP:
4315 func_name = "JSON_VALUE";
4317 break;
4318 case JSON_TABLE_OP:
4319 func_name = "JSON_TABLE";
4321 break;
4322 default:
4323 elog(ERROR, "invalid JsonFuncExpr op %d", (int) func->op);
4324 default_format = JS_FORMAT_DEFAULT; /* keep compiler quiet */
4325 break;
4326 }
4327
4328 /*
4329 * Even though the syntax allows it, FORMAT JSON specification in
4330 * RETURNING is meaningless except for JSON_QUERY(). Flag if not
4331 * JSON_QUERY().
4332 */
4333 if (func->output && func->op != JSON_QUERY_OP)
4334 {
4336
4337 if (format->format_type != JS_FORMAT_DEFAULT ||
4338 format->encoding != JS_ENC_DEFAULT)
4339 ereport(ERROR,
4341 errmsg("cannot specify FORMAT JSON in RETURNING clause of %s()",
4342 func_name),
4343 parser_errposition(pstate, format->location));
4344 }
4345
4346 /* OMIT QUOTES is meaningless when strings are wrapped. */
4347 if (func->op == JSON_QUERY_OP)
4348 {
4349 if (func->quotes == JS_QUOTES_OMIT &&
4350 (func->wrapper == JSW_CONDITIONAL ||
4351 func->wrapper == JSW_UNCONDITIONAL))
4352 ereport(ERROR,
4354 errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used"),
4355 parser_errposition(pstate, func->location));
4356 if (func->on_empty != NULL &&
4358 func->on_empty->btype != JSON_BEHAVIOR_NULL &&
4363 {
4364 if (func->column_name == NULL)
4365 ereport(ERROR,
4367 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4368 errmsg("invalid %s behavior", "ON EMPTY"),
4369 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
4370 second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
4371 errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s.",
4372 "ON EMPTY", "JSON_QUERY()"),
4373 parser_errposition(pstate, func->on_empty->location));
4374 else
4375 ereport(ERROR,
4377 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4378 errmsg("invalid %s behavior for column \"%s\"",
4379 "ON EMPTY", func->column_name),
4380 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4381 errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns.",
4382 "ON EMPTY"),
4383 parser_errposition(pstate, func->on_empty->location));
4384 }
4385 if (func->on_error != NULL &&
4387 func->on_error->btype != JSON_BEHAVIOR_NULL &&
4392 {
4393 if (func->column_name == NULL)
4394 ereport(ERROR,
4396 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4397 errmsg("invalid %s behavior", "ON ERROR"),
4398 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
4399 second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
4400 errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s.",
4401 "ON ERROR", "JSON_QUERY()"),
4402 parser_errposition(pstate, func->on_error->location));
4403 else
4404 ereport(ERROR,
4406 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4407 errmsg("invalid %s behavior for column \"%s\"",
4408 "ON ERROR", func->column_name),
4409 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4410 errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns.",
4411 "ON ERROR"),
4412 parser_errposition(pstate, func->on_error->location));
4413 }
4414 }
4415
4416 /* Check that ON ERROR/EMPTY behavior values are valid for the function. */
4417 if (func->op == JSON_EXISTS_OP &&
4418 func->on_error != NULL &&
4420 func->on_error->btype != JSON_BEHAVIOR_TRUE &&
4423 {
4424 if (func->column_name == NULL)
4425 ereport(ERROR,
4427 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4428 errmsg("invalid %s behavior", "ON ERROR"),
4429 errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s.",
4430 "ON ERROR", "JSON_EXISTS()"),
4431 parser_errposition(pstate, func->on_error->location));
4432 else
4433 ereport(ERROR,
4435 /*- translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) */
4436 errmsg("invalid %s behavior for column \"%s\"",
4437 "ON ERROR", func->column_name),
4438 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4439 errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns.",
4440 "ON ERROR"),
4441 parser_errposition(pstate, func->on_error->location));
4442 }
4443 if (func->op == JSON_VALUE_OP)
4444 {
4445 if (func->on_empty != NULL &&
4447 func->on_empty->btype != JSON_BEHAVIOR_NULL &&
4449 {
4450 if (func->column_name == NULL)
4451 ereport(ERROR,
4453 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4454 errmsg("invalid %s behavior", "ON EMPTY"),
4455 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
4456 second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
4457 errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s.",
4458 "ON EMPTY", "JSON_VALUE()"),
4459 parser_errposition(pstate, func->on_empty->location));
4460 else
4461 ereport(ERROR,
4463 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4464 errmsg("invalid %s behavior for column \"%s\"",
4465 "ON EMPTY", func->column_name),
4466 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4467 errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns.",
4468 "ON EMPTY"),
4469 parser_errposition(pstate, func->on_empty->location));
4470 }
4471 if (func->on_error != NULL &&
4473 func->on_error->btype != JSON_BEHAVIOR_NULL &&
4475 {
4476 if (func->column_name == NULL)
4477 ereport(ERROR,
4479 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4480 errmsg("invalid %s behavior", "ON ERROR"),
4481 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
4482 second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
4483 errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s.",
4484 "ON ERROR", "JSON_VALUE()"),
4485 parser_errposition(pstate, func->on_error->location));
4486 else
4487 ereport(ERROR,
4489 /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4490 errmsg("invalid %s behavior for column \"%s\"",
4491 "ON ERROR", func->column_name),
4492 /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
4493 errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns.",
4494 "ON ERROR"),
4495 parser_errposition(pstate, func->on_error->location));
4496 }
4497 }
4498
4499 jsexpr = makeNode(JsonExpr);
4500 jsexpr->location = func->location;
4501 jsexpr->op = func->op;
4502 jsexpr->column_name = func->column_name;
4503
4504 /*
4505 * jsonpath machinery can only handle jsonb documents, so coerce the input
4506 * if not already of jsonb type.
4507 */
4508 jsexpr->formatted_expr = transformJsonValueExpr(pstate, func_name,
4509 func->context_item,
4511 JSONBOID,
4512 false);
4513 jsexpr->format = func->context_item->format;
4514
4515 path_spec = transformExprRecurse(pstate, func->pathspec);
4516 pathspec_type = exprType(path_spec);
4517 pathspec_loc = exprLocation(path_spec);
4518 coerced_path_spec = coerce_to_target_type(pstate, path_spec,
4520 JSONPATHOID, -1,
4523 pathspec_loc);
4524 if (coerced_path_spec == NULL)
4525 ereport(ERROR,
4527 errmsg("JSON path expression must be of type %s, not of type %s",
4528 "jsonpath", format_type_be(pathspec_type)),
4530 jsexpr->path_spec = coerced_path_spec;
4531
4532 /* Transform and coerce the PASSING arguments to jsonb. */
4533 transformJsonPassingArgs(pstate, func_name,
4535 func->passing,
4536 &jsexpr->passing_values,
4537 &jsexpr->passing_names);
4538
4539 /* Transform the JsonOutput into JsonReturning. */
4540 jsexpr->returning = transformJsonOutput(pstate, func->output, false);
4541
4542 switch (func->op)
4543 {
4544 case JSON_EXISTS_OP:
4545 /* JSON_EXISTS returns boolean by default. */
4546 if (!OidIsValid(jsexpr->returning->typid))
4547 {
4548 jsexpr->returning->typid = BOOLOID;
4549 jsexpr->returning->typmod = -1;
4550 jsexpr->collation = InvalidOid;
4551 }
4552
4553 /* JSON_TABLE() COLUMNS can specify a non-boolean type. */
4554 if (jsexpr->returning->typid != BOOLOID)
4555 jsexpr->use_json_coercion = true;
4556
4557 jsexpr->on_error = transformJsonBehavior(pstate,
4558 jsexpr,
4559 func->on_error,
4561 jsexpr->returning);
4562 break;
4563
4564 case JSON_QUERY_OP:
4565 /* JSON_QUERY returns jsonb by default. */
4566 if (!OidIsValid(jsexpr->returning->typid))
4567 {
4568 JsonReturning *ret = jsexpr->returning;
4569
4570 ret->typid = JSONBOID;
4571 ret->typmod = -1;
4572 }
4573
4574 jsexpr->collation = get_typcollation(jsexpr->returning->typid);
4575
4576 /*
4577 * Keep quotes on scalar strings by default, omitting them only if
4578 * OMIT QUOTES is specified.
4579 */
4580 jsexpr->omit_quotes = (func->quotes == JS_QUOTES_OMIT);
4581 jsexpr->wrapper = func->wrapper;
4582
4583 /*
4584 * Set up to coerce the result value of JsonPathValue() to the
4585 * RETURNING type (default or user-specified), if needed. Also if
4586 * OMIT QUOTES is specified.
4587 */
4588 if (jsexpr->returning->typid != JSONBOID || jsexpr->omit_quotes)
4589 jsexpr->use_json_coercion = true;
4590
4591 /* Assume NULL ON EMPTY when ON EMPTY is not specified. */
4592 jsexpr->on_empty = transformJsonBehavior(pstate,
4593 jsexpr,
4594 func->on_empty,
4596 jsexpr->returning);
4597 /* Assume NULL ON ERROR when ON ERROR is not specified. */
4598 jsexpr->on_error = transformJsonBehavior(pstate,
4599 jsexpr,
4600 func->on_error,
4602 jsexpr->returning);
4603 break;
4604
4605 case JSON_VALUE_OP:
4606 /* JSON_VALUE returns text by default. */
4607 if (!OidIsValid(jsexpr->returning->typid))
4608 {
4609 jsexpr->returning->typid = TEXTOID;
4610 jsexpr->returning->typmod = -1;
4611 }
4612 jsexpr->collation = get_typcollation(jsexpr->returning->typid);
4613
4614 /*
4615 * Override whatever transformJsonOutput() set these to, which
4616 * assumes that output type to be jsonb.
4617 */
4620
4621 /* Always omit quotes from scalar strings. */
4622 jsexpr->omit_quotes = true;
4623
4624 /*
4625 * Set up to coerce the result value of JsonPathValue() to the
4626 * RETURNING type (default or user-specified), if needed.
4627 */
4628 if (jsexpr->returning->typid != TEXTOID)
4629 {
4630 if (get_typtype(jsexpr->returning->typid) == TYPTYPE_DOMAIN &&
4632 jsexpr->use_json_coercion = true;
4633 else
4634 jsexpr->use_io_coercion = true;
4635 }
4636
4637 /* Assume NULL ON EMPTY when ON EMPTY is not specified. */
4638 jsexpr->on_empty = transformJsonBehavior(pstate,
4639 jsexpr,
4640 func->on_empty,
4642 jsexpr->returning);
4643 /* Assume NULL ON ERROR when ON ERROR is not specified. */
4644 jsexpr->on_error = transformJsonBehavior(pstate,
4645 jsexpr,
4646 func->on_error,
4648 jsexpr->returning);
4649 break;
4650
4651 case JSON_TABLE_OP:
4652 if (!OidIsValid(jsexpr->returning->typid))
4653 {
4654 jsexpr->returning->typid = exprType(jsexpr->formatted_expr);
4655 jsexpr->returning->typmod = -1;
4656 }
4657 jsexpr->collation = get_typcollation(jsexpr->returning->typid);
4658
4659 /*
4660 * Assume EMPTY ARRAY ON ERROR when ON ERROR is not specified.
4661 *
4662 * ON EMPTY cannot be specified at the top level but it can be for
4663 * the individual columns.
4664 */
4665 jsexpr->on_error = transformJsonBehavior(pstate,
4666 jsexpr,
4667 func->on_error,
4669 jsexpr->returning);
4670 break;
4671
4672 default:
4673 elog(ERROR, "invalid JsonFuncExpr op %d", (int) func->op);
4674 break;
4675 }
4676
4677 return (Node *) jsexpr;
4678}
char get_typtype(Oid typid)
Definition lsyscache.c:2779
static JsonBehavior * transformJsonBehavior(ParseState *pstate, JsonExpr *jsexpr, JsonBehavior *behavior, JsonBehaviorType default_behavior, JsonReturning *returning)
static void transformJsonPassingArgs(ParseState *pstate, const char *constructName, JsonFormatType format, List *args, List **passing_values, List **passing_names)
@ JS_QUOTES_OMIT
JsonFormatType
Definition primnodes.h:1662
@ JSW_UNCONDITIONAL
Definition primnodes.h:1778
@ JSW_CONDITIONAL
Definition primnodes.h:1777
@ JSON_QUERY_OP
Definition primnodes.h:1828
@ JSON_TABLE_OP
Definition primnodes.h:1830
@ JSON_EXISTS_OP
Definition primnodes.h:1827
@ JSON_VALUE_OP
Definition primnodes.h:1829
char * column_name
Definition primnodes.h:1844
Node * formatted_expr
Definition primnodes.h:1848
ParseLoc location
Definition primnodes.h:1884
List * passing_values
Definition primnodes.h:1861
JsonBehavior * on_empty
Definition primnodes.h:1864
JsonFormat * format
Definition primnodes.h:1851
List * passing_names
Definition primnodes.h:1860
Node * path_spec
Definition primnodes.h:1854
bool use_io_coercion
Definition primnodes.h:1871
JsonReturning * returning
Definition primnodes.h:1857
bool use_json_coercion
Definition primnodes.h:1872
JsonWrapper wrapper
Definition primnodes.h:1875
JsonExprOp op
Definition primnodes.h:1842
JsonBehavior * on_error
Definition primnodes.h:1865
bool omit_quotes
Definition primnodes.h:1878
JsonEncoding encoding
Definition primnodes.h:1677
JsonOutput * output
char * column_name
JsonWrapper wrapper
JsonQuotes quotes
JsonExprOp op
JsonBehavior * on_empty
ParseLoc location
Node * pathspec
JsonBehavior * on_error
JsonValueExpr * context_item
JsonReturning * returning
JsonFormat * format
Definition primnodes.h:1710
bool DomainHasConstraints(Oid type_id)
Definition typcache.c:1488

References JsonBehavior::btype, COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_EXPLICIT, JsonExpr::collation, JsonFuncExpr::column_name, JsonExpr::column_name, JsonFuncExpr::context_item, DomainHasConstraints(), elog, JsonFormat::encoding, ereport, errcode(), errdetail(), errmsg(), ERROR, exprLocation(), exprType(), fb(), format, JsonReturning::format, JsonValueExpr::format, JsonExpr::format, JsonFormat::format_type, format_type_be(), JsonExpr::formatted_expr, get_typcollation(), get_typtype(), InvalidOid, JS_ENC_DEFAULT, JS_FORMAT_DEFAULT, JS_FORMAT_JSONB, JS_QUOTES_OMIT, JSON_BEHAVIOR_DEFAULT, JSON_BEHAVIOR_EMPTY, JSON_BEHAVIOR_EMPTY_ARRAY, JSON_BEHAVIOR_EMPTY_OBJECT, JSON_BEHAVIOR_ERROR, JSON_BEHAVIOR_FALSE, JSON_BEHAVIOR_NULL, JSON_BEHAVIOR_TRUE, JSON_BEHAVIOR_UNKNOWN, JSON_EXISTS_OP, JSON_QUERY_OP, JSON_TABLE_OP, JSON_VALUE_OP, JSW_CONDITIONAL, JSW_UNCONDITIONAL, JsonFuncExpr::location, JsonBehavior::location, JsonExpr::location, makeNode, OidIsValid, JsonExpr::omit_quotes, JsonFuncExpr::on_empty, JsonExpr::on_empty, JsonFuncExpr::on_error, JsonExpr::on_error, JsonFuncExpr::op, JsonExpr::op, JsonFuncExpr::output, parser_errposition(), JsonFuncExpr::passing, JsonExpr::passing_names, JsonExpr::passing_values, JsonExpr::path_spec, JsonFuncExpr::pathspec, JsonFuncExpr::quotes, JsonOutput::returning, JsonExpr::returning, transformExprRecurse(), transformJsonBehavior(), transformJsonOutput(), transformJsonPassingArgs(), transformJsonValueExpr(), JsonReturning::typid, JsonReturning::typmod, JsonExpr::use_io_coercion, JsonExpr::use_json_coercion, JsonFuncExpr::wrapper, and JsonExpr::wrapper.

Referenced by transformExprRecurse().

◆ transformJsonIsPredicate()

static Node * transformJsonIsPredicate ( ParseState pstate,
JsonIsPredicate pred 
)
static

Definition at line 4113 of file parse_expr.c.

4114{
4115 Oid exprtype;
4116 Node *expr = transformJsonParseArg(pstate, pred->expr, pred->format,
4117 &exprtype);
4118
4119 /* make resulting expression */
4120 if (exprtype != TEXTOID && exprtype != JSONOID && exprtype != JSONBOID)
4121 ereport(ERROR,
4123 errmsg("cannot use type %s in IS JSON predicate",
4124 format_type_be(exprtype))));
4125
4126 /* This intentionally(?) drops the format clause. */
4127 return makeJsonIsPredicate(expr, NULL, pred->item_type,
4128 pred->unique_keys, pred->location);
4129}
Node * makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type, bool unique_keys, int location)
Definition makefuncs.c:986
static Node * transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format, Oid *exprtype)
JsonFormat * format
Definition primnodes.h:1761
JsonValueType item_type
Definition primnodes.h:1762
ParseLoc location
Definition primnodes.h:1764

References ereport, errcode(), errmsg(), ERROR, JsonIsPredicate::expr, fb(), JsonIsPredicate::format, format_type_be(), JsonIsPredicate::item_type, JsonIsPredicate::location, makeJsonIsPredicate(), transformJsonParseArg(), and JsonIsPredicate::unique_keys.

Referenced by transformExprRecurse().

◆ transformJsonObjectAgg()

static Node * transformJsonObjectAgg ( ParseState pstate,
JsonObjectAgg agg 
)
static

Definition at line 3931 of file parse_expr.c.

3932{
3933 JsonReturning *returning;
3934 Node *key;
3935 Node *val;
3936 List *args;
3937 Oid aggfnoid;
3938 Oid aggtype;
3939
3940 key = transformExprRecurse(pstate, (Node *) agg->arg->key);
3941 val = transformJsonValueExpr(pstate, "JSON_OBJECTAGG()",
3942 agg->arg->value,
3944 InvalidOid, false);
3945 args = list_make2(key, val);
3946
3947 returning = transformJsonConstructorOutput(pstate, agg->constructor->output,
3948 args);
3949
3950 if (returning->format->format_type == JS_FORMAT_JSONB)
3951 {
3952 if (agg->absent_on_null)
3953 if (agg->unique)
3955 else
3956 aggfnoid = F_JSONB_OBJECT_AGG_STRICT;
3957 else if (agg->unique)
3958 aggfnoid = F_JSONB_OBJECT_AGG_UNIQUE;
3959 else
3960 aggfnoid = F_JSONB_OBJECT_AGG;
3961
3962 aggtype = JSONBOID;
3963 }
3964 else
3965 {
3966 if (agg->absent_on_null)
3967 if (agg->unique)
3969 else
3970 aggfnoid = F_JSON_OBJECT_AGG_STRICT;
3971 else if (agg->unique)
3972 aggfnoid = F_JSON_OBJECT_AGG_UNIQUE;
3973 else
3974 aggfnoid = F_JSON_OBJECT_AGG;
3975
3976 aggtype = JSONOID;
3977 }
3978
3979 return transformJsonAggConstructor(pstate, agg->constructor, returning,
3980 args, aggfnoid, aggtype,
3982 agg->unique, agg->absent_on_null);
3983}
@ JSCTOR_JSON_OBJECTAGG
Definition primnodes.h:1717

References fb(), JsonReturning::format, JsonFormat::format_type, InvalidOid, JS_FORMAT_DEFAULT, JS_FORMAT_JSONB, JSCTOR_JSON_OBJECTAGG, list_make2, transformExprRecurse(), transformJsonAggConstructor(), transformJsonConstructorOutput(), transformJsonValueExpr(), and val.

Referenced by transformExprRecurse().

◆ transformJsonObjectConstructor()

static Node * transformJsonObjectConstructor ( ParseState pstate,
JsonObjectConstructor ctor 
)
static

Definition at line 3737 of file parse_expr.c.

3738{
3739 JsonReturning *returning;
3740 List *args = NIL;
3741
3742 /* transform key-value pairs, if any */
3743 if (ctor->exprs)
3744 {
3745 ListCell *lc;
3746
3747 /* transform and append key-value arguments */
3748 foreach(lc, ctor->exprs)
3749 {
3751 Node *key = transformExprRecurse(pstate, (Node *) kv->key);
3752 Node *val = transformJsonValueExpr(pstate, "JSON_OBJECT()",
3753 kv->value,
3755 InvalidOid, false);
3756
3757 args = lappend(args, key);
3758 args = lappend(args, val);
3759 }
3760 }
3761
3762 returning = transformJsonConstructorOutput(pstate, ctor->output, args);
3763
3764 return makeJsonConstructorExpr(pstate, JSCTOR_JSON_OBJECT, args, NULL,
3765 returning, ctor->unique,
3766 ctor->absent_on_null, ctor->location);
3767}
@ JSCTOR_JSON_OBJECT
Definition primnodes.h:1715

References castNode, fb(), InvalidOid, JS_FORMAT_DEFAULT, JSCTOR_JSON_OBJECT, lappend(), lfirst, makeJsonConstructorExpr(), NIL, transformExprRecurse(), transformJsonConstructorOutput(), transformJsonValueExpr(), and val.

Referenced by transformExprRecurse().

◆ transformJsonOutput()

static JsonReturning * transformJsonOutput ( ParseState pstate,
const JsonOutput output,
bool  allow_format 
)
static

Definition at line 3523 of file parse_expr.c.

3525{
3526 JsonReturning *ret;
3527
3528 /* if output clause is not specified, make default clause value */
3529 if (!output)
3530 {
3531 ret = makeNode(JsonReturning);
3532
3534 ret->typid = InvalidOid;
3535 ret->typmod = -1;
3536
3537 return ret;
3538 }
3539
3540 ret = copyObject(output->returning);
3541
3542 typenameTypeIdAndMod(pstate, output->typeName, &ret->typid, &ret->typmod);
3543
3544 if (output->typeName->setof)
3545 ereport(ERROR,
3547 errmsg("returning SETOF types is not supported in SQL/JSON functions"));
3548
3549 if (get_typtype(ret->typid) == TYPTYPE_PSEUDO)
3550 ereport(ERROR,
3552 errmsg("returning pseudo-types is not supported in SQL/JSON functions"));
3553
3555 /* assign JSONB format when returning jsonb, or JSON format otherwise */
3556 ret->format->format_type =
3558 else
3559 checkJsonOutputFormat(pstate, ret->format, ret->typid, allow_format);
3560
3561 return ret;
3562}
JsonFormat * makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
Definition makefuncs.c:922
static void checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format, Oid targettype, bool allow_format_for_non_strings)
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition parse_type.c:310

References checkJsonOutputFormat(), copyObject, ereport, errcode(), errmsg(), ERROR, fb(), JsonReturning::format, JsonFormat::format_type, get_typtype(), InvalidOid, JS_ENC_DEFAULT, JS_FORMAT_DEFAULT, JS_FORMAT_JSON, JS_FORMAT_JSONB, makeJsonFormat(), makeNode, output, typenameTypeIdAndMod(), JsonReturning::typid, and JsonReturning::typmod.

Referenced by transformJsonConstructorOutput(), transformJsonFuncExpr(), transformJsonReturning(), and transformJsonSerializeExpr().

◆ transformJsonParseArg()

static Node * transformJsonParseArg ( ParseState pstate,
Node jsexpr,
JsonFormat format,
Oid exprtype 
)
static

Definition at line 4063 of file parse_expr.c.

4065{
4066 Node *raw_expr = transformExprRecurse(pstate, jsexpr);
4067 Node *expr = raw_expr;
4068
4069 *exprtype = exprType(expr);
4070
4071 /* prepare input document */
4072 if (*exprtype == BYTEAOID)
4073 {
4075
4076 expr = raw_expr;
4078 *exprtype = TEXTOID;
4079
4080 jve = makeJsonValueExpr((Expr *) raw_expr, (Expr *) expr, format);
4081 expr = (Node *) jve;
4082 }
4083 else
4084 {
4085 char typcategory;
4086 bool typispreferred;
4087
4089
4090 if (*exprtype == UNKNOWNOID || typcategory == TYPCATEGORY_STRING)
4091 {
4092 expr = coerce_to_target_type(pstate, expr, *exprtype,
4093 TEXTOID, -1,
4096 *exprtype = TEXTOID;
4097 }
4098
4099 if (format->encoding != JS_ENC_DEFAULT)
4100 ereport(ERROR,
4102 parser_errposition(pstate, format->location),
4103 errmsg("cannot use JSON FORMAT ENCODING clause for non-bytea input types")));
4104 }
4105
4106 return expr;
4107}
static Node * makeJsonByteaToTextConversion(Node *expr, JsonFormat *format, int location)
@ COERCION_IMPLICIT
Definition primnodes.h:746

References COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_IMPLICIT, ereport, errcode(), errmsg(), ERROR, exprLocation(), exprType(), fb(), format, get_type_category_preferred(), JS_ENC_DEFAULT, makeJsonByteaToTextConversion(), makeJsonValueExpr(), parser_errposition(), and transformExprRecurse().

Referenced by transformJsonIsPredicate(), and transformJsonParseExpr().

◆ transformJsonParseExpr()

static Node * transformJsonParseExpr ( ParseState pstate,
JsonParseExpr jsexpr 
)
static

Definition at line 4176 of file parse_expr.c.

4177{
4178 JsonOutput *output = jsexpr->output;
4179 JsonReturning *returning;
4180 Node *arg;
4181
4182 returning = transformJsonReturning(pstate, output, "JSON()");
4183
4184 if (jsexpr->unique_keys)
4185 {
4186 /*
4187 * Coerce string argument to text and then to json[b] in the executor
4188 * node with key uniqueness check.
4189 */
4190 JsonValueExpr *jve = jsexpr->expr;
4191 Oid arg_type;
4192
4193 arg = transformJsonParseArg(pstate, (Node *) jve->raw_expr, jve->format,
4194 &arg_type);
4195
4196 if (arg_type != TEXTOID)
4197 ereport(ERROR,
4199 errmsg("cannot use non-string types with WITH UNIQUE KEYS clause"),
4200 parser_errposition(pstate, jsexpr->location)));
4201 }
4202 else
4203 {
4204 /*
4205 * Coerce argument to target type using CAST for compatibility with PG
4206 * function-like CASTs.
4207 */
4208 arg = transformJsonValueExpr(pstate, "JSON()", jsexpr->expr,
4209 JS_FORMAT_JSON, returning->typid, false);
4210 }
4211
4213 returning, jsexpr->unique_keys, false,
4214 jsexpr->location);
4215}
static JsonReturning * transformJsonReturning(ParseState *pstate, JsonOutput *output, const char *fname)
@ JSCTOR_JSON_PARSE
Definition primnodes.h:1719
JsonValueExpr * expr
ParseLoc location
JsonOutput * output

References arg, ereport, errcode(), errmsg(), ERROR, JsonParseExpr::expr, fb(), JS_FORMAT_JSON, JSCTOR_JSON_PARSE, list_make1, JsonParseExpr::location, makeJsonConstructorExpr(), JsonParseExpr::output, output, parser_errposition(), transformJsonParseArg(), transformJsonReturning(), transformJsonValueExpr(), JsonReturning::typid, and JsonParseExpr::unique_keys.

Referenced by transformExprRecurse().

◆ transformJsonPassingArgs()

static void transformJsonPassingArgs ( ParseState pstate,
const char constructName,
JsonFormatType  format,
List args,
List **  passing_values,
List **  passing_names 
)
static

Definition at line 4684 of file parse_expr.c.

4687{
4688 ListCell *lc;
4689
4690 *passing_values = NIL;
4691 *passing_names = NIL;
4692
4693 foreach(lc, args)
4694 {
4697 arg->val, format,
4698 InvalidOid, true);
4699
4700 *passing_values = lappend(*passing_values, expr);
4701 *passing_names = lappend(*passing_names, makeString(arg->name));
4702 }
4703}

References arg, castNode, fb(), format, InvalidOid, lappend(), lfirst, makeString(), NIL, and transformJsonValueExpr().

Referenced by transformJsonFuncExpr().

◆ transformJsonReturning()

static JsonReturning * transformJsonReturning ( ParseState pstate,
JsonOutput output,
const char fname 
)
static

Definition at line 4136 of file parse_expr.c.

4137{
4138 JsonReturning *returning;
4139
4140 if (output)
4141 {
4142 returning = transformJsonOutput(pstate, output, false);
4143
4144 Assert(OidIsValid(returning->typid));
4145
4146 if (returning->typid != JSONOID && returning->typid != JSONBOID)
4147 ereport(ERROR,
4149 errmsg("cannot use type %s in RETURNING clause of %s",
4150 format_type_be(returning->typid), fname),
4151 errhint("Try returning json or jsonb."),
4152 parser_errposition(pstate, output->typeName->location)));
4153 }
4154 else
4155 {
4156 /* Output type is JSON by default. */
4157 Oid targettype = JSONOID;
4159
4160 returning = makeNode(JsonReturning);
4161 returning->format = makeJsonFormat(format, JS_ENC_DEFAULT, -1);
4162 returning->typid = targettype;
4163 returning->typmod = -1;
4164 }
4165
4166 return returning;
4167}

References Assert, ereport, errcode(), errhint(), errmsg(), ERROR, fb(), format, JsonReturning::format, format_type_be(), JS_ENC_DEFAULT, JS_FORMAT_JSON, makeJsonFormat(), makeNode, OidIsValid, output, parser_errposition(), transformJsonOutput(), JsonReturning::typid, and JsonReturning::typmod.

Referenced by transformJsonParseExpr(), and transformJsonScalarExpr().

◆ transformJsonScalarExpr()

static Node * transformJsonScalarExpr ( ParseState pstate,
JsonScalarExpr jsexpr 
)
static

Definition at line 4225 of file parse_expr.c.

4226{
4227 Node *arg = transformExprRecurse(pstate, (Node *) jsexpr->expr);
4228 JsonOutput *output = jsexpr->output;
4229 JsonReturning *returning;
4230
4231 returning = transformJsonReturning(pstate, output, "JSON_SCALAR()");
4232
4233 if (exprType(arg) == UNKNOWNOID)
4234 arg = coerce_to_specific_type(pstate, arg, TEXTOID, "JSON_SCALAR");
4235
4237 returning, false, false, jsexpr->location);
4238}
@ JSCTOR_JSON_SCALAR
Definition primnodes.h:1720
ParseLoc location
JsonOutput * output

References arg, coerce_to_specific_type(), JsonScalarExpr::expr, exprType(), fb(), JSCTOR_JSON_SCALAR, list_make1, JsonScalarExpr::location, makeJsonConstructorExpr(), JsonScalarExpr::output, output, transformExprRecurse(), and transformJsonReturning().

Referenced by transformExprRecurse().

◆ transformJsonSerializeExpr()

static Node * transformJsonSerializeExpr ( ParseState pstate,
JsonSerializeExpr expr 
)
static

Definition at line 4248 of file parse_expr.c.

4249{
4250 JsonReturning *returning;
4251 Node *arg = transformJsonValueExpr(pstate, "JSON_SERIALIZE()",
4252 expr->expr,
4254 InvalidOid, false);
4255
4256 if (expr->output)
4257 {
4258 returning = transformJsonOutput(pstate, expr->output, true);
4259
4260 if (returning->typid != BYTEAOID)
4261 {
4262 char typcategory;
4263 bool typispreferred;
4264
4268 ereport(ERROR,
4270 errmsg("cannot use type %s in RETURNING clause of %s",
4271 format_type_be(returning->typid),
4272 "JSON_SERIALIZE()"),
4273 errhint("Try returning a string type or bytea.")));
4274 }
4275 }
4276 else
4277 {
4278 /* RETURNING TEXT FORMAT JSON is by default */
4279 returning = makeNode(JsonReturning);
4281 returning->typid = TEXTOID;
4282 returning->typmod = -1;
4283 }
4284
4286 NULL, returning, false, false, expr->location);
4287}
@ JSCTOR_JSON_SERIALIZE
Definition primnodes.h:1721
JsonOutput * output
JsonValueExpr * expr

References arg, ereport, errcode(), errhint(), errmsg(), ERROR, JsonSerializeExpr::expr, fb(), JsonReturning::format, format_type_be(), get_type_category_preferred(), InvalidOid, JS_ENC_DEFAULT, JS_FORMAT_JSON, JSCTOR_JSON_SERIALIZE, list_make1, JsonSerializeExpr::location, makeJsonConstructorExpr(), makeJsonFormat(), makeNode, JsonSerializeExpr::output, transformJsonOutput(), transformJsonValueExpr(), JsonReturning::typid, and JsonReturning::typmod.

Referenced by transformExprRecurse().

◆ transformJsonValueExpr()

static Node * transformJsonValueExpr ( ParseState pstate,
const char constructName,
JsonValueExpr ve,
JsonFormatType  default_format,
Oid  targettype,
bool  isarg 
)
static

Definition at line 3311 of file parse_expr.c.

3314{
3315 Node *expr = transformExprRecurse(pstate, (Node *) ve->raw_expr);
3316 Node *rawexpr;
3318 Oid exprtype;
3319 int location;
3320 char typcategory;
3321 bool typispreferred;
3322
3323 if (exprType(expr) == UNKNOWNOID)
3324 expr = coerce_to_specific_type(pstate, expr, TEXTOID, constructName);
3325
3326 rawexpr = expr;
3327 exprtype = exprType(expr);
3328 location = exprLocation(expr);
3329
3331
3332 if (ve->format->format_type != JS_FORMAT_DEFAULT)
3333 {
3334 if (ve->format->encoding != JS_ENC_DEFAULT && exprtype != BYTEAOID)
3335 ereport(ERROR,
3337 errmsg("JSON ENCODING clause is only allowed for bytea input type"),
3338 parser_errposition(pstate, ve->format->location));
3339
3340 if (exprtype == JSONOID || exprtype == JSONBOID)
3341 format = JS_FORMAT_DEFAULT; /* do not format json[b] types */
3342 else
3343 format = ve->format->format_type;
3344 }
3345 else if (isarg)
3346 {
3347 /*
3348 * Special treatment for PASSING arguments.
3349 *
3350 * Pass types supported by GetJsonPathVar() / JsonItemFromDatum()
3351 * directly without converting to json[b].
3352 */
3353 switch (exprtype)
3354 {
3355 case BOOLOID:
3356 case NUMERICOID:
3357 case INT2OID:
3358 case INT4OID:
3359 case INT8OID:
3360 case FLOAT4OID:
3361 case FLOAT8OID:
3362 case TEXTOID:
3363 case VARCHAROID:
3364 case DATEOID:
3365 case TIMEOID:
3366 case TIMETZOID:
3367 case TIMESTAMPOID:
3368 case TIMESTAMPTZOID:
3369 return expr;
3370
3371 default:
3373 return expr;
3374 /* else convert argument to json[b] type */
3375 break;
3376 }
3377
3379 }
3380 else if (exprtype == JSONOID || exprtype == JSONBOID)
3381 format = JS_FORMAT_DEFAULT; /* do not format json[b] types */
3382 else
3384
3385 if (format != JS_FORMAT_DEFAULT ||
3386 (OidIsValid(targettype) && exprtype != targettype))
3387 {
3388 Node *coerced;
3389 bool only_allow_cast = OidIsValid(targettype);
3390
3391 /*
3392 * PASSING args are handled appropriately by GetJsonPathVar() /
3393 * JsonItemFromDatum().
3394 */
3395 if (!isarg &&
3396 !only_allow_cast &&
3397 exprtype != BYTEAOID && typcategory != TYPCATEGORY_STRING)
3398 ereport(ERROR,
3400 ve->format->format_type == JS_FORMAT_DEFAULT ?
3401 errmsg("cannot use non-string types with implicit FORMAT JSON clause") :
3402 errmsg("cannot use non-string types with explicit FORMAT JSON clause"),
3403 parser_errposition(pstate, ve->format->location >= 0 ?
3404 ve->format->location : location));
3405
3406 /* Convert encoded JSON text from bytea. */
3407 if (format == JS_FORMAT_JSON && exprtype == BYTEAOID)
3408 {
3409 expr = makeJsonByteaToTextConversion(expr, ve->format, location);
3410 exprtype = TEXTOID;
3411 }
3412
3413 if (!OidIsValid(targettype))
3414 targettype = format == JS_FORMAT_JSONB ? JSONBOID : JSONOID;
3415
3416 /* Try to coerce to the target type. */
3417 coerced = coerce_to_target_type(pstate, expr, exprtype,
3418 targettype, -1,
3421 location);
3422
3423 if (!coerced)
3424 {
3425 /* If coercion failed, use to_json()/to_jsonb() functions. */
3426 FuncExpr *fexpr;
3427 Oid fnoid;
3428
3429 /*
3430 * Though only allow a cast when the target type is specified by
3431 * the caller.
3432 */
3433 if (only_allow_cast)
3434 ereport(ERROR,
3436 errmsg("cannot cast type %s to %s",
3437 format_type_be(exprtype),
3438 format_type_be(targettype)),
3439 parser_errposition(pstate, location)));
3440
3441 fnoid = targettype == JSONOID ? F_TO_JSON : F_TO_JSONB;
3442 fexpr = makeFuncExpr(fnoid, targettype, list_make1(expr),
3444
3445 fexpr->location = location;
3446
3447 coerced = (Node *) fexpr;
3448 }
3449
3450 if (coerced == expr)
3451 expr = rawexpr;
3452 else
3453 {
3454 ve = copyObject(ve);
3455 ve->raw_expr = (Expr *) rawexpr;
3456 ve->formatted_expr = (Expr *) coerced;
3457
3458 expr = (Node *) ve;
3459 }
3460 }
3461
3462 /* If returning a JsonValueExpr, formatted_expr must have been set. */
3463 Assert(!IsA(expr, JsonValueExpr) ||
3464 ((JsonValueExpr *) expr)->formatted_expr != NULL);
3465
3466 return expr;
3467}

References Assert, COERCE_EXPLICIT_CALL, COERCE_EXPLICIT_CAST, coerce_to_specific_type(), coerce_to_target_type(), COERCION_EXPLICIT, copyObject, ereport, errcode(), errmsg(), ERROR, exprLocation(), exprType(), fb(), format, format_type_be(), get_type_category_preferred(), InvalidOid, IsA, JS_ENC_DEFAULT, JS_FORMAT_DEFAULT, JS_FORMAT_JSON, JS_FORMAT_JSONB, list_make1, makeFuncExpr(), makeJsonByteaToTextConversion(), OidIsValid, parser_errposition(), and transformExprRecurse().

Referenced by transformJsonArrayAgg(), transformJsonArrayConstructor(), transformJsonFuncExpr(), transformJsonObjectAgg(), transformJsonObjectConstructor(), transformJsonParseExpr(), transformJsonPassingArgs(), and transformJsonSerializeExpr().

◆ transformMergeSupportFunc()

static Node * transformMergeSupportFunc ( ParseState pstate,
MergeSupportFunc f 
)
static

Definition at line 1389 of file parse_expr.c.

1390{
1391 /*
1392 * All we need to do is check that we're in the RETURNING list of a MERGE
1393 * command. If so, we just return the node as-is.
1394 */
1396 {
1398
1399 while (parent_pstate &&
1402
1403 if (!parent_pstate)
1404 ereport(ERROR,
1406 errmsg("MERGE_ACTION() can only be used in the RETURNING list of a MERGE command"),
1407 parser_errposition(pstate, f->location));
1408 }
1409
1410 return (Node *) f;
1411}
ParseLoc location
Definition primnodes.h:668
ParseState * parentParseState
Definition parse_node.h:194

References ereport, errcode(), errmsg(), ERROR, EXPR_KIND_MERGE_RETURNING, fb(), MergeSupportFunc::location, ParseState::p_expr_kind, ParseState::parentParseState, and parser_errposition().

Referenced by transformExprRecurse().

◆ transformMinMaxExpr()

static Node * transformMinMaxExpr ( ParseState pstate,
MinMaxExpr m 
)
static

Definition at line 2276 of file parse_expr.c.

2277{
2279 List *newargs = NIL;
2281 const char *funcname = (m->op == IS_GREATEST) ? "GREATEST" : "LEAST";
2282 ListCell *args;
2283
2284 newm->op = m->op;
2285 foreach(args, m->args)
2286 {
2287 Node *e = (Node *) lfirst(args);
2288 Node *newe;
2289
2290 newe = transformExprRecurse(pstate, e);
2292 }
2293
2294 newm->minmaxtype = select_common_type(pstate, newargs, funcname, NULL);
2295 /* minmaxcollid and inputcollid will be set by parse_collate.c */
2296
2297 /* Convert arguments if necessary */
2298 foreach(args, newargs)
2299 {
2300 Node *e = (Node *) lfirst(args);
2301 Node *newe;
2302
2303 newe = coerce_to_common_type(pstate, e,
2304 newm->minmaxtype,
2305 funcname);
2307 }
2308
2309 newm->args = newcoercedargs;
2310 newm->location = m->location;
2311 return (Node *) newm;
2312}
#define funcname
@ IS_GREATEST
Definition primnodes.h:1527
List * args
Definition primnodes.h:1543
ParseLoc location
Definition primnodes.h:1545
MinMaxOp op
Definition primnodes.h:1541

References MinMaxExpr::args, coerce_to_common_type(), fb(), funcname, IS_GREATEST, lappend(), lfirst, MinMaxExpr::location, makeNode, NIL, MinMaxExpr::op, select_common_type(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformMultiAssignRef()

static Node * transformMultiAssignRef ( ParseState pstate,
MultiAssignRef maref 
)
static

Definition at line 1495 of file parse_expr.c.

1496{
1498 RowExpr *rexpr;
1499 Query *qtree;
1501
1502 /* We should only see this in first-stage processing of UPDATE tlists */
1504
1505 /* We only need to transform the source if this is the first column */
1506 if (maref->colno == 1)
1507 {
1508 /*
1509 * For now, we only allow EXPR SubLinks and RowExprs as the source of
1510 * an UPDATE multiassignment. This is sufficient to cover interesting
1511 * cases; at worst, someone would have to write (SELECT * FROM expr)
1512 * to expand a composite-returning expression of another form.
1513 */
1514 if (IsA(maref->source, SubLink) &&
1515 ((SubLink *) maref->source)->subLinkType == EXPR_SUBLINK)
1516 {
1517 /* Relabel it as a MULTIEXPR_SUBLINK */
1518 sublink = (SubLink *) maref->source;
1519 sublink->subLinkType = MULTIEXPR_SUBLINK;
1520 /* And transform it */
1522 (Node *) sublink);
1523
1524 qtree = castNode(Query, sublink->subselect);
1525
1526 /* Check subquery returns required number of columns */
1527 if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns)
1528 ereport(ERROR,
1530 errmsg("number of columns does not match number of values"),
1531 parser_errposition(pstate, sublink->location)));
1532
1533 /*
1534 * Build a resjunk tlist item containing the MULTIEXPR SubLink,
1535 * and add it to pstate->p_multiassign_exprs, whence it will later
1536 * get appended to the completed targetlist. We needn't worry
1537 * about selecting a resno for it; transformUpdateStmt will do
1538 * that.
1539 */
1540 tle = makeTargetEntry((Expr *) sublink, 0, NULL, true);
1542 tle);
1543
1544 /*
1545 * Assign a unique-within-this-targetlist ID to the MULTIEXPR
1546 * SubLink. We can just use its position in the
1547 * p_multiassign_exprs list.
1548 */
1549 sublink->subLinkId = list_length(pstate->p_multiassign_exprs);
1550 }
1551 else if (IsA(maref->source, RowExpr))
1552 {
1553 /* Transform the RowExpr, allowing SetToDefault items */
1554 rexpr = (RowExpr *) transformRowExpr(pstate,
1555 (RowExpr *) maref->source,
1556 true);
1557
1558 /* Check it returns required number of columns */
1559 if (list_length(rexpr->args) != maref->ncolumns)
1560 ereport(ERROR,
1562 errmsg("number of columns does not match number of values"),
1563 parser_errposition(pstate, rexpr->location)));
1564
1565 /*
1566 * Temporarily append it to p_multiassign_exprs, so we can get it
1567 * back when we come back here for additional columns.
1568 */
1569 tle = makeTargetEntry((Expr *) rexpr, 0, NULL, true);
1571 tle);
1572 }
1573 else
1574 ereport(ERROR,
1576 errmsg("source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression"),
1577 parser_errposition(pstate, exprLocation(maref->source))));
1578 }
1579 else
1580 {
1581 /*
1582 * Second or later column in a multiassignment. Re-fetch the
1583 * transformed SubLink or RowExpr, which we assume is still the last
1584 * entry in p_multiassign_exprs.
1585 */
1586 Assert(pstate->p_multiassign_exprs != NIL);
1588 }
1589
1590 /*
1591 * Emit the appropriate output expression for the current column
1592 */
1593 if (IsA(tle->expr, SubLink))
1594 {
1595 Param *param;
1596
1597 sublink = (SubLink *) tle->expr;
1598 Assert(sublink->subLinkType == MULTIEXPR_SUBLINK);
1599 qtree = castNode(Query, sublink->subselect);
1600
1601 /* Build a Param representing the current subquery output column */
1602 tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1);
1603 Assert(!tle->resjunk);
1604
1605 param = makeNode(Param);
1606 param->paramkind = PARAM_MULTIEXPR;
1607 param->paramid = (sublink->subLinkId << 16) | maref->colno;
1608 param->paramtype = exprType((Node *) tle->expr);
1609 param->paramtypmod = exprTypmod((Node *) tle->expr);
1610 param->paramcollid = exprCollation((Node *) tle->expr);
1611 param->location = exprLocation((Node *) tle->expr);
1612
1613 return (Node *) param;
1614 }
1615
1616 if (IsA(tle->expr, RowExpr))
1617 {
1618 Node *result;
1619
1620 rexpr = (RowExpr *) tle->expr;
1621
1622 /* Just extract and return the next element of the RowExpr */
1623 result = (Node *) list_nth(rexpr->args, maref->colno - 1);
1624
1625 /*
1626 * If we're at the last column, delete the RowExpr from
1627 * p_multiassign_exprs; we don't need it anymore, and don't want it in
1628 * the finished UPDATE tlist. We assume this is still the last entry
1629 * in p_multiassign_exprs.
1630 */
1631 if (maref->colno == maref->ncolumns)
1632 pstate->p_multiassign_exprs =
1634
1635 return result;
1636 }
1637
1638 elog(ERROR, "unexpected expr type in multiassign list");
1639 return NULL; /* keep compiler quiet */
1640}
List * list_delete_last(List *list)
Definition list.c:957
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition makefuncs.c:289
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
@ MULTIEXPR_SUBLINK
Definition primnodes.h:1034
@ PARAM_MULTIEXPR
Definition primnodes.h:387
List * p_multiassign_exprs
Definition parse_node.h:216
List * args
Definition primnodes.h:1448
ParseLoc location
Definition primnodes.h:1472

References RowExpr::args, Assert, castNode, count_nonjunk_tlist_entries(), elog, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_UPDATE_SOURCE, EXPR_SUBLINK, exprCollation(), exprLocation(), exprType(), exprTypmod(), fb(), IsA, lappend(), list_delete_last(), list_length(), list_nth(), llast, Param::location, RowExpr::location, makeNode, makeTargetEntry(), MULTIEXPR_SUBLINK, NIL, ParseState::p_expr_kind, ParseState::p_multiassign_exprs, PARAM_MULTIEXPR, Param::paramcollid, Param::paramid, Param::paramkind, Param::paramtype, Param::paramtypmod, parser_errposition(), transformExprRecurse(), and transformRowExpr().

Referenced by transformExprRecurse().

◆ transformParamRef()

static Node * transformParamRef ( ParseState pstate,
ParamRef pref 
)
static

Definition at line 886 of file parse_expr.c.

887{
888 Node *result;
889
890 /*
891 * The core parser knows nothing about Params. If a hook is supplied,
892 * call it. If not, or if the hook returns NULL, throw a generic error.
893 */
894 if (pstate->p_paramref_hook != NULL)
895 result = pstate->p_paramref_hook(pstate, pref);
896 else
897 result = NULL;
898
899 if (result == NULL)
902 errmsg("there is no parameter $%d", pref->number),
903 parser_errposition(pstate, pref->location)));
904
905 return result;
906}
ParseParamRefHook p_paramref_hook
Definition parse_node.h:240

References ereport, errcode(), errmsg(), ERROR, fb(), ParseState::p_paramref_hook, and parser_errposition().

Referenced by transformExprRecurse().

◆ transformRowExpr()

static Node * transformRowExpr ( ParseState pstate,
RowExpr r,
bool  allowDefault 
)
static

Definition at line 2189 of file parse_expr.c.

2190{
2191 RowExpr *newr;
2192 char fname[16];
2193 int fnum;
2194
2196
2197 /* Transform the field expressions */
2198 newr->args = transformExpressionList(pstate, r->args,
2199 pstate->p_expr_kind, allowDefault);
2200
2201 /* Disallow more columns than will fit in a tuple */
2203 ereport(ERROR,
2205 errmsg("ROW expressions can have at most %d entries",
2207 parser_errposition(pstate, r->location)));
2208
2209 /* Barring later casting, we consider the type RECORD */
2210 newr->row_typeid = RECORDOID;
2211 newr->row_format = COERCE_IMPLICIT_CAST;
2212
2213 /* ROW() has anonymous columns, so invent some field names */
2214 newr->colnames = NIL;
2215 for (fnum = 1; fnum <= list_length(newr->args); fnum++)
2216 {
2217 snprintf(fname, sizeof(fname), "f%d", fnum);
2218 newr->colnames = lappend(newr->colnames, makeString(pstrdup(fname)));
2219 }
2220
2221 newr->location = r->location;
2222
2223 return (Node *) newr;
2224}
#define MaxTupleAttributeNumber
List * transformExpressionList(ParseState *pstate, List *exprlist, ParseExprKind exprKind, bool allowDefault)
#define snprintf
Definition port.h:260

References RowExpr::args, COERCE_IMPLICIT_CAST, ereport, errcode(), errmsg(), ERROR, fb(), lappend(), list_length(), RowExpr::location, makeNode, makeString(), MaxTupleAttributeNumber, NIL, ParseState::p_expr_kind, parser_errposition(), pstrdup(), snprintf, and transformExpressionList().

Referenced by transformExprRecurse(), and transformMultiAssignRef().

◆ transformSQLValueFunction()

static Node * transformSQLValueFunction ( ParseState pstate,
SQLValueFunction svf 
)
static

Definition at line 2315 of file parse_expr.c.

2316{
2317 /*
2318 * All we need to do is insert the correct result type and (where needed)
2319 * validate the typmod, so we just modify the node in-place.
2320 */
2321 switch (svf->op)
2322 {
2323 case SVFOP_CURRENT_DATE:
2324 svf->type = DATEOID;
2325 break;
2326 case SVFOP_CURRENT_TIME:
2327 svf->type = TIMETZOID;
2328 break;
2330 svf->type = TIMETZOID;
2331 svf->typmod = anytime_typmod_check(true, svf->typmod);
2332 break;
2334 svf->type = TIMESTAMPTZOID;
2335 break;
2337 svf->type = TIMESTAMPTZOID;
2338 svf->typmod = anytimestamp_typmod_check(true, svf->typmod);
2339 break;
2340 case SVFOP_LOCALTIME:
2341 svf->type = TIMEOID;
2342 break;
2343 case SVFOP_LOCALTIME_N:
2344 svf->type = TIMEOID;
2345 svf->typmod = anytime_typmod_check(false, svf->typmod);
2346 break;
2348 svf->type = TIMESTAMPOID;
2349 break;
2351 svf->type = TIMESTAMPOID;
2352 svf->typmod = anytimestamp_typmod_check(false, svf->typmod);
2353 break;
2354 case SVFOP_CURRENT_ROLE:
2355 case SVFOP_CURRENT_USER:
2356 case SVFOP_USER:
2357 case SVFOP_SESSION_USER:
2360 svf->type = NAMEOID;
2361 break;
2362 }
2363
2364 return (Node *) svf;
2365}
int32 anytimestamp_typmod_check(bool istz, int32 typmod)
Definition timestamp.c:125
int32 anytime_typmod_check(bool istz, int32 typmod)
Definition date.c:73
@ SVFOP_CURRENT_CATALOG
Definition primnodes.h:1574
@ SVFOP_LOCALTIME_N
Definition primnodes.h:1567
@ SVFOP_CURRENT_TIMESTAMP
Definition primnodes.h:1564
@ SVFOP_LOCALTIME
Definition primnodes.h:1566
@ SVFOP_CURRENT_TIMESTAMP_N
Definition primnodes.h:1565
@ SVFOP_CURRENT_ROLE
Definition primnodes.h:1570
@ SVFOP_USER
Definition primnodes.h:1572
@ SVFOP_CURRENT_SCHEMA
Definition primnodes.h:1575
@ SVFOP_LOCALTIMESTAMP_N
Definition primnodes.h:1569
@ SVFOP_CURRENT_DATE
Definition primnodes.h:1561
@ SVFOP_CURRENT_TIME_N
Definition primnodes.h:1563
@ SVFOP_CURRENT_TIME
Definition primnodes.h:1562
@ SVFOP_LOCALTIMESTAMP
Definition primnodes.h:1568
@ SVFOP_CURRENT_USER
Definition primnodes.h:1571
@ SVFOP_SESSION_USER
Definition primnodes.h:1573
SQLValueFunctionOp op
Definition primnodes.h:1581

References anytime_typmod_check(), anytimestamp_typmod_check(), fb(), SQLValueFunction::op, SVFOP_CURRENT_CATALOG, SVFOP_CURRENT_DATE, SVFOP_CURRENT_ROLE, SVFOP_CURRENT_SCHEMA, SVFOP_CURRENT_TIME, SVFOP_CURRENT_TIME_N, SVFOP_CURRENT_TIMESTAMP, SVFOP_CURRENT_TIMESTAMP_N, SVFOP_CURRENT_USER, SVFOP_LOCALTIME, SVFOP_LOCALTIME_N, SVFOP_LOCALTIMESTAMP, SVFOP_LOCALTIMESTAMP_N, SVFOP_SESSION_USER, SVFOP_USER, and SQLValueFunction::typmod.

Referenced by transformExprRecurse().

◆ transformSubLink()

static Node * transformSubLink ( ParseState pstate,
SubLink sublink 
)
static

Definition at line 1783 of file parse_expr.c.

1784{
1785 Node *result = (Node *) sublink;
1786 Query *qtree;
1787 const char *err;
1788
1789 /*
1790 * Check to see if the sublink is in an invalid place within the query. We
1791 * allow sublinks everywhere in SELECT/INSERT/UPDATE/DELETE/MERGE, but
1792 * generally not in utility statements.
1793 */
1794 err = NULL;
1795 switch (pstate->p_expr_kind)
1796 {
1797 case EXPR_KIND_NONE:
1798 Assert(false); /* can't happen */
1799 break;
1800 case EXPR_KIND_OTHER:
1801 /* Accept sublink here; caller must throw error if wanted */
1802 break;
1803 case EXPR_KIND_JOIN_ON:
1807 case EXPR_KIND_WHERE:
1808 case EXPR_KIND_POLICY:
1809 case EXPR_KIND_HAVING:
1810 case EXPR_KIND_FILTER:
1821 case EXPR_KIND_GROUP_BY:
1822 case EXPR_KIND_ORDER_BY:
1824 case EXPR_KIND_LIMIT:
1825 case EXPR_KIND_OFFSET:
1828 case EXPR_KIND_VALUES:
1831 /* okay */
1832 break;
1835 err = _("cannot use subquery in check constraint");
1836 break;
1839 err = _("cannot use subquery in DEFAULT expression");
1840 break;
1842 err = _("cannot use subquery in index expression");
1843 break;
1845 err = _("cannot use subquery in index predicate");
1846 break;
1848 err = _("cannot use subquery in statistics expression");
1849 break;
1851 err = _("cannot use subquery in transform expression");
1852 break;
1854 err = _("cannot use subquery in EXECUTE parameter");
1855 break;
1857 err = _("cannot use subquery in trigger WHEN condition");
1858 break;
1860 err = _("cannot use subquery in partition bound");
1861 break;
1863 err = _("cannot use subquery in partition key expression");
1864 break;
1866 err = _("cannot use subquery in CALL argument");
1867 break;
1869 err = _("cannot use subquery in COPY FROM WHERE condition");
1870 break;
1872 err = _("cannot use subquery in column generation expression");
1873 break;
1874
1875 /*
1876 * There is intentionally no default: case here, so that the
1877 * compiler will warn if we add a new ParseExprKind without
1878 * extending this switch. If we do see an unrecognized value at
1879 * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
1880 * which is sane anyway.
1881 */
1882 }
1883 if (err)
1884 ereport(ERROR,
1886 errmsg_internal("%s", err),
1887 parser_errposition(pstate, sublink->location)));
1888
1889 pstate->p_hasSubLinks = true;
1890
1891 /*
1892 * OK, let's transform the sub-SELECT.
1893 */
1894 qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false, true);
1895
1896 /*
1897 * Check that we got a SELECT. Anything else should be impossible given
1898 * restrictions of the grammar, but check anyway.
1899 */
1900 if (!IsA(qtree, Query) ||
1901 qtree->commandType != CMD_SELECT)
1902 elog(ERROR, "unexpected non-SELECT command in SubLink");
1903
1904 sublink->subselect = (Node *) qtree;
1905
1906 if (sublink->subLinkType == EXISTS_SUBLINK)
1907 {
1908 /*
1909 * EXISTS needs no test expression or combining operator. These fields
1910 * should be null already, but make sure.
1911 */
1912 sublink->testexpr = NULL;
1913 sublink->operName = NIL;
1914 }
1915 else if (sublink->subLinkType == EXPR_SUBLINK ||
1916 sublink->subLinkType == ARRAY_SUBLINK)
1917 {
1918 /*
1919 * Make sure the subselect delivers a single column (ignoring resjunk
1920 * targets).
1921 */
1922 if (count_nonjunk_tlist_entries(qtree->targetList) != 1)
1923 ereport(ERROR,
1925 errmsg("subquery must return only one column"),
1926 parser_errposition(pstate, sublink->location)));
1927
1928 /*
1929 * EXPR and ARRAY need no test expression or combining operator. These
1930 * fields should be null already, but make sure.
1931 */
1932 sublink->testexpr = NULL;
1933 sublink->operName = NIL;
1934 }
1935 else if (sublink->subLinkType == MULTIEXPR_SUBLINK)
1936 {
1937 /* Same as EXPR case, except no restriction on number of columns */
1938 sublink->testexpr = NULL;
1939 sublink->operName = NIL;
1940 }
1941 else
1942 {
1943 /* ALL, ANY, or ROWCOMPARE: generate row-comparing expression */
1944 Node *lefthand;
1945 List *left_list;
1947 ListCell *l;
1948
1949 /*
1950 * If the source was "x IN (select)", convert to "x = ANY (select)".
1951 */
1952 if (sublink->operName == NIL)
1953 sublink->operName = list_make1(makeString("="));
1954
1955 /*
1956 * Transform lefthand expression, and convert to a list
1957 */
1958 lefthand = transformExprRecurse(pstate, sublink->testexpr);
1959 if (lefthand && IsA(lefthand, RowExpr))
1960 left_list = ((RowExpr *) lefthand)->args;
1961 else
1963
1964 /*
1965 * Build a list of PARAM_SUBLINK nodes representing the output columns
1966 * of the subquery.
1967 */
1968 right_list = NIL;
1969 foreach(l, qtree->targetList)
1970 {
1972 Param *param;
1973
1974 if (tent->resjunk)
1975 continue;
1976
1977 param = makeNode(Param);
1978 param->paramkind = PARAM_SUBLINK;
1979 param->paramid = tent->resno;
1980 param->paramtype = exprType((Node *) tent->expr);
1981 param->paramtypmod = exprTypmod((Node *) tent->expr);
1982 param->paramcollid = exprCollation((Node *) tent->expr);
1983 param->location = -1;
1984
1985 right_list = lappend(right_list, param);
1986 }
1987
1988 /*
1989 * We could rely on make_row_comparison_op to complain if the list
1990 * lengths differ, but we prefer to generate a more specific error
1991 * message.
1992 */
1994 ereport(ERROR,
1996 errmsg("subquery has too many columns"),
1997 parser_errposition(pstate, sublink->location)));
1999 ereport(ERROR,
2001 errmsg("subquery has too few columns"),
2002 parser_errposition(pstate, sublink->location)));
2003
2004 /*
2005 * Identify the combining operator(s) and generate a suitable
2006 * row-comparison expression.
2007 */
2008 sublink->testexpr = make_row_comparison_op(pstate,
2009 sublink->operName,
2010 left_list,
2011 right_list,
2012 sublink->location);
2013 }
2014
2015 return result;
2016}
@ CMD_SELECT
Definition nodes.h:275
Query * parse_sub_analyze(Node *parseTree, ParseState *parentParseState, CommonTableExpr *parentCTE, bool locked_from_parent, bool resolve_unknowns)
Definition analyze.c:234
@ ARRAY_SUBLINK
Definition primnodes.h:1035
@ EXISTS_SUBLINK
Definition primnodes.h:1029
@ PARAM_SUBLINK
Definition primnodes.h:386
ParseLoc location
Definition primnodes.h:403
int32 paramtypmod
Definition primnodes.h:399
Oid paramcollid
Definition primnodes.h:401
bool p_hasSubLinks
Definition parse_node.h:229

References _, ARRAY_SUBLINK, Assert, CMD_SELECT, count_nonjunk_tlist_entries(), elog, ereport, err(), errcode(), errmsg(), errmsg_internal(), ERROR, EXISTS_SUBLINK, EXPR_KIND_ALTER_COL_TRANSFORM, EXPR_KIND_CALL_ARGUMENT, EXPR_KIND_CHECK_CONSTRAINT, EXPR_KIND_COLUMN_DEFAULT, EXPR_KIND_COPY_WHERE, EXPR_KIND_CYCLE_MARK, EXPR_KIND_DISTINCT_ON, EXPR_KIND_DOMAIN_CHECK, EXPR_KIND_EXECUTE_PARAMETER, EXPR_KIND_FILTER, EXPR_KIND_FROM_FUNCTION, EXPR_KIND_FROM_SUBSELECT, EXPR_KIND_FUNCTION_DEFAULT, EXPR_KIND_GENERATED_COLUMN, EXPR_KIND_GROUP_BY, EXPR_KIND_HAVING, EXPR_KIND_INDEX_EXPRESSION, EXPR_KIND_INDEX_PREDICATE, EXPR_KIND_INSERT_TARGET, EXPR_KIND_JOIN_ON, EXPR_KIND_JOIN_USING, EXPR_KIND_LIMIT, EXPR_KIND_MERGE_RETURNING, EXPR_KIND_MERGE_WHEN, EXPR_KIND_NONE, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_OTHER, EXPR_KIND_PARTITION_BOUND, EXPR_KIND_PARTITION_EXPRESSION, EXPR_KIND_POLICY, EXPR_KIND_RETURNING, EXPR_KIND_SELECT_TARGET, EXPR_KIND_STATS_EXPRESSION, EXPR_KIND_TRIGGER_WHEN, EXPR_KIND_UPDATE_SOURCE, EXPR_KIND_UPDATE_TARGET, EXPR_KIND_VALUES, EXPR_KIND_VALUES_SINGLE, EXPR_KIND_WHERE, EXPR_KIND_WINDOW_FRAME_GROUPS, EXPR_KIND_WINDOW_FRAME_RANGE, EXPR_KIND_WINDOW_FRAME_ROWS, EXPR_KIND_WINDOW_ORDER, EXPR_KIND_WINDOW_PARTITION, EXPR_SUBLINK, exprCollation(), exprType(), exprTypmod(), fb(), IsA, lappend(), lfirst, list_length(), list_make1, Param::location, make_row_comparison_op(), makeNode, makeString(), MULTIEXPR_SUBLINK, NIL, ParseState::p_expr_kind, ParseState::p_hasSubLinks, PARAM_SUBLINK, Param::paramcollid, Param::paramid, Param::paramkind, Param::paramtype, Param::paramtypmod, parse_sub_analyze(), parser_errposition(), and transformExprRecurse().

Referenced by transformExprRecurse().

◆ transformTypeCast()

static Node * transformTypeCast ( ParseState pstate,
TypeCast tc 
)
static

Definition at line 2715 of file parse_expr.c.

2716{
2717 Node *result;
2718 Node *arg = tc->arg;
2719 Node *expr;
2720 Oid inputType;
2723 int location;
2724
2725 /* Look up the type name first */
2726 typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod);
2727
2728 /*
2729 * If the subject of the typecast is an ARRAY[] construct and the target
2730 * type is an array type, we invoke transformArrayExpr() directly so that
2731 * we can pass down the type information. This avoids some cases where
2732 * transformArrayExpr() might not infer the correct type. Otherwise, just
2733 * transform the argument normally.
2734 */
2735 if (IsA(arg, A_ArrayExpr))
2736 {
2740
2741 /*
2742 * If target is a domain over array, work with the base array type
2743 * here. Below, we'll cast the array type to the domain. In the
2744 * usual case that the target is not a domain, the remaining steps
2745 * will be a no-op.
2746 */
2751 {
2752 expr = transformArrayExpr(pstate,
2753 (A_ArrayExpr *) arg,
2757 }
2758 else
2759 expr = transformExprRecurse(pstate, arg);
2760 }
2761 else
2762 expr = transformExprRecurse(pstate, arg);
2763
2764 inputType = exprType(expr);
2765 if (inputType == InvalidOid)
2766 return expr; /* do nothing if NULL input */
2767
2768 /*
2769 * Location of the coercion is preferentially the location of the :: or
2770 * CAST symbol, but if there is none then use the location of the type
2771 * name (this can happen in TypeName 'string' syntax, for instance).
2772 */
2773 location = tc->location;
2774 if (location < 0)
2775 location = tc->typeName->location;
2776
2777 result = coerce_to_target_type(pstate, expr, inputType,
2781 location);
2782 if (result == NULL)
2783 ereport(ERROR,
2785 errmsg("cannot cast type %s to %s",
2788 parser_coercion_errposition(pstate, location, expr)));
2789
2790 return result;
2791}
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition lsyscache.c:2688

References arg, COERCE_EXPLICIT_CAST, coerce_to_target_type(), COERCION_EXPLICIT, ereport, errcode(), errmsg(), ERROR, exprType(), fb(), format_type_be(), get_element_type(), getBaseTypeAndTypmod(), InvalidOid, IsA, OidIsValid, parser_coercion_errposition(), transformArrayExpr(), transformExprRecurse(), and typenameTypeIdAndMod().

Referenced by transformExprRecurse().

◆ transformWholeRowRef()

static Node * transformWholeRowRef ( ParseState pstate,
ParseNamespaceItem nsitem,
int  sublevels_up,
int  location 
)
static

Definition at line 2633 of file parse_expr.c.

2635{
2636 /*
2637 * Build the appropriate referencing node. Normally this can be a
2638 * whole-row Var, but if the nsitem is a JOIN USING alias then it contains
2639 * only a subset of the columns of the underlying join RTE, so that will
2640 * not work. Instead we immediately expand the reference into a RowExpr.
2641 * Since the JOIN USING's common columns are fully determined at this
2642 * point, there seems no harm in expanding it now rather than during
2643 * planning.
2644 *
2645 * Note that if the nsitem is an OLD/NEW alias for the target RTE (as can
2646 * appear in a RETURNING list), its alias won't match the target RTE's
2647 * alias, but we still want to make a whole-row Var here rather than a
2648 * RowExpr, for consistency with direct references to the target RTE, and
2649 * so that any dropped columns are handled correctly. Thus we also check
2650 * p_returning_type here.
2651 *
2652 * Note that if the RTE is a function returning scalar, we create just a
2653 * plain reference to the function value, not a composite containing a
2654 * single column. This is pretty inconsistent at first sight, but it's
2655 * what we've done historically. One argument for it is that "rel" and
2656 * "rel.*" mean the same thing for composite relations, so why not for
2657 * scalar functions...
2658 */
2659 if (nsitem->p_names == nsitem->p_rte->eref ||
2660 nsitem->p_returning_type != VAR_RETURNING_DEFAULT)
2661 {
2662 Var *result;
2663
2664 result = makeWholeRowVar(nsitem->p_rte, nsitem->p_rtindex,
2665 sublevels_up, true);
2666
2667 /* mark Var for RETURNING OLD/NEW, as necessary */
2668 result->varreturningtype = nsitem->p_returning_type;
2669
2670 /* location is not filled in by makeWholeRowVar */
2671 result->location = location;
2672
2673 /* mark Var if it's nulled by any outer joins */
2674 markNullableIfNeeded(pstate, result);
2675
2676 /* mark relation as requiring whole-row SELECT access */
2677 markVarForSelectPriv(pstate, result);
2678
2679 return (Node *) result;
2680 }
2681 else
2682 {
2683 RowExpr *rowexpr;
2684 List *fields;
2685
2686 /*
2687 * We want only as many columns as are listed in p_names->colnames,
2688 * and we should use those names not whatever possibly-aliased names
2689 * are in the RTE. We needn't worry about marking the RTE for SELECT
2690 * access, as the common columns are surely so marked already.
2691 */
2692 expandRTE(nsitem->p_rte, nsitem->p_rtindex, sublevels_up,
2693 nsitem->p_returning_type, location, false, NULL, &fields);
2694 rowexpr = makeNode(RowExpr);
2695 rowexpr->args = list_truncate(fields,
2696 list_length(nsitem->p_names->colnames));
2697 rowexpr->row_typeid = RECORDOID;
2698 rowexpr->row_format = COERCE_IMPLICIT_CAST;
2699 rowexpr->colnames = copyObject(nsitem->p_names->colnames);
2700 rowexpr->location = location;
2701
2702 /* XXX we ought to mark the row as possibly nullable */
2703
2704 return (Node *) rowexpr;
2705 }
2706}
List * list_truncate(List *list, int new_size)
Definition list.c:631
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition makefuncs.c:137
void markNullableIfNeeded(ParseState *pstate, Var *var)
void markVarForSelectPriv(ParseState *pstate, Var *var)
void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, VarReturningType returning_type, int location, bool include_dropped, List **colnames, List **colvars)
@ VAR_RETURNING_DEFAULT
Definition primnodes.h:256
ParseLoc location
Definition primnodes.h:310
VarReturningType varreturningtype
Definition primnodes.h:297

References RowExpr::args, COERCE_IMPLICIT_CAST, copyObject, expandRTE(), fb(), list_length(), list_truncate(), Var::location, RowExpr::location, makeNode, makeWholeRowVar(), markNullableIfNeeded(), markVarForSelectPriv(), VAR_RETURNING_DEFAULT, and Var::varreturningtype.

Referenced by transformColumnRef().

◆ transformXmlExpr()

static Node * transformXmlExpr ( ParseState pstate,
XmlExpr x 
)
static

Definition at line 2368 of file parse_expr.c.

2369{
2370 XmlExpr *newx;
2371 ListCell *lc;
2372 int i;
2373
2375 newx->op = x->op;
2376 if (x->name)
2377 newx->name = map_sql_identifier_to_xml_name(x->name, false, false);
2378 else
2379 newx->name = NULL;
2380 newx->xmloption = x->xmloption;
2381 newx->type = XMLOID; /* this just marks the node as transformed */
2382 newx->typmod = -1;
2383 newx->location = x->location;
2384
2385 /*
2386 * gram.y built the named args as a list of ResTarget. Transform each,
2387 * and break the names out as a separate list.
2388 */
2389 newx->named_args = NIL;
2390 newx->arg_names = NIL;
2391
2392 foreach(lc, x->named_args)
2393 {
2395 Node *expr;
2396 char *argname;
2397
2398 expr = transformExprRecurse(pstate, r->val);
2399
2400 if (r->name)
2401 argname = map_sql_identifier_to_xml_name(r->name, false, false);
2402 else if (IsA(r->val, ColumnRef))
2404 true, false);
2405 else
2406 {
2407 ereport(ERROR,
2409 x->op == IS_XMLELEMENT
2410 ? errmsg("unnamed XML attribute value must be a column reference")
2411 : errmsg("unnamed XML element value must be a column reference"),
2412 parser_errposition(pstate, r->location)));
2413 argname = NULL; /* keep compiler quiet */
2414 }
2415
2416 /* reject duplicate argnames in XMLELEMENT only */
2417 if (x->op == IS_XMLELEMENT)
2418 {
2419 ListCell *lc2;
2420
2421 foreach(lc2, newx->arg_names)
2422 {
2423 if (strcmp(argname, strVal(lfirst(lc2))) == 0)
2424 ereport(ERROR,
2426 errmsg("XML attribute name \"%s\" appears more than once",
2427 argname),
2428 parser_errposition(pstate, r->location)));
2429 }
2430 }
2431
2432 newx->named_args = lappend(newx->named_args, expr);
2433 newx->arg_names = lappend(newx->arg_names, makeString(argname));
2434 }
2435
2436 /* The other arguments are of varying types depending on the function */
2437 newx->args = NIL;
2438 i = 0;
2439 foreach(lc, x->args)
2440 {
2441 Node *e = (Node *) lfirst(lc);
2442 Node *newe;
2443
2444 newe = transformExprRecurse(pstate, e);
2445 switch (x->op)
2446 {
2447 case IS_XMLCONCAT:
2449 "XMLCONCAT");
2450 break;
2451 case IS_XMLELEMENT:
2452 /* no coercion necessary */
2453 break;
2454 case IS_XMLFOREST:
2456 "XMLFOREST");
2457 break;
2458 case IS_XMLPARSE:
2459 if (i == 0)
2461 "XMLPARSE");
2462 else
2463 newe = coerce_to_boolean(pstate, newe, "XMLPARSE");
2464 break;
2465 case IS_XMLPI:
2467 "XMLPI");
2468 break;
2469 case IS_XMLROOT:
2470 if (i == 0)
2472 "XMLROOT");
2473 else if (i == 1)
2475 "XMLROOT");
2476 else
2478 "XMLROOT");
2479 break;
2480 case IS_XMLSERIALIZE:
2481 /* not handled here */
2482 Assert(false);
2483 break;
2484 case IS_DOCUMENT:
2486 "IS DOCUMENT");
2487 break;
2488 }
2489 newx->args = lappend(newx->args, newe);
2490 i++;
2491 }
2492
2493 return (Node *) newx;
2494}
int x
Definition isn.c:75
char * FigureColname(Node *node)
@ IS_DOCUMENT
Definition primnodes.h:1612
@ IS_XMLFOREST
Definition primnodes.h:1607
@ IS_XMLCONCAT
Definition primnodes.h:1605
@ IS_XMLPI
Definition primnodes.h:1609
@ IS_XMLPARSE
Definition primnodes.h:1608
@ IS_XMLSERIALIZE
Definition primnodes.h:1611
@ IS_XMLROOT
Definition primnodes.h:1610
@ IS_XMLELEMENT
Definition primnodes.h:1606
char * map_sql_identifier_to_xml_name(const char *ident, bool fully_escaped, bool escape_period)
Definition xml.c:2418

References Assert, coerce_to_boolean(), coerce_to_specific_type(), ereport, errcode(), errmsg(), ERROR, fb(), FigureColname(), i, IS_DOCUMENT, IS_XMLCONCAT, IS_XMLELEMENT, IS_XMLFOREST, IS_XMLPARSE, IS_XMLPI, IS_XMLROOT, IS_XMLSERIALIZE, IsA, lappend(), lfirst, lfirst_node, ResTarget::location, makeNode, makeString(), map_sql_identifier_to_xml_name(), ResTarget::name, NIL, parser_errposition(), strVal, transformExprRecurse(), ResTarget::val, and x.

Referenced by transformExprRecurse().

◆ transformXmlSerialize()

static Node * transformXmlSerialize ( ParseState pstate,
XmlSerialize xs 
)
static

Definition at line 2497 of file parse_expr.c.

2498{
2499 Node *result;
2500 XmlExpr *xexpr;
2503
2504 xexpr = makeNode(XmlExpr);
2505 xexpr->op = IS_XMLSERIALIZE;
2506 xexpr->args = list_make1(coerce_to_specific_type(pstate,
2507 transformExprRecurse(pstate, xs->expr),
2508 XMLOID,
2509 "XMLSERIALIZE"));
2510
2511 typenameTypeIdAndMod(pstate, xs->typeName, &targetType, &targetTypmod);
2512
2513 xexpr->xmloption = xs->xmloption;
2514 xexpr->indent = xs->indent;
2515 xexpr->location = xs->location;
2516 /* We actually only need these to be able to parse back the expression. */
2517 xexpr->type = targetType;
2518 xexpr->typmod = targetTypmod;
2519
2520 /*
2521 * The actual target type is determined this way. SQL allows char and
2522 * varchar as target types. We allow anything that can be cast implicitly
2523 * from text. This way, user-defined text-like data types automatically
2524 * fit in.
2525 */
2526 result = coerce_to_target_type(pstate, (Node *) xexpr,
2530 -1);
2531 if (result == NULL)
2532 ereport(ERROR,
2534 errmsg("cannot cast XMLSERIALIZE result to %s",
2536 parser_errposition(pstate, xexpr->location)));
2537 return result;
2538}
List * args
Definition primnodes.h:1633
ParseLoc location
Definition primnodes.h:1642
bool indent
Definition primnodes.h:1637
XmlExprOp op
Definition primnodes.h:1625

References XmlExpr::args, COERCE_IMPLICIT_CAST, coerce_to_specific_type(), coerce_to_target_type(), COERCION_IMPLICIT, ereport, errcode(), errmsg(), ERROR, fb(), format_type_be(), XmlExpr::indent, IS_XMLSERIALIZE, list_make1, XmlExpr::location, makeNode, XmlExpr::op, parser_errposition(), transformExprRecurse(), and typenameTypeIdAndMod().

Referenced by transformExprRecurse().

◆ unknown_attribute()

static void unknown_attribute ( ParseState pstate,
Node relref,
const char attname,
int  location 
)
static

Definition at line 392 of file parse_expr.c.

394{
396
397 if (IsA(relref, Var) &&
398 ((Var *) relref)->varattno == InvalidAttrNumber)
399 {
400 /* Reference the RTE by alias not by actual table name */
402 ((Var *) relref)->varno,
403 ((Var *) relref)->varlevelsup);
406 errmsg("column %s.%s does not exist",
407 rte->eref->aliasname, attname),
408 parser_errposition(pstate, location)));
409 }
410 else
411 {
412 /* Have to do it by reference to the type of the expression */
414
415 if (ISCOMPLEX(relTypeId))
418 errmsg("column \"%s\" not found in data type %s",
420 parser_errposition(pstate, location)));
421 else if (relTypeId == RECORDOID)
424 errmsg("could not identify column \"%s\" in record data type",
425 attname),
426 parser_errposition(pstate, location)));
427 else
430 errmsg("column notation .%s applied to type %s, "
431 "which is not a composite type",
433 parser_errposition(pstate, location)));
434 }
435}
#define InvalidAttrNumber
Definition attnum.h:23
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
#define ISCOMPLEX(typeid)
Definition parse_type.h:59
NameData attname

References attname, ereport, errcode(), errmsg(), ERROR, exprType(), fb(), format_type_be(), GetRTEByRangeTablePosn(), InvalidAttrNumber, IsA, ISCOMPLEX, and parser_errposition().

Referenced by transformIndirection().

◆ ValidJsonBehaviorDefaultExpr()

static bool ValidJsonBehaviorDefaultExpr ( Node expr,
void context 
)
static

Definition at line 4710 of file parse_expr.c.

4711{
4712 if (expr == NULL)
4713 return false;
4714
4715 switch (nodeTag(expr))
4716 {
4717 /* Acceptable expression nodes */
4718 case T_Const:
4719 case T_FuncExpr:
4720 case T_OpExpr:
4721 return true;
4722
4723 /* Acceptable iff arg of the following nodes is one of the above */
4724 case T_CoerceViaIO:
4725 case T_CoerceToDomain:
4726 case T_ArrayCoerceExpr:
4728 case T_RelabelType:
4729 case T_CollateExpr:
4731 context);
4732 default:
4733 break;
4734 }
4735
4736 return false;
4737}
#define expression_tree_walker(n, w, c)
Definition nodeFuncs.h:153

References expression_tree_walker, fb(), nodeTag, and ValidJsonBehaviorDefaultExpr().

Referenced by transformJsonBehavior(), and ValidJsonBehaviorDefaultExpr().

Variable Documentation

◆ Transform_null_equals

bool Transform_null_equals = false

Definition at line 45 of file parse_expr.c.

Referenced by transformAExprOp().