Skip to content

Commit eb47ee4

Browse files
committed
Fix grammar for IN/OUT/INOUT parameters. This commit doesn't actually
implement any new feature, it just pushes the 'not implemented' error message deeper into the backend. I also tweaked the grammar to accept Oracle-ish parameter syntax (parameter name first), as well as the SQL99 standard syntax (parameter mode first), since it was easy and people will doubtless try to use both anyway.
1 parent 8c85a34 commit eb47ee4

File tree

5 files changed

+81
-32
lines changed

5 files changed

+81
-32
lines changed

src/backend/commands/functioncmds.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.57 2005/03/29 00:16:57 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.58 2005/03/29 17:58:49 tgl Exp $
1414
*
1515
* DESCRIPTION
1616
* These routines take the parse tree and pick out the
@@ -154,6 +154,15 @@ examine_parameter_list(List *parameter, Oid languageOid,
154154
errmsg("functions cannot have more than %d arguments",
155155
FUNC_MAX_ARGS)));
156156

157+
if (fp->mode == FUNC_PARAM_OUT)
158+
ereport(ERROR,
159+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
160+
errmsg("CREATE FUNCTION / OUT parameters are not implemented")));
161+
if (fp->mode == FUNC_PARAM_INOUT)
162+
ereport(ERROR,
163+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
164+
errmsg("CREATE FUNCTION / INOUT parameters are not implemented")));
165+
157166
toid = LookupTypeName(t);
158167
if (OidIsValid(toid))
159168
{

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.298 2005/03/14 00:19:36 neilc Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.299 2005/03/29 17:58:50 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1888,6 +1888,7 @@ _copyFunctionParameter(FunctionParameter *from)
18881888

18891889
COPY_STRING_FIELD(name);
18901890
COPY_NODE_FIELD(argType);
1891+
COPY_SCALAR_FIELD(mode);
18911892

18921893
return newnode;
18931894
}

src/backend/nodes/equalfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.237 2005/03/14 00:19:36 neilc Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.238 2005/03/29 17:58:50 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -949,6 +949,7 @@ _equalFunctionParameter(FunctionParameter *a, FunctionParameter *b)
949949
{
950950
COMPARE_STRING_FIELD(name);
951951
COMPARE_NODE_FIELD(argType);
952+
COMPARE_SCALAR_FIELD(mode);
952953

953954
return true;
954955
}

src/backend/parser/gram.y

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.484 2005/03/14 00:19:36 neilc Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.485 2005/03/29 17:58:50 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -114,6 +114,8 @@ static void doNegateFloat(Value *v);
114114

115115
TypeName *typnam;
116116
FunctionParameter *fun_param;
117+
FunctionParameterMode fun_param_mode;
118+
FuncWithArgs *funwithargs;
117119
DefElem *defelt;
118120
SortBy *sortby;
119121
JoinExpr *jexpr;
@@ -206,7 +208,7 @@ static void doNegateFloat(Value *v);
206208
%type <ival> privilege
207209
%type <list> privileges privilege_list
208210
%type <privtarget> privilege_target
209-
%type <node> function_with_argtypes
211+
%type <funwithargs> function_with_argtypes
210212
%type <list> function_with_argtypes_list
211213
%type <chr> TriggerOneEvent
212214

@@ -233,9 +235,10 @@ static void doNegateFloat(Value *v);
233235

234236
%type <defelt> createfunc_opt_item common_func_opt_item
235237
%type <fun_param> func_arg
238+
%type <fun_param_mode> arg_class
236239
%type <typnam> func_return func_type aggr_argtype
237240

238-
%type <boolean> arg_class TriggerForType OptTemp
241+
%type <boolean> TriggerForType OptTemp
239242
%type <oncommit> OnCommitOption
240243
%type <withoids> OptWithOids WithOidsAs
241244

@@ -3177,7 +3180,7 @@ function_with_argtypes:
31773180
FuncWithArgs *n = makeNode(FuncWithArgs);
31783181
n->funcname = $1;
31793182
n->funcargs = extractArgTypes($2);
3180-
$$ = (Node *)n;
3183+
$$ = n;
31813184
}
31823185
;
31833186

@@ -3295,7 +3298,13 @@ func_args_list:
32953298
| func_args_list ',' func_arg { $$ = lappend($1, $3); }
32963299
;
32973300

3298-
/* We can catch over-specified arguments here if we want to,
3301+
/*
3302+
* The style with arg_class first is SQL99 standard, but Oracle puts
3303+
* param_name first; accept both since it's likely people will try both
3304+
* anyway. Don't bother trying to save productions by letting arg_class
3305+
* have an empty alternative ... you'll get shift/reduce conflicts.
3306+
*
3307+
* We can catch over-specified arguments here if we want to,
32993308
* but for now better to silently swallow typmod, etc.
33003309
* - thomas 2000-03-22
33013310
*/
@@ -3305,33 +3314,48 @@ func_arg:
33053314
FunctionParameter *n = makeNode(FunctionParameter);
33063315
n->name = $2;
33073316
n->argType = $3;
3317+
n->mode = $1;
33083318
$$ = n;
33093319
}
3310-
| arg_class func_type
3320+
| param_name arg_class func_type
33113321
{
33123322
FunctionParameter *n = makeNode(FunctionParameter);
3313-
n->name = NULL;
3323+
n->name = $1;
3324+
n->argType = $3;
3325+
n->mode = $2;
3326+
$$ = n;
3327+
}
3328+
| param_name func_type
3329+
{
3330+
FunctionParameter *n = makeNode(FunctionParameter);
3331+
n->name = $1;
33143332
n->argType = $2;
3333+
n->mode = FUNC_PARAM_IN;
33153334
$$ = n;
33163335
}
3317-
;
3318-
3319-
arg_class: IN_P { $$ = FALSE; }
3320-
| OUT_P
3336+
| arg_class func_type
33213337
{
3322-
ereport(ERROR,
3323-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3324-
errmsg("CREATE FUNCTION / OUT parameters are not implemented")));
3325-
$$ = TRUE;
3338+
FunctionParameter *n = makeNode(FunctionParameter);
3339+
n->name = NULL;
3340+
n->argType = $2;
3341+
n->mode = $1;
3342+
$$ = n;
33263343
}
3327-
| INOUT
3344+
| func_type
33283345
{
3329-
ereport(ERROR,
3330-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3331-
errmsg("CREATE FUNCTION / INOUT parameters are not implemented")));
3332-
$$ = FALSE;
3346+
FunctionParameter *n = makeNode(FunctionParameter);
3347+
n->name = NULL;
3348+
n->argType = $1;
3349+
n->mode = FUNC_PARAM_IN;
3350+
$$ = n;
33333351
}
3334-
| /*EMPTY*/ { $$ = FALSE; }
3352+
;
3353+
3354+
/* INOUT is SQL99 standard, IN OUT is for Oracle compatibility */
3355+
arg_class: IN_P { $$ = FUNC_PARAM_IN; }
3356+
| OUT_P { $$ = FUNC_PARAM_OUT; }
3357+
| INOUT { $$ = FUNC_PARAM_INOUT; }
3358+
| IN_P OUT_P { $$ = FUNC_PARAM_INOUT; }
33353359
;
33363360

33373361
/*
@@ -3458,7 +3482,7 @@ AlterFunctionStmt:
34583482
ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict
34593483
{
34603484
AlterFunctionStmt *n = makeNode(AlterFunctionStmt);
3461-
n->func = (FuncWithArgs *) $3;
3485+
n->func = $3;
34623486
n->actions = $4;
34633487
$$ = (Node *) n;
34643488
}
@@ -3561,7 +3585,7 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
35613585
CreateCastStmt *n = makeNode(CreateCastStmt);
35623586
n->sourcetype = $4;
35633587
n->targettype = $6;
3564-
n->func = (FuncWithArgs *) $10;
3588+
n->func = $10;
35653589
n->context = (CoercionContext) $11;
35663590
$$ = (Node *)n;
35673591
}
@@ -8299,9 +8323,9 @@ check_func_name(List *names)
82998323

83008324
/* extractArgTypes()
83018325
* Given a list of FunctionParameter nodes, extract a list of just the
8302-
* argument types (TypeNames). Most of the productions using func_args
8303-
* don't currently want the full FunctionParameter data, so we use this
8304-
* rather than having two sets of productions.
8326+
* argument types (TypeNames) for input parameters only. This is what
8327+
* is needed to look up an existing function, which is what is wanted by
8328+
* the productions that use this call.
83058329
*/
83068330
static List *
83078331
extractArgTypes(List *parameters)
@@ -8313,7 +8337,8 @@ extractArgTypes(List *parameters)
83138337
{
83148338
FunctionParameter *p = (FunctionParameter *) lfirst(i);
83158339

8316-
result = lappend(result, p->argType);
8340+
if (p->mode != FUNC_PARAM_OUT) /* keep if IN or INOUT */
8341+
result = lappend(result, p->argType);
83178342
}
83188343
return result;
83198344
}

src/include/nodes/parsenodes.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.274 2005/03/14 00:19:37 neilc Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.275 2005/03/29 17:58:51 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -899,6 +899,11 @@ typedef struct PrivGrantee
899899
char *groupname;
900900
} PrivGrantee;
901901

902+
/*
903+
* Note: FuncWithArgs carries only the types of the input parameters of the
904+
* function. So it is sufficient to identify an existing function, but it
905+
* is not enough info to define a function nor to call it.
906+
*/
902907
typedef struct FuncWithArgs
903908
{
904909
NodeTag type;
@@ -1389,12 +1394,20 @@ typedef struct CreateFunctionStmt
13891394
List *withClause; /* a list of DefElem */
13901395
} CreateFunctionStmt;
13911396

1397+
typedef enum FunctionParameterMode
1398+
{
1399+
/* the assigned enum values appear in pg_proc, don't change 'em! */
1400+
FUNC_PARAM_IN = 'i', /* input only */
1401+
FUNC_PARAM_OUT = 'o', /* output only */
1402+
FUNC_PARAM_INOUT = 'b' /* both */
1403+
} FunctionParameterMode;
1404+
13921405
typedef struct FunctionParameter
13931406
{
13941407
NodeTag type;
13951408
char *name; /* parameter name, or NULL if not given */
13961409
TypeName *argType; /* TypeName for parameter type */
1397-
/* someday add IN/OUT/INOUT indicator here */
1410+
FunctionParameterMode mode; /* IN/OUT/INOUT */
13981411
} FunctionParameter;
13991412

14001413
typedef struct AlterFunctionStmt

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy