aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-03-16 00:31:55 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-03-16 00:31:55 +0000
commit23160139617f6cb998604c7324da2175f7409db5 (patch)
treecdd877b18be4f800499f4240c76aaed7759e0a2f /src/backend/utils/adt/ruleutils.c
parent5981b9d03e724a54f3eac706c27056d601954a7f (diff)
downloadpostgresql-23160139617f6cb998604c7324da2175f7409db5.tar.gz
postgresql-23160139617f6cb998604c7324da2175f7409db5.zip
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.
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c81
1 files changed, 48 insertions, 33 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 9942bcc291b..714140e0617 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.216 2006/03/14 22:48:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.217 2006/03/16 00:31:55 tgl Exp $
**********************************************************************/
#include "postgres.h"
@@ -176,7 +176,7 @@ static void get_from_clause_item(Node *jtnode, Query *query,
deparse_context *context);
static void get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
deparse_context *context);
-static void get_from_clause_coldeflist(List *coldeflist,
+static void get_from_clause_coldeflist(List *names, List *types, List *typmods,
deparse_context *context);
static void get_opclass_name(Oid opclass, Oid actual_datatype,
StringInfo buf);
@@ -1497,13 +1497,16 @@ deparse_context_for_subplan(const char *name, List *tlist,
/*
* We create an RTE_SPECIAL RangeTblEntry, and store the given tlist
- * in its coldeflist field. This is a hack to make the tlist available
+ * in its funccoltypes field. This is a hack to make the tlist available
* to get_name_for_var_field(). RTE_SPECIAL nodes shouldn't appear in
* deparse contexts otherwise.
+ *
+ * XXX this desperately needs redesign, as it fails to handle cases where
+ * we need to drill down through multiple tlists.
*/
rte->rtekind = RTE_SPECIAL;
rte->relid = InvalidOid;
- rte->coldeflist = tlist;
+ rte->funccoltypes = tlist;
rte->eref = makeAlias(name, attrs);
rte->inh = false;
rte->inFromCl = true;
@@ -2678,9 +2681,9 @@ get_name_for_var_field(Var *var, int fieldno,
* Look into the subplan's target list to get the referenced
* expression, and then pass it to get_expr_result_type().
*/
- if (rte->coldeflist)
+ if (rte->funccoltypes)
{
- TargetEntry *ste = get_tle_by_resno(rte->coldeflist, attnum);
+ TargetEntry *ste = get_tle_by_resno(rte->funccoltypes, attnum);
if (ste != NULL)
expr = (Node *) ste->expr;
@@ -4205,7 +4208,6 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
{
int varno = ((RangeTblRef *) jtnode)->rtindex;
RangeTblEntry *rte = rt_fetch(varno, query->rtable);
- List *coldeflist = NIL;
bool gavealias = false;
switch (rte->rtekind)
@@ -4226,8 +4228,6 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
case RTE_FUNCTION:
/* Function RTE */
get_rule_expr(rte->funcexpr, context, true);
- /* might need to emit column list for RECORD function */
- coldeflist = rte->coldeflist;
break;
default:
elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
@@ -4265,27 +4265,37 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
gavealias = true;
}
- if (coldeflist != NIL)
+ if (rte->rtekind == RTE_FUNCTION)
{
- if (!gavealias)
- appendStringInfo(buf, " AS ");
- get_from_clause_coldeflist(coldeflist, context);
+ if (rte->funccoltypes != NIL)
+ {
+ /* Function returning RECORD, reconstruct the columndefs */
+ if (!gavealias)
+ appendStringInfo(buf, " AS ");
+ get_from_clause_coldeflist(rte->eref->colnames,
+ rte->funccoltypes,
+ rte->funccoltypmods,
+ context);
+ }
+ else
+ {
+ /*
+ * For a function RTE, always emit a complete column alias
+ * list; this is to protect against possible instability of
+ * the default column names (eg, from altering parameter
+ * names).
+ */
+ get_from_clause_alias(rte->eref, rte, context);
+ }
}
else
{
/*
- * For a function RTE, always emit a complete column alias list;
- * this is to protect against possible instability of the default
- * column names (eg, from altering parameter names). Otherwise
- * just report whatever the user originally gave as column
- * aliases.
+ * For non-function RTEs, just report whatever the user originally
+ * gave as column aliases.
*/
- if (rte->rtekind == RTE_FUNCTION)
- get_from_clause_alias(rte->eref, rte, context);
- else
- get_from_clause_alias(rte->alias, rte, context);
+ get_from_clause_alias(rte->alias, rte, context);
}
-
}
else if (IsA(jtnode, JoinExpr))
{
@@ -4463,30 +4473,35 @@ get_from_clause_alias(Alias *alias, RangeTblEntry *rte,
* responsible for ensuring that an alias or AS is present before it.
*/
static void
-get_from_clause_coldeflist(List *coldeflist, deparse_context *context)
+get_from_clause_coldeflist(List *names, List *types, List *typmods,
+ deparse_context *context)
{
StringInfo buf = context->buf;
- ListCell *col;
+ ListCell *l1;
+ ListCell *l2;
+ ListCell *l3;
int i = 0;
appendStringInfoChar(buf, '(');
- foreach(col, coldeflist)
+ l2 = list_head(types);
+ l3 = list_head(typmods);
+ foreach(l1, names)
{
- ColumnDef *n = lfirst(col);
- char *attname;
- Oid atttypeid;
+ char *attname = strVal(lfirst(l1));
+ Oid atttypid;
int32 atttypmod;
- attname = n->colname;
- atttypeid = typenameTypeId(NULL, n->typename);
- atttypmod = n->typename->typmod;
+ atttypid = lfirst_oid(l2);
+ l2 = lnext(l2);
+ atttypmod = lfirst_int(l3);
+ l3 = lnext(l3);
if (i > 0)
appendStringInfo(buf, ", ");
appendStringInfo(buf, "%s %s",
quote_identifier(attname),
- format_type_with_typemod(atttypeid, atttypmod));
+ format_type_with_typemod(atttypid, atttypmod));
i++;
}