diff options
Diffstat (limited to 'src/backend/catalog/pg_aggregate.c')
| -rw-r--r-- | src/backend/catalog/pg_aggregate.c | 126 |
1 files changed, 41 insertions, 85 deletions
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index a9f270fccf..951e45c5ff 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.43 2002/04/09 20:35:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.44 2002/04/11 19:59:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,15 +19,16 @@ #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" +#include "catalog/pg_language.h" #include "catalog/pg_proc.h" -#include "catalog/pg_type.h" -#include "miscadmin.h" +#include "optimizer/cost.h" #include "parser/parse_coerce.h" #include "parser/parse_func.h" #include "parser/parse_type.h" #include "utils/builtins.h" #include "utils/syscache.h" + /* * AggregateCreate */ @@ -50,7 +51,7 @@ AggregateCreate(const char *aggName, Oid finaltype; Oid fnArgs[FUNC_MAX_ARGS]; int nargs; - NameData aname; + Oid procOid; TupleDesc tupDesc; int i; @@ -61,15 +62,6 @@ AggregateCreate(const char *aggName, if (!aggtransfnName) elog(ERROR, "aggregate must have a transition function"); - /* make sure there is no existing agg of same name and base type */ - if (SearchSysCacheExists(AGGNAME, - PointerGetDatum(aggName), - ObjectIdGetDatum(aggBaseType), - 0, 0)) - elog(ERROR, - "aggregate function \"%s\" with base type %s already exists", - aggName, typeidTypeName(aggBaseType)); - /* handle transfn */ MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid)); fnArgs[0] = aggTransType; @@ -109,8 +101,8 @@ AggregateCreate(const char *aggName, /* handle finalfn, if supplied */ if (aggfinalfnName) { + MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid)); fnArgs[0] = aggTransType; - fnArgs[1] = 0; finalfn = LookupFuncName(aggfinalfnName, 1, fnArgs); if (!OidIsValid(finalfn)) func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL); @@ -132,21 +124,47 @@ AggregateCreate(const char *aggName, } Assert(OidIsValid(finaltype)); + /* + * Everything looks okay. Try to create the pg_proc entry for the + * aggregate. (This could fail if there's already a conflicting entry.) + */ + MemSet(fnArgs, 0, FUNC_MAX_ARGS * sizeof(Oid)); + fnArgs[0] = aggBaseType; + + procOid = ProcedureCreate(aggName, + aggNamespace, + false, /* no replacement */ + false, /* doesn't return a set */ + finaltype, /* returnType */ + INTERNALlanguageId, /* languageObjectId */ + "aggregate_dummy", /* placeholder proc */ + "-", /* probin */ + true, /* isAgg */ + true, /* (obsolete "trusted") */ + false, /* isImplicit */ + false, /* isStrict (not needed for agg) */ + PROVOLATILE_IMMUTABLE, /* volatility (not needed for agg) */ + BYTE_PCT, /* default cost values */ + PERBYTE_CPU, + PERCALL_CPU, + OUTIN_RATIO, + 1, /* parameterCount */ + fnArgs); /* parameterTypes */ + + /* + * Okay to create the pg_aggregate entry. + */ + /* initialize nulls and values */ for (i = 0; i < Natts_pg_aggregate; i++) { nulls[i] = ' '; values[i] = (Datum) NULL; } - namestrcpy(&aname, aggName); - values[Anum_pg_aggregate_aggname - 1] = NameGetDatum(&aname); - values[Anum_pg_aggregate_aggowner - 1] = Int32GetDatum(GetUserId()); + values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid); values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn); values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn); - values[Anum_pg_aggregate_aggbasetype - 1] = ObjectIdGetDatum(aggBaseType); values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType); - values[Anum_pg_aggregate_aggfinaltype - 1] = ObjectIdGetDatum(finaltype); - if (agginitval) values[Anum_pg_aggregate_agginitval - 1] = DirectFunctionCall1(textin, CStringGetDatum(agginitval)); @@ -155,12 +173,9 @@ AggregateCreate(const char *aggName, aggdesc = heap_openr(AggregateRelationName, RowExclusiveLock); tupDesc = aggdesc->rd_att; - if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc, - values, - nulls))) - elog(ERROR, "AggregateCreate: heap_formtuple failed"); - if (!OidIsValid(heap_insert(aggdesc, tup))) - elog(ERROR, "AggregateCreate: heap_insert failed"); + + tup = heap_formtuple(tupDesc, values, nulls); + heap_insert(aggdesc, tup); if (RelationGetForm(aggdesc)->relhasindex) { @@ -173,62 +188,3 @@ AggregateCreate(const char *aggName, heap_close(aggdesc, RowExclusiveLock); } - -Datum -AggNameGetInitVal(char *aggName, Oid basetype, bool *isNull) -{ - HeapTuple tup; - Oid transtype, - typinput, - typelem; - Datum textInitVal; - char *strInitVal; - Datum initVal; - - Assert(PointerIsValid(aggName)); - Assert(PointerIsValid(isNull)); - - tup = SearchSysCache(AGGNAME, - PointerGetDatum(aggName), - ObjectIdGetDatum(basetype), - 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "AggNameGetInitVal: cache lookup failed for aggregate '%s'", - aggName); - transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype; - - /* - * initval is potentially null, so don't try to access it as a struct - * field. Must do it the hard way with SysCacheGetAttr. - */ - textInitVal = SysCacheGetAttr(AGGNAME, tup, - Anum_pg_aggregate_agginitval, - isNull); - if (*isNull) - { - ReleaseSysCache(tup); - return (Datum) 0; - } - - strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal)); - - ReleaseSysCache(tup); - - tup = SearchSysCache(TYPEOID, - ObjectIdGetDatum(transtype), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type %u", transtype); - - typinput = ((Form_pg_type) GETSTRUCT(tup))->typinput; - typelem = ((Form_pg_type) GETSTRUCT(tup))->typelem; - ReleaseSysCache(tup); - - initVal = OidFunctionCall3(typinput, - CStringGetDatum(strInitVal), - ObjectIdGetDatum(typelem), - Int32GetDatum(-1)); - - pfree(strInitVal); - return initVal; -} |
