Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit28d2420

Browse files
committed
This patch adds support for %TYPE in CREATE FUNCTION argument and return
types. This version has an elog() to remind the user the typeresolution is not dynamic.Ian Lance Taylor
1 parent0a93285 commit28d2420

File tree

9 files changed

+170
-13
lines changed

9 files changed

+170
-13
lines changed

‎doc/src/sgml/ref/create_function.sgml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.23 2001/05/19 09:01:10 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.24 2001/06/04 23:27:23 momjian Exp $
33
-->
44

55
<refentry id="SQL-CREATEFUNCTION">
@@ -55,10 +55,16 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
5555
<listitem>
5656
<para>
5757
The data type(s) of the function's arguments, if any. The
58-
input types may be base or complex types, or
59-
<literal>opaque</literal>. <literal>Opaque</literal> indicates
58+
input types may be base or complex types,
59+
<literal>opaque</literal>, or the same as the type of an
60+
existing column. <literal>Opaque</literal> indicates
6061
that the function accepts arguments of a non-SQL type such as
6162
<type>char *</type>.
63+
The type of a column is indicated using <replaceable
64+
class="parameter">tablename</replaceable>.<replaceable
65+
class="parameter">columnname</replaceable><literal>%TYPE</literal>;
66+
using this can sometimes help make a function independent from
67+
changes to the definition of a table.
6268
</para>
6369
</listitem>
6470
</varlistentry>
@@ -69,8 +75,10 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
6975
<listitem>
7076
<para>
7177
The return data type. The output type may be specified as a
72-
base type, complex type, <literal>setof</literal> type, or
73-
<literal>opaque</literal>. The <literal>setof</literal>
78+
base type, complex type, <literal>setof</literal> type,
79+
<literal>opaque</literal>, or the same as the type of an
80+
existing column.
81+
The <literal>setof</literal>
7482
modifier indicates that the function will return a set of
7583
items, rather than a single item. Functions with a declared
7684
return type of <literal>opaque</literal> do not return a value.

‎src/backend/parser/analyze.c

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
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
*/
@@ -29,6 +29,7 @@
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);
5152
staticQuery*transformUpdateStmt(ParseState*pstate,UpdateStmt*stmt);
5253
staticQuery*transformCreateStmt(ParseState*pstate,CreateStmt*stmt);
5354
staticQuery*transformAlterTableStmt(ParseState*pstate,AlterTableStmt*stmt);
55+
staticNode*transformTypeRefs(ParseState*pstate,Node*stmt);
5456

57+
staticvoidtransformTypeRefsList(ParseState*pstate,List*l);
58+
staticvoidtransformTypeRef(ParseState*pstate,TypeName*tn);
5559
staticList*getSetColTypes(ParseState*pstate,Node*node);
5660
staticvoidtransformForUpdate(Query*qry,List*forUpdate);
5761
staticvoidtransformFkeyGetPrimaryKey(FkConstraint*fkconstraint,Oid*pktypoid);
@@ -232,6 +236,17 @@ transformStmt(ParseState *pstate, Node *parseTree)
232236
(SelectStmt*)parseTree);
233237
break;
234238

239+
/*
240+
* Convert use of %TYPE in statements where it is permitted.
241+
*/
242+
caseT_ProcedureStmt:
243+
caseT_CommentStmt:
244+
caseT_RemoveFuncStmt:
245+
caseT_DefineStmt:
246+
result=makeNode(Query);
247+
result->commandType=CMD_UTILITY;
248+
result->utilityStmt=transformTypeRefs(pstate,parseTree);
249+
break;
235250

236251
default:
237252

@@ -2701,6 +2716,107 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
27012716
returnqry;
27022717
}
27032718

2719+
/*
2720+
* Transform uses of %TYPE in a statement.
2721+
*/
2722+
staticNode*
2723+
transformTypeRefs(ParseState*pstate,Node*stmt)
2724+
{
2725+
switch (nodeTag(stmt))
2726+
{
2727+
caseT_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+
caseT_CommentStmt:
2738+
{
2739+
CommentStmt*cs= (CommentStmt*)stmt;
2740+
2741+
transformTypeRefsList(pstate,cs->objlist);
2742+
}
2743+
break;
2744+
2745+
caseT_RemoveFuncStmt:
2746+
{
2747+
RemoveFuncStmt*rs= (RemoveFuncStmt*)stmt;
2748+
2749+
transformTypeRefsList(pstate,rs->args);
2750+
}
2751+
break;
2752+
2753+
caseT_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+
returnstmt;
2778+
}
2779+
2780+
/*
2781+
* Transform uses of %TYPE in a list.
2782+
*/
2783+
staticvoid
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+
staticvoid
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 */
27052821
void
27062822
CheckSelectForUpdate(Query*qry)

‎src/backend/parser/gram.y

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.227 2001/05/27 09:59:29 petere Exp $
14+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.228 2001/06/04 23:27:23 momjian Exp $
1515
*
1616
* HISTORY
1717
* AUTHORDATEMAJOR EVENT
@@ -192,7 +192,7 @@ static void doNegateFloat(Value *v);
192192
def_list,opt_indirection,group_clause,TriggerFuncArgs,
193193
select_limit,opt_select_limit
194194

195-
%type<typnam>func_arg,func_return,aggr_argtype
195+
%type<typnam>func_arg,func_return,func_type,aggr_argtype
196196

197197
%type<boolean>opt_arg,TriggerForOpt,TriggerForType,OptTemp
198198

@@ -2490,15 +2490,15 @@ func_args_list: func_arg
24902490
{$$ = lappend($1,$3); }
24912491
;
24922492

2493-
func_arg:opt_argTypename
2493+
func_arg:opt_argfunc_type
24942494
{
24952495
/* We can catch over-specified arguments here if we want to,
24962496
* but for now better to silently swallow typmod, etc.
24972497
* - thomas 2000-03-22
24982498
*/
24992499
$$ =$2;
25002500
}
2501-
|Typename
2501+
|func_type
25022502
{
25032503
$$ =$1;
25042504
}
@@ -2526,7 +2526,7 @@ func_as: Sconst
25262526
{$$ = makeList2(makeString($1), makeString($3)); }
25272527
;
25282528

2529-
func_return:Typename
2529+
func_return:func_type
25302530
{
25312531
/* We can catch over-specified arguments here if we want to,
25322532
* but for now better to silently swallow typmod, etc.
@@ -2536,6 +2536,18 @@ func_return: Typename
25362536
}
25372537
;
25382538

2539+
func_type:Typename
2540+
{
2541+
$$ =$1;
2542+
}
2543+
|IDENT'.'ColId'%'TYPE_P
2544+
{
2545+
$$ = makeNode(TypeName);
2546+
$$->name =$1;
2547+
$$->typmod = -1;
2548+
$$->attrname =$3;
2549+
}
2550+
;
25392551

25402552
/*****************************************************************************
25412553
*

‎src/backend/parser/parse_expr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.96 2001/05/21 18:42:08 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.97 2001/06/04 23:27:23 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -942,6 +942,7 @@ parser_typecast_expression(ParseState *pstate,
942942
char*
943943
TypeNameToInternalName(TypeName*typename)
944944
{
945+
Assert(typename->attrname==NULL);
945946
if (typename->arrayBounds!=NIL)
946947
{
947948

‎src/include/nodes/parsenodes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parsenodes.h,v 1.129 2001/05/21 18:42:08 momjian Exp $
10+
* $Id: parsenodes.h,v 1.130 2001/06/04 23:27:23 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -951,6 +951,7 @@ typedef struct TypeName
951951
boolsetof;/* is a set? */
952952
int32typmod;/* type modifier */
953953
List*arrayBounds;/* array bounds */
954+
char*attrname;/* field name when using %TYPE */
954955
}TypeName;
955956

956957
/*

‎src/test/regress/input/create_function_2.source

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ CREATE FUNCTION hobby_construct(text, text)
1313
LANGUAGE 'sql';
1414

1515

16+
CREATE FUNCTION hobbies_by_name(hobbies_r.name%TYPE)
17+
RETURNS hobbies_r.person%TYPE
18+
AS 'select person from hobbies_r where name = $1'
19+
LANGUAGE 'sql';
20+
21+
1622
CREATE FUNCTION equipment(hobbies_r)
1723
RETURNS setof equipment_r
1824
AS 'select * from equipment_r where hobby = $1.name'

‎src/test/regress/input/misc.source

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ SELECT user_relns() AS user_relns
214214

215215
--SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))) AS equip_name;
216216

217+
SELECT hobbies_by_name('basketball');
217218

218219
--
219220
-- check that old-style C functions work properly with TOASTed values

‎src/test/regress/output/create_function_2.source

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ CREATE FUNCTION hobby_construct(text, text)
99
RETURNS hobbies_r
1010
AS 'select $1 as name, $2 as hobby'
1111
LANGUAGE 'sql';
12+
CREATE FUNCTION hobbies_by_name(hobbies_r.name%TYPE)
13+
RETURNS hobbies_r.person%TYPE
14+
AS 'select person from hobbies_r where name = $1'
15+
LANGUAGE 'sql';
16+
NOTICE: hobbies_r.name%TYPE converted to text
17+
NOTICE: hobbies_r.person%TYPE converted to text
1218
CREATE FUNCTION equipment(hobbies_r)
1319
RETURNS setof equipment_r
1420
AS 'select * from equipment_r where hobby = $1.name'

‎src/test/regress/output/misc.source

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,12 @@ SELECT user_relns() AS user_relns
656656
(90 rows)
657657

658658
--SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))) AS equip_name;
659+
SELECT hobbies_by_name('basketball');
660+
hobbies_by_name
661+
-----------------
662+
joe
663+
(1 row)
664+
659665
--
660666
-- check that old-style C functions work properly with TOASTed values
661667
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp