Commit eb47ee48 authored by Tom Lane's avatar Tom Lane

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.
parent 8c85a34a
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.57 2005/03/29 00:16:57 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.58 2005/03/29 17:58:49 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* These routines take the parse tree and pick out the * These routines take the parse tree and pick out the
...@@ -154,6 +154,15 @@ examine_parameter_list(List *parameter, Oid languageOid, ...@@ -154,6 +154,15 @@ examine_parameter_list(List *parameter, Oid languageOid,
errmsg("functions cannot have more than %d arguments", errmsg("functions cannot have more than %d arguments",
FUNC_MAX_ARGS))); FUNC_MAX_ARGS)));
if (fp->mode == FUNC_PARAM_OUT)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE FUNCTION / OUT parameters are not implemented")));
if (fp->mode == FUNC_PARAM_INOUT)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CREATE FUNCTION / INOUT parameters are not implemented")));
toid = LookupTypeName(t); toid = LookupTypeName(t);
if (OidIsValid(toid)) if (OidIsValid(toid))
{ {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.298 2005/03/14 00:19:36 neilc Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.299 2005/03/29 17:58:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1888,6 +1888,7 @@ _copyFunctionParameter(FunctionParameter *from) ...@@ -1888,6 +1888,7 @@ _copyFunctionParameter(FunctionParameter *from)
COPY_STRING_FIELD(name); COPY_STRING_FIELD(name);
COPY_NODE_FIELD(argType); COPY_NODE_FIELD(argType);
COPY_SCALAR_FIELD(mode);
return newnode; return newnode;
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.237 2005/03/14 00:19:36 neilc Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.238 2005/03/29 17:58:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -949,6 +949,7 @@ _equalFunctionParameter(FunctionParameter *a, FunctionParameter *b) ...@@ -949,6 +949,7 @@ _equalFunctionParameter(FunctionParameter *a, FunctionParameter *b)
{ {
COMPARE_STRING_FIELD(name); COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(argType); COMPARE_NODE_FIELD(argType);
COMPARE_SCALAR_FIELD(mode);
return true; return true;
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.484 2005/03/14 00:19:36 neilc Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.485 2005/03/29 17:58:50 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -114,6 +114,8 @@ static void doNegateFloat(Value *v); ...@@ -114,6 +114,8 @@ static void doNegateFloat(Value *v);
TypeName *typnam; TypeName *typnam;
FunctionParameter *fun_param; FunctionParameter *fun_param;
FunctionParameterMode fun_param_mode;
FuncWithArgs *funwithargs;
DefElem *defelt; DefElem *defelt;
SortBy *sortby; SortBy *sortby;
JoinExpr *jexpr; JoinExpr *jexpr;
...@@ -206,7 +208,7 @@ static void doNegateFloat(Value *v); ...@@ -206,7 +208,7 @@ static void doNegateFloat(Value *v);
%type <ival> privilege %type <ival> privilege
%type <list> privileges privilege_list %type <list> privileges privilege_list
%type <privtarget> privilege_target %type <privtarget> privilege_target
%type <node> function_with_argtypes %type <funwithargs> function_with_argtypes
%type <list> function_with_argtypes_list %type <list> function_with_argtypes_list
%type <chr> TriggerOneEvent %type <chr> TriggerOneEvent
...@@ -233,9 +235,10 @@ static void doNegateFloat(Value *v); ...@@ -233,9 +235,10 @@ static void doNegateFloat(Value *v);
%type <defelt> createfunc_opt_item common_func_opt_item %type <defelt> createfunc_opt_item common_func_opt_item
%type <fun_param> func_arg %type <fun_param> func_arg
%type <fun_param_mode> arg_class
%type <typnam> func_return func_type aggr_argtype %type <typnam> func_return func_type aggr_argtype
%type <boolean> arg_class TriggerForType OptTemp %type <boolean> TriggerForType OptTemp
%type <oncommit> OnCommitOption %type <oncommit> OnCommitOption
%type <withoids> OptWithOids WithOidsAs %type <withoids> OptWithOids WithOidsAs
...@@ -3177,7 +3180,7 @@ function_with_argtypes: ...@@ -3177,7 +3180,7 @@ function_with_argtypes:
FuncWithArgs *n = makeNode(FuncWithArgs); FuncWithArgs *n = makeNode(FuncWithArgs);
n->funcname = $1; n->funcname = $1;
n->funcargs = extractArgTypes($2); n->funcargs = extractArgTypes($2);
$$ = (Node *)n; $$ = n;
} }
; ;
...@@ -3295,7 +3298,13 @@ func_args_list: ...@@ -3295,7 +3298,13 @@ func_args_list:
| func_args_list ',' func_arg { $$ = lappend($1, $3); } | func_args_list ',' func_arg { $$ = lappend($1, $3); }
; ;
/* We can catch over-specified arguments here if we want to, /*
* The style with arg_class first is SQL99 standard, but Oracle puts
* param_name first; accept both since it's likely people will try both
* anyway. Don't bother trying to save productions by letting arg_class
* have an empty alternative ... you'll get shift/reduce conflicts.
*
* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc. * but for now better to silently swallow typmod, etc.
* - thomas 2000-03-22 * - thomas 2000-03-22
*/ */
...@@ -3305,33 +3314,48 @@ func_arg: ...@@ -3305,33 +3314,48 @@ func_arg:
FunctionParameter *n = makeNode(FunctionParameter); FunctionParameter *n = makeNode(FunctionParameter);
n->name = $2; n->name = $2;
n->argType = $3; n->argType = $3;
n->mode = $1;
$$ = n; $$ = n;
} }
| arg_class func_type | param_name arg_class func_type
{ {
FunctionParameter *n = makeNode(FunctionParameter); FunctionParameter *n = makeNode(FunctionParameter);
n->name = NULL; n->name = $1;
n->argType = $3;
n->mode = $2;
$$ = n;
}
| param_name func_type
{
FunctionParameter *n = makeNode(FunctionParameter);
n->name = $1;
n->argType = $2; n->argType = $2;
n->mode = FUNC_PARAM_IN;
$$ = n; $$ = n;
} }
; | arg_class func_type
arg_class: IN_P { $$ = FALSE; }
| OUT_P
{ {
ereport(ERROR, FunctionParameter *n = makeNode(FunctionParameter);
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), n->name = NULL;
errmsg("CREATE FUNCTION / OUT parameters are not implemented"))); n->argType = $2;
$$ = TRUE; n->mode = $1;
$$ = n;
} }
| INOUT | func_type
{ {
ereport(ERROR, FunctionParameter *n = makeNode(FunctionParameter);
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), n->name = NULL;
errmsg("CREATE FUNCTION / INOUT parameters are not implemented"))); n->argType = $1;
$$ = FALSE; n->mode = FUNC_PARAM_IN;
$$ = n;
} }
| /*EMPTY*/ { $$ = FALSE; } ;
/* INOUT is SQL99 standard, IN OUT is for Oracle compatibility */
arg_class: IN_P { $$ = FUNC_PARAM_IN; }
| OUT_P { $$ = FUNC_PARAM_OUT; }
| INOUT { $$ = FUNC_PARAM_INOUT; }
| IN_P OUT_P { $$ = FUNC_PARAM_INOUT; }
; ;
/* /*
...@@ -3458,7 +3482,7 @@ AlterFunctionStmt: ...@@ -3458,7 +3482,7 @@ AlterFunctionStmt:
ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict
{ {
AlterFunctionStmt *n = makeNode(AlterFunctionStmt); AlterFunctionStmt *n = makeNode(AlterFunctionStmt);
n->func = (FuncWithArgs *) $3; n->func = $3;
n->actions = $4; n->actions = $4;
$$ = (Node *) n; $$ = (Node *) n;
} }
...@@ -3561,7 +3585,7 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')' ...@@ -3561,7 +3585,7 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
CreateCastStmt *n = makeNode(CreateCastStmt); CreateCastStmt *n = makeNode(CreateCastStmt);
n->sourcetype = $4; n->sourcetype = $4;
n->targettype = $6; n->targettype = $6;
n->func = (FuncWithArgs *) $10; n->func = $10;
n->context = (CoercionContext) $11; n->context = (CoercionContext) $11;
$$ = (Node *)n; $$ = (Node *)n;
} }
...@@ -8299,9 +8323,9 @@ check_func_name(List *names) ...@@ -8299,9 +8323,9 @@ check_func_name(List *names)
/* extractArgTypes() /* extractArgTypes()
* Given a list of FunctionParameter nodes, extract a list of just the * Given a list of FunctionParameter nodes, extract a list of just the
* argument types (TypeNames). Most of the productions using func_args * argument types (TypeNames) for input parameters only. This is what
* don't currently want the full FunctionParameter data, so we use this * is needed to look up an existing function, which is what is wanted by
* rather than having two sets of productions. * the productions that use this call.
*/ */
static List * static List *
extractArgTypes(List *parameters) extractArgTypes(List *parameters)
...@@ -8313,7 +8337,8 @@ extractArgTypes(List *parameters) ...@@ -8313,7 +8337,8 @@ extractArgTypes(List *parameters)
{ {
FunctionParameter *p = (FunctionParameter *) lfirst(i); FunctionParameter *p = (FunctionParameter *) lfirst(i);
result = lappend(result, p->argType); if (p->mode != FUNC_PARAM_OUT) /* keep if IN or INOUT */
result = lappend(result, p->argType);
} }
return result; return result;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.274 2005/03/14 00:19:37 neilc Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.275 2005/03/29 17:58:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -899,6 +899,11 @@ typedef struct PrivGrantee ...@@ -899,6 +899,11 @@ typedef struct PrivGrantee
char *groupname; char *groupname;
} PrivGrantee; } PrivGrantee;
/*
* Note: FuncWithArgs carries only the types of the input parameters of the
* function. So it is sufficient to identify an existing function, but it
* is not enough info to define a function nor to call it.
*/
typedef struct FuncWithArgs typedef struct FuncWithArgs
{ {
NodeTag type; NodeTag type;
...@@ -1389,12 +1394,20 @@ typedef struct CreateFunctionStmt ...@@ -1389,12 +1394,20 @@ typedef struct CreateFunctionStmt
List *withClause; /* a list of DefElem */ List *withClause; /* a list of DefElem */
} CreateFunctionStmt; } CreateFunctionStmt;
typedef enum FunctionParameterMode
{
/* the assigned enum values appear in pg_proc, don't change 'em! */
FUNC_PARAM_IN = 'i', /* input only */
FUNC_PARAM_OUT = 'o', /* output only */
FUNC_PARAM_INOUT = 'b' /* both */
} FunctionParameterMode;
typedef struct FunctionParameter typedef struct FunctionParameter
{ {
NodeTag type; NodeTag type;
char *name; /* parameter name, or NULL if not given */ char *name; /* parameter name, or NULL if not given */
TypeName *argType; /* TypeName for parameter type */ TypeName *argType; /* TypeName for parameter type */
/* someday add IN/OUT/INOUT indicator here */ FunctionParameterMode mode; /* IN/OUT/INOUT */
} FunctionParameter; } FunctionParameter;
typedef struct AlterFunctionStmt typedef struct AlterFunctionStmt
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment