00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "postgres.h"
00024
00025 #include "access/heapam.h"
00026 #include "access/htup_details.h"
00027 #include "catalog/dependency.h"
00028 #include "catalog/indexing.h"
00029 #include "catalog/pg_aggregate.h"
00030 #include "catalog/pg_proc.h"
00031 #include "catalog/pg_type.h"
00032 #include "commands/alter.h"
00033 #include "commands/defrem.h"
00034 #include "miscadmin.h"
00035 #include "parser/parse_func.h"
00036 #include "parser/parse_type.h"
00037 #include "utils/acl.h"
00038 #include "utils/builtins.h"
00039 #include "utils/lsyscache.h"
00040 #include "utils/syscache.h"
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 Oid
00051 DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
00052 {
00053 char *aggName;
00054 Oid aggNamespace;
00055 AclResult aclresult;
00056 List *transfuncName = NIL;
00057 List *finalfuncName = NIL;
00058 List *sortoperatorName = NIL;
00059 TypeName *baseType = NULL;
00060 TypeName *transType = NULL;
00061 char *initval = NULL;
00062 Oid *aggArgTypes;
00063 int numArgs;
00064 Oid transTypeId;
00065 char transTypeType;
00066 ListCell *pl;
00067
00068
00069 aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName);
00070
00071
00072 aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE);
00073 if (aclresult != ACLCHECK_OK)
00074 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00075 get_namespace_name(aggNamespace));
00076
00077 foreach(pl, parameters)
00078 {
00079 DefElem *defel = (DefElem *) lfirst(pl);
00080
00081
00082
00083
00084
00085 if (pg_strcasecmp(defel->defname, "sfunc") == 0)
00086 transfuncName = defGetQualifiedName(defel);
00087 else if (pg_strcasecmp(defel->defname, "sfunc1") == 0)
00088 transfuncName = defGetQualifiedName(defel);
00089 else if (pg_strcasecmp(defel->defname, "finalfunc") == 0)
00090 finalfuncName = defGetQualifiedName(defel);
00091 else if (pg_strcasecmp(defel->defname, "sortop") == 0)
00092 sortoperatorName = defGetQualifiedName(defel);
00093 else if (pg_strcasecmp(defel->defname, "basetype") == 0)
00094 baseType = defGetTypeName(defel);
00095 else if (pg_strcasecmp(defel->defname, "stype") == 0)
00096 transType = defGetTypeName(defel);
00097 else if (pg_strcasecmp(defel->defname, "stype1") == 0)
00098 transType = defGetTypeName(defel);
00099 else if (pg_strcasecmp(defel->defname, "initcond") == 0)
00100 initval = defGetString(defel);
00101 else if (pg_strcasecmp(defel->defname, "initcond1") == 0)
00102 initval = defGetString(defel);
00103 else
00104 ereport(WARNING,
00105 (errcode(ERRCODE_SYNTAX_ERROR),
00106 errmsg("aggregate attribute \"%s\" not recognized",
00107 defel->defname)));
00108 }
00109
00110
00111
00112
00113 if (transType == NULL)
00114 ereport(ERROR,
00115 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00116 errmsg("aggregate stype must be specified")));
00117 if (transfuncName == NIL)
00118 ereport(ERROR,
00119 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00120 errmsg("aggregate sfunc must be specified")));
00121
00122
00123
00124
00125 if (oldstyle)
00126 {
00127
00128
00129
00130
00131
00132
00133
00134 if (baseType == NULL)
00135 ereport(ERROR,
00136 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00137 errmsg("aggregate input type must be specified")));
00138
00139 if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0)
00140 {
00141 numArgs = 0;
00142 aggArgTypes = NULL;
00143 }
00144 else
00145 {
00146 numArgs = 1;
00147 aggArgTypes = (Oid *) palloc(sizeof(Oid));
00148 aggArgTypes[0] = typenameTypeId(NULL, baseType);
00149 }
00150 }
00151 else
00152 {
00153
00154
00155
00156 ListCell *lc;
00157 int i = 0;
00158
00159 if (baseType != NULL)
00160 ereport(ERROR,
00161 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00162 errmsg("basetype is redundant with aggregate input type specification")));
00163
00164 numArgs = list_length(args);
00165 aggArgTypes = (Oid *) palloc(sizeof(Oid) * numArgs);
00166 foreach(lc, args)
00167 {
00168 TypeName *curTypeName = (TypeName *) lfirst(lc);
00169
00170 aggArgTypes[i++] = typenameTypeId(NULL, curTypeName);
00171 }
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 transTypeId = typenameTypeId(NULL, transType);
00186 transTypeType = get_typtype(transTypeId);
00187 if (transTypeType == TYPTYPE_PSEUDO &&
00188 !IsPolymorphicType(transTypeId))
00189 {
00190 if (transTypeId == INTERNALOID && superuser())
00191 ;
00192 else
00193 ereport(ERROR,
00194 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00195 errmsg("aggregate transition data type cannot be %s",
00196 format_type_be(transTypeId))));
00197 }
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 if (initval && transTypeType != TYPTYPE_PSEUDO)
00209 {
00210 Oid typinput,
00211 typioparam;
00212
00213 getTypeInputInfo(transTypeId, &typinput, &typioparam);
00214 (void) OidInputFunctionCall(typinput, initval, typioparam, -1);
00215 }
00216
00217
00218
00219
00220 return AggregateCreate(aggName,
00221 aggNamespace,
00222 aggArgTypes,
00223 numArgs,
00224 transfuncName,
00225 finalfuncName,
00226 sortoperatorName,
00227 transTypeId,
00228 initval);
00229 }