1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

This patch adds support for %TYPE in CREATE FUNCTION argument and return

types.  This version has an elog() to remind the user the type
resolution is not dynamic.

Ian Lance Taylor
This commit is contained in:
Bruce Momjian
2001-06-04 23:27:23 +00:00
parent 0a93285d88
commit 28d2420eef
9 changed files with 170 additions and 13 deletions

View File

@ -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)

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.227 2001/05/27 09:59:29 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.228 2001/06/04 23:27:23 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -192,7 +192,7 @@ static void doNegateFloat(Value *v);
def_list, opt_indirection, group_clause, TriggerFuncArgs,
select_limit, opt_select_limit
%type <typnam> func_arg, func_return, aggr_argtype
%type <typnam> func_arg, func_return, func_type, aggr_argtype
%type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp
@ -2490,7 +2490,7 @@ func_args_list: func_arg
{ $$ = lappend($1, $3); }
;
func_arg: opt_arg Typename
func_arg: opt_arg func_type
{
/* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc.
@ -2498,7 +2498,7 @@ func_arg: opt_arg Typename
*/
$$ = $2;
}
| Typename
| func_type
{
$$ = $1;
}
@ -2526,7 +2526,7 @@ func_as: Sconst
{ $$ = makeList2(makeString($1), makeString($3)); }
;
func_return: Typename
func_return: func_type
{
/* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc.
@ -2536,6 +2536,18 @@ func_return: Typename
}
;
func_type: Typename
{
$$ = $1;
}
| IDENT '.' ColId '%' TYPE_P
{
$$ = makeNode(TypeName);
$$->name = $1;
$$->typmod = -1;
$$->attrname = $3;
}
;
/*****************************************************************************
*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.96 2001/05/21 18:42:08 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.97 2001/06/04 23:27:23 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -942,6 +942,7 @@ parser_typecast_expression(ParseState *pstate,
char *
TypeNameToInternalName(TypeName *typename)
{
Assert(typename->attrname == NULL);
if (typename->arrayBounds != NIL)
{