LCOV - differential code coverage report
Current view: top level - src/backend/commands - operatorcmds.c (source / functions) Coverage Total Hit LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 91.5 % 211 193 9 9 2 83 8 100 16 82 2
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 5 5 5 5
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 8 8 8
Legend: Lines: hit not hit (240..) days: 91.1 % 203 185 9 9 2 83 100 16 81
Function coverage date bins:
(240..) days: 50.0 % 10 5 5 5

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * operatorcmds.c
                                  4                 :  *
                                  5                 :  *    Routines for operator manipulation commands
                                  6                 :  *
                                  7                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  8                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :  *
                                 10                 :  *
                                 11                 :  * IDENTIFICATION
                                 12                 :  *    src/backend/commands/operatorcmds.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                 :  * NOTES
                                 22                 :  *    These things must be defined and committed in the following order:
                                 23                 :  *      "create function":
                                 24                 :  *              input/output, recv/send functions
                                 25                 :  *      "create type":
                                 26                 :  *              type
                                 27                 :  *      "create operator":
                                 28                 :  *              operators
                                 29                 :  *
                                 30                 :  *-------------------------------------------------------------------------
                                 31                 :  */
                                 32                 : #include "postgres.h"
                                 33                 : 
                                 34                 : #include "access/htup_details.h"
                                 35                 : #include "access/table.h"
                                 36                 : #include "catalog/dependency.h"
                                 37                 : #include "catalog/indexing.h"
                                 38                 : #include "catalog/objectaccess.h"
                                 39                 : #include "catalog/pg_namespace.h"
                                 40                 : #include "catalog/pg_operator.h"
                                 41                 : #include "catalog/pg_proc.h"
                                 42                 : #include "catalog/pg_type.h"
                                 43                 : #include "commands/alter.h"
                                 44                 : #include "commands/defrem.h"
                                 45                 : #include "miscadmin.h"
                                 46                 : #include "parser/parse_func.h"
                                 47                 : #include "parser/parse_oper.h"
                                 48                 : #include "parser/parse_type.h"
                                 49                 : #include "utils/acl.h"
                                 50                 : #include "utils/builtins.h"
                                 51                 : #include "utils/lsyscache.h"
                                 52                 : #include "utils/rel.h"
                                 53                 : #include "utils/syscache.h"
                                 54                 : 
                                 55                 : static Oid  ValidateRestrictionEstimator(List *restrictionName);
                                 56                 : static Oid  ValidateJoinEstimator(List *joinName);
                                 57                 : 
                                 58                 : /*
                                 59                 :  * DefineOperator
                                 60                 :  *      this function extracts all the information from the
                                 61                 :  *      parameter list generated by the parser and then has
                                 62                 :  *      OperatorCreate() do all the actual work.
                                 63                 :  *
                                 64                 :  * 'parameters' is a list of DefElem
                                 65                 :  */
                                 66                 : ObjectAddress
 7664 tgl                        67 GIC         742 : DefineOperator(List *names, List *parameters)
                                 68                 : {
 7664 tgl                        69 ECB             :     char       *oprName;
                                 70                 :     Oid         oprNamespace;
                                 71                 :     AclResult   aclresult;
 2118 tgl                        72 GIC         742 :     bool        canMerge = false;   /* operator merges */
 5624 bruce                      73             742 :     bool        canHash = false;    /* operator hashes */
 2118 tgl                        74 CBC         742 :     List       *functionName = NIL; /* function for operator */
                                 75             742 :     TypeName   *typeName1 = NULL;   /* first type name */
                                 76             742 :     TypeName   *typeName2 = NULL;   /* second type name */
 7664                            77             742 :     Oid         typeId1 = InvalidOid;   /* types converted to OID */
                                 78             742 :     Oid         typeId2 = InvalidOid;
 4128 peter_e                    79 ECB             :     Oid         rettype;
 6385 bruce                      80 CBC         742 :     List       *commutatorName = NIL;   /* optional commutator operator name */
 2118 tgl                        81 GIC         742 :     List       *negatorName = NIL;  /* optional negator operator name */
 1698 peter_e                    82 CBC         742 :     List       *restrictionName = NIL;  /* optional restrict. sel. function */
                                 83             742 :     List       *joinName = NIL; /* optional join sel. function */
 5349 tgl                        84 ECB             :     Oid         functionOid;    /* functions converted to OID */
                                 85                 :     Oid         restrictionOid;
                                 86                 :     Oid         joinOid;
                                 87                 :     Oid         typeId[2];      /* to hold left and right arg */
                                 88                 :     int         nargs;
                                 89                 :     ListCell   *pl;
                                 90                 : 
                                 91                 :     /* Convert list of names to a name and namespace */
 7664 tgl                        92 GIC         742 :     oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
                                 93                 : 
 7652 tgl                        94 ECB             :     /* Check we have creation rights in target namespace */
  147 peter                      95 GNC         742 :     aclresult = object_aclcheck(NamespaceRelationId, oprNamespace, GetUserId(), ACL_CREATE);
 7652 tgl                        96 GIC         742 :     if (aclresult != ACLCHECK_OK)
 1954 peter_e                    97 CBC           3 :         aclcheck_error(aclresult, OBJECT_SCHEMA,
 7191 tgl                        98               3 :                        get_namespace_name(oprNamespace));
 7652 tgl                        99 ECB             : 
 7664                           100                 :     /*
                                101                 :      * loop over the definition list and extract the information we need.
                                102                 :      */
 7664 tgl                       103 GIC        4816 :     foreach(pl, parameters)
                                104                 :     {
 7664 tgl                       105 CBC        4083 :         DefElem    *defel = (DefElem *) lfirst(pl);
                                106                 : 
 1899                           107            4083 :         if (strcmp(defel->defname, "leftarg") == 0)
                                108                 :         {
 7664                           109             693 :             typeName1 = defGetTypeName(defel);
 7664 tgl                       110 GIC         693 :             if (typeName1->setof)
 7203 tgl                       111 CBC           3 :                 ereport(ERROR,
 7203 tgl                       112 ECB             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 2118                           113                 :                          errmsg("SETOF type not allowed for operator argument")));
                                114                 :         }
 1899 tgl                       115 GIC        3390 :         else if (strcmp(defel->defname, "rightarg") == 0)
                                116                 :         {
 7664 tgl                       117 CBC         727 :             typeName2 = defGetTypeName(defel);
 7664 tgl                       118 GIC         727 :             if (typeName2->setof)
 7203 tgl                       119 CBC           3 :                 ereport(ERROR,
 7203 tgl                       120 ECB             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 2118                           121                 :                          errmsg("SETOF type not allowed for operator argument")));
                                122                 :         }
                                123                 :         /* "function" and "procedure" are equivalent here */
 1698 peter_e                   124 GIC        2663 :         else if (strcmp(defel->defname, "function") == 0)
                                125              14 :             functionName = defGetQualifiedName(defel);
 1899 tgl                       126 CBC        2649 :         else if (strcmp(defel->defname, "procedure") == 0)
 7663                           127             713 :             functionName = defGetQualifiedName(defel);
 1899                           128            1936 :         else if (strcmp(defel->defname, "commutator") == 0)
 7663                           129             474 :             commutatorName = defGetQualifiedName(defel);
 1899                           130            1462 :         else if (strcmp(defel->defname, "negator") == 0)
 7663                           131             320 :             negatorName = defGetQualifiedName(defel);
 1899                           132            1142 :         else if (strcmp(defel->defname, "restrict") == 0)
 7663                           133             496 :             restrictionName = defGetQualifiedName(defel);
 1899                           134             646 :         else if (strcmp(defel->defname, "join") == 0)
 7663                           135             484 :             joinName = defGetQualifiedName(defel);
 1899                           136             162 :         else if (strcmp(defel->defname, "hashes") == 0)
 6904                           137              46 :             canHash = defGetBoolean(defel);
 1899                           138             116 :         else if (strcmp(defel->defname, "merges") == 0)
 6904                           139              70 :             canMerge = defGetBoolean(defel);
 5951 tgl                       140 ECB             :         /* These obsolete options are taken as meaning canMerge */
 1899 tgl                       141 CBC          46 :         else if (strcmp(defel->defname, "sort1") == 0)
 5951 tgl                       142 GIC           5 :             canMerge = true;
 1899 tgl                       143 CBC          41 :         else if (strcmp(defel->defname, "sort2") == 0)
 5951                           144               5 :             canMerge = true;
 1899                           145              36 :         else if (strcmp(defel->defname, "ltcmp") == 0)
 5951                           146               3 :             canMerge = true;
 1899                           147              33 :         else if (strcmp(defel->defname, "gtcmp") == 0)
 5951                           148               3 :             canMerge = true;
 7664 tgl                       149 ECB             :         else
 2826 heikki.linnakangas        150                 :         {
                                151                 :             /* WARNING, not ERROR, for historical backwards-compatibility */
 7203 tgl                       152 GIC          30 :             ereport(WARNING,
                                153                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
 7203 tgl                       154 ECB             :                      errmsg("operator attribute \"%s\" not recognized",
                                155                 :                             defel->defname)));
                                156                 :         }
                                157                 :     }
                                158                 : 
                                159                 :     /*
                                160                 :      * make sure we have our required definitions
                                161                 :      */
 7663 tgl                       162 GIC         733 :     if (functionName == NIL)
 7203                           163               6 :         ereport(ERROR,
 7203 tgl                       164 ECB             :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 1698 peter_e                   165                 :                  errmsg("operator function must be specified")));
                                166                 : 
                                167                 :     /* Transform type names to type OIDs */
 7664 tgl                       168 GIC         727 :     if (typeName1)
 4549 peter_e                   169             690 :         typeId1 = typenameTypeId(NULL, typeName1);
 7664 tgl                       170 CBC         727 :     if (typeName2)
 4549 peter_e                   171             721 :         typeId2 = typenameTypeId(NULL, typeName2);
 7664 tgl                       172 ECB             : 
  934                           173                 :     /*
                                174                 :      * If only the right argument is missing, the user is likely trying to
                                175                 :      * create a postfix operator, so give them a hint about why that does not
                                176                 :      * work.  But if both arguments are missing, do not mention postfix
                                177                 :      * operators, as the user most likely simply neglected to mention the
                                178                 :      * arguments.
                                179                 :      */
 5349 tgl                       180 GIC         727 :     if (!OidIsValid(typeId1) && !OidIsValid(typeId2))
                                181               3 :         ereport(ERROR,
 5349 tgl                       182 ECB             :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
  934                           183                 :                  errmsg("operator argument types must be specified")));
  934 tgl                       184 GIC         724 :     if (!OidIsValid(typeId2))
                                185               3 :         ereport(ERROR,
  934 tgl                       186 ECB             :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                187                 :                  errmsg("operator right argument type must be specified"),
                                188                 :                  errdetail("Postfix operators are not supported.")));
                                189                 : 
 4128 peter_e                   190 GIC         721 :     if (typeName1)
                                191                 :     {
  147 peter                     192 GNC         687 :         aclresult = object_aclcheck(TypeRelationId, typeId1, GetUserId(), ACL_USAGE);
 4128 peter_e                   193 GIC         687 :         if (aclresult != ACLCHECK_OK)
 3950 peter_e                   194 CBC           6 :             aclcheck_error_type(aclresult, typeId1);
 4128 peter_e                   195 ECB             :     }
                                196                 : 
 4128 peter_e                   197 GIC         715 :     if (typeName2)
                                198                 :     {
  147 peter                     199 GNC         715 :         aclresult = object_aclcheck(TypeRelationId, typeId2, GetUserId(), ACL_USAGE);
 4128 peter_e                   200 GIC         715 :         if (aclresult != ACLCHECK_OK)
 3950 peter_e                   201 CBC           3 :             aclcheck_error_type(aclresult, typeId2);
 4128 peter_e                   202 ECB             :     }
                                203                 : 
                                204                 :     /*
                                205                 :      * Look up the operator's underlying function.
                                206                 :      */
 5349 tgl                       207 GIC         712 :     if (!OidIsValid(typeId1))
                                208                 :     {
 5349 tgl                       209 CBC          34 :         typeId[0] = typeId2;
 5349 tgl                       210 GIC          34 :         nargs = 1;
 5349 tgl                       211 ECB             :     }
 5349 tgl                       212 CBC         678 :     else if (!OidIsValid(typeId2))
                                213                 :     {
 5349 tgl                       214 LBC           0 :         typeId[0] = typeId1;
 5349 tgl                       215 UIC           0 :         nargs = 1;
 5349 tgl                       216 EUB             :     }
                                217                 :     else
                                218                 :     {
 5349 tgl                       219 GIC         678 :         typeId[0] = typeId1;
                                220             678 :         typeId[1] = typeId2;
 5349 tgl                       221 CBC         678 :         nargs = 2;
 5349 tgl                       222 ECB             :     }
 5349 tgl                       223 CBC         712 :     functionOid = LookupFuncName(functionName, nargs, typeId, false);
                                224                 : 
 5349 tgl                       225 ECB             :     /*
                                226                 :      * We require EXECUTE rights for the function.  This isn't strictly
                                227                 :      * necessary, since EXECUTE will be checked at any attempted use of the
                                228                 :      * operator, but it seems like a good idea anyway.
                                229                 :      */
  147 peter                     230 GNC         712 :     aclresult = object_aclcheck(ProcedureRelationId, functionOid, GetUserId(), ACL_EXECUTE);
 5349 tgl                       231 GIC         712 :     if (aclresult != ACLCHECK_OK)
 1954 peter_e                   232 CBC           3 :         aclcheck_error(aclresult, OBJECT_FUNCTION,
 5349 tgl                       233               3 :                        NameListToString(functionName));
 5349 tgl                       234 ECB             : 
 4128 peter_e                   235 CBC         709 :     rettype = get_func_rettype(functionOid);
  147 peter                     236 GNC         709 :     aclresult = object_aclcheck(TypeRelationId, rettype, GetUserId(), ACL_USAGE);
 4128 peter_e                   237 CBC         709 :     if (aclresult != ACLCHECK_OK)
 3950                           238               3 :         aclcheck_error_type(aclresult, rettype);
 4128 peter_e                   239 ECB             : 
 5349 tgl                       240                 :     /*
                                241                 :      * Look up restriction and join estimators if specified
                                242                 :      */
 5349 tgl                       243 GIC         706 :     if (restrictionName)
 2826 heikki.linnakangas        244             496 :         restrictionOid = ValidateRestrictionEstimator(restrictionName);
 5349 tgl                       245 ECB             :     else
 5349 tgl                       246 CBC         210 :         restrictionOid = InvalidOid;
 5349 tgl                       247 GIC         706 :     if (joinName)
 2826 heikki.linnakangas        248 CBC         484 :         joinOid = ValidateJoinEstimator(joinName);
 5349 tgl                       249 ECB             :     else
 5349 tgl                       250 CBC         222 :         joinOid = InvalidOid;
                                251                 : 
 7664 tgl                       252 ECB             :     /*
                                253                 :      * now have OperatorCreate do all the work..
                                254                 :      */
                                255                 :     return
 3602 bruce                     256 GIC         706 :         OperatorCreate(oprName, /* operator name */
                                257                 :                        oprNamespace,    /* namespace */
 3602 bruce                     258 ECB             :                        typeId1, /* left type id */
                                259                 :                        typeId2, /* right type id */
                                260                 :                        functionOid, /* function for operator */
                                261                 :                        commutatorName,  /* optional commutator operator name */
                                262                 :                        negatorName, /* optional negator operator name */
                                263                 :                        restrictionOid,  /* optional restrict. sel. function */
                                264                 :                        joinOid, /* optional join sel. function name */
                                265                 :                        canMerge,    /* operator merges */
                                266                 :                        canHash);    /* operator hashes */
                                267                 : }
                                268                 : 
                                269                 : /*
                                270                 :  * Look up a restriction estimator function by name, and verify that it has
                                271                 :  * the correct signature and we have the permissions to attach it to an
                                272                 :  * operator.
                                273                 :  */
                                274                 : static Oid
 2826 heikki.linnakangas        275 GIC         721 : ValidateRestrictionEstimator(List *restrictionName)
                                276                 : {
 2826 heikki.linnakangas        277 ECB             :     Oid         typeId[4];
                                278                 :     Oid         restrictionOid;
                                279                 :     AclResult   aclresult;
                                280                 : 
 2826 heikki.linnakangas        281 GIC         721 :     typeId[0] = INTERNALOID;    /* PlannerInfo */
                                282             721 :     typeId[1] = OIDOID;         /* operator OID */
 2826 heikki.linnakangas        283 CBC         721 :     typeId[2] = INTERNALOID;    /* args list */
                                284             721 :     typeId[3] = INT4OID;        /* varRelid */
 2826 heikki.linnakangas        285 ECB             : 
 2826 heikki.linnakangas        286 CBC         721 :     restrictionOid = LookupFuncName(restrictionName, 4, typeId, false);
                                287                 : 
 2826 heikki.linnakangas        288 ECB             :     /* estimators must return float8 */
 2826 heikki.linnakangas        289 GIC         718 :     if (get_func_rettype(restrictionOid) != FLOAT8OID)
 2826 heikki.linnakangas        290 UIC           0 :         ereport(ERROR,
 2826 heikki.linnakangas        291 ECB             :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 2118 tgl                       292 EUB             :                  errmsg("restriction estimator function %s must return type %s",
                                293                 :                         NameListToString(restrictionName), "float8")));
                                294                 : 
                                295                 :     /* Require EXECUTE rights for the estimator */
  147 peter                     296 GNC         718 :     aclresult = object_aclcheck(ProcedureRelationId, restrictionOid, GetUserId(), ACL_EXECUTE);
 2826 heikki.linnakangas        297 GIC         718 :     if (aclresult != ACLCHECK_OK)
 1954 peter_e                   298 LBC           0 :         aclcheck_error(aclresult, OBJECT_FUNCTION,
 2826 heikki.linnakangas        299               0 :                        NameListToString(restrictionName));
 2826 heikki.linnakangas        300 EUB             : 
 2826 heikki.linnakangas        301 GBC         718 :     return restrictionOid;
                                302                 : }
 2826 heikki.linnakangas        303 ECB             : 
                                304                 : /*
                                305                 :  * Look up a join estimator function by name, and verify that it has the
                                306                 :  * correct signature and we have the permissions to attach it to an
                                307                 :  * operator.
                                308                 :  */
                                309                 : static Oid
 2826 heikki.linnakangas        310 GIC         709 : ValidateJoinEstimator(List *joinName)
                                311                 : {
 2826 heikki.linnakangas        312 ECB             :     Oid         typeId[5];
                                313                 :     Oid         joinOid;
                                314                 :     Oid         joinOid2;
                                315                 :     AclResult   aclresult;
                                316                 : 
 2826 heikki.linnakangas        317 GIC         709 :     typeId[0] = INTERNALOID;    /* PlannerInfo */
                                318             709 :     typeId[1] = OIDOID;         /* operator OID */
 2826 heikki.linnakangas        319 CBC         709 :     typeId[2] = INTERNALOID;    /* args list */
                                320             709 :     typeId[3] = INT2OID;        /* jointype */
                                321             709 :     typeId[4] = INTERNALOID;    /* SpecialJoinInfo */
 2826 heikki.linnakangas        322 ECB             : 
                                323                 :     /*
                                324                 :      * As of Postgres 8.4, the preferred signature for join estimators has 5
                                325                 :      * arguments, but we still allow the old 4-argument form.  Whine about
                                326                 :      * ambiguity if both forms exist.
                                327                 :      */
 2826 heikki.linnakangas        328 GIC         709 :     joinOid = LookupFuncName(joinName, 5, typeId, true);
  972 tgl                       329             709 :     joinOid2 = LookupFuncName(joinName, 4, typeId, true);
  972 tgl                       330 CBC         709 :     if (OidIsValid(joinOid))
  972 tgl                       331 ECB             :     {
  972 tgl                       332 CBC         706 :         if (OidIsValid(joinOid2))
  972 tgl                       333 UIC           0 :             ereport(ERROR,
  972 tgl                       334 ECB             :                     (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
  972 tgl                       335 EUB             :                      errmsg("join estimator function %s has multiple matches",
                                336                 :                             NameListToString(joinName))));
                                337                 :     }
                                338                 :     else
                                339                 :     {
  972 tgl                       340 GIC           3 :         joinOid = joinOid2;
                                341                 :         /* If not found, reference the 5-argument signature in error msg */
  972 tgl                       342 CBC           3 :         if (!OidIsValid(joinOid))
  972 tgl                       343 GIC           3 :             joinOid = LookupFuncName(joinName, 5, typeId, false);
  972 tgl                       344 ECB             :     }
 2826 heikki.linnakangas        345                 : 
                                346                 :     /* estimators must return float8 */
 2826 heikki.linnakangas        347 GIC         706 :     if (get_func_rettype(joinOid) != FLOAT8OID)
 2826 heikki.linnakangas        348 UIC           0 :         ereport(ERROR,
 2826 heikki.linnakangas        349 ECB             :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 2495 rhaas                     350 EUB             :                  errmsg("join estimator function %s must return type %s",
                                351                 :                         NameListToString(joinName), "float8")));
                                352                 : 
                                353                 :     /* Require EXECUTE rights for the estimator */
  147 peter                     354 GNC         706 :     aclresult = object_aclcheck(ProcedureRelationId, joinOid, GetUserId(), ACL_EXECUTE);
 2826 heikki.linnakangas        355 GIC         706 :     if (aclresult != ACLCHECK_OK)
 1954 peter_e                   356 LBC           0 :         aclcheck_error(aclresult, OBJECT_FUNCTION,
 2826 heikki.linnakangas        357               0 :                        NameListToString(joinName));
 2826 heikki.linnakangas        358 EUB             : 
 2826 heikki.linnakangas        359 GBC         706 :     return joinOid;
                                360                 : }
 2826 heikki.linnakangas        361 ECB             : 
                                362                 : /*
                                363                 :  * Guts of operator deletion.
                                364                 :  */
                                365                 : void
 7576 tgl                       366 GIC         336 : RemoveOperatorById(Oid operOid)
                                367                 : {
 7576 tgl                       368 ECB             :     Relation    relation;
                                369                 :     HeapTuple   tup;
                                370                 :     Form_pg_operator op;
                                371                 : 
 1539 andres                    372 GIC         336 :     relation = table_open(OperatorRelationId, RowExclusiveLock);
                                373                 : 
 4802 rhaas                     374 CBC         336 :     tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
 7522 bruce                     375 GIC         336 :     if (!HeapTupleIsValid(tup)) /* should not happen */
 7203 tgl                       376 LBC           0 :         elog(ERROR, "cache lookup failed for operator %u", operOid);
 2571 tgl                       377 CBC         336 :     op = (Form_pg_operator) GETSTRUCT(tup);
 2571 tgl                       378 EUB             : 
 2571 tgl                       379 ECB             :     /*
                                380                 :      * Reset links from commutator and negator, if any.  In case of a
                                381                 :      * self-commutator or self-negator, this means we have to re-fetch the
                                382                 :      * updated tuple.  (We could optimize away updates on the tuple we're
                                383                 :      * about to drop, but it doesn't seem worth convoluting the logic for.)
                                384                 :      */
 2571 tgl                       385 GIC         336 :     if (OidIsValid(op->oprcom) || OidIsValid(op->oprnegate))
                                386                 :     {
 2571 tgl                       387 CBC         154 :         OperatorUpd(operOid, op->oprcom, op->oprnegate, true);
 2571 tgl                       388 GIC         154 :         if (operOid == op->oprcom || operOid == op->oprnegate)
 2571 tgl                       389 ECB             :         {
 2571 tgl                       390 CBC          47 :             ReleaseSysCache(tup);
 2571 tgl                       391 GIC          47 :             tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
 2571 tgl                       392 CBC          47 :             if (!HeapTupleIsValid(tup)) /* should not happen */
 2571 tgl                       393 LBC           0 :                 elog(ERROR, "cache lookup failed for operator %u", operOid);
 2571 tgl                       394 ECB             :         }
 2571 tgl                       395 EUB             :     }
                                396                 : 
 2258 tgl                       397 GIC         336 :     CatalogTupleDelete(relation, &tup->t_self);
                                398                 : 
 7576 tgl                       399 CBC         336 :     ReleaseSysCache(tup);
                                400                 : 
 1539 andres                    401             336 :     table_close(relation, RowExclusiveLock);
 7664 tgl                       402 GIC         336 : }
 2826 heikki.linnakangas        403 ECB             : 
                                404                 : /*
                                405                 :  * AlterOperator
                                406                 :  *      routine implementing ALTER OPERATOR <operator> SET (option = ...).
                                407                 :  *
                                408                 :  * Currently, only RESTRICT and JOIN estimator functions can be changed.
                                409                 :  */
                                410                 : ObjectAddress
 2826 heikki.linnakangas        411 GIC         258 : AlterOperator(AlterOperatorStmt *stmt)
                                412                 : {
 2826 heikki.linnakangas        413 ECB             :     ObjectAddress address;
                                414                 :     Oid         oprId;
                                415                 :     Relation    catalog;
                                416                 :     HeapTuple   tup;
                                417                 :     Form_pg_operator oprForm;
                                418                 :     int         i;
                                419                 :     ListCell   *pl;
                                420                 :     Datum       values[Natts_pg_operator];
                                421                 :     bool        nulls[Natts_pg_operator];
                                422                 :     bool        replaces[Natts_pg_operator];
 1698 peter_e                   423 GIC         258 :     List       *restrictionName = NIL;  /* optional restrict. sel. function */
 2826 heikki.linnakangas        424             258 :     bool        updateRestriction = false;
 2826 heikki.linnakangas        425 ECB             :     Oid         restrictionOid;
 1698 peter_e                   426 CBC         258 :     List       *joinName = NIL; /* optional join sel. function */
 2826 heikki.linnakangas        427 GIC         258 :     bool        updateJoin = false;
 2826 heikki.linnakangas        428 ECB             :     Oid         joinOid;
                                429                 : 
                                430                 :     /* Look up the operator */
 2293 peter_e                   431 GIC         258 :     oprId = LookupOperWithArgs(stmt->opername, false);
 1539 andres                    432             258 :     catalog = table_open(OperatorRelationId, RowExclusiveLock);
 2826 heikki.linnakangas        433 CBC         258 :     tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(oprId));
 1435 tgl                       434             258 :     if (!HeapTupleIsValid(tup))
 2826 heikki.linnakangas        435 LBC           0 :         elog(ERROR, "cache lookup failed for operator %u", oprId);
 2826 heikki.linnakangas        436 CBC         258 :     oprForm = (Form_pg_operator) GETSTRUCT(tup);
 2826 heikki.linnakangas        437 EUB             : 
 2826 heikki.linnakangas        438 ECB             :     /* Process options */
 2826 heikki.linnakangas        439 GIC         723 :     foreach(pl, stmt->options)
                                440                 :     {
 2826 heikki.linnakangas        441 CBC         480 :         DefElem    *defel = (DefElem *) lfirst(pl);
                                442                 :         List       *param;
 2826 heikki.linnakangas        443 ECB             : 
 2826 heikki.linnakangas        444 GIC         480 :         if (defel->arg == NULL)
                                445              15 :             param = NIL;        /* NONE, removes the function */
 2826 heikki.linnakangas        446 ECB             :         else
 2826 heikki.linnakangas        447 CBC         465 :             param = defGetQualifiedName(defel);
                                448                 : 
 1899 tgl                       449             480 :         if (strcmp(defel->defname, "restrict") == 0)
                                450                 :         {
 2826 heikki.linnakangas        451             234 :             restrictionName = param;
 2826 heikki.linnakangas        452 GIC         234 :             updateRestriction = true;
 2826 heikki.linnakangas        453 ECB             :         }
 1899 tgl                       454 CBC         246 :         else if (strcmp(defel->defname, "join") == 0)
                                455                 :         {
 2826 heikki.linnakangas        456             231 :             joinName = param;
 2826 heikki.linnakangas        457 GIC         231 :             updateJoin = true;
 2826 heikki.linnakangas        458 ECB             :         }
                                459                 : 
                                460                 :         /*
                                461                 :          * The rest of the options that CREATE accepts cannot be changed.
                                462                 :          * Check for them so that we can give a meaningful error message.
                                463                 :          */
 1899 tgl                       464 GIC          15 :         else if (strcmp(defel->defname, "leftarg") == 0 ||
                                465              15 :                  strcmp(defel->defname, "rightarg") == 0 ||
 1698 peter_e                   466 CBC          15 :                  strcmp(defel->defname, "function") == 0 ||
 1899 tgl                       467              15 :                  strcmp(defel->defname, "procedure") == 0 ||
                                468              15 :                  strcmp(defel->defname, "commutator") == 0 ||
                                469               9 :                  strcmp(defel->defname, "negator") == 0 ||
                                470               3 :                  strcmp(defel->defname, "hashes") == 0 ||
                                471               3 :                  strcmp(defel->defname, "merges") == 0)
 2826 heikki.linnakangas        472 ECB             :         {
 2826 heikki.linnakangas        473 CBC          12 :             ereport(ERROR,
                                474                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
 2497 peter_e                   475 ECB             :                      errmsg("operator attribute \"%s\" cannot be changed",
                                476                 :                             defel->defname)));
                                477                 :         }
                                478                 :         else
 2826 heikki.linnakangas        479 GIC           3 :             ereport(ERROR,
                                480                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
 2826 heikki.linnakangas        481 ECB             :                      errmsg("operator attribute \"%s\" not recognized",
                                482                 :                             defel->defname)));
                                483                 :     }
                                484                 : 
                                485                 :     /* Check permissions. Must be owner. */
  147 peter                     486 GNC         243 :     if (!object_ownercheck(OperatorRelationId, oprId, GetUserId()))
 1954 peter_e                   487 GIC           3 :         aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
 2826 heikki.linnakangas        488 CBC           3 :                        NameStr(oprForm->oprname));
 2826 heikki.linnakangas        489 ECB             : 
                                490                 :     /*
                                491                 :      * Look up restriction and join estimators if specified
                                492                 :      */
 2826 heikki.linnakangas        493 GIC         240 :     if (restrictionName)
                                494             225 :         restrictionOid = ValidateRestrictionEstimator(restrictionName);
 2826 heikki.linnakangas        495 ECB             :     else
 2826 heikki.linnakangas        496 CBC          15 :         restrictionOid = InvalidOid;
 2826 heikki.linnakangas        497 GIC         237 :     if (joinName)
 2826 heikki.linnakangas        498 CBC         225 :         joinOid = ValidateJoinEstimator(joinName);
 2826 heikki.linnakangas        499 ECB             :     else
 2826 heikki.linnakangas        500 CBC          12 :         joinOid = InvalidOid;
                                501                 : 
 2826 heikki.linnakangas        502 ECB             :     /* Perform additional checks, like OperatorCreate does */
 2826 heikki.linnakangas        503 GIC         234 :     if (!(OidIsValid(oprForm->oprleft) && OidIsValid(oprForm->oprright)))
                                504                 :     {
 2826 heikki.linnakangas        505 ECB             :         /* If it's not a binary op, these things mustn't be set: */
 2826 heikki.linnakangas        506 UIC           0 :         if (OidIsValid(joinOid))
                                507               0 :             ereport(ERROR,
 2826 heikki.linnakangas        508 EUB             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 2118 tgl                       509                 :                      errmsg("only binary operators can have join selectivity")));
                                510                 :     }
                                511                 : 
 2826 heikki.linnakangas        512 GIC         234 :     if (oprForm->oprresult != BOOLOID)
                                513                 :     {
 2826 heikki.linnakangas        514 LBC           0 :         if (OidIsValid(restrictionOid))
 2826 heikki.linnakangas        515 UIC           0 :             ereport(ERROR,
 2826 heikki.linnakangas        516 EUB             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                517                 :                      errmsg("only boolean operators can have restriction selectivity")));
 2826 heikki.linnakangas        518 UIC           0 :         if (OidIsValid(joinOid))
                                519               0 :             ereport(ERROR,
 2826 heikki.linnakangas        520 EUB             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
 2118 tgl                       521                 :                      errmsg("only boolean operators can have join selectivity")));
                                522                 :     }
                                523                 : 
                                524                 :     /* Update the tuple */
 2826 heikki.linnakangas        525 GIC        3744 :     for (i = 0; i < Natts_pg_operator; ++i)
                                526                 :     {
 2826 heikki.linnakangas        527 CBC        3510 :         values[i] = (Datum) 0;
 2826 heikki.linnakangas        528 GIC        3510 :         replaces[i] = false;
 2826 heikki.linnakangas        529 CBC        3510 :         nulls[i] = false;
 2826 heikki.linnakangas        530 ECB             :     }
 2826 heikki.linnakangas        531 CBC         234 :     if (updateRestriction)
                                532                 :     {
                                533             228 :         replaces[Anum_pg_operator_oprrest - 1] = true;
 2826 heikki.linnakangas        534 GIC         228 :         values[Anum_pg_operator_oprrest - 1] = restrictionOid;
 2826 heikki.linnakangas        535 ECB             :     }
 2826 heikki.linnakangas        536 CBC         234 :     if (updateJoin)
                                537                 :     {
                                538             228 :         replaces[Anum_pg_operator_oprjoin - 1] = true;
 2826 heikki.linnakangas        539 GIC         228 :         values[Anum_pg_operator_oprjoin - 1] = joinOid;
 2826 heikki.linnakangas        540 ECB             :     }
                                541                 : 
 2826 heikki.linnakangas        542 GIC         234 :     tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
                                543                 :                             values, nulls, replaces);
 2826 heikki.linnakangas        544 ECB             : 
 2259 alvherre                  545 GIC         234 :     CatalogTupleUpdate(catalog, &tup->t_self, tup);
                                546                 : 
  600 tgl                       547 CBC         234 :     address = makeOperatorDependencies(tup, false, true);
                                548                 : 
 2656                           549             234 :     InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0);
                                550                 : 
 1539 andres                    551             234 :     table_close(catalog, NoLock);
                                552                 : 
 2826 heikki.linnakangas        553             234 :     return address;
                                554                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a