66 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
9- *$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.188 2001/06/0416:17:30 tgl Exp $
9+ *$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.189 2001/06/0423:27:23 momjian Exp $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
2929#include "parser/parse_relation.h"
3030#include "parser/parse_target.h"
3131#include "parser/parse_type.h"
32+ #include "parser/parse_expr.h"
3233#include "rewrite/rewriteManip.h"
3334#include "utils/builtins.h"
3435#include "utils/fmgroids.h"
@@ -51,7 +52,10 @@ static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
5152static Query * transformUpdateStmt (ParseState * pstate ,UpdateStmt * stmt );
5253static Query * transformCreateStmt (ParseState * pstate ,CreateStmt * stmt );
5354static Query * transformAlterTableStmt (ParseState * pstate ,AlterTableStmt * stmt );
55+ static Node * transformTypeRefs (ParseState * pstate ,Node * stmt );
5456
57+ static void transformTypeRefsList (ParseState * pstate ,List * l );
58+ static void transformTypeRef (ParseState * pstate ,TypeName * tn );
5559static List * getSetColTypes (ParseState * pstate ,Node * node );
5660static void transformForUpdate (Query * qry ,List * forUpdate );
5761static void transformFkeyGetPrimaryKey (FkConstraint * fkconstraint ,Oid * pktypoid );
@@ -232,6 +236,17 @@ transformStmt(ParseState *pstate, Node *parseTree)
232236 (SelectStmt * )parseTree );
233237break ;
234238
239+ /*
240+ * Convert use of %TYPE in statements where it is permitted.
241+ */
242+ case T_ProcedureStmt :
243+ case T_CommentStmt :
244+ case T_RemoveFuncStmt :
245+ case T_DefineStmt :
246+ result = makeNode (Query );
247+ result -> commandType = CMD_UTILITY ;
248+ result -> utilityStmt = transformTypeRefs (pstate ,parseTree );
249+ break ;
235250
236251default :
237252
@@ -2701,6 +2716,107 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
27012716return qry ;
27022717}
27032718
2719+ /*
2720+ * Transform uses of %TYPE in a statement.
2721+ */
2722+ static Node *
2723+ transformTypeRefs (ParseState * pstate ,Node * stmt )
2724+ {
2725+ switch (nodeTag (stmt ))
2726+ {
2727+ case T_ProcedureStmt :
2728+ {
2729+ ProcedureStmt * ps = (ProcedureStmt * )stmt ;
2730+
2731+ transformTypeRefsList (pstate ,ps -> argTypes );
2732+ transformTypeRef (pstate , (TypeName * )ps -> returnType );
2733+ transformTypeRefsList (pstate ,ps -> withClause );
2734+ }
2735+ break ;
2736+
2737+ case T_CommentStmt :
2738+ {
2739+ CommentStmt * cs = (CommentStmt * )stmt ;
2740+
2741+ transformTypeRefsList (pstate ,cs -> objlist );
2742+ }
2743+ break ;
2744+
2745+ case T_RemoveFuncStmt :
2746+ {
2747+ RemoveFuncStmt * rs = (RemoveFuncStmt * )stmt ;
2748+
2749+ transformTypeRefsList (pstate ,rs -> args );
2750+ }
2751+ break ;
2752+
2753+ case T_DefineStmt :
2754+ {
2755+ DefineStmt * ds = (DefineStmt * )stmt ;
2756+ List * ele ;
2757+
2758+ foreach (ele ,ds -> definition )
2759+ {
2760+ DefElem * de = (DefElem * )lfirst (ele );
2761+
2762+ if (de -> arg != NULL
2763+ && IsA (de -> arg ,TypeName ))
2764+ {
2765+ transformTypeRef (pstate , (TypeName * )de -> arg );
2766+ }
2767+ }
2768+ }
2769+ break ;
2770+
2771+ default :
2772+ elog (ERROR ,"Unsupported type %d in transformTypeRefs" ,
2773+ nodeTag (stmt ));
2774+ break ;
2775+ }
2776+
2777+ return stmt ;
2778+ }
2779+
2780+ /*
2781+ * Transform uses of %TYPE in a list.
2782+ */
2783+ static void
2784+ transformTypeRefsList (ParseState * pstate ,List * l )
2785+ {
2786+ List * ele ;
2787+
2788+ foreach (ele ,l )
2789+ {
2790+ if (IsA (lfirst (ele ),TypeName ))
2791+ transformTypeRef (pstate , (TypeName * )lfirst (ele ));
2792+ }
2793+ }
2794+
2795+ /*
2796+ * Transform a TypeName to not use %TYPE.
2797+ */
2798+ static void
2799+ transformTypeRef (ParseState * pstate ,TypeName * tn )
2800+ {
2801+ Attr * att ;
2802+ Node * n ;
2803+ Var * v ;
2804+ char * tyn ;
2805+
2806+ if (tn -> attrname == NULL )
2807+ return ;
2808+ att = makeAttr (tn -> name ,tn -> attrname );
2809+ n = transformExpr (pstate , (Node * )att ,EXPR_COLUMN_FIRST );
2810+ if (!IsA (n ,Var ))
2811+ elog (ERROR ,"unsupported expression in %%TYPE" );
2812+ v = (Var * )n ;
2813+ tyn = typeidTypeName (v -> vartype );
2814+ elog (NOTICE ,"%s.%s%%TYPE converted to %s" ,tn -> name ,tn -> attrname ,tyn );
2815+ tn -> name = tyn ;
2816+ tn -> typmod = v -> vartypmod ;
2817+ tn -> attrname = NULL ;
2818+ }
2819+
27042820/* exported so planner can check again after rewriting, query pullup, etc */
27052821void
27062822CheckSelectForUpdate (Query * qry )