Functions live in namespaces. Qualified function names work, eg

SELECT schema1.func2(...).  Aggregate names can be qualified at the
syntactic level, but the qualification is ignored for the moment.
This commit is contained in:
Tom Lane 2002-04-09 20:35:55 +00:00
parent c419c22414
commit f2d70d32eb
36 changed files with 655 additions and 661 deletions

View File

@ -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;
}

View File

@ -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))

View File

@ -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?
*/

View File

@ -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);

View File

@ -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);

View File

@ -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))
{

View File

@ -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;
Oid oid;
/* First, initialize function's argument list with their type oids */
/* Look up the procedure */
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);
}
/* 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;

View File

@ -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)
{

View File

@ -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");
}

View File

@ -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;

View File

@ -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);
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 (!HeapTupleIsValid(tup))
func_error("RemoveFunction", functionName, nargs, argList, NULL);
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 */

View File

@ -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);

View File

@ -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;

View File

@ -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))

View File

@ -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
*

View File

@ -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 ");

View File

@ -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");

View File

@ -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)
{

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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:

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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