Fix grammar for IN/OUT/INOUT parameters. This commit doesn't actually
authorTom Lane
Tue, 29 Mar 2005 17:58:51 +0000 (17:58 +0000)
committerTom Lane
Tue, 29 Mar 2005 17:58:51 +0000 (17:58 +0000)
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.

src/backend/commands/functioncmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/include/nodes/parsenodes.h

index 069adf46af5acaf4085b02e8ec6cca0a2ee18ff9..c2c521bbfeab77ddc2e1ffbbbcc9bc240763c4e1 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * 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
  *   These routines take the parse tree and pick out the
@@ -154,6 +154,15 @@ examine_parameter_list(List *parameter, Oid languageOid,
                   errmsg("functions cannot have more than %d arguments",
                          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);
        if (OidIsValid(toid))
        {
index 92f7168ae9fbf4d3337636c41a5b5b056f71cfdb..c2130e370d4b8b8277725d131c617d1e11f9e40b 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * 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)
 
    COPY_STRING_FIELD(name);
    COPY_NODE_FIELD(argType);
+   COPY_SCALAR_FIELD(mode);
 
    return newnode;
 }
index cbd99dab7207787f992efcaa810722296cee2d36..bcf8c36393725505e5a7ee600b577dd47d061326 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * 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)
 {
    COMPARE_STRING_FIELD(name);
    COMPARE_NODE_FIELD(argType);
+   COMPARE_SCALAR_FIELD(mode);
 
    return true;
 }
index a88262d432816afb3755be874688a8bbb01dc225..62497957263e6c709d52bc1e83cd68894bedbffe 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * 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
  *   AUTHOR            DATE            MAJOR EVENT
@@ -114,6 +114,8 @@ static void doNegateFloat(Value *v);
 
    TypeName            *typnam;
    FunctionParameter   *fun_param;
+   FunctionParameterMode fun_param_mode;
+   FuncWithArgs        *funwithargs;
    DefElem             *defelt;
    SortBy              *sortby;
    JoinExpr            *jexpr;
@@ -206,7 +208,7 @@ static void doNegateFloat(Value *v);
 %type    privilege
 %type    privileges privilege_list
 %type  privilege_target
-%type <node>   function_with_argtypes
+%type <funwithargs> function_with_argtypes
 %type    function_with_argtypes_list
 %type     TriggerOneEvent
 
@@ -233,9 +235,10 @@ static void doNegateFloat(Value *v);
 
 %type  createfunc_opt_item common_func_opt_item
 %type  func_arg
+%type  arg_class
 %type  func_return func_type aggr_argtype
 
-%type  arg_class TriggerForType OptTemp
+%type   TriggerForType OptTemp
 %type  OnCommitOption
 %type  OptWithOids WithOidsAs
 
@@ -3177,7 +3180,7 @@ function_with_argtypes:
                    FuncWithArgs *n = makeNode(FuncWithArgs);
                    n->funcname = $1;
                    n->funcargs = extractArgTypes($2);
-                   $$ = (Node *)n;
+                   $$ = n;
                }
        ;
 
@@ -3295,7 +3298,13 @@ func_args_list:
            | 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.
  * - thomas 2000-03-22
  */
@@ -3305,33 +3314,48 @@ func_arg:
                    FunctionParameter *n = makeNode(FunctionParameter);
                    n->name = $2;
                    n->argType = $3;
+                   n->mode = $1;
                    $$ = n;
                }
-           | arg_class func_type
+           | param_name arg_class func_type
                {
                    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->mode = FUNC_PARAM_IN;
                    $$ = n;
                }
-       ;
-
-arg_class: IN_P                                    { $$ = FALSE; }
-           | OUT_P
+           | arg_class func_type
                {
-                   ereport(ERROR,
-                           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                            errmsg("CREATE FUNCTION / OUT parameters are not implemented")));
-                   $$ = TRUE;
+                   FunctionParameter *n = makeNode(FunctionParameter);
+                   n->name = NULL;
+                   n->argType = $2;
+                   n->mode = $1;
+                   $$ = n;
                }
-           | INOUT
+           | func_type
                {
-                   ereport(ERROR,
-                           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                            errmsg("CREATE FUNCTION / INOUT parameters are not implemented")));
-                   $$ = FALSE;
+                   FunctionParameter *n = makeNode(FunctionParameter);
+                   n->name = NULL;
+                   n->argType = $1;
+                   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:
            ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict
                {
                    AlterFunctionStmt *n = makeNode(AlterFunctionStmt);
-                   n->func = (FuncWithArgs *) $3;
+                   n->func = $3;
                    n->actions = $4;
                    $$ = (Node *) n;
                }
@@ -3561,7 +3585,7 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
                    CreateCastStmt *n = makeNode(CreateCastStmt);
                    n->sourcetype = $4;
                    n->targettype = $6;
-                   n->func = (FuncWithArgs *) $10;
+                   n->func = $10;
                    n->context = (CoercionContext) $11;
                    $$ = (Node *)n;
                }
@@ -8299,9 +8323,9 @@ check_func_name(List *names)
 
 /* extractArgTypes()
  * Given a list of FunctionParameter nodes, extract a list of just the
- * argument types (TypeNames).  Most of the productions using func_args
- * don't currently want the full FunctionParameter data, so we use this
- * rather than having two sets of productions.
+ * argument types (TypeNames) for input parameters only.  This is what
+ * is needed to look up an existing function, which is what is wanted by
+ * the productions that use this call.
  */
 static List *
 extractArgTypes(List *parameters)
@@ -8313,7 +8337,8 @@ extractArgTypes(List *parameters)
    {
        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;
 }
index 8cf274b14ce1374a5151895b56d5f860247fcf48..a6a79e3a4fa5fc041bcdd3b9f9f8bb19915454cd 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * 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
    char       *groupname;
 } 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
 {
    NodeTag     type;
@@ -1389,12 +1394,20 @@ typedef struct CreateFunctionStmt
    List       *withClause;     /* a list of DefElem */
 } 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
 {
    NodeTag     type;
    char       *name;           /* parameter name, or NULL if not given */
    TypeName   *argType;        /* TypeName for parameter type */
-   /* someday add IN/OUT/INOUT indicator here */
+   FunctionParameterMode mode; /* IN/OUT/INOUT */
 } FunctionParameter;
 
 typedef struct AlterFunctionStmt