]> granicus.if.org Git - postgresql/blobdiff - src/backend/catalog/pg_operator.c
message refinements
[postgresql] / src / backend / catalog / pg_operator.c
index 06c558821fb362eba67422e24eb440aadde1bdc2..a72565e9709d284ed723a72a69cabe149ba8276b 100644 (file)
@@ -3,11 +3,12 @@
  * pg_operator.c
  *       routines to support manipulation of the pg_operator relation
  *
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.40 1999/07/16 04:58:37 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.61 2001/08/10 15:49:39 petere Exp $
  *
  * NOTES
  *       these routines moved here from commands/define.c and somewhat cleaned up.
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/indexing.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
 #include "utils/builtins.h"
+#include "utils/fmgroids.h"
 #include "utils/syscache.h"
 
-#ifndef HAVE_MEMMOVE
-#include <regex/utils.h>
-#else
-#include <string.h>
-#endif
 
 static Oid OperatorGetWithOpenRelation(Relation pg_operator_desc,
                                                        const char *operatorName,
@@ -71,14 +69,15 @@ static void OperatorUpd(Oid baseId, Oid commId, Oid negId);
 /* ----------------------------------------------------------------
  *             OperatorGetWithOpenRelation
  *
- *             preforms a scan on pg_operator for an operator tuple
+ *             performs a scan on pg_operator for an operator tuple
  *             with given name and left/right type oids.
- * ----------------------------------------------------------------
+ *
  *       pg_operator_desc      -- reldesc for pg_operator
  *       operatorName          -- name of operator to fetch
  *       leftObjectId          -- left data type oid of operator to fetch
  *       rightObjectId         -- right data type oid of operator to fetch
  *       defined                       -- set TRUE if defined (not a shell)
+ * ----------------------------------------------------------------
  */
 static Oid
 OperatorGetWithOpenRelation(Relation pg_operator_desc,
@@ -90,31 +89,26 @@ OperatorGetWithOpenRelation(Relation pg_operator_desc,
        HeapScanDesc pg_operator_scan;
        Oid                     operatorObjectId;
        HeapTuple       tup;
+       ScanKeyData     opKey[3];
 
-       static ScanKeyData opKey[3] = {
-               {0, Anum_pg_operator_oprname, F_NAMEEQ},
-               {0, Anum_pg_operator_oprleft, F_OIDEQ},
-               {0, Anum_pg_operator_oprright, F_OIDEQ},
-       };
-
-       fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
-       fmgr_info(F_OIDEQ, &opKey[1].sk_func);
-       fmgr_info(F_OIDEQ, &opKey[2].sk_func);
-       opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
-       opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
-       opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
-
-       /* ----------------
-        *      form scan key
-        * ----------------
+       /*
+        * form scan key
         */
-       opKey[0].sk_argument = PointerGetDatum(operatorName);
-       opKey[1].sk_argument = ObjectIdGetDatum(leftObjectId);
-       opKey[2].sk_argument = ObjectIdGetDatum(rightObjectId);
+       ScanKeyEntryInitialize(&opKey[0], 0x0,
+                                                  Anum_pg_operator_oprname,
+                                                  F_NAMEEQ,
+                                                  PointerGetDatum(operatorName));
+       ScanKeyEntryInitialize(&opKey[1], 0x0,
+                                                  Anum_pg_operator_oprleft,
+                                                  F_OIDEQ,
+                                                  ObjectIdGetDatum(leftObjectId));
+       ScanKeyEntryInitialize(&opKey[2], 0x0,
+                                                  Anum_pg_operator_oprright,
+                                                  F_OIDEQ,
+                                                  ObjectIdGetDatum(rightObjectId));
 
-       /* ----------------
-        *      begin the scan
-        * ----------------
+       /*
+        * begin the scan
         */
        pg_operator_scan = heap_beginscan(pg_operator_desc,
                                                                          0,
@@ -122,10 +116,9 @@ OperatorGetWithOpenRelation(Relation pg_operator_desc,
                                                                          3,
                                                                          opKey);
 
-       /* ----------------
-        *      fetch the operator tuple, if it exists, and determine
-        *      the proper return oid value.
-        * ----------------
+       /*
+        * fetch the operator tuple, if it exists, and determine the proper
+        * return oid value.
         */
        tup = heap_getnext(pg_operator_scan, 0);
 
@@ -142,9 +135,8 @@ OperatorGetWithOpenRelation(Relation pg_operator_desc,
                *defined = false;
        }
 
-       /* ----------------
-        *      close the scan and return the oid.
-        * ----------------
+       /*
+        * close the scan and return the oid.
         */
        heap_endscan(pg_operator_scan);
 
@@ -172,19 +164,18 @@ OperatorGet(char *operatorName,
        bool            leftDefined = false;
        bool            rightDefined = false;
 
-       /* ----------------
-        *      look up the operator data types.
+       /*
+        * look up the operator data types.
         *
-        *      Note: types must be defined before operators
-        * ----------------
+        * Note: types must be defined before operators
         */
        if (leftTypeName)
        {
                leftObjectId = TypeGet(leftTypeName, &leftDefined);
 
                if (!OidIsValid(leftObjectId) || !leftDefined)
-                       elog(ERROR, "OperatorGet: left type '%s' nonexistent",
-                                leftTypeName);
+                       elog(ERROR, "left type \"%s\" of operator %s does not exist",
+                                leftTypeName, operatorName);
        }
 
        if (rightTypeName)
@@ -192,24 +183,22 @@ OperatorGet(char *operatorName,
                rightObjectId = TypeGet(rightTypeName, &rightDefined);
 
                if (!OidIsValid(rightObjectId) || !rightDefined)
-                       elog(ERROR, "OperatorGet: right type '%s' nonexistent",
-                                rightTypeName);
+                       elog(ERROR, "right type \"%s\" of operator %s does not exist",
+                                rightTypeName, operatorName);
        }
 
        if (!((OidIsValid(leftObjectId) && leftDefined) ||
                  (OidIsValid(rightObjectId) && rightDefined)))
-               elog(ERROR, "OperatorGet: must have at least one argument type");
+               elog(ERROR, "operator %s must have at least one operand type", operatorName);
 
-       /* ----------------
-        *      open the pg_operator relation
-        * ----------------
+       /*
+        * open the pg_operator relation
         */
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
 
-       /* ----------------
-        *      get the oid for the operator with the appropriate name
-        *      and left/right types.
-        * ----------------
+       /*
+        * get the oid for the operator with the appropriate name and
+        * left/right types.
         */
        operatorObjectId = OperatorGetWithOpenRelation(pg_operator_desc,
                                                                                                   operatorName,
@@ -217,11 +206,10 @@ OperatorGet(char *operatorName,
                                                                                                   rightObjectId,
                                                                                                   defined);
 
-       /* ----------------
-        *      close the relation and return the operator oid.
-        * ----------------
+       /*
+        * close the relation and return the operator oid.
         */
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, AccessShareLock);
 
        return operatorObjectId;
 }
@@ -245,9 +233,8 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
        NameData        oname;
        TupleDesc       tupDesc;
 
-       /* ----------------
-        *      initialize our *nulls and *values arrays
-        * ----------------
+       /*
+        * initialize our *nulls and *values arrays
         */
        for (i = 0; i < Natts_pg_operator; ++i)
        {
@@ -255,19 +242,18 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
                values[i] = (Datum) NULL;               /* redundant, but safe */
        }
 
-       /* ----------------
-        *      initialize *values with the operator name and input data types.
-        *      Note that oprcode is set to InvalidOid, indicating it's a shell.
-        * ----------------
+       /*
+        * initialize *values with the operator name and input data types.
+        * Note that oprcode is set to InvalidOid, indicating it's a shell.
         */
        i = 0;
        namestrcpy(&oname, operatorName);
        values[i++] = NameGetDatum(&oname);
        values[i++] = Int32GetDatum(GetUserId());
-       values[i++] = (Datum) (uint16) 0;
-       values[i++] = (Datum) 'b';      /* assume it's binary */
-       values[i++] = (Datum) (bool) 0;
-       values[i++] = (Datum) (bool) 0;
+       values[i++] = UInt16GetDatum(0);
+       values[i++] = CharGetDatum('b');        /* assume it's binary */
+       values[i++] = BoolGetDatum(false);
+       values[i++] = BoolGetDatum(false);
        values[i++] = ObjectIdGetDatum(leftObjectId);           /* <-- left oid */
        values[i++] = ObjectIdGetDatum(rightObjectId);          /* <-- right oid */
        values[i++] = ObjectIdGetDatum(InvalidOid);
@@ -279,9 +265,8 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
        values[i++] = ObjectIdGetDatum(InvalidOid);
        values[i++] = ObjectIdGetDatum(InvalidOid);
 
-       /* ----------------
-        *      create a new operator tuple
-        * ----------------
+       /*
+        * create a new operator tuple
         */
        tupDesc = pg_operator_desc->rd_att;
 
@@ -289,19 +274,25 @@ OperatorShellMakeWithOpenRelation(Relation pg_operator_desc,
                                                 values,
                                                 nulls);
 
-       /* ----------------
-        *      insert our "shell" operator tuple and
-        *      close the relation
-        * ----------------
+       /*
+        * insert our "shell" operator tuple and close the relation
         */
        heap_insert(pg_operator_desc, tup);
        operatorObjectId = tup->t_data->t_oid;
 
-       /* ----------------
-        *      free the tuple and return the operator oid
-        * ----------------
+       if (RelationGetForm(pg_operator_desc)->relhasindex)
+       {
+               Relation        idescs[Num_pg_operator_indices];
+
+               CatalogOpenIndices(Num_pg_operator_indices, Name_pg_operator_indices, idescs);
+               CatalogIndexInsert(idescs, Num_pg_operator_indices, pg_operator_desc, tup);
+               CatalogCloseIndices(Num_pg_operator_indices, idescs);
+       }
+
+       /*
+        * free the tuple and return the operator oid
         */
-       pfree(tup);
+       heap_freetuple(tup);
 
        return operatorObjectId;
 }
@@ -328,9 +319,8 @@ OperatorShellMake(char *operatorName,
        bool            leftDefined = false;
        bool            rightDefined = false;
 
-       /* ----------------
-        *      get the left and right type oid's for this operator
-        * ----------------
+       /*
+        * get the left and right type oid's for this operator
         */
        if (leftTypeName)
                leftObjectId = TypeGet(leftTypeName, &leftDefined);
@@ -340,28 +330,26 @@ OperatorShellMake(char *operatorName,
 
        if (!((OidIsValid(leftObjectId) && leftDefined) ||
                  (OidIsValid(rightObjectId) && rightDefined)))
-               elog(ERROR, "OperatorShellMake: no valid argument types??");
+               elog(ERROR, "OperatorShellMake: the operand types are not valid");
 
-       /* ----------------
-        *      open pg_operator
-        * ----------------
+       /*
+        * open pg_operator
         */
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
 
-       /* ----------------
-        *      add a "shell" operator tuple to the operator relation
-        *      and recover the shell tuple's oid.
-        * ----------------
+       /*
+        * add a "shell" operator tuple to the operator relation and recover
+        * the shell tuple's oid.
         */
        operatorObjectId = OperatorShellMakeWithOpenRelation(pg_operator_desc,
                                                                                                                 operatorName,
                                                                                                                 leftObjectId,
                                                                                                                 rightObjectId);
-       /* ----------------
-        *      close the operator relation and return the oid.
-        * ----------------
+
+       /*
+        * close the operator relation and return the oid.
         */
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, RowExclusiveLock);
 
        return operatorObjectId;
 }
@@ -401,7 +389,7 @@ OperatorShellMake(char *operatorName,
  *      resultType -- defer this, since it must be determined from
  *                                the pg_procedure catalog
  *      commutatorObjectId -- if this is NULL, enter ObjectId=0
- *                                       else if this already exists, enter it's ObjectId
+ *                                       else if this already exists, enter its ObjectId
  *                                       else if this does not yet exist, and is not
  *                                             the same as the main operatorName, then create
  *                                             a shell and enter the new ObjectId
@@ -414,7 +402,7 @@ OperatorShellMake(char *operatorName,
  *      rightSortObjectId -- same as for commutatorObjectId
  *      operatorProcedure -- must access the pg_procedure catalog to get the
  *                                ObjectId of the procedure that actually does the operator
- *                                actions this is required.  Do an amgetattr to find out the
+ *                                actions this is required.  Do a lookup to find out the
  *                                return type of the procedure
  *      restrictionProcedure -- must access the pg_procedure catalog to get
  *                                the ObjectId but this is optional
@@ -461,7 +449,6 @@ OperatorDef(char *operatorName,
        int                     i,
                                j;
        Relation        pg_operator_desc;
-
        HeapScanDesc pg_operator_scan;
        HeapTuple       tup;
        char            nulls[Natts_pg_operator];
@@ -477,23 +464,11 @@ OperatorDef(char *operatorName,
        bool            rightDefined = false;
        bool            selfCommutator = false;
        char       *name[4];
-       Oid                     typeId[8];
+       Oid                     typeId[FUNC_MAX_ARGS];
        int                     nargs;
        NameData        oname;
        TupleDesc       tupDesc;
-
-       static ScanKeyData opKey[3] = {
-               {0, Anum_pg_operator_oprname, F_NAMEEQ},
-               {0, Anum_pg_operator_oprleft, F_OIDEQ},
-               {0, Anum_pg_operator_oprright, F_OIDEQ},
-       };
-
-       fmgr_info(F_NAMEEQ, &opKey[0].sk_func);
-       fmgr_info(F_OIDEQ, &opKey[1].sk_func);
-       fmgr_info(F_OIDEQ, &opKey[2].sk_func);
-       opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
-       opKey[1].sk_nargs = opKey[1].sk_func.fn_nargs;
-       opKey[2].sk_nargs = opKey[2].sk_func.fn_nargs;
+       ScanKeyData     opKey[3];
 
        operatorObjectId = OperatorGet(operatorName,
                                                                   leftTypeName,
@@ -509,18 +484,17 @@ OperatorDef(char *operatorName,
         * filling in a previously-created shell.
         */
 
-       /* ----------------
-        *      look up the operator data types.
+       /*
+        * look up the operator data types.
         *
-        *      Note: types must be defined before operators
-        * ----------------
+        * Note: types must be defined before operators
         */
        if (leftTypeName)
        {
                leftTypeId = TypeGet(leftTypeName, &leftDefined);
 
                if (!OidIsValid(leftTypeId) || !leftDefined)
-                       elog(ERROR, "OperatorDef: left type '%s' nonexistent",
+                       elog(ERROR, "left type \"%s\" does not exist",
                                 leftTypeName);
        }
 
@@ -529,13 +503,13 @@ OperatorDef(char *operatorName,
                rightTypeId = TypeGet(rightTypeName, &rightDefined);
 
                if (!OidIsValid(rightTypeId) || !rightDefined)
-                       elog(ERROR, "OperatorDef: right type '%s' nonexistent",
+                       elog(ERROR, "right type \"%s\" does not exist",
                                 rightTypeName);
        }
 
        if (!((OidIsValid(leftTypeId) && leftDefined) ||
                  (OidIsValid(rightTypeId) && rightDefined)))
-               elog(ERROR, "OperatorDef: must have at least one argument type");
+               elog(ERROR, "operator must have at least one operand type");
 
        for (i = 0; i < Natts_pg_operator; ++i)
        {
@@ -544,14 +518,12 @@ OperatorDef(char *operatorName,
                nulls[i] = ' ';
        }
 
-       /* ----------------
-        * Look up registered procedures -- find the return type
-        * of procedureName to place in "result" field.
-        * Do this before shells are created so we don't
-        * have to worry about deleting them later.
-        * ----------------
+       /*
+        * Look up registered procedures -- find the return type of
+        * procedureName to place in "result" field. Do this before shells are
+        * created so we don't have to worry about deleting them later.
         */
-       MemSet(typeId, 0, 8 * sizeof(Oid));
+       MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid));
        if (!leftTypeName)
        {
                typeId[0] = rightTypeId;
@@ -568,12 +540,11 @@ OperatorDef(char *operatorName,
                typeId[1] = rightTypeId;
                nargs = 2;
        }
-       tup = SearchSysCacheTuple(PRONAME,
-                                                         PointerGetDatum(procedureName),
-                                                         Int32GetDatum(nargs),
-                                                         PointerGetDatum(typeId),
-                                                         0);
-
+       tup = SearchSysCache(PROCNAME,
+                                                PointerGetDatum(procedureName),
+                                                Int32GetDatum(nargs),
+                                                PointerGetDatum(typeId),
+                                                0);
        if (!HeapTupleIsValid(tup))
                func_error("OperatorDef", procedureName, nargs, typeId, NULL);
 
@@ -581,69 +552,70 @@ OperatorDef(char *operatorName,
        values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(((Form_pg_proc)
                                                                                        GETSTRUCT(tup))->prorettype);
 
-       /* ----------------
-        *      find restriction
-        * ----------------
+       ReleaseSysCache(tup);
+
+       /*
+        * find restriction estimator
         */
        if (restrictionName)
        {                                                       /* optional */
-               MemSet(typeId, 0, 8 * sizeof(Oid));
-               typeId[0] = OIDOID;             /* operator OID */
-               typeId[1] = OIDOID;             /* relation OID */
-               typeId[2] = INT2OID;    /* attribute number */
-               typeId[3] = 0;                  /* value - can be any type      */
-               typeId[4] = INT4OID;    /* flags - left or right selectivity */
-               tup = SearchSysCacheTuple(PRONAME,
-                                                                 PointerGetDatum(restrictionName),
-                                                                 Int32GetDatum(5),
-                                                                 PointerGetDatum(typeId),
-                                                                 0);
-               if (!HeapTupleIsValid(tup))
-                       func_error("OperatorDef", restrictionName, 5, typeId, NULL);
-
-               values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(tup->t_data->t_oid);
+               Oid                     restOid;
+
+               MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid));
+               typeId[0] = 0;                  /* Query (opaque type) */
+               typeId[1] = OIDOID;             /* operator OID */
+               typeId[2] = 0;                  /* args list (opaque type) */
+               typeId[3] = INT4OID;    /* varRelid */
+
+               restOid = GetSysCacheOid(PROCNAME,
+                                                                PointerGetDatum(restrictionName),
+                                                                Int32GetDatum(4),
+                                                                PointerGetDatum(typeId),
+                                                                0);
+               if (!OidIsValid(restOid))
+                       func_error("OperatorDef", restrictionName, 4, typeId, NULL);
+
+               values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restOid);
        }
        else
                values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
 
-       /* ----------------
-        *      find join - only valid for binary operators
-        * ----------------
+       /*
+        * find join estimator
         */
        if (joinName)
        {                                                       /* optional */
-               MemSet(typeId, 0, 8 * sizeof(Oid));
-               typeId[0] = OIDOID;             /* operator OID */
-               typeId[1] = OIDOID;             /* relation OID 1 */
-               typeId[2] = INT2OID;    /* attribute number 1 */
-               typeId[3] = OIDOID;             /* relation OID 2 */
-               typeId[4] = INT2OID;    /* attribute number 2 */
-
-               tup = SearchSysCacheTuple(PRONAME,
-                                                                 PointerGetDatum(joinName),
-                                                                 Int32GetDatum(5),
-                                                                 PointerGetDatum(typeId),
-                                                                 0);
-               if (!HeapTupleIsValid(tup))
-                       func_error("OperatorDef", joinName, 5, typeId, NULL);
-
-               values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(tup->t_data->t_oid);
+               Oid                     joinOid;
+
+               MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid));
+               typeId[0] = 0;                  /* Query (opaque type) */
+               typeId[1] = OIDOID;             /* operator OID */
+               typeId[2] = 0;                  /* args list (opaque type) */
+
+               joinOid = GetSysCacheOid(PROCNAME,
+                                                                PointerGetDatum(joinName),
+                                                                Int32GetDatum(3),
+                                                                PointerGetDatum(typeId),
+                                                                0);
+               if (!OidIsValid(joinOid))
+                       func_error("OperatorDef", joinName, 3, typeId, NULL);
+
+               values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinOid);
        }
        else
                values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
 
-       /* ----------------
+       /*
         * set up values in the operator tuple
-        * ----------------
         */
        i = 0;
        namestrcpy(&oname, operatorName);
        values[i++] = NameGetDatum(&oname);
        values[i++] = Int32GetDatum(GetUserId());
        values[i++] = UInt16GetDatum(precedence);
-       values[i++] = leftTypeName ? (rightTypeName ? 'b' : 'r') : 'l';
-       values[i++] = Int8GetDatum(isLeftAssociative);
-       values[i++] = Int8GetDatum(canHash);
+       values[i++] = CharGetDatum(leftTypeName ? (rightTypeName ? 'b' : 'r') : 'l');
+       values[i++] = BoolGetDatum(isLeftAssociative);
+       values[i++] = BoolGetDatum(canHash);
        values[i++] = ObjectIdGetDatum(leftTypeId);
        values[i++] = ObjectIdGetDatum(rightTypeId);
 
@@ -732,7 +704,7 @@ OperatorDef(char *operatorName,
                                                                                          otherRightTypeName);
                                if (!OidIsValid(other_oid))
                                        elog(ERROR,
-                                                "OperatorDef: can't create operator shell '%s'",
+                                          "OperatorDef: can't create operator shell \"%s\"",
                                                 name[j]);
                                values[i++] = ObjectIdGetDatum(other_oid);
                        }
@@ -745,7 +717,7 @@ OperatorDef(char *operatorName,
                                 */
                                if (j != 0)
                                        elog(ERROR,
-                                                "OperatorDef: operator can't be its own negator or sort op");
+                                                "operator cannot be its own negator or sort operator");
                                selfCommutator = true;
                                values[i++] = ObjectIdGetDatum(InvalidOid);
                        }
@@ -759,16 +731,28 @@ OperatorDef(char *operatorName,
 
        /* last three fields were filled in above */
 
+       pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
+
        /*
         * If we are adding to an operator shell, get its t_self
         */
-       pg_operator_desc = heap_openr(OperatorRelationName);
-
        if (operatorObjectId)
        {
-               opKey[0].sk_argument = PointerGetDatum(operatorName);
-               opKey[1].sk_argument = ObjectIdGetDatum(leftTypeId);
-               opKey[2].sk_argument = ObjectIdGetDatum(rightTypeId);
+               /* Make sure we can see the shell even if it is new in current cmd */
+               CommandCounterIncrement();
+
+               ScanKeyEntryInitialize(&opKey[0], 0x0,
+                                                          Anum_pg_operator_oprname,
+                                                          F_NAMEEQ,
+                                                          PointerGetDatum(operatorName));
+               ScanKeyEntryInitialize(&opKey[1], 0x0,
+                                                          Anum_pg_operator_oprleft,
+                                                          F_OIDEQ,
+                                                          ObjectIdGetDatum(leftTypeId));
+               ScanKeyEntryInitialize(&opKey[2], 0x0,
+                                                          Anum_pg_operator_oprright,
+                                                          F_OIDEQ,
+                                                          ObjectIdGetDatum(rightTypeId));
 
                pg_operator_scan = heap_beginscan(pg_operator_desc,
                                                                                  0,
@@ -785,12 +769,10 @@ OperatorDef(char *operatorName,
                                                                   nulls,
                                                                   replaces);
 
-                       setheapoverride(true);
-                       heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
-                       setheapoverride(false);
+                       simple_heap_update(pg_operator_desc, &tup->t_self, tup);
                }
                else
-                       elog(ERROR, "OperatorDef: no operator %u", operatorObjectId);
+                       elog(ERROR, "OperatorDef: operator %u not found", operatorObjectId);
 
                heap_endscan(pg_operator_scan);
        }
@@ -803,7 +785,16 @@ OperatorDef(char *operatorName,
                operatorObjectId = tup->t_data->t_oid;
        }
 
-       heap_close(pg_operator_desc);
+       if (RelationGetForm(pg_operator_desc)->relhasindex)
+       {
+               Relation        idescs[Num_pg_operator_indices];
+
+               CatalogOpenIndices(Num_pg_operator_indices, Name_pg_operator_indices, idescs);
+               CatalogIndexInsert(idescs, Num_pg_operator_indices, pg_operator_desc, tup);
+               CatalogCloseIndices(Num_pg_operator_indices, idescs);
+       }
+
+       heap_close(pg_operator_desc, RowExclusiveLock);
 
        /*
         * If a commutator and/or negator link is provided, update the other
@@ -843,25 +834,28 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
        char            nulls[Natts_pg_operator];
        char            replaces[Natts_pg_operator];
        Datum           values[Natts_pg_operator];
-
-       static ScanKeyData opKey[1] = {
-               {0, ObjectIdAttributeNumber, F_OIDEQ},
-       };
-
-       fmgr_info(F_OIDEQ, &opKey[0].sk_func);
-       opKey[0].sk_nargs = opKey[0].sk_func.fn_nargs;
+       ScanKeyData     opKey[1];
 
        for (i = 0; i < Natts_pg_operator; ++i)
        {
-               values[i] = (Datum) NULL;
+               values[i] = (Datum) 0;
                replaces[i] = ' ';
                nulls[i] = ' ';
        }
 
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
 
-       /* check and update the commutator, if necessary */
-       opKey[0].sk_argument = ObjectIdGetDatum(commId);
+       /*
+        * check and update the commutator & negator, if necessary
+        *
+        * First make sure we can see them...
+        */
+       CommandCounterIncrement();
+
+       ScanKeyEntryInitialize(&opKey[0], 0x0,
+                                                  ObjectIdAttributeNumber,
+                                                  F_OIDEQ,
+                                                  ObjectIdGetDatum(commId));
 
        pg_operator_scan = heap_beginscan(pg_operator_desc,
                                                                          0,
@@ -905,15 +899,21 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                                                                           nulls,
                                                                           replaces);
 
-                               setheapoverride(true);
-                               heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
-                               setheapoverride(false);
+                               simple_heap_update(pg_operator_desc, &tup->t_self, tup);
+
+                               if (RelationGetForm(pg_operator_desc)->relhasindex)
+                               {
+                                       Relation        idescs[Num_pg_operator_indices];
 
+                                       CatalogOpenIndices(Num_pg_operator_indices, Name_pg_operator_indices, idescs);
+                                       CatalogIndexInsert(idescs, Num_pg_operator_indices, pg_operator_desc, tup);
+                                       CatalogCloseIndices(Num_pg_operator_indices, idescs);
+                               }
                        }
                }
                heap_endscan(pg_operator_scan);
 
-               heap_close(pg_operator_desc);
+               heap_close(pg_operator_desc, RowExclusiveLock);
 
                return;
        }
@@ -931,9 +931,16 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                                                           nulls,
                                                           replaces);
 
-               setheapoverride(true);
-               heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
-               setheapoverride(false);
+               simple_heap_update(pg_operator_desc, &tup->t_self, tup);
+
+               if (RelationGetForm(pg_operator_desc)->relhasindex)
+               {
+                       Relation        idescs[Num_pg_operator_indices];
+
+                       CatalogOpenIndices(Num_pg_operator_indices, Name_pg_operator_indices, idescs);
+                       CatalogIndexInsert(idescs, Num_pg_operator_indices, pg_operator_desc, tup);
+                       CatalogCloseIndices(Num_pg_operator_indices, idescs);
+               }
 
                values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;
                replaces[Anum_pg_operator_oprcom - 1] = ' ';
@@ -962,14 +969,21 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                                                           nulls,
                                                           replaces);
 
-               setheapoverride(true);
-               heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
-               setheapoverride(false);
+               simple_heap_update(pg_operator_desc, &tup->t_self, tup);
+
+               if (RelationGetForm(pg_operator_desc)->relhasindex)
+               {
+                       Relation        idescs[Num_pg_operator_indices];
+
+                       CatalogOpenIndices(Num_pg_operator_indices, Name_pg_operator_indices, idescs);
+                       CatalogIndexInsert(idescs, Num_pg_operator_indices, pg_operator_desc, tup);
+                       CatalogCloseIndices(Num_pg_operator_indices, idescs);
+               }
        }
 
        heap_endscan(pg_operator_scan);
 
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, RowExclusiveLock);
 }
 
 
@@ -1009,28 +1023,25 @@ OperatorCreate(char *operatorName,
                           char *rightSortName)
 {
        if (!leftTypeName && !rightTypeName)
-               elog(ERROR, "OperatorCreate: at least one of leftarg or rightarg must be defined");
+               elog(ERROR, "at least one of leftarg or rightarg must be specified");
 
        if (!(leftTypeName && rightTypeName))
        {
                /* If it's not a binary op, these things mustn't be set: */
                if (commutatorName)
-                       elog(ERROR, "OperatorCreate: only binary operators can have commutators");
-               if (negatorName)
-                       elog(ERROR, "OperatorCreate: only binary operators can have negators");
-               if (restrictionName || joinName)
-                       elog(ERROR, "OperatorCreate: only binary operators can have selectivity");
+                       elog(ERROR, "only binary operators can have commutators");
+               if (joinName)
+                       elog(ERROR, "only binary operators can have join selectivity");
                if (canHash)
-                       elog(ERROR, "OperatorCreate: only binary operators can hash");
+                       elog(ERROR, "only binary operators can hash");
                if (leftSortName || rightSortName)
-                       elog(ERROR, "OperatorCreate: only binary operators can have sort links");
+                       elog(ERROR, "only binary operators can have sort links");
        }
 
-       /* ----------------
-        *      Use OperatorDef() to define the specified operator and
-        *      also create shells for the operator's associated operators
-        *      if they don't already exist.
-        * ----------------
+       /*
+        * Use OperatorDef() to define the specified operator and also create
+        * shells for the operator's associated operators if they don't
+        * already exist.
         */
        OperatorDef(operatorName,
                                leftTypeName,