Skip to content

Commit 2316013

Browse files
committed
Clean up representation of function RTEs for functions returning RECORD.
The original coding stored the raw parser output (ColumnDef and TypeName nodes) which was ugly, bulky, and wrong because it failed to create any dependency on the referenced datatype --- and in fact would not track type renamings and suchlike. Instead store a list of column type OIDs in the RTE. Also fix up general failure of recordDependencyOnExpr to do anything sane about recording dependencies on datatypes. While there are many cases where there will be an indirect dependency (eg if an operator returns a datatype, the dependency on the operator is enough), we do have to record the datatype as a separate dependency in examples like CoerceToDomain. initdb forced because of change of stored rules.
1 parent 5981b9d commit 2316013

File tree

13 files changed

+249
-145
lines changed

13 files changed

+249
-145
lines changed

src/backend/access/common/tupdesc.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.115 2006/03/14 22:48:18 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.116 2006/03/16 00:31:54 tgl Exp $
1212
*
1313
* NOTES
1414
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -554,3 +554,54 @@ BuildDescForRelation(List *schema)
554554

555555
return desc;
556556
}
557+
558+
/*
559+
* BuildDescFromLists
560+
*
561+
* Build a TupleDesc given lists of column names (as String nodes),
562+
* column type OIDs, and column typmods. No constraints are generated.
563+
*
564+
* This is essentially a cut-down version of BuildDescForRelation for use
565+
* with functions returning RECORD.
566+
*/
567+
TupleDesc
568+
BuildDescFromLists(List *names, List *types, List *typmods)
569+
{
570+
int natts;
571+
AttrNumber attnum;
572+
ListCell *l1;
573+
ListCell *l2;
574+
ListCell *l3;
575+
TupleDesc desc;
576+
577+
natts = list_length(names);
578+
Assert(natts == list_length(types));
579+
Assert(natts == list_length(typmods));
580+
581+
/*
582+
* allocate a new tuple descriptor
583+
*/
584+
desc = CreateTemplateTupleDesc(natts, false);
585+
586+
attnum = 0;
587+
588+
l2 = list_head(types);
589+
l3 = list_head(typmods);
590+
foreach(l1, names)
591+
{
592+
char *attname = strVal(lfirst(l1));
593+
Oid atttypid;
594+
int32 atttypmod;
595+
596+
atttypid = lfirst_oid(l2);
597+
l2 = lnext(l2);
598+
atttypmod = lfirst_int(l3);
599+
l3 = lnext(l3);
600+
601+
attnum++;
602+
603+
TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0);
604+
}
605+
606+
return desc;
607+
}

src/backend/catalog/dependency.c

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.50 2006/03/05 15:58:22 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.51 2006/03/16 00:31:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -850,11 +850,6 @@ doDeletion(const ObjectAddress *object)
850850
*
851851
* rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
852852
* It can be NIL if no such variables are expected.
853-
*
854-
* XXX is it important to create dependencies on the datatypes mentioned in
855-
* the expression? In most cases this would be redundant (eg, a ref to an
856-
* operator indirectly references its input and output datatypes), but I'm
857-
* not quite convinced there are no cases where we need it.
858853
*/
859854
void
860855
recordDependencyOnExpr(const ObjectAddress *depender,
@@ -975,6 +970,13 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
975970
* To do so, we do not scan the joinaliasvars list of a join RTE while
976971
* scanning the query rangetable, but instead scan each individual entry
977972
* of the alias list when we find a reference to it.
973+
*
974+
* Note: in many cases we do not need to create dependencies on the datatypes
975+
* involved in an expression, because we'll have an indirect dependency via
976+
* some other object. For instance Var nodes depend on a column which depends
977+
* on the datatype, and OpExpr nodes depend on the operator which depends on
978+
* the datatype. However we do need a type dependency if there is no such
979+
* indirect dependency, as for example in Const and CoerceToDomain nodes.
978980
*/
979981
static bool
980982
find_expr_references_walker(Node *node,
@@ -1033,6 +1035,10 @@ find_expr_references_walker(Node *node,
10331035
Const *con = (Const *) node;
10341036
Oid objoid;
10351037

1038+
/* A constant must depend on the constant's datatype */
1039+
add_object_address(OCLASS_TYPE, con->consttype, 0,
1040+
&context->addrs);
1041+
10361042
/*
10371043
* If it's a regclass or similar literal referring to an existing
10381044
* object, add a reference to that object. (Currently, only the
@@ -1081,6 +1087,14 @@ find_expr_references_walker(Node *node,
10811087
}
10821088
return false;
10831089
}
1090+
if (IsA(node, Param))
1091+
{
1092+
Param *param = (Param *) node;
1093+
1094+
/* A parameter must depend on the parameter's datatype */
1095+
add_object_address(OCLASS_TYPE, param->paramtype, 0,
1096+
&context->addrs);
1097+
}
10841098
if (IsA(node, FuncExpr))
10851099
{
10861100
FuncExpr *funcexpr = (FuncExpr *) node;
@@ -1134,6 +1148,29 @@ find_expr_references_walker(Node *node,
11341148
/* Extra work needed here if we ever need this case */
11351149
elog(ERROR, "already-planned subqueries not supported");
11361150
}
1151+
if (IsA(node, RelabelType))
1152+
{
1153+
RelabelType *relab = (RelabelType *) node;
1154+
1155+
/* since there is no function dependency, need to depend on type */
1156+
add_object_address(OCLASS_TYPE, relab->resulttype, 0,
1157+
&context->addrs);
1158+
}
1159+
if (IsA(node, ConvertRowtypeExpr))
1160+
{
1161+
ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
1162+
1163+
/* since there is no function dependency, need to depend on type */
1164+
add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
1165+
&context->addrs);
1166+
}
1167+
if (IsA(node, RowExpr))
1168+
{
1169+
RowExpr *rowexpr = (RowExpr *) node;
1170+
1171+
add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
1172+
&context->addrs);
1173+
}
11371174
if (IsA(node, RowCompareExpr))
11381175
{
11391176
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
@@ -1151,6 +1188,13 @@ find_expr_references_walker(Node *node,
11511188
}
11521189
/* fall through to examine arguments */
11531190
}
1191+
if (IsA(node, CoerceToDomain))
1192+
{
1193+
CoerceToDomain *cd = (CoerceToDomain *) node;
1194+
1195+
add_object_address(OCLASS_TYPE, cd->resulttype, 0,
1196+
&context->addrs);
1197+
}
11541198
if (IsA(node, Query))
11551199
{
11561200
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
@@ -1160,17 +1204,32 @@ find_expr_references_walker(Node *node,
11601204

11611205
/*
11621206
* Add whole-relation refs for each plain relation mentioned in the
1163-
* subquery's rtable. (Note: query_tree_walker takes care of
1164-
* recursing into RTE_FUNCTION and RTE_SUBQUERY RTEs, so no need to do
1165-
* that here. But keep it from looking at join alias lists.)
1207+
* subquery's rtable, as well as datatype refs for any datatypes used
1208+
* as a RECORD function's output. (Note: query_tree_walker takes care
1209+
* of recursing into RTE_FUNCTION and RTE_SUBQUERY RTEs, so no need to
1210+
* do that here. But keep it from looking at join alias lists.)
11661211
*/
11671212
foreach(rtable, query->rtable)
11681213
{
11691214
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtable);
1215+
ListCell *ct;
11701216

1171-
if (rte->rtekind == RTE_RELATION)
1172-
add_object_address(OCLASS_CLASS, rte->relid, 0,
1173-
&context->addrs);
1217+
switch (rte->rtekind)
1218+
{
1219+
case RTE_RELATION:
1220+
add_object_address(OCLASS_CLASS, rte->relid, 0,
1221+
&context->addrs);
1222+
break;
1223+
case RTE_FUNCTION:
1224+
foreach(ct, rte->funccoltypes)
1225+
{
1226+
add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
1227+
&context->addrs);
1228+
}
1229+
break;
1230+
default:
1231+
break;
1232+
}
11741233
}
11751234

11761235
/* Examine substructure of query */

src/backend/executor/nodeFunctionscan.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.37 2006/03/05 15:58:26 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.38 2006/03/16 00:31:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -202,7 +202,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
202202
}
203203
else if (functypclass == TYPEFUNC_RECORD)
204204
{
205-
tupdesc = BuildDescForRelation(rte->coldeflist);
205+
tupdesc = BuildDescFromLists(rte->eref->colnames,
206+
rte->funccoltypes,
207+
rte->funccoltypmods);
206208
}
207209
else
208210
{

src/backend/nodes/copyfuncs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.330 2006/03/14 22:48:19 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.331 2006/03/16 00:31:54 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1355,7 +1355,8 @@ _copyRangeTblEntry(RangeTblEntry *from)
13551355
COPY_SCALAR_FIELD(relid);
13561356
COPY_NODE_FIELD(subquery);
13571357
COPY_NODE_FIELD(funcexpr);
1358-
COPY_NODE_FIELD(coldeflist);
1358+
COPY_NODE_FIELD(funccoltypes);
1359+
COPY_NODE_FIELD(funccoltypmods);
13591360
COPY_SCALAR_FIELD(jointype);
13601361
COPY_NODE_FIELD(joinaliasvars);
13611362
COPY_NODE_FIELD(alias);

src/backend/nodes/equalfuncs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.266 2006/03/14 22:48:19 tgl Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.267 2006/03/16 00:31:54 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -1730,7 +1730,8 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
17301730
COMPARE_SCALAR_FIELD(relid);
17311731
COMPARE_NODE_FIELD(subquery);
17321732
COMPARE_NODE_FIELD(funcexpr);
1733-
COMPARE_NODE_FIELD(coldeflist);
1733+
COMPARE_NODE_FIELD(funccoltypes);
1734+
COMPARE_NODE_FIELD(funccoltypmods);
17341735
COMPARE_SCALAR_FIELD(jointype);
17351736
COMPARE_NODE_FIELD(joinaliasvars);
17361737
COMPARE_NODE_FIELD(alias);

src/backend/nodes/outfuncs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.270 2006/03/14 22:48:19 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.271 2006/03/16 00:31:54 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1450,7 +1450,7 @@ _outTypeName(StringInfo str, TypeName *node)
14501450
WRITE_BOOL_FIELD(pct_type);
14511451
WRITE_INT_FIELD(typmod);
14521452
WRITE_NODE_FIELD(arrayBounds);
1453-
/* location is deliberately not stored */
1453+
WRITE_INT_FIELD(location);
14541454
}
14551455

14561456
static void
@@ -1580,7 +1580,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
15801580
break;
15811581
case RTE_FUNCTION:
15821582
WRITE_NODE_FIELD(funcexpr);
1583-
WRITE_NODE_FIELD(coldeflist);
1583+
WRITE_NODE_FIELD(funccoltypes);
1584+
WRITE_NODE_FIELD(funccoltypmods);
15841585
break;
15851586
case RTE_JOIN:
15861587
WRITE_ENUM_FIELD(jointype, JoinType);

src/backend/nodes/readfuncs.c

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.186 2006/03/14 22:48:19 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.187 2006/03/16 00:31:55 tgl Exp $
1212
*
1313
* NOTES
1414
* Path and Plan nodes do not have any readfuncs support, because we
@@ -863,42 +863,6 @@ _readFromExpr(void)
863863
* Stuff from parsenodes.h.
864864
*/
865865

866-
static ColumnDef *
867-
_readColumnDef(void)
868-
{
869-
READ_LOCALS(ColumnDef);
870-
871-
READ_STRING_FIELD(colname);
872-
READ_NODE_FIELD(typename);
873-
READ_INT_FIELD(inhcount);
874-
READ_BOOL_FIELD(is_local);
875-
READ_BOOL_FIELD(is_not_null);
876-
READ_NODE_FIELD(raw_default);
877-
READ_STRING_FIELD(cooked_default);
878-
READ_NODE_FIELD(constraints);
879-
READ_NODE_FIELD(support);
880-
881-
READ_DONE();
882-
}
883-
884-
static TypeName *
885-
_readTypeName(void)
886-
{
887-
READ_LOCALS(TypeName);
888-
889-
READ_NODE_FIELD(names);
890-
READ_OID_FIELD(typeid);
891-
READ_BOOL_FIELD(timezone);
892-
READ_BOOL_FIELD(setof);
893-
READ_BOOL_FIELD(pct_type);
894-
READ_INT_FIELD(typmod);
895-
READ_NODE_FIELD(arrayBounds);
896-
/* location is deliberately not stored */
897-
local_node->location = -1;
898-
899-
READ_DONE();
900-
}
901-
902866
/*
903867
* _readRangeTblEntry
904868
*/
@@ -923,7 +887,8 @@ _readRangeTblEntry(void)
923887
break;
924888
case RTE_FUNCTION:
925889
READ_NODE_FIELD(funcexpr);
926-
READ_NODE_FIELD(coldeflist);
890+
READ_NODE_FIELD(funccoltypes);
891+
READ_NODE_FIELD(funccoltypmods);
927892
break;
928893
case RTE_JOIN:
929894
READ_ENUM_FIELD(jointype, JoinType);
@@ -1042,10 +1007,6 @@ parseNodeString(void)
10421007
return_value = _readJoinExpr();
10431008
else if (MATCH("FROMEXPR", 8))
10441009
return_value = _readFromExpr();
1045-
else if (MATCH("COLUMNDEF", 9))
1046-
return_value = _readColumnDef();
1047-
else if (MATCH("TYPENAME", 8))
1048-
return_value = _readTypeName();
10491010
else if (MATCH("RTE", 3))
10501011
return_value = _readRangeTblEntry();
10511012
else if (MATCH("NOTIFY", 6))

0 commit comments

Comments
 (0)