/* Save and restore identity of expression type we're parsing */
Assert(exprKind != EXPR_KIND_NONE);
sv_expr_kind = pstate->p_expr_kind;
pstate->p_expr_kind = exprKind;
/* Guard against stack overflow due to overly complex expressions */
check_stack_depth();
switch (nodeTag(expr))
{ case T_ColumnRef:
result = transformColumnRef(pstate, (ColumnRef *) expr); break;
case T_ParamRef:
result = transformParamRef(pstate, (ParamRef *) expr); break;
case T_A_Const:
result = (Node *) make_const(pstate, (A_Const *) expr); break;
case T_A_Indirection:
result = transformIndirection(pstate, (A_Indirection *) expr); break;
case T_A_ArrayExpr:
result = transformArrayExpr(pstate, (A_ArrayExpr *) expr,
InvalidOid, InvalidOid, -1); break;
case T_TypeCast:
result = transformTypeCast(pstate, (TypeCast *) expr); break;
case T_CollateClause:
result = transformCollateClause(pstate, (CollateClause *) expr); break;
case T_A_Expr:
{
A_Expr *a = (A_Expr *) expr;
switch (a->kind)
{ case AEXPR_OP:
result = transformAExprOp(pstate, a); break; case AEXPR_OP_ANY:
result = transformAExprOpAny(pstate, a); break; case AEXPR_OP_ALL:
result = transformAExprOpAll(pstate, a); break; case AEXPR_DISTINCT: case AEXPR_NOT_DISTINCT:
result = transformAExprDistinct(pstate, a); break; case AEXPR_NULLIF:
result = transformAExprNullIf(pstate, a); break; case AEXPR_IN:
result = transformAExprIn(pstate, a); break; case AEXPR_LIKE: case AEXPR_ILIKE: case AEXPR_SIMILAR: /* we can transform these just like AEXPR_OP */
result = transformAExprOp(pstate, a); break; case AEXPR_BETWEEN: case AEXPR_NOT_BETWEEN: case AEXPR_BETWEEN_SYM: case AEXPR_NOT_BETWEEN_SYM:
result = transformAExprBetween(pstate, a); break; default:
elog(ERROR, "unrecognized A_Expr kind: %d", a->kind);
result = NULL; /* keep compiler quiet */ break;
} break;
}
case T_BoolExpr:
result = transformBoolExpr(pstate, (BoolExpr *) expr); break;
case T_FuncCall:
result = transformFuncCall(pstate, (FuncCall *) expr); break;
case T_MultiAssignRef:
result = transformMultiAssignRef(pstate, (MultiAssignRef *) expr); break;
case T_GroupingFunc:
result = transformGroupingFunc(pstate, (GroupingFunc *) expr); break;
case T_MergeSupportFunc:
result = transformMergeSupportFunc(pstate,
(MergeSupportFunc *) expr); break;
case T_NamedArgExpr:
{
NamedArgExpr *na = (NamedArgExpr *) expr;
case T_SubLink:
result = transformSubLink(pstate, (SubLink *) expr); break;
case T_CaseExpr:
result = transformCaseExpr(pstate, (CaseExpr *) expr); break;
case T_RowExpr:
result = transformRowExpr(pstate, (RowExpr *) expr, false); break;
case T_CoalesceExpr:
result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr); break;
case T_MinMaxExpr:
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr); break;
case T_SQLValueFunction:
result = transformSQLValueFunction(pstate,
(SQLValueFunction *) expr); break;
case T_XmlExpr:
result = transformXmlExpr(pstate, (XmlExpr *) expr); break;
case T_XmlSerialize:
result = transformXmlSerialize(pstate, (XmlSerialize *) expr); break;
case T_NullTest:
{
NullTest *n = (NullTest *) expr;
n->arg = (Expr *) transformExprRecurse(pstate, (Node *) n->arg); /* the argument can be any type, so don't coerce it */
n->argisrow = type_is_rowtype(exprType((Node *) n->arg));
result = expr; break;
}
case T_BooleanTest:
result = transformBooleanTest(pstate, (BooleanTest *) expr); break;
case T_CurrentOfExpr:
result = transformCurrentOfExpr(pstate, (CurrentOfExpr *) expr); break;
/* *InallplaceswhereDEFAULTislegal,thecallershouldhave *processeditratherthanpassingittotransformExpr().
*/ case T_SetToDefault:
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("DEFAULT is not allowed in this context"),
parser_errposition(pstate,
((SetToDefault *) expr)->location))); break;
/* *CaseTestExprdoesn'trequireanyprocessing;itisonly *injectedintoparsetreesinafully-formedstate. * *OrdinarilyweshouldnotseeaVarhere,butitisconvenient *fortransformJoinUsingClause()tocreateuntransformedoperator *treescontainingalready-transformedVars.Thebest *alternativewouldbetodeconstructandreconstructcolumn *references,whichseemsexpensivelypointless.Soallowit.
*/ case T_CaseTestExpr: case T_Var:
{
result = (Node *) expr; break;
}
case T_JsonObjectConstructor:
result = transformJsonObjectConstructor(pstate, (JsonObjectConstructor *) expr); break;
case T_JsonArrayConstructor:
result = transformJsonArrayConstructor(pstate, (JsonArrayConstructor *) expr); break;
case T_JsonArrayQueryConstructor:
result = transformJsonArrayQueryConstructor(pstate, (JsonArrayQueryConstructor *) expr); break;
case T_JsonObjectAgg:
result = transformJsonObjectAgg(pstate, (JsonObjectAgg *) expr); break;
case T_JsonArrayAgg:
result = transformJsonArrayAgg(pstate, (JsonArrayAgg *) expr); break;
case T_JsonIsPredicate:
result = transformJsonIsPredicate(pstate, (JsonIsPredicate *) expr); break;
case T_JsonParseExpr:
result = transformJsonParseExpr(pstate, (JsonParseExpr *) expr); break;
case T_JsonScalarExpr:
result = transformJsonScalarExpr(pstate, (JsonScalarExpr *) expr); break;
case T_JsonSerializeExpr:
result = transformJsonSerializeExpr(pstate, (JsonSerializeExpr *) expr); break;
case T_JsonFuncExpr:
result = transformJsonFuncExpr(pstate, (JsonFuncExpr *) expr); break;
default: /* should not reach here */
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
result = NULL; /* keep compiler quiet */ break;
}
if (IsA(relref, Var) &&
((Var *) relref)->varattno == InvalidAttrNumber)
{ /* Reference the RTE by alias not by actual table name */
rte = GetRTEByRangeTablePosn(pstate,
((Var *) relref)->varno,
((Var *) relref)->varlevelsup);
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column %s.%s does not exist",
rte->eref->aliasname, attname),
parser_errposition(pstate, location)));
} else
{ /* Have to do it by reference to the type of the expression */
Oid relTypeId = exprType(relref);
if (ISCOMPLEX(relTypeId))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" not found in data type %s",
attname, format_type_be(relTypeId)),
parser_errposition(pstate, location))); elseif (relTypeId == RECORDOID)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("could not identify column \"%s\" in record data type",
attname),
parser_errposition(pstate, location))); else
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("column notation .%s applied to type %s, " "which is not a composite type",
attname, format_type_be(relTypeId)),
parser_errposition(pstate, location)));
}
}
if (IsA(n, A_Indices))
subscripts = lappend(subscripts, n); elseif (IsA(n, A_Star))
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row expansion via \"*\" is not supported here"),
parser_errposition(pstate, location)));
} else
{
Node *newresult;
Assert(IsA(n, String));
/* process subscripts before this field selection */ if (subscripts)
result = (Node *) transformContainerSubscripts(pstate,
result,
exprType(result),
exprTypmod(result),
subscripts, false);
subscripts = NIL;
newresult = ParseFuncOrColumn(pstate,
list_make1(n),
list_make1(result),
last_srf,
NULL, false,
location); if (newresult == NULL)
unknown_attribute(pstate, result, strVal(n), location);
result = newresult;
}
} /* process trailing subscripts, if any */ if (subscripts)
result = (Node *) transformContainerSubscripts(pstate,
result,
exprType(result),
exprTypmod(result),
subscripts, false);
/* *Checktoseeifthecolumnreferenceisinaninvalidplacewithinthe *query.Weallowcolumnreferencesinmostplaces,exceptindefault *expressionsandpartitionboundexpressions.
*/
err = NULL; switch (pstate->p_expr_kind)
{ case EXPR_KIND_NONE:
Assert(false); /* can't happen */ break; case EXPR_KIND_OTHER: case EXPR_KIND_JOIN_ON: case EXPR_KIND_JOIN_USING: case EXPR_KIND_FROM_SUBSELECT: case EXPR_KIND_FROM_FUNCTION: case EXPR_KIND_WHERE: case EXPR_KIND_POLICY: case EXPR_KIND_HAVING: case EXPR_KIND_FILTER: case EXPR_KIND_WINDOW_PARTITION: case EXPR_KIND_WINDOW_ORDER: case EXPR_KIND_WINDOW_FRAME_RANGE: case EXPR_KIND_WINDOW_FRAME_ROWS: case EXPR_KIND_WINDOW_FRAME_GROUPS: case EXPR_KIND_SELECT_TARGET: case EXPR_KIND_INSERT_TARGET: case EXPR_KIND_UPDATE_SOURCE: case EXPR_KIND_UPDATE_TARGET: case EXPR_KIND_MERGE_WHEN: case EXPR_KIND_GROUP_BY: case EXPR_KIND_ORDER_BY: case EXPR_KIND_DISTINCT_ON: case EXPR_KIND_LIMIT: case EXPR_KIND_OFFSET: case EXPR_KIND_RETURNING: case EXPR_KIND_MERGE_RETURNING: case EXPR_KIND_VALUES: case EXPR_KIND_VALUES_SINGLE: case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK: case EXPR_KIND_FUNCTION_DEFAULT: case EXPR_KIND_INDEX_EXPRESSION: case EXPR_KIND_INDEX_PREDICATE: case EXPR_KIND_STATS_EXPRESSION: case EXPR_KIND_ALTER_COL_TRANSFORM: case EXPR_KIND_EXECUTE_PARAMETER: case EXPR_KIND_TRIGGER_WHEN: case EXPR_KIND_PARTITION_EXPRESSION: case EXPR_KIND_CALL_ARGUMENT: case EXPR_KIND_COPY_WHERE: case EXPR_KIND_GENERATED_COLUMN: case EXPR_KIND_CYCLE_MARK: /* okay */ break;
case EXPR_KIND_COLUMN_DEFAULT:
err = _("cannot use column reference in DEFAULT expression"); break; case EXPR_KIND_PARTITION_BOUND:
err = _("cannot use column reference in partition bound expression"); break;
/* Try to identify as a column of the nsitem */
node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
cref->location); if (node == NULL)
{ /* Try it as a function call on the whole row */
node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
node = ParseFuncOrColumn(pstate,
list_make1(makeString(colname)),
list_make1(node),
pstate->p_last_srf,
NULL, false,
cref->location);
} break;
} default:
crerr = CRERR_TOO_MANY; /* too many dotted names */ break;
}
/* *ThecoreparserknowsnothingaboutParams.Ifahookissupplied, *callit.Ifnot,orifthehookreturnsNULL,throwagenericerror.
*/ if (pstate->p_paramref_hook != NULL)
result = pstate->p_paramref_hook(pstate, pref); else
result = NULL;
if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_PARAMETER),
errmsg("there is no parameter $%d", pref->number),
parser_errposition(pstate, pref->location)));
return result;
}
/* Test whether an a_expr is a plain NULL constant or not */ staticbool
exprIsNullConstant(Node *arg)
{ if (arg && IsA(arg, A_Const))
{
A_Const *con = (A_Const *) arg;
/* *IfeitherinputisanundecoratedNULLliteral,transformtoaNullTest *ontheotherinput.That'ssimplertoprocessthanafullDistinctExpr, *anditavoidsneedingtorequirethatthedatatypehavean=operator.
*/ if (exprIsNullConstant(rexpr)) return make_nulltest_from_distinct(pstate, a, lexpr); if (exprIsNullConstant(lexpr)) return make_nulltest_from_distinct(pstate, a, rexpr);
result = (OpExpr *) make_op(pstate,
a->name,
lexpr,
rexpr,
pstate->p_last_srf,
a->location);
/* *Thecomparisonoperatoritselfshouldyieldboolean...
*/ if (result->opresulttype != BOOLOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), /* translator: %s is name of a SQL construct, eg NULLIF */
errmsg("%s requires = operator to yield boolean", "NULLIF"),
parser_errposition(pstate, a->location))); if (result->opretset)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), /* translator: %s is name of a SQL construct, eg NULLIF */
errmsg("%s must not return a set", "NULLIF"),
parser_errposition(pstate, a->location)));
/* *ScalarArrayOpExprisonlygoingtobeusefulifthere'smorethanone *non-Varrighthanditem.
*/ if (list_length(rnonvars) > 1)
{
List *allexprs;
Oid scalar_type;
Oid array_type;
/* We have to verify that the selected type actually works */ if (OidIsValid(scalar_type) &&
!verify_common_type(scalar_type, allexprs))
scalar_type = InvalidOid;
while (parent_pstate &&
parent_pstate->p_expr_kind != EXPR_KIND_MERGE_RETURNING)
parent_pstate = parent_pstate->parentParseState;
if (!parent_pstate)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("MERGE_ACTION() can only be used in the RETURNING list of a MERGE command"),
parser_errposition(pstate, f->location));
}
/* We should only see this in first-stage processing of UPDATE tlists */
Assert(pstate->p_expr_kind == EXPR_KIND_UPDATE_SOURCE);
/* We only need to transform the source if this is the first column */ if (maref->colno == 1)
{ /* *Fornow,weonlyallowEXPRSubLinksandRowExprsasthesourceof *anUPDATEmultiassignment.Thisissufficienttocoverinteresting *cases;atworst,someonewouldhavetowrite(SELECT*FROMexpr) *toexpandacomposite-returningexpressionofanotherform.
*/ if (IsA(maref->source, SubLink) &&
((SubLink *) maref->source)->subLinkType == EXPR_SUBLINK)
{ /* Relabel it as a MULTIEXPR_SUBLINK */
sublink = (SubLink *) maref->source;
sublink->subLinkType = MULTIEXPR_SUBLINK; /* And transform it */
sublink = (SubLink *) transformExprRecurse(pstate,
(Node *) sublink);
qtree = castNode(Query, sublink->subselect);
/* Check subquery returns required number of columns */ if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("number of columns does not match number of values"),
parser_errposition(pstate, sublink->location)));
/* Check it returns required number of columns */ if (list_length(rexpr->args) != maref->ncolumns)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("number of columns does not match number of values"),
parser_errposition(pstate, rexpr->location)));
/* *Temporarilyappendittop_multiassign_exprs,sowecangetit *backwhenwecomebackhereforadditionalcolumns.
*/
tle = makeTargetEntry((Expr *) rexpr, 0, NULL, true);
pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs,
tle);
} else
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression"),
parser_errposition(pstate, exprLocation(maref->source))));
} else
{ /* *Secondorlatercolumninamultiassignment.Re-fetchthe *transformedSubLinkorRowExpr,whichweassumeisstillthelast *entryinp_multiassign_exprs.
*/
Assert(pstate->p_multiassign_exprs != NIL);
tle = (TargetEntry *) llast(pstate->p_multiassign_exprs);
}
/* *Emittheappropriateoutputexpressionforthecurrentcolumn
*/ if (IsA(tle->expr, SubLink))
{
Param *param;
/* Build a Param representing the current subquery output column */
tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1);
Assert(!tle->resjunk);
ptype = select_common_type(pstate, resultexprs, "CASE", NULL);
Assert(OidIsValid(ptype));
newc->casetype = ptype; /* casecollid will be set by parse_collate.c */
/* Convert default result clause, if necessary */
newc->defresult = (Expr *)
coerce_to_common_type(pstate,
(Node *) newc->defresult,
ptype, "CASE/ELSE");
/* if any subexpression contained a SRF, complain */ if (pstate->p_last_srf != last_srf)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is name of a SQL construct, eg GROUP BY */
errmsg("set-returning functions are not allowed in %s", "CASE"),
errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
parser_errposition(pstate,
exprLocation(pstate->p_last_srf))));
/* *Checktoseeifthesublinkisinaninvalidplacewithinthequery.We *allowsublinkseverywhereinSELECT/INSERT/UPDATE/DELETE/MERGE,but *generallynotinutilitystatements.
*/
err = NULL; switch (pstate->p_expr_kind)
{ case EXPR_KIND_NONE:
Assert(false); /* can't happen */ break; case EXPR_KIND_OTHER: /* Accept sublink here; caller must throw error if wanted */ break; case EXPR_KIND_JOIN_ON: case EXPR_KIND_JOIN_USING: case EXPR_KIND_FROM_SUBSELECT: case EXPR_KIND_FROM_FUNCTION: case EXPR_KIND_WHERE: case EXPR_KIND_POLICY: case EXPR_KIND_HAVING: case EXPR_KIND_FILTER: case EXPR_KIND_WINDOW_PARTITION: case EXPR_KIND_WINDOW_ORDER: case EXPR_KIND_WINDOW_FRAME_RANGE: case EXPR_KIND_WINDOW_FRAME_ROWS: case EXPR_KIND_WINDOW_FRAME_GROUPS: case EXPR_KIND_SELECT_TARGET: case EXPR_KIND_INSERT_TARGET: case EXPR_KIND_UPDATE_SOURCE: case EXPR_KIND_UPDATE_TARGET: case EXPR_KIND_MERGE_WHEN: case EXPR_KIND_GROUP_BY: case EXPR_KIND_ORDER_BY: case EXPR_KIND_DISTINCT_ON: case EXPR_KIND_LIMIT: case EXPR_KIND_OFFSET: case EXPR_KIND_RETURNING: case EXPR_KIND_MERGE_RETURNING: case EXPR_KIND_VALUES: case EXPR_KIND_VALUES_SINGLE: case EXPR_KIND_CYCLE_MARK: /* okay */ break; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK:
err = _("cannot use subquery in check constraint"); break; case EXPR_KIND_COLUMN_DEFAULT: case EXPR_KIND_FUNCTION_DEFAULT:
err = _("cannot use subquery in DEFAULT expression"); break; case EXPR_KIND_INDEX_EXPRESSION:
err = _("cannot use subquery in index expression"); break; case EXPR_KIND_INDEX_PREDICATE:
err = _("cannot use subquery in index predicate"); break; case EXPR_KIND_STATS_EXPRESSION:
err = _("cannot use subquery in statistics expression"); break; case EXPR_KIND_ALTER_COL_TRANSFORM:
err = _("cannot use subquery in transform expression"); break; case EXPR_KIND_EXECUTE_PARAMETER:
err = _("cannot use subquery in EXECUTE parameter"); break; case EXPR_KIND_TRIGGER_WHEN:
err = _("cannot use subquery in trigger WHEN condition"); break; case EXPR_KIND_PARTITION_BOUND:
err = _("cannot use subquery in partition bound"); break; case EXPR_KIND_PARTITION_EXPRESSION:
err = _("cannot use subquery in partition key expression"); break; case EXPR_KIND_CALL_ARGUMENT:
err = _("cannot use subquery in CALL argument"); break; case EXPR_KIND_COPY_WHERE:
err = _("cannot use subquery in COPY FROM WHERE condition"); break; case EXPR_KIND_GENERATED_COLUMN:
err = _("cannot use subquery in column generation expression"); break;
/* *Wecouldrelyonmake_row_comparison_optocomplainifthelist *lengthsdiffer,butweprefertogenerateamorespecificerror *message.
*/ if (list_length(left_list) < list_length(right_list))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery has too many columns"),
parser_errposition(pstate, sublink->location))); if (list_length(left_list) > list_length(right_list))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery has too few columns"),
parser_errposition(pstate, sublink->location)));
/* *Selectatargettypefortheelements. * *Ifwehaven'tbeengivenatargetarraytype,wemusttrytodeducea *commontypebasedonthetypesoftheindividualelementspresent.
*/ if (OidIsValid(array_type))
{ /* Caller must ensure array_type matches element_type */
Assert(OidIsValid(element_type));
coerce_type = (newa->multidims ? array_type : element_type);
coerce_hard = true;
} else
{ /* Can't handle an empty array without a target type */ if (newelems == NIL)
ereport(ERROR,
(errcode(ERRCODE_INDETERMINATE_DATATYPE),
errmsg("cannot determine type of empty array"),
errhint("Explicitly cast to the desired type, " "for example ARRAY[]::integer[]."),
parser_errposition(pstate, a->location)));
/* Select a common type for the elements */
coerce_type = select_common_type(pstate, newelems, "ARRAY", NULL);
if (newa->multidims)
{
array_type = coerce_type;
element_type = get_element_type(array_type); if (!OidIsValid(element_type))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find element type for data type %s",
format_type_be(array_type)),
parser_errposition(pstate, a->location)));
} else
{
element_type = coerce_type;
array_type = get_array_type(element_type); if (!OidIsValid(array_type))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s",
format_type_be(element_type)),
parser_errposition(pstate, a->location)));
}
coerce_hard = false;
}
/* Transform the field expressions */
newr->args = transformExpressionList(pstate, r->args,
pstate->p_expr_kind, allowDefault);
/* Disallow more columns than will fit in a tuple */ if (list_length(newr->args) > MaxTupleAttributeNumber)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_COLUMNS),
errmsg("ROW expressions can have at most %d entries",
MaxTupleAttributeNumber),
parser_errposition(pstate, r->location)));
/* Barring later casting, we consider the type RECORD */
newr->row_typeid = RECORDOID;
newr->row_format = COERCE_IMPLICIT_CAST;
/* ROW() has anonymous columns, so invent some field names */
newr->colnames = NIL; for (fnum = 1; fnum <= list_length(newr->args); fnum++)
{
snprintf(fname, sizeof(fname), "f%d", fnum);
newr->colnames = lappend(newr->colnames, makeString(pstrdup(fname)));
}
/* if any subexpression contained a SRF, complain */ if (pstate->p_last_srf != last_srf)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is name of a SQL construct, eg GROUP BY */
errmsg("set-returning functions are not allowed in %s", "COALESCE"),
errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
parser_errposition(pstate,
exprLocation(pstate->p_last_srf))));
if (r->name)
argname = map_sql_identifier_to_xml_name(r->name, false, false); elseif (IsA(r->val, ColumnRef))
argname = map_sql_identifier_to_xml_name(FigureColname(r->val), true, false); else
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
x->op == IS_XMLELEMENT
? errmsg("unnamed XML attribute value must be a column reference")
: errmsg("unnamed XML element value must be a column reference"),
parser_errposition(pstate, r->location)));
argname = NULL; /* keep compiler quiet */
}
/* reject duplicate argnames in XMLELEMENT only */ if (x->op == IS_XMLELEMENT)
{
ListCell *lc2;
foreach(lc2, newx->arg_names)
{ if (strcmp(argname, strVal(lfirst(lc2))) == 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("XML attribute name \"%s\" appears more than once",
argname),
parser_errposition(pstate, r->location)));
}
}
/* The other arguments are of varying types depending on the function */
newx->args = NIL;
i = 0;
foreach(lc, x->args)
{
Node *e = (Node *) lfirst(lc);
Node *newe;
newe = transformExprRecurse(pstate, e); switch (x->op)
{ case IS_XMLCONCAT:
newe = coerce_to_specific_type(pstate, newe, XMLOID, "XMLCONCAT"); break; case IS_XMLELEMENT: /* no coercion necessary */ break; case IS_XMLFOREST:
newe = coerce_to_specific_type(pstate, newe, XMLOID, "XMLFOREST"); break; case IS_XMLPARSE: if (i == 0)
newe = coerce_to_specific_type(pstate, newe, TEXTOID, "XMLPARSE"); else
newe = coerce_to_boolean(pstate, newe, "XMLPARSE"); break; case IS_XMLPI:
newe = coerce_to_specific_type(pstate, newe, TEXTOID, "XMLPI"); break; case IS_XMLROOT: if (i == 0)
newe = coerce_to_specific_type(pstate, newe, XMLOID, "XMLROOT"); elseif (i == 1)
newe = coerce_to_specific_type(pstate, newe, TEXTOID, "XMLROOT"); else
newe = coerce_to_specific_type(pstate, newe, INT4OID, "XMLROOT"); break; case IS_XMLSERIALIZE: /* not handled here */
Assert(false); break; case IS_DOCUMENT:
newe = coerce_to_specific_type(pstate, newe, XMLOID, "IS DOCUMENT"); break;
}
newx->args = lappend(newx->args, newe);
i++;
}
xexpr->xmloption = xs->xmloption;
xexpr->indent = xs->indent;
xexpr->location = xs->location; /* We actually only need these to be able to parse back the expression. */
xexpr->type = targetType;
xexpr->typmod = targetTypmod;
/* *Theactualtargettypeisdeterminedthisway.SQLallowscharand *varcharastargettypes.Weallowanythingthatcanbecastimplicitly *fromtext.Thisway,user-definedtext-likedatatypesautomatically *fitin.
*/
result = coerce_to_target_type(pstate, (Node *) xexpr,
TEXTOID, targetType, targetTypmod,
COERCION_IMPLICIT,
COERCE_IMPLICIT_CAST,
-1); if (result == NULL)
ereport(ERROR,
(errcode(ERRCODE_CANNOT_COERCE),
errmsg("cannot cast XMLSERIALIZE result to %s",
format_type_be(targetType)),
parser_errposition(pstate, xexpr->location))); return result;
}
static Node *
transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
{ /* CURRENT OF can only appear at top level of UPDATE/DELETE */
Assert(pstate->p_target_nsitem != NULL);
cexpr->cvarno = pstate->p_target_nsitem->p_rtindex;
/* *ChecktoseeifthecursornamematchesaparameteroftypeREFCURSOR. *Ifso,replacetherawnamereferencewithaparameterreference.(This *isahackfortheconvenienceofplpgsql.)
*/ if (cexpr->cursor_name != NULL) /* in case already transformed */
{
ColumnRef *cref = makeNode(ColumnRef);
Node *node = NULL;
/* Build an unqualified ColumnRef with the given name */
cref->fields = list_make1(makeString(cexpr->cursor_name));
cref->location = -1;
/* See if there is a translation available from a parser hook */ if (pstate->p_pre_columnref_hook != NULL)
node = pstate->p_pre_columnref_hook(pstate, cref); if (node == NULL && pstate->p_post_columnref_hook != NULL)
node = pstate->p_post_columnref_hook(pstate, cref, NULL);
if (p->paramkind == PARAM_EXTERN &&
p->paramtype == REFCURSOROID)
{ /* Matches, so convert CURRENT OF to a param reference */
cexpr->cursor_name = NULL;
cexpr->cursor_param = p->paramid;
}
}
}
/* *Theunknowntypeisnotcollatable,butcoerce_type()takescareofit *separately,sowe'llletitgohere.
*/ if (!type_is_collatable(argtype) && argtype != UNKNOWNOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("collations are not supported by type %s",
format_type_be(argtype)),
parser_errposition(pstate, c->location)));
/* *Transforma"rowcompare-oprow"construct * *Theinputsarelistsofalready-transformedexpressions. *Aswithcoerce_type,pstatemaybeNULLifnospecialunknown-Param *processingiswanted. * *TheoutputmaybeasingleOpExpr,anANDorORcombinationofOpExprs, *oraRowCompareExpr.Inallcasesitisguaranteedtoreturnboolean. *TheAND,OR,andRowCompareExprcasesfurtherimplythingsaboutthe *behavioroftheoperators(ie,theybehaveas=,<>,or<<=>>=).
*/ static Node *
make_row_comparison_op(ParseState *pstate, List *opname,
List *largs, List *rargs, int location)
{
RowCompareExpr *rcexpr;
CompareType cmptype;
List *opexprs;
List *opnos;
List *opfamilies;
ListCell *l,
*r;
List **opinfo_lists;
Bitmapset *cmptypes; int nopers; int i;
nopers = list_length(largs); if (nopers != list_length(rargs))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unequal number of entries in row expressions"),
parser_errposition(pstate, location)));
/* *Wecan'tcomparezero-lengthrowsbecausethereisnoprincipledbasis *forfiguringoutwhattheoperatoris.
*/ if (nopers == 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot compare rows of zero length"),
parser_errposition(pstate, location)));
this_cmptypes = bms_add_member(this_cmptypes, opinfo->cmptype);
} if (i == 0)
cmptypes = this_cmptypes; else
cmptypes = bms_int_members(cmptypes, this_cmptypes);
i++;
}
/* *Iftherearemultiplecommoninterpretations,wemayuseanyoneof *them...thiscodingarbitrarilypicksthelowestcomparisontype *number.
*/
i = bms_next_member(cmptypes, -1); if (i < 0)
{ /* No common interpretation, so fail */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine interpretation of row comparison operator %s",
strVal(llast(opname))),
errhint("Row comparison operators must be associated with btree operator families."),
parser_errposition(pstate, location)));
}
cmptype = (CompareType) i;
/* *Transforma"rowISDISTINCTFROMrow"construct * *TheinputRowExprsarealreadytransformed
*/ static Node *
make_row_distinct_op(ParseState *pstate, List *opname,
RowExpr *lrow, RowExpr *rrow, int location)
{
Node *result = NULL;
List *largs = lrow->args;
List *rargs = rrow->args;
ListCell *l,
*r;
if (list_length(largs) != list_length(rargs))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unequal number of entries in row expressions"),
parser_errposition(pstate, location)));
cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg, location); if (result == NULL)
result = cmp; else
result = (Node *) makeBoolExpr(OR_EXPR,
list_make2(result, cmp),
location);
}
if (result == NULL)
{ /* zero-length rows? Generate constant FALSE */
result = makeBoolConst(false, false);
}
return result;
}
/* *makethenodeforanISDISTINCTFROMoperator
*/ static Expr *
make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location)
{
Expr *result;
result = make_op(pstate, opname, ltree, rtree,
pstate->p_last_srf, location); if (((OpExpr *) result)->opresulttype != BOOLOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), /* translator: %s is name of a SQL construct, eg NULLIF */
errmsg("%s requires = operator to yield boolean", "IS DISTINCT FROM"),
parser_errposition(pstate, location))); if (((OpExpr *) result)->opretset)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), /* translator: %s is name of a SQL construct, eg NULLIF */
errmsg("%s must not return a set", "IS DISTINCT FROM"),
parser_errposition(pstate, location)));
nt->arg = (Expr *) transformExprRecurse(pstate, arg); /* the argument can be any type, so don't coerce it */ if (distincta->kind == AEXPR_NOT_DISTINCT)
nt->nulltesttype = IS_NULL; else
nt->nulltesttype = IS_NOT_NULL; /* argisrow = false is correct whether or not arg is composite */
nt->argisrow = false;
nt->location = distincta->location; return (Node *) nt;
}
/* *Produceastringidentifyinganexpressionbykind. * *Note:whenpractical,useasimpleSQLkeywordfortheresult.Ifthat *doesn'tworkwell,checkcallsitestoseewhethercustomerrormessage *stringsarerequired.
*/ constchar *
ParseExprKindName(ParseExprKind exprKind)
{ switch (exprKind)
{ case EXPR_KIND_NONE: return"invalid expression context"; case EXPR_KIND_OTHER: return"extension expression"; case EXPR_KIND_JOIN_ON: return"JOIN/ON"; case EXPR_KIND_JOIN_USING: return"JOIN/USING"; case EXPR_KIND_FROM_SUBSELECT: return"sub-SELECT in FROM"; case EXPR_KIND_FROM_FUNCTION: return"function in FROM"; case EXPR_KIND_WHERE: return"WHERE"; case EXPR_KIND_POLICY: return"POLICY"; case EXPR_KIND_HAVING: return"HAVING"; case EXPR_KIND_FILTER: return"FILTER"; case EXPR_KIND_WINDOW_PARTITION: return"window PARTITION BY"; case EXPR_KIND_WINDOW_ORDER: return"window ORDER BY"; case EXPR_KIND_WINDOW_FRAME_RANGE: return"window RANGE"; case EXPR_KIND_WINDOW_FRAME_ROWS: return"window ROWS"; case EXPR_KIND_WINDOW_FRAME_GROUPS: return"window GROUPS"; case EXPR_KIND_SELECT_TARGET: return"SELECT"; case EXPR_KIND_INSERT_TARGET: return"INSERT"; case EXPR_KIND_UPDATE_SOURCE: case EXPR_KIND_UPDATE_TARGET: return"UPDATE"; case EXPR_KIND_MERGE_WHEN: return"MERGE WHEN"; case EXPR_KIND_GROUP_BY: return"GROUP BY"; case EXPR_KIND_ORDER_BY: return"ORDER BY"; case EXPR_KIND_DISTINCT_ON: return"DISTINCT ON"; case EXPR_KIND_LIMIT: return"LIMIT"; case EXPR_KIND_OFFSET: return"OFFSET"; case EXPR_KIND_RETURNING: case EXPR_KIND_MERGE_RETURNING: return"RETURNING"; case EXPR_KIND_VALUES: case EXPR_KIND_VALUES_SINGLE: return"VALUES"; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK: return"CHECK"; case EXPR_KIND_COLUMN_DEFAULT: case EXPR_KIND_FUNCTION_DEFAULT: return"DEFAULT"; case EXPR_KIND_INDEX_EXPRESSION: return"index expression"; case EXPR_KIND_INDEX_PREDICATE: return"index predicate"; case EXPR_KIND_STATS_EXPRESSION: return"statistics expression"; case EXPR_KIND_ALTER_COL_TRANSFORM: return"USING"; case EXPR_KIND_EXECUTE_PARAMETER: return"EXECUTE"; case EXPR_KIND_TRIGGER_WHEN: return"WHEN"; case EXPR_KIND_PARTITION_BOUND: return"partition bound"; case EXPR_KIND_PARTITION_EXPRESSION: return"PARTITION BY"; case EXPR_KIND_CALL_ARGUMENT: return"CALL"; case EXPR_KIND_COPY_WHERE: return"WHERE"; case EXPR_KIND_GENERATED_COLUMN: return"GENERATED AS"; case EXPR_KIND_CYCLE_MARK: return"CYCLE";
if (ve->format->format_type != JS_FORMAT_DEFAULT)
{ if (ve->format->encoding != JS_ENC_DEFAULT && exprtype != BYTEAOID)
ereport(ERROR,
errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("JSON ENCODING clause is only allowed for bytea input type"),
parser_errposition(pstate, ve->format->location));
if (exprtype == JSONOID || exprtype == JSONBOID)
format = JS_FORMAT_DEFAULT; /* do not format json[b] types */ else
format = ve->format->format_type;
} elseif (isarg)
{ /* *SpecialtreatmentforPASSINGarguments. * *PasstypessupportedbyGetJsonPathVar()/JsonItemFromDatum() *directlywithoutconvertingtojson[b].
*/ switch (exprtype)
{ case BOOLOID: case NUMERICOID: case INT2OID: case INT4OID: case INT8OID: case FLOAT4OID: case FLOAT8OID: case TEXTOID: case VARCHAROID: case DATEOID: case TIMEOID: case TIMETZOID: case TIMESTAMPOID: case TIMESTAMPTZOID: return expr;
default: if (typcategory == TYPCATEGORY_STRING) return expr; /* else convert argument to json[b] type */ break;
}
format = default_format;
} elseif (exprtype == JSONOID || exprtype == JSONBOID)
format = JS_FORMAT_DEFAULT; /* do not format json[b] types */ else
format = default_format;
/* If returning a JsonValueExpr, formatted_expr must have been set. */
Assert(!IsA(expr, JsonValueExpr) ||
((JsonValueExpr *) expr)->formatted_expr != NULL);
if (typcategory != TYPCATEGORY_STRING)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
parser_errposition(pstate, format->location),
errmsg("cannot use JSON format with non-string output types"));
}
if (output->typeName->setof)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("returning SETOF types is not supported in SQL/JSON functions"));
if (get_typtype(ret->typid) == TYPTYPE_PSEUDO)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("returning pseudo-types is not supported in SQL/JSON functions"));
if (ret->format->format_type == JS_FORMAT_DEFAULT) /* assign JSONB format when returning jsonb, or JSON format otherwise */
ret->format->format_type =
ret->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON; else
checkJsonOutputFormat(pstate, ret->format, ret->typid, allow_format);
if (have_jsonb)
{
returning->typid = JSONBOID;
returning->format->format_type = JS_FORMAT_JSONB;
} else
{ /* XXX TEXT is default by the standard, but we return JSON */
returning->typid = JSONOID;
returning->format->format_type = JS_FORMAT_JSON;
}
/* if output type is not specified or equals to function type, return */ if (!OidIsValid(returning->typid) || returning->typid == exprtype) return expr;
location = exprLocation(expr);
if (location < 0)
location = returning->format->location;
/* special case for RETURNING bytea FORMAT json */ if (returning->format->format_type == JS_FORMAT_JSON &&
returning->typid == BYTEAOID)
{ /* encode json text into bytea using pg_convert_to() */
Node *texpr = coerce_to_specific_type(pstate, expr, TEXTOID, "JSON_FUNCTION"); Const *enc = getJsonEncodingConst(returning->format);
FuncExpr *fexpr = makeFuncExpr(F_CONVERT_TO, BYTEAOID,
list_make2(texpr, enc),
InvalidOid, InvalidOid,
COERCE_EXPLICIT_CALL);
if (count_nonjunk_tlist_entries(query->targetList) != 1)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("subquery must return only one column"),
parser_errposition(pstate, ctor->location));
if (agg_ctor->over)
{ /* window function */
WindowFunc *wfunc = makeNode(WindowFunc);
wfunc->winfnoid = aggfnoid;
wfunc->wintype = aggtype; /* wincollid and inputcollid will be set by parse_collate.c */
wfunc->args = args;
wfunc->aggfilter = aggfilter;
wfunc->runCondition = NIL; /* winref will be set by transformWindowFuncCall */
wfunc->winstar = false;
wfunc->winagg = true;
wfunc->location = agg_ctor->location;
/* *orderedaggsnotallowedinwindowsyet
*/ if (agg_ctor->agg_order != NIL)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("aggregate ORDER BY is not implemented for window functions"),
parser_errposition(pstate, agg_ctor->location));
/* parse_agg.c does additional window-func-specific processing */
transformWindowFuncCall(pstate, wfunc, agg_ctor->over);
/* aggcollid and inputcollid will be set by parse_collate.c */ /* aggtranstype will be set by planner */ /* aggargtypes will be set by transformAggregateCall */ /* aggdirectargs and args will be set by transformAggregateCall */ /* aggorder and aggdistinct will be set by transformAggregateCall */
aggref->aggfilter = aggfilter;
aggref->aggstar = false;
aggref->aggvariadic = false;
aggref->aggkind = AGGKIND_NORMAL;
aggref->aggpresorted = false; /* agglevelsup will be set by transformAggregateCall */
aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */
aggref->aggno = -1; /* planner will set aggno and aggtransno */
aggref->aggtransno = -1;
aggref->location = agg_ctor->location;
if (format->encoding != JS_ENC_DEFAULT)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
parser_errposition(pstate, format->location),
errmsg("cannot use JSON FORMAT ENCODING clause for non-bytea input types")));
}
/* make resulting expression */ if (exprtype != TEXTOID && exprtype != JSONOID && exprtype != JSONBOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot use type %s in IS JSON predicate",
format_type_be(exprtype))));
/* This intentionally(?) drops the format clause. */ return makeJsonIsPredicate(expr, NULL, pred->item_type,
pred->unique_keys, pred->location);
}
if (output)
{
returning = transformJsonOutput(pstate, output, false);
Assert(OidIsValid(returning->typid));
if (returning->typid != JSONOID && returning->typid != JSONBOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot use type %s in RETURNING clause of %s",
format_type_be(returning->typid), fname),
errhint("Try returning json or jsonb."),
parser_errposition(pstate, output->typeName->location)));
} else
{ /* Output type is JSON by default. */
Oid targettype = JSONOID;
JsonFormatType format = JS_FORMAT_JSON;
if (expr->output)
{
returning = transformJsonOutput(pstate, expr->output, true);
if (returning->typid != BYTEAOID)
{ char typcategory; bool typispreferred;
get_type_category_preferred(returning->typid, &typcategory,
&typispreferred); if (typcategory != TYPCATEGORY_STRING)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot use type %s in RETURNING clause of %s",
format_type_be(returning->typid), "JSON_SERIALIZE()"),
errhint("Try returning a string type or bytea.")));
}
} else
{ /* RETURNING TEXT FORMAT JSON is by default */
returning = makeNode(JsonReturning);
returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
returning->typid = TEXTOID;
returning->typmod = -1;
}
if (format->format_type != JS_FORMAT_DEFAULT ||
format->encoding != JS_ENC_DEFAULT)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cannot specify FORMAT JSON in RETURNING clause of %s()",
func_name),
parser_errposition(pstate, format->location));
}
/* OMIT QUOTES is meaningless when strings are wrapped. */ if (func->op == JSON_QUERY_OP)
{ if (func->quotes == JS_QUOTES_OMIT &&
(func->wrapper == JSW_CONDITIONAL ||
func->wrapper == JSW_UNCONDITIONAL))
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used"),
parser_errposition(pstate, func->location)); if (func->on_empty != NULL &&
func->on_empty->btype != JSON_BEHAVIOR_ERROR &&
func->on_empty->btype != JSON_BEHAVIOR_NULL &&
func->on_empty->btype != JSON_BEHAVIOR_EMPTY &&
func->on_empty->btype != JSON_BEHAVIOR_EMPTY_ARRAY &&
func->on_empty->btype != JSON_BEHAVIOR_EMPTY_OBJECT &&
func->on_empty->btype != JSON_BEHAVIOR_DEFAULT)
{ if (func->column_name == NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior", "ON EMPTY"), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s.", "ON EMPTY", "JSON_QUERY()"),
parser_errposition(pstate, func->on_empty->location)); else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior for column \"%s\"", "ON EMPTY", func->column_name), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns.", "ON EMPTY"),
parser_errposition(pstate, func->on_empty->location));
} if (func->on_error != NULL &&
func->on_error->btype != JSON_BEHAVIOR_ERROR &&
func->on_error->btype != JSON_BEHAVIOR_NULL &&
func->on_error->btype != JSON_BEHAVIOR_EMPTY &&
func->on_error->btype != JSON_BEHAVIOR_EMPTY_ARRAY &&
func->on_error->btype != JSON_BEHAVIOR_EMPTY_OBJECT &&
func->on_error->btype != JSON_BEHAVIOR_DEFAULT)
{ if (func->column_name == NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior", "ON ERROR"), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for %s.", "ON ERROR", "JSON_QUERY()"),
parser_errposition(pstate, func->on_error->location)); else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior for column \"%s\"", "ON ERROR", func->column_name), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errdetail("Only ERROR, NULL, EMPTY ARRAY, EMPTY OBJECT, or DEFAULT expression is allowed in %s for formatted columns.", "ON ERROR"),
parser_errposition(pstate, func->on_error->location));
}
}
/* Check that ON ERROR/EMPTY behavior values are valid for the function. */ if (func->op == JSON_EXISTS_OP &&
func->on_error != NULL &&
func->on_error->btype != JSON_BEHAVIOR_ERROR &&
func->on_error->btype != JSON_BEHAVIOR_TRUE &&
func->on_error->btype != JSON_BEHAVIOR_FALSE &&
func->on_error->btype != JSON_BEHAVIOR_UNKNOWN)
{ if (func->column_name == NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior", "ON ERROR"),
errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for %s.", "ON ERROR", "JSON_EXISTS()"),
parser_errposition(pstate, func->on_error->location)); else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: first %s is name a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior for column \"%s\"", "ON ERROR", func->column_name), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errdetail("Only ERROR, TRUE, FALSE, or UNKNOWN is allowed in %s for EXISTS columns.", "ON ERROR"),
parser_errposition(pstate, func->on_error->location));
} if (func->op == JSON_VALUE_OP)
{ if (func->on_empty != NULL &&
func->on_empty->btype != JSON_BEHAVIOR_ERROR &&
func->on_empty->btype != JSON_BEHAVIOR_NULL &&
func->on_empty->btype != JSON_BEHAVIOR_DEFAULT)
{ if (func->column_name == NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior", "ON EMPTY"), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s.", "ON EMPTY", "JSON_VALUE()"),
parser_errposition(pstate, func->on_empty->location)); else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior for column \"%s\"", "ON EMPTY", func->column_name), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns.", "ON EMPTY"),
parser_errposition(pstate, func->on_empty->location));
} if (func->on_error != NULL &&
func->on_error->btype != JSON_BEHAVIOR_ERROR &&
func->on_error->btype != JSON_BEHAVIOR_NULL &&
func->on_error->btype != JSON_BEHAVIOR_DEFAULT)
{ if (func->column_name == NULL)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior", "ON ERROR"), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY),
second %s is a SQL/JSON function name (e.g. JSON_QUERY) */
errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for %s.", "ON ERROR", "JSON_VALUE()"),
parser_errposition(pstate, func->on_error->location)); else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR), /*- translator: first %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errmsg("invalid %s behavior for column \"%s\"", "ON ERROR", func->column_name), /*- translator: %s is name of a SQL/JSON clause (eg. ON EMPTY) */
errdetail("Only ERROR, NULL, or DEFAULT expression is allowed in %s for scalar columns.", "ON ERROR"),
parser_errposition(pstate, func->on_error->location));
}
}
/* Assume NULL ON EMPTY when ON EMPTY is not specified. */
jsexpr->on_empty = transformJsonBehavior(pstate,
jsexpr,
func->on_empty,
JSON_BEHAVIOR_NULL,
jsexpr->returning); /* Assume NULL ON ERROR when ON ERROR is not specified. */
jsexpr->on_error = transformJsonBehavior(pstate,
jsexpr,
func->on_error,
JSON_BEHAVIOR_NULL,
jsexpr->returning); break;
case JSON_VALUE_OP: /* JSON_VALUE returns text by default. */ if (!OidIsValid(jsexpr->returning->typid))
{
jsexpr->returning->typid = TEXTOID;
jsexpr->returning->typmod = -1;
}
jsexpr->collation = get_typcollation(jsexpr->returning->typid);
/* Assume NULL ON EMPTY when ON EMPTY is not specified. */
jsexpr->on_empty = transformJsonBehavior(pstate,
jsexpr,
func->on_empty,
JSON_BEHAVIOR_NULL,
jsexpr->returning); /* Assume NULL ON ERROR when ON ERROR is not specified. */
jsexpr->on_error = transformJsonBehavior(pstate,
jsexpr,
func->on_error,
JSON_BEHAVIOR_NULL,
jsexpr->returning); break;
case JSON_TABLE_OP: if (!OidIsValid(jsexpr->returning->typid))
{
jsexpr->returning->typid = exprType(jsexpr->formatted_expr);
jsexpr->returning->typmod = -1;
}
jsexpr->collation = get_typcollation(jsexpr->returning->typid);
default:
elog(ERROR, "invalid JsonFuncExpr op %d", (int) func->op); break;
}
return (Node *) jsexpr;
}
/* *TransformaSQL/JSONPASSINGclause.
*/ staticvoid
transformJsonPassingArgs(ParseState *pstate, constchar *constructName,
JsonFormatType format, List *args,
List **passing_values, List **passing_names)
{
ListCell *lc;
switch (nodeTag(expr))
{ /* Acceptable expression nodes */ case T_Const: case T_FuncExpr: case T_OpExpr: returntrue;
/* Acceptable iff arg of the following nodes is one of the above */ case T_CoerceViaIO: case T_CoerceToDomain: case T_ArrayCoerceExpr: case T_ConvertRowtypeExpr: case T_RelabelType: case T_CollateExpr: return expression_tree_walker(expr, ValidJsonBehaviorDefaultExpr,
context); default: break;
}
if (behavior)
{
btype = behavior->btype;
location = behavior->location; if (btype == JSON_BEHAVIOR_DEFAULT)
{
Oid targetcoll = jsexpr->collation;
Oid exprcoll;
if (!ValidJsonBehaviorDefaultExpr(expr, NULL))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("can only specify a constant, non-aggregate function, or operator expression for DEFAULT"),
parser_errposition(pstate, exprLocation(expr)))); if (contain_var_clause(expr))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("DEFAULT expression must not contain column references"),
parser_errposition(pstate, exprLocation(expr)))); if (expression_returns_set(expr))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("DEFAULT expression must not return a set"),
parser_errposition(pstate, exprLocation(expr))));
/* *RejectaDEFAULTexpressionwhosecollationdiffersfromthe *enclosingJSONexpression'sresultcollation *(jsexpr->collation),aschosenbytheRETURNINGclause.
*/
exprcoll = exprCollation(expr); if (!OidIsValid(exprcoll))
exprcoll = get_typcollation(exprType(expr)); if (OidIsValid(targetcoll) && OidIsValid(exprcoll) &&
targetcoll != exprcoll)
ereport(ERROR,
errcode(ERRCODE_COLLATION_MISMATCH),
errmsg("collation of DEFAULT expression conflicts with RETURNING clause"),
errdetail("\"%s\" versus \"%s\"",
get_collation_name(exprcoll),
get_collation_name(targetcoll)),
parser_errposition(pstate, exprLocation(expr)));
}
}
if (coerced_expr == NULL)
{ /* *ProvideaHINTiftheexpressioncomesfromaDEFAULT *clause.
*/ if (btype == JSON_BEHAVIOR_DEFAULT)
ereport(ERROR,
errcode(ERRCODE_CANNOT_COERCE),
errmsg("cannot cast behavior expression of type %s to %s",
format_type_be(exprType(expr)),
format_type_be(returning->typid)),
errhint("You will need to explicitly cast the expression to type %s.",
format_type_be(returning->typid)),
parser_errposition(pstate, exprLocation(expr))); else
ereport(ERROR,
errcode(ERRCODE_CANNOT_COERCE),
errmsg("cannot cast behavior expression of type %s to %s",
format_type_be(exprType(expr)),
format_type_be(returning->typid)),
parser_errposition(pstate, exprLocation(expr)));
}
/* *ReturnsaConstnodeholdingthevalueforthegivennon-ERROR *JsonBehaviorType.
*/ static Node *
GetJsonBehaviorConst(JsonBehaviorType btype, int location)
{
Datum val = (Datum) 0;
Oid typid = JSONBOID; int len = -1; bool isbyval = false; bool isnull = false; Const *con;
switch (btype)
{ case JSON_BEHAVIOR_EMPTY_ARRAY:
val = DirectFunctionCall1(jsonb_in, CStringGetDatum("[]")); break;
case JSON_BEHAVIOR_EMPTY_OBJECT:
val = DirectFunctionCall1(jsonb_in, CStringGetDatum("{}")); break;
case JSON_BEHAVIOR_TRUE:
val = BoolGetDatum(true);
typid = BOOLOID;
len = sizeof(bool);
isbyval = true; break;
case JSON_BEHAVIOR_FALSE:
val = BoolGetDatum(false);
typid = BOOLOID;
len = sizeof(bool);
isbyval = true; break;
case JSON_BEHAVIOR_NULL: case JSON_BEHAVIOR_UNKNOWN: case JSON_BEHAVIOR_EMPTY:
val = (Datum) 0;
isnull = true;
typid = INT4OID;
len = sizeof(int32);
isbyval = true; break;
/* These two behavior types are handled by the caller. */ case JSON_BEHAVIOR_DEFAULT: case JSON_BEHAVIOR_ERROR:
Assert(false); break;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.309Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.