mirror of https://github.com/citusdata/citus.git
Merge pull request #1632 from citusdata/update_copied_code
Add latest PostgreSQL changes to copy-pasted code cr: @mtuncerpull/1635/merge
commit
e29ebe57fd
|
@ -3111,7 +3111,9 @@ InterShardDDLTaskList(Oid leftRelationId, Oid rightRelationId,
|
||||||
*
|
*
|
||||||
* This code is heavily borrowed from RangeVarCallbackForDropRelation() in
|
* This code is heavily borrowed from RangeVarCallbackForDropRelation() in
|
||||||
* commands/tablecmds.c in Postgres source. We need this to ensure the right
|
* commands/tablecmds.c in Postgres source. We need this to ensure the right
|
||||||
* order of locking while dealing with DROP INDEX statments.
|
* order of locking while dealing with DROP INDEX statments. Because we are
|
||||||
|
* exclusively using this callback for INDEX processing, the PARTITION-related
|
||||||
|
* logic from PostgreSQL's similar callback has been omitted as unneeded.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, void *arg)
|
RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, void *arg)
|
||||||
|
|
|
@ -93,7 +93,7 @@
|
||||||
#define PRETTYINDENT_JOIN 4
|
#define PRETTYINDENT_JOIN 4
|
||||||
#define PRETTYINDENT_VAR 4
|
#define PRETTYINDENT_VAR 4
|
||||||
|
|
||||||
#define PRETTYINDENT_LIMIT 40 /* wrap limit */
|
#define PRETTYINDENT_LIMIT 40 /* wrap limit */
|
||||||
|
|
||||||
/* Pretty flags */
|
/* Pretty flags */
|
||||||
#define PRETTYFLAG_PAREN 1
|
#define PRETTYFLAG_PAREN 1
|
||||||
|
@ -125,8 +125,8 @@ typedef struct
|
||||||
bool varprefix; /* TRUE to print prefixes on Vars */
|
bool varprefix; /* TRUE to print prefixes on Vars */
|
||||||
Oid distrelid; /* the distributed table being modified, if valid */
|
Oid distrelid; /* the distributed table being modified, if valid */
|
||||||
int64 shardid; /* a distributed table's shardid, if positive */
|
int64 shardid; /* a distributed table's shardid, if positive */
|
||||||
ParseExprKind special_exprkind; /* set only for exprkinds needing
|
ParseExprKind special_exprkind; /* set only for exprkinds needing special
|
||||||
* special handling */
|
* handling */
|
||||||
} deparse_context;
|
} deparse_context;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -292,7 +292,7 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char name[NAMEDATALEN]; /* Hash key --- must be first */
|
char name[NAMEDATALEN]; /* Hash key --- must be first */
|
||||||
int counter; /* Largest addition used so far for name */
|
int counter; /* Largest addition used so far for name */
|
||||||
} NameHashEntry;
|
} NameHashEntry;
|
||||||
|
|
||||||
|
@ -390,6 +390,9 @@ static void get_rule_expr(Node *node, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
|
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
|
static void get_rule_expr_funccall(Node *node, deparse_context *context,
|
||||||
|
bool showimplicit);
|
||||||
|
static bool looks_like_function(Node *node);
|
||||||
static void get_oper_expr(OpExpr *expr, deparse_context *context);
|
static void get_oper_expr(OpExpr *expr, deparse_context *context);
|
||||||
static void get_func_expr(FuncExpr *expr, deparse_context *context,
|
static void get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
|
@ -2148,19 +2151,19 @@ get_select_query_def(Query *query, deparse_context *context,
|
||||||
break;
|
break;
|
||||||
case LCS_FORKEYSHARE:
|
case LCS_FORKEYSHARE:
|
||||||
appendContextKeyword(context, " FOR KEY SHARE",
|
appendContextKeyword(context, " FOR KEY SHARE",
|
||||||
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
||||||
break;
|
break;
|
||||||
case LCS_FORSHARE:
|
case LCS_FORSHARE:
|
||||||
appendContextKeyword(context, " FOR SHARE",
|
appendContextKeyword(context, " FOR SHARE",
|
||||||
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
||||||
break;
|
break;
|
||||||
case LCS_FORNOKEYUPDATE:
|
case LCS_FORNOKEYUPDATE:
|
||||||
appendContextKeyword(context, " FOR NO KEY UPDATE",
|
appendContextKeyword(context, " FOR NO KEY UPDATE",
|
||||||
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
||||||
break;
|
break;
|
||||||
case LCS_FORUPDATE:
|
case LCS_FORUPDATE:
|
||||||
appendContextKeyword(context, " FOR UPDATE",
|
appendContextKeyword(context, " FOR UPDATE",
|
||||||
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
-PRETTYINDENT_STD, PRETTYINDENT_STD, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3018,8 +3021,8 @@ get_insert_query_def(Query *query, deparse_context *context)
|
||||||
* tle->resname, since resname will fail to track RENAME.
|
* tle->resname, since resname will fail to track RENAME.
|
||||||
*/
|
*/
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||||
tle->resno)));
|
tle->resno)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print any indirection needed (subfields or subscripts), and strip
|
* Print any indirection needed (subfields or subscripts), and strip
|
||||||
|
@ -3299,8 +3302,11 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
||||||
/*
|
/*
|
||||||
* We must dig down into the expr to see if it's a PARAM_MULTIEXPR
|
* We must dig down into the expr to see if it's a PARAM_MULTIEXPR
|
||||||
* Param. That could be buried under FieldStores and ArrayRefs
|
* Param. That could be buried under FieldStores and ArrayRefs
|
||||||
* (cf processIndirection()), and underneath those there could be
|
* and CoerceToDomains (cf processIndirection()), and underneath
|
||||||
* an implicit type coercion.
|
* those there could be an implicit type coercion. Because we
|
||||||
|
* would ignore implicit type coercions anyway, we don't need to
|
||||||
|
* be as careful as processIndirection() is about descending past
|
||||||
|
* implicit CoerceToDomains.
|
||||||
*/
|
*/
|
||||||
expr = (Node *) tle->expr;
|
expr = (Node *) tle->expr;
|
||||||
while (expr)
|
while (expr)
|
||||||
|
@ -3319,6 +3325,14 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
||||||
break;
|
break;
|
||||||
expr = (Node *) aref->refassgnexpr;
|
expr = (Node *) aref->refassgnexpr;
|
||||||
}
|
}
|
||||||
|
else if (IsA(expr, CoerceToDomain))
|
||||||
|
{
|
||||||
|
CoerceToDomain *cdomain = (CoerceToDomain *) expr;
|
||||||
|
|
||||||
|
if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
|
||||||
|
break;
|
||||||
|
expr = (Node *) cdomain->arg;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3330,7 +3344,7 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
||||||
cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
|
cur_ma_sublink = (SubLink *) lfirst(next_ma_cell);
|
||||||
next_ma_cell = lnext(next_ma_cell);
|
next_ma_cell = lnext(next_ma_cell);
|
||||||
remaining_ma_columns = count_nonjunk_tlist_entries(
|
remaining_ma_columns = count_nonjunk_tlist_entries(
|
||||||
((Query *) cur_ma_sublink->subselect)->targetList);
|
((Query *) cur_ma_sublink->subselect)->targetList);
|
||||||
Assert(((Param *) expr)->paramid ==
|
Assert(((Param *) expr)->paramid ==
|
||||||
((cur_ma_sublink->subLinkId << 16) | 1));
|
((cur_ma_sublink->subLinkId << 16) | 1));
|
||||||
appendStringInfoChar(buf, '(');
|
appendStringInfoChar(buf, '(');
|
||||||
|
@ -3342,8 +3356,8 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
||||||
* tle->resname, since resname will fail to track RENAME.
|
* tle->resname, since resname will fail to track RENAME.
|
||||||
*/
|
*/
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
quote_identifier(get_relid_attribute_name(rte->relid,
|
quote_identifier(get_relid_attribute_name(rte->relid,
|
||||||
tle->resno)));
|
tle->resno)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print any indirection needed (subfields or subscripts), and strip
|
* Print any indirection needed (subfields or subscripts), and strip
|
||||||
|
@ -4423,6 +4437,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||||
case T_MinMaxExpr:
|
case T_MinMaxExpr:
|
||||||
case T_SQLValueFunction:
|
case T_SQLValueFunction:
|
||||||
case T_XmlExpr:
|
case T_XmlExpr:
|
||||||
|
case T_NextValueExpr:
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
case T_Aggref:
|
case T_Aggref:
|
||||||
case T_WindowFunc:
|
case T_WindowFunc:
|
||||||
|
@ -4532,17 +4547,17 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||||
return false;
|
return false;
|
||||||
return true; /* own parentheses */
|
return true; /* own parentheses */
|
||||||
}
|
}
|
||||||
case T_BoolExpr: /* lower precedence */
|
case T_BoolExpr: /* lower precedence */
|
||||||
case T_ArrayRef: /* other separators */
|
case T_ArrayRef: /* other separators */
|
||||||
case T_ArrayExpr: /* other separators */
|
case T_ArrayExpr: /* other separators */
|
||||||
case T_RowExpr: /* other separators */
|
case T_RowExpr: /* other separators */
|
||||||
case T_CoalesceExpr: /* own parentheses */
|
case T_CoalesceExpr: /* own parentheses */
|
||||||
case T_MinMaxExpr: /* own parentheses */
|
case T_MinMaxExpr: /* own parentheses */
|
||||||
case T_XmlExpr: /* own parentheses */
|
case T_XmlExpr: /* own parentheses */
|
||||||
case T_NullIfExpr: /* other separators */
|
case T_NullIfExpr: /* other separators */
|
||||||
case T_Aggref: /* own parentheses */
|
case T_Aggref: /* own parentheses */
|
||||||
case T_WindowFunc: /* own parentheses */
|
case T_WindowFunc: /* own parentheses */
|
||||||
case T_CaseExpr: /* other separators */
|
case T_CaseExpr: /* other separators */
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -4583,16 +4598,16 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||||
return false;
|
return false;
|
||||||
return true; /* own parentheses */
|
return true; /* own parentheses */
|
||||||
}
|
}
|
||||||
case T_ArrayRef: /* other separators */
|
case T_ArrayRef: /* other separators */
|
||||||
case T_ArrayExpr: /* other separators */
|
case T_ArrayExpr: /* other separators */
|
||||||
case T_RowExpr: /* other separators */
|
case T_RowExpr: /* other separators */
|
||||||
case T_CoalesceExpr: /* own parentheses */
|
case T_CoalesceExpr: /* own parentheses */
|
||||||
case T_MinMaxExpr: /* own parentheses */
|
case T_MinMaxExpr: /* own parentheses */
|
||||||
case T_XmlExpr: /* own parentheses */
|
case T_XmlExpr: /* own parentheses */
|
||||||
case T_NullIfExpr: /* other separators */
|
case T_NullIfExpr: /* other separators */
|
||||||
case T_Aggref: /* own parentheses */
|
case T_Aggref: /* own parentheses */
|
||||||
case T_WindowFunc: /* own parentheses */
|
case T_WindowFunc: /* own parentheses */
|
||||||
case T_CaseExpr: /* other separators */
|
case T_CaseExpr: /* other separators */
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -4891,7 +4906,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
appendStringInfo(buf, " %s %s (",
|
appendStringInfo(buf, " %s %s (",
|
||||||
generate_operator_name(expr->opno,
|
generate_operator_name(expr->opno,
|
||||||
exprType(arg1),
|
exprType(arg1),
|
||||||
get_base_element_type(exprType(arg2))),
|
get_base_element_type(exprType(arg2))),
|
||||||
expr->useOr ? "ANY" : "ALL");
|
expr->useOr ? "ANY" : "ALL");
|
||||||
get_rule_expr_paren(arg2, context, true, node);
|
get_rule_expr_paren(arg2, context, true, node);
|
||||||
|
|
||||||
|
@ -4911,7 +4926,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
|
((SubLink *) arg2)->subLinkType == EXPR_SUBLINK)
|
||||||
appendStringInfo(buf, "::%s",
|
appendStringInfo(buf, "::%s",
|
||||||
format_type_with_typemod(exprType(arg2),
|
format_type_with_typemod(exprType(arg2),
|
||||||
exprTypmod(arg2)));
|
exprTypmod(arg2)));
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
if (!PRETTY_PAREN(context))
|
if (!PRETTY_PAREN(context))
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
|
@ -5269,7 +5284,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
*/
|
*/
|
||||||
if (arrayexpr->elements == NIL)
|
if (arrayexpr->elements == NIL)
|
||||||
appendStringInfo(buf, "::%s",
|
appendStringInfo(buf, "::%s",
|
||||||
format_type_with_typemod(arrayexpr->array_typeid, -1));
|
format_type_with_typemod(arrayexpr->array_typeid, -1));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -5331,7 +5346,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
|
if (rowexpr->row_format == COERCE_EXPLICIT_CAST)
|
||||||
appendStringInfo(buf, "::%s",
|
appendStringInfo(buf, "::%s",
|
||||||
format_type_with_typemod(rowexpr->row_typeid, -1));
|
format_type_with_typemod(rowexpr->row_typeid, -1));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -5364,9 +5379,9 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
* be perfect.
|
* be perfect.
|
||||||
*/
|
*/
|
||||||
appendStringInfo(buf, ") %s ROW(",
|
appendStringInfo(buf, ") %s ROW(",
|
||||||
generate_operator_name(linitial_oid(rcexpr->opnos),
|
generate_operator_name(linitial_oid(rcexpr->opnos),
|
||||||
exprType(linitial(rcexpr->largs)),
|
exprType(linitial(rcexpr->largs)),
|
||||||
exprType(linitial(rcexpr->rargs))));
|
exprType(linitial(rcexpr->rargs))));
|
||||||
sep = "";
|
sep = "";
|
||||||
foreach(arg, rcexpr->rargs)
|
foreach(arg, rcexpr->rargs)
|
||||||
{
|
{
|
||||||
|
@ -5564,7 +5579,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
Assert(!con->constisnull);
|
Assert(!con->constisnull);
|
||||||
if (DatumGetBool(con->constvalue))
|
if (DatumGetBool(con->constvalue))
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
" PRESERVE WHITESPACE");
|
" PRESERVE WHITESPACE");
|
||||||
else
|
else
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
" STRIP WHITESPACE");
|
" STRIP WHITESPACE");
|
||||||
|
@ -5592,15 +5607,15 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
{
|
{
|
||||||
case XML_STANDALONE_YES:
|
case XML_STANDALONE_YES:
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
", STANDALONE YES");
|
", STANDALONE YES");
|
||||||
break;
|
break;
|
||||||
case XML_STANDALONE_NO:
|
case XML_STANDALONE_NO:
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
", STANDALONE NO");
|
", STANDALONE NO");
|
||||||
break;
|
break;
|
||||||
case XML_STANDALONE_NO_VALUE:
|
case XML_STANDALONE_NO_VALUE:
|
||||||
appendStringInfoString(buf,
|
appendStringInfoString(buf,
|
||||||
", STANDALONE NO VALUE");
|
", STANDALONE NO VALUE");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -5752,6 +5767,22 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_NextValueExpr:
|
||||||
|
{
|
||||||
|
NextValueExpr *nvexpr = (NextValueExpr *) node;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This isn't exactly nextval(), but that seems close enough
|
||||||
|
* for EXPLAIN's purposes.
|
||||||
|
*/
|
||||||
|
appendStringInfoString(buf, "nextval(");
|
||||||
|
simple_quote_literal(buf,
|
||||||
|
generate_relation_name(nvexpr->seqid,
|
||||||
|
NIL));
|
||||||
|
appendStringInfoChar(buf, ')');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case T_InferenceElem:
|
case T_InferenceElem:
|
||||||
{
|
{
|
||||||
InferenceElem *iexpr = (InferenceElem *) node;
|
InferenceElem *iexpr = (InferenceElem *) node;
|
||||||
|
@ -5786,7 +5817,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
|
|
||||||
if (iexpr->infercollid)
|
if (iexpr->infercollid)
|
||||||
appendStringInfo(buf, " COLLATE %s",
|
appendStringInfo(buf, " COLLATE %s",
|
||||||
generate_collation_name(iexpr->infercollid));
|
generate_collation_name(iexpr->infercollid));
|
||||||
|
|
||||||
/* Add the operator class name, if not default */
|
/* Add the operator class name, if not default */
|
||||||
if (iexpr->inferopclass)
|
if (iexpr->inferopclass)
|
||||||
|
@ -5810,12 +5841,11 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
case PARTITION_STRATEGY_LIST:
|
case PARTITION_STRATEGY_LIST:
|
||||||
Assert(spec->listdatums != NIL);
|
Assert(spec->listdatums != NIL);
|
||||||
|
|
||||||
appendStringInfoString(buf, "FOR VALUES");
|
appendStringInfoString(buf, "FOR VALUES IN (");
|
||||||
appendStringInfoString(buf, " IN (");
|
|
||||||
sep = "";
|
sep = "";
|
||||||
foreach(cell, spec->listdatums)
|
foreach(cell, spec->listdatums)
|
||||||
{
|
{
|
||||||
Const *val = lfirst(cell);
|
Const *val = castNode(Const, lfirst(cell));
|
||||||
|
|
||||||
appendStringInfoString(buf, sep);
|
appendStringInfoString(buf, sep);
|
||||||
get_const_expr(val, context, -1);
|
get_const_expr(val, context, -1);
|
||||||
|
@ -5831,50 +5861,9 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||||
list_length(spec->lowerdatums) ==
|
list_length(spec->lowerdatums) ==
|
||||||
list_length(spec->upperdatums));
|
list_length(spec->upperdatums));
|
||||||
|
|
||||||
appendStringInfoString(buf, "FOR VALUES");
|
appendStringInfo(buf, "FOR VALUES FROM %s TO %s",
|
||||||
appendStringInfoString(buf, " FROM");
|
get_range_partbound_string(spec->lowerdatums),
|
||||||
appendStringInfoString(buf, " (");
|
get_range_partbound_string(spec->upperdatums));
|
||||||
sep = "";
|
|
||||||
foreach(cell, spec->lowerdatums)
|
|
||||||
{
|
|
||||||
PartitionRangeDatum *datum = lfirst(cell);
|
|
||||||
Const *val;
|
|
||||||
|
|
||||||
appendStringInfoString(buf, sep);
|
|
||||||
if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
|
|
||||||
appendStringInfoString(buf, "MINVALUE");
|
|
||||||
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
|
|
||||||
appendStringInfoString(buf, "MAXVALUE");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val = (Const *) datum->value;
|
|
||||||
get_const_expr(val, context, -1);
|
|
||||||
}
|
|
||||||
sep = ", ";
|
|
||||||
}
|
|
||||||
appendStringInfoString(buf, ")");
|
|
||||||
|
|
||||||
appendStringInfoString(buf, " TO");
|
|
||||||
appendStringInfoString(buf, " (");
|
|
||||||
sep = "";
|
|
||||||
foreach(cell, spec->upperdatums)
|
|
||||||
{
|
|
||||||
PartitionRangeDatum *datum = lfirst(cell);
|
|
||||||
Const *val;
|
|
||||||
|
|
||||||
appendStringInfoString(buf, sep);
|
|
||||||
if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
|
|
||||||
appendStringInfoString(buf, "MINVALUE");
|
|
||||||
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
|
|
||||||
appendStringInfoString(buf, "MAXVALUE");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val = (Const *) datum->value;
|
|
||||||
get_const_expr(val, context, -1);
|
|
||||||
}
|
|
||||||
sep = ", ";
|
|
||||||
}
|
|
||||||
appendStringInfoString(buf, ")");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -5931,6 +5920,64 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
|
||||||
get_rule_expr(node, context, showimplicit);
|
get_rule_expr(node, context, showimplicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_rule_expr_funccall - Parse back a function-call expression
|
||||||
|
*
|
||||||
|
* Same as get_rule_expr(), except that we guarantee that the output will
|
||||||
|
* look like a function call, or like one of the things the grammar treats as
|
||||||
|
* equivalent to a function call (see the func_expr_windowless production).
|
||||||
|
* This is needed in places where the grammar uses func_expr_windowless and
|
||||||
|
* you can't substitute a parenthesized a_expr. If what we have isn't going
|
||||||
|
* to look like a function call, wrap it in a dummy CAST() expression, which
|
||||||
|
* will satisfy the grammar --- and, indeed, is likely what the user wrote to
|
||||||
|
* produce such a thing.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_rule_expr_funccall(Node *node, deparse_context *context,
|
||||||
|
bool showimplicit)
|
||||||
|
{
|
||||||
|
if (looks_like_function(node))
|
||||||
|
get_rule_expr(node, context, showimplicit);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringInfo buf = context->buf;
|
||||||
|
|
||||||
|
appendStringInfoString(buf, "CAST(");
|
||||||
|
/* no point in showing any top-level implicit cast */
|
||||||
|
get_rule_expr(node, context, false);
|
||||||
|
appendStringInfo(buf, " AS %s)",
|
||||||
|
format_type_with_typemod(exprType(node),
|
||||||
|
exprTypmod(node)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to identify node types that satisfy func_expr_windowless.
|
||||||
|
* If in doubt, "false" is always a safe answer.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
looks_like_function(Node *node)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return false; /* probably shouldn't happen */
|
||||||
|
switch (nodeTag(node))
|
||||||
|
{
|
||||||
|
case T_FuncExpr:
|
||||||
|
/* OK, unless it's going to deparse as a cast */
|
||||||
|
return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL);
|
||||||
|
case T_NullIfExpr:
|
||||||
|
case T_CoalesceExpr:
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
case T_SQLValueFunction:
|
||||||
|
case T_XmlExpr:
|
||||||
|
/* these are all accepted by func_expr_common_subexpr */
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_oper_expr - Parse back an OpExpr node
|
* get_oper_expr - Parse back an OpExpr node
|
||||||
|
@ -6385,7 +6432,7 @@ get_const_expr(Const *constval, deparse_context *context, int showtype)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendStringInfo(buf, "'%s'", extval);
|
appendStringInfo(buf, "'%s'", extval);
|
||||||
needlabel = true; /* we must attach a cast */
|
needlabel = true; /* we must attach a cast */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6404,7 +6451,7 @@ get_const_expr(Const *constval, deparse_context *context, int showtype)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendStringInfo(buf, "'%s'", extval);
|
appendStringInfo(buf, "'%s'", extval);
|
||||||
needlabel = true; /* we must attach a cast */
|
needlabel = true; /* we must attach a cast */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6566,8 +6613,8 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
|
||||||
get_rule_expr(linitial(opexpr->args), context, true);
|
get_rule_expr(linitial(opexpr->args), context, true);
|
||||||
if (!opname)
|
if (!opname)
|
||||||
opname = generate_operator_name(opexpr->opno,
|
opname = generate_operator_name(opexpr->opno,
|
||||||
exprType(linitial(opexpr->args)),
|
exprType(linitial(opexpr->args)),
|
||||||
exprType(lsecond(opexpr->args)));
|
exprType(lsecond(opexpr->args)));
|
||||||
sep = ", ";
|
sep = ", ";
|
||||||
}
|
}
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
|
@ -6581,7 +6628,7 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
|
||||||
get_rule_expr((Node *) rcexpr->largs, context, true);
|
get_rule_expr((Node *) rcexpr->largs, context, true);
|
||||||
opname = generate_operator_name(linitial_oid(rcexpr->opnos),
|
opname = generate_operator_name(linitial_oid(rcexpr->opnos),
|
||||||
exprType(linitial(rcexpr->largs)),
|
exprType(linitial(rcexpr->largs)),
|
||||||
exprType(linitial(rcexpr->rargs)));
|
exprType(linitial(rcexpr->rargs)));
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6598,7 +6645,7 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ANY_SUBLINK:
|
case ANY_SUBLINK:
|
||||||
if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
|
if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */
|
||||||
appendStringInfoString(buf, " IN ");
|
appendStringInfoString(buf, " IN ");
|
||||||
else
|
else
|
||||||
appendStringInfo(buf, " %s ANY ", opname);
|
appendStringInfo(buf, " %s ANY ", opname);
|
||||||
|
@ -6921,7 +6968,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||||
if (list_length(rte->functions) == 1 &&
|
if (list_length(rte->functions) == 1 &&
|
||||||
(rtfunc1->funccolnames == NIL || !rte->funcordinality))
|
(rtfunc1->funccolnames == NIL || !rte->funcordinality))
|
||||||
{
|
{
|
||||||
get_rule_expr(rtfunc1->funcexpr, context, true);
|
get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
|
||||||
/* we'll print the coldeflist below, if it has one */
|
/* we'll print the coldeflist below, if it has one */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6984,7 +7031,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||||
|
|
||||||
if (funcno > 0)
|
if (funcno > 0)
|
||||||
appendStringInfoString(buf, ", ");
|
appendStringInfoString(buf, ", ");
|
||||||
get_rule_expr(rtfunc->funcexpr, context, true);
|
get_rule_expr_funccall(rtfunc->funcexpr, context, true);
|
||||||
if (rtfunc->funccolnames != NIL)
|
if (rtfunc->funccolnames != NIL)
|
||||||
{
|
{
|
||||||
/* Reconstruct the column definition list */
|
/* Reconstruct the column definition list */
|
||||||
|
@ -7177,6 +7224,11 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||||
if (!PRETTY_PAREN(context))
|
if (!PRETTY_PAREN(context))
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
}
|
}
|
||||||
|
else if (j->jointype != JOIN_INNER)
|
||||||
|
{
|
||||||
|
/* If we didn't say CROSS JOIN above, we must provide an ON */
|
||||||
|
appendStringInfoString(buf, " ON TRUE");
|
||||||
|
}
|
||||||
|
|
||||||
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
|
@ -7373,13 +7425,17 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||||
*
|
*
|
||||||
* We strip any top-level FieldStore or assignment ArrayRef nodes that
|
* We strip any top-level FieldStore or assignment ArrayRef nodes that
|
||||||
* appear in the input, printing them as decoration for the base column
|
* appear in the input, printing them as decoration for the base column
|
||||||
* name (which we assume the caller just printed). Return the subexpression
|
* name (which we assume the caller just printed). We might also need to
|
||||||
* that's to be assigned.
|
* strip CoerceToDomain nodes, but only ones that appear above assignment
|
||||||
|
* nodes.
|
||||||
|
*
|
||||||
|
* Returns the subexpression that's to be assigned.
|
||||||
*/
|
*/
|
||||||
static Node *
|
static Node *
|
||||||
processIndirection(Node *node, deparse_context *context)
|
processIndirection(Node *node, deparse_context *context)
|
||||||
{
|
{
|
||||||
StringInfo buf = context->buf;
|
StringInfo buf = context->buf;
|
||||||
|
CoerceToDomain *cdomain = NULL;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -7404,7 +7460,7 @@ processIndirection(Node *node, deparse_context *context)
|
||||||
*/
|
*/
|
||||||
Assert(list_length(fstore->fieldnums) == 1);
|
Assert(list_length(fstore->fieldnums) == 1);
|
||||||
fieldname = get_relid_attribute_name(typrelid,
|
fieldname = get_relid_attribute_name(typrelid,
|
||||||
linitial_int(fstore->fieldnums));
|
linitial_int(fstore->fieldnums));
|
||||||
appendStringInfo(buf, ".%s", quote_identifier(fieldname));
|
appendStringInfo(buf, ".%s", quote_identifier(fieldname));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7427,10 +7483,28 @@ processIndirection(Node *node, deparse_context *context)
|
||||||
*/
|
*/
|
||||||
node = (Node *) aref->refassgnexpr;
|
node = (Node *) aref->refassgnexpr;
|
||||||
}
|
}
|
||||||
|
else if (IsA(node, CoerceToDomain))
|
||||||
|
{
|
||||||
|
cdomain = (CoerceToDomain *) node;
|
||||||
|
/* If it's an explicit domain coercion, we're done */
|
||||||
|
if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
|
||||||
|
break;
|
||||||
|
/* Tentatively descend past the CoerceToDomain */
|
||||||
|
node = (Node *) cdomain->arg;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we descended past a CoerceToDomain whose argument turned out not to
|
||||||
|
* be a FieldStore or array assignment, back up to the CoerceToDomain.
|
||||||
|
* (This is not enough to be fully correct if there are nested implicit
|
||||||
|
* CoerceToDomains, but such cases shouldn't ever occur.)
|
||||||
|
*/
|
||||||
|
if (cdomain && node == (Node *) cdomain->arg)
|
||||||
|
node = (Node *) cdomain;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7791,4 +7865,44 @@ generate_operator_name(Oid operid, Oid arg1, Oid arg2)
|
||||||
return buf.data;
|
return buf.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_one_range_partition_bound_string
|
||||||
|
* A C string representation of one range partition bound
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
get_range_partbound_string(List *bound_datums)
|
||||||
|
{
|
||||||
|
deparse_context context;
|
||||||
|
StringInfo buf = makeStringInfo();
|
||||||
|
ListCell *cell;
|
||||||
|
char *sep;
|
||||||
|
|
||||||
|
memset(&context, 0, sizeof(deparse_context));
|
||||||
|
context.buf = buf;
|
||||||
|
|
||||||
|
appendStringInfoString(buf, "(");
|
||||||
|
sep = "";
|
||||||
|
foreach(cell, bound_datums)
|
||||||
|
{
|
||||||
|
PartitionRangeDatum *datum =
|
||||||
|
castNode(PartitionRangeDatum, lfirst(cell));
|
||||||
|
|
||||||
|
appendStringInfoString(buf, sep);
|
||||||
|
if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
|
||||||
|
appendStringInfoString(buf, "MINVALUE");
|
||||||
|
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
|
||||||
|
appendStringInfoString(buf, "MAXVALUE");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Const *val = castNode(Const, datum->value);
|
||||||
|
|
||||||
|
get_const_expr(val, &context, -1);
|
||||||
|
}
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
|
appendStringInfoString(buf, ")");
|
||||||
|
|
||||||
|
return buf->data;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* (PG_VERSION_NUM >= 100000) */
|
#endif /* (PG_VERSION_NUM >= 100000) */
|
||||||
|
|
|
@ -386,6 +386,9 @@ static void get_rule_expr(Node *node, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
|
static void get_rule_expr_toplevel(Node *node, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
|
static void get_rule_expr_funccall(Node *node, deparse_context *context,
|
||||||
|
bool showimplicit);
|
||||||
|
static bool looks_like_function(Node *node);
|
||||||
static void get_oper_expr(OpExpr *expr, deparse_context *context);
|
static void get_oper_expr(OpExpr *expr, deparse_context *context);
|
||||||
static void get_func_expr(FuncExpr *expr, deparse_context *context,
|
static void get_func_expr(FuncExpr *expr, deparse_context *context,
|
||||||
bool showimplicit);
|
bool showimplicit);
|
||||||
|
@ -3282,8 +3285,11 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
||||||
/*
|
/*
|
||||||
* We must dig down into the expr to see if it's a PARAM_MULTIEXPR
|
* We must dig down into the expr to see if it's a PARAM_MULTIEXPR
|
||||||
* Param. That could be buried under FieldStores and ArrayRefs
|
* Param. That could be buried under FieldStores and ArrayRefs
|
||||||
* (cf processIndirection()), and underneath those there could be
|
* and CoerceToDomains (cf processIndirection()), and underneath
|
||||||
* an implicit type coercion.
|
* those there could be an implicit type coercion. Because we
|
||||||
|
* would ignore implicit type coercions anyway, we don't need to
|
||||||
|
* be as careful as processIndirection() is about descending past
|
||||||
|
* implicit CoerceToDomains.
|
||||||
*/
|
*/
|
||||||
expr = (Node *) tle->expr;
|
expr = (Node *) tle->expr;
|
||||||
while (expr)
|
while (expr)
|
||||||
|
@ -3302,6 +3308,14 @@ get_update_query_targetlist_def(Query *query, List *targetList,
|
||||||
break;
|
break;
|
||||||
expr = (Node *) aref->refassgnexpr;
|
expr = (Node *) aref->refassgnexpr;
|
||||||
}
|
}
|
||||||
|
else if (IsA(expr, CoerceToDomain))
|
||||||
|
{
|
||||||
|
CoerceToDomain *cdomain = (CoerceToDomain *) expr;
|
||||||
|
|
||||||
|
if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
|
||||||
|
break;
|
||||||
|
expr = (Node *) cdomain->arg;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5763,6 +5777,63 @@ get_rule_expr_toplevel(Node *node, deparse_context *context,
|
||||||
get_rule_expr(node, context, showimplicit);
|
get_rule_expr(node, context, showimplicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_rule_expr_funccall - Parse back a function-call expression
|
||||||
|
*
|
||||||
|
* Same as get_rule_expr(), except that we guarantee that the output will
|
||||||
|
* look like a function call, or like one of the things the grammar treats as
|
||||||
|
* equivalent to a function call (see the func_expr_windowless production).
|
||||||
|
* This is needed in places where the grammar uses func_expr_windowless and
|
||||||
|
* you can't substitute a parenthesized a_expr. If what we have isn't going
|
||||||
|
* to look like a function call, wrap it in a dummy CAST() expression, which
|
||||||
|
* will satisfy the grammar --- and, indeed, is likely what the user wrote to
|
||||||
|
* produce such a thing.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
get_rule_expr_funccall(Node *node, deparse_context *context,
|
||||||
|
bool showimplicit)
|
||||||
|
{
|
||||||
|
if (looks_like_function(node))
|
||||||
|
get_rule_expr(node, context, showimplicit);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringInfo buf = context->buf;
|
||||||
|
|
||||||
|
appendStringInfoString(buf, "CAST(");
|
||||||
|
/* no point in showing any top-level implicit cast */
|
||||||
|
get_rule_expr(node, context, false);
|
||||||
|
appendStringInfo(buf, " AS %s)",
|
||||||
|
format_type_with_typemod(exprType(node),
|
||||||
|
exprTypmod(node)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to identify node types that satisfy func_expr_windowless.
|
||||||
|
* If in doubt, "false" is always a safe answer.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
looks_like_function(Node *node)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return false; /* probably shouldn't happen */
|
||||||
|
switch (nodeTag(node))
|
||||||
|
{
|
||||||
|
case T_FuncExpr:
|
||||||
|
/* OK, unless it's going to deparse as a cast */
|
||||||
|
return (((FuncExpr *) node)->funcformat == COERCE_EXPLICIT_CALL);
|
||||||
|
case T_NullIfExpr:
|
||||||
|
case T_CoalesceExpr:
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
case T_XmlExpr:
|
||||||
|
/* these are all accepted by func_expr_common_subexpr */
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_oper_expr - Parse back an OpExpr node
|
* get_oper_expr - Parse back an OpExpr node
|
||||||
|
@ -6641,7 +6712,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||||
if (list_length(rte->functions) == 1 &&
|
if (list_length(rte->functions) == 1 &&
|
||||||
(rtfunc1->funccolnames == NIL || !rte->funcordinality))
|
(rtfunc1->funccolnames == NIL || !rte->funcordinality))
|
||||||
{
|
{
|
||||||
get_rule_expr(rtfunc1->funcexpr, context, true);
|
get_rule_expr_funccall(rtfunc1->funcexpr, context, true);
|
||||||
/* we'll print the coldeflist below, if it has one */
|
/* we'll print the coldeflist below, if it has one */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6704,7 +6775,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||||
|
|
||||||
if (funcno > 0)
|
if (funcno > 0)
|
||||||
appendStringInfoString(buf, ", ");
|
appendStringInfoString(buf, ", ");
|
||||||
get_rule_expr(rtfunc->funcexpr, context, true);
|
get_rule_expr_funccall(rtfunc->funcexpr, context, true);
|
||||||
if (rtfunc->funccolnames != NIL)
|
if (rtfunc->funccolnames != NIL)
|
||||||
{
|
{
|
||||||
/* Reconstruct the column definition list */
|
/* Reconstruct the column definition list */
|
||||||
|
@ -6894,6 +6965,11 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
||||||
if (!PRETTY_PAREN(context))
|
if (!PRETTY_PAREN(context))
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
}
|
}
|
||||||
|
else if (j->jointype != JOIN_INNER)
|
||||||
|
{
|
||||||
|
/* If we didn't say CROSS JOIN above, we must provide an ON */
|
||||||
|
appendStringInfoString(buf, " ON TRUE");
|
||||||
|
}
|
||||||
|
|
||||||
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
||||||
appendStringInfoChar(buf, ')');
|
appendStringInfoChar(buf, ')');
|
||||||
|
@ -7090,13 +7166,17 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
|
||||||
*
|
*
|
||||||
* We strip any top-level FieldStore or assignment ArrayRef nodes that
|
* We strip any top-level FieldStore or assignment ArrayRef nodes that
|
||||||
* appear in the input, printing them as decoration for the base column
|
* appear in the input, printing them as decoration for the base column
|
||||||
* name (which we assume the caller just printed). Return the subexpression
|
* name (which we assume the caller just printed). We might also need to
|
||||||
* that's to be assigned.
|
* strip CoerceToDomain nodes, but only ones that appear above assignment
|
||||||
|
* nodes.
|
||||||
|
*
|
||||||
|
* Returns the subexpression that's to be assigned.
|
||||||
*/
|
*/
|
||||||
static Node *
|
static Node *
|
||||||
processIndirection(Node *node, deparse_context *context)
|
processIndirection(Node *node, deparse_context *context)
|
||||||
{
|
{
|
||||||
StringInfo buf = context->buf;
|
StringInfo buf = context->buf;
|
||||||
|
CoerceToDomain *cdomain = NULL;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -7144,10 +7224,28 @@ processIndirection(Node *node, deparse_context *context)
|
||||||
*/
|
*/
|
||||||
node = (Node *) aref->refassgnexpr;
|
node = (Node *) aref->refassgnexpr;
|
||||||
}
|
}
|
||||||
|
else if (IsA(node, CoerceToDomain))
|
||||||
|
{
|
||||||
|
cdomain = (CoerceToDomain *) node;
|
||||||
|
/* If it's an explicit domain coercion, we're done */
|
||||||
|
if (cdomain->coercionformat != COERCE_IMPLICIT_CAST)
|
||||||
|
break;
|
||||||
|
/* Tentatively descend past the CoerceToDomain */
|
||||||
|
node = (Node *) cdomain->arg;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we descended past a CoerceToDomain whose argument turned out not to
|
||||||
|
* be a FieldStore or array assignment, back up to the CoerceToDomain.
|
||||||
|
* (This is not enough to be fully correct if there are nested implicit
|
||||||
|
* CoerceToDomains, but such cases shouldn't ever occur.)
|
||||||
|
*/
|
||||||
|
if (cdomain && node == (Node *) cdomain->arg)
|
||||||
|
node = (Node *) cdomain;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue