diff options
Diffstat (limited to 'src/backend/commands')
| -rw-r--r-- | src/backend/commands/comment.c | 25 | ||||
| -rw-r--r-- | src/backend/commands/define.c | 91 | ||||
| -rw-r--r-- | src/backend/commands/indexcmds.c | 6 | ||||
| -rw-r--r-- | src/backend/commands/remove.c | 54 |
4 files changed, 127 insertions, 49 deletions
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index b7d57f6cce..b7de77067d 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1999-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.39 2002/04/09 20:35:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.40 2002/04/11 19:59:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,15 +25,11 @@ #include "catalog/pg_operator.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_trigger.h" -#include "catalog/pg_type.h" #include "commands/comment.h" #include "miscadmin.h" -#include "nodes/makefuncs.h" -#include "parser/parse_agg.h" #include "parser/parse_func.h" #include "parser/parse_type.h" #include "parser/parse.h" -#include "rewrite/rewriteRemove.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -573,7 +569,6 @@ CommentAggregate(List *aggregate, List *arguments, char *comment) TypeName *aggtype = (TypeName *) lfirst(arguments); Oid baseoid, oid; - Oid classoid; /* First, attempt to determine the base aggregate oid */ if (aggtype) @@ -581,18 +576,13 @@ CommentAggregate(List *aggregate, List *arguments, char *comment) else baseoid = InvalidOid; - /* Now, attempt to find the actual tuple in pg_aggregate */ + /* Now, attempt to find the actual tuple in pg_proc */ - oid = GetSysCacheOid(AGGNAME, - PointerGetDatum(strVal(lfirst(aggregate))), /* XXX */ - ObjectIdGetDatum(baseoid), - 0, 0); - if (!OidIsValid(oid)) - agg_error("CommentAggregate", aggregate, baseoid); + oid = find_aggregate_func("CommentAggregate", aggregate, baseoid); /* Next, validate the user's attempt to comment */ - if (!pg_aggr_ownercheck(oid, GetUserId())) + if (!pg_proc_ownercheck(oid, GetUserId())) { if (baseoid == InvalidOid) elog(ERROR, "you are not permitted to comment on aggregate %s for all types", @@ -602,14 +592,9 @@ CommentAggregate(List *aggregate, List *arguments, char *comment) NameListToString(aggregate), format_type_be(baseoid)); } - /* pg_aggregate doesn't have a hard-coded OID, so must look it up */ - - classoid = get_relname_relid(AggregateRelationName, PG_CATALOG_NAMESPACE); - Assert(OidIsValid(classoid)); - /* Call CreateComments() to create/drop the comments */ - CreateComments(oid, classoid, 0, comment); + CreateComments(oid, RelOid_pg_proc, 0, comment); } /* diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index cccbcdfaa5..692fc9f957 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.74 2002/04/09 20:35:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.75 2002/04/11 19:59:57 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -141,13 +141,56 @@ compute_return_type(TypeName *returnType, Oid languageOid, *returnsSet_p = returnType->setof; } - -static void -compute_full_attributes(List *parameters, - int32 *byte_pct_p, int32 *perbyte_cpu_p, - int32 *percall_cpu_p, int32 *outin_ratio_p, - bool *isStrict_p, char *volatility_p) +/* + * Interpret the argument-types list of the CREATE FUNCTION statement. + */ +static int +compute_parameter_types(List *argTypes, Oid languageOid, + Oid *parameterTypes) { + int parameterCount = 0; + List *x; + + MemSet(parameterTypes, 0, FUNC_MAX_ARGS * sizeof(Oid)); + foreach(x, argTypes) + { + TypeName *t = (TypeName *) lfirst(x); + Oid toid; + + if (parameterCount >= FUNC_MAX_ARGS) + elog(ERROR, "functions cannot have more than %d arguments", + FUNC_MAX_ARGS); + + toid = LookupTypeName(t); + if (OidIsValid(toid)) + { + if (!get_typisdefined(toid)) + elog(WARNING, "Argument type \"%s\" is only a shell", + TypeNameToString(t)); + } + else + { + char *typnam = TypeNameToString(t); + + if (strcmp(typnam, "opaque") == 0) + { + if (languageOid == SQLlanguageId) + elog(ERROR, "SQL functions cannot have arguments of type \"opaque\""); + toid = InvalidOid; + } + else + elog(ERROR, "Type \"%s\" does not exist", typnam); + } + + if (t->setof) + elog(ERROR, "functions cannot accept set arguments"); + + parameterTypes[parameterCount++] = toid; + } + + return parameterCount; +} + /*------------- * Interpret the parameters *parameters and return their contents as * *byte_pct_p, etc. @@ -155,7 +198,10 @@ compute_full_attributes(List *parameters, * These parameters supply optional information about a function. * All have defaults if not specified. * - * Note: currently, only two of these parameters actually do anything: + * Note: currently, only three of these parameters actually do anything: + * + * * isImplicit means the function may be used as an implicit type + * coercion. * * * isStrict means the function should not be called when any NULL * inputs are present; instead a NULL result value should be assumed. @@ -168,6 +214,13 @@ compute_full_attributes(List *parameters, * for a long time. *------------ */ +static void +compute_full_attributes(List *parameters, + int32 *byte_pct_p, int32 *perbyte_cpu_p, + int32 *percall_cpu_p, int32 *outin_ratio_p, + bool *isImplicit_p, bool *isStrict_p, + char *volatility_p) +{ List *pl; /* the defaults */ @@ -175,6 +228,7 @@ compute_full_attributes(List *parameters, *perbyte_cpu_p = PERBYTE_CPU; *percall_cpu_p = PERCALL_CPU; *outin_ratio_p = OUTIN_RATIO; + *isImplicit_p = false; *isStrict_p = false; *volatility_p = PROVOLATILE_VOLATILE; @@ -182,7 +236,9 @@ compute_full_attributes(List *parameters, { DefElem *param = (DefElem *) lfirst(pl); - if (strcasecmp(param->defname, "isstrict") == 0) + if (strcasecmp(param->defname, "implicitcoercion") == 0) + *isImplicit_p = true; + else if (strcasecmp(param->defname, "isstrict") == 0) *isStrict_p = true; else if (strcasecmp(param->defname, "isimmutable") == 0) *volatility_p = PROVOLATILE_IMMUTABLE; @@ -276,11 +332,14 @@ CreateFunction(ProcedureStmt *stmt) Oid languageOid; char *funcname; Oid namespaceId; + int parameterCount; + Oid parameterTypes[FUNC_MAX_ARGS]; int32 byte_pct, perbyte_cpu, percall_cpu, outin_ratio; - bool isStrict; + bool isImplicit, + isStrict; char volatility; HeapTuple languageTuple; Form_pg_language languageStruct; @@ -316,9 +375,13 @@ CreateFunction(ProcedureStmt *stmt) compute_return_type(stmt->returnType, languageOid, &prorettype, &returnsSet); + parameterCount = compute_parameter_types(stmt->argTypes, languageOid, + parameterTypes); + compute_full_attributes(stmt->withClause, &byte_pct, &perbyte_cpu, &percall_cpu, - &outin_ratio, &isStrict, &volatility); + &outin_ratio, &isImplicit, &isStrict, + &volatility); interpret_AS_clause(languageOid, languageName, stmt->as, &prosrc_str, &probin_str); @@ -335,18 +398,20 @@ CreateFunction(ProcedureStmt *stmt) languageOid, prosrc_str, /* converted to text later */ probin_str, /* converted to text later */ + false, /* not an aggregate */ true, /* (obsolete "trusted") */ + isImplicit, isStrict, volatility, byte_pct, perbyte_cpu, percall_cpu, outin_ratio, - stmt->argTypes); + parameterCount, + parameterTypes); } - /* * DefineOperator * this function extracts all the information from the diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 43539cd625..0a8ddc1807 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.68 2002/04/09 20:35:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.69 2002/04/11 19:59:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -303,7 +303,9 @@ FuncIndexArgs(IndexInfo *indexInfo, &true_typeids); if (fdresult != FUNCDETAIL_NORMAL) { - if (fdresult == FUNCDETAIL_COERCION) + if (fdresult == FUNCDETAIL_AGGREGATE) + elog(ERROR, "DefineIndex: functional index may not use an aggregate function"); + else if (fdresult == FUNCDETAIL_COERCION) 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 diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index 8969b9cdc1..c32d2b215c 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.73 2002/04/09 20:35:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.74 2002/04/11 19:59:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,7 +24,6 @@ #include "commands/defrem.h" #include "miscadmin.h" #include "parser/parse.h" -#include "parser/parse_agg.h" #include "parser/parse_func.h" #include "parser/parse_type.h" #include "utils/acl.h" @@ -381,6 +380,11 @@ RemoveFunction(List *functionName, /* function name to be removed */ elog(ERROR, "RemoveFunction: function '%s': permission denied", NameListToString(functionName)); + if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) + elog(ERROR, "RemoveFunction: function '%s' is an aggregate" + "\n\tUse DROP AGGREGATE to remove it", + NameListToString(functionName)); + if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId) { /* "Helpful" WARNING when removing a builtin function ... */ @@ -404,6 +408,7 @@ RemoveAggregate(List *aggName, TypeName *aggType) Relation relation; HeapTuple tup; Oid basetypeID; + Oid procOid; /* * if a basetype is passed in, then attempt to find an aggregate for @@ -413,23 +418,16 @@ RemoveAggregate(List *aggName, TypeName *aggType) * a basetype of zero. This is valid. It means that the aggregate is * to apply to all basetypes (eg, COUNT). */ - if (aggType) basetypeID = typenameTypeId(aggType); else basetypeID = InvalidOid; - relation = heap_openr(AggregateRelationName, RowExclusiveLock); + procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID); - tup = SearchSysCache(AGGNAME, - PointerGetDatum(strVal(llast(aggName))), - ObjectIdGetDatum(basetypeID), - 0, 0); + /* Permission check */ - if (!HeapTupleIsValid(tup)) - agg_error("RemoveAggregate", aggName, basetypeID); - - if (!pg_aggr_ownercheck(tup->t_data->t_oid, GetUserId())) + if (!pg_proc_ownercheck(procOid, GetUserId())) { if (basetypeID == InvalidOid) elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied", @@ -439,8 +437,36 @@ RemoveAggregate(List *aggName, TypeName *aggType) NameListToString(aggName), format_type_be(basetypeID)); } - /* Remove any comments related to this aggregate */ - DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); + /* Remove the pg_proc tuple */ + + relation = heap_openr(ProcedureRelationName, RowExclusiveLock); + + tup = SearchSysCache(PROCOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s", + NameListToString(aggName)); + + /* Delete any comments associated with this function */ + DeleteComments(procOid, RelationGetRelid(relation)); + + simple_heap_delete(relation, &tup->t_self); + + ReleaseSysCache(tup); + + heap_close(relation, RowExclusiveLock); + + /* Remove the pg_aggregate tuple */ + + relation = heap_openr(AggregateRelationName, RowExclusiveLock); + + tup = SearchSysCache(AGGFNOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "RemoveAggregate: couldn't find pg_aggregate tuple for %s", + NameListToString(aggName)); simple_heap_delete(relation, &tup->t_self); |
