aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/bootstrap/bootparse.y3
-rw-r--r--src/backend/catalog/aclchk.c50
-rw-r--r--src/backend/catalog/namespace.c28
-rw-r--r--src/backend/catalog/pg_aggregate.c35
-rw-r--r--src/backend/catalog/pg_operator.c49
-rw-r--r--src/backend/catalog/pg_proc.c6
-rw-r--r--src/backend/commands/comment.c314
-rw-r--r--src/backend/commands/define.c71
-rw-r--r--src/backend/commands/indexcmds.c11
-rw-r--r--src/backend/commands/proclang.c29
-rw-r--r--src/backend/commands/remove.c67
-rw-r--r--src/backend/commands/trigger.c20
-rw-r--r--src/backend/nodes/copyfuncs.c30
-rw-r--r--src/backend/nodes/equalfuncs.c24
-rw-r--r--src/backend/nodes/list.c32
-rw-r--r--src/backend/nodes/outfuncs.c6
-rw-r--r--src/backend/parser/analyze.c40
-rw-r--r--src/backend/parser/gram.y140
-rw-r--r--src/backend/parser/parse_agg.c15
-rw-r--r--src/backend/parser/parse_coerce.c27
-rw-r--r--src/backend/parser/parse_expr.c17
-rw-r--r--src/backend/parser/parse_func.c146
-rw-r--r--src/backend/parser/parse_target.c47
-rw-r--r--src/backend/tcop/utility.c9
-rw-r--r--src/backend/utils/cache/syscache.c10
-rw-r--r--src/include/catalog/namespace.h4
-rw-r--r--src/include/catalog/pg_aggregate.h6
-rw-r--r--src/include/commands/comment.h5
-rw-r--r--src/include/commands/defrem.h6
-rw-r--r--src/include/nodes/parsenodes.h42
-rw-r--r--src/include/nodes/pg_list.h4
-rw-r--r--src/include/parser/gramparse.h3
-rw-r--r--src/include/parser/parse_agg.h6
-rw-r--r--src/include/parser/parse_func.h12
-rw-r--r--src/include/utils/syscache.h4
-rw-r--r--src/test/regress/expected/privileges.out2
36 files changed, 657 insertions, 663 deletions
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 7afd6659e1a..b5d039f9355 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.43 2002/04/01 14:22:41 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.44 2002/04/09 20:35:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -272,6 +272,7 @@ boot_index_param:
{
IndexElem *n = makeNode(IndexElem);
n->name = LexIDStr($1);
+ n->funcname = n->args = NIL; /* no func indexes */
n->class = LexIDStr($2);
$$ = n;
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 00c52e89c4b..07f49c75ab2 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.61 2002/03/31 06:26:29 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.62 2002/04/09 20:35:46 tgl Exp $
*
* NOTES
* See acl.h.
@@ -283,51 +283,6 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
}
-static Oid
-find_function_with_arglist(char *name, List *arguments)
-{
- Oid oid;
- Oid argoids[FUNC_MAX_ARGS];
- int i;
- int16 argcount;
-
- MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
- argcount = length(arguments);
- if (argcount > FUNC_MAX_ARGS)
- elog(ERROR, "functions cannot have more than %d arguments",
- FUNC_MAX_ARGS);
-
- for (i = 0; i < argcount; i++)
- {
- TypeName *t = (TypeName *) lfirst(arguments);
-
- argoids[i] = LookupTypeName(t);
- if (!OidIsValid(argoids[i]))
- {
- char *typnam = TypeNameToString(t);
-
- if (strcmp(typnam, "opaque") == 0)
- argoids[i] = InvalidOid;
- else
- elog(ERROR, "Type \"%s\" does not exist", typnam);
- }
-
- arguments = lnext(arguments);
- }
-
- oid = GetSysCacheOid(PROCNAME,
- PointerGetDatum(name),
- Int16GetDatum(argcount),
- PointerGetDatum(argoids),
- 0);
-
- if (!OidIsValid(oid))
- func_error(NULL, name, argcount, argoids, NULL);
-
- return oid;
-}
-
-
static void
ExecuteGrantStmt_Function(GrantStmt *stmt)
{
@@ -365,7 +320,8 @@ ExecuteGrantStmt_Function(GrantStmt *stmt)
char nulls[Natts_pg_proc];
char replaces[Natts_pg_proc];
- oid = find_function_with_arglist(func->funcname, func->funcargs);
+ oid = LookupFuncNameTypeNames(func->funcname, func->funcargs,
+ true, "GRANT");
relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(oid), 0, 0, 0);
if (!HeapTupleIsValid(tuple))
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index a7d73bbf272..6880dbe19e3 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.6 2002/04/06 06:59:21 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.7 2002/04/09 20:35:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,6 +28,7 @@
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shadow.h"
+#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "storage/backendid.h"
@@ -367,7 +368,7 @@ FuncnameGetCandidates(List *names, int nargs)
}
/* Search syscache by name and nargs only */
- catlist = SearchSysCacheList(PROCNAME, 2,
+ catlist = SearchSysCacheList(PROCNAMENSP, 2,
CStringGetDatum(funcname),
Int16GetDatum(nargs),
0, 0);
@@ -565,6 +566,29 @@ makeRangeVarFromNameList(List *names)
}
/*
+ * NameListToString
+ * Utility routine to convert a qualified-name list into a string.
+ * Used primarily to form error messages.
+ */
+char *
+NameListToString(List *names)
+{
+ StringInfoData string;
+ List *l;
+
+ initStringInfo(&string);
+
+ foreach(l, names)
+ {
+ if (l != names)
+ appendStringInfoChar(&string, '.');
+ appendStringInfo(&string, "%s", strVal(lfirst(l)));
+ }
+
+ return string.data;
+}
+
+/*
* isTempNamespace - is the given namespace my temporary-table namespace?
*/
bool
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 1a73f42c334..a9f270fccf8 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.42 2002/03/29 19:06:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.43 2002/04/09 20:35:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,6 +17,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -33,8 +34,8 @@
void
AggregateCreate(const char *aggName,
Oid aggNamespace,
- char *aggtransfnName,
- char *aggfinalfnName,
+ List *aggtransfnName,
+ List *aggfinalfnName,
Oid aggBaseType,
Oid aggTransType,
const char *agginitval)
@@ -79,19 +80,18 @@ AggregateCreate(const char *aggName,
}
else
nargs = 1;
- tup = SearchSysCache(PROCNAME,
- PointerGetDatum(aggtransfnName),
- Int32GetDatum(nargs),
- PointerGetDatum(fnArgs),
- 0);
+ transfn = LookupFuncName(aggtransfnName, nargs, fnArgs);
+ if (!OidIsValid(transfn))
+ func_error("AggregateCreate", aggtransfnName, nargs, fnArgs, NULL);
+ tup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(transfn),
+ 0, 0, 0);
if (!HeapTupleIsValid(tup))
func_error("AggregateCreate", aggtransfnName, nargs, fnArgs, NULL);
- transfn = tup->t_data->t_oid;
- Assert(OidIsValid(transfn));
proc = (Form_pg_proc) GETSTRUCT(tup);
if (proc->prorettype != aggTransType)
elog(ERROR, "return type of transition function %s is not %s",
- aggtransfnName, typeidTypeName(aggTransType));
+ NameListToString(aggtransfnName), typeidTypeName(aggTransType));
/*
* If the transfn is strict and the initval is NULL, make sure input
@@ -111,15 +111,14 @@ AggregateCreate(const char *aggName,
{
fnArgs[0] = aggTransType;
fnArgs[1] = 0;
- tup = SearchSysCache(PROCNAME,
- PointerGetDatum(aggfinalfnName),
- Int32GetDatum(1),
- PointerGetDatum(fnArgs),
- 0);
+ finalfn = LookupFuncName(aggfinalfnName, 1, fnArgs);
+ if (!OidIsValid(finalfn))
+ func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL);
+ tup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(finalfn),
+ 0, 0, 0);
if (!HeapTupleIsValid(tup))
func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL);
- finalfn = tup->t_data->t_oid;
- Assert(OidIsValid(finalfn));
proc = (Form_pg_proc) GETSTRUCT(tup);
finaltype = proc->prorettype;
ReleaseSysCache(tup);
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 8942c266fd6..41023b7edc8 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.64 2002/03/29 19:06:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.65 2002/04/09 20:35:47 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
@@ -27,6 +27,7 @@
#include "parser/parse_func.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -42,13 +43,13 @@ static Oid OperatorShellMake(const char *operatorName,
static void OperatorDef(const char *operatorName,
Oid leftTypeId,
Oid rightTypeId,
- const char *procedureName,
+ List *procedureName,
uint16 precedence,
bool isLeftAssociative,
const char *commutatorName,
const char *negatorName,
- const char *restrictionName,
- const char *joinName,
+ List *restrictionName,
+ List *joinName,
bool canHash,
const char *leftSortName,
const char *rightSortName);
@@ -373,13 +374,13 @@ static void
OperatorDef(const char *operatorName,
Oid leftTypeId,
Oid rightTypeId,
- const char *procedureName,
+ List *procedureName,
uint16 precedence,
bool isLeftAssociative,
const char *commutatorName,
const char *negatorName,
- const char *restrictionName,
- const char *joinName,
+ List *restrictionName,
+ List *joinName,
bool canHash,
const char *leftSortName,
const char *rightSortName)
@@ -398,6 +399,7 @@ OperatorDef(const char *operatorName,
const char *name[4];
Oid typeId[FUNC_MAX_ARGS];
int nargs;
+ Oid procOid;
NameData oname;
TupleDesc tupDesc;
ScanKeyData opKey[3];
@@ -456,19 +458,12 @@ OperatorDef(const char *operatorName,
typeId[1] = rightTypeId;
nargs = 2;
}
- tup = SearchSysCache(PROCNAME,
- PointerGetDatum(procedureName),
- Int32GetDatum(nargs),
- PointerGetDatum(typeId),
- 0);
- if (!HeapTupleIsValid(tup))
+ procOid = LookupFuncName(procedureName, nargs, typeId);
+ if (!OidIsValid(procOid))
func_error("OperatorDef", procedureName, nargs, typeId, NULL);
- values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(tup->t_data->t_oid);
- values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(((Form_pg_proc)
- GETSTRUCT(tup))->prorettype);
-
- ReleaseSysCache(tup);
+ values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(procOid);
+ values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(get_func_rettype(procOid));
/*
* find restriction estimator
@@ -483,11 +478,7 @@ OperatorDef(const char *operatorName,
typeId[2] = 0; /* args list (opaque type) */
typeId[3] = INT4OID; /* varRelid */
- restOid = GetSysCacheOid(PROCNAME,
- PointerGetDatum(restrictionName),
- Int32GetDatum(4),
- PointerGetDatum(typeId),
- 0);
+ restOid = LookupFuncName(restrictionName, 4, typeId);
if (!OidIsValid(restOid))
func_error("OperatorDef", restrictionName, 4, typeId, NULL);
@@ -508,11 +499,7 @@ OperatorDef(const char *operatorName,
typeId[1] = OIDOID; /* operator OID */
typeId[2] = 0; /* args list (opaque type) */
- joinOid = GetSysCacheOid(PROCNAME,
- PointerGetDatum(joinName),
- Int32GetDatum(3),
- PointerGetDatum(typeId),
- 0);
+ joinOid = LookupFuncName(joinName, 3, typeId);
if (!OidIsValid(joinOid))
func_error("OperatorDef", joinName, 3, typeId, NULL);
@@ -950,13 +937,13 @@ OperatorCreate(const char *operatorName,
OperatorDef(operatorName,
leftTypeId,
rightTypeId,
- procedureName,
+ makeList1(makeString((char*) procedureName)), /* XXX */
precedence,
isLeftAssociative,
commutatorName,
negatorName,
- restrictionName,
- joinName,
+ restrictionName ? makeList1(makeString((char*) restrictionName)) : NIL, /* XXX */
+ joinName ? makeList1(makeString((char*) joinName)) : NIL, /* XXX */
canHash,
leftSortName,
rightSortName);
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 02f76e7679a..8cb89b979cb 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.68 2002/04/05 00:31:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.69 2002/04/09 20:35:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -271,11 +271,11 @@ ProcedureCreate(const char *procedureName,
tupDesc = rel->rd_att;
/* Check for pre-existing definition */
- oldtup = SearchSysCache(PROCNAME,
+ oldtup = SearchSysCache(PROCNAMENSP,
PointerGetDatum(procedureName),
UInt16GetDatum(parameterCount),
PointerGetDatum(typev),
- 0);
+ ObjectIdGetDatum(procNamespace));
if (HeapTupleIsValid(oldtup))
{
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index f8e5bc6fc6f..b7d57f6cce5 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.38 2002/03/29 19:06:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.39 2002/04/09 20:35:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/namespace.h"
#include "catalog/pg_database.h"
#include "catalog/pg_description.h"
#include "catalog/pg_namespace.h"
@@ -40,87 +41,74 @@
#include "utils/syscache.h"
-/*------------------------------------------------------------------
+/*
* Static Function Prototypes --
*
* The following protoypes are declared static so as not to conflict
* with any other routines outside this module. These routines are
* called by the public function CommentObject() routine to create
* the appropriate comment for the specific object type.
- *------------------------------------------------------------------
*/
-static void CommentRelation(int objtype, char * schemaname, char *relation,
- char *comment);
-static void CommentAttribute(char * schemaname, char *relation,
- char *attrib, char *comment);
-static void CommentDatabase(char *database, char *comment);
-static void CommentRewrite(char *rule, char *comment);
-static void CommentType(char *type, char *comment);
-static void CommentAggregate(char *aggregate, List *arguments, char *comment);
-static void CommentProc(char *function, List *arguments, char *comment);
-static void CommentOperator(char *opname, List *arguments, char *comment);
-static void CommentTrigger(char *trigger, char *schemaname, char *relation,
- char *comments);
-
-
-/*------------------------------------------------------------------
+static void CommentRelation(int objtype, List *relname, char *comment);
+static void CommentAttribute(List *qualname, char *comment);
+static void CommentDatabase(List *qualname, char *comment);
+static void CommentRule(List *qualname, char *comment);
+static void CommentType(List *typename, char *comment);
+static void CommentAggregate(List *aggregate, List *arguments, char *comment);
+static void CommentProc(List *function, List *arguments, char *comment);
+static void CommentOperator(List *qualname, List *arguments, char *comment);
+static void CommentTrigger(List *qualname, char *comment);
+
+
+/*
* CommentObject --
*
* This routine is used to add the associated comment into
- * pg_description for the object specified by the paramters handed
- * to this routine. If the routine cannot determine an Oid to
- * associated with the parameters handed to this routine, an
- * error is thrown. Otherwise the comment is added to pg_description
- * by calling the CreateComments() routine. If the comment string is
- * empty, CreateComments() will drop any comments associated with
- * the object.
- *------------------------------------------------------------------
-*/
-
+ * pg_description for the object specified by the given SQL command.
+ */
void
-CommentObject(int objtype, char *schemaname, char *objname, char *objproperty,
- List *objlist, char *comment)
+CommentObject(CommentStmt *stmt)
{
- switch (objtype)
+ switch (stmt->objtype)
{
case INDEX:
case SEQUENCE:
case TABLE:
case VIEW:
- CommentRelation(objtype, schemaname, objname, comment);
+ CommentRelation(stmt->objtype, stmt->objname, stmt->comment);
break;
case COLUMN:
- CommentAttribute(schemaname, objname, objproperty, comment);
+ CommentAttribute(stmt->objname, stmt->comment);
break;
case DATABASE:
- CommentDatabase(objname, comment);
+ CommentDatabase(stmt->objname, stmt->comment);
break;
case RULE:
- CommentRewrite(objname, comment);
+ CommentRule(stmt->objname, stmt->comment);
break;
case TYPE_P:
- CommentType(objname, comment);
+ CommentType(stmt->objname, stmt->comment);
break;
case AGGREGATE:
- CommentAggregate(objname, objlist, comment);
+ CommentAggregate(stmt->objname, stmt->objargs, stmt->comment);
break;
case FUNCTION:
- CommentProc(objname, objlist, comment);
+ CommentProc(stmt->objname, stmt->objargs, stmt->comment);
break;
case OPERATOR:
- CommentOperator(objname, objlist, comment);
+ CommentOperator(stmt->objname, stmt->objargs, stmt->comment);
break;
case TRIGGER:
- CommentTrigger(objname, schemaname, objproperty, comment);
+ CommentTrigger(stmt->objname, stmt->comment);
break;
default:
elog(ERROR, "An attempt was made to comment on a unknown type: %d",
- objtype);
+ stmt->objtype);
}
}
-/*------------------------------------------------------------------
+/*
* CreateComments --
*
* Create a comment for the specified object descriptor. Inserts a new
@@ -128,9 +116,7 @@ CommentObject(int objtype, char *schemaname, char *objname, char *objproperty,
*
* If the comment given is null or an empty string, instead delete any
* existing comment for the specified key.
- *------------------------------------------------------------------
*/
-
void
CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
{
@@ -254,15 +240,13 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
heap_close(description, NoLock);
}
-/*------------------------------------------------------------------
+/*
* DeleteComments --
*
* This routine is used to purge all comments associated with an object,
* regardless of their objsubid. It is called, for example, when a relation
* is destroyed.
- *------------------------------------------------------------------
*/
-
void
DeleteComments(Oid oid, Oid classoid)
{
@@ -316,7 +300,7 @@ DeleteComments(Oid oid, Oid classoid)
heap_close(description, NoLock);
}
-/*------------------------------------------------------------------
+/*
* CommentRelation --
*
* This routine is used to add/drop a comment from a relation, where
@@ -324,20 +308,14 @@ DeleteComments(Oid oid, Oid classoid)
* finds the relation name by searching the system cache, locating
* the appropriate tuple, and inserting a comment using that
* tuple's oid. Its parameters are the relation name and comments.
- *------------------------------------------------------------------
*/
-
static void
-CommentRelation(int reltype, char *schemaname, char *relname, char *comment)
+CommentRelation(int objtype, List *relname, char *comment)
{
Relation relation;
- RangeVar *tgtrel = makeNode(RangeVar);
-
-
- tgtrel->relname = relname;
- tgtrel->schemaname = schemaname;
- /* FIXME SCHEMA: Can we add comments to temp relations? */
- tgtrel->istemp = false;
+ RangeVar *tgtrel;
+
+ tgtrel = makeRangeVarFromNameList(relname);
/*
* Open the relation. We do this mainly to acquire a lock that
@@ -349,27 +327,32 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment)
/* Check object security */
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
- elog(ERROR, "you are not permitted to comment on class '%s'", relname);
+ elog(ERROR, "you are not permitted to comment on class '%s'",
+ RelationGetRelationName(relation));
/* Next, verify that the relation type matches the intent */
- switch (reltype)
+ switch (objtype)
{
case INDEX:
if (relation->rd_rel->relkind != RELKIND_INDEX)
- elog(ERROR, "relation '%s' is not an index", relname);
+ elog(ERROR, "relation '%s' is not an index",
+ RelationGetRelationName(relation));
break;
case TABLE:
if (relation->rd_rel->relkind != RELKIND_RELATION)
- elog(ERROR, "relation '%s' is not a table", relname);
+ elog(ERROR, "relation '%s' is not a table",
+ RelationGetRelationName(relation));
break;
case VIEW:
if (relation->rd_rel->relkind != RELKIND_VIEW)
- elog(ERROR, "relation '%s' is not a view", relname);
+ elog(ERROR, "relation '%s' is not a view",
+ RelationGetRelationName(relation));
break;
case SEQUENCE:
if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
- elog(ERROR, "relation '%s' is not a sequence", relname);
+ elog(ERROR, "relation '%s' is not a sequence",
+ RelationGetRelationName(relation));
break;
}
@@ -381,7 +364,7 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment)
relation_close(relation, NoLock);
}
-/*------------------------------------------------------------------
+/*
* CommentAttribute --
*
* This routine is used to add/drop a comment from an attribute
@@ -390,34 +373,40 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment)
* attribute. If successful, a comment is added/dropped, else an
* elog() exception is thrown. The parameters are the relation
* and attribute names, and the comments
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment)
+CommentAttribute(List *qualname, char *comment)
{
- RangeVar *rel = makeNode(RangeVar);
+ int nnames;
+ List *relname;
+ char *attrname;
+ RangeVar *rel;
Relation relation;
AttrNumber attnum;
- /* Open the containing relation to ensure it won't go away meanwhile */
+ /* Separate relname and attr name */
+ nnames = length(qualname);
+ if (nnames < 2)
+ elog(ERROR, "CommentAttribute: must specify relation.attribute");
+ relname = ltruncate(nnames-1, listCopy(qualname));
+ attrname = strVal(nth(nnames-1, qualname));
- rel->relname = relname;
- rel->schemaname = schemaname;
- rel->istemp = false;
+ /* Open the containing relation to ensure it won't go away meanwhile */
+ rel = makeRangeVarFromNameList(relname);
relation = heap_openrv(rel, AccessShareLock);
/* Check object security */
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
- elog(ERROR, "you are not permitted to comment on class '%s'", relname);
+ elog(ERROR, "you are not permitted to comment on class '%s'",
+ RelationGetRelationName(relation));
/* Now, fetch the attribute number from the system cache */
attnum = get_attnum(RelationGetRelid(relation), attrname);
if (attnum == InvalidAttrNumber)
elog(ERROR, "'%s' is not an attribute of class '%s'",
- attrname, relname);
+ attrname, RelationGetRelationName(relation));
/* Create the comment using the relation's oid */
@@ -429,7 +418,7 @@ CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment)
heap_close(relation, NoLock);
}
-/*------------------------------------------------------------------
+/*
* CommentDatabase --
*
* This routine is used to add/drop any user-comments a user might
@@ -437,23 +426,26 @@ CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment)
* security for owner permissions, and, if succesful, will then
* attempt to find the oid of the database specified. Once found,
* a comment is added/dropped using the CreateComments() routine.
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentDatabase(char *database, char *comment)
+CommentDatabase(List *qualname, char *comment)
{
+ char *database;
Relation pg_database;
ScanKeyData entry;
HeapScanDesc scan;
HeapTuple dbtuple;
Oid oid;
+ if (length(qualname) != 1)
+ elog(ERROR, "CommentDatabase: database name may not be qualified");
+ database = strVal(lfirst(qualname));
+
/* First find the tuple in pg_database for the database */
pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname,
- F_NAMEEQ, NameGetDatum(database));
+ F_NAMEEQ, CStringGetDatum(database));
scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
dbtuple = heap_getnext(scan, 0);
@@ -479,25 +471,29 @@ CommentDatabase(char *database, char *comment)
heap_close(pg_database, AccessShareLock);
}
-/*------------------------------------------------------------------
- * CommentRewrite --
+/*
+ * CommentRule --
*
* This routine is used to add/drop any user-comments a user might
* have regarding a specified RULE. The rule is specified by name
* and, if found, and the user has appropriate permissions, a
* comment will be added/dropped using the CreateComments() routine.
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentRewrite(char *rule, char *comment)
+CommentRule(List *qualname, char *comment)
{
+ char *rule;
HeapTuple tuple;
Oid reloid;
Oid ruleoid;
Oid classoid;
int32 aclcheck;
+ /* XXX this is gonna change soon */
+ if (length(qualname) != 1)
+ elog(ERROR, "CommentRule: rule name may not be qualified");
+ rule = strVal(lfirst(qualname));
+
/* Find the rule's pg_rewrite tuple, get its OID and its table's OID */
tuple = SearchSysCache(RULENAME,
@@ -528,7 +524,7 @@ CommentRewrite(char *rule, char *comment)
CreateComments(ruleoid, classoid, 0, comment);
}
-/*------------------------------------------------------------------
+/*
* CommentType --
*
* This routine is used to add/drop any user-comments a user might
@@ -536,42 +532,43 @@ CommentRewrite(char *rule, char *comment)
* and, if found, and the user has appropriate permissions, a
* comment will be added/dropped using the CreateComments() routine.
* The type's name and the comments are the paramters to this routine.
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentType(char *type, char *comment)
+CommentType(List *typename, char *comment)
{
+ TypeName *tname;
Oid oid;
+ /* XXX a bit of a crock; should accept TypeName in COMMENT syntax */
+ tname = makeNode(TypeName);
+ tname->names = typename;
+ tname->typmod = -1;
+
/* Find the type's oid */
- /* XXX WRONG: need to deal with qualified type names */
- oid = typenameTypeId(makeTypeName(type));
+ oid = typenameTypeId(tname);
/* Check object security */
if (!pg_type_ownercheck(oid, GetUserId()))
- elog(ERROR, "you are not permitted to comment on type '%s'",
- type);
+ elog(ERROR, "you are not permitted to comment on type %s",
+ TypeNameToString(tname));
/* Call CreateComments() to create/drop the comments */
CreateComments(oid, RelOid_pg_type, 0, comment);
}
-/*------------------------------------------------------------------
+/*
* CommentAggregate --
*
* This routine is used to allow a user to provide comments on an
* aggregate function. The aggregate function is determined by both
* its name and its argument type, which, with the comments are
* the three parameters handed to this routine.
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentAggregate(char *aggregate, List *arguments, char *comment)
+CommentAggregate(List *aggregate, List *arguments, char *comment)
{
TypeName *aggtype = (TypeName *) lfirst(arguments);
Oid baseoid,
@@ -587,7 +584,7 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
/* Now, attempt to find the actual tuple in pg_aggregate */
oid = GetSysCacheOid(AGGNAME,
- PointerGetDatum(aggregate),
+ PointerGetDatum(strVal(lfirst(aggregate))), /* XXX */
ObjectIdGetDatum(baseoid),
0, 0);
if (!OidIsValid(oid))
@@ -598,11 +595,11 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
if (!pg_aggr_ownercheck(oid, GetUserId()))
{
if (baseoid == InvalidOid)
- elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types",
- aggregate);
+ elog(ERROR, "you are not permitted to comment on aggregate %s for all types",
+ NameListToString(aggregate));
else
- elog(ERROR, "you are not permitted to comment on aggregate '%s' for type %s",
- aggregate, format_type_be(baseoid));
+ elog(ERROR, "you are not permitted to comment on aggregate %s for type %s",
+ NameListToString(aggregate), format_type_be(baseoid));
}
/* pg_aggregate doesn't have a hard-coded OID, so must look it up */
@@ -615,7 +612,7 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
CreateComments(oid, classoid, 0, comment);
}
-/*------------------------------------------------------------------
+/*
* CommentProc --
*
* This routine is used to allow a user to provide comments on an
@@ -623,64 +620,29 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
* its name and its argument list. The argument list is expected to
* be a series of parsed nodes pointed to by a List object. If the
* comments string is empty, the associated comment is dropped.
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentProc(char *function, List *arguments, char *comment)
+CommentProc(List *function, List *arguments, char *comment)
{
- Oid oid,
- argoids[FUNC_MAX_ARGS];
- int i,
- argcount;
-
- /* First, initialize function's argument list with their type oids */
-
- MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
- argcount = length(arguments);
- if (argcount > FUNC_MAX_ARGS)
- elog(ERROR, "functions cannot have more than %d arguments",
- FUNC_MAX_ARGS);
- for (i = 0; i < argcount; i++)
- {
- TypeName *t = (TypeName *) lfirst(arguments);
-
- argoids[i] = LookupTypeName(t);
- if (!OidIsValid(argoids[i]))
- {
- char *typnam = TypeNameToString(t);
-
- if (strcmp(typnam, "opaque") == 0)
- argoids[i] = InvalidOid;
- else
- elog(ERROR, "Type \"%s\" does not exist", typnam);
- }
+ Oid oid;
- arguments = lnext(arguments);
- }
+ /* Look up the procedure */
- /* Now, find the corresponding oid for this procedure */
-
- oid = GetSysCacheOid(PROCNAME,
- PointerGetDatum(function),
- Int32GetDatum(argcount),
- PointerGetDatum(argoids),
- 0);
- if (!OidIsValid(oid))
- func_error("CommentProc", function, argcount, argoids, NULL);
+ oid = LookupFuncNameTypeNames(function, arguments,
+ true, "CommentProc");
/* Now, validate the user's ability to comment on this function */
if (!pg_proc_ownercheck(oid, GetUserId()))
- elog(ERROR, "you are not permitted to comment on function '%s'",
- function);
+ elog(ERROR, "you are not permitted to comment on function %s",
+ NameListToString(function));
/* Call CreateComments() to create/drop the comments */
CreateComments(oid, RelOid_pg_proc, 0, comment);
}
-/*------------------------------------------------------------------
+/*
* CommentOperator --
*
* This routine is used to allow a user to provide comments on an
@@ -694,12 +656,11 @@ CommentProc(char *function, List *arguments, char *comment)
* NOTE: we actually attach the comment to the procedure that underlies
* the operator. This is a feature, not a bug: we want the same comment
* to be visible for both operator and function.
- *------------------------------------------------------------------
-*/
-
+ */
static void
-CommentOperator(char *opername, List *arguments, char *comment)
+CommentOperator(List *qualname, List *arguments, char *comment)
{
+ char *opername = strVal(lfirst(qualname)); /* XXX */
TypeName *typenode1 = (TypeName *) lfirst(arguments);
TypeName *typenode2 = (TypeName *) lsecond(arguments);
char oprtype = 0;
@@ -760,21 +721,22 @@ CommentOperator(char *opername, List *arguments, char *comment)
CreateComments(oid, RelOid_pg_proc, 0, comment);
}
-/*------------------------------------------------------------------
+/*
* CommentTrigger --
*
* This routine is used to allow a user to provide comments on a
* trigger event. The trigger for commenting is determined by both
* its name and the relation to which it refers. The arguments to this
- * function are the trigger name, the relation name, and the comments
- * to add/drop.
- *------------------------------------------------------------------
-*/
-
+ * function are the trigger name and relation name (merged into a qualified
+ * name), and the comment to add/drop.
+ */
static void
-CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment)
+CommentTrigger(List *qualname, char *comment)
{
- RangeVar *rel = makeNode(RangeVar);
+ int nnames;
+ List *relname;
+ char *trigname;
+ RangeVar *rel;
Relation pg_trigger,
relation;
HeapTuple triggertuple;
@@ -782,16 +744,22 @@ CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment)
ScanKeyData entry[2];
Oid oid;
- /* First, validate the user's action */
+ /* Separate relname and trig name */
+ nnames = length(qualname);
+ if (nnames < 2)
+ elog(ERROR, "CommentTrigger: must specify relation and trigger");
+ relname = ltruncate(nnames-1, listCopy(qualname));
+ trigname = strVal(nth(nnames-1, qualname));
- rel->relname = relname;
- rel->schemaname = schemaname;
- rel->istemp = false;
+ /* Open the owning relation to ensure it won't go away meanwhile */
+ rel = makeRangeVarFromNameList(relname);
relation = heap_openrv(rel, AccessShareLock);
+ /* Check object security */
+
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
- elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'",
- trigger, "defined for relation", relname);
+ elog(ERROR, "you are not permitted to comment on trigger '%s' for relation '%s'",
+ trigname, RelationGetRelationName(relation));
/* Fetch the trigger oid from pg_trigger */
@@ -801,15 +769,15 @@ CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment)
ObjectIdGetDatum(RelationGetRelid(relation)));
ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname,
F_NAMEEQ,
- NameGetDatum(trigger));
+ CStringGetDatum(trigname));
scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 2, entry);
triggertuple = heap_getnext(scan, 0);
/* If no trigger exists for the relation specified, notify user */
if (!HeapTupleIsValid(triggertuple))
- elog(ERROR, "trigger '%s' defined for relation '%s' does not exist",
- trigger, relname);
+ elog(ERROR, "trigger '%s' for relation '%s' does not exist",
+ trigname, RelationGetRelationName(relation));
oid = triggertuple->t_data->t_oid;
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index eaff4e66dfa..cccbcdfaa59 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.73 2002/04/05 00:31:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.74 2002/04/09 20:35:47 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -60,9 +60,10 @@
#include "utils/syscache.h"
-static Oid findTypeIOFunction(const char *procname, bool isOutput);
+static Oid findTypeIOFunction(List *procname, bool isOutput);
static char *defGetString(DefElem *def);
static double defGetNumeric(DefElem *def);
+static List *defGetQualifiedName(DefElem *def);
static TypeName *defGetTypeName(DefElem *def);
static int defGetTypeLength(DefElem *def);
@@ -474,8 +475,8 @@ DefineAggregate(List *names, List *parameters)
{
char *aggName;
Oid aggNamespace;
- char *transfuncName = NULL;
- char *finalfuncName = NULL;
+ List *transfuncName = NIL;
+ List *finalfuncName = NIL;
TypeName *baseType = NULL;
TypeName *transType = NULL;
char *initval = NULL;
@@ -495,11 +496,11 @@ DefineAggregate(List *names, List *parameters)
* spellings for sfunc, stype, initcond.
*/
if (strcasecmp(defel->defname, "sfunc") == 0)
- transfuncName = defGetString(defel);
+ transfuncName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "sfunc1") == 0)
- transfuncName = defGetString(defel);
+ transfuncName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "finalfunc") == 0)
- finalfuncName = defGetString(defel);
+ finalfuncName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "basetype") == 0)
baseType = defGetTypeName(defel);
else if (strcasecmp(defel->defname, "stype") == 0)
@@ -522,7 +523,7 @@ DefineAggregate(List *names, List *parameters)
elog(ERROR, "Define: \"basetype\" unspecified");
if (transType == NULL)
elog(ERROR, "Define: \"stype\" unspecified");
- if (transfuncName == NULL)
+ if (transfuncName == NIL)
elog(ERROR, "Define: \"sfunc\" unspecified");
/*
@@ -800,10 +801,10 @@ DefineType(List *names, List *parameters)
int16 internalLength = -1; /* int2 */
int16 externalLength = -1; /* int2 */
Oid elemType = InvalidOid;
- char *inputName = NULL;
- char *outputName = NULL;
- char *sendName = NULL;
- char *receiveName = NULL;
+ List *inputName = NIL;
+ List *outputName = NIL;
+ List *sendName = NIL;
+ List *receiveName = NIL;
char *defaultValue = NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
@@ -838,13 +839,13 @@ DefineType(List *names, List *parameters)
else if (strcasecmp(defel->defname, "externallength") == 0)
externalLength = defGetTypeLength(defel);
else if (strcasecmp(defel->defname, "input") == 0)
- inputName = defGetString(defel);
+ inputName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "output") == 0)
- outputName = defGetString(defel);
+ outputName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "send") == 0)
- sendName = defGetString(defel);
+ sendName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "receive") == 0)
- receiveName = defGetString(defel);
+ receiveName = defGetQualifiedName(defel);
else if (strcasecmp(defel->defname, "delimiter") == 0)
{
char *p = defGetString(defel);
@@ -909,9 +910,9 @@ DefineType(List *names, List *parameters)
/*
* make sure we have our required definitions
*/
- if (inputName == NULL)
+ if (inputName == NIL)
elog(ERROR, "Define: \"input\" unspecified");
- if (outputName == NULL)
+ if (outputName == NIL)
elog(ERROR, "Define: \"output\" unspecified");
/* Convert I/O proc names to OIDs */
@@ -989,7 +990,7 @@ DefineType(List *names, List *parameters)
}
static Oid
-findTypeIOFunction(const char *procname, bool isOutput)
+findTypeIOFunction(List *procname, bool isOutput)
{
Oid argList[FUNC_MAX_ARGS];
int nargs;
@@ -1001,11 +1002,7 @@ findTypeIOFunction(const char *procname, bool isOutput)
*/
MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
- procOid = GetSysCacheOid(PROCNAME,
- PointerGetDatum(procname),
- Int32GetDatum(1),
- PointerGetDatum(argList),
- 0);
+ procOid = LookupFuncName(procname, 1, argList);
if (!OidIsValid(procOid))
{
@@ -1028,11 +1025,7 @@ findTypeIOFunction(const char *procname, bool isOutput)
argList[1] = OIDOID;
argList[2] = INT4OID;
}
- procOid = GetSysCacheOid(PROCNAME,
- PointerGetDatum(procname),
- Int32GetDatum(nargs),
- PointerGetDatum(argList),
- 0);
+ procOid = LookupFuncName(procname, nargs, argList);
if (!OidIsValid(procOid))
func_error("TypeCreate", procname, 1, argList, NULL);
@@ -1094,6 +1087,26 @@ defGetNumeric(DefElem *def)
return 0; /* keep compiler quiet */
}
+static List *
+defGetQualifiedName(DefElem *def)
+{
+ if (def->arg == NULL)
+ elog(ERROR, "Define: \"%s\" requires a parameter",
+ def->defname);
+ switch (nodeTag(def->arg))
+ {
+ case T_TypeName:
+ return ((TypeName *) def->arg)->names;
+ case T_String:
+ /* Allow quoted name for backwards compatibility */
+ return makeList1(def->arg);
+ default:
+ elog(ERROR, "Define: argument of \"%s\" must be a name",
+ def->defname);
+ }
+ return NIL; /* keep compiler quiet */
+}
+
static TypeName *
defGetTypeName(DefElem *def)
{
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index b5067f99278..43539cd625a 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.67 2002/04/05 00:31:26 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.68 2002/04/09 20:35:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,7 +36,7 @@
#include "utils/syscache.h"
-#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL)
+#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->funcname != NIL)
/* non-export function prototypes */
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
@@ -297,7 +297,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
* that. So, check to make sure that the selected function has
* exact-match or binary-compatible input types.
*/
- fdresult = func_get_detail(funcIndex->name, funcIndex->args,
+ fdresult = func_get_detail(funcIndex->funcname, funcIndex->args,
nargs, argTypes,
&funcid, &rettype, &retset,
&true_typeids);
@@ -307,7 +307,8 @@ FuncIndexArgs(IndexInfo *indexInfo,
elog(ERROR, "DefineIndex: functional index must use a real function, not a type coercion"
"\n\tTry specifying the index opclass you want to use, instead");
else
- func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL);
+ func_error("DefineIndex", funcIndex->funcname, nargs, argTypes,
+ NULL);
}
if (retset)
@@ -316,7 +317,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
for (i = 0; i < nargs; i++)
{
if (!IsBinaryCompatible(argTypes[i], true_typeids[i]))
- func_error("DefineIndex", funcIndex->name, nargs, argTypes,
+ func_error("DefineIndex", funcIndex->funcname, nargs, argTypes,
"Index function must be binary-compatible with table datatype");
}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index d9cf0f0814a..4ef8d8f72a0 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.29 2002/02/18 23:11:11 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.30 2002/04/09 20:35:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,12 +18,15 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/namespace.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "commands/proclang.h"
#include "fmgr.h"
#include "miscadmin.h"
+#include "parser/parse_func.h"
#include "utils/builtins.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -50,15 +53,13 @@ void
CreateProceduralLanguage(CreatePLangStmt *stmt)
{
char languageName[NAMEDATALEN];
- HeapTuple procTup;
-
+ Oid procOid;
Oid typev[FUNC_MAX_ARGS];
char nulls[Natts_pg_language];
Datum values[Natts_pg_language];
Relation rel;
HeapTuple tup;
TupleDesc tupDesc;
-
int i;
/*
@@ -83,18 +84,14 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
* Lookup the PL handler function and check that it is of return type
* Opaque
*/
- memset(typev, 0, sizeof(typev));
- procTup = SearchSysCache(PROCNAME,
- PointerGetDatum(stmt->plhandler),
- Int32GetDatum(0),
- PointerGetDatum(typev),
- 0);
- if (!HeapTupleIsValid(procTup))
+ MemSet(typev, 0, sizeof(typev));
+ procOid = LookupFuncName(stmt->plhandler, 0, typev);
+ if (!OidIsValid(procOid))
elog(ERROR, "PL handler function %s() doesn't exist",
- stmt->plhandler);
- if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid)
+ NameListToString(stmt->plhandler));
+ if (get_func_rettype(procOid) != InvalidOid)
elog(ERROR, "PL handler function %s() isn't of return type Opaque",
- stmt->plhandler);
+ NameListToString(stmt->plhandler));
/*
* Insert the new language into pg_language
@@ -109,13 +106,11 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
values[i++] = PointerGetDatum(languageName);
values[i++] = BoolGetDatum(true); /* lanispl */
values[i++] = BoolGetDatum(stmt->pltrusted);
- values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
+ values[i++] = ObjectIdGetDatum(procOid);
values[i++] = DirectFunctionCall1(textin,
CStringGetDatum(stmt->plcompiler));
nulls[i] = 'n'; /* lanacl */
- ReleaseSysCache(procTup);
-
rel = heap_openr(LanguageRelationName, RowExclusiveLock);
tupDesc = rel->rd_att;
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index fb73fe3bd02..8969b9cdc13 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.72 2002/03/29 19:06:06 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.73 2002/04/09 20:35:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,6 +16,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
+#include "catalog/namespace.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -357,60 +358,38 @@ RemoveDomain(List *names, int behavior)
* ...
*/
void
-RemoveFunction(char *functionName, /* function name to be removed */
+RemoveFunction(List *functionName, /* function name to be removed */
List *argTypes) /* list of TypeName nodes */
{
- int nargs = length(argTypes);
+ Oid funcOid;
Relation relation;
HeapTuple tup;
- Oid argList[FUNC_MAX_ARGS];
- int i;
-
- if (nargs > FUNC_MAX_ARGS)
- elog(ERROR, "functions cannot have more than %d arguments",
- FUNC_MAX_ARGS);
- MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
- for (i = 0; i < nargs; i++)
- {
- TypeName *t = (TypeName *) lfirst(argTypes);
-
- argList[i] = LookupTypeName(t);
- if (!OidIsValid(argList[i]))
- {
- char *typnam = TypeNameToString(t);
-
- if (strcmp(typnam, "opaque") == 0)
- argList[i] = InvalidOid;
- else
- elog(ERROR, "Type \"%s\" does not exist", typnam);
- }
- argTypes = lnext(argTypes);
- }
+ funcOid = LookupFuncNameTypeNames(functionName, argTypes,
+ true, "RemoveFunction");
relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
- tup = SearchSysCache(PROCNAME,
- PointerGetDatum(functionName),
- Int32GetDatum(nargs),
- PointerGetDatum(argList),
- 0);
-
- if (!HeapTupleIsValid(tup))
- func_error("RemoveFunction", functionName, nargs, argList, NULL);
+ tup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "RemoveFunction: couldn't find tuple for function %s",
+ NameListToString(functionName));
- if (!pg_proc_ownercheck(tup->t_data->t_oid, GetUserId()))
+ if (!pg_proc_ownercheck(funcOid, GetUserId()))
elog(ERROR, "RemoveFunction: function '%s': permission denied",
- functionName);
+ NameListToString(functionName));
if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
{
/* "Helpful" WARNING when removing a builtin function ... */
- elog(WARNING, "Removing built-in function \"%s\"", functionName);
+ elog(WARNING, "Removing built-in function \"%s\"",
+ NameListToString(functionName));
}
/* Delete any comments associated with this function */
- DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
+ DeleteComments(funcOid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self);
@@ -420,7 +399,7 @@ RemoveFunction(char *functionName, /* function name to be removed */
}
void
-RemoveAggregate(char *aggName, TypeName *aggType)
+RemoveAggregate(List *aggName, TypeName *aggType)
{
Relation relation;
HeapTuple tup;
@@ -443,7 +422,7 @@ RemoveAggregate(char *aggName, TypeName *aggType)
relation = heap_openr(AggregateRelationName, RowExclusiveLock);
tup = SearchSysCache(AGGNAME,
- PointerGetDatum(aggName),
+ PointerGetDatum(strVal(llast(aggName))),
ObjectIdGetDatum(basetypeID),
0, 0);
@@ -453,11 +432,11 @@ RemoveAggregate(char *aggName, TypeName *aggType)
if (!pg_aggr_ownercheck(tup->t_data->t_oid, GetUserId()))
{
if (basetypeID == InvalidOid)
- elog(ERROR, "RemoveAggregate: aggregate '%s' for all types: permission denied",
- aggName);
+ elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied",
+ NameListToString(aggName));
else
- elog(ERROR, "RemoveAggregate: aggregate '%s' for type %s: permission denied",
- aggName, format_type_be(basetypeID));
+ elog(ERROR, "RemoveAggregate: aggregate %s for type %s: permission denied",
+ NameListToString(aggName), format_type_be(basetypeID));
}
/* Remove any comments related to this aggregate */
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index c05b2ec51a3..72f13d3db49 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.111 2002/04/01 22:36:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.112 2002/04/09 20:35:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,6 +26,7 @@
#include "commands/trigger.h"
#include "executor/executor.h"
#include "miscadmin.h"
+#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
@@ -163,18 +164,19 @@ CreateTrigger(CreateTrigStmt *stmt)
* Find and validate the trigger function.
*/
MemSet(fargtypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
- tuple = SearchSysCache(PROCNAME,
- PointerGetDatum(stmt->funcname),
- Int32GetDatum(0),
- PointerGetDatum(fargtypes),
- 0);
+ funcoid = LookupFuncName(stmt->funcname, 0, fargtypes);
+ if (!OidIsValid(funcoid))
+ elog(ERROR, "CreateTrigger: function %s() does not exist",
+ NameListToString(stmt->funcname));
+ tuple = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcoid),
+ 0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "CreateTrigger: function %s() does not exist",
- stmt->funcname);
+ NameListToString(stmt->funcname));
if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype != 0)
elog(ERROR, "CreateTrigger: function %s() must return OPAQUE",
- stmt->funcname);
- funcoid = tuple->t_data->t_oid;
+ NameListToString(stmt->funcname));
funclang = ((Form_pg_proc) GETSTRUCT(tuple))->prolang;
ReleaseSysCache(tuple);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index b633b02b79d..873658774ca 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.175 2002/04/05 11:56:48 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.176 2002/04/09 20:35:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1587,8 +1587,7 @@ _copyFuncCall(FuncCall *from)
{
FuncCall *newnode = makeNode(FuncCall);
- if (from->funcname)
- newnode->funcname = pstrdup(from->funcname);
+ Node_Copy(from, newnode, funcname);
Node_Copy(from, newnode, args);
newnode->agg_star = from->agg_star;
newnode->agg_distinct = from->agg_distinct;
@@ -1719,6 +1718,7 @@ _copyIndexElem(IndexElem *from)
if (from->name)
newnode->name = pstrdup(from->name);
+ Node_Copy(from, newnode, funcname);
Node_Copy(from, newnode, args);
if (from->class)
newnode->class = pstrdup(from->class);
@@ -1940,8 +1940,7 @@ _copyFuncWithArgs(FuncWithArgs *from)
{
FuncWithArgs *newnode = makeNode(FuncWithArgs);
- if (from->funcname)
- newnode->funcname = pstrdup(from->funcname);
+ Node_Copy(from, newnode, funcname);
Node_Copy(from, newnode, funcargs);
return newnode;
@@ -2052,13 +2051,10 @@ _copyCommentStmt(CommentStmt *from)
CommentStmt *newnode = makeNode(CommentStmt);
newnode->objtype = from->objtype;
- if (from->objschema)
- newnode->objschema = pstrdup(from->objschema);
- newnode->objname = pstrdup(from->objname);
- if (from->objproperty)
- newnode->objproperty = pstrdup(from->objproperty);
- Node_Copy(from, newnode, objlist);
- newnode->comment = pstrdup(from->comment);
+ Node_Copy(from, newnode, objname);
+ Node_Copy(from, newnode, objargs);
+ if (from->comment)
+ newnode->comment = pstrdup(from->comment);
return newnode;
}
@@ -2114,7 +2110,7 @@ _copyRemoveAggrStmt(RemoveAggrStmt *from)
{
RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt);
- newnode->aggname = pstrdup(from->aggname);
+ Node_Copy(from, newnode, aggname);
Node_Copy(from, newnode, aggtype);
return newnode;
@@ -2125,7 +2121,7 @@ _copyRemoveFuncStmt(RemoveFuncStmt *from)
{
RemoveFuncStmt *newnode = makeNode(RemoveFuncStmt);
- newnode->funcname = pstrdup(from->funcname);
+ Node_Copy(from, newnode, funcname);
Node_Copy(from, newnode, args);
return newnode;
@@ -2370,8 +2366,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
if (from->trigname)
newnode->trigname = pstrdup(from->trigname);
Node_Copy(from, newnode, relation);
- if (from->funcname)
- newnode->funcname = pstrdup(from->funcname);
+ Node_Copy(from, newnode, funcname);
Node_Copy(from, newnode, args);
newnode->before = from->before;
newnode->row = from->row;
@@ -2411,8 +2406,7 @@ _copyCreatePLangStmt(CreatePLangStmt *from)
if (from->plname)
newnode->plname = pstrdup(from->plname);
- if (from->plhandler)
- newnode->plhandler = pstrdup(from->plhandler);
+ Node_Copy(from, newnode, plhandler);
if (from->plcompiler)
newnode->plcompiler = pstrdup(from->plcompiler);
newnode->pltrusted = from->pltrusted;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index eceb8cb36f7..9458ebc5b95 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.123 2002/04/05 11:56:50 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.124 2002/04/09 20:35:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -769,7 +769,7 @@ _equalPrivGrantee(PrivGrantee *a, PrivGrantee *b)
static bool
_equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b)
{
- return equalstr(a->funcname, b->funcname)
+ return equal(a->funcname, b->funcname)
&& equal(a->funcargs, b->funcargs);
}
@@ -877,13 +877,9 @@ _equalCommentStmt(CommentStmt *a, CommentStmt *b)
{
if (a->objtype != b->objtype)
return false;
- if (!equalstr(a->objname, b->objname))
+ if (!equal(a->objname, b->objname))
return false;
- if (!equalstr(a->objschema, b->objschema))
- return false;
- if (!equalstr(a->objproperty, b->objproperty))
- return false;
- if (!equal(a->objlist, b->objlist))
+ if (!equal(a->objargs, b->objargs))
return false;
if (!equalstr(a->comment, b->comment))
return false;
@@ -953,7 +949,7 @@ _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
static bool
_equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
{
- if (!equalstr(a->aggname, b->aggname))
+ if (!equal(a->aggname, b->aggname))
return false;
if (!equal(a->aggtype, b->aggtype))
return false;
@@ -964,7 +960,7 @@ _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
static bool
_equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
{
- if (!equalstr(a->funcname, b->funcname))
+ if (!equal(a->funcname, b->funcname))
return false;
if (!equal(a->args, b->args))
return false;
@@ -1207,7 +1203,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
return false;
if (!equal(a->relation, b->relation))
return false;
- if (!equalstr(a->funcname, b->funcname))
+ if (!equal(a->funcname, b->funcname))
return false;
if (!equal(a->args, b->args))
return false;
@@ -1253,7 +1249,7 @@ _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
{
if (!equalstr(a->plname, b->plname))
return false;
- if (!equalstr(a->plhandler, b->plhandler))
+ if (!equal(a->plhandler, b->plhandler))
return false;
if (!equalstr(a->plcompiler, b->plcompiler))
return false;
@@ -1463,7 +1459,7 @@ _equalIdent(Ident *a, Ident *b)
static bool
_equalFuncCall(FuncCall *a, FuncCall *b)
{
- if (!equalstr(a->funcname, b->funcname))
+ if (!equal(a->funcname, b->funcname))
return false;
if (!equal(a->args, b->args))
return false;
@@ -1601,6 +1597,8 @@ _equalIndexElem(IndexElem *a, IndexElem *b)
{
if (!equalstr(a->name, b->name))
return false;
+ if (!equal(a->funcname, b->funcname))
+ return false;
if (!equal(a->args, b->args))
return false;
if (!equalstr(a->class, b->class))
diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
index 9b588150fda..a61991f38fa 100644
--- a/src/backend/nodes/list.c
+++ b/src/backend/nodes/list.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.39 2001/03/22 03:59:32 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.40 2002/04/09 20:35:50 tgl Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
@@ -234,6 +234,36 @@ length(List *l)
}
/*
+ * llast
+ *
+ * Get the last element of l ... error if empty list
+ */
+void *
+llast(List *l)
+{
+ if (l == NIL)
+ elog(ERROR, "llast: empty list");
+ while (lnext(l) != NIL)
+ l = lnext(l);
+ return lfirst(l);
+}
+
+/*
+ * llasti
+ *
+ * As above, but for integer lists
+ */
+int
+llasti(List *l)
+{
+ if (l == NIL)
+ elog(ERROR, "llasti: empty list");
+ while (lnext(l) != NIL)
+ l = lnext(l);
+ return lfirsti(l);
+}
+
+/*
* freeList
*
* Free the List nodes of a list
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 20d25c64397..a495f5ed10b 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.152 2002/03/29 19:06:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.153 2002/04/09 20:35:50 tgl Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -160,7 +160,7 @@ static void
_outFuncCall(StringInfo str, FuncCall *node)
{
appendStringInfo(str, "FUNCTION ");
- _outToken(str, node->funcname);
+ _outNode(str, node->funcname);
appendStringInfo(str, " :args ");
_outNode(str, node->args);
appendStringInfo(str, " :agg_star %s :agg_distinct %s ",
@@ -213,6 +213,8 @@ _outIndexElem(StringInfo str, IndexElem *node)
{
appendStringInfo(str, " INDEXELEM :name ");
_outToken(str, node->name);
+ appendStringInfo(str, " :funcname ");
+ _outNode(str, node->funcname);
appendStringInfo(str, " :args ");
_outNode(str, node->args);
appendStringInfo(str, " :class ");
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 0de9c5bb851..8b3f218b83a 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.227 2002/04/05 11:56:51 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.228 2002/04/09 20:35:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,7 @@
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "parser/analyze.h"
+#include "parser/gramparse.h"
#include "parser/parsetree.h"
#include "parser/parse_agg.h"
#include "parser/parse_clause.h"
@@ -859,7 +860,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
snamenode->val.type = T_String;
snamenode->val.val.str = qstring;
funccallnode = makeNode(FuncCall);
- funccallnode->funcname = "nextval";
+ funccallnode->funcname = SystemFuncName("nextval");
funccallnode->args = makeList1(snamenode);
funccallnode->agg_star = false;
funccallnode->agg_distinct = false;
@@ -1197,7 +1198,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
foreach(columns, index->indexParams)
{
iparam = (IndexElem *) lfirst(columns);
- if (strcmp(key->name, iparam->name) == 0)
+ if (iparam->name && strcmp(key->name, iparam->name) == 0)
elog(ERROR, "%s: column \"%s\" appears twice in %s constraint",
cxt->stmtType, key->name,
index->primary ? "PRIMARY KEY" : "UNIQUE");
@@ -1206,6 +1207,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
/* OK, add it to the index definition */
iparam = makeNode(IndexElem);
iparam->name = pstrdup(key->name);
+ iparam->funcname = NIL;
iparam->args = NIL;
iparam->class = NULL;
index->indexParams = lappend(index->indexParams, iparam);
@@ -1281,7 +1283,9 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
if (index->idxname == NULL && index->indexParams != NIL)
{
iparam = lfirst(index->indexParams);
- index->idxname = CreateIndexName((cxt->relation)->relname, iparam->name,
+ index->idxname = CreateIndexName(cxt->relation->relname,
+ iparam->name ? iparam->name :
+ strVal(llast(iparam->funcname)),
"key", cxt->alist);
}
if (index->idxname == NULL) /* should not happen */
@@ -1292,7 +1296,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
cxt->stmtType,
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
(index->primary ? "PRIMARY KEY" : "UNIQUE"),
- index->idxname, (cxt->relation)->relname);
+ index->idxname, cxt->relation->relname);
}
}
@@ -1365,6 +1369,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
IndexElem *ielem = lfirst(attr);
Ident *pkattr = (Ident *) makeNode(Ident);
+ Assert(ielem->name); /* no func index here */
pkattr->name = pstrdup(ielem->name);
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
pkattr);
@@ -1417,7 +1422,8 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
{
IndexElem *indparm = lfirst(indparms);
- if (strcmp(indparm->name, pkattr->name) == 0)
+ if (indparm->name &&
+ strcmp(indparm->name, pkattr->name) == 0)
{
found = true;
break;
@@ -1470,7 +1476,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relation = cxt->relation;
- fk_trigger->funcname = "RI_FKey_check_ins";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
fk_trigger->before = false;
fk_trigger->row = true;
fk_trigger->actions[0] = 'i';
@@ -1542,21 +1548,21 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
>> FKCONSTR_ON_DELETE_SHIFT)
{
case FKCONSTR_ON_KEY_NOACTION:
- fk_trigger->funcname = "RI_FKey_noaction_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
break;
case FKCONSTR_ON_KEY_RESTRICT:
fk_trigger->deferrable = false;
fk_trigger->initdeferred = false;
- fk_trigger->funcname = "RI_FKey_restrict_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
break;
case FKCONSTR_ON_KEY_CASCADE:
- fk_trigger->funcname = "RI_FKey_cascade_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
break;
case FKCONSTR_ON_KEY_SETNULL:
- fk_trigger->funcname = "RI_FKey_setnull_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
break;
case FKCONSTR_ON_KEY_SETDEFAULT:
- fk_trigger->funcname = "RI_FKey_setdefault_del";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
break;
default:
elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
@@ -1614,21 +1620,21 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
>> FKCONSTR_ON_UPDATE_SHIFT)
{
case FKCONSTR_ON_KEY_NOACTION:
- fk_trigger->funcname = "RI_FKey_noaction_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
break;
case FKCONSTR_ON_KEY_RESTRICT:
fk_trigger->deferrable = false;
fk_trigger->initdeferred = false;
- fk_trigger->funcname = "RI_FKey_restrict_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
break;
case FKCONSTR_ON_KEY_CASCADE:
- fk_trigger->funcname = "RI_FKey_cascade_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
break;
case FKCONSTR_ON_KEY_SETNULL:
- fk_trigger->funcname = "RI_FKey_setnull_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
break;
case FKCONSTR_ON_KEY_SETDEFAULT:
- fk_trigger->funcname = "RI_FKey_setdefault_upd";
+ fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
break;
default:
elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 6ba8766e1ac..3488fb0762f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.300 2002/04/05 11:56:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.301 2002/04/09 20:35:51 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -175,8 +175,9 @@ static bool set_name_needs_quotes(const char *name);
%type <str> relation_name, copy_file_name, copy_delimiter, copy_null,
database_name, access_method_clause, access_method, attr_name,
- class, index_name, name, function_name, file_name,
- func_name, handler_name
+ class, index_name, name, function_name, file_name
+
+%type <list> func_name, handler_name
%type <range> qualified_name, OptConstrFromTable
@@ -1859,9 +1860,9 @@ opt_trusted: TRUSTED { $$ = TRUE; }
* Work around by using name and dotted_name separately.
*/
handler_name: name
- { $$ = $1; }
+ { $$ = makeList1(makeString($1)); }
| dotted_name
- { $$ = strVal(lfirst($1)); /* XXX changing soon */ }
+ { $$ = $1; }
;
opt_lancompiler: LANCOMPILER Sconst { $$ = $2; }
@@ -2081,7 +2082,7 @@ DefineStmt: CREATE AGGREGATE func_name definition
{
DefineStmt *n = makeNode(DefineStmt);
n->defType = AGGREGATE;
- n->defnames = makeList1(makeString($3)); /* XXX */
+ n->defnames = $3;
n->definition = $4;
$$ = (Node *)n;
}
@@ -2199,54 +2200,21 @@ TruncateStmt: TRUNCATE opt_table qualified_name
*
*****************************************************************************/
-CommentStmt: COMMENT ON comment_type name IS comment_text
+CommentStmt: COMMENT ON comment_type any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = $3;
n->objname = $4;
- n->objproperty = NULL;
- n->objlist = NULL;
+ n->objargs = NIL;
n->comment = $6;
$$ = (Node *) n;
}
- | COMMENT ON COLUMN ColId '.' attr_name IS comment_text
- {
- /*
- * We can't use qualified_name here as the '.' causes a shift/red;
- * with ColId we do not test for NEW and OLD as table names, but it is OK
- * as they would fail anyway as COMMENT cannot appear in a RULE.
- * ColumnRef is also innapropriate as we don't take subscripts
- * or '*' and have a very precise number of elements (2 or 3)
- * so we do it from scratch.
- */
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COLUMN;
- n->objschema = NULL;
- n->objname = $4;
- n->objproperty = $6;
- n->objlist = NULL;
- n->comment = $8;
- $$ = (Node *) n;
- }
- | COMMENT ON COLUMN ColId '.' ColId '.' attr_name IS comment_text
- {
- CommentStmt *n = makeNode(CommentStmt);
- n->objtype = COLUMN;
- n->objschema = $4;
- n->objname = $6;
- n->objproperty = $8;
- n->objlist = NULL;
- n->comment = $10;
- $$ = (Node *) n;
- }
| COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE;
- n->objschema = NULL;
n->objname = $4;
- n->objproperty = NULL;
- n->objlist = makeList1($6);
+ n->objargs = makeList1($6);
n->comment = $9;
$$ = (Node *) n;
}
@@ -2254,10 +2222,8 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = FUNCTION;
- n->objschema = NULL;
n->objname = $4;
- n->objproperty = NULL;
- n->objlist = $5;
+ n->objargs = $5;
n->comment = $7;
$$ = (Node *) n;
}
@@ -2265,28 +2231,24 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OPERATOR;
- n->objschema = NULL;
- n->objname = $4;
- n->objproperty = NULL;
- n->objlist = $6;
+ n->objname = makeList1(makeString($4)); /* XXX */
+ n->objargs = $6;
n->comment = $9;
$$ = (Node *) n;
}
- | COMMENT ON TRIGGER name ON qualified_name IS comment_text
+ | COMMENT ON TRIGGER name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = TRIGGER;
- /* NOTE: schemaname here refers to the table in objproperty */
- n->objschema = $6->schemaname;
- n->objname = $4;
- n->objproperty = $6->relname;
- n->objlist = NULL;
+ n->objname = lappend($6, makeString($4));
+ n->objargs = NIL;
n->comment = $8;
$$ = (Node *) n;
}
;
-comment_type: DATABASE { $$ = DATABASE; }
+comment_type: COLUMN { $$ = COLUMN; }
+ | DATABASE { $$ = DATABASE; }
| INDEX { $$ = INDEX; }
| RULE { $$ = RULE; }
| SEQUENCE { $$ = SEQUENCE; }
@@ -2650,7 +2612,8 @@ index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
func_index: func_name '(' name_list ')' opt_class
{
$$ = makeNode(IndexElem);
- $$->name = $1;
+ $$->name = NULL;
+ $$->funcname = $1;
$$->args = $3;
$$->class = $5;
}
@@ -2660,6 +2623,7 @@ index_elem: attr_name opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
+ $$->funcname = NIL;
$$->args = NIL;
$$->class = $2;
}
@@ -2726,7 +2690,7 @@ ProcedureStmt: CREATE opt_or_replace FUNCTION func_name func_args
{
ProcedureStmt *n = makeNode(ProcedureStmt);
n->replace = $2;
- n->funcname = makeList1(makeString($4)); /* XXX */
+ n->funcname = $4;
n->argTypes = $5;
n->returnType = $7;
n->withClause = $12;
@@ -4680,7 +4644,7 @@ row_expr: '(' row_descriptor ')' IN select_with_parens
FuncCall *n = makeNode(FuncCall);
List *largs = $2;
List *rargs = $6;
- n->funcname = xlateSqlFunc("overlaps");
+ n->funcname = SystemFuncName("overlaps");
if (length(largs) == 1)
largs = lappend(largs, $2);
else if (length(largs) != 2)
@@ -4755,7 +4719,7 @@ a_expr: c_expr
| a_expr AT TIME ZONE c_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "timezone";
+ n->funcname = SystemFuncName("timezone");
n->args = makeList2($5, $1);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4820,7 +4784,7 @@ a_expr: c_expr
| a_expr LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($3, $5);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4831,7 +4795,7 @@ a_expr: c_expr
| a_expr NOT LIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($4, $6);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4842,7 +4806,7 @@ a_expr: c_expr
| a_expr ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($3, $5);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -4853,7 +4817,7 @@ a_expr: c_expr
| a_expr NOT ILIKE a_expr ESCAPE a_expr
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "like_escape";
+ n->funcname = SystemFuncName("like_escape");
n->args = makeList2($4, $6);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5300,7 +5264,7 @@ c_expr: columnref
| CURRENT_USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "current_user";
+ n->funcname = SystemFuncName("current_user");
n->args = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5309,7 +5273,7 @@ c_expr: columnref
| SESSION_USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "session_user";
+ n->funcname = SystemFuncName("session_user");
n->args = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5318,7 +5282,7 @@ c_expr: columnref
| USER opt_empty_parentheses
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "current_user";
+ n->funcname = SystemFuncName("current_user");
n->args = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5327,7 +5291,7 @@ c_expr: columnref
| EXTRACT '(' extract_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "date_part";
+ n->funcname = SystemFuncName("date_part");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5337,7 +5301,7 @@ c_expr: columnref
{
/* position(A in B) is converted to position(B, A) */
FuncCall *n = makeNode(FuncCall);
- n->funcname = "position";
+ n->funcname = SystemFuncName("position");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5349,7 +5313,7 @@ c_expr: columnref
* substring(A, B, C) - thomas 2000-11-28
*/
FuncCall *n = makeNode(FuncCall);
- n->funcname = "substring";
+ n->funcname = SystemFuncName("substring");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5361,7 +5325,7 @@ c_expr: columnref
* - thomas 1997-07-19
*/
FuncCall *n = makeNode(FuncCall);
- n->funcname = "btrim";
+ n->funcname = SystemFuncName("btrim");
n->args = $4;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5370,7 +5334,7 @@ c_expr: columnref
| TRIM '(' LEADING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "ltrim";
+ n->funcname = SystemFuncName("ltrim");
n->args = $4;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5379,7 +5343,7 @@ c_expr: columnref
| TRIM '(' TRAILING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "rtrim";
+ n->funcname = SystemFuncName("rtrim");
n->args = $4;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5388,7 +5352,7 @@ c_expr: columnref
| TRIM '(' trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "btrim";
+ n->funcname = SystemFuncName("btrim");
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@@ -5798,19 +5762,11 @@ class: ColId { $$ = $1; };
index_name: ColId { $$ = $1; };
file_name: Sconst { $$ = $1; };
-/* func_name will soon return a List ... but not yet */
-/*
func_name: function_name
- { $$ = makeList1(makeString($1)); }
+ { $$ = makeList1(makeString(xlateSqlFunc($1))); }
| dotted_name
{ $$ = $1; }
;
-*/
-func_name: function_name
- { $$ = $1; }
- | dotted_name
- { $$ = strVal(lfirst($1)); }
- ;
/* Constants
@@ -5942,9 +5898,9 @@ type_name: IDENT { $$ = $1; }
/* Function identifier --- names that can be function names.
*/
-function_name: IDENT { $$ = xlateSqlFunc($1); }
- | unreserved_keyword { $$ = xlateSqlFunc($1); }
- | func_name_keyword { $$ = xlateSqlFunc($1); }
+function_name: IDENT { $$ = $1; }
+ | unreserved_keyword { $$ = $1; }
+ | func_name_keyword { $$ = $1; }
;
/* Column label --- allowed labels in "AS" clauses.
@@ -6459,6 +6415,8 @@ makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg)
/* xlateSqlFunc()
* Convert alternate function names to internal Postgres functions.
*
+ * NOTE: these conversions are only applied to unqualified function names.
+ *
* Do not convert "float", since that is handled elsewhere
* for FLOAT(p) syntax.
*
@@ -6482,6 +6440,8 @@ xlateSqlFunc(char *name)
/* xlateSqlType()
* Convert alternate type names to internal Postgres types.
*
+ * NOTE: these conversions are only applied to unqualified type names.
+ *
* NB: do NOT put "char" -> "bpchar" here, because that renders it impossible
* to refer to our single-byte char type, even with quotes. (Without quotes,
* CHAR is a keyword, and the code above produces "bpchar" for it.)
@@ -6521,6 +6481,14 @@ xlateSqlType(char *name)
return name;
} /* xlateSqlType() */
+/* SystemFuncName()
+ * Build a properly-qualified reference to a built-in function.
+ */
+List *
+SystemFuncName(char *name)
+{
+ return makeList2(makeString("pg_catalog"), makeString(name));
+}
void parser_init(Oid *typev, int nargs)
{
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index dc939a71801..3812579a4db 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -8,12 +8,13 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.47 2002/03/21 16:00:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.48 2002/04/09 20:35:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
@@ -187,7 +188,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual)
Aggref *
-ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
+ParseAgg(ParseState *pstate, List *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct)
{
HeapTuple aggtuple;
@@ -195,7 +196,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
Aggref *aggref;
aggtuple = SearchSysCache(AGGNAME,
- PointerGetDatum(aggname),
+ PointerGetDatum(strVal(llast(aggname))),
ObjectIdGetDatum(basetype),
0, 0);
/* shouldn't happen --- caller should have checked already */
@@ -218,7 +219,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
*/
aggref = makeNode(Aggref);
- aggref->aggname = pstrdup(aggname);
+ aggref->aggname = pstrdup(strVal(llast(aggname)));
aggref->basetype = aggform->aggbasetype;
aggref->aggtype = aggform->aggfinaltype;
aggref->target = lfirst(args);
@@ -237,7 +238,7 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
* basetype
*/
void
-agg_error(char *caller, char *aggname, Oid basetypeID)
+agg_error(const char *caller, List *aggname, Oid basetypeID)
{
/*
* basetypeID that is Invalid (zero) means aggregate over all types.
@@ -246,8 +247,8 @@ agg_error(char *caller, char *aggname, Oid basetypeID)
if (basetypeID == InvalidOid)
elog(ERROR, "%s: aggregate '%s' for all types does not exist",
- caller, aggname);
+ caller, NameListToString(aggname));
else
elog(ERROR, "%s: aggregate '%s' for type %s does not exist",
- caller, aggname, format_type_be(basetypeID));
+ caller, NameListToString(aggname), format_type_be(basetypeID));
}
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 690a047915a..4dd5777e1e1 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.68 2002/03/20 19:44:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.69 2002/04/09 20:35:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -657,7 +657,8 @@ PreferredType(CATEGORY category, Oid type)
* Look for a coercion function between two types.
*
* A coercion function must be named after (the internal name of) its
- * result type, and must accept exactly the specified input type.
+ * result type, and must accept exactly the specified input type. We
+ * also require it to be defined in the same namespace as its result type.
*
* This routine is also used to look for length-coercion functions, which
* are similar but accept a second argument. secondArgType is the type
@@ -669,14 +670,19 @@ PreferredType(CATEGORY category, Oid type)
static Oid
find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType)
{
- char *funcname;
+ Type targetType;
+ char *typname;
+ Oid typnamespace;
Oid oid_array[FUNC_MAX_ARGS];
int nargs;
HeapTuple ftup;
Form_pg_proc pform;
Oid funcid;
- funcname = typeidTypeName(targetTypeId);
+ targetType = typeidType(targetTypeId);
+ typname = NameStr(((Form_pg_type) GETSTRUCT(targetType))->typname);
+ typnamespace = ((Form_pg_type) GETSTRUCT(targetType))->typnamespace;
+
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
oid_array[0] = inputTypeId;
if (OidIsValid(secondArgType))
@@ -687,22 +693,27 @@ find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType)
else
nargs = 1;
- ftup = SearchSysCache(PROCNAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
+ ftup = SearchSysCache(PROCNAMENSP,
+ CStringGetDatum(typname),
+ Int16GetDatum(nargs),
PointerGetDatum(oid_array),
- 0);
+ ObjectIdGetDatum(typnamespace));
if (!HeapTupleIsValid(ftup))
+ {
+ ReleaseSysCache(targetType);
return InvalidOid;
+ }
/* Make sure the function's result type is as expected, too */
pform = (Form_pg_proc) GETSTRUCT(ftup);
if (pform->prorettype != targetTypeId)
{
ReleaseSysCache(ftup);
+ ReleaseSysCache(targetType);
return InvalidOid;
}
funcid = ftup->t_data->t_oid;
ReleaseSysCache(ftup);
+ ReleaseSysCache(targetType);
return funcid;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 2a5a7698d85..f8449716061 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.112 2002/03/29 19:06:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.113 2002/04/09 20:35:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -129,7 +129,8 @@ transformExpr(ParseState *pstate, Node *expr)
/* handle qualification, if any */
foreach(fields, pref->fields)
{
- result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
+ result = ParseFuncOrColumn(pstate,
+ makeList1(lfirst(fields)),
makeList1(result),
false, false, true);
}
@@ -158,7 +159,8 @@ transformExpr(ParseState *pstate, Node *expr)
/* handle qualification, if any */
foreach(fields, efs->fields)
{
- result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
+ result = ParseFuncOrColumn(pstate,
+ makeList1(lfirst(fields)),
makeList1(result),
false, false, true);
}
@@ -728,7 +730,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
rv = makeNode(RangeVar);
rv->relname = name1;
rv->inhOpt = INH_DEFAULT;
- node = ParseFuncOrColumn(pstate, name2,
+ node = ParseFuncOrColumn(pstate,
+ makeList1(makeString(name2)),
makeList1(rv),
false, false, true);
}
@@ -761,7 +764,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
rv->schemaname = name1;
rv->relname = name2;
rv->inhOpt = INH_DEFAULT;
- node = ParseFuncOrColumn(pstate, name3,
+ node = ParseFuncOrColumn(pstate,
+ makeList1(makeString(name3)),
makeList1(rv),
false, false, true);
}
@@ -801,7 +805,8 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
rv->schemaname = name2;
rv->relname = name3;
rv->inhOpt = INH_DEFAULT;
- node = ParseFuncOrColumn(pstate, name4,
+ node = ParseFuncOrColumn(pstate,
+ makeList1(makeString(name4)),
makeList1(rv),
false, false, true);
}
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 578402fd255..a86195126ff 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.124 2002/04/06 06:59:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.125 2002/04/09 20:35:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,7 +54,7 @@ static int match_argtypes(int nargs,
static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
static FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids,
FuncCandidateList candidates);
-static int agg_get_candidates(char *aggname, Oid typeId,
+static int agg_get_candidates(List *aggname, Oid typeId,
FuncCandidateList *candidates);
static Oid agg_select_candidate(Oid typeid, FuncCandidateList candidates);
@@ -64,22 +64,22 @@ static Oid agg_select_candidate(Oid typeid, FuncCandidateList candidates);
*
* For historical reasons, Postgres tries to treat the notations tab.col
* and col(tab) as equivalent: if a single-argument function call has an
- * argument of complex type and the function name matches any attribute
- * of the type, we take it as a column projection.
+ * argument of complex type and the (unqualified) function name matches
+ * any attribute of the type, we take it as a column projection.
*
* Hence, both cases come through here. The is_column parameter tells us
* which syntactic construct is actually being dealt with, but this is
* intended to be used only to deliver an appropriate error message,
* not to affect the semantics. When is_column is true, we should have
- * a single argument (the putative table), function name equal to the
- * column name, and no aggregate decoration.
+ * a single argument (the putative table), unqualified function name
+ * equal to the column name, and no aggregate decoration.
*
* In the function-call case, the argument expressions have been transformed
* already. In the column case, we may get either a transformed expression
* or a RangeVar node as argument.
*/
Node *
-ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
+ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
bool agg_star, bool agg_distinct, bool is_column)
{
Oid rettype;
@@ -113,23 +113,28 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
{
first_arg = lfirst(fargs);
if (first_arg == NULL) /* should not happen */
- elog(ERROR, "Function '%s' does not allow NULL input", funcname);
+ elog(ERROR, "Function '%s' does not allow NULL input",
+ NameListToString(funcname));
}
/*
* check for column projection: if function has one argument, and that
- * argument is of complex type, then the function could be a projection.
+ * argument is of complex type, and function name is not qualified,
+ * then the "function call" could be a projection. We also check
+ * that there wasn't any aggregate decoration.
*/
- /* We only have one parameter, and it's not got aggregate decoration */
- if (nargs == 1 && !must_be_agg)
+ if (nargs == 1 && !must_be_agg && length(funcname) == 1)
{
+ char *cname = strVal(lfirst(funcname));
+
/* Is it a not-yet-transformed RangeVar node? */
if (IsA(first_arg, RangeVar))
{
/* First arg is a relation. This could be a projection. */
refname = ((RangeVar *) first_arg)->relname;
- retval = qualifiedNameToVar(pstate, refname, funcname, true);
+ /* XXX WRONG: ignores possible qualification of argument */
+ retval = qualifiedNameToVar(pstate, refname, cname, true);
if (retval)
return retval;
}
@@ -140,9 +145,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* ParseComplexProjection can't handle the projection, we have
* to keep going.
*/
- retval = ParseComplexProjection(pstate,
- funcname,
- first_arg);
+ retval = ParseComplexProjection(pstate, cname, first_arg);
if (retval)
return retval;
}
@@ -175,7 +178,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* try for exact match first... */
if (SearchSysCacheExists(AGGNAME,
- PointerGetDatum(funcname),
+ PointerGetDatum(strVal(llast(funcname))),
ObjectIdGetDatum(basetype),
0, 0))
return (Node *) ParseAgg(pstate, funcname, basetype,
@@ -183,7 +186,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* check for aggregate-that-accepts-any-type (eg, COUNT) */
if (SearchSysCacheExists(AGGNAME,
- PointerGetDatum(funcname),
+ PointerGetDatum(strVal(llast(funcname))),
ObjectIdGetDatum(0),
0, 0))
return (Node *) ParseAgg(pstate, funcname, 0,
@@ -211,7 +214,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
{
/* Multiple possible matches --- give up */
elog(ERROR, "Unable to select an aggregate function %s(%s)",
- funcname, format_type_be(basetype));
+ NameListToString(funcname), format_type_be(basetype));
}
}
@@ -222,7 +225,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* function could not have been meant.
*/
elog(ERROR, "There is no aggregate function %s(%s)",
- funcname, format_type_be(basetype));
+ NameListToString(funcname), format_type_be(basetype));
}
}
@@ -275,7 +278,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
*/
if (is_column)
elog(ERROR, "No such attribute %s.%s",
- refname, funcname);
+ refname, strVal(lfirst(funcname)));
else
{
elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
@@ -329,7 +332,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* give an error message that is appropriate for that case.
*/
if (is_column)
- elog(ERROR, "Attribute \"%s\" not found", funcname);
+ elog(ERROR, "Attribute \"%s\" not found",
+ strVal(lfirst(funcname)));
/* Else generate a detailed complaint */
func_error(NULL, funcname, nargs, oid_array,
"Unable to identify a function that satisfies the "
@@ -373,7 +377,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
static int
-agg_get_candidates(char *aggname,
+agg_get_candidates(List *aggname,
Oid typeId,
FuncCandidateList *candidates)
{
@@ -388,7 +392,7 @@ agg_get_candidates(char *aggname,
ScanKeyEntryInitialize(&aggKey[0], 0,
Anum_pg_aggregate_aggname,
F_NAMEEQ,
- NameGetDatum(aggname));
+ NameGetDatum(strVal(llast(aggname))));
pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock);
pg_aggregate_scan = systable_beginscan(pg_aggregate_desc,
@@ -862,7 +866,7 @@ func_select_candidate(int nargs,
* d) if the answer is zero, try the next array from vector #1
*/
FuncDetailCode
-func_get_detail(char *funcname,
+func_get_detail(List *funcname,
List *fargs,
int nargs,
Oid *argtypes,
@@ -875,7 +879,7 @@ func_get_detail(char *funcname,
FuncCandidateList best_candidate;
/* Get list of possible candidates from namespace search */
- function_typeids = FuncnameGetCandidates(makeList1(makeString(funcname)), nargs);
+ function_typeids = FuncnameGetCandidates(funcname, nargs);
/*
* See if there is an exact match
@@ -917,15 +921,11 @@ func_get_detail(char *funcname,
if (nargs == 1)
{
Oid targetType;
+ TypeName *tn = makeNode(TypeName);
- /* XXX WRONG: need to search searchpath for name; but little
- * point in fixing before we revise this code for qualified
- * funcnames too.
- */
- targetType = GetSysCacheOid(TYPENAMENSP,
- PointerGetDatum(funcname),
- ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
- 0, 0);
+ tn->names = funcname;
+ tn->typmod = -1;
+ targetType = LookupTypeName(tn);
if (OidIsValid(targetType) &&
!ISCOMPLEX(targetType))
{
@@ -1409,7 +1409,7 @@ ParseComplexProjection(ParseState *pstate,
* argument types
*/
void
-func_error(const char *caller, const char *funcname,
+func_error(const char *caller, List *funcname,
int nargs, const Oid *argtypes,
const char *msg)
{
@@ -1439,13 +1439,87 @@ func_error(const char *caller, const char *funcname,
if (caller == NULL)
{
elog(ERROR, "Function '%s(%s)' does not exist%s%s",
- funcname, p,
+ NameListToString(funcname), p,
((msg != NULL) ? "\n\t" : ""), ((msg != NULL) ? msg : ""));
}
else
{
elog(ERROR, "%s: function '%s(%s)' does not exist%s%s",
- caller, funcname, p,
+ caller, NameListToString(funcname), p,
((msg != NULL) ? "\n\t" : ""), ((msg != NULL) ? msg : ""));
}
}
+
+/*
+ * LookupFuncName
+ * Given a possibly-qualified function name and a set of argument types,
+ * look up the function. Returns InvalidOid if no such function.
+ *
+ * If the function name is not schema-qualified, it is sought in the current
+ * namespace search path.
+ */
+Oid
+LookupFuncName(List *funcname, int nargs, const Oid *argtypes)
+{
+ FuncCandidateList clist;
+
+ clist = FuncnameGetCandidates(funcname, nargs);
+
+ while (clist)
+ {
+ if (memcmp(argtypes, clist->args, nargs * sizeof(Oid)) == 0)
+ return clist->oid;
+ clist = clist->next;
+ }
+
+ return InvalidOid;
+}
+
+/*
+ * LookupFuncNameTypeNames
+ * Like LookupFuncName, but the argument types are specified by a
+ * list of TypeName nodes. Also, if we fail to find the function
+ * and caller is not NULL, then an error is reported via func_error.
+ *
+ * "opaque" is accepted as a typename only if opaqueOK is true.
+ */
+Oid
+LookupFuncNameTypeNames(List *funcname, List *argtypes, bool opaqueOK,
+ const char *caller)
+{
+ Oid funcoid;
+ Oid argoids[FUNC_MAX_ARGS];
+ int argcount;
+ int i;
+
+ MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
+ argcount = length(argtypes);
+ if (argcount > FUNC_MAX_ARGS)
+ elog(ERROR, "functions cannot have more than %d arguments",
+ FUNC_MAX_ARGS);
+
+ for (i = 0; i < argcount; i++)
+ {
+ TypeName *t = (TypeName *) lfirst(argtypes);
+
+ argoids[i] = LookupTypeName(t);
+ if (!OidIsValid(argoids[i]))
+ {
+ char *typnam = TypeNameToString(t);
+
+ if (opaqueOK && strcmp(typnam, "opaque") == 0)
+ argoids[i] = InvalidOid;
+ else
+ elog(ERROR, "Type \"%s\" does not exist", typnam);
+ }
+
+ argtypes = lnext(argtypes);
+ }
+
+ funcoid = LookupFuncName(funcname, argcount, argoids);
+
+ if (!OidIsValid(funcoid) && caller != NULL)
+ func_error(caller, funcname, argcount, argoids, NULL);
+
+ return funcoid;
+}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index e8e82a45c3b..83c53de5d1d 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.82 2002/04/05 11:56:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.83 2002/04/09 20:35:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -498,48 +498,34 @@ FigureColnameInternal(Node *node, char **name)
return 2;
case T_ColumnRef:
{
- List *fields = ((ColumnRef *) node)->fields;
+ char *cname = strVal(llast(((ColumnRef *) node)->fields));
- while (lnext(fields) != NIL)
- fields = lnext(fields);
- if (strcmp(strVal(lfirst(fields)), "*") != 0)
+ if (strcmp(cname, "*") != 0)
{
- *name = strVal(lfirst(fields));
+ *name = cname;
return 2;
}
}
break;
case T_ExprFieldSelect:
{
- List *fields = ((ExprFieldSelect *) node)->fields;
+ char *fname = strVal(llast(((ExprFieldSelect *) node)->fields));
- if (fields)
+ if (strcmp(fname, "*") != 0)
{
- while (lnext(fields) != NIL)
- fields = lnext(fields);
- if (strcmp(strVal(lfirst(fields)), "*") != 0)
- {
- *name = strVal(lfirst(fields));
- return 2;
- }
+ *name = fname;
+ return 2;
}
}
break;
case T_FuncCall:
- *name = ((FuncCall *) node)->funcname;
+ *name = strVal(llast(((FuncCall *) node)->funcname));
return 2;
case T_A_Const:
if (((A_Const *) node)->typename != NULL)
{
- List *names = ((A_Const *) node)->typename->names;
-
- if (names != NIL)
- {
- while (lnext(names) != NIL)
- names = lnext(names);
- *name = strVal(lfirst(names));
- return 1;
- }
+ *name = strVal(llast(((A_Const *) node)->typename->names));
+ return 1;
}
break;
case T_TypeCast:
@@ -549,15 +535,8 @@ FigureColnameInternal(Node *node, char **name)
{
if (((TypeCast *) node)->typename != NULL)
{
- List *names = ((TypeCast *) node)->typename->names;
-
- if (names != NIL)
- {
- while (lnext(names) != NIL)
- names = lnext(names);
- *name = strVal(lfirst(names));
- return 1;
- }
+ *name = strVal(llast(((TypeCast *) node)->typename->names));
+ return 1;
}
}
break;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index bd5e31666ca..ed87b00b757 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.145 2002/04/01 04:35:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.146 2002/04/09 20:35:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -345,12 +345,7 @@ ProcessUtility(Node *parsetree,
break;
case T_CommentStmt:
- {
- CommentStmt *stmt = (CommentStmt *) parsetree;
-
- CommentObject(stmt->objtype, stmt->objschema, stmt->objname,
- stmt->objproperty, stmt->objlist, stmt->comment);
- }
+ CommentObject((CommentStmt *) parsetree);
break;
case T_CopyStmt:
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 7e6a95a324e..36535bd7fa9 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.74 2002/04/06 06:59:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.75 2002/04/09 20:35:54 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -303,15 +303,15 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
- {ProcedureRelationName, /* PROCNAME */
- ProcedureNameNspIndex, /* XXX very temporary */
+ {ProcedureRelationName, /* PROCNAMENSP */
+ ProcedureNameNspIndex,
0,
- 3,
+ 4,
{
Anum_pg_proc_proname,
Anum_pg_proc_pronargs,
Anum_pg_proc_proargtypes,
- 0
+ Anum_pg_proc_pronamespace
}},
{ProcedureRelationName, /* PROCOID */
ProcedureOidIndex,
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 4c81e78f3ff..15a21e77d5d 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: namespace.h,v 1.6 2002/04/06 06:59:24 tgl Exp $
+ * $Id: namespace.h,v 1.7 2002/04/09 20:35:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,6 +47,8 @@ extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
extern RangeVar *makeRangeVarFromNameList(List *names);
+extern char *NameListToString(List *names);
+
extern bool isTempNamespace(Oid namespaceId);
/* stuff for search_path GUC variable */
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 65494e8afe2..3d44f4c4c0f 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_aggregate.h,v 1.36 2002/03/29 19:06:18 tgl Exp $
+ * $Id: pg_aggregate.h,v 1.37 2002/04/09 20:35:54 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -157,8 +157,8 @@ DATA(insert OID = 0 ( stddev PGUID numeric_accum numeric_stddev 1700 1231 1700
*/
extern void AggregateCreate(const char *aggName,
Oid aggNamespace,
- char *aggtransfnName,
- char *aggfinalfnName,
+ List *aggtransfnName,
+ List *aggfinalfnName,
Oid aggBaseType,
Oid aggTransType,
const char *agginitval);
diff --git a/src/include/commands/comment.h b/src/include/commands/comment.h
index f1e9a760b0b..bf2acfcfa0e 100644
--- a/src/include/commands/comment.h
+++ b/src/include/commands/comment.h
@@ -12,7 +12,7 @@
#ifndef COMMENT_H
#define COMMENT_H
-#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
/*------------------------------------------------------------------
* Function Prototypes --
@@ -25,8 +25,7 @@
*------------------------------------------------------------------
*/
-extern void CommentObject(int objtype, char * schemaname, char *objname,
- char *objproperty, List *objlist, char *comment);
+extern void CommentObject(CommentStmt *stmt);
extern void DeleteComments(Oid oid, Oid classoid);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 69f180ec162..83b8fec6d77 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: defrem.h,v 1.33 2002/03/29 19:06:22 tgl Exp $
+ * $Id: defrem.h,v 1.34 2002/04/09 20:35:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,10 +45,10 @@ extern void DefineDomain(CreateDomainStmt *stmt);
* prototypes in remove.c
*/
extern void RemoveDomain(List *names, int behavior);
-extern void RemoveFunction(char *functionName, List *argTypes);
+extern void RemoveFunction(List *functionName, List *argTypes);
extern void RemoveOperator(char *operatorName,
TypeName *typeName1, TypeName *typeName2);
extern void RemoveType(List *names);
-extern void RemoveAggregate(char *aggName, TypeName *aggType);
+extern void RemoveAggregate(List *aggName, TypeName *aggType);
#endif /* DEFREM_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index e2b0d9f38f3..6fc2fec9ad9 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.168 2002/04/05 11:56:54 momjian Exp $
+ * $Id: parsenodes.h,v 1.169 2002/04/09 20:35:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -304,7 +304,7 @@ typedef struct Ident
typedef struct FuncCall
{
NodeTag type;
- char *funcname; /* name of function */
+ List *funcname; /* qualified name of function */
List *args; /* the arguments (list of exprs) */
bool agg_star; /* argument was really '*' */
bool agg_distinct; /* arguments were labeled DISTINCT */
@@ -390,15 +390,16 @@ typedef struct RangeSubselect
/*
* IndexElem - index parameters (used in CREATE INDEX)
*
- * For a plain index, each 'name' is an attribute name in the heap relation,
- * and 'args' is NIL. For a functional index, only one IndexElem is allowed.
- * It has name = name of function and args = list of attribute names that
- * are the function's arguments.
+ * For a plain index, each 'name' is an attribute name in the heap relation;
+ * 'funcname' and 'args' are NIL. For a functional index, only one IndexElem
+ * is allowed. It has name = NULL, funcname = name of function and args =
+ * list of attribute names that are the function's arguments.
*/
typedef struct IndexElem
{
NodeTag type;
- char *name; /* name of attribute to index, or function */
+ char *name; /* name of attribute to index, or NULL */
+ List *funcname; /* qualified name of function */
List *args; /* list of names of function arguments */
char *class; /* name of desired opclass; NULL = default */
} IndexElem;
@@ -780,7 +781,7 @@ typedef struct PrivGrantee
typedef struct FuncWithArgs
{
NodeTag type;
- char *funcname;
+ List *funcname; /* qualified name of function */
List *funcargs; /* list of Typename nodes */
} FuncWithArgs;
@@ -919,10 +920,10 @@ typedef struct FkConstraint
typedef struct CreateTrigStmt
{
NodeTag type;
- char *trigname; /* TRIGGER' name */
- RangeVar *relation; /* triggered relation */
- char *funcname; /* function to call (or NULL) */
- List *args; /* list of (T_String) Values or NULL */
+ char *trigname; /* TRIGGER's name */
+ RangeVar *relation; /* relation trigger is on */
+ List *funcname; /* qual. name of function to call */
+ List *args; /* list of (T_String) Values or NIL */
bool before; /* BEFORE/AFTER */
bool row; /* ROW/STATEMENT */
char actions[4]; /* Insert, Update, Delete */
@@ -954,7 +955,7 @@ typedef struct CreatePLangStmt
{
NodeTag type;
char *plname; /* PL name */
- char *plhandler; /* PL call handler function */
+ List *plhandler; /* PL call handler function (qual. name) */
char *plcompiler; /* lancompiler text */
bool pltrusted; /* PL is trusted */
} CreatePLangStmt;
@@ -1097,12 +1098,9 @@ typedef struct CommentStmt
{
NodeTag type;
int objtype; /* Object's type */
- char *objschema; /* Schema where object is defined,
- * if object is schema specific */
- char *objname; /* Name of the object */
- char *objproperty; /* Property Id (such as column) */
- List *objlist; /* Arguments for VAL objects */
- char *comment; /* The comment to insert */
+ List *objname; /* Qualified name of the object */
+ List *objargs; /* Arguments if needed (eg, for functions) */
+ char *comment; /* Comment to insert, or NULL to remove */
} CommentStmt;
/* ----------------------
@@ -1154,7 +1152,7 @@ typedef struct ProcedureStmt
{
NodeTag type;
bool replace; /* T => replace if already exists */
- List *funcname; /* name of function to create */
+ List *funcname; /* qualified name of function to create */
List *argTypes; /* list of argument types (TypeName nodes) */
TypeName *returnType; /* the return type */
List *withClause; /* a list of DefElem */
@@ -1169,7 +1167,7 @@ typedef struct ProcedureStmt
typedef struct RemoveAggrStmt
{
NodeTag type;
- char *aggname; /* aggregate to drop */
+ List *aggname; /* aggregate to drop */
TypeName *aggtype; /* TypeName for input datatype, or NULL */
} RemoveAggrStmt;
@@ -1180,7 +1178,7 @@ typedef struct RemoveAggrStmt
typedef struct RemoveFuncStmt
{
NodeTag type;
- char *funcname; /* function to drop */
+ List *funcname; /* function to drop */
List *args; /* types of the arguments */
} RemoveFuncStmt;
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 6b224d6c385..722fb772916 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_list.h,v 1.26 2001/11/05 17:46:34 momjian Exp $
+ * $Id: pg_list.h,v 1.27 2002/04/09 20:35:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -109,6 +109,8 @@ typedef struct List
* function prototypes in nodes/list.c
*/
extern int length(List *list);
+extern void *llast(List *list);
+extern int llasti(List *list);
extern List *nconc(List *list1, List *list2);
extern List *lcons(void *datum, List *list);
extern List *lconsi(int datum, List *list);
diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h
index a9932ab59a0..42ae42d9e63 100644
--- a/src/include/parser/gramparse.h
+++ b/src/include/parser/gramparse.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: gramparse.h,v 1.19 2001/11/05 17:46:34 momjian Exp $
+ * $Id: gramparse.h,v 1.20 2002/04/09 20:35:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,6 +29,7 @@ extern Oid param_type(int t);
extern int yyparse(void);
extern char *xlateSqlFunc(char *name);
extern char *xlateSqlType(char *name);
+extern List *SystemFuncName(char *name);
bool exprIsNullConstant(Node *arg);
#endif /* GRAMPARSE_H */
diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h
index 666e4ede764..03ac8dc6462 100644
--- a/src/include/parser/parse_agg.h
+++ b/src/include/parser/parse_agg.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_agg.h,v 1.21 2002/03/21 16:01:55 tgl Exp $
+ * $Id: parse_agg.h,v 1.22 2002/04/09 20:35:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,8 +18,8 @@
extern void AddAggToParseState(ParseState *pstate, Aggref *aggref);
extern void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual);
-extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
+extern Aggref *ParseAgg(ParseState *pstate, List *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct);
-extern void agg_error(char *caller, char *aggname, Oid basetypeID);
+extern void agg_error(const char *caller, List *aggname, Oid basetypeID);
#endif /* PARSE_AGG_H */
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index 01e5b16e2b5..3a7641e1de7 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_func.h,v 1.37 2002/03/29 19:06:24 tgl Exp $
+ * $Id: parse_func.h,v 1.38 2002/04/09 20:35:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,18 +48,22 @@ typedef enum
extern Node *ParseFuncOrColumn(ParseState *pstate,
- char *funcname, List *fargs,
+ List *funcname, List *fargs,
bool agg_star, bool agg_distinct, bool is_column);
-extern FuncDetailCode func_get_detail(char *funcname, List *fargs,
+extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
int nargs, Oid *argtypes,
Oid *funcid, Oid *rettype,
bool *retset, Oid **true_typeids);
extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
-extern void func_error(const char *caller, const char *funcname,
+extern void func_error(const char *caller, List *funcname,
int nargs, const Oid *argtypes,
const char *msg);
+extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes);
+extern Oid LookupFuncNameTypeNames(List *funcname, List *argtypes,
+ bool opaqueOK, const char *caller);
+
#endif /* PARSE_FUNC_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 1d9ddd9acfd..365d9efdb5d 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: syscache.h,v 1.42 2002/04/06 06:59:25 tgl Exp $
+ * $Id: syscache.h,v 1.43 2002/04/09 20:35:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -49,7 +49,7 @@
#define NAMESPACEOID 18
#define OPERNAME 19
#define OPEROID 20
-#define PROCNAME 21
+#define PROCNAMENSP 21
#define PROCOID 22
#define RELNAMENSP 23
#define RELOID 24
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 6c9b84dda2b..ab4db0d93ef 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -205,7 +205,7 @@ GRANT USAGE ON FUNCTION testfunc1(int) TO regressuser3; -- semantic error
ERROR: invalid privilege type USAGE for function object
GRANT ALL PRIVILEGES ON FUNCTION testfunc1(int) TO regressuser4;
GRANT ALL PRIVILEGES ON FUNCTION testfunc_nosuch(int) TO regressuser4;
-ERROR: Function 'testfunc_nosuch(int4)' does not exist
+ERROR: GRANT: function 'testfunc_nosuch(int4)' does not exist
SET SESSION AUTHORIZATION regressuser2;
SELECT testfunc1(5), testfunc2(5); -- ok
testfunc1 | testfunc2