/* *exprType- *returnstheOidofthetypeoftheexpression'sresult.
*/
Oid
exprType(const Node *expr)
{
Oid type;
if (!expr) return InvalidOid;
switch (nodeTag(expr))
{ case T_Var:
type = ((const Var *) expr)->vartype; break; case T_Const:
type = ((constConst *) expr)->consttype; break; case T_Param:
type = ((const Param *) expr)->paramtype; break; case T_Aggref:
type = ((const Aggref *) expr)->aggtype; break; case T_GroupingFunc:
type = INT4OID; break; case T_WindowFunc:
type = ((const WindowFunc *) expr)->wintype; break; case T_MergeSupportFunc:
type = ((const MergeSupportFunc *) expr)->msftype; break; case T_SubscriptingRef:
type = ((const SubscriptingRef *) expr)->refrestype; break; case T_FuncExpr:
type = ((const FuncExpr *) expr)->funcresulttype; break; case T_NamedArgExpr:
type = exprType((Node *) ((const NamedArgExpr *) expr)->arg); break; case T_OpExpr:
type = ((const OpExpr *) expr)->opresulttype; break; case T_DistinctExpr:
type = ((const DistinctExpr *) expr)->opresulttype; break; case T_NullIfExpr:
type = ((const NullIfExpr *) expr)->opresulttype; break; case T_ScalarArrayOpExpr:
type = BOOLOID; break; case T_BoolExpr:
type = BOOLOID; break; case T_SubLink:
{ const SubLink *sublink = (const SubLink *) expr;
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
{ /* get the type of the subselect's first target column */
Query *qtree = (Query *) sublink->subselect;
TargetEntry *tent;
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot get type for untransformed sublink");
tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
type = exprType((Node *) tent->expr); if (sublink->subLinkType == ARRAY_SUBLINK)
{
type = get_promoted_array_type(type); if (!OidIsValid(type))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s",
format_type_be(exprType((Node *) tent->expr)))));
}
} elseif (sublink->subLinkType == MULTIEXPR_SUBLINK)
{ /* MULTIEXPR is always considered to return RECORD */
type = RECORDOID;
} else
{ /* for all other sublink types, result is boolean */
type = BOOLOID;
}
} break; case T_SubPlan:
{ const SubPlan *subplan = (const SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
{ /* get the type of the subselect's first target column */
type = subplan->firstColType; if (subplan->subLinkType == ARRAY_SUBLINK)
{
type = get_promoted_array_type(type); if (!OidIsValid(type))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find array type for data type %s",
format_type_be(subplan->firstColType))));
}
} elseif (subplan->subLinkType == MULTIEXPR_SUBLINK)
{ /* MULTIEXPR is always considered to return RECORD */
type = RECORDOID;
} else
{ /* for all other subplan types, result is boolean */
type = BOOLOID;
}
} break; case T_AlternativeSubPlan:
{ const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr;
/* subplans should all return the same thing */
type = exprType((Node *) linitial(asplan->subplans));
} break; case T_FieldSelect:
type = ((const FieldSelect *) expr)->resulttype; break; case T_FieldStore:
type = ((const FieldStore *) expr)->resulttype; break; case T_RelabelType:
type = ((const RelabelType *) expr)->resulttype; break; case T_CoerceViaIO:
type = ((const CoerceViaIO *) expr)->resulttype; break; case T_ArrayCoerceExpr:
type = ((const ArrayCoerceExpr *) expr)->resulttype; break; case T_ConvertRowtypeExpr:
type = ((const ConvertRowtypeExpr *) expr)->resulttype; break; case T_CollateExpr:
type = exprType((Node *) ((const CollateExpr *) expr)->arg); break; case T_CaseExpr:
type = ((const CaseExpr *) expr)->casetype; break; case T_CaseTestExpr:
type = ((const CaseTestExpr *) expr)->typeId; break; case T_ArrayExpr:
type = ((const ArrayExpr *) expr)->array_typeid; break; case T_RowExpr:
type = ((const RowExpr *) expr)->row_typeid; break; case T_RowCompareExpr:
type = BOOLOID; break; case T_CoalesceExpr:
type = ((const CoalesceExpr *) expr)->coalescetype; break; case T_MinMaxExpr:
type = ((const MinMaxExpr *) expr)->minmaxtype; break; case T_SQLValueFunction:
type = ((const SQLValueFunction *) expr)->type; break; case T_XmlExpr: if (((const XmlExpr *) expr)->op == IS_DOCUMENT)
type = BOOLOID; elseif (((const XmlExpr *) expr)->op == IS_XMLSERIALIZE)
type = TEXTOID; else
type = XMLOID; break; case T_JsonValueExpr:
{ const JsonValueExpr *jve = (const JsonValueExpr *) expr;
type = exprType((Node *) jve->formatted_expr);
} break; case T_JsonConstructorExpr:
type = ((const JsonConstructorExpr *) expr)->returning->typid; break; case T_JsonIsPredicate:
type = BOOLOID; break; case T_JsonExpr:
{ const JsonExpr *jexpr = (const JsonExpr *) expr;
type = jexpr->returning->typid; break;
} case T_JsonBehavior:
{ const JsonBehavior *behavior = (const JsonBehavior *) expr;
type = exprType(behavior->expr); break;
} case T_NullTest:
type = BOOLOID; break; case T_BooleanTest:
type = BOOLOID; break; case T_CoerceToDomain:
type = ((const CoerceToDomain *) expr)->resulttype; break; case T_CoerceToDomainValue:
type = ((const CoerceToDomainValue *) expr)->typeId; break; case T_SetToDefault:
type = ((const SetToDefault *) expr)->typeId; break; case T_CurrentOfExpr:
type = BOOLOID; break; case T_NextValueExpr:
type = ((const NextValueExpr *) expr)->typeId; break; case T_InferenceElem:
{ const InferenceElem *n = (const InferenceElem *) expr;
type = exprType((Node *) n->expr);
} break; case T_ReturningExpr:
type = exprType((Node *) ((const ReturningExpr *) expr)->retexpr); break; case T_PlaceHolderVar:
type = exprType((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
type = InvalidOid; /* keep compiler quiet */ break;
} return type;
}
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
{ /* get the typmod of the subselect's first target column */
Query *qtree = (Query *) sublink->subselect;
TargetEntry *tent;
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot get type for untransformed sublink");
tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk); return exprTypmod((Node *) tent->expr); /* note we don't need to care if it's an array */
} /* otherwise, result is RECORD or BOOLEAN, typmod is -1 */
} break; case T_SubPlan:
{ const SubPlan *subplan = (const SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
{ /* get the typmod of the subselect's first target column */ /* note we don't need to care if it's an array */ return subplan->firstColTypmod;
} /* otherwise, result is RECORD or BOOLEAN, typmod is -1 */
} break; case T_AlternativeSubPlan:
{ const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr;
/* subplans should all return the same thing */ return exprTypmod((Node *) linitial(asplan->subplans));
} break; case T_FieldSelect: return ((const FieldSelect *) expr)->resulttypmod; case T_RelabelType: return ((const RelabelType *) expr)->resulttypmod; case T_ArrayCoerceExpr: return ((const ArrayCoerceExpr *) expr)->resulttypmod; case T_CollateExpr: return exprTypmod((Node *) ((const CollateExpr *) expr)->arg); case T_CaseExpr:
{ /* *Ifallthealternativesagreeontype/typmod,returnthat *typmod,elseuse-1
*/ const CaseExpr *cexpr = (const CaseExpr *) expr;
Oid casetype = cexpr->casetype;
int32 typmod;
ListCell *arg;
if (!cexpr->defresult) return -1; if (exprType((Node *) cexpr->defresult) != casetype) return -1;
typmod = exprTypmod((Node *) cexpr->defresult); if (typmod < 0) return -1; /* no point in trying harder */
foreach(arg, cexpr->args)
{
CaseWhen *w = lfirst_node(CaseWhen, arg);
if (exprType((Node *) w->result) != casetype) return -1; if (exprTypmod((Node *) w->result) != typmod) return -1;
} return typmod;
} break; case T_CaseTestExpr: return ((const CaseTestExpr *) expr)->typeMod; case T_ArrayExpr:
{ /* *Ifalltheelementsagreeontype/typmod,returnthat *typmod,elseuse-1
*/ const ArrayExpr *arrayexpr = (const ArrayExpr *) expr;
Oid commontype;
int32 typmod;
ListCell *elem;
if (arrayexpr->elements == NIL) return -1;
typmod = exprTypmod((Node *) linitial(arrayexpr->elements)); if (typmod < 0) return -1; /* no point in trying harder */ if (arrayexpr->multidims)
commontype = arrayexpr->array_typeid; else
commontype = arrayexpr->element_typeid;
foreach(elem, arrayexpr->elements)
{
Node *e = (Node *) lfirst(elem);
if (exprType(e) != commontype) return -1; if (exprTypmod(e) != typmod) return -1;
} return typmod;
} break; case T_CoalesceExpr:
{ /* *Ifallthealternativesagreeontype/typmod,returnthat *typmod,elseuse-1
*/ const CoalesceExpr *cexpr = (const CoalesceExpr *) expr;
Oid coalescetype = cexpr->coalescetype;
int32 typmod;
ListCell *arg;
if (exprType((Node *) linitial(cexpr->args)) != coalescetype) return -1;
typmod = exprTypmod((Node *) linitial(cexpr->args)); if (typmod < 0) return -1; /* no point in trying harder */
for_each_from(arg, cexpr->args, 1)
{
Node *e = (Node *) lfirst(arg);
if (exprType(e) != coalescetype) return -1; if (exprTypmod(e) != typmod) return -1;
} return typmod;
} break; case T_MinMaxExpr:
{ /* *Ifallthealternativesagreeontype/typmod,returnthat *typmod,elseuse-1
*/ const MinMaxExpr *mexpr = (const MinMaxExpr *) expr;
Oid minmaxtype = mexpr->minmaxtype;
int32 typmod;
ListCell *arg;
if (exprType((Node *) linitial(mexpr->args)) != minmaxtype) return -1;
typmod = exprTypmod((Node *) linitial(mexpr->args)); if (typmod < 0) return -1; /* no point in trying harder */
for_each_from(arg, mexpr->args, 1)
{
Node *e = (Node *) lfirst(arg);
if (exprType(e) != minmaxtype) return -1; if (exprTypmod(e) != typmod) return -1;
} return typmod;
} break; case T_SQLValueFunction: return ((const SQLValueFunction *) expr)->typmod; case T_JsonValueExpr: return exprTypmod((Node *) ((const JsonValueExpr *) expr)->formatted_expr); case T_JsonConstructorExpr: return ((const JsonConstructorExpr *) expr)->returning->typmod; case T_JsonExpr:
{ const JsonExpr *jexpr = (const JsonExpr *) expr;
if (arg && IsA(arg, Const))
{ /* Modify the Const directly to preserve const-flatness. */ Const *con = (Const *) arg;
if (!overwrite_ok)
con = copyObject(con);
con->consttype = rtype;
con->consttypmod = rtypmod;
con->constcollid = rcollid; /* We keep the Const's original location. */ return (Node *) con;
} elseif (exprType(arg) == rtype &&
exprTypmod(arg) == rtypmod &&
exprCollation(arg) == rcollid)
{ /* Sometimes we find a nest of relabels that net out to nothing. */ return arg;
} else
{ /* Nope, gotta have a RelabelType. */
RelabelType *newrelabel = makeNode(RelabelType);
/* Avoid recursion for some cases that parser checks not to return a set */ if (IsA(node, Aggref)) returnfalse; if (IsA(node, GroupingFunc)) returnfalse; if (IsA(node, WindowFunc)) returnfalse;
/* *exprCollation- *returnstheOidofthecollationoftheexpression'sresult. * *Note:expressionnodesthatcaninvokefunctionsgenerallyhavean *"inputcollid"field,whichiswhatthefunctionshoulduseascollation. *Thatistheresolvedcommoncollationofthenode'sinputs.Itisoften *butnotalwaysthesameastheresultcollation;inparticular,ifthe *functionproducesanon-collatableresulttypefromcollatableinputs *orviceversa,thetwoaredifferent.
*/
Oid
exprCollation(const Node *expr)
{
Oid coll;
if (!expr) return InvalidOid;
switch (nodeTag(expr))
{ case T_Var:
coll = ((const Var *) expr)->varcollid; break; case T_Const:
coll = ((constConst *) expr)->constcollid; break; case T_Param:
coll = ((const Param *) expr)->paramcollid; break; case T_Aggref:
coll = ((const Aggref *) expr)->aggcollid; break; case T_GroupingFunc:
coll = InvalidOid; break; case T_WindowFunc:
coll = ((const WindowFunc *) expr)->wincollid; break; case T_MergeSupportFunc:
coll = ((const MergeSupportFunc *) expr)->msfcollid; break; case T_SubscriptingRef:
coll = ((const SubscriptingRef *) expr)->refcollid; break; case T_FuncExpr:
coll = ((const FuncExpr *) expr)->funccollid; break; case T_NamedArgExpr:
coll = exprCollation((Node *) ((const NamedArgExpr *) expr)->arg); break; case T_OpExpr:
coll = ((const OpExpr *) expr)->opcollid; break; case T_DistinctExpr:
coll = ((const DistinctExpr *) expr)->opcollid; break; case T_NullIfExpr:
coll = ((const NullIfExpr *) expr)->opcollid; break; case T_ScalarArrayOpExpr: /* ScalarArrayOpExpr's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_BoolExpr: /* BoolExpr's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_SubLink:
{ const SubLink *sublink = (const SubLink *) expr;
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
{ /* get the collation of subselect's first target column */
Query *qtree = (Query *) sublink->subselect;
TargetEntry *tent;
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot get collation for untransformed sublink");
tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
coll = exprCollation((Node *) tent->expr); /* collation doesn't change if it's converted to array */
} else
{ /* otherwise, SubLink's result is RECORD or BOOLEAN */
coll = InvalidOid; /* ... so it has no collation */
}
} break; case T_SubPlan:
{ const SubPlan *subplan = (const SubPlan *) expr;
if (subplan->subLinkType == EXPR_SUBLINK ||
subplan->subLinkType == ARRAY_SUBLINK)
{ /* get the collation of subselect's first target column */
coll = subplan->firstColCollation; /* collation doesn't change if it's converted to array */
} else
{ /* otherwise, SubPlan's result is RECORD or BOOLEAN */
coll = InvalidOid; /* ... so it has no collation */
}
} break; case T_AlternativeSubPlan:
{ const AlternativeSubPlan *asplan = (const AlternativeSubPlan *) expr;
/* subplans should all return the same thing */
coll = exprCollation((Node *) linitial(asplan->subplans));
} break; case T_FieldSelect:
coll = ((const FieldSelect *) expr)->resultcollid; break; case T_FieldStore: /* FieldStore's result is composite ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_RelabelType:
coll = ((const RelabelType *) expr)->resultcollid; break; case T_CoerceViaIO:
coll = ((const CoerceViaIO *) expr)->resultcollid; break; case T_ArrayCoerceExpr:
coll = ((const ArrayCoerceExpr *) expr)->resultcollid; break; case T_ConvertRowtypeExpr: /* ConvertRowtypeExpr's result is composite ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_CollateExpr:
coll = ((const CollateExpr *) expr)->collOid; break; case T_CaseExpr:
coll = ((const CaseExpr *) expr)->casecollid; break; case T_CaseTestExpr:
coll = ((const CaseTestExpr *) expr)->collation; break; case T_ArrayExpr:
coll = ((const ArrayExpr *) expr)->array_collid; break; case T_RowExpr: /* RowExpr's result is composite ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_RowCompareExpr: /* RowCompareExpr's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_CoalesceExpr:
coll = ((const CoalesceExpr *) expr)->coalescecollid; break; case T_MinMaxExpr:
coll = ((const MinMaxExpr *) expr)->minmaxcollid; break; case T_SQLValueFunction: /* Returns either NAME or a non-collatable type */ if (((const SQLValueFunction *) expr)->type == NAMEOID)
coll = C_COLLATION_OID; else
coll = InvalidOid; break; case T_XmlExpr:
if (ctor->coercion)
coll = exprCollation((Node *) ctor->coercion); else
coll = InvalidOid;
} break; case T_JsonIsPredicate: /* IS JSON's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_JsonExpr:
{ const JsonExpr *jsexpr = (JsonExpr *) expr;
if (behavior->expr)
coll = exprCollation(behavior->expr); else
coll = InvalidOid;
} break; case T_NullTest: /* NullTest's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_BooleanTest: /* BooleanTest's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_CoerceToDomain:
coll = ((const CoerceToDomain *) expr)->resultcollid; break; case T_CoerceToDomainValue:
coll = ((const CoerceToDomainValue *) expr)->collation; break; case T_SetToDefault:
coll = ((const SetToDefault *) expr)->collation; break; case T_CurrentOfExpr: /* CurrentOfExpr's result is boolean ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_NextValueExpr: /* NextValueExpr's result is an integer type ... */
coll = InvalidOid; /* ... so it has no collation */ break; case T_InferenceElem:
coll = exprCollation((Node *) ((const InferenceElem *) expr)->expr); break; case T_ReturningExpr:
coll = exprCollation((Node *) ((const ReturningExpr *) expr)->retexpr); break; case T_PlaceHolderVar:
coll = exprCollation((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
coll = InvalidOid; /* keep compiler quiet */ break;
} return coll;
}
/* *exprInputCollation- *returnstheOidofthecollationafunctionshoulduse,ifavailable. * *ResultisInvalidOidifthenodetypedoesn'tstorethisinformation.
*/
Oid
exprInputCollation(const Node *expr)
{
Oid coll;
/* *exprSetCollation- *Assigncollationinformationtoanexpressiontreenode. * *Note:sincethisisonlyusedduringparseanalysis,wedon'tneedto *worryaboutsubplans,PlaceHolderVars,orReturningExprs.
*/ void
exprSetCollation(Node *expr, Oid collation)
{ switch (nodeTag(expr))
{ case T_Var:
((Var *) expr)->varcollid = collation; break; case T_Const:
((Const *) expr)->constcollid = collation; break; case T_Param:
((Param *) expr)->paramcollid = collation; break; case T_Aggref:
((Aggref *) expr)->aggcollid = collation; break; case T_GroupingFunc:
Assert(!OidIsValid(collation)); break; case T_WindowFunc:
((WindowFunc *) expr)->wincollid = collation; break; case T_MergeSupportFunc:
((MergeSupportFunc *) expr)->msfcollid = collation; break; case T_SubscriptingRef:
((SubscriptingRef *) expr)->refcollid = collation; break; case T_FuncExpr:
((FuncExpr *) expr)->funccollid = collation; break; case T_NamedArgExpr:
Assert(collation == exprCollation((Node *) ((NamedArgExpr *) expr)->arg)); break; case T_OpExpr:
((OpExpr *) expr)->opcollid = collation; break; case T_DistinctExpr:
((DistinctExpr *) expr)->opcollid = collation; break; case T_NullIfExpr:
((NullIfExpr *) expr)->opcollid = collation; break; case T_ScalarArrayOpExpr: /* ScalarArrayOpExpr's result is boolean ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_BoolExpr: /* BoolExpr's result is boolean ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_SubLink: #ifdef USE_ASSERT_CHECKING
{
SubLink *sublink = (SubLink *) expr;
if (sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == ARRAY_SUBLINK)
{ /* get the collation of subselect's first target column */
Query *qtree = (Query *) sublink->subselect;
TargetEntry *tent;
if (!qtree || !IsA(qtree, Query))
elog(ERROR, "cannot set collation for untransformed sublink");
tent = linitial_node(TargetEntry, qtree->targetList);
Assert(!tent->resjunk);
Assert(collation == exprCollation((Node *) tent->expr));
} else
{ /* otherwise, result is RECORD or BOOLEAN */
Assert(!OidIsValid(collation));
}
} #endif/* USE_ASSERT_CHECKING */ break; case T_FieldSelect:
((FieldSelect *) expr)->resultcollid = collation; break; case T_FieldStore: /* FieldStore's result is composite ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_RelabelType:
((RelabelType *) expr)->resultcollid = collation; break; case T_CoerceViaIO:
((CoerceViaIO *) expr)->resultcollid = collation; break; case T_ArrayCoerceExpr:
((ArrayCoerceExpr *) expr)->resultcollid = collation; break; case T_ConvertRowtypeExpr: /* ConvertRowtypeExpr's result is composite ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_CaseExpr:
((CaseExpr *) expr)->casecollid = collation; break; case T_ArrayExpr:
((ArrayExpr *) expr)->array_collid = collation; break; case T_RowExpr: /* RowExpr's result is composite ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_RowCompareExpr: /* RowCompareExpr's result is boolean ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_CoalesceExpr:
((CoalesceExpr *) expr)->coalescecollid = collation; break; case T_MinMaxExpr:
((MinMaxExpr *) expr)->minmaxcollid = collation; break; case T_SQLValueFunction:
Assert((((SQLValueFunction *) expr)->type == NAMEOID) ?
(collation == C_COLLATION_OID) :
(collation == InvalidOid)); break; case T_XmlExpr:
Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ?
(collation == DEFAULT_COLLATION_OID) :
(collation == InvalidOid)); break; case T_JsonValueExpr:
exprSetCollation((Node *) ((JsonValueExpr *) expr)->formatted_expr,
collation); break; case T_JsonConstructorExpr:
{
JsonConstructorExpr *ctor = (JsonConstructorExpr *) expr;
if (ctor->coercion)
exprSetCollation((Node *) ctor->coercion, collation); else
Assert(!OidIsValid(collation)); /* result is always a
* json[b] type */
} break; case T_JsonIsPredicate:
Assert(!OidIsValid(collation)); /* result is always boolean */ break; case T_JsonExpr:
{
JsonExpr *jexpr = (JsonExpr *) expr;
jexpr->collation = collation;
} break; case T_JsonBehavior:
Assert(((JsonBehavior *) expr)->expr == NULL ||
exprCollation(((JsonBehavior *) expr)->expr) == collation); break; case T_NullTest: /* NullTest's result is boolean ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_BooleanTest: /* BooleanTest's result is boolean ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_CoerceToDomain:
((CoerceToDomain *) expr)->resultcollid = collation; break; case T_CoerceToDomainValue:
((CoerceToDomainValue *) expr)->collation = collation; break; case T_SetToDefault:
((SetToDefault *) expr)->collation = collation; break; case T_CurrentOfExpr: /* CurrentOfExpr's result is boolean ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; case T_NextValueExpr: /* NextValueExpr's result is an integer type ... */
Assert(!OidIsValid(collation)); /* ... so never set a collation */ break; default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); break;
}
}
/* *exprSetInputCollation- *Assigninput-collationinformationtoanexpressiontreenode. * *Thisisano-opfornodetypesthatdon'tstoretheirinputcollation. *NoteweomitRowCompareExpr,whichneedsspecialtreatmentsinceit *containsmultipleinputcollationOIDs.
*/ void
exprSetInputCollation(Node *expr, Oid inputcollation)
{ switch (nodeTag(expr))
{ case T_Aggref:
((Aggref *) expr)->inputcollid = inputcollation; break; case T_WindowFunc:
((WindowFunc *) expr)->inputcollid = inputcollation; break; case T_FuncExpr:
((FuncExpr *) expr)->inputcollid = inputcollation; break; case T_OpExpr:
((OpExpr *) expr)->inputcollid = inputcollation; break; case T_DistinctExpr:
((DistinctExpr *) expr)->inputcollid = inputcollation; break; case T_NullIfExpr:
((NullIfExpr *) expr)->inputcollid = inputcollation; break; case T_ScalarArrayOpExpr:
((ScalarArrayOpExpr *) expr)->inputcollid = inputcollation; break; case T_MinMaxExpr:
((MinMaxExpr *) expr)->inputcollid = inputcollation; break; default: break;
}
}
if (expr == NULL) return -1; switch (nodeTag(expr))
{ case T_RangeVar:
loc = ((const RangeVar *) expr)->location; break; case T_TableFunc:
loc = ((const TableFunc *) expr)->location; break; case T_Var:
loc = ((const Var *) expr)->location; break; case T_Const:
loc = ((constConst *) expr)->location; break; case T_Param:
loc = ((const Param *) expr)->location; break; case T_Aggref: /* function name should always be the first thing */
loc = ((const Aggref *) expr)->location; break; case T_GroupingFunc:
loc = ((const GroupingFunc *) expr)->location; break; case T_WindowFunc: /* function name should always be the first thing */
loc = ((const WindowFunc *) expr)->location; break; case T_MergeSupportFunc:
loc = ((const MergeSupportFunc *) expr)->location; break; case T_SubscriptingRef: /* just use container argument's location */
loc = exprLocation((Node *) ((const SubscriptingRef *) expr)->refexpr); break; case T_FuncExpr:
{ const FuncExpr *fexpr = (const FuncExpr *) expr;
/* consider both function name and leftmost arg */
loc = leftmostLoc(fexpr->location,
exprLocation((Node *) fexpr->args));
} break; case T_NamedArgExpr:
{ const NamedArgExpr *na = (const NamedArgExpr *) expr;
/* consider both argument name and value */
loc = leftmostLoc(na->location,
exprLocation((Node *) na->arg));
} break; case T_OpExpr: case T_DistinctExpr: /* struct-equivalent to OpExpr */ case T_NullIfExpr: /* struct-equivalent to OpExpr */
{ const OpExpr *opexpr = (const OpExpr *) expr;
/* consider both operator name and leftmost arg */
loc = leftmostLoc(opexpr->location,
exprLocation((Node *) opexpr->args));
} break; case T_ScalarArrayOpExpr:
{ const ScalarArrayOpExpr *saopexpr = (const ScalarArrayOpExpr *) expr;
/* consider both operator name and leftmost arg */
loc = leftmostLoc(saopexpr->location,
exprLocation((Node *) saopexpr->args));
} break; case T_BoolExpr:
{ const BoolExpr *bexpr = (const BoolExpr *) expr;
/* check the testexpr, if any, and the operator/keyword */
loc = leftmostLoc(exprLocation(sublink->testexpr),
sublink->location);
} break; case T_FieldSelect: /* just use argument's location */
loc = exprLocation((Node *) ((const FieldSelect *) expr)->arg); break; case T_FieldStore: /* just use argument's location */
loc = exprLocation((Node *) ((const FieldStore *) expr)->arg); break; case T_RelabelType:
{ const RelabelType *rexpr = (const RelabelType *) expr;
/* Much as above */
loc = leftmostLoc(rexpr->location,
exprLocation((Node *) rexpr->arg));
} break; case T_CoerceViaIO:
{ const CoerceViaIO *cexpr = (const CoerceViaIO *) expr;
/* Much as above */
loc = leftmostLoc(cexpr->location,
exprLocation((Node *) cexpr->arg));
} break; case T_ArrayCoerceExpr:
{ const ArrayCoerceExpr *cexpr = (const ArrayCoerceExpr *) expr;
/* Much as above */
loc = leftmostLoc(cexpr->location,
exprLocation((Node *) cexpr->arg));
} break; case T_ConvertRowtypeExpr:
{ const ConvertRowtypeExpr *cexpr = (const ConvertRowtypeExpr *) expr;
/* Much as above */
loc = leftmostLoc(cexpr->location,
exprLocation((Node *) cexpr->arg));
} break; case T_CollateExpr: /* just use argument's location */
loc = exprLocation((Node *) ((const CollateExpr *) expr)->arg); break; case T_CaseExpr: /* CASE keyword should always be the first thing */
loc = ((const CaseExpr *) expr)->location; break; case T_CaseWhen: /* WHEN keyword should always be the first thing */
loc = ((const CaseWhen *) expr)->location; break; case T_ArrayExpr: /* the location points at ARRAY or [, which must be leftmost */
loc = ((const ArrayExpr *) expr)->location; break; case T_RowExpr: /* the location points at ROW or (, which must be leftmost */
loc = ((const RowExpr *) expr)->location; break; case T_RowCompareExpr: /* just use leftmost argument's location */
loc = exprLocation((Node *) ((const RowCompareExpr *) expr)->largs); break; case T_CoalesceExpr: /* COALESCE keyword should always be the first thing */
loc = ((const CoalesceExpr *) expr)->location; break; case T_MinMaxExpr: /* GREATEST/LEAST keyword should always be the first thing */
loc = ((const MinMaxExpr *) expr)->location; break; case T_SQLValueFunction: /* function keyword should always be the first thing */
loc = ((const SQLValueFunction *) expr)->location; break; case T_XmlExpr:
{ const XmlExpr *xexpr = (const XmlExpr *) expr;
/* consider both function name and leftmost arg */
loc = leftmostLoc(xexpr->location,
exprLocation((Node *) xexpr->args));
} break; case T_JsonFormat:
loc = ((const JsonFormat *) expr)->location; break; case T_JsonValueExpr:
loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->raw_expr); break; case T_JsonConstructorExpr:
loc = ((const JsonConstructorExpr *) expr)->location; break; case T_JsonIsPredicate:
loc = ((const JsonIsPredicate *) expr)->location; break; case T_JsonExpr:
{ const JsonExpr *jsexpr = (const JsonExpr *) expr;
/* consider both function name and leftmost arg */
loc = leftmostLoc(jsexpr->location,
exprLocation(jsexpr->formatted_expr));
} break; case T_JsonBehavior:
loc = exprLocation(((JsonBehavior *) expr)->expr); break; case T_NullTest:
{ const NullTest *nexpr = (const NullTest *) expr;
/* Much as above */
loc = leftmostLoc(nexpr->location,
exprLocation((Node *) nexpr->arg));
} break; case T_BooleanTest:
{ const BooleanTest *bexpr = (const BooleanTest *) expr;
/* Much as above */
loc = leftmostLoc(bexpr->location,
exprLocation((Node *) bexpr->arg));
} break; case T_CoerceToDomain:
{ const CoerceToDomain *cexpr = (const CoerceToDomain *) expr;
/* Much as above */
loc = leftmostLoc(cexpr->location,
exprLocation((Node *) cexpr->arg));
} break; case T_CoerceToDomainValue:
loc = ((const CoerceToDomainValue *) expr)->location; break; case T_SetToDefault:
loc = ((const SetToDefault *) expr)->location; break; case T_ReturningExpr:
loc = exprLocation((Node *) ((const ReturningExpr *) expr)->retexpr); break; case T_TargetEntry: /* just use argument's location */
loc = exprLocation((Node *) ((const TargetEntry *) expr)->expr); break; case T_IntoClause: /* use the contained RangeVar's location --- close enough */
loc = exprLocation((Node *) ((const IntoClause *) expr)->rel); break; case T_List:
{ /* report location of first list member that has a location */
ListCell *lc;
loc = -1; /* just to suppress compiler warning */
foreach(lc, (const List *) expr)
{
loc = exprLocation((Node *) lfirst(lc)); if (loc >= 0) break;
}
} break; case T_A_Expr:
{ const A_Expr *aexpr = (const A_Expr *) expr;
/* use leftmost of operator or left operand (if any) */ /* we assume right operand can't be to left of operator */
loc = leftmostLoc(aexpr->location,
exprLocation(aexpr->lexpr));
} break; case T_ColumnRef:
loc = ((const ColumnRef *) expr)->location; break; case T_ParamRef:
loc = ((const ParamRef *) expr)->location; break; case T_A_Const:
loc = ((const A_Const *) expr)->location; break; case T_FuncCall:
{ const FuncCall *fc = (const FuncCall *) expr;
/* consider both function name and leftmost arg */ /* (we assume any ORDER BY nodes must be to right of name) */
loc = leftmostLoc(fc->location,
exprLocation((Node *) fc->args));
} break; case T_A_ArrayExpr: /* the location points at ARRAY or [, which must be leftmost */
loc = ((const A_ArrayExpr *) expr)->location; break; case T_ResTarget: /* we need not examine the contained expression (if any) */
loc = ((const ResTarget *) expr)->location; break; case T_MultiAssignRef:
loc = exprLocation(((const MultiAssignRef *) expr)->source); break; case T_TypeCast:
{ const TypeCast *tc = (const TypeCast *) expr;
/* *ThiscouldrepresentCAST(),::,orTypeName'literal',so *anyofthecomponentsmightbeleftmost.
*/
loc = exprLocation(tc->arg);
loc = leftmostLoc(loc, tc->typeName->location);
loc = leftmostLoc(loc, tc->location);
} break; case T_CollateClause: /* just use argument's location */
loc = exprLocation(((const CollateClause *) expr)->arg); break; case T_SortBy: /* just use argument's location (ignore operator, if any) */
loc = exprLocation(((const SortBy *) expr)->node); break; case T_WindowDef:
loc = ((const WindowDef *) expr)->location; break; case T_RangeTableSample:
loc = ((const RangeTableSample *) expr)->location; break; case T_TypeName:
loc = ((constTypeName *) expr)->location; break; case T_ColumnDef:
loc = ((const ColumnDef *) expr)->location; break; case T_Constraint:
loc = ((const Constraint *) expr)->location; break; case T_FunctionParameter:
loc = ((const FunctionParameter *) expr)->location; break; case T_XmlSerialize: /* XMLSERIALIZE keyword should always be the first thing */
loc = ((const XmlSerialize *) expr)->location; break; case T_GroupingSet:
loc = ((const GroupingSet *) expr)->location; break; case T_WithClause:
loc = ((const WithClause *) expr)->location; break; case T_InferClause:
loc = ((const InferClause *) expr)->location; break; case T_OnConflictClause:
loc = ((const OnConflictClause *) expr)->location; break; case T_CTESearchClause:
loc = ((const CTESearchClause *) expr)->location; break; case T_CTECycleClause:
loc = ((const CTECycleClause *) expr)->location; break; case T_CommonTableExpr:
loc = ((const CommonTableExpr *) expr)->location; break; case T_JsonKeyValue: /* just use the key's location */
loc = exprLocation((Node *) ((const JsonKeyValue *) expr)->key); break; case T_JsonObjectConstructor:
loc = ((const JsonObjectConstructor *) expr)->location; break; case T_JsonArrayConstructor:
loc = ((const JsonArrayConstructor *) expr)->location; break; case T_JsonArrayQueryConstructor:
loc = ((const JsonArrayQueryConstructor *) expr)->location; break; case T_JsonAggConstructor:
loc = ((const JsonAggConstructor *) expr)->location; break; case T_JsonObjectAgg:
loc = exprLocation((Node *) ((const JsonObjectAgg *) expr)->constructor); break; case T_JsonArrayAgg:
loc = exprLocation((Node *) ((const JsonArrayAgg *) expr)->constructor); break; case T_PlaceHolderVar: /* just use argument's location */
loc = exprLocation((Node *) ((const PlaceHolderVar *) expr)->phexpr); break; case T_InferenceElem: /* just use nested expr's location */
loc = exprLocation((Node *) ((const InferenceElem *) expr)->expr); break; case T_PartitionElem:
loc = ((const PartitionElem *) expr)->location; break; case T_PartitionSpec:
loc = ((const PartitionSpec *) expr)->location; break; case T_PartitionBoundSpec:
loc = ((const PartitionBoundSpec *) expr)->location; break; case T_PartitionRangeDatum:
loc = ((const PartitionRangeDatum *) expr)->location; break; default: /* for any other node type it's just unknown... */
loc = -1; break;
} return loc;
}
/* *fix_opfuncids *CalculateopfuncidfieldfromopnoforeachOpExprnodeingiventree. *Thegiventreecanbeanythingexpression_tree_walkerhandles. * *Theargumentismodifiedin-place.(ThisisOKsincewe'dwantthe *samechangeforanynode,evenifitgetsvisitedmorethanoncedueto *sharedstructure.)
*/ void
fix_opfuncids(Node *node)
{ /* This tree walk requires no special setup, so away we go... */
fix_opfuncids_walker(node, NULL);
}
if (checker(expr->aggfnoid, context)) returntrue;
} break; case T_WindowFunc:
{
WindowFunc *expr = (WindowFunc *) node;
if (checker(expr->winfnoid, context)) returntrue;
} break; case T_FuncExpr:
{
FuncExpr *expr = (FuncExpr *) node;
if (checker(expr->funcid, context)) returntrue;
} break; case T_OpExpr: case T_DistinctExpr: /* struct-equivalent to OpExpr */ case T_NullIfExpr: /* struct-equivalent to OpExpr */
{
OpExpr *expr = (OpExpr *) node;
/* Set opfuncid if it wasn't set already */
set_opfuncid(expr); if (checker(expr->opfuncid, context)) returntrue;
} break; case T_ScalarArrayOpExpr:
{
ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
set_sa_opfuncid(expr); if (checker(expr->opfuncid, context)) returntrue;
} break; case T_CoerceViaIO:
{
CoerceViaIO *expr = (CoerceViaIO *) node;
Oid iofunc;
Oid typioparam; bool typisvarlena;
/* check the result type's input function */
getTypeInputInfo(expr->resulttype,
&iofunc, &typioparam); if (checker(iofunc, context)) returntrue; /* check the input type's output function */
getTypeOutputInfo(exprType((Node *) expr->arg),
&iofunc, &typisvarlena); if (checker(iofunc, context)) returntrue;
} break; case T_RowCompareExpr:
{
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
ListCell *opid;
foreach(opid, rcexpr->opnos)
{
Oid opfuncid = get_opcode(lfirst_oid(opid));
/* Guard against stack overflow due to overly complex expressions */
check_stack_depth();
switch (nodeTag(node))
{ case T_Var: case T_Const: case T_Param: case T_CaseTestExpr: case T_SQLValueFunction: case T_CoerceToDomainValue: case T_SetToDefault: case T_CurrentOfExpr: case T_NextValueExpr: case T_RangeTblRef: case T_SortGroupClause: case T_CTESearchClause: case T_MergeSupportFunc: /* primitive node types with no expression subnodes */ break; case T_WithCheckOption: return WALK(((WithCheckOption *) node)->qual); case T_Aggref:
{
Aggref *expr = (Aggref *) node;
/* recurse directly on Lists */ if (LIST_WALK(expr->aggdirectargs)) returntrue; if (LIST_WALK(expr->args)) returntrue; if (LIST_WALK(expr->aggorder)) returntrue; if (LIST_WALK(expr->aggdistinct)) returntrue; if (WALK(expr->aggfilter)) returntrue;
} break; case T_GroupingFunc:
{
GroupingFunc *grouping = (GroupingFunc *) node;
if (LIST_WALK(grouping->args)) returntrue;
} break; case T_WindowFunc:
{
WindowFunc *expr = (WindowFunc *) node;
/* recurse directly on List */ if (LIST_WALK(expr->args)) returntrue; if (WALK(expr->aggfilter)) returntrue; if (WALK(expr->runCondition)) returntrue;
} break; case T_WindowFuncRunCondition:
{
WindowFuncRunCondition *expr = (WindowFuncRunCondition *) node;
if (WALK(expr->arg)) returntrue;
} break; case T_SubscriptingRef:
{
SubscriptingRef *sbsref = (SubscriptingRef *) node;
/* recurse directly for upper/lower container index lists */ if (LIST_WALK(sbsref->refupperindexpr)) returntrue; if (LIST_WALK(sbsref->reflowerindexpr)) returntrue; /* walker must see the refexpr and refassgnexpr, however */ if (WALK(sbsref->refexpr)) returntrue;
if (WALK(sbsref->refassgnexpr)) returntrue;
} break; case T_FuncExpr:
{
FuncExpr *expr = (FuncExpr *) node;
if (LIST_WALK(expr->args)) returntrue;
} break; case T_NamedArgExpr: return WALK(((NamedArgExpr *) node)->arg); case T_OpExpr: case T_DistinctExpr: /* struct-equivalent to OpExpr */ case T_NullIfExpr: /* struct-equivalent to OpExpr */
{
OpExpr *expr = (OpExpr *) node;
if (LIST_WALK(expr->args)) returntrue;
} break; case T_ScalarArrayOpExpr:
{
ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
if (LIST_WALK(expr->args)) returntrue;
} break; case T_BoolExpr:
{
BoolExpr *expr = (BoolExpr *) node;
if (LIST_WALK(expr->args)) returntrue;
} break; case T_SubLink:
{
SubLink *sublink = (SubLink *) node;
/* recurse into the testexpr, but not into the Plan */ if (WALK(subplan->testexpr)) returntrue; /* also examine args list */ if (LIST_WALK(subplan->args)) returntrue;
} break; case T_AlternativeSubPlan: return LIST_WALK(((AlternativeSubPlan *) node)->subplans); case T_FieldSelect: return WALK(((FieldSelect *) node)->arg); case T_FieldStore:
{
FieldStore *fstore = (FieldStore *) node;
if (WALK(fstore->arg)) returntrue; if (WALK(fstore->newvals)) returntrue;
} break; case T_RelabelType: return WALK(((RelabelType *) node)->arg); case T_CoerceViaIO: return WALK(((CoerceViaIO *) node)->arg); case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
if (WALK(acoerce->arg)) returntrue; if (WALK(acoerce->elemexpr)) returntrue;
} break; case T_ConvertRowtypeExpr: return WALK(((ConvertRowtypeExpr *) node)->arg); case T_CollateExpr: return WALK(((CollateExpr *) node)->arg); case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
if (WALK(caseexpr->arg)) returntrue; /* we assume walker doesn't care about CaseWhens, either */
foreach(temp, caseexpr->args)
{
CaseWhen *when = lfirst_node(CaseWhen, temp);
if (WALK(when->expr)) returntrue; if (WALK(when->result)) returntrue;
} if (WALK(caseexpr->defresult)) returntrue;
} break; case T_ArrayExpr: return WALK(((ArrayExpr *) node)->elements); case T_RowExpr: /* Assume colnames isn't interesting */ return WALK(((RowExpr *) node)->args); case T_RowCompareExpr:
{
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
if (WALK(rcexpr->largs)) returntrue; if (WALK(rcexpr->rargs)) returntrue;
} break; case T_CoalesceExpr: return WALK(((CoalesceExpr *) node)->args); case T_MinMaxExpr: return WALK(((MinMaxExpr *) node)->args); case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
if (WALK(xexpr->named_args)) returntrue; /* we assume walker doesn't care about arg_names */ if (WALK(xexpr->args)) returntrue;
} break; case T_JsonValueExpr:
{
JsonValueExpr *jve = (JsonValueExpr *) node;
if (WALK(jve->raw_expr)) returntrue; if (WALK(jve->formatted_expr)) returntrue;
} break; case T_JsonConstructorExpr:
{
JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
if (WALK(ctor->args)) returntrue; if (WALK(ctor->func)) returntrue; if (WALK(ctor->coercion)) returntrue;
} break; case T_JsonIsPredicate: return WALK(((JsonIsPredicate *) node)->expr); case T_JsonExpr:
{
JsonExpr *jexpr = (JsonExpr *) node;
if (WALK(jexpr->formatted_expr)) returntrue; if (WALK(jexpr->path_spec)) returntrue; if (WALK(jexpr->passing_values)) returntrue; /* we assume walker doesn't care about passing_names */ if (WALK(jexpr->on_empty)) returntrue; if (WALK(jexpr->on_error)) returntrue;
} break; case T_JsonBehavior:
{
JsonBehavior *behavior = (JsonBehavior *) node;
if (WALK(behavior->expr)) returntrue;
} break; case T_NullTest: return WALK(((NullTest *) node)->arg); case T_BooleanTest: return WALK(((BooleanTest *) node)->arg); case T_CoerceToDomain: return WALK(((CoerceToDomain *) node)->arg); case T_TargetEntry: return WALK(((TargetEntry *) node)->expr); case T_Query: /* Do nothing with a sub-Query, per discussion above */ break; case T_WindowClause:
{
WindowClause *wc = (WindowClause *) node;
if (WALK(wc->partitionClause)) returntrue; if (WALK(wc->orderClause)) returntrue; if (WALK(wc->startOffset)) returntrue; if (WALK(wc->endOffset)) returntrue;
} break; case T_CTECycleClause:
{
CTECycleClause *cc = (CTECycleClause *) node;
if (WALK(cc->cycle_mark_value)) returntrue; if (WALK(cc->cycle_mark_default)) returntrue;
} break; case T_CommonTableExpr:
{
CommonTableExpr *cte = (CommonTableExpr *) node;
/* *InvokethewalkerontheCTE'sQuerynode,soitcan *recurseintothesub-queryifitwantsto.
*/ if (WALK(cte->ctequery)) returntrue;
if (WALK(cte->search_clause)) returntrue; if (WALK(cte->cycle_clause)) returntrue;
} break; case T_JsonKeyValue:
{
JsonKeyValue *kv = (JsonKeyValue *) node;
if (WALK(kv->key)) returntrue; if (WALK(kv->value)) returntrue;
} break; case T_JsonObjectConstructor:
{
JsonObjectConstructor *ctor = (JsonObjectConstructor *) node;
if (LIST_WALK(ctor->exprs)) returntrue;
} break; case T_JsonArrayConstructor:
{
JsonArrayConstructor *ctor = (JsonArrayConstructor *) node;
if (LIST_WALK(ctor->exprs)) returntrue;
} break; case T_JsonArrayQueryConstructor:
{
JsonArrayQueryConstructor *ctor = (JsonArrayQueryConstructor *) node;
if (WALK(ctor->query)) returntrue;
} break; case T_JsonAggConstructor:
{
JsonAggConstructor *ctor = (JsonAggConstructor *) node;
if (WALK(ctor->agg_filter)) returntrue; if (WALK(ctor->agg_order)) returntrue; if (WALK(ctor->over)) returntrue;
} break; case T_JsonObjectAgg:
{
JsonObjectAgg *ctor = (JsonObjectAgg *) node;
if (WALK(ctor->constructor)) returntrue; if (WALK(ctor->arg)) returntrue;
} break; case T_JsonArrayAgg:
{
JsonArrayAgg *ctor = (JsonArrayAgg *) node;
if (WALK(ctor->constructor)) returntrue; if (WALK(ctor->arg)) returntrue;
} break;
case T_PartitionBoundSpec:
{
PartitionBoundSpec *pbs = (PartitionBoundSpec *) node;
if (WALK(pbs->listdatums)) returntrue; if (WALK(pbs->lowerdatums)) returntrue; if (WALK(pbs->upperdatums)) returntrue;
} break; case T_PartitionRangeDatum:
{
PartitionRangeDatum *prd = (PartitionRangeDatum *) node;
if (WALK(prd->value)) returntrue;
} break; case T_List:
foreach(temp, (List *) node)
{ if (WALK(lfirst(temp))) returntrue;
} break; case T_FromExpr:
{
FromExpr *from = (FromExpr *) node;
if (LIST_WALK(from->fromlist)) returntrue; if (WALK(from->quals)) returntrue;
} break; case T_OnConflictExpr:
{
OnConflictExpr *onconflict = (OnConflictExpr *) node;
if (WALK(onconflict->arbiterElems)) returntrue; if (WALK(onconflict->arbiterWhere)) returntrue; if (WALK(onconflict->onConflictSet)) returntrue; if (WALK(onconflict->onConflictWhere)) returntrue; if (WALK(onconflict->exclRelTlist)) returntrue;
} break; case T_MergeAction:
{
MergeAction *action = (MergeAction *) node;
if (WALK(action->qual)) returntrue; if (WALK(action->targetList)) returntrue;
} break; case T_PartitionPruneStepOp:
{
PartitionPruneStepOp *opstep = (PartitionPruneStepOp *) node;
if (WALK(opstep->exprs)) returntrue;
} break; case T_PartitionPruneStepCombine: /* no expression subnodes */ break; case T_JoinExpr:
{
JoinExpr *join = (JoinExpr *) node;
if (WALK(join->larg)) returntrue; if (WALK(join->rarg)) returntrue; if (WALK(join->quals)) returntrue;
if (WALK(setop->larg)) returntrue; if (WALK(setop->rarg)) returntrue;
/* groupClauses are deemed uninteresting */
} break; case T_IndexClause:
{
IndexClause *iclause = (IndexClause *) node;
if (WALK(iclause->rinfo)) returntrue; if (LIST_WALK(iclause->indexquals)) returntrue;
} break; case T_PlaceHolderVar: return WALK(((PlaceHolderVar *) node)->phexpr); case T_InferenceElem: return WALK(((InferenceElem *) node)->expr); case T_ReturningExpr: return WALK(((ReturningExpr *) node)->retexpr); case T_AppendRelInfo:
{
AppendRelInfo *appinfo = (AppendRelInfo *) node;
if (LIST_WALK(appinfo->translated_vars)) returntrue;
} break; case T_PlaceHolderInfo: return WALK(((PlaceHolderInfo *) node)->ph_var); case T_RangeTblFunction: return WALK(((RangeTblFunction *) node)->funcexpr); case T_TableSampleClause:
{
TableSampleClause *tsc = (TableSampleClause *) node;
if (LIST_WALK(tsc->args)) returntrue; if (WALK(tsc->repeatable)) returntrue;
} break; case T_TableFunc:
{
TableFunc *tf = (TableFunc *) node;
if (WALK(tf->ns_uris)) returntrue; if (WALK(tf->docexpr)) returntrue; if (WALK(tf->rowexpr)) returntrue; if (WALK(tf->colexprs)) returntrue; if (WALK(tf->coldefexprs)) returntrue; if (WALK(tf->colvalexprs)) returntrue; if (WALK(tf->passingvalexprs)) returntrue;
} break; default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node)); break;
} returnfalse;
/* The WALK() macro can be re-used below, but LIST_WALK() not so much */ #undef LIST_WALK
}
if (WALK(query->targetList)) returntrue; if (WALK(query->withCheckOptions)) returntrue; if (WALK(query->onConflict)) returntrue; if (WALK(query->mergeActionList)) returntrue; if (WALK(query->mergeJoinCondition)) returntrue; if (WALK(query->returningList)) returntrue; if (WALK(query->jointree)) returntrue; if (WALK(query->setOperations)) returntrue; if (WALK(query->havingQual)) returntrue; if (WALK(query->limitOffset)) returntrue; if (WALK(query->limitCount)) returntrue;
/* *Mostcallersaren'tinterestedinSortGroupClausenodessincethose *don'tcontainactualexpressions.HowevertheydocontainOIDswhich *maybeneededbydependencywalkersetc.
*/ if ((flags & QTW_EXAMINE_SORTGROUP))
{ if (WALK(query->groupClause)) returntrue; if (WALK(query->windowClause)) returntrue; if (WALK(query->sortClause)) returntrue; if (WALK(query->distinctClause)) returntrue;
} else
{ /* *ButweneedtowalktheexpressionsunderWindowClausenodeseven *ifwe'renotinterestedinSortGroupClausenodes.
*/
ListCell *lc;
if (range_table_entry_walker(rte, walker, context, flags)) returntrue;
} returnfalse;
}
/* *SomecallersevenwanttoscantheexpressionsinindividualRTEs.
*/ bool
range_table_entry_walker_impl(RangeTblEntry *rte,
tree_walker_callback walker, void *context, int flags)
{ /* *WalkersmightneedtoexaminetheRTEnodeitselfeitherbeforeor *aftervisitingitscontents(or,conceivably,both).Notethatifyou *specifyneitherflag,thewalkerwon'tbecalledontheRTEatall.
*/ if (flags & QTW_EXAMINE_RTES_BEFORE) if (WALK(rte)) returntrue;
switch (rte->rtekind)
{ case RTE_RELATION: if (WALK(rte->tablesample)) returntrue; break; case RTE_SUBQUERY: if (!(flags & QTW_IGNORE_RT_SUBQUERIES)) if (WALK(rte->subquery)) returntrue; break; case RTE_JOIN: if (!(flags & QTW_IGNORE_JOINALIASES)) if (WALK(rte->joinaliasvars)) returntrue; break; case RTE_FUNCTION: if (WALK(rte->functions)) returntrue; break; case RTE_TABLEFUNC: if (WALK(rte->tablefunc)) returntrue; break; case RTE_VALUES: if (WALK(rte->values_lists)) returntrue; break; case RTE_CTE: case RTE_NAMEDTUPLESTORE: case RTE_RESULT: /* nothing to do */ break; case RTE_GROUP: if (!(flags & QTW_IGNORE_GROUPEXPRS)) if (WALK(rte->groupexprs)) returntrue; break;
}
if (WALK(rte->securityQuals)) returntrue;
if (flags & QTW_EXAMINE_RTES_AFTER) if (WALK(rte)) returntrue;
returnfalse;
}
/* *expression_tree_mutator()isdesignedtosupportroutinesthatmakea *modifiedcopyofanexpressiontree,withsomenodesbeingadded, *removed,orreplacedbynewsubtrees.Theoriginaltreeis(normally) *notchanged.Eachrecursionlevelisresponsibleforreturningacopyof *(orappropriatelymodifiedsubstitutefor)thesubtreeitishanded. *Amutatorroutineshouldlooklikethis: * *Node*my_mutator(Node*node,my_struct*context) *{ *if(node==NULL) *returnNULL; *// check for nodes that special work is required for, eg: *if(IsA(node,Var)) *{ *...createandreturnmodifiedcopyofVarnode *} *elseif(IsA(node,...)) *{ *...dospecialtransformationsofothernodetypes *} *// for any node type not specially processed, do: *returnexpression_tree_mutator(node,my_mutator,context); *} * *The"context"argumentpointstoastructthatholdswhatevercontext *informationthemutatorroutineneeds---itcanbeusedtoreturnextra *datagatheredbythemutator,too.Thisargumentisnottouchedby *expression_tree_mutator,butitispasseddowntorecursivesub-invocations *ofmy_mutator.Thetreewalkisstartedfromasetuproutinethat *fillsintheappropriatecontextstruct,callsmy_mutatorwiththe *top-levelnodeofthetree,anddoesanyrequiredpost-processing. * *EachlevelofrecursionmustreturnanappropriatelymodifiedNode. *Ifexpression_tree_mutator()iscalled,itwillmakeanexactcopy *ofthegivenNode,butinvokemy_mutator()tocopythesub-node(s) *ofthatNode.Inthisway,my_mutator()hasfullcontroloverthe *copyingprocessbutneednotdirectlydealwithexpressiontrees *thatithasnointerestin. * *Justasforexpression_tree_walker,thenodetypeshandledby *expression_tree_mutatorincludeallthosenormallyfoundintargetlists *andqualifierclausesduringtheplanningstage. * *expression_tree_mutatorwillhandleSubLinknodesbyrecursingnormally *intothe"testexpr"subtree(whichisanexpressionbelongingtotheouter *plan).Itwillalsocallthemutatoronthesub-Querynode;however,when *expression_tree_mutatoritselfiscalledonaQuerynode,itdoesnothing *andreturnstheunmodifiedQuerynode.Theneteffectisthatunlessthe *mutatordoessomethingspecialataQuerynode,sub-selectswillnotbe *visitedormodified;theoriginalsub-selectwillbelinkedtobythenew *SubLinknode.Mutatorsthatwanttodescendintosub-selectswillusually *dosobyrecognizingQuerynodesandcallingquery_tree_mutator(below). * *expression_tree_mutatorwillhandleaSubPlannodebyrecursingintothe *"testexpr"andthe"args"list(whichbelongtotheouterplan),butit *willsimplycopythelinktotheinnerplan,sincethat'stypicallywhat *expressiontreemutatorswant.Amutatorthatwantstomodifythesubplan *canforceappropriatebehaviorbyrecognizingSubPlanexpressionnodes *anddoingtherightthing.
*/
/* Guard against stack overflow due to overly complex expressions */
check_stack_depth();
switch (nodeTag(node))
{ /* *Primitivenodetypeswithnoexpressionsubnodes.Varand *Constarefrequentenoughtodeservespecialcases,theothers *wejustusecopyObjectfor.
*/ case T_Var:
{
Var *var = (Var *) node;
Var *newnode;
FLATCOPY(newnode, var, Var); /* Assume we need not copy the varnullingrels bitmapset */ return (Node *) newnode;
} break; case T_Const:
{ Const *oldnode = (Const *) node; Const *newnode;
FLATCOPY(newnode, oldnode, Const); /* XXX we don't bother with datumCopy; should we? */ return (Node *) newnode;
} break; case T_Param: case T_CaseTestExpr: case T_SQLValueFunction: case T_JsonFormat: case T_CoerceToDomainValue: case T_SetToDefault: case T_CurrentOfExpr: case T_NextValueExpr: case T_RangeTblRef: case T_SortGroupClause: case T_CTESearchClause: case T_MergeSupportFunc: return copyObject(node); case T_WithCheckOption:
{
WithCheckOption *wco = (WithCheckOption *) node;
WithCheckOption *newnode;
FLATCOPY(newnode, subplan, SubPlan); /* transform testexpr */
MUTATE(newnode->testexpr, subplan->testexpr, Node *); /* transform args list (params to be passed to subplan) */
MUTATE(newnode->args, subplan->args, List *); /* but not the sub-Plan itself, which is referenced as-is */ return (Node *) newnode;
} break; case T_AlternativeSubPlan:
{
AlternativeSubPlan *asplan = (AlternativeSubPlan *) node;
AlternativeSubPlan *newnode;
/* *Thewalkerhasalreadyvisitedthecurrentnode,andsoweneedonly *recurseintoanysub-nodesithas.
*/ if (node == NULL) returnfalse;
/* Guard against stack overflow due to overly complex expressions */
check_stack_depth();
switch (nodeTag(node))
{ case T_JsonFormat: case T_SetToDefault: case T_CurrentOfExpr: case T_SQLValueFunction: case T_Integer: case T_Float: case T_Boolean: case T_String: case T_BitString: case T_ParamRef: case T_A_Const: case T_A_Star: case T_MergeSupportFunc: case T_ReturningOption: /* primitive node types with no subnodes */ break; case T_Alias: /* we assume the colnames list isn't interesting */ break; case T_RangeVar: return WALK(((RangeVar *) node)->alias); case T_GroupingFunc: return WALK(((GroupingFunc *) node)->args); case T_SubLink:
{
SubLink *sublink = (SubLink *) node;
if (WALK(sublink->testexpr)) returntrue; /* we assume the operName is not interesting */ if (WALK(sublink->subselect)) returntrue;
} break; case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
if (WALK(caseexpr->arg)) returntrue; /* we assume walker doesn't care about CaseWhens, either */
foreach(temp, caseexpr->args)
{
CaseWhen *when = lfirst_node(CaseWhen, temp);
if (WALK(when->expr)) returntrue; if (WALK(when->result)) returntrue;
} if (WALK(caseexpr->defresult)) returntrue;
} break; case T_RowExpr: /* Assume colnames isn't interesting */ return WALK(((RowExpr *) node)->args); case T_CoalesceExpr: return WALK(((CoalesceExpr *) node)->args); case T_MinMaxExpr: return WALK(((MinMaxExpr *) node)->args); case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
if (WALK(xexpr->named_args)) returntrue; /* we assume walker doesn't care about arg_names */ if (WALK(xexpr->args)) returntrue;
} break; case T_JsonReturning: return WALK(((JsonReturning *) node)->format); case T_JsonValueExpr:
{
JsonValueExpr *jve = (JsonValueExpr *) node;
if (WALK(jve->raw_expr)) returntrue; if (WALK(jve->formatted_expr)) returntrue; if (WALK(jve->format)) returntrue;
} break; case T_JsonParseExpr:
{
JsonParseExpr *jpe = (JsonParseExpr *) node;
if (WALK(jpe->expr)) returntrue; if (WALK(jpe->output)) returntrue;
} break; case T_JsonScalarExpr:
{
JsonScalarExpr *jse = (JsonScalarExpr *) node;
if (WALK(jse->expr)) returntrue; if (WALK(jse->output)) returntrue;
} break; case T_JsonSerializeExpr:
{
JsonSerializeExpr *jse = (JsonSerializeExpr *) node;
if (WALK(jse->expr)) returntrue; if (WALK(jse->output)) returntrue;
} break; case T_JsonConstructorExpr:
{
JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
if (WALK(ctor->args)) returntrue; if (WALK(ctor->func)) returntrue; if (WALK(ctor->coercion)) returntrue; if (WALK(ctor->returning)) returntrue;
} break; case T_JsonIsPredicate: return WALK(((JsonIsPredicate *) node)->expr); case T_JsonArgument: return WALK(((JsonArgument *) node)->val); case T_JsonFuncExpr:
{
JsonFuncExpr *jfe = (JsonFuncExpr *) node;
if (WALK(jfe->context_item)) returntrue; if (WALK(jfe->pathspec)) returntrue; if (WALK(jfe->passing)) returntrue; if (WALK(jfe->output)) returntrue; if (WALK(jfe->on_empty)) returntrue; if (WALK(jfe->on_error)) returntrue;
} break; case T_JsonBehavior:
{
JsonBehavior *jb = (JsonBehavior *) node;
if (WALK(jb->expr)) returntrue;
} break; case T_JsonTable:
{
JsonTable *jt = (JsonTable *) node;
if (WALK(jt->context_item)) returntrue; if (WALK(jt->pathspec)) returntrue; if (WALK(jt->passing)) returntrue; if (WALK(jt->columns)) returntrue; if (WALK(jt->on_error)) returntrue;
} break; case T_JsonTableColumn:
{
JsonTableColumn *jtc = (JsonTableColumn *) node;
if (WALK(jtc->typeName)) returntrue; if (WALK(jtc->on_empty)) returntrue; if (WALK(jtc->on_error)) returntrue; if (WALK(jtc->columns)) returntrue;
} break; case T_JsonTablePathSpec: return WALK(((JsonTablePathSpec *) node)->string); case T_NullTest: return WALK(((NullTest *) node)->arg); case T_BooleanTest: return WALK(((BooleanTest *) node)->arg); case T_JoinExpr:
{
JoinExpr *join = (JoinExpr *) node;
if (WALK(join->larg)) returntrue; if (WALK(join->rarg)) returntrue; if (WALK(join->quals)) returntrue; if (WALK(join->alias)) returntrue; /* using list is deemed uninteresting */
} break; case T_IntoClause:
{
IntoClause *into = (IntoClause *) node;
if (WALK(into->rel)) returntrue; /* colNames, options are deemed uninteresting */ /* viewQuery should be null in raw parsetree, but check it */ if (WALK(into->viewQuery)) returntrue;
} break; case T_List:
foreach(temp, (List *) node)
{ if (WALK((Node *) lfirst(temp))) returntrue;
} break; case T_InsertStmt:
{
InsertStmt *stmt = (InsertStmt *) node;
if (WALK(stmt->relation)) returntrue; if (WALK(stmt->cols)) returntrue; if (WALK(stmt->selectStmt)) returntrue; if (WALK(stmt->onConflictClause)) returntrue; if (WALK(stmt->returningClause)) returntrue; if (WALK(stmt->withClause)) returntrue;
} break; case T_DeleteStmt:
{
DeleteStmt *stmt = (DeleteStmt *) node;
if (WALK(stmt->relation)) returntrue; if (WALK(stmt->usingClause)) returntrue; if (WALK(stmt->whereClause)) returntrue; if (WALK(stmt->returningClause)) returntrue; if (WALK(stmt->withClause)) returntrue;
} break; case T_UpdateStmt:
{
UpdateStmt *stmt = (UpdateStmt *) node;
if (WALK(stmt->relation)) returntrue; if (WALK(stmt->targetList)) returntrue; if (WALK(stmt->whereClause)) returntrue; if (WALK(stmt->fromClause)) returntrue; if (WALK(stmt->returningClause)) returntrue; if (WALK(stmt->withClause)) returntrue;
} break; case T_MergeStmt:
{
MergeStmt *stmt = (MergeStmt *) node;
if (WALK(stmt->relation)) returntrue; if (WALK(stmt->sourceRelation)) returntrue; if (WALK(stmt->joinCondition)) returntrue; if (WALK(stmt->mergeWhenClauses)) returntrue; if (WALK(stmt->returningClause)) returntrue; if (WALK(stmt->withClause)) returntrue;
} break; case T_MergeWhenClause:
{
MergeWhenClause *mergeWhenClause = (MergeWhenClause *) node;
if (WALK(mergeWhenClause->condition)) returntrue; if (WALK(mergeWhenClause->targetList)) returntrue; if (WALK(mergeWhenClause->values)) returntrue;
} break; case T_ReturningClause:
{
ReturningClause *returning = (ReturningClause *) node;
if (WALK(returning->options)) returntrue; if (WALK(returning->exprs)) returntrue;
} break; case T_SelectStmt:
{
SelectStmt *stmt = (SelectStmt *) node;
if (WALK(stmt->distinctClause)) returntrue; if (WALK(stmt->intoClause)) returntrue; if (WALK(stmt->targetList)) returntrue; if (WALK(stmt->fromClause)) returntrue; if (WALK(stmt->whereClause)) returntrue; if (WALK(stmt->groupClause)) returntrue; if (WALK(stmt->havingClause)) returntrue; if (WALK(stmt->windowClause)) returntrue; if (WALK(stmt->valuesLists)) returntrue; if (WALK(stmt->sortClause)) returntrue; if (WALK(stmt->limitOffset)) returntrue; if (WALK(stmt->limitCount)) returntrue; if (WALK(stmt->lockingClause)) returntrue; if (WALK(stmt->withClause)) returntrue; if (WALK(stmt->larg)) returntrue; if (WALK(stmt->rarg)) returntrue;
} break; case T_PLAssignStmt:
{
PLAssignStmt *stmt = (PLAssignStmt *) node;
if (WALK(stmt->indirection)) returntrue; if (WALK(stmt->val)) returntrue;
} break; case T_A_Expr:
{
A_Expr *expr = (A_Expr *) node;
if (WALK(expr->lexpr)) returntrue; if (WALK(expr->rexpr)) returntrue; /* operator name is deemed uninteresting */
} break; case T_BoolExpr:
{
BoolExpr *expr = (BoolExpr *) node;
if (WALK(expr->args)) returntrue;
} break; case T_ColumnRef: /* we assume the fields contain nothing interesting */ break; case T_FuncCall:
{
FuncCall *fcall = (FuncCall *) node;
if (WALK(fcall->args)) returntrue; if (WALK(fcall->agg_order)) returntrue; if (WALK(fcall->agg_filter)) returntrue; if (WALK(fcall->over)) returntrue; /* function name is deemed uninteresting */
} break; case T_NamedArgExpr: return WALK(((NamedArgExpr *) node)->arg); case T_A_Indices:
{
A_Indices *indices = (A_Indices *) node;
if (WALK(indices->lidx)) returntrue; if (WALK(indices->uidx)) returntrue;
} break; case T_A_Indirection:
{
A_Indirection *indir = (A_Indirection *) node;
if (WALK(indir->arg)) returntrue; if (WALK(indir->indirection)) returntrue;
} break; case T_A_ArrayExpr: return WALK(((A_ArrayExpr *) node)->elements); case T_ResTarget:
{
ResTarget *rt = (ResTarget *) node;
if (WALK(rt->indirection)) returntrue; if (WALK(rt->val)) returntrue;
} break; case T_MultiAssignRef: return WALK(((MultiAssignRef *) node)->source); case T_TypeCast:
{
TypeCast *tc = (TypeCast *) node;
if (WALK(tc->arg)) returntrue; if (WALK(tc->typeName)) returntrue;
} break; case T_CollateClause: return WALK(((CollateClause *) node)->arg); case T_SortBy: return WALK(((SortBy *) node)->node); case T_WindowDef:
{
WindowDef *wd = (WindowDef *) node;
if (WALK(wd->partitionClause)) returntrue; if (WALK(wd->orderClause)) returntrue; if (WALK(wd->startOffset)) returntrue; if (WALK(wd->endOffset)) returntrue;
} break; case T_RangeSubselect:
{
RangeSubselect *rs = (RangeSubselect *) node;
if (WALK(rs->subquery)) returntrue; if (WALK(rs->alias)) returntrue;
} break; case T_RangeFunction:
{
RangeFunction *rf = (RangeFunction *) node;
if (WALK(rf->functions)) returntrue; if (WALK(rf->alias)) returntrue; if (WALK(rf->coldeflist)) returntrue;
} break; case T_RangeTableSample:
{
RangeTableSample *rts = (RangeTableSample *) node;
if (WALK(rts->relation)) returntrue; /* method name is deemed uninteresting */ if (WALK(rts->args)) returntrue; if (WALK(rts->repeatable)) returntrue;
} break; case T_RangeTableFunc:
{
RangeTableFunc *rtf = (RangeTableFunc *) node;
if (WALK(rtf->docexpr)) returntrue; if (WALK(rtf->rowexpr)) returntrue; if (WALK(rtf->namespaces)) returntrue; if (WALK(rtf->columns)) returntrue; if (WALK(rtf->alias)) returntrue;
} break; case T_RangeTableFuncCol:
{
RangeTableFuncCol *rtfc = (RangeTableFuncCol *) node;
if (WALK(rtfc->colexpr)) returntrue; if (WALK(rtfc->coldefexpr)) returntrue;
} break; case T_TypeName:
{ TypeName *tn = (TypeName *) node;
if (WALK(tn->typmods)) returntrue; if (WALK(tn->arrayBounds)) returntrue; /* type name itself is deemed uninteresting */
} break; case T_ColumnDef:
{
ColumnDef *coldef = (ColumnDef *) node;
if (WALK(coldef->typeName)) returntrue; if (WALK(coldef->raw_default)) returntrue; if (WALK(coldef->collClause)) returntrue; /* for now, constraints are ignored */
} break; case T_IndexElem:
{
IndexElem *indelem = (IndexElem *) node;
if (WALK(indelem->expr)) returntrue; /* collation and opclass names are deemed uninteresting */
} break; case T_GroupingSet: return WALK(((GroupingSet *) node)->content); case T_LockingClause: return WALK(((LockingClause *) node)->lockedRels); case T_XmlSerialize:
{
XmlSerialize *xs = (XmlSerialize *) node;
if (WALK(xs->expr)) returntrue; if (WALK(xs->typeName)) returntrue;
} break; case T_WithClause: return WALK(((WithClause *) node)->ctes); case T_InferClause:
{
InferClause *stmt = (InferClause *) node;
if (WALK(stmt->indexElems)) returntrue; if (WALK(stmt->whereClause)) returntrue;
} break; case T_OnConflictClause:
{
OnConflictClause *stmt = (OnConflictClause *) node;
if (WALK(stmt->infer)) returntrue; if (WALK(stmt->targetList)) returntrue; if (WALK(stmt->whereClause)) returntrue;
} break; case T_CommonTableExpr: /* search_clause and cycle_clause are not interesting here */ return WALK(((CommonTableExpr *) node)->ctequery); case T_JsonOutput:
{
JsonOutput *out = (JsonOutput *) node;
if (WALK(out->typeName)) returntrue; if (WALK(out->returning)) returntrue;
} break; case T_JsonKeyValue:
{
JsonKeyValue *jkv = (JsonKeyValue *) node;
if (WALK(jkv->key)) returntrue; if (WALK(jkv->value)) returntrue;
} break; case T_JsonObjectConstructor:
{
JsonObjectConstructor *joc = (JsonObjectConstructor *) node;
if (WALK(joc->output)) returntrue; if (WALK(joc->exprs)) returntrue;
} break; case T_JsonArrayConstructor:
{
JsonArrayConstructor *jac = (JsonArrayConstructor *) node;
if (WALK(jac->output)) returntrue; if (WALK(jac->exprs)) returntrue;
} break; case T_JsonAggConstructor:
{
JsonAggConstructor *ctor = (JsonAggConstructor *) node;
if (WALK(ctor->output)) returntrue; if (WALK(ctor->agg_order)) returntrue; if (WALK(ctor->agg_filter)) returntrue; if (WALK(ctor->over)) returntrue;
} break; case T_JsonObjectAgg:
{
JsonObjectAgg *joa = (JsonObjectAgg *) node;
if (WALK(joa->constructor)) returntrue; if (WALK(joa->arg)) returntrue;
} break; case T_JsonArrayAgg:
{
JsonArrayAgg *jaa = (JsonArrayAgg *) node;
if (WALK(jaa->constructor)) returntrue; if (WALK(jaa->arg)) returntrue;
} break; case T_JsonArrayQueryConstructor:
{
JsonArrayQueryConstructor *jaqc = (JsonArrayQueryConstructor *) node;
if (WALK(jaqc->output)) returntrue; if (WALK(jaqc->query)) returntrue;
} break; default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node)); break;
} returnfalse;
}
/* *WalktheconstituentplansofaModifyTable,Append,MergeAppend, *BitmapAnd,orBitmapOrnode.
*/ staticbool
planstate_walk_members(PlanState **planstates, int nplans,
planstate_tree_walker_callback walker, void *context)
{ int j;
for (j = 0; j < nplans; j++)
{ if (PSWALK(planstates[j])) returntrue;
}
returnfalse;
}
Messung V0.5 in Prozent
¤ 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.171Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
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.