LCOV - differential code coverage report
Current view: top level - src/backend/commands - aggregatecmds.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 86.1 % 180 155 25 155
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 2 2 2
Baseline: 16@8cea358b128 Branches: 58.5 % 236 138 98 138
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 86.1 % 180 155 25 155
Function coverage date bins:
(240..) days: 100.0 % 2 2 2
Branch coverage date bins:
(240..) days: 58.5 % 236 138 98 138

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * aggregatecmds.c
                                  4                 :                :  *
                                  5                 :                :  *    Routines for aggregate-manipulation commands
                                  6                 :                :  *
                                  7                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  8                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :                :  *
                                 10                 :                :  *
                                 11                 :                :  * IDENTIFICATION
                                 12                 :                :  *    src/backend/commands/aggregatecmds.c
                                 13                 :                :  *
                                 14                 :                :  * DESCRIPTION
                                 15                 :                :  *    The "DefineFoo" routines take the parse tree and pick out the
                                 16                 :                :  *    appropriate arguments/flags, passing the results to the
                                 17                 :                :  *    corresponding "FooDefine" routines (in src/catalog) that do
                                 18                 :                :  *    the actual catalog-munging.  These routines also verify permission
                                 19                 :                :  *    of the user to execute the command.
                                 20                 :                :  *
                                 21                 :                :  *-------------------------------------------------------------------------
                                 22                 :                :  */
                                 23                 :                : #include "postgres.h"
                                 24                 :                : 
                                 25                 :                : #include "catalog/namespace.h"
                                 26                 :                : #include "catalog/pg_aggregate.h"
                                 27                 :                : #include "catalog/pg_namespace.h"
                                 28                 :                : #include "catalog/pg_proc.h"
                                 29                 :                : #include "catalog/pg_type.h"
                                 30                 :                : #include "commands/defrem.h"
                                 31                 :                : #include "miscadmin.h"
                                 32                 :                : #include "parser/parse_type.h"
                                 33                 :                : #include "utils/acl.h"
                                 34                 :                : #include "utils/builtins.h"
                                 35                 :                : #include "utils/lsyscache.h"
                                 36                 :                : 
                                 37                 :                : 
                                 38                 :                : static char extractModify(DefElem *defel);
                                 39                 :                : 
                                 40                 :                : 
                                 41                 :                : /*
                                 42                 :                :  *  DefineAggregate
                                 43                 :                :  *
                                 44                 :                :  * "oldstyle" signals the old (pre-8.2) style where the aggregate input type
                                 45                 :                :  * is specified by a BASETYPE element in the parameters.  Otherwise,
                                 46                 :                :  * "args" is a pair, whose first element is a list of FunctionParameter structs
                                 47                 :                :  * defining the agg's arguments (both direct and aggregated), and whose second
                                 48                 :                :  * element is an Integer node with the number of direct args, or -1 if this
                                 49                 :                :  * isn't an ordered-set aggregate.
                                 50                 :                :  * "parameters" is a list of DefElem representing the agg's definition clauses.
                                 51                 :                :  */
                                 52                 :                : ObjectAddress
 1853 rhodiumtoad@postgres       53                 :CBC         452 : DefineAggregate(ParseState *pstate,
                                 54                 :                :                 List *name,
                                 55                 :                :                 List *args,
                                 56                 :                :                 bool oldstyle,
                                 57                 :                :                 List *parameters,
                                 58                 :                :                 bool replace)
                                 59                 :                : {
                                 60                 :                :     char       *aggName;
                                 61                 :                :     Oid         aggNamespace;
                                 62                 :                :     AclResult   aclresult;
 3765 tgl@sss.pgh.pa.us          63                 :            452 :     char        aggKind = AGGKIND_NORMAL;
 8035                            64                 :            452 :     List       *transfuncName = NIL;
                                 65                 :            452 :     List       *finalfuncName = NIL;
 3007 rhaas@postgresql.org       66                 :            452 :     List       *combinefuncName = NIL;
 2938                            67                 :            452 :     List       *serialfuncName = NIL;
                                 68                 :            452 :     List       *deserialfuncName = NIL;
 3655 tgl@sss.pgh.pa.us          69                 :            452 :     List       *mtransfuncName = NIL;
                                 70                 :            452 :     List       *minvtransfuncName = NIL;
                                 71                 :            452 :     List       *mfinalfuncName = NIL;
 3644                            72                 :            452 :     bool        finalfuncExtraArgs = false;
                                 73                 :            452 :     bool        mfinalfuncExtraArgs = false;
 2374                            74                 :            452 :     char        finalfuncModify = 0;
                                 75                 :            452 :     char        mfinalfuncModify = 0;
 6942                            76                 :            452 :     List       *sortoperatorName = NIL;
 8035                            77                 :            452 :     TypeName   *baseType = NULL;
                                 78                 :            452 :     TypeName   *transType = NULL;
 3655                            79                 :            452 :     TypeName   *mtransType = NULL;
 3802                            80                 :            452 :     int32       transSpace = 0;
 3655                            81                 :            452 :     int32       mtransSpace = 0;
 8035                            82                 :            452 :     char       *initval = NULL;
 3655                            83                 :            452 :     char       *minitval = NULL;
 2931 rhaas@postgresql.org       84                 :            452 :     char       *parallel = NULL;
                                 85                 :                :     int         numArgs;
 3765 tgl@sss.pgh.pa.us          86                 :            452 :     int         numDirectArgs = 0;
                                 87                 :                :     oidvector  *parameterTypes;
                                 88                 :                :     ArrayType  *allParameterTypes;
                                 89                 :                :     ArrayType  *parameterModes;
                                 90                 :                :     ArrayType  *parameterNames;
                                 91                 :                :     List       *parameterDefaults;
                                 92                 :                :     Oid         variadicArgType;
                                 93                 :                :     Oid         transTypeId;
 3655                            94                 :            452 :     Oid         mtransTypeId = InvalidOid;
                                 95                 :                :     char        transTypeType;
                                 96                 :            452 :     char        mtransTypeType = 0;
 2931 rhaas@postgresql.org       97                 :            452 :     char        proparallel = PROPARALLEL_UNSAFE;
                                 98                 :                :     ListCell   *pl;
                                 99                 :                : 
                                100                 :                :     /* Convert list of names to a name and namespace */
 6574 tgl@sss.pgh.pa.us         101                 :            452 :     aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName);
                                102                 :                : 
                                103                 :                :     /* Check we have creation rights in target namespace */
  518 peter@eisentraut.org      104                 :            452 :     aclresult = object_aclcheck(NamespaceRelationId, aggNamespace, GetUserId(), ACL_CREATE);
 8023 tgl@sss.pgh.pa.us         105         [ -  + ]:            452 :     if (aclresult != ACLCHECK_OK)
 2325 peter_e@gmx.net           106                 :UBC           0 :         aclcheck_error(aclresult, OBJECT_SCHEMA,
 7562 tgl@sss.pgh.pa.us         107                 :              0 :                        get_namespace_name(aggNamespace));
                                108                 :                : 
                                109                 :                :     /* Deconstruct the output of the aggr_args grammar production */
 3765 tgl@sss.pgh.pa.us         110         [ +  + ]:CBC         452 :     if (!oldstyle)
                                111                 :                :     {
                                112         [ -  + ]:            271 :         Assert(list_length(args) == 2);
                                113                 :            271 :         numDirectArgs = intVal(lsecond(args));
                                114         [ +  + ]:            271 :         if (numDirectArgs >= 0)
                                115                 :             11 :             aggKind = AGGKIND_ORDERED_SET;
                                116                 :                :         else
                                117                 :            260 :             numDirectArgs = 0;
 2561                           118                 :            271 :         args = linitial_node(List, args);
                                119                 :                :     }
                                120                 :                : 
                                121                 :                :     /* Examine aggregate's definition clauses */
 8035                           122   [ +  -  +  +  :           2228 :     foreach(pl, parameters)
                                              +  + ]
                                123                 :                :     {
 2561                           124                 :           1776 :         DefElem    *defel = lfirst_node(DefElem, pl);
                                125                 :                : 
                                126                 :                :         /*
                                127                 :                :          * sfunc1, stype1, and initcond1 are accepted as obsolete spellings
                                128                 :                :          * for sfunc, stype, initcond.
                                129                 :                :          */
 2270                           130         [ +  + ]:           1776 :         if (strcmp(defel->defname, "sfunc") == 0)
 8035                           131                 :            431 :             transfuncName = defGetQualifiedName(defel);
 2270                           132         [ +  + ]:           1345 :         else if (strcmp(defel->defname, "sfunc1") == 0)
 8035                           133                 :             15 :             transfuncName = defGetQualifiedName(defel);
 2270                           134         [ +  + ]:           1330 :         else if (strcmp(defel->defname, "finalfunc") == 0)
 8035                           135                 :            194 :             finalfuncName = defGetQualifiedName(defel);
 2270                           136         [ +  + ]:           1136 :         else if (strcmp(defel->defname, "combinefunc") == 0)
 3007 rhaas@postgresql.org      137                 :             16 :             combinefuncName = defGetQualifiedName(defel);
 2270 tgl@sss.pgh.pa.us         138         [ +  + ]:           1120 :         else if (strcmp(defel->defname, "serialfunc") == 0)
 2938 rhaas@postgresql.org      139                 :             18 :             serialfuncName = defGetQualifiedName(defel);
 2270 tgl@sss.pgh.pa.us         140         [ +  + ]:           1102 :         else if (strcmp(defel->defname, "deserialfunc") == 0)
 2938 rhaas@postgresql.org      141                 :             15 :             deserialfuncName = defGetQualifiedName(defel);
 2270 tgl@sss.pgh.pa.us         142         [ +  + ]:           1087 :         else if (strcmp(defel->defname, "msfunc") == 0)
 3655                           143                 :             30 :             mtransfuncName = defGetQualifiedName(defel);
 2270                           144         [ +  + ]:           1057 :         else if (strcmp(defel->defname, "minvfunc") == 0)
 3655                           145                 :             30 :             minvtransfuncName = defGetQualifiedName(defel);
 2270                           146         [ -  + ]:           1027 :         else if (strcmp(defel->defname, "mfinalfunc") == 0)
 3655 tgl@sss.pgh.pa.us         147                 :UBC           0 :             mfinalfuncName = defGetQualifiedName(defel);
 2270 tgl@sss.pgh.pa.us         148         [ +  + ]:CBC        1027 :         else if (strcmp(defel->defname, "finalfunc_extra") == 0)
 3644                           149                 :              8 :             finalfuncExtraArgs = defGetBoolean(defel);
 2270                           150         [ -  + ]:           1019 :         else if (strcmp(defel->defname, "mfinalfunc_extra") == 0)
 3644 tgl@sss.pgh.pa.us         151                 :UBC           0 :             mfinalfuncExtraArgs = defGetBoolean(defel);
 2270 tgl@sss.pgh.pa.us         152         [ +  + ]:CBC        1019 :         else if (strcmp(defel->defname, "finalfunc_modify") == 0)
 2374                           153                 :             10 :             finalfuncModify = extractModify(defel);
 2270                           154         [ -  + ]:           1009 :         else if (strcmp(defel->defname, "mfinalfunc_modify") == 0)
 2374 tgl@sss.pgh.pa.us         155                 :UBC           0 :             mfinalfuncModify = extractModify(defel);
 2270 tgl@sss.pgh.pa.us         156         [ +  + ]:CBC        1009 :         else if (strcmp(defel->defname, "sortop") == 0)
 6942                           157                 :              4 :             sortoperatorName = defGetQualifiedName(defel);
 2270                           158         [ +  + ]:           1005 :         else if (strcmp(defel->defname, "basetype") == 0)
 8035                           159                 :            175 :             baseType = defGetTypeName(defel);
 2270                           160         [ +  + ]:            830 :         else if (strcmp(defel->defname, "hypothetical") == 0)
                                161                 :                :         {
 3765                           162         [ +  - ]:              4 :             if (defGetBoolean(defel))
                                163                 :                :             {
                                164         [ -  + ]:              4 :                 if (aggKind == AGGKIND_NORMAL)
 3765 tgl@sss.pgh.pa.us         165         [ #  # ]:UBC           0 :                     ereport(ERROR,
                                166                 :                :                             (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                167                 :                :                              errmsg("only ordered-set aggregates can be hypothetical")));
 3765 tgl@sss.pgh.pa.us         168                 :CBC           4 :                 aggKind = AGGKIND_HYPOTHETICAL;
                                169                 :                :             }
                                170                 :                :         }
 2270                           171         [ +  + ]:            826 :         else if (strcmp(defel->defname, "stype") == 0)
 8035                           172                 :            431 :             transType = defGetTypeName(defel);
 2270                           173         [ +  + ]:            395 :         else if (strcmp(defel->defname, "stype1") == 0)
 8035                           174                 :             15 :             transType = defGetTypeName(defel);
 2270                           175         [ +  + ]:            380 :         else if (strcmp(defel->defname, "sspace") == 0)
 3802                           176                 :              4 :             transSpace = defGetInt32(defel);
 2270                           177         [ +  + ]:            376 :         else if (strcmp(defel->defname, "mstype") == 0)
 3655                           178                 :             30 :             mtransType = defGetTypeName(defel);
 2270                           179         [ -  + ]:            346 :         else if (strcmp(defel->defname, "msspace") == 0)
 3655 tgl@sss.pgh.pa.us         180                 :UBC           0 :             mtransSpace = defGetInt32(defel);
 2270 tgl@sss.pgh.pa.us         181         [ +  + ]:CBC         346 :         else if (strcmp(defel->defname, "initcond") == 0)
 8035                           182                 :            279 :             initval = defGetString(defel);
 2270                           183         [ +  + ]:             67 :         else if (strcmp(defel->defname, "initcond1") == 0)
 8035                           184                 :              9 :             initval = defGetString(defel);
 2270                           185         [ +  + ]:             58 :         else if (strcmp(defel->defname, "minitcond") == 0)
 3655                           186                 :              8 :             minitval = defGetString(defel);
 2270                           187         [ +  + ]:             50 :         else if (strcmp(defel->defname, "parallel") == 0)
 2931 rhaas@postgresql.org      188                 :             17 :             parallel = defGetString(defel);
                                189                 :                :         else
 7574 tgl@sss.pgh.pa.us         190         [ +  - ]:             33 :             ereport(WARNING,
                                191                 :                :                     (errcode(ERRCODE_SYNTAX_ERROR),
                                192                 :                :                      errmsg("aggregate attribute \"%s\" not recognized",
                                193                 :                :                             defel->defname)));
                                194                 :                :     }
                                195                 :                : 
                                196                 :                :     /*
                                197                 :                :      * make sure we have our required definitions
                                198                 :                :      */
 8035                           199         [ +  + ]:            452 :     if (transType == NULL)
 7574                           200         [ +  - ]:              6 :         ereport(ERROR,
                                201                 :                :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                202                 :                :                  errmsg("aggregate stype must be specified")));
 8035                           203         [ -  + ]:            446 :     if (transfuncName == NIL)
 7574 tgl@sss.pgh.pa.us         204         [ #  # ]:UBC           0 :         ereport(ERROR,
                                205                 :                :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                206                 :                :                  errmsg("aggregate sfunc must be specified")));
                                207                 :                : 
                                208                 :                :     /*
                                209                 :                :      * if mtransType is given, mtransfuncName and minvtransfuncName must be as
                                210                 :                :      * well; if not, then none of the moving-aggregate options should have
                                211                 :                :      * been given.
                                212                 :                :      */
 3655 tgl@sss.pgh.pa.us         213         [ +  + ]:CBC         446 :     if (mtransType != NULL)
                                214                 :                :     {
                                215         [ -  + ]:             30 :         if (mtransfuncName == NIL)
 3655 tgl@sss.pgh.pa.us         216         [ #  # ]:UBC           0 :             ereport(ERROR,
                                217                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                218                 :                :                      errmsg("aggregate msfunc must be specified when mstype is specified")));
 3655 tgl@sss.pgh.pa.us         219         [ -  + ]:CBC          30 :         if (minvtransfuncName == NIL)
 3655 tgl@sss.pgh.pa.us         220         [ #  # ]:UBC           0 :             ereport(ERROR,
                                221                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                222                 :                :                      errmsg("aggregate minvfunc must be specified when mstype is specified")));
                                223                 :                :     }
                                224                 :                :     else
                                225                 :                :     {
 3655 tgl@sss.pgh.pa.us         226         [ -  + ]:CBC         416 :         if (mtransfuncName != NIL)
 3655 tgl@sss.pgh.pa.us         227         [ #  # ]:UBC           0 :             ereport(ERROR,
                                228                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                229                 :                :                      errmsg("aggregate msfunc must not be specified without mstype")));
 3655 tgl@sss.pgh.pa.us         230         [ -  + ]:CBC         416 :         if (minvtransfuncName != NIL)
 3655 tgl@sss.pgh.pa.us         231         [ #  # ]:UBC           0 :             ereport(ERROR,
                                232                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                233                 :                :                      errmsg("aggregate minvfunc must not be specified without mstype")));
 3655 tgl@sss.pgh.pa.us         234         [ -  + ]:CBC         416 :         if (mfinalfuncName != NIL)
 3655 tgl@sss.pgh.pa.us         235         [ #  # ]:UBC           0 :             ereport(ERROR,
                                236                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                237                 :                :                      errmsg("aggregate mfinalfunc must not be specified without mstype")));
 3655 tgl@sss.pgh.pa.us         238         [ -  + ]:CBC         416 :         if (mtransSpace != 0)
 3655 tgl@sss.pgh.pa.us         239         [ #  # ]:UBC           0 :             ereport(ERROR,
                                240                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                241                 :                :                      errmsg("aggregate msspace must not be specified without mstype")));
 3655 tgl@sss.pgh.pa.us         242         [ -  + ]:CBC         416 :         if (minitval != NULL)
 3655 tgl@sss.pgh.pa.us         243         [ #  # ]:UBC           0 :             ereport(ERROR,
                                244                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                245                 :                :                      errmsg("aggregate minitcond must not be specified without mstype")));
                                246                 :                :     }
                                247                 :                : 
                                248                 :                :     /*
                                249                 :                :      * Default values for modify flags can only be determined once we know the
                                250                 :                :      * aggKind.
                                251                 :                :      */
 2374 tgl@sss.pgh.pa.us         252         [ +  + ]:CBC         446 :     if (finalfuncModify == 0)
                                253         [ +  + ]:            436 :         finalfuncModify = (aggKind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
                                254         [ +  - ]:            446 :     if (mfinalfuncModify == 0)
                                255         [ +  + ]:            446 :         mfinalfuncModify = (aggKind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
                                256                 :                : 
                                257                 :                :     /*
                                258                 :                :      * look up the aggregate's input datatype(s).
                                259                 :                :      */
 6574                           260         [ +  + ]:            446 :     if (oldstyle)
                                261                 :                :     {
                                262                 :                :         /*
                                263                 :                :          * Old style: use basetype parameter.  This supports aggregates of
                                264                 :                :          * zero or one input, with input type ANY meaning zero inputs.
                                265                 :                :          *
                                266                 :                :          * Historically we allowed the command to look like basetype = 'ANY'
                                267                 :                :          * so we must do a case-insensitive comparison for the name ANY. Ugh.
                                268                 :                :          */
                                269                 :                :         Oid         aggArgTypes[1];
                                270                 :                : 
                                271         [ +  + ]:            178 :         if (baseType == NULL)
                                272         [ +  - ]:              3 :             ereport(ERROR,
                                273                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                274                 :                :                      errmsg("aggregate input type must be specified")));
                                275                 :                : 
                                276         [ +  + ]:            175 :         if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0)
                                277                 :                :         {
 6471                           278                 :              3 :             numArgs = 0;
 3876                           279                 :              3 :             aggArgTypes[0] = InvalidOid;
                                280                 :                :         }
                                281                 :                :         else
                                282                 :                :         {
 6471                           283                 :            172 :             numArgs = 1;
 4920 peter_e@gmx.net           284                 :            172 :             aggArgTypes[0] = typenameTypeId(NULL, baseType);
                                285                 :                :         }
 3876 tgl@sss.pgh.pa.us         286                 :            175 :         parameterTypes = buildoidvector(aggArgTypes, numArgs);
                                287                 :            175 :         allParameterTypes = NULL;
                                288                 :            175 :         parameterModes = NULL;
                                289                 :            175 :         parameterNames = NULL;
                                290                 :            175 :         parameterDefaults = NIL;
 3765                           291                 :            175 :         variadicArgType = InvalidOid;
                                292                 :                :     }
                                293                 :                :     else
                                294                 :                :     {
                                295                 :                :         /*
                                296                 :                :          * New style: args is a list of FunctionParameters (possibly zero of
                                297                 :                :          * 'em).  We share functioncmds.c's code for processing them.
                                298                 :                :          */
                                299                 :                :         Oid         requiredResultType;
                                300                 :                : 
 6574                           301         [ -  + ]:            268 :         if (baseType != NULL)
 6574 tgl@sss.pgh.pa.us         302         [ #  # ]:UBC           0 :             ereport(ERROR,
                                303                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                304                 :                :                      errmsg("basetype is redundant with aggregate input type specification")));
                                305                 :                : 
 6471 tgl@sss.pgh.pa.us         306                 :CBC         268 :         numArgs = list_length(args);
 2777 peter_e@gmx.net           307                 :            268 :         interpret_function_parameter_list(pstate,
                                308                 :                :                                           args,
                                309                 :                :                                           InvalidOid,
                                310                 :                :                                           OBJECT_AGGREGATE,
                                311                 :                :                                           &parameterTypes,
                                312                 :                :                                           NULL,
                                313                 :                :                                           &allParameterTypes,
                                314                 :                :                                           &parameterModes,
                                315                 :                :                                           &parameterNames,
                                316                 :                :                                           NULL,
                                317                 :                :                                           &parameterDefaults,
                                318                 :                :                                           &variadicArgType,
                                319                 :                :                                           &requiredResultType);
                                320                 :                :         /* Parameter defaults are not currently allowed by the grammar */
 3876 tgl@sss.pgh.pa.us         321         [ -  + ]:            265 :         Assert(parameterDefaults == NIL);
                                322                 :                :         /* There shouldn't have been any OUT parameters, either */
                                323         [ -  + ]:            265 :         Assert(requiredResultType == InvalidOid);
                                324                 :                :     }
                                325                 :                : 
                                326                 :                :     /*
                                327                 :                :      * look up the aggregate's transtype.
                                328                 :                :      *
                                329                 :                :      * transtype can't be a pseudo-type, since we need to be able to store
                                330                 :                :      * values of the transtype.  However, we can allow polymorphic transtype
                                331                 :                :      * in some cases (AggregateCreate will check).  Also, we allow "internal"
                                332                 :                :      * for functions that want to pass pointers to private data structures;
                                333                 :                :      * but allow that only to superusers, since you could crash the system (or
                                334                 :                :      * worse) by connecting up incompatible internal-using functions in an
                                335                 :                :      * aggregate.
                                336                 :                :      */
 4920 peter_e@gmx.net           337                 :            440 :     transTypeId = typenameTypeId(NULL, transType);
 4210 tgl@sss.pgh.pa.us         338                 :            440 :     transTypeType = get_typtype(transTypeId);
                                339   [ +  +  +  + ]:            440 :     if (transTypeType == TYPTYPE_PSEUDO &&
 6222                           340   [ +  +  +  -  :            140 :         !IsPolymorphicType(transTypeId))
                                     +  -  +  -  +  
                                     -  +  +  +  -  
                                     +  -  +  -  +  
                                                 - ]
                                341                 :                :     {
 5630                           342   [ +  -  +  - ]:             29 :         if (transTypeId == INTERNALOID && superuser())
                                343                 :                :              /* okay */ ;
                                344                 :                :         else
 5630 tgl@sss.pgh.pa.us         345         [ #  # ]:UBC           0 :             ereport(ERROR,
                                346                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                347                 :                :                      errmsg("aggregate transition data type cannot be %s",
                                348                 :                :                             format_type_be(transTypeId))));
                                349                 :                :     }
                                350                 :                : 
 2853 tgl@sss.pgh.pa.us         351   [ +  +  +  + ]:CBC         440 :     if (serialfuncName && deserialfuncName)
                                352                 :                :     {
                                353                 :                :         /*
                                354                 :                :          * Serialization is only needed/allowed for transtype INTERNAL.
                                355                 :                :          */
 2938 rhaas@postgresql.org      356         [ -  + ]:             15 :         if (transTypeId != INTERNALOID)
 2938 rhaas@postgresql.org      357         [ #  # ]:UBC           0 :             ereport(ERROR,
                                358                 :                :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                359                 :                :                      errmsg("serialization functions may be specified only when the aggregate transition data type is %s",
                                360                 :                :                             format_type_be(INTERNALOID))));
                                361                 :                :     }
 2853 tgl@sss.pgh.pa.us         362   [ +  +  -  + ]:CBC         425 :     else if (serialfuncName || deserialfuncName)
                                363                 :                :     {
                                364                 :                :         /*
                                365                 :                :          * Cannot specify one function without the other.
                                366                 :                :          */
                                367         [ +  - ]:              3 :         ereport(ERROR,
                                368                 :                :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                369                 :                :                  errmsg("must specify both or neither of serialization and deserialization functions")));
                                370                 :                :     }
                                371                 :                : 
                                372                 :                :     /*
                                373                 :                :      * If a moving-aggregate transtype is specified, look that up.  Same
                                374                 :                :      * restrictions as for transtype.
                                375                 :                :      */
 3655                           376         [ +  + ]:            437 :     if (mtransType)
                                377                 :                :     {
                                378                 :             30 :         mtransTypeId = typenameTypeId(NULL, mtransType);
                                379                 :             30 :         mtransTypeType = get_typtype(mtransTypeId);
                                380   [ -  +  -  - ]:             30 :         if (mtransTypeType == TYPTYPE_PSEUDO &&
 3655 tgl@sss.pgh.pa.us         381   [ #  #  #  #  :UBC           0 :             !IsPolymorphicType(mtransTypeId))
                                     #  #  #  #  #  
                                     #  #  #  #  #  
                                     #  #  #  #  #  
                                                 # ]
                                382                 :                :         {
                                383   [ #  #  #  # ]:              0 :             if (mtransTypeId == INTERNALOID && superuser())
                                384                 :                :                  /* okay */ ;
                                385                 :                :             else
                                386         [ #  # ]:              0 :                 ereport(ERROR,
                                387                 :                :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                388                 :                :                          errmsg("aggregate transition data type cannot be %s",
                                389                 :                :                                 format_type_be(mtransTypeId))));
                                390                 :                :         }
                                391                 :                :     }
                                392                 :                : 
                                393                 :                :     /*
                                394                 :                :      * If we have an initval, and it's not for a pseudotype (particularly a
                                395                 :                :      * polymorphic type), make sure it's acceptable to the type's input
                                396                 :                :      * function.  We will store the initval as text, because the input
                                397                 :                :      * function isn't necessarily immutable (consider "now" for timestamp),
                                398                 :                :      * and we want to use the runtime not creation-time interpretation of the
                                399                 :                :      * value.  However, if it's an incorrect value it seems much more
                                400                 :                :      * user-friendly to complain at CREATE AGGREGATE time.
                                401                 :                :      */
 4210 tgl@sss.pgh.pa.us         402   [ +  +  +  + ]:CBC         437 :     if (initval && transTypeType != TYPTYPE_PSEUDO)
                                403                 :                :     {
                                404                 :                :         Oid         typinput,
                                405                 :                :                     typioparam;
                                406                 :                : 
                                407                 :            185 :         getTypeInputInfo(transTypeId, &typinput, &typioparam);
                                408                 :            185 :         (void) OidInputFunctionCall(typinput, initval, typioparam, -1);
                                409                 :                :     }
                                410                 :                : 
                                411                 :                :     /*
                                412                 :                :      * Likewise for moving-aggregate initval.
                                413                 :                :      */
 3655                           414   [ +  +  +  - ]:            437 :     if (minitval && mtransTypeType != TYPTYPE_PSEUDO)
                                415                 :                :     {
                                416                 :                :         Oid         typinput,
                                417                 :                :                     typioparam;
                                418                 :                : 
                                419                 :              8 :         getTypeInputInfo(mtransTypeId, &typinput, &typioparam);
                                420                 :              8 :         (void) OidInputFunctionCall(typinput, minitval, typioparam, -1);
                                421                 :                :     }
                                422                 :                : 
 2931 rhaas@postgresql.org      423         [ +  + ]:            437 :     if (parallel)
                                424                 :                :     {
 2270 tgl@sss.pgh.pa.us         425         [ +  + ]:             17 :         if (strcmp(parallel, "safe") == 0)
 2931 rhaas@postgresql.org      426                 :             14 :             proparallel = PROPARALLEL_SAFE;
 2270 tgl@sss.pgh.pa.us         427         [ -  + ]:              3 :         else if (strcmp(parallel, "restricted") == 0)
 2931 rhaas@postgresql.org      428                 :UBC           0 :             proparallel = PROPARALLEL_RESTRICTED;
 2270 tgl@sss.pgh.pa.us         429         [ -  + ]:CBC           3 :         else if (strcmp(parallel, "unsafe") == 0)
 2931 rhaas@postgresql.org      430                 :UBC           0 :             proparallel = PROPARALLEL_UNSAFE;
                                431                 :                :         else
 2931 rhaas@postgresql.org      432         [ +  - ]:CBC           3 :             ereport(ERROR,
                                433                 :                :                     (errcode(ERRCODE_SYNTAX_ERROR),
                                434                 :                :                      errmsg("parameter \"parallel\" must be SAFE, RESTRICTED, or UNSAFE")));
                                435                 :                :     }
                                436                 :                : 
                                437                 :                :     /*
                                438                 :                :      * Most of the argument-checking is done inside of AggregateCreate
                                439                 :                :      */
 2489 tgl@sss.pgh.pa.us         440                 :            434 :     return AggregateCreate(aggName, /* aggregate name */
                                441                 :                :                            aggNamespace,    /* namespace */
                                442                 :                :                            replace,
                                443                 :                :                            aggKind,
                                444                 :                :                            numArgs,
                                445                 :                :                            numDirectArgs,
                                446                 :                :                            parameterTypes,
                                447                 :                :                            PointerGetDatum(allParameterTypes),
                                448                 :                :                            PointerGetDatum(parameterModes),
                                449                 :                :                            PointerGetDatum(parameterNames),
                                450                 :                :                            parameterDefaults,
                                451                 :                :                            variadicArgType,
                                452                 :                :                            transfuncName,   /* step function name */
                                453                 :                :                            finalfuncName,   /* final function name */
                                454                 :                :                            combinefuncName, /* combine function name */
                                455                 :                :                            serialfuncName,  /* serial function name */
                                456                 :                :                            deserialfuncName,    /* deserial function name */
                                457                 :                :                            mtransfuncName,  /* fwd trans function name */
                                458                 :                :                            minvtransfuncName,   /* inv trans function name */
                                459                 :                :                            mfinalfuncName,  /* final function name */
                                460                 :                :                            finalfuncExtraArgs,
                                461                 :                :                            mfinalfuncExtraArgs,
                                462                 :                :                            finalfuncModify,
                                463                 :                :                            mfinalfuncModify,
                                464                 :                :                            sortoperatorName,    /* sort operator name */
                                465                 :                :                            transTypeId, /* transition data type */
                                466                 :                :                            transSpace,  /* transition space */
                                467                 :                :                            mtransTypeId,    /* transition data type */
                                468                 :                :                            mtransSpace, /* transition space */
                                469                 :                :                            initval, /* initial condition */
                                470                 :                :                            minitval,    /* initial condition */
                                471                 :                :                            proparallel);    /* parallel safe? */
                                472                 :                : }
                                473                 :                : 
                                474                 :                : /*
                                475                 :                :  * Convert the string form of [m]finalfunc_modify to the catalog representation
                                476                 :                :  */
                                477                 :                : static char
 2374                           478                 :             10 : extractModify(DefElem *defel)
                                479                 :                : {
                                480                 :             10 :     char       *val = defGetString(defel);
                                481                 :                : 
                                482         [ -  + ]:             10 :     if (strcmp(val, "read_only") == 0)
 2374 tgl@sss.pgh.pa.us         483                 :UBC           0 :         return AGGMODIFY_READ_ONLY;
 2155 tgl@sss.pgh.pa.us         484         [ +  + ]:CBC          10 :     if (strcmp(val, "shareable") == 0)
                                485                 :              7 :         return AGGMODIFY_SHAREABLE;
 2374                           486         [ +  - ]:              3 :     if (strcmp(val, "read_write") == 0)
                                487                 :              3 :         return AGGMODIFY_READ_WRITE;
 2374 tgl@sss.pgh.pa.us         488         [ #  # ]:UBC           0 :     ereport(ERROR,
                                489                 :                :             (errcode(ERRCODE_SYNTAX_ERROR),
                                490                 :                :              errmsg("parameter \"%s\" must be READ_ONLY, SHAREABLE, or READ_WRITE",
                                491                 :                :                     defel->defname)));
                                492                 :                :     return 0;                   /* keep compiler quiet */
                                493                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622