diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 7afd6659e1af28620ea691a6f78a5d000b237f22..b5d039f9355ef63831e56edcf35786f811afee7c 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 00c52e89c4b80da4f5ff2836733ff1c75997d278..07f49c75ab2cffa3b4ac1c21a017730abb0c0d72 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 a7d73bbf272240050e271d9d37508f2a44ab1541..6880dbe19e396e1b92424b79c1c8c54fddb88c42 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); @@ -564,6 +565,29 @@ makeRangeVarFromNameList(List *names) return rel; } +/* + * 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? */ diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 1a73f42c3344a78792b6f28483dc3e64a9772043..a9f270fccf8afd718e3b17da992d2f3d5f9882c7 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 8942c266fd6b9d68c41c37a50be3a6c3e74acee7..41023b7edc8c8266a09ebaf377e3bbad8a39aa7b 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 02f76e7679a942f34b12bd59abfa3a9533c93ac3..8cb89b979cbab9f2a0d5f92a23e85743e1e19b94 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 f8e5bc6fc6fd6fe3fe96c274ea191c6d0f5d9fe8..b7d57f6cce5959c3c1577a99d9d656cda4766d72 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 eaff4e66dfa80d262f50206828d62da93348cfcf..cccbcdfaa5922ec6bfed384e90cba9a86a634103 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 b5067f99278fa21659a2fb66759c54f369529483..43539cd625af170521eb1c6a8a4f1c4933a1d8fa 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 d9cf0f0814a380d9c4892a7d85a64865fb787f3e..4ef8d8f72a0bee3b3a69cab019cd467181aa6bd2 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 fb73fe3bd0236c8ef2b4e2d6f0f37e64ccb66592..8969b9cdc13b9d6e896997bd722d1fc9d4b2dfc3 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 c05b2ec51a31b895cdeb882a56bb8ddd69ffd40f..72f13d3db491dd041cface0469dd567463a654ee 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 b633b02b79d29bcfee773d80215f2d63c193f0da..873658774ca9acc2cdbbc648ce5b26313e94a1e6 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 eceb8cb36f796e0aa0acb660dac9f6e8df433a51..9458ebc5b95568daf03dc25089151198f2e52867 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 9b588150fda8be7757d8345626164ef383f7be59..a61991f38fa015aa095b52f4b407eeb74f8aee69 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 @@ -233,6 +233,36 @@ length(List *l) return i; } +/* + * 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 * diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 20d25c6439785068389070b7128b2d689f8e61a9..a495f5ed10b3e42cb7336d9f720014d94ac40dc0 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 0de9c5bb851b86f1bf2f87d5ebaec9518b90a1a5..8b3f218b83adc7d987c95f949ab254feb0fed4b3 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 6ba8766e1ac173cfe40c5e4c750a7ed3fbdd97e0..3488fb0762ff3a6af8589eddb9f12b727558359f 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 dc939a71801e129102ab62bd44bf5dbf35e7fec6..3812579a4dbbc9ec41380c8ad1507d80f04974ac 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 690a047915ac202cfb32e4aabe6fe99cd1c288a5..4dd5777e1e11f6c9b5ddd01f4d0961d258f43dc4 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 2a5a7698d858fd0c4705785a663870784b2afa6d..f84497160613e6e6bb47cbc92ea951a083f8d507 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 578402fd255293543a98abaa3275fa5444498b2c..a86195126ffafc29dcb6ab59ebd6c26d8492d8b5 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 e8e82a45c3b9d09ee65388eab049546bae5eed50..83c53de5d1d7aeea8c25646fdc4e15dfccb2d8bd 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 bd5e31666ca9c70c8489fccbcd2b98303b551d95..ed87b00b75783e2ea5b010783267444164cbc64b 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 7e6a95a324e464a932a7855edec6c0e037057f3d..36535bd7fa92d70764bb0b0e330a12b57c0e73ed 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 4c81e78f3ffbe3699bf638798a7ec84679a46046..15a21e77d5d76b3193526cb3f27bbdaf068bc93e 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 65494e8afe200fe83d7489414196c2069dc1299f..3d44f4c4c0fb6389cddc3891e7a30ecd0bb2093a 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 f1e9a760b0b08f60f61b9ecb1e0b31acbe01ca34..bf2acfcfa0ed9479f862b2247b0749b179c4a09f 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 69f180ec1622e9afe80796a77882ec390fcfcd9c..83b8fec6d77cb05cc6e06f9561186fcf7231181d 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 e2b0d9f38f3d43b1d060a16d732e8e1814890a1a..6fc2fec9ad952d677b1edcc36e5f269465eaf1f1 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 6b224d6c3859b189d8d1af989222a999c09d56b8..722fb772916a404e04c387b908c5930ed8130856 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 a9932ab59a041d184f764af8e56dece2b602df5f..42ae42d9e63b084e5d3db3fb6f2821d71d197e3a 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 666e4ede7645706e5b8acc3b434534bba5956b0f..03ac8dc64622e243829dbab8cf41bfadaa2b67db 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 01e5b16e2b5d54a88c91a8c44778263559726471..3a7641e1de7a18d4deb127fe8a261145392cc435 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 1d9ddd9acfd8f37173802ac48e0889947c4f0d08..365d9efdb5d4d92bbdd514b7a85f0ea77e77b0c9 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 6c9b84dda2b8f56a4d63deec162b66c41300679d..ab4db0d93ef345673bfaaad954b30ce7f6dc0423 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