diff options
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 118 |
1 files changed, 117 insertions, 1 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 2bef065b11a..c6f21e77b03 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.188 2001/06/04 16:17:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.189 2001/06/04 23:27:23 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ #include "parser/parse_relation.h" #include "parser/parse_target.h" #include "parser/parse_type.h" +#include "parser/parse_expr.h" #include "rewrite/rewriteManip.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -51,7 +52,10 @@ static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt); static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt); static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt); static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt); +static Node *transformTypeRefs(ParseState *pstate, Node *stmt); +static void transformTypeRefsList(ParseState *pstate, List *l); +static void transformTypeRef(ParseState *pstate, TypeName *tn); static List *getSetColTypes(ParseState *pstate, Node *node); static void transformForUpdate(Query *qry, List *forUpdate); static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid); @@ -232,6 +236,17 @@ transformStmt(ParseState *pstate, Node *parseTree) (SelectStmt *) parseTree); break; + /* + * Convert use of %TYPE in statements where it is permitted. + */ + case T_ProcedureStmt: + case T_CommentStmt: + case T_RemoveFuncStmt: + case T_DefineStmt: + result = makeNode(Query); + result->commandType = CMD_UTILITY; + result->utilityStmt = transformTypeRefs(pstate, parseTree); + break; default: @@ -2701,6 +2716,107 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt) return qry; } +/* + * Transform uses of %TYPE in a statement. + */ +static Node * +transformTypeRefs(ParseState *pstate, Node *stmt) +{ + switch (nodeTag(stmt)) + { + case T_ProcedureStmt: + { + ProcedureStmt *ps = (ProcedureStmt *) stmt; + + transformTypeRefsList(pstate, ps->argTypes); + transformTypeRef(pstate, (TypeName *) ps->returnType); + transformTypeRefsList(pstate, ps->withClause); + } + break; + + case T_CommentStmt: + { + CommentStmt *cs = (CommentStmt *) stmt; + + transformTypeRefsList(pstate, cs->objlist); + } + break; + + case T_RemoveFuncStmt: + { + RemoveFuncStmt *rs = (RemoveFuncStmt *) stmt; + + transformTypeRefsList(pstate, rs->args); + } + break; + + case T_DefineStmt: + { + DefineStmt *ds = (DefineStmt *) stmt; + List *ele; + + foreach(ele, ds->definition) + { + DefElem *de = (DefElem *) lfirst(ele); + + if (de->arg != NULL + && IsA(de->arg, TypeName)) + { + transformTypeRef(pstate, (TypeName *) de->arg); + } + } + } + break; + + default: + elog(ERROR, "Unsupported type %d in transformTypeRefs", + nodeTag(stmt)); + break; + } + + return stmt; +} + +/* + * Transform uses of %TYPE in a list. + */ +static void +transformTypeRefsList(ParseState *pstate, List *l) +{ + List *ele; + + foreach(ele, l) + { + if (IsA(lfirst(ele), TypeName)) + transformTypeRef(pstate, (TypeName *) lfirst(ele)); + } +} + +/* + * Transform a TypeName to not use %TYPE. + */ +static void +transformTypeRef(ParseState *pstate, TypeName *tn) +{ + Attr *att; + Node *n; + Var *v; + char *tyn; + + if (tn->attrname == NULL) + return; + att = makeAttr(tn->name, tn->attrname); + n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST); + if (! IsA(n, Var)) + elog(ERROR, "unsupported expression in %%TYPE"); + v = (Var *) n; + tyn = typeidTypeName(v->vartype); + elog(NOTICE, "%s.%s%%TYPE converted to %s", tn->name, tn->attrname, tyn); + tn->name = tyn; + tn->typmod = v->vartypmod; + tn->attrname = NULL; +} + /* exported so planner can check again after rewriting, query pullup, etc */ void CheckSelectForUpdate(Query *qry) |