Commit f2c65737 authored by Tom Lane's avatar Tom Lane

Add CREATE OR REPLACE FUNCTION syntax to allow replacing a function

definition without changing the function's OID, thereby not breaking
rules, views, triggers, etc that depend on it.  From Gavin Sherry.
parent f24fe141
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.26 2001/09/03 12:57:49 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.27 2001/10/02 21:39:35 tgl Exp $
--> -->
<refentry id="SQL-CREATEFUNCTION"> <refentry id="SQL-CREATEFUNCTION">
...@@ -15,12 +15,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.26 2001/09/03 ...@@ -15,12 +15,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.26 2001/09/03
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] ) CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] )
RETURNS <replaceable class="parameter">rettype</replaceable> RETURNS <replaceable class="parameter">rettype</replaceable>
AS '<replaceable class="parameter">definition</replaceable>' AS '<replaceable class="parameter">definition</replaceable>'
LANGUAGE <replaceable class="parameter">langname</replaceable> LANGUAGE <replaceable class="parameter">langname</replaceable>
[ WITH ( <replaceable class="parameter">attribute</replaceable> [, ...] ) ] [ WITH ( <replaceable class="parameter">attribute</replaceable> [, ...] ) ]
CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] ) CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] )
RETURNS <replaceable class="parameter">rettype</replaceable> RETURNS <replaceable class="parameter">rettype</replaceable>
AS '<replaceable class="parameter">obj_file</replaceable>', '<replaceable class="parameter">link_symbol</replaceable>' AS '<replaceable class="parameter">obj_file</replaceable>', '<replaceable class="parameter">link_symbol</replaceable>'
LANGUAGE <replaceable class="parameter">langname</replaceable> LANGUAGE <replaceable class="parameter">langname</replaceable>
...@@ -33,6 +33,8 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab ...@@ -33,6 +33,8 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
<para> <para>
<command>CREATE FUNCTION</command> defines a new function. <command>CREATE FUNCTION</command> defines a new function.
<command>CREATE OR REPLACE FUNCTION</command> will either create
a new function, or replace an existing definition.
<variablelist> <variablelist>
<title>Parameters</title> <title>Parameters</title>
...@@ -202,11 +204,6 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab ...@@ -202,11 +204,6 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
for further information on writing external functions. for further information on writing external functions.
</para> </para>
<para>
Use <command>DROP FUNCTION</command>
to remove user-defined functions.
</para>
<para> <para>
The full <acronym>SQL</acronym> type syntax is allowed for The full <acronym>SQL</acronym> type syntax is allowed for
input arguments and return value. However, some details of the input arguments and return value. However, some details of the
...@@ -250,6 +247,29 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab ...@@ -250,6 +247,29 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
linkend="sql-load"> command. linkend="sql-load"> command.
</para> </para>
<para>
Use <command>DROP FUNCTION</command>
to remove user-defined functions.
</para>
<para>
To update the definition of an existing function, use
<command>CREATE OR REPLACE FUNCTION</command>. Note that it is
not possible to change the name or argument types of a function
this way (if you tried, you'd just be creating a new, distinct
function). Also, <command>CREATE OR REPLACE FUNCTION</command>
will not let you change the return type of an existing function.
To do that, you must drop and re-create the function.
</para>
<para>
If you drop and then re-create a function, the new function is not
the same entity as the old; you will break existing rules, views,
triggers, etc that referred to the old function. Use
<command>CREATE OR REPLACE FUNCTION</command> to change a function
definition without breaking objects that refer to the function.
</para>
</refsect1> </refsect1>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.59 2001/09/08 01:10:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.60 2001/10/02 21:39:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -41,6 +41,7 @@ static void checkretval(Oid rettype, List *queryTreeList); ...@@ -41,6 +41,7 @@ static void checkretval(Oid rettype, List *queryTreeList);
*/ */
Oid Oid
ProcedureCreate(char *procedureName, ProcedureCreate(char *procedureName,
bool replace,
bool returnsSet, bool returnsSet,
char *returnTypeName, char *returnTypeName,
char *languageName, char *languageName,
...@@ -58,10 +59,12 @@ ProcedureCreate(char *procedureName, ...@@ -58,10 +59,12 @@ ProcedureCreate(char *procedureName,
int i; int i;
Relation rel; Relation rel;
HeapTuple tup; HeapTuple tup;
HeapTuple oldtup;
bool defined; bool defined;
uint16 parameterCount; uint16 parameterCount;
char nulls[Natts_pg_proc]; char nulls[Natts_pg_proc];
Datum values[Natts_pg_proc]; Datum values[Natts_pg_proc];
char replaces[Natts_pg_proc];
Oid languageObjectId; Oid languageObjectId;
Oid typeObjectId; Oid typeObjectId;
List *x; List *x;
...@@ -120,15 +123,6 @@ ProcedureCreate(char *procedureName, ...@@ -120,15 +123,6 @@ ProcedureCreate(char *procedureName,
typev[parameterCount++] = toid; typev[parameterCount++] = toid;
} }
/* Check for duplicate definition */
if (SearchSysCacheExists(PROCNAME,
PointerGetDatum(procedureName),
UInt16GetDatum(parameterCount),
PointerGetDatum(typev),
0))
elog(ERROR, "function %s already exists with same argument types",
procedureName);
if (languageObjectId == SQLlanguageId) if (languageObjectId == SQLlanguageId)
{ {
...@@ -260,13 +254,14 @@ ProcedureCreate(char *procedureName, ...@@ -260,13 +254,14 @@ ProcedureCreate(char *procedureName,
} }
/* /*
* All seems OK; prepare the tuple to be inserted into pg_proc. * All seems OK; prepare the data to be inserted into pg_proc.
*/ */
for (i = 0; i < Natts_pg_proc; ++i) for (i = 0; i < Natts_pg_proc; ++i)
{ {
nulls[i] = ' '; nulls[i] = ' ';
values[i] = (Datum) NULL; values[i] = (Datum) NULL;
replaces[i] = 'r';
} }
i = 0; i = 0;
...@@ -293,14 +288,49 @@ ProcedureCreate(char *procedureName, ...@@ -293,14 +288,49 @@ ProcedureCreate(char *procedureName,
CStringGetDatum(probin)); CStringGetDatum(probin));
rel = heap_openr(ProcedureRelationName, RowExclusiveLock); rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
tupDesc = rel->rd_att; tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc,
values,
nulls);
heap_insert(rel, tup); /* Check for pre-existing definition */
oldtup = SearchSysCache(PROCNAME,
PointerGetDatum(procedureName),
UInt16GetDatum(parameterCount),
PointerGetDatum(typev),
0);
if (HeapTupleIsValid(oldtup))
{
/* There is one; okay to replace it? */
Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
if (!replace)
elog(ERROR, "function %s already exists with same argument types",
procedureName);
if (GetUserId() != oldproc->proowner && !superuser())
elog(ERROR, "ProcedureCreate: you do not have permission to replace function %s",
procedureName);
/*
* Not okay to change the return type of the existing proc, since
* existing rules, views, etc may depend on the return type.
*/
if (typeObjectId != oldproc->prorettype ||
returnsSet != oldproc->proretset)
elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
"\n\tUse DROP FUNCTION first.");
/* Okay, do it... */
tup = heap_modifytuple(oldtup, rel, values, nulls, replaces);
simple_heap_update(rel, &tup->t_self, tup);
ReleaseSysCache(oldtup);
}
else
{
/* Creating a new procedure */
tup = heap_formtuple(tupDesc, values, nulls);
heap_insert(rel, tup);
}
/* Need to update indices for either the insert or update case */
if (RelationGetForm(rel)->relhasindex) if (RelationGetForm(rel)->relhasindex)
{ {
Relation idescs[Num_pg_proc_indices]; Relation idescs[Num_pg_proc_indices];
...@@ -309,9 +339,12 @@ ProcedureCreate(char *procedureName, ...@@ -309,9 +339,12 @@ ProcedureCreate(char *procedureName,
CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup); CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup);
CatalogCloseIndices(Num_pg_proc_indices, idescs); CatalogCloseIndices(Num_pg_proc_indices, idescs);
} }
heap_close(rel, RowExclusiveLock);
retval = tup->t_data->t_oid; retval = tup->t_data->t_oid;
heap_freetuple(tup); heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
return retval; return retval;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.60 2001/09/08 01:10:20 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.61 2001/10/02 21:39:35 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -324,6 +324,7 @@ CreateFunction(ProcedureStmt *stmt) ...@@ -324,6 +324,7 @@ CreateFunction(ProcedureStmt *stmt)
* to do so, go ahead and create the function. * to do so, go ahead and create the function.
*/ */
ProcedureCreate(stmt->funcname, ProcedureCreate(stmt->funcname,
stmt->replace,
returnsSet, returnsSet,
prorettype, prorettype,
languageName, languageName,
......
...@@ -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
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.156 2001/09/18 01:59:06 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.157 2001/10/02 21:39:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2071,6 +2071,7 @@ _copyProcedureStmt(ProcedureStmt *from) ...@@ -2071,6 +2071,7 @@ _copyProcedureStmt(ProcedureStmt *from)
{ {
ProcedureStmt *newnode = makeNode(ProcedureStmt); ProcedureStmt *newnode = makeNode(ProcedureStmt);
newnode->replace = from->replace;
newnode->funcname = pstrdup(from->funcname); newnode->funcname = pstrdup(from->funcname);
Node_Copy(from, newnode, argTypes); Node_Copy(from, newnode, argTypes);
Node_Copy(from, newnode, returnType); Node_Copy(from, newnode, returnType);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.104 2001/09/18 01:59:06 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.105 2001/10/02 21:39:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -941,6 +941,8 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b) ...@@ -941,6 +941,8 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
static bool static bool
_equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b) _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
{ {
if (a->replace != b->replace)
return false;
if (!equalstr(a->funcname, b->funcname)) if (!equalstr(a->funcname, b->funcname))
return false; return false;
if (!equal(a->argTypes, b->argTypes)) if (!equal(a->argTypes, b->argTypes))
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.255 2001/10/01 04:19:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.256 2001/10/02 21:39:35 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -151,7 +151,7 @@ static void doNegateFloat(Value *v); ...@@ -151,7 +151,7 @@ static void doNegateFloat(Value *v);
%type <list> createdb_opt_list, createdb_opt_item %type <list> createdb_opt_list, createdb_opt_item
%type <ival> opt_lock, lock_type %type <ival> opt_lock, lock_type
%type <boolean> opt_force %type <boolean> opt_force, opt_or_replace
%type <list> user_list %type <list> user_list
...@@ -321,13 +321,13 @@ static void doNegateFloat(Value *v); ...@@ -321,13 +321,13 @@ static void doNegateFloat(Value *v);
VALUES, VARCHAR, VARYING, VIEW, VALUES, VARCHAR, VARYING, VIEW,
WHEN, WHERE, WITH, WORK, YEAR_P, ZONE WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
/* Keywords (in SQL3 reserved words) */ /* Keywords (in SQL99 reserved words) */
%token CHAIN, CHARACTERISTICS, %token CHAIN, CHARACTERISTICS,
DEFERRABLE, DEFERRED, DEFERRABLE, DEFERRED,
IMMEDIATE, INITIALLY, INOUT, IMMEDIATE, INITIALLY, INOUT,
OFF, OUT, OFF, OUT,
PATH_P, PENDANT, PATH_P, PENDANT,
RESTRICT, REPLACE, RESTRICT,
TRIGGER, TRIGGER,
WITHOUT WITHOUT
...@@ -2497,33 +2497,32 @@ RecipeStmt: EXECUTE RECIPE recipe_name ...@@ -2497,33 +2497,32 @@ RecipeStmt: EXECUTE RECIPE recipe_name
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* define function <fname> * create [or replace] function <fname>
* [(<type-1> { , <type-n>})] * [(<type-1> { , <type-n>})]
* returns <type-r> * returns <type-r>
* as <filename or code in language as appropriate> * as <filename or code in language as appropriate>
* language <lang> [with * language <lang> [with parameters]
* [ arch_pct = <percentage | pre-defined>]
* [, disk_pct = <percentage | pre-defined>]
* [, byte_pct = <percentage | pre-defined>]
* [, perbyte_cpu = <int | pre-defined>]
* [, percall_cpu = <int | pre-defined>]
* [, iscachable] ]
* *
*****************************************************************************/ *****************************************************************************/
ProcedureStmt: CREATE FUNCTION func_name func_args ProcedureStmt: CREATE opt_or_replace FUNCTION func_name func_args
RETURNS func_return AS func_as LANGUAGE ColId_or_Sconst opt_with RETURNS func_return AS func_as LANGUAGE ColId_or_Sconst opt_with
{ {
ProcedureStmt *n = makeNode(ProcedureStmt); ProcedureStmt *n = makeNode(ProcedureStmt);
n->funcname = $3; n->replace = $2;
n->argTypes = $4; n->funcname = $4;
n->returnType = (Node *)$6; n->argTypes = $5;
n->withClause = $11; n->returnType = (Node *) $7;
n->as = $8; n->withClause = $12;
n->language = $10; n->as = $9;
n->language = $11;
$$ = (Node *)n; $$ = (Node *)n;
}; };
opt_or_replace: OR REPLACE { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
opt_with: WITH definition { $$ = $2; } opt_with: WITH definition { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
...@@ -5682,6 +5681,7 @@ TokenId: ABSOLUTE { $$ = "absolute"; } ...@@ -5682,6 +5681,7 @@ TokenId: ABSOLUTE { $$ = "absolute"; }
| REINDEX { $$ = "reindex"; } | REINDEX { $$ = "reindex"; }
| RELATIVE { $$ = "relative"; } | RELATIVE { $$ = "relative"; }
| RENAME { $$ = "rename"; } | RENAME { $$ = "rename"; }
| REPLACE { $$ = "replace"; }
| RESTRICT { $$ = "restrict"; } | RESTRICT { $$ = "restrict"; }
| RETURNS { $$ = "returns"; } | RETURNS { $$ = "returns"; }
| REVOKE { $$ = "revoke"; } | REVOKE { $$ = "revoke"; }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.97 2001/08/26 16:56:00 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.98 2001/10/02 21:39:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -216,6 +216,7 @@ static ScanKeyword ScanKeywords[] = { ...@@ -216,6 +216,7 @@ static ScanKeyword ScanKeywords[] = {
{"reindex", REINDEX}, {"reindex", REINDEX},
{"relative", RELATIVE}, {"relative", RELATIVE},
{"rename", RENAME}, {"rename", RENAME},
{"replace", REPLACE},
{"reset", RESET}, {"reset", RESET},
{"restrict", RESTRICT}, {"restrict", RESTRICT},
{"returns", RETURNS}, {"returns", RETURNS},
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.38 2001/09/08 01:10:20 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.39 2001/10/02 21:39:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -51,6 +51,7 @@ SetDefine(char *querystr, char *typename) ...@@ -51,6 +51,7 @@ SetDefine(char *querystr, char *typename)
char repl[Natts_pg_proc]; char repl[Natts_pg_proc];
setoid = ProcedureCreate(procname, /* changed below, after oid known */ setoid = ProcedureCreate(procname, /* changed below, after oid known */
false, /* don't replace */
true, /* returnsSet */ true, /* returnsSet */
typename, /* returnTypeName */ typename, /* returnTypeName */
"sql", /* languageName */ "sql", /* languageName */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_proc.h,v 1.212 2001/09/28 08:09:13 thomas Exp $ * $Id: pg_proc.h,v 1.213 2001/10/02 21:39:36 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -2854,6 +2854,7 @@ DESCR("time zone"); ...@@ -2854,6 +2854,7 @@ DESCR("time zone");
* prototypes for functions pg_proc.c * prototypes for functions pg_proc.c
*/ */
extern Oid ProcedureCreate(char *procedureName, extern Oid ProcedureCreate(char *procedureName,
bool replace,
bool returnsSet, bool returnsSet,
char *returnTypeName, char *returnTypeName,
char *languageName, char *languageName,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.144 2001/09/18 01:59:06 tgl Exp $ * $Id: parsenodes.h,v 1.145 2001/10/02 21:39:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -514,6 +514,7 @@ typedef struct IndexStmt ...@@ -514,6 +514,7 @@ typedef struct IndexStmt
typedef struct ProcedureStmt typedef struct ProcedureStmt
{ {
NodeTag type; NodeTag type;
bool replace; /* T => replace if already exists */
char *funcname; /* name of function to create */ char *funcname; /* name of function to create */
List *argTypes; /* list of argument types (TypeName nodes) */ List *argTypes; /* list of argument types (TypeName nodes) */
Node *returnType; /* the return type (a TypeName node) */ Node *returnType; /* the return type (a TypeName node) */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.44 2001/09/19 14:09:32 meskes Exp $ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.45 2001/10/02 21:39:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -118,6 +118,7 @@ static ScanKeyword ScanKeywords[] = { ...@@ -118,6 +118,7 @@ static ScanKeyword ScanKeywords[] = {
{"force", FORCE}, {"force", FORCE},
{"foreign", FOREIGN}, {"foreign", FOREIGN},
{"forward", FORWARD}, {"forward", FORWARD},
{"freeze", FREEZE},
{"from", FROM}, {"from", FROM},
{"full", FULL}, {"full", FULL},
{"function", FUNCTION}, {"function", FUNCTION},
...@@ -215,6 +216,7 @@ static ScanKeyword ScanKeywords[] = { ...@@ -215,6 +216,7 @@ static ScanKeyword ScanKeywords[] = {
{"reindex", REINDEX}, {"reindex", REINDEX},
{"relative", RELATIVE}, {"relative", RELATIVE},
{"rename", RENAME}, {"rename", RENAME},
{"replace", REPLACE},
{"reset", RESET}, {"reset", RESET},
{"restrict", RESTRICT}, {"restrict", RESTRICT},
{"returns", RETURNS}, {"returns", RETURNS},
...@@ -262,7 +264,7 @@ static ScanKeyword ScanKeywords[] = { ...@@ -262,7 +264,7 @@ static ScanKeyword ScanKeywords[] = {
{"truncate", TRUNCATE}, {"truncate", TRUNCATE},
{"trusted", TRUSTED}, {"trusted", TRUSTED},
{"type", TYPE_P}, {"type", TYPE_P},
{"unencrypted", UNENCRYPTED}, {"unencrypted", UNENCRYPTED},
{"union", UNION}, {"union", UNION},
{"unique", UNIQUE}, {"unique", UNIQUE},
{"unknown", UNKNOWN}, {"unknown", UNKNOWN},
......
...@@ -202,7 +202,7 @@ make_name(void) ...@@ -202,7 +202,7 @@ make_name(void)
%token DEFERRABLE, DEFERRED, %token DEFERRABLE, DEFERRED,
IMMEDIATE, INITIALLY, IMMEDIATE, INITIALLY,
PENDANT, PENDANT,
RESTRICT, REPLACE, RESTRICT,
TRIGGER TRIGGER
/* Keywords (in SQL92 non-reserved words) */ /* Keywords (in SQL92 non-reserved words) */
...@@ -338,7 +338,7 @@ make_name(void) ...@@ -338,7 +338,7 @@ make_name(void)
%type <str> constraints_set_mode comment_type comment_cl comment_ag %type <str> constraints_set_mode comment_type comment_cl comment_ag
%type <str> CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete %type <str> CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
%type <str> opt_force key_update CreateSchemaStmt PosIntStringConst %type <str> opt_force key_update CreateSchemaStmt PosIntStringConst
%type <str> IntConst PosIntConst grantee_list func_type %type <str> IntConst PosIntConst grantee_list func_type opt_or_replace
%type <str> select_limit opt_for_update_clause CheckPointStmt %type <str> select_limit opt_for_update_clause CheckPointStmt
%type <str> ECPGWhenever ECPGConnect connection_target ECPGOpen %type <str> ECPGWhenever ECPGConnect connection_target ECPGOpen
...@@ -1881,26 +1881,24 @@ RecipeStmt: EXECUTE RECIPE recipe_name ...@@ -1881,26 +1881,24 @@ RecipeStmt: EXECUTE RECIPE recipe_name
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* define function <fname> * create [or replace] function <fname>
* [(<type-1> { , <type-n>})] * [(<type-1> { , <type-n>})]
* returns <type-r> * returns <type-r>
* as <filename or code in language as appropriate> * as <filename or code in language as appropriate>
* language <lang> [with * language <lang> [with parameters]
* [ arch_pct = <percentage | pre-defined>]
* [, disk_pct = <percentage | pre-defined>]
* [, byte_pct = <percentage | pre-defined>]
* [, perbyte_cpu = <int | pre-defined>]
* [, percall_cpu = <int | pre-defined>]
* [, iscachable]
* *
*****************************************************************************/ *****************************************************************************/
ProcedureStmt: CREATE FUNCTION func_name func_args ProcedureStmt: CREATE opt_or_replace FUNCTION func_name func_args
RETURNS func_return AS func_as LANGUAGE ColId_or_Sconst opt_with RETURNS func_return AS func_as LANGUAGE ColId_or_Sconst opt_with
{ {
$$ = cat_str(10, make_str("create function"), $3, $4, make_str("returns"), $6, make_str("as"), $8, make_str("language"), $10, $11); $$ = cat_str(12, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, make_str("as"), $9, make_str("language"), $11, $12);
} }
opt_or_replace: OR REPLACE { $$ = make_str("or replace"); }
| /*EMPTY*/ { $$ = EMPTY; }
;
opt_with: WITH definition { $$ = cat2_str(make_str("with"), $2); } opt_with: WITH definition { $$ = cat2_str(make_str("with"), $2); }
| /*EMPTY*/ { $$ = EMPTY; } | /*EMPTY*/ { $$ = EMPTY; }
; ;
...@@ -5043,6 +5041,7 @@ TokenId: ABSOLUTE { $$ = make_str("absolute"); } ...@@ -5043,6 +5041,7 @@ TokenId: ABSOLUTE { $$ = make_str("absolute"); }
| REINDEX { $$ = make_str("reindex"); } | REINDEX { $$ = make_str("reindex"); }
| RELATIVE { $$ = make_str("relative"); } | RELATIVE { $$ = make_str("relative"); }
| RENAME { $$ = make_str("rename"); } | RENAME { $$ = make_str("rename"); }
| REPLACE { $$ = make_str("replace"); }
| RESTRICT { $$ = make_str("restrict"); } | RESTRICT { $$ = make_str("restrict"); }
| RETURNS { $$ = make_str("returns"); } | RETURNS { $$ = make_str("returns"); }
| REVOKE { $$ = make_str("revoke"); } | REVOKE { $$ = make_str("revoke"); }
......
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