]> granicus.if.org Git - postgresql/commitdiff
Cross-data-type comparisons are now indexable by btrees, pursuant to my
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 12 Nov 2003 21:15:59 +0000 (21:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 12 Nov 2003 21:15:59 +0000 (21:15 +0000)
pghackers proposal of 8-Nov.  All the existing cross-type comparison
operators (int2/int4/int8 and float4/float8) have appropriate support.
The original proposal of storing the right-hand-side datatype as part of
the primary key for pg_amop and pg_amproc got modified a bit in the event;
it is easier to store zero as the 'default' case and only store a nonzero
when the operator is actually cross-type.  Along the way, remove the
long-since-defunct bigbox_ops operator class.

76 files changed:
contrib/dblink/dblink.c
contrib/miscutil/misc_utils.c
doc/src/sgml/catalogs.sgml
doc/src/sgml/xindex.sgml
src/backend/access/common/scankey.c
src/backend/access/gist/gistget.c
src/backend/access/gist/gistscan.c
src/backend/access/heap/tuptoaster.c
src/backend/access/nbtree/nbtcompare.c
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtree.c
src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtsort.c
src/backend/access/nbtree/nbtutils.c
src/backend/access/rtree/rtproc.c
src/backend/access/rtree/rtscan.c
src/backend/catalog/aclchk.c
src/backend/catalog/dependency.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/pg_constraint.c
src/backend/catalog/pg_conversion.c
src/backend/catalog/pg_depend.c
src/backend/catalog/pg_largeobject.c
src/backend/commands/async.c
src/backend/commands/cluster.c
src/backend/commands/comment.c
src/backend/commands/dbcommands.c
src/backend/commands/functioncmds.c
src/backend/commands/indexcmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/tablecmds.c
src/backend/commands/trigger.c
src/backend/commands/typecmds.c
src/backend/commands/user.c
src/backend/commands/vacuum.c
src/backend/executor/nodeIndexscan.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/util/plancat.c
src/backend/parser/parse_func.c
src/backend/rewrite/rewriteRemove.c
src/backend/storage/large_object/inv_api.c
src/backend/utils/adt/float.c
src/backend/utils/adt/regproc.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/cache/catcache.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/syscache.c
src/backend/utils/cache/typcache.c
src/backend/utils/init/postinit.c
src/backend/utils/sort/tuplesort.c
src/include/access/nbtree.h
src/include/access/skey.h
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/namespace.h
src/include/catalog/pg_amop.h
src/include/catalog/pg_amproc.h
src/include/catalog/pg_opclass.h
src/include/catalog/pg_proc.h
src/include/nodes/plannodes.h
src/include/utils/builtins.h
src/include/utils/geo_decls.h
src/include/utils/lsyscache.h
src/include/utils/rel.h
src/test/regress/expected/create_index.out
src/test/regress/expected/oidjoins.out
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/create_index.sql
src/test/regress/sql/oidjoins.sql
src/test/regress/sql/opr_sanity.sql

index 5728682ccc8d600ae9e3b64eba0599d8aad5c830..bb601c5436acc0cd8fa9993e11c7da0bfc4fb497 100644 (file)
@@ -1357,10 +1357,10 @@ get_pkey_attnames(Oid relid, int16 *numatts)
 
        /* use relid to get all related indexes */
        indexRelation = heap_openr(IndexRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry, 0,
-                                                  Anum_pg_index_indrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
+       ScanKeyInit(&entry,
+                               Anum_pg_index_indrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
        scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry);
 
        while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
index bf84f3b3c2e120cc2b828a2023b71e0143205a0d..fb121e83803b3f7f0282242ee34085fc5f7fe53c 100644 (file)
@@ -21,7 +21,6 @@
 #include "access/tupdesc.h"
 #include "catalog/catname.h"
 #include "catalog/pg_listener.h"
-#include "catalog/pg_type.h"
 #include "commands/async.h"
 #include "fmgr.h"
 #include "storage/lmgr.h"
@@ -87,10 +86,10 @@ active_listeners(text *relname)
                MemSet(listen_name, 0, NAMEDATALEN);
                len = MIN(VARSIZE(relname) - VARHDRSZ, NAMEDATALEN - 1);
                memcpy(listen_name, VARDATA(relname), len);
-               ScanKeyEntryInitialize(&key, 0,
-                                                          Anum_pg_listener_relname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          PointerGetDatum(listen_name), NAMEOID);
+               ScanKeyInit(&key,
+                                       Anum_pg_listener_relname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       PointerGetDatum(listen_name));
                sRel = heap_beginscan(lRel, SnapshotNow, 1, &key);
        }
        else
index bd208906dfe50f965eb1a3fa6a58339d176411c2..37f8b9cd659025f201c3f2d582861db59ce63e09 100644 (file)
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.78 2003/11/02 12:53:57 petere Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.79 2003/11/12 21:15:42 tgl Exp $
  -->
 
 <chapter id="catalogs">
       <entry>The index operator class this entry is for</entry>
      </row>
 
+     <row>
+      <entry><structfield>amopsubtype</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
+      <entry>Subtype to distinguish multiple entries for one strategy;
+             zero for default</entry>
+     </row>
+
      <row>
       <entry><structfield>amopstrategy</structfield></entry>
       <entry><type>int2</type></entry>
       <entry>The index operator class this entry is for</entry>
      </row>
 
+     <row>
+      <entry><structfield>amprocsubtype</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
+      <entry>Subtype, if cross-type routine, else zero</entry>
+     </row>
+
      <row>
       <entry><structfield>amprocnum</structfield></entry>
       <entry><type>int2</type></entry>
       <entry><structfield>opcintype</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
-      <entry>Input data type of the operator class</entry>
+      <entry>Data type that the operator class indexes</entry>
      </row>
 
      <row>
       <entry><structfield>opckeytype</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
-      <entry>Type of index data, or zero if same as <structfield>opcintype</></entry>
+      <entry>Type of data stored in index, or zero if same as <structfield>opcintype</></entry>
      </row>
 
     </tbody>
index 85aba8abe7058d61aa4990336bb2b83905d82e71..877709cee687d83447b0f623a288bb776834cd80 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.34 2003/11/01 01:56:29 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.35 2003/11/12 21:15:45 tgl Exp $
 -->
 
 <sect1 id="xindex">
@@ -80,7 +80,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.34 2003/11/01 01:56:29 pete
    The same operator class name
    can be used for several different index methods (for example, both B-tree
    and hash index methods have operator classes named
-   <literal>oid_ops</literal>), but each such class is an independent
+   <literal>int4_ops</literal>), but each such class is an independent
    entity and must be defined separately.
   </para>
  </sect2>
@@ -589,6 +589,71 @@ CREATE OPERATOR CLASS complex_abs_ops
   </para>
  </sect2>
 
+ <sect2 id="xindex-opclass-crosstype">
+  <title>Cross-Data-Type Operator Classes</title>
+
+  <para>
+   So far we have implicitly assumed that an operator class deals with
+   only one data type.  While there certainly can be only one data type in
+   a particular index column, it is often useful to index operations that
+   compare an indexed column to a value of a different data type.  This is
+   presently supported by the B-tree and GiST index methods.
+  </para>
+
+  <para>
+   B-trees require the left-hand operand of each operator to be the indexed
+   data type, but the right-hand operand can be of a different type.  There
+   must be a support function having a matching signature.  For example,
+   the built-in operator class for type <type>bigint</> (<type>int8</>)
+   allows cross-type comparisons to <type>int4</> and <type>int2</>.  It
+   could be duplicated by this definition:
+
+<programlisting>
+CREATE OPERATOR CLASS int8_ops
+DEFAULT FOR TYPE int8 USING btree AS
+  -- standard int8 comparisons
+  OPERATOR 1 &lt; ,
+  OPERATOR 2 &lt;= ,
+  OPERATOR 3 = ,
+  OPERATOR 4 &gt;= ,
+  OPERATOR 5 &gt; ,
+  FUNCTION 1 btint8cmp(int8, int8) ,
+
+  -- cross-type comparisons to int2 (smallint)
+  OPERATOR 1 &lt; (int8, int2) ,
+  OPERATOR 2 &lt;= (int8, int2) ,
+  OPERATOR 3 = (int8, int2) ,
+  OPERATOR 4 &gt;= (int8, int2) ,
+  OPERATOR 5 &gt; (int8, int2) ,
+  FUNCTION 1 btint82cmp(int8, int2) ,
+
+  -- cross-type comparisons to int4 (integer)
+  OPERATOR 1 &lt; (int8, int4) ,
+  OPERATOR 2 &lt;= (int8, int4) ,
+  OPERATOR 3 = (int8, int4) ,
+  OPERATOR 4 &gt;= (int8, int4) ,
+  OPERATOR 5 &gt; (int8, int4) ,
+  FUNCTION 1 btint84cmp(int8, int4) ;
+</programlisting>
+
+   Notice that this definition <quote>overloads</> the operator strategy and
+   support function numbers.  This is allowed (for B-tree operator classes
+   only) so long as each instance of a particular number has a different
+   right-hand data type.  The instances that are not cross-type are the
+   default or primary operators of the operator class.
+  </para>
+
+  <para>
+   GiST indexes do not allow overloading of strategy or support function
+   numbers, but it is still possible to get the effect of supporting
+   multiple right-hand data types, by assigning a distinct strategy number
+   to each operator that needs to be supported.  The <literal>consistent</>
+   support function must determine what it needs to do based on the strategy
+   number, and must be prepared to accept comparison values of the appropriate
+   data types.
+  </para>
+ </sect2>
+
  <sect2 id="xindex-opclass-dependencies">
   <title>System Dependencies on Operator Classes</title>
 
index 93741cbb849d9e8673f8cc9d380fdb6951dce7a3..2fa02b7d91ffeb62e22a2985db061b900f8c7e87 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.23 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.24 2003/11/12 21:15:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,15 +31,43 @@ ScanKeyEntryInitialize(ScanKey entry,
                                           int flags,
                                           AttrNumber attributeNumber,
                                           StrategyNumber strategy,
+                                          Oid subtype,
                                           RegProcedure procedure,
-                                          Datum argument,
-                                          Oid argtype)
+                                          Datum argument)
 {
        entry->sk_flags = flags;
        entry->sk_attno = attributeNumber;
        entry->sk_strategy = strategy;
+       entry->sk_subtype = subtype;
+       entry->sk_argument = argument;
+       fmgr_info(procedure, &entry->sk_func);
+}
+
+/*
+ * ScanKeyInit
+ *             Shorthand version of ScanKeyEntryInitialize: flags and subtype
+ *             are assumed to be zero (the usual value).
+ *
+ * This is the recommended version for hardwired lookups in system catalogs.
+ * It cannot handle NULL arguments, unary operators, or nondefault operators,
+ * but we need none of those features for most hardwired lookups.
+ *
+ * Note: CurrentMemoryContext at call should be as long-lived as the ScanKey
+ * itself, because that's what will be used for any subsidiary info attached
+ * to the ScanKey's FmgrInfo record.
+ */
+void
+ScanKeyInit(ScanKey entry,
+                       AttrNumber attributeNumber,
+                       StrategyNumber strategy,
+                       RegProcedure procedure,
+                       Datum argument)
+{
+       entry->sk_flags = 0;
+       entry->sk_attno = attributeNumber;
+       entry->sk_strategy = strategy;
+       entry->sk_subtype = InvalidOid;
        entry->sk_argument = argument;
-       entry->sk_argtype = argtype;
        fmgr_info(procedure, &entry->sk_func);
 }
 
@@ -57,14 +85,14 @@ ScanKeyEntryInitializeWithInfo(ScanKey entry,
                                                           int flags,
                                                           AttrNumber attributeNumber,
                                                           StrategyNumber strategy,
+                                                          Oid subtype,
                                                           FmgrInfo *finfo,
-                                                          Datum argument,
-                                                          Oid argtype)
+                                                          Datum argument)
 {
        entry->sk_flags = flags;
        entry->sk_attno = attributeNumber;
        entry->sk_strategy = strategy;
+       entry->sk_subtype = subtype;
        entry->sk_argument = argument;
-       entry->sk_argtype = argtype;
        fmgr_info_copy(&entry->sk_func, finfo, CurrentMemoryContext);
 }
index 24168c992693c18d48ab5355cf2a68384233dca4..5db69a6b40a0638c666933570db53ea81c9719f4 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.37 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.38 2003/11/12 21:15:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -221,40 +221,50 @@ gistindex_keytest(IndexTuple tuple,
                                  Page p,
                                  OffsetNumber offset)
 {
-       bool            isNull;
-       Datum           datum;
-       Datum           test;
-       GISTENTRY       de;
-
        IncrIndexProcessed();
 
        while (scanKeySize > 0)
        {
+               Datum           datum;
+               bool            isNull;
+               Datum           test;
+               GISTENTRY       de;
+
                datum = index_getattr(tuple,
-                                                         key[0].sk_attno,
+                                                         key->sk_attno,
                                                          giststate->tupdesc,
                                                          &isNull);
+               /* is the index entry NULL? */
                if (isNull)
                {
                        /* XXX eventually should check if SK_ISNULL */
                        return false;
                }
-
-/* this code from backend/access/common/indexvalid.c. But why and what???
-               if (key[0].sk_flags & SK_ISNULL)
+               /* is the compared-to datum NULL? */
+               if (key->sk_flags & SK_ISNULL)
                        return false;
-*/
-               gistdentryinit(giststate, key[0].sk_attno - 1, &de,
+
+               gistdentryinit(giststate, key->sk_attno - 1, &de,
                                           datum, r, p, offset,
                                           IndexTupleSize(tuple) - sizeof(IndexTupleData),
                                           FALSE, isNull);
 
-               test = FunctionCall3(&key[0].sk_func,
+               /*
+                * Call the Consistent function to evaluate the test.  The arguments
+                * are the index datum (as a GISTENTRY*), the comparison datum, and
+                * the comparison operator's strategy number and subtype from pg_amop.
+                *
+                * (Presently there's no need to pass the subtype since it'll always
+                * be zero, but might as well pass it for possible future use.)
+                */
+               test = FunctionCall4(&key->sk_func,
                                                         PointerGetDatum(&de),
-                                                        key[0].sk_argument,
-                                                        Int32GetDatum(key[0].sk_strategy));
+                                                        key->sk_argument,
+                                                        Int32GetDatum(key->sk_strategy),
+                                                        ObjectIdGetDatum(key->sk_subtype));
 
-               if (de.key != datum && !isAttByVal(giststate, key[0].sk_attno - 1))
+               /* if index datum had to be decompressed, free it */
+               if (de.key != datum && !isAttByVal(giststate, key->sk_attno - 1))
                        if (DatumGetPointer(de.key) != NULL)
                                pfree(DatumGetPointer(de.key));
 
@@ -264,6 +274,7 @@ gistindex_keytest(IndexTuple tuple,
                scanKeySize--;
                key++;
        }
+
        return true;
 }
 
index 960d1c2f25bcd207855ac5043c2b5fd0bbf4bd83..9b9d1f603411c44d053a6aaaba17ef676c1de724 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.48 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.49 2003/11/12 21:15:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -109,7 +109,8 @@ gistrescan(PG_FUNCTION_ARGS)
                 * Modify the scan key so that the Consistent function is called
                 * for all comparisons.  The original operator is passed to the
                 * Consistent function in the form of its strategy number, which
-                * is available from the sk_strategy field.
+                * is available from the sk_strategy field, and its subtype from
+                * the sk_subtype field.
                 */
                for (i = 0; i < s->numberOfKeys; i++)
                {
index 0bfe3c01b8fa55be8d825e5f39dde98c02dff504..f643906da1f92bfce24f69f7875f00cb7dfcf244 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.39 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.40 2003/11/12 21:15:46 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -31,7 +31,6 @@
 #include "access/genam.h"
 #include "access/tuptoaster.h"
 #include "catalog/catalog.h"
-#include "catalog/pg_type.h"
 #include "utils/rel.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -968,11 +967,10 @@ toast_delete_datum(Relation rel, Datum value)
         * Setup a scan key to fetch from the index by va_valueid (we don't
         * particularly care whether we see them in sequence or not)
         */
-       ScanKeyEntryInitialize(&toastkey, 0,
-                                                  (AttrNumber) 1,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(attr->va_content.va_external.va_valueid),
-                                                  OIDOID);
+       ScanKeyInit(&toastkey,
+                               (AttrNumber) 1,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
 
        /*
         * Find the chunks by index
@@ -1040,11 +1038,10 @@ toast_fetch_datum(varattrib *attr)
        /*
         * Setup a scan key to fetch from the index by va_valueid
         */
-       ScanKeyEntryInitialize(&toastkey, 0,
-                                                  (AttrNumber) 1,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(attr->va_content.va_external.va_valueid),
-                                                  OIDOID);
+       ScanKeyInit(&toastkey,
+                               (AttrNumber) 1,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
 
        /*
         * Read the chunks by index
@@ -1195,33 +1192,32 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
         * Setup a scan key to fetch from the index. This is either two keys
         * or three depending on the number of chunks.
         */
-       ScanKeyEntryInitialize(&toastkey[0], 0,
-                                                  (AttrNumber) 1,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(attr->va_content.va_external.va_valueid),
-                                                  OIDOID);
+       ScanKeyInit(&toastkey[0],
+                               (AttrNumber) 1,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
 
        /*
         * Use equality condition for one chunk, a range condition otherwise:
         */
        if (numchunks == 1)
        {
-               ScanKeyEntryInitialize(&toastkey[1], 0,
-                                                          (AttrNumber) 2,
-                                                          BTEqualStrategyNumber, F_INT4EQ,
-                                                          Int32GetDatum(startchunk), INT4OID);
+               ScanKeyInit(&toastkey[1],
+                                       (AttrNumber) 2,
+                                       BTEqualStrategyNumber, F_INT4EQ,
+                                       Int32GetDatum(startchunk));
                nscankeys = 2;
        }
        else
        {
-               ScanKeyEntryInitialize(&toastkey[1], 0,
-                                                          (AttrNumber) 2,
-                                                          BTGreaterEqualStrategyNumber, F_INT4GE,
-                                                          Int32GetDatum(startchunk), INT4OID);
-               ScanKeyEntryInitialize(&toastkey[2], 0,
-                                                          (AttrNumber) 2,
-                                                          BTLessEqualStrategyNumber, F_INT4LE,
-                                                          Int32GetDatum(endchunk), INT4OID);
+               ScanKeyInit(&toastkey[1],
+                                       (AttrNumber) 2,
+                                       BTGreaterEqualStrategyNumber, F_INT4GE,
+                                       Int32GetDatum(startchunk));
+               ScanKeyInit(&toastkey[2],
+                                       (AttrNumber) 2,
+                                       BTLessEqualStrategyNumber, F_INT4LE,
+                                       Int32GetDatum(endchunk));
                nscankeys = 3;
        }
 
index 79756513abf72e340d42c73c2eddc469d1fba673..bd6988583050e34dd612d93390e90e31160ab395 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.46 2003/08/04 02:39:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.47 2003/11/12 21:15:46 tgl Exp $
  *
  * NOTES
  *
@@ -97,6 +97,90 @@ btint8cmp(PG_FUNCTION_ARGS)
                PG_RETURN_INT32(-1);
 }
 
+Datum
+btint48cmp(PG_FUNCTION_ARGS)
+{
+       int32           a = PG_GETARG_INT32(0);
+       int64           b = PG_GETARG_INT64(1);
+
+       if (a > b)
+               PG_RETURN_INT32(1);
+       else if (a == b)
+               PG_RETURN_INT32(0);
+       else
+               PG_RETURN_INT32(-1);
+}
+
+Datum
+btint84cmp(PG_FUNCTION_ARGS)
+{
+       int64           a = PG_GETARG_INT64(0);
+       int32           b = PG_GETARG_INT32(1);
+
+       if (a > b)
+               PG_RETURN_INT32(1);
+       else if (a == b)
+               PG_RETURN_INT32(0);
+       else
+               PG_RETURN_INT32(-1);
+}
+
+Datum
+btint24cmp(PG_FUNCTION_ARGS)
+{
+       int16           a = PG_GETARG_INT16(0);
+       int32           b = PG_GETARG_INT32(1);
+
+       if (a > b)
+               PG_RETURN_INT32(1);
+       else if (a == b)
+               PG_RETURN_INT32(0);
+       else
+               PG_RETURN_INT32(-1);
+}
+
+Datum
+btint42cmp(PG_FUNCTION_ARGS)
+{
+       int32           a = PG_GETARG_INT32(0);
+       int16           b = PG_GETARG_INT16(1);
+
+       if (a > b)
+               PG_RETURN_INT32(1);
+       else if (a == b)
+               PG_RETURN_INT32(0);
+       else
+               PG_RETURN_INT32(-1);
+}
+
+Datum
+btint28cmp(PG_FUNCTION_ARGS)
+{
+       int16           a = PG_GETARG_INT16(0);
+       int64           b = PG_GETARG_INT64(1);
+
+       if (a > b)
+               PG_RETURN_INT32(1);
+       else if (a == b)
+               PG_RETURN_INT32(0);
+       else
+               PG_RETURN_INT32(-1);
+}
+
+Datum
+btint82cmp(PG_FUNCTION_ARGS)
+{
+       int64           a = PG_GETARG_INT64(0);
+       int16           b = PG_GETARG_INT16(1);
+
+       if (a > b)
+               PG_RETURN_INT32(1);
+       else if (a == b)
+               PG_RETURN_INT32(0);
+       else
+               PG_RETURN_INT32(-1);
+}
+
 Datum
 btoidcmp(PG_FUNCTION_ARGS)
 {
index 98f3abb511fc28894fbe20b83fb94acd6f589cff..719b1e1f0ed9ca868fa7e099329f6c9a967987e4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.107 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.108 2003/11/12 21:15:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1577,26 +1577,27 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
 
        for (i = 1; i <= keysz; i++)
        {
-               ScanKey         entry = &scankey[i - 1];
                AttrNumber      attno;
                Datum           datum;
                bool            isNull;
                int32           result;
 
-               attno = entry->sk_attno;
+               attno = scankey->sk_attno;
                Assert(attno == i);
                datum = index_getattr(itup, attno, itupdesc, &isNull);
 
                /* NULLs are never equal to anything */
-               if ((entry->sk_flags & SK_ISNULL) || isNull)
+               if (isNull || (scankey->sk_flags & SK_ISNULL))
                        return false;
 
-               result = DatumGetInt32(FunctionCall2(&entry->sk_func,
-                                                                                        entry->sk_argument,
-                                                                                        datum));
+               result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
+                                                                                        datum,
+                                                                                        scankey->sk_argument));
 
                if (result != 0)
                        return false;
+
+               scankey++;
        }
 
        /* if we get here, the keys are equal */
index 3979f79c3585103c7e560ae2e26ab3c1097d0bbe..f920d2497ee65990d50c892bbdeb9f312dc186d3 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.106 2003/09/29 23:40:26 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.107 2003/11/12 21:15:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -397,7 +397,6 @@ btrescan(PG_FUNCTION_ARGS)
                        so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData));
                else
                        so->keyData = (ScanKey) NULL;
-               so->numberOfKeys = scan->numberOfKeys;
                scan->opaque = so;
        }
 
@@ -423,38 +422,14 @@ btrescan(PG_FUNCTION_ARGS)
         * _bt_first.      - vadim 05/05/97
         */
        if (scankey && scan->numberOfKeys > 0)
-       {
                memmove(scan->keyData,
                                scankey,
                                scan->numberOfKeys * sizeof(ScanKeyData));
-               so->numberOfKeys = scan->numberOfKeys;
-               memmove(so->keyData,
-                               scankey,
-                               so->numberOfKeys * sizeof(ScanKeyData));
-       }
+       so->numberOfKeys = 0;           /* until _bt_preprocess_keys sets it */
 
        PG_RETURN_VOID();
 }
 
-void
-btmovescan(IndexScanDesc scan, Datum v)
-{
-       ItemPointer iptr;
-       BTScanOpaque so;
-
-       so = (BTScanOpaque) scan->opaque;
-
-       /* we aren't holding any read locks, but gotta drop the pin */
-       if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
-       {
-               ReleaseBuffer(so->btso_curbuf);
-               so->btso_curbuf = InvalidBuffer;
-               ItemPointerSetInvalid(iptr);
-       }
-
-       so->keyData[0].sk_argument = v;
-}
-
 /*
  *     btendscan() -- close down a scan
  */
index 432a1ab0c2a26e4eba41f683310059f0bfba9560..87178d124245077c1a2ce34c6ae87d39170293c3 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.81 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.82 2003/11/12 21:15:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 
 #include "access/genam.h"
 #include "access/nbtree.h"
+#include "utils/lsyscache.h"
 
 
 static Buffer _bt_walk_left(Relation rel, Buffer buf);
@@ -325,17 +326,16 @@ _bt_compare(Relation rel,
         * (see _bt_first).
         */
 
-       for (i = 0; i < keysz; i++)
+       for (i = 1; i <= keysz; i++)
        {
-               ScanKey         entry = &scankey[i];
                Datum           datum;
                bool            isNull;
                int32           result;
 
-               datum = index_getattr(itup, entry->sk_attno, itupdesc, &isNull);
+               datum = index_getattr(itup, scankey->sk_attno, itupdesc, &isNull);
 
                /* see comments about NULLs handling in btbuild */
-               if (entry->sk_flags & SK_ISNULL)                /* key is NULL */
+               if (scankey->sk_flags & SK_ISNULL)              /* key is NULL */
                {
                        if (isNull)
                                result = 0;             /* NULL "=" NULL */
@@ -348,14 +348,28 @@ _bt_compare(Relation rel,
                }
                else
                {
-                       result = DatumGetInt32(FunctionCall2(&entry->sk_func,
-                                                                                                entry->sk_argument,
-                                                                                                datum));
+                       /*
+                        * The sk_func needs to be passed the index value as left arg
+                        * and the sk_argument as right arg (they might be of different
+                        * types).  Since it is convenient for callers to think of
+                        * _bt_compare as comparing the scankey to the index item,
+                        * we have to flip the sign of the comparison result.
+                        *
+                        * Note: curious-looking coding is to avoid overflow if
+                        * comparison function returns INT_MIN.  There is no risk of
+                        * overflow for positive results.
+                        */
+                       result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
+                                                                                                datum,
+                                                                                                scankey->sk_argument));
+                       result = (result < 0) ? 1 : -result;
                }
 
                /* if the keys are unequal, return the difference */
                if (result != 0)
                        return result;
+
+               scankey++;
        }
 
        /* if we get here, the keys are equal */
@@ -448,126 +462,203 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
        StrategyNumber strat;
        bool            res;
        int32           result;
-       bool            scanFromEnd;
        bool            continuescan;
        ScanKey         scankeys = NULL;
+       ScanKey    *startKeys = NULL;
        int                     keysCount = 0;
-       int                *nKeyIs = NULL;
-       int                     i,
-                               j;
+       int                     i;
        StrategyNumber strat_total;
 
        /*
-        * Order the scan keys in our canonical fashion and eliminate any
-        * redundant keys.
+        * Examine the scan keys and eliminate any redundant keys; also
+        * discover how many keys must be matched to continue the scan.
         */
-       _bt_orderkeys(scan);
+       _bt_preprocess_keys(scan);
 
        /*
-        * Quit now if _bt_orderkeys() discovered that the scan keys can never
-        * be satisfied (eg, x == 1 AND x > 2).
+        * Quit now if _bt_preprocess_keys() discovered that the scan keys can
+        * never be satisfied (eg, x == 1 AND x > 2).
         */
        if (!so->qual_ok)
                return false;
 
-       /*
+       /*----------
         * Examine the scan keys to discover where we need to start the scan.
+        *
+        * We want to identify the keys that can be used as starting boundaries;
+        * these are =, >, or >= keys for a forward scan or =, <, <= keys for
+        * a backwards scan.  We can use keys for multiple attributes so long as
+        * the prior attributes had only =, >= (resp. =, <=) keys.  Once we accept
+        * a > or < boundary or find an attribute with no boundary (which can be
+        * thought of as the same as "> -infinity"), we can't use keys for any
+        * attributes to its right, because it would break our simplistic notion
+        * of what initial positioning strategy to use.
+        *
+        * When the scan keys include non-default operators, _bt_preprocess_keys
+        * may not be able to eliminate redundant keys; in such cases we will
+        * arbitrarily pick a usable one for each attribute.  This is correct
+        * but possibly not optimal behavior.  (For example, with keys like
+        * "x >= 4 AND x >= 5" we would elect to scan starting at x=4 when
+        * x=5 would be more efficient.)  Since the situation only arises in
+        * hokily-worded queries, live with it.
+        *
+        * When both equality and inequality keys appear for a single attribute
+        * (again, only possible when non-default operators appear), we *must*
+        * select one of the equality keys for the starting point, because
+        * _bt_checkkeys() will stop the scan as soon as an equality qual fails.
+        * For example, if we have keys like "x >= 4 AND x = 10" and we elect to
+        * start at x=4, we will fail and stop before reaching x=10.  If multiple
+        * equality quals survive preprocessing, however, it doesn't matter which
+        * one we use --- by definition, they are either redundant or
+        * contradictory.
+        *----------
         */
-       scanFromEnd = false;
        strat_total = BTEqualStrategyNumber;
        if (so->numberOfKeys > 0)
        {
-               nKeyIs = (int *) palloc(so->numberOfKeys * sizeof(int));
-               for (i = 0; i < so->numberOfKeys; i++)
-               {
-                       AttrNumber      attno = so->keyData[i].sk_attno;
-
-                       /* ignore keys for already-determined attrs */
-                       if (attno <= keysCount)
-                               continue;
-                       /* if we didn't find a boundary for the preceding attr, quit */
-                       if (attno > keysCount + 1)
-                               break;
+               AttrNumber      curattr;
+               ScanKey         chosen;
+               ScanKey         cur;
 
-                       /*
-                        * Can we use this key as a starting boundary for this attr?
-                        *
-                        * We can use multiple keys if they look like, say, = >= = but we
-                        * have to stop after accepting a > or < boundary.
-                        */
-                       strat = so->keyData[i].sk_strategy;
-                       if (strat == strat_total ||
-                               strat == BTEqualStrategyNumber)
-                               nKeyIs[keysCount++] = i;
-                       else if (ScanDirectionIsBackward(dir) &&
-                                        (strat == BTLessStrategyNumber ||
-                                         strat == BTLessEqualStrategyNumber))
+               startKeys = (ScanKey *) palloc(so->numberOfKeys * sizeof(ScanKey));
+               /*
+                * chosen is the so-far-chosen key for the current attribute, if any.
+                * We don't cast the decision in stone until we reach keys for the
+                * next attribute.
+                */
+               curattr = 1;
+               chosen = NULL;
+               /*
+                * Loop iterates from 0 to numberOfKeys inclusive; we use the last
+                * pass to handle after-last-key processing.  Actual exit from the
+                * loop is at one of the "break" statements below.
+                */
+               for (cur = so->keyData, i = 0;; cur++, i++)
+               {
+                       if (i >= so->numberOfKeys || cur->sk_attno != curattr)
                        {
-                               nKeyIs[keysCount++] = i;
-                               strat_total = strat;
-                               if (strat == BTLessStrategyNumber)
+                               /*
+                                * Done looking at keys for curattr.  If we didn't find a
+                                * usable boundary key, quit; else save the boundary key
+                                * pointer in startKeys.
+                                */
+                               if (chosen == NULL)
+                                       break;
+                               startKeys[keysCount++] = chosen;
+                               /*
+                                * Adjust strat_total, and quit if we have stored a > or < key.
+                                */
+                               strat = chosen->sk_strategy;
+                               if (strat != BTEqualStrategyNumber)
+                               {
+                                       strat_total = strat;
+                                       if (strat == BTGreaterStrategyNumber ||
+                                               strat == BTLessStrategyNumber)
+                                               break;
+                               }
+                               /*
+                                * Done if that was the last attribute.
+                                */
+                               if (i >= so->numberOfKeys)
                                        break;
+                               /*
+                                * Reset for next attr, which should be in sequence.
+                                */
+                               Assert(cur->sk_attno == curattr + 1);
+                               curattr = cur->sk_attno;
+                               chosen = NULL;
                        }
-                       else if (ScanDirectionIsForward(dir) &&
-                                        (strat == BTGreaterStrategyNumber ||
-                                         strat == BTGreaterEqualStrategyNumber))
+
+                       /* Can we use this key as a starting boundary for this attr? */
+                       switch (cur->sk_strategy)
                        {
-                               nKeyIs[keysCount++] = i;
-                               strat_total = strat;
-                               if (strat == BTGreaterStrategyNumber)
+                               case BTLessStrategyNumber:
+                               case BTLessEqualStrategyNumber:
+                                       if (chosen == NULL && ScanDirectionIsBackward(dir))
+                                               chosen = cur;
+                                       break;
+                               case BTEqualStrategyNumber:
+                                       /* override any non-equality choice */
+                                       chosen = cur;
+                                       break;
+                               case BTGreaterEqualStrategyNumber:
+                               case BTGreaterStrategyNumber:
+                                       if (chosen == NULL && ScanDirectionIsForward(dir))
+                                               chosen = cur;
                                        break;
                        }
                }
-               if (keysCount == 0)
-                       scanFromEnd = true;
        }
-       else
-               scanFromEnd = true;
 
-       /* if we just need to walk down one edge of the tree, do that */
-       if (scanFromEnd)
+       /*
+        * If we found no usable boundary keys, we have to start from one end
+        * of the tree.  Walk down that edge to the first or last key, and
+        * scan from there.
+        */
+       if (keysCount == 0)
        {
-               if (nKeyIs)
-                       pfree(nKeyIs);
+               if (startKeys)
+                       pfree(startKeys);
                return _bt_endpoint(scan, dir);
        }
 
        /*
         * We want to start the scan somewhere within the index.  Set up a
-        * scankey we can use to search for the correct starting point.
+        * 3-way-comparison scankey we can use to search for the boundary
+        * point we identified above.
         */
        scankeys = (ScanKey) palloc(keysCount * sizeof(ScanKeyData));
        for (i = 0; i < keysCount; i++)
        {
-               FmgrInfo   *procinfo;
-
-               j = nKeyIs[i];
+               ScanKey         cur = startKeys[i];
 
                /*
-                * _bt_orderkeys disallows it, but it's place to add some code
+                * _bt_preprocess_keys disallows it, but it's place to add some code
                 * later
                 */
-               if (so->keyData[j].sk_flags & SK_ISNULL)
+               if (cur->sk_flags & SK_ISNULL)
                {
-                       pfree(nKeyIs);
+                       pfree(startKeys);
                        pfree(scankeys);
                        elog(ERROR, "btree doesn't support is(not)null, yet");
                        return false;
                }
                /*
-                * XXX what if sk_argtype is not same as index?
+                * If scankey operator is of default subtype, we can use the
+                * cached comparison procedure; otherwise gotta look it up in
+                * the catalogs.
                 */
-               procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
-               ScanKeyEntryInitializeWithInfo(scankeys + i,
-                                                                          so->keyData[j].sk_flags,
-                                                                          i + 1,
-                                                                          InvalidStrategy,
-                                                                          procinfo,
-                                                                          so->keyData[j].sk_argument,
-                                                                          so->keyData[j].sk_argtype);
+               if (cur->sk_subtype == InvalidOid)
+               {
+                       FmgrInfo   *procinfo;
+
+                       procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
+                       ScanKeyEntryInitializeWithInfo(scankeys + i,
+                                                                                  cur->sk_flags,
+                                                                                  i + 1,
+                                                                                  InvalidStrategy,
+                                                                                  InvalidOid,
+                                                                                  procinfo,
+                                                                                  cur->sk_argument);
+               }
+               else
+               {
+                       RegProcedure cmp_proc;
+
+                       cmp_proc = get_opclass_proc(rel->rd_index->indclass[i],
+                                                                               cur->sk_subtype,
+                                                                               BTORDER_PROC);
+                       ScanKeyEntryInitialize(scankeys + i,
+                                                                  cur->sk_flags,
+                                                                  i + 1,
+                                                                  InvalidStrategy,
+                                                                  cur->sk_subtype,
+                                                                  cmp_proc,
+                                                                  cur->sk_argument);
+               }
        }
-       if (nKeyIs)
-               pfree(nKeyIs);
+
+       pfree(startKeys);
 
        current = &(scan->currentItemData);
 
@@ -607,7 +698,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
         *
         * We could step forward in the latter case, but that'd be a waste of
         * time if we want to scan backwards.  So, it's now time to examine
-        * the scan strategy to find the exact place to start the scan.
+        * the initial-positioning strategy to find the exact place to start
+        * the scan.
         *
         * Note: if _bt_step fails (meaning we fell off the end of the index in
         * one direction or the other), we either return false (no matches) or
@@ -855,8 +947,8 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
                }
        }
        else
-/* backwards scan */
        {
+               /* backwards scan */
                if (offnum > P_FIRSTDATAKEY(opaque))
                        offnum = OffsetNumberPrev(offnum);
                else
@@ -1115,7 +1207,8 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
 }
 
 /*
- *     _bt_endpoint() -- Find the first or last key in the index.
+ *     _bt_endpoint() -- Find the first or last key in the index, and scan
+ * from there to the first key satisfying all the quals.
  *
  * This is used by _bt_first() to set up a scan when we've determined
  * that the scan must start at the beginning or end of the index (for
@@ -1205,7 +1298,9 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
        btitem = (BTItem) PageGetItem(page, PageGetItemId(page, start));
        itup = &(btitem->bti_itup);
 
-       /* see if we picked a winner */
+       /*
+        * Okay, we are on the first or last tuple.  Does it pass all the quals?
+        */
        if (_bt_checkkeys(scan, itup, dir, &continuescan))
        {
                /* yes, return it */
@@ -1214,7 +1309,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
        }
        else if (continuescan)
        {
-               /* no, but there might be another one that is */
+               /* no, but there might be another one that does */
                res = _bt_next(scan, dir);
        }
        else
index a56665be5c4642830917868dc5f0a235aac9160a..ed920eafd33dfff13d267459175b61c9ebe041ec 100644 (file)
@@ -36,7 +36,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.77 2003/09/29 23:40:26 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.78 2003/11/12 21:15:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -594,33 +594,37 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
                 * Another BTSpool for dead tuples exists. Now we have to merge
                 * btspool and btspool2.
                 */
-               ScanKey         entry;
-               Datum           attrDatum1,
-                                       attrDatum2;
-               bool            isFirstNull,
-                                       isSecondNull;
-               int32           compare;
 
                /* the preparation of merge */
-               bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free);
-               bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, true, &should_free2);
+               bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
+                                                                                          true, &should_free);
+               bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate,
+                                                                                               true, &should_free2);
                indexScanKey = _bt_mkscankey_nodata(index);
+
                for (;;)
                {
                        load1 = true;           /* load BTSpool next ? */
-                       if (NULL == bti2)
+                       if (bti2 == NULL)
                        {
-                               if (NULL == bti)
+                               if (bti == NULL)
                                        break;
                        }
-                       else if (NULL != bti)
+                       else if (bti != NULL)
                        {
-
                                for (i = 1; i <= keysz; i++)
                                {
+                                       ScanKey         entry;
+                                       Datum           attrDatum1,
+                                                               attrDatum2;
+                                       bool            isFirstNull,
+                                                               isSecondNull;
+
                                        entry = indexScanKey + i - 1;
-                                       attrDatum1 = index_getattr((IndexTuple) bti, i, tupdes, &isFirstNull);
-                                       attrDatum2 = index_getattr((IndexTuple) bti2, i, tupdes, &isSecondNull);
+                                       attrDatum1 = index_getattr((IndexTuple) bti, i, tupdes,
+                                                                                          &isFirstNull);
+                                       attrDatum2 = index_getattr((IndexTuple) bti2, i, tupdes,
+                                                                                          &isSecondNull);
                                        if (isFirstNull)
                                        {
                                                if (!isSecondNull)
@@ -633,7 +637,11 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
                                                break;
                                        else
                                        {
-                                               compare = DatumGetInt32(FunctionCall2(&entry->sk_func, attrDatum1, attrDatum2));
+                                               int32           compare;
+
+                                               compare = DatumGetInt32(FunctionCall2(&entry->sk_func,
+                                                                                                                         attrDatum1,
+                                                                                                                         attrDatum2));
                                                if (compare > 0)
                                                {
                                                        load1 = false;
@@ -656,14 +664,16 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
                                _bt_buildadd(index, state, bti);
                                if (should_free)
                                        pfree((void *) bti);
-                               bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free);
+                               bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
+                                                                                                          true, &should_free);
                        }
                        else
                        {
                                _bt_buildadd(index, state, bti2);
                                if (should_free2)
                                        pfree((void *) bti2);
-                               bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, true, &should_free2);
+                               bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate,
+                                                                                                               true, &should_free2);
                        }
                }
                _bt_freeskey(indexScanKey);
@@ -671,7 +681,8 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2)
        else
        {
                /* merge is unnecessary */
-               while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL)
+               while ((bti = (BTItem) tuplesort_getindextuple(btspool->sortstate,
+                                                                                               true, &should_free)) != NULL)
                {
                        /* When we see first tuple, create first index page */
                        if (state == NULL)
index 54cd7c8cd018a9b5150cc3054bc541d6d7de51da..2c9fd741ff39aa4959ca7665bbcd4d9936c64ced 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.55 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.56 2003/11/12 21:15:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,6 @@
 #include "access/nbtree.h"
 #include "catalog/catalog.h"
 #include "executor/execdebug.h"
-#include "utils/lsyscache.h"
 
 
 /*
@@ -49,8 +48,8 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
                bool            null;
 
                /*
-                * We can use the cached support procs since no cross-type comparison
-                * can be needed.
+                * We can use the cached (default) support procs since no cross-type
+                * comparison can be needed.
                 */
                procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
                arg = index_getattr(itup, i + 1, itupdesc, &null);
@@ -58,9 +57,9 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
                                                                           null ? SK_ISNULL : 0,
                                                                           (AttrNumber) (i + 1),
                                                                           InvalidStrategy,
+                                                                          InvalidOid,
                                                                           procinfo,
-                                                                          arg,
-                                                                          itupdesc->attrs[i]->atttypid);
+                                                                          arg);
        }
 
        return skey;
@@ -94,17 +93,17 @@ _bt_mkscankey_nodata(Relation rel)
                FmgrInfo   *procinfo;
 
                /*
-                * We can use the cached support procs since no cross-type comparison
-                * can be needed.
+                * We can use the cached (default) support procs since no cross-type
+                * comparison can be needed.
                 */
                procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
                ScanKeyEntryInitializeWithInfo(&skey[i],
                                                                           SK_ISNULL,
                                                                           (AttrNumber) (i + 1),
                                                                           InvalidStrategy,
+                                                                          InvalidOid,
                                                                           procinfo,
-                                                                          (Datum) 0,
-                                                                          itupdesc->attrs[i]->atttypid);
+                                                                          (Datum) 0);
        }
 
        return skey;
@@ -161,105 +160,104 @@ _bt_formitem(IndexTuple itup)
 }
 
 /*----------
- *     _bt_orderkeys() -- Put keys in a sensible order for conjunctive quals.
+ *     _bt_preprocess_keys() -- Preprocess scan keys
  *
- * After this routine runs, the scan keys are ordered by index attribute
- * (all quals for attr 1, then all for attr 2, etc) and within each attr
- * the keys are ordered by constraint type: ">", ">=", "=", "<=", "<".
- * Furthermore, redundant keys are eliminated: we keep only the tightest
- * >/>= bound and the tightest </<= bound, and if there's an = key then
- * that's the only one returned.  (So, we return either a single = key,
- * or one or two boundary-condition keys for each attr.)
+ * The caller-supplied keys (in scan->keyData[]) are copied to
+ * so->keyData[] with possible transformation.  scan->numberOfKeys is
+ * the number of input keys, so->numberOfKeys gets the number of output
+ * keys (possibly less, never greater).
  *
- * As a byproduct of this work, we can detect contradictory quals such
- * as "x = 1 AND x > 2".  If we see that, we return so->quals_ok = FALSE,
- * indicating the scan need not be run at all since no tuples can match.
+ * The primary purpose of this routine is to discover how many scan keys
+ * must be satisfied to continue the scan.  It also attempts to eliminate
+ * redundant keys and detect contradictory keys.  At present, redundant and
+ * contradictory keys can only be detected for same-data-type comparisons,
+ * but that's the usual case so it seems worth doing.
+ *
+ * The output keys must be sorted by index attribute.  Presently we expect
+ * (but verify) that the input keys are already so sorted --- this is done
+ * by group_clauses_by_indexkey() in indxpath.c.  Some reordering of the keys
+ * within each attribute may be done as a byproduct of the processing here,
+ * but no other code depends on that.
  *
- * Another byproduct is to determine how many quals must be satisfied to
+ * Aside from preparing so->keyData[], this routine sets
+ * so->numberOfRequiredKeys to the number of quals that must be satisfied to
  * continue the scan.  _bt_checkkeys uses this.  For example, if the quals
  * are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple
  * (1,2,7), but we must continue the scan in case there are tuples (1,3,z).
  * But once we reach tuples like (1,4,z) we can stop scanning because no
  * later tuples could match.  This is reflected by setting
- * so->numberOfRequiredKeys to the number of leading keys that must be
- * matched to continue the scan.  numberOfRequiredKeys is equal to the
- * number of leading "=" keys plus the key(s) for the first non "="
- * attribute, which can be seen to be correct by considering the above
- * example.
+ * so->numberOfRequiredKeys to 2, the number of leading keys that must be
+ * matched to continue the scan.  In general, numberOfRequiredKeys is equal
+ * to the number of keys for leading attributes with "=" keys, plus the
+ * key(s) for the first non "=" attribute, which can be seen to be correct
+ * by considering the above example.
+ *
+ * If possible, redundant keys are eliminated: we keep only the tightest
+ * >/>= bound and the tightest </<= bound, and if there's an = key then
+ * that's the only one returned.  (So, we return either a single = key,
+ * or one or two boundary-condition keys for each attr.)  However, we can
+ * only detect redundant keys when the right-hand datatypes are all equal
+ * to the index datatype, because we do not know suitable operators for
+ * comparing right-hand values of two different datatypes.  (In theory
+ * we could handle comparison of a RHS of the index datatype with a RHS of
+ * another type, but that seems too much pain for too little gain.)  So,
+ * keys whose operator has a nondefault subtype (ie, its RHS is not of the
+ * index datatype) are ignored here, except for noting whether they impose
+ * an "=" condition or not.
+ *
+ * As a byproduct of this work, we can detect contradictory quals such
+ * as "x = 1 AND x > 2".  If we see that, we return so->quals_ok = FALSE,
+ * indicating the scan need not be run at all since no tuples can match.
+ * Again though, only keys with RHS datatype equal to the index datatype
+ * can be checked for contradictions.
  *
  * Furthermore, we detect the case where the index is unique and we have
  * equality quals for all columns.     In this case there can be at most one
  * (visible) matching tuple.  index_getnext uses this to avoid uselessly
  * continuing the scan after finding one match.
- *
- * The initial ordering of the keys is expected to be by attribute already
- * (see group_clauses_by_indexkey() in indxpath.c).  The task here is to
- * standardize the appearance of multiple keys for the same attribute.
  *----------
  */
 void
-_bt_orderkeys(IndexScanDesc scan)
+_bt_preprocess_keys(IndexScanDesc scan)
 {
        Relation        relation = scan->indexRelation;
        BTScanOpaque so = (BTScanOpaque) scan->opaque;
-       ScanKeyData xform[BTMaxStrategyNumber];
-       bool            init[BTMaxStrategyNumber];
-       int                     numberOfKeys = so->numberOfKeys;
-       ScanKey         key;
+       int                     numberOfKeys = scan->numberOfKeys;
+       int                     new_numberOfKeys;
+       ScanKey         inkeys;
+       ScanKey         outkeys;
        ScanKey         cur;
+       ScanKey         xform[BTMaxStrategyNumber];
+       bool            allEqualSoFar;
+       bool            hasOtherTypeEqual;
        Datum           test;
        int                     i,
                                j;
        AttrNumber      attno;
-       int                     new_numberOfKeys;
-       bool            allEqualSoFar;
 
+       /* initialize result variables */
        so->qual_ok = true;
+       so->numberOfKeys = 0;
        so->numberOfRequiredKeys = 0;
        scan->keys_are_unique = false;
 
        if (numberOfKeys < 1)
                return;                                 /* done if qual-less scan */
 
-       key = so->keyData;
-       cur = &key[0];
-       /* check input keys are correctly ordered */
+       inkeys = scan->keyData;
+       outkeys = so->keyData;
+       cur = &inkeys[0];
+       /* we check that input keys are correctly ordered */
        if (cur->sk_attno != 1)
                elog(ERROR, "key(s) for attribute 1 missed");
 
-#if 0
-       /* XXX verify that operator strategy info is correct */
-       /* XXX this is temporary for debugging; it's pretty expensive */
-       /* XXX can't do it during bootstrap, else will recurse infinitely */
-       {
-               extern bool criticalRelcachesBuilt;
-               static bool inRecursion = false;
-
-               if (criticalRelcachesBuilt && !inRecursion)
-               {
-                       inRecursion = true;
-                       for (i = 0; i < numberOfKeys; i++)
-                       {
-                               AttrNumber      attno = key[i].sk_attno;
-                               Oid                     opclass;
-                               Oid                     chk_oper;
-
-                               opclass = relation->rd_index->indclass[attno-1];
-                               chk_oper = get_opclass_member(opclass, key[i].sk_strategy);
-                               Assert(key[i].sk_func.fn_oid == get_opcode(chk_oper));
-                       }
-                       inRecursion = false;
-               }
-       }
-#endif
-
        /* We can short-circuit most of the work if there's just one key */
        if (numberOfKeys == 1)
        {
                /*
                 * We don't use indices for 'A is null' and 'A is not null'
                 * currently and 'A < = > <> NULL' will always fail - so qual is
-                * not Ok if comparison value is NULL.          - vadim 03/21/97
+                * not OK if comparison value is NULL.          - vadim 03/21/97
                 */
                if (cur->sk_flags & SK_ISNULL)
                        so->qual_ok = false;
@@ -270,6 +268,8 @@ _bt_orderkeys(IndexScanDesc scan)
                        if (cur->sk_strategy == BTEqualStrategyNumber)
                                scan->keys_are_unique = true;
                }
+               memcpy(outkeys, inkeys, sizeof(ScanKeyData));
+               so->numberOfKeys = 1;
                so->numberOfRequiredKeys = 1;
                return;
        }
@@ -283,12 +283,15 @@ _bt_orderkeys(IndexScanDesc scan)
        /*
         * Initialize for processing of keys for attr 1.
         *
-        * xform[i] holds a copy of the current scan key of strategy type i+1, if
-        * any; init[i] is TRUE if we have found such a key for this attr.
+        * xform[i] points to the currently best scan key of strategy type i+1,
+        * if any is found with a default operator subtype; it is NULL if we
+        * haven't yet found such a key for this attr.  Scan keys of nondefault
+        * subtypes are transferred to the output with no processing except for
+        * noting if they are of "=" type.
         */
        attno = 1;
-       MemSet(xform, 0, sizeof(xform));        /* not really necessary */
-       MemSet(init, 0, sizeof(init));
+       memset(xform, 0, sizeof(xform));
+       hasOtherTypeEqual = false;
 
        /*
         * Loop iterates from 0 to numberOfKeys inclusive; we use the last
@@ -329,80 +332,78 @@ _bt_orderkeys(IndexScanDesc scan)
                         * of key > 2 && key == 1 and so on we have to set qual_ok to
                         * false before discarding the other keys.
                         */
-                       if (init[BTEqualStrategyNumber - 1])
+                       if (xform[BTEqualStrategyNumber - 1])
                        {
-                               ScanKeyData *eq,
-                                                  *chk;
+                               ScanKey         eq = xform[BTEqualStrategyNumber - 1];
 
-                               eq = &xform[BTEqualStrategyNumber - 1];
                                for (j = BTMaxStrategyNumber; --j >= 0;)
                                {
-                                       if (!init[j] ||
-                                               j == (BTEqualStrategyNumber - 1))
+                                       ScanKey         chk = xform[j];
+
+                                       if (!chk || j == (BTEqualStrategyNumber - 1))
                                                continue;
-                                       chk = &xform[j];
                                        test = FunctionCall2(&chk->sk_func,
                                                                                 eq->sk_argument,
                                                                                 chk->sk_argument);
                                        if (!DatumGetBool(test))
+                                       {
                                                so->qual_ok = false;
+                                               break;
+                                       }
                                }
-                               init[BTLessStrategyNumber - 1] = false;
-                               init[BTLessEqualStrategyNumber - 1] = false;
-                               init[BTGreaterEqualStrategyNumber - 1] = false;
-                               init[BTGreaterStrategyNumber - 1] = false;
+                               xform[BTLessStrategyNumber - 1] = NULL;
+                               xform[BTLessEqualStrategyNumber - 1] = NULL;
+                               xform[BTGreaterEqualStrategyNumber - 1] = NULL;
+                               xform[BTGreaterStrategyNumber - 1] = NULL;
                        }
                        else
                        {
                                /*
-                                * No "=" for this key, so we're done with required keys
+                                * If no "=" for this key, we're done with required keys
                                 */
-                               allEqualSoFar = false;
+                               if (! hasOtherTypeEqual)
+                                       allEqualSoFar = false;
                        }
 
                        /* keep only one of <, <= */
-                       if (init[BTLessStrategyNumber - 1]
-                               && init[BTLessEqualStrategyNumber - 1])
+                       if (xform[BTLessStrategyNumber - 1]
+                               && xform[BTLessEqualStrategyNumber - 1])
                        {
-                               ScanKeyData *lt = &xform[BTLessStrategyNumber - 1];
-                               ScanKeyData *le = &xform[BTLessEqualStrategyNumber - 1];
+                               ScanKey lt = xform[BTLessStrategyNumber - 1];
+                               ScanKey le = xform[BTLessEqualStrategyNumber - 1];
 
                                test = FunctionCall2(&le->sk_func,
                                                                         lt->sk_argument,
                                                                         le->sk_argument);
                                if (DatumGetBool(test))
-                                       init[BTLessEqualStrategyNumber - 1] = false;
+                                       xform[BTLessEqualStrategyNumber - 1] = NULL;
                                else
-                                       init[BTLessStrategyNumber - 1] = false;
+                                       xform[BTLessStrategyNumber - 1] = NULL;
                        }
 
                        /* keep only one of >, >= */
-                       if (init[BTGreaterStrategyNumber - 1]
-                               && init[BTGreaterEqualStrategyNumber - 1])
+                       if (xform[BTGreaterStrategyNumber - 1]
+                               && xform[BTGreaterEqualStrategyNumber - 1])
                        {
-                               ScanKeyData *gt = &xform[BTGreaterStrategyNumber - 1];
-                               ScanKeyData *ge = &xform[BTGreaterEqualStrategyNumber - 1];
+                               ScanKey gt = xform[BTGreaterStrategyNumber - 1];
+                               ScanKey ge = xform[BTGreaterEqualStrategyNumber - 1];
 
                                test = FunctionCall2(&ge->sk_func,
                                                                         gt->sk_argument,
                                                                         ge->sk_argument);
                                if (DatumGetBool(test))
-                                       init[BTGreaterEqualStrategyNumber - 1] = false;
+                                       xform[BTGreaterEqualStrategyNumber - 1] = NULL;
                                else
-                                       init[BTGreaterStrategyNumber - 1] = false;
+                                       xform[BTGreaterStrategyNumber - 1] = NULL;
                        }
 
                        /*
-                        * Emit the cleaned-up keys back into the key[] array in the
-                        * correct order.  Note we are overwriting our input here!
-                        * It's OK because (a) xform[] is a physical copy of the keys
-                        * we want, (b) we cannot emit more keys than we input, so we
-                        * won't overwrite as-yet-unprocessed keys.
+                        * Emit the cleaned-up keys into the outkeys[] array.
                         */
                        for (j = BTMaxStrategyNumber; --j >= 0;)
                        {
-                               if (init[j])
-                                       memcpy(&key[new_numberOfKeys++], &xform[j],
+                               if (xform[j])
+                                       memcpy(&outkeys[new_numberOfKeys++], xform[j],
                                                   sizeof(ScanKeyData));
                        }
 
@@ -421,31 +422,43 @@ _bt_orderkeys(IndexScanDesc scan)
 
                        /* Re-initialize for new attno */
                        attno = cur->sk_attno;
-                       MemSet(xform, 0, sizeof(xform));        /* not really necessary */
-                       MemSet(init, 0, sizeof(init));
+                       memset(xform, 0, sizeof(xform));
+                       hasOtherTypeEqual = false;
                }
 
-               /* figure out which strategy this key's operator corresponds to */
+               /* check strategy this key's operator corresponds to */
                j = cur->sk_strategy - 1;
 
+               /* if wrong RHS data type, punt */
+               if (cur->sk_subtype != InvalidOid)
+               {
+                       memcpy(&outkeys[new_numberOfKeys++], cur,
+                                  sizeof(ScanKeyData));
+                       if (j == (BTEqualStrategyNumber - 1))
+                               hasOtherTypeEqual = true;
+                       continue;
+               }
+
                /* have we seen one of these before? */
-               if (init[j])
+               if (xform[j])
                {
-                       /* yup, keep the more restrictive value */
+                       /* yup, keep the more restrictive key */
                        test = FunctionCall2(&cur->sk_func,
                                                                 cur->sk_argument,
-                                                                xform[j].sk_argument);
+                                                                xform[j]->sk_argument);
                        if (DatumGetBool(test))
-                               xform[j].sk_argument = cur->sk_argument;
+                               xform[j] = cur;
                        else if (j == (BTEqualStrategyNumber - 1))
+                       {
+                               /* key == a && key == b, but a != b */
                                so->qual_ok = false;
-                       /* key == a && key == b, but a != b */
+                               return;
+                       }
                }
                else
                {
                        /* nope, so remember this scankey */
-                       memcpy(&xform[j], cur, sizeof(ScanKeyData));
-                       init[j] = true;
+                       xform[j] = cur;
                }
        }
 
@@ -465,8 +478,8 @@ _bt_orderkeys(IndexScanDesc scan)
  *
  * If the tuple fails to pass the qual, we also determine whether there's
  * any need to continue the scan beyond this tuple, and set *continuescan
- * accordingly.  See comments for _bt_orderkeys(), above, about how this is
- * done.
+ * accordingly.  See comments for _bt_preprocess_keys(), above, about how
+ * this is done.
  */
 bool
 _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
@@ -474,7 +487,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
 {
        BTScanOpaque so = (BTScanOpaque) scan->opaque;
        int                     keysz = so->numberOfKeys;
-       int                     keysok;
+       int                     ikey;
        TupleDesc       tupdesc;
        ScanKey         key;
 
@@ -484,13 +497,11 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
        if (keysz == 0)
                return true;
 
-       tupdesc = RelationGetDescr(scan->indexRelation);
-       key = so->keyData;
-       keysok = 0;
-
        IncrIndexProcessed();
 
-       while (keysz > 0)
+       tupdesc = RelationGetDescr(scan->indexRelation);
+
+       for (key = so->keyData, ikey = 0; ikey < keysz; key++, ikey++)
        {
                Datum           datum;
                bool            isNull;
@@ -504,7 +515,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
                /* btree doesn't support 'A is null' clauses, yet */
                if (key->sk_flags & SK_ISNULL)
                {
-                       /* we shouldn't get here, really; see _bt_orderkeys() */
+                       /* we shouldn't get here, really; see _bt_preprocess_keys() */
                        *continuescan = false;
                        return false;
                }
@@ -518,7 +529,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
                         * one of the "must match" subset.      On a backward scan,
                         * however, we should keep going.
                         */
-                       if (keysok < so->numberOfRequiredKeys &&
+                       if (ikey < so->numberOfRequiredKeys &&
                                ScanDirectionIsForward(dir))
                                *continuescan = false;
 
@@ -534,16 +545,50 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
                {
                        /*
                         * Tuple fails this qual.  If it's a required qual, then we
-                        * can conclude no further tuples will pass, either.
+                        * may be able to conclude no further tuples will pass, either.
+                        * We have to look at the scan direction and the qual type.
+                        *
+                        * Note: the only case in which we would keep going after failing
+                        * a required qual is if there are partially-redundant quals that
+                        * _bt_preprocess_keys() was unable to eliminate.  For example,
+                        * given "x > 4 AND x > 10" where both are cross-type comparisons
+                        * and so not removable, we might start the scan at the x = 4
+                        * boundary point.  The "x > 10" condition will fail until we
+                        * pass x = 10, but we must not stop the scan on its account.
+                        *
+                        * Note: because we stop the scan as soon as any required equality
+                        * qual fails, it is critical that equality quals be used for the
+                        * initial positioning in _bt_first() when they are available.
+                        * See comments in _bt_first().
+                        */
+                       if (ikey < so->numberOfRequiredKeys)
+                       {
+                               switch (key->sk_strategy)
+                               {
+                                       case BTLessStrategyNumber:
+                                       case BTLessEqualStrategyNumber:
+                                               if (ScanDirectionIsForward(dir))
+                                                       *continuescan = false;
+                                               break;
+                                       case BTEqualStrategyNumber:
+                                               *continuescan = false;
+                                               break;
+                                       case BTGreaterEqualStrategyNumber:
+                                       case BTGreaterStrategyNumber:
+                                               if (ScanDirectionIsBackward(dir))
+                                                       *continuescan = false;
+                                               break;
+                                       default:
+                                               elog(ERROR, "unrecognized StrategyNumber: %d",
+                                                        key->sk_strategy);
+                               }
+                       }
+
+                       /*
+                        * In any case, this indextuple doesn't match the qual.
                         */
-                       if (keysok < so->numberOfRequiredKeys)
-                               *continuescan = false;
                        return false;
                }
-
-               keysok++;
-               key++;
-               keysz--;
        }
 
        /* If we get here, the tuple passes all quals. */
index 790f6bc7b69b8c4bc09ede30771b70154db3b81a..985993fb687a32c0021d2b7c02369b874ef6a3be 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.37 2003/08/04 02:39:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.38 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -82,20 +82,6 @@ rt_box_size(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
-/*
- *     rt_bigbox_size() -- Compute a size for big boxes.
- *
- *             In an earlier release of the system, this routine did something
- *             different from rt_box_size.  We now use floats, rather than ints,
- *             as the return type for the size routine, so we no longer need to
- *             have a special return type for big boxes.
- */
-Datum
-rt_bigbox_size(PG_FUNCTION_ARGS)
-{
-       return rt_box_size(fcinfo);
-}
-
 Datum
 rt_poly_union(PG_FUNCTION_ARGS)
 {
index 263fff4bf26c30ab899b861c6400bce0535e79e4..5026bd78a70c02ba4de51cf22485a59ba886d66e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.48 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.49 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -123,15 +123,17 @@ rtrescan(PG_FUNCTION_ARGS)
 
                        opclass = s->indexRelation->rd_index->indclass[attno-1];
                        int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy);
-                       int_oper = get_opclass_member(opclass, int_strategy);
+                       int_oper = get_opclass_member(opclass,
+                                                                                 s->keyData[i].sk_subtype,
+                                                                                 int_strategy);
                        int_proc = get_opcode(int_oper);
                        ScanKeyEntryInitialize(&(p->s_internalKey[i]),
                                                                   s->keyData[i].sk_flags,
                                                                   attno,
                                                                   int_strategy,
+                                                                  s->keyData[i].sk_subtype,
                                                                   int_proc,
-                                                                  s->keyData[i].sk_argument,
-                                                                  s->keyData[i].sk_argtype);
+                                                                  s->keyData[i].sk_argument);
                }
        }
 
index a1b697bee8544f1ead267fc02e3d6f417e8ad47e..7534750c99eb2051b4c3c83d8eb798bb15529ca4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.92 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.93 2003/11/12 21:15:48 tgl Exp $
  *
  * NOTES
  *       See acl.h.
@@ -366,10 +366,10 @@ ExecuteGrantStmt_Database(GrantStmt *stmt)
                char            replaces[Natts_pg_database];
 
                relation = heap_openr(DatabaseRelationName, RowExclusiveLock);
-               ScanKeyEntryInitialize(&entry[0], 0,
-                                                          Anum_pg_database_datname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          CStringGetDatum(dbname), NAMEOID);
+               ScanKeyInit(&entry[0],
+                                       Anum_pg_database_datname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       CStringGetDatum(dbname));
                scan = heap_beginscan(relation, SnapshotNow, 1, entry);
                tuple = heap_getnext(scan, ForwardScanDirection);
                if (!HeapTupleIsValid(tuple))
@@ -1131,10 +1131,10 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode)
         * There's no syscache for pg_database, so must look the hard way
         */
        pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(db_oid), OIDOID);
+       ScanKeyInit(&entry[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(db_oid));
        scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
        tuple = heap_getnext(scan, ForwardScanDirection);
        if (!HeapTupleIsValid(tuple))
@@ -1531,10 +1531,10 @@ pg_database_ownercheck(Oid db_oid, AclId userid)
 
        /* There's no syscache for pg_database, so must look the hard way */
        pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(db_oid), OIDOID);
+       ScanKeyInit(&entry[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(db_oid));
        scan = heap_beginscan(pg_database, SnapshotNow, 1, entry);
 
        dbtuple = heap_getnext(scan, ForwardScanDirection);
index b0e17652c749db4f76b1c8586009abf3372ec697..d64f027ef64a21a14440221d8353ebbeb431d28a 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.32 2003/11/09 21:30:35 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.33 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,6 @@
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_trigger.h"
-#include "catalog/pg_type.h"
 #include "commands/comment.h"
 #include "commands/defrem.h"
 #include "commands/proclang.h"
@@ -283,20 +282,20 @@ findAutoDeletableObjects(const ObjectAddress *object,
         * When dropping a whole object (subId = 0), find pg_depend records for
         * its sub-objects too.
         */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_depend_refclassid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->classId), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_depend_refobjid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->objectId), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_depend_refclassid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
+       ScanKeyInit(&key[1],
+                               Anum_pg_depend_refobjid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
        if (object->objectSubId != 0)
        {
-               ScanKeyEntryInitialize(&key[2], 0,
-                                                          Anum_pg_depend_refobjsubid,
-                                                          BTEqualStrategyNumber, F_INT4EQ,
-                                                          Int32GetDatum(object->objectSubId), INT4OID);
+               ScanKeyInit(&key[2],
+                                       Anum_pg_depend_refobjsubid,
+                                       BTEqualStrategyNumber, F_INT4EQ,
+                                       Int32GetDatum(object->objectSubId));
                nkeys = 3;
        }
        else
@@ -418,20 +417,20 @@ recursiveDeletion(const ObjectAddress *object,
         * When dropping a whole object (subId = 0), remove all pg_depend records
         * for its sub-objects too.
         */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_depend_classid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->classId), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_depend_objid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->objectId), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_depend_classid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
+       ScanKeyInit(&key[1],
+                               Anum_pg_depend_objid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
        if (object->objectSubId != 0)
        {
-               ScanKeyEntryInitialize(&key[2], 0,
-                                                          Anum_pg_depend_objsubid,
-                                                          BTEqualStrategyNumber, F_INT4EQ,
-                                                          Int32GetDatum(object->objectSubId), INT4OID);
+               ScanKeyInit(&key[2],
+                                       Anum_pg_depend_objsubid,
+                                       BTEqualStrategyNumber, F_INT4EQ,
+                                       Int32GetDatum(object->objectSubId));
                nkeys = 3;
        }
        else
@@ -651,20 +650,20 @@ deleteDependentObjects(const ObjectAddress *object,
        HeapTuple       tup;
        ObjectAddress otherObject;
 
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_depend_refclassid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->classId), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_depend_refobjid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->objectId), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_depend_refclassid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
+       ScanKeyInit(&key[1],
+                               Anum_pg_depend_refobjid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
        if (object->objectSubId != 0)
        {
-               ScanKeyEntryInitialize(&key[2], 0,
-                                                          Anum_pg_depend_refobjsubid,
-                                                          BTEqualStrategyNumber, F_INT4EQ,
-                                                          Int32GetDatum(object->objectSubId), INT4OID);
+               ScanKeyInit(&key[2],
+                                       Anum_pg_depend_refobjsubid,
+                                       BTEqualStrategyNumber, F_INT4EQ,
+                                       Int32GetDatum(object->objectSubId));
                nkeys = 3;
        }
        else
@@ -1473,11 +1472,10 @@ getObjectDescription(const ObjectAddress *object)
 
                                castDesc = heap_openr(CastRelationName, AccessShareLock);
 
-                               ScanKeyEntryInitialize(&skey[0], 0,
-                                                                          ObjectIdAttributeNumber,
-                                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                                          ObjectIdGetDatum(object->objectId),
-                                                                          OIDOID);
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
 
                                rcscan = systable_beginscan(castDesc, CastOidIndex, true,
                                                                                        SnapshotNow, 1, skey);
@@ -1509,11 +1507,10 @@ getObjectDescription(const ObjectAddress *object)
 
                                conDesc = heap_openr(ConstraintRelationName, AccessShareLock);
 
-                               ScanKeyEntryInitialize(&skey[0], 0,
-                                                                          ObjectIdAttributeNumber,
-                                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                                          ObjectIdGetDatum(object->objectId),
-                                                                          OIDOID);
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
 
                                rcscan = systable_beginscan(conDesc, ConstraintOidIndex, true,
                                                                                        SnapshotNow, 1, skey);
@@ -1570,11 +1567,10 @@ getObjectDescription(const ObjectAddress *object)
 
                                attrdefDesc = heap_openr(AttrDefaultRelationName, AccessShareLock);
 
-                               ScanKeyEntryInitialize(&skey[0], 0,
-                                                                          ObjectIdAttributeNumber,
-                                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                                          ObjectIdGetDatum(object->objectId),
-                                                                          OIDOID);
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
 
                                adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndex,
                                                                                        true, SnapshotNow, 1, skey);
@@ -1672,11 +1668,10 @@ getObjectDescription(const ObjectAddress *object)
 
                                ruleDesc = heap_openr(RewriteRelationName, AccessShareLock);
 
-                               ScanKeyEntryInitialize(&skey[0], 0,
-                                                                          ObjectIdAttributeNumber,
-                                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                                          ObjectIdGetDatum(object->objectId),
-                                                                          OIDOID);
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
 
                                rcscan = systable_beginscan(ruleDesc, RewriteOidIndex, true,
                                                                                        SnapshotNow, 1, skey);
@@ -1708,11 +1703,10 @@ getObjectDescription(const ObjectAddress *object)
 
                                trigDesc = heap_openr(TriggerRelationName, AccessShareLock);
 
-                               ScanKeyEntryInitialize(&skey[0], 0,
-                                                                          ObjectIdAttributeNumber,
-                                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                                          ObjectIdGetDatum(object->objectId),
-                                                                          OIDOID);
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
 
                                tgscan = systable_beginscan(trigDesc, TriggerOidIndex, true,
                                                                                        SnapshotNow, 1, skey);
index 75445334ec7d4254eb30fecede5992c3177b24d2..a0962f487dd0521741c772f0318b95cd3d5da6e0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.254 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.255 2003/11/12 21:15:48 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -853,11 +853,10 @@ RelationRemoveInheritance(Relation relation)
 
        catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
 
-       ScanKeyEntryInitialize(&key, 0,
-                                                  Anum_pg_inherits_inhrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&key,
+                               Anum_pg_inherits_inhrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndex, true,
                                                          SnapshotNow, 1, &key);
@@ -920,10 +919,10 @@ DeleteAttributeTuples(Oid relid)
        attrel = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        /* Use the index to scan only attributes of the target relation */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_attribute_attrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_attribute_attrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
 
        scan = systable_beginscan(attrel, AttributeRelidNumIndex, true,
                                                          SnapshotNow, 1, key);
@@ -1035,14 +1034,14 @@ RemoveAttrDefault(Oid relid, AttrNumber attnum,
 
        attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
 
-       ScanKeyEntryInitialize(&scankeys[0], 0,
-                                                  Anum_pg_attrdef_adrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
-       ScanKeyEntryInitialize(&scankeys[1], 0,
-                                                  Anum_pg_attrdef_adnum,
-                                                  BTEqualStrategyNumber, F_INT2EQ,
-                                                  Int16GetDatum(attnum), INT2OID);
+       ScanKeyInit(&scankeys[0],
+                               Anum_pg_attrdef_adrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
+       ScanKeyInit(&scankeys[1],
+                               Anum_pg_attrdef_adnum,
+                               BTEqualStrategyNumber, F_INT2EQ,
+                               Int16GetDatum(attnum));
 
        scan = systable_beginscan(attrdef_rel, AttrDefaultIndex, true,
                                                          SnapshotNow, 2, scankeys);
@@ -1092,10 +1091,10 @@ RemoveAttrDefaultById(Oid attrdefId)
        attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
 
        /* Find the pg_attrdef tuple */
-       ScanKeyEntryInitialize(&scankeys[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(attrdefId), OIDOID);
+       ScanKeyInit(&scankeys[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(attrdefId));
 
        scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndex, true,
                                                          SnapshotNow, 1, scankeys);
@@ -1829,10 +1828,10 @@ RemoveRelConstraints(Relation rel, const char *constrName,
        conrel = heap_openr(ConstraintRelationName, RowExclusiveLock);
 
        /* Use the index to scan only constraints of the target relation */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_constraint_conrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(rel)), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_constraint_conrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(rel)));
 
        conscan = systable_beginscan(conrel, ConstraintRelidIndex, true,
                                                                 SnapshotNow, 1, key);
@@ -1883,19 +1882,19 @@ RemoveStatistics(Relation rel, AttrNumber attnum)
 
        pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
 
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_statistic_starelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(rel)), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_statistic_starelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(rel)));
 
        if (attnum == 0)
                nkeys = 1;
        else
        {
-               ScanKeyEntryInitialize(&key[1], 0,
-                                                          Anum_pg_statistic_staattnum,
-                                                          BTEqualStrategyNumber, F_INT2EQ,
-                                                          Int16GetDatum(attnum), INT2OID);
+               ScanKeyInit(&key[1],
+                                       Anum_pg_statistic_staattnum,
+                                       BTEqualStrategyNumber, F_INT2EQ,
+                                       Int16GetDatum(attnum));
                nkeys = 2;
        }
 
@@ -2050,10 +2049,10 @@ heap_truncate_check_FKs(Relation rel)
         */
        fkeyRel = heap_openr(ConstraintRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&key, 0,
-                                                  Anum_pg_constraint_confrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
+       ScanKeyInit(&key,
+                               Anum_pg_constraint_confrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
 
        fkeyScan = systable_beginscan(fkeyRel, NULL, false,
                                                                  SnapshotNow, 1, &key);
index 67f970c55d78c53c38bf25f8813bf265caac930c..72f76b01b06d2e18e7e81fed3aee12932d3bd716 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.220 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.221 2003/11/12 21:15:48 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -992,10 +992,10 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
        {
                ScanKeyData key[1];
 
-               ScanKeyEntryInitialize(&key[0], 0,
-                                                          ObjectIdAttributeNumber,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(relid), OIDOID);
+               ScanKeyInit(&key[0],
+                                       ObjectIdAttributeNumber,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(relid));
 
                pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
                tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
@@ -1195,10 +1195,10 @@ UpdateStats(Oid relid, double reltuples)
        {
                ScanKeyData key[1];
 
-               ScanKeyEntryInitialize(&key[0], 0,
-                                                          ObjectIdAttributeNumber,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(relid), OIDOID);
+               ScanKeyInit(&key[0],
+                                       ObjectIdAttributeNumber,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(relid));
 
                pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key);
                tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
index 0fa665a568d3422095a09faa6ad98b7e20a5dec0..2cb71f6bfccade2ada0339f3156094984129ac77 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.17 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.18 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -281,15 +281,15 @@ ConstraintNameIsUsed(CONSTRAINTCATEGORY conCat, Oid objId, Oid objNamespace, con
 
        found = false;
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_constraint_conname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  CStringGetDatum(cname), NAMEOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_constraint_conname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               CStringGetDatum(cname));
 
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_constraint_connamespace,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(objNamespace), OIDOID);
+       ScanKeyInit(&skey[1],
+                               Anum_pg_constraint_connamespace,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(objNamespace));
 
        conscan = systable_beginscan(conDesc, ConstraintNameNspIndex, true,
                                                                 SnapshotNow, 2, skey);
@@ -355,15 +355,15 @@ GenerateConstraintName(CONSTRAINTCATEGORY conCat, Oid objId, Oid objNamespace, i
                 */
                found = false;
 
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_constraint_conname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          CStringGetDatum(cname), NAMEOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_constraint_conname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       CStringGetDatum(cname));
 
-               ScanKeyEntryInitialize(&skey[1], 0,
-                                                          Anum_pg_constraint_connamespace,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(objNamespace), OIDOID);
+               ScanKeyInit(&skey[1],
+                                       Anum_pg_constraint_connamespace,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(objNamespace));
 
                conscan = systable_beginscan(conDesc, ConstraintNameNspIndex, true,
                                                                         SnapshotNow, 2, skey);
@@ -422,10 +422,10 @@ RemoveConstraintById(Oid conId)
 
        conDesc = heap_openr(ConstraintRelationName, RowExclusiveLock);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(conId), OIDOID);
+       ScanKeyInit(&skey[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(conId));
 
        conscan = systable_beginscan(conDesc, ConstraintOidIndex, true,
                                                                 SnapshotNow, 1, skey);
index 709f50f2a5d01159bc37ca533775a30e8b9d52b5..7f7811c88df7d8b8c37e7a1c2f86dc0831302b26 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.16 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.17 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,6 @@
 #include "catalog/pg_class.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/namespace.h"
-#include "catalog/pg_type.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -177,10 +176,10 @@ RemoveConversionById(Oid conversionOid)
        HeapScanDesc scan;
        ScanKeyData scanKeyData;
 
-       ScanKeyEntryInitialize(&scanKeyData, 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(conversionOid), OIDOID);
+       ScanKeyInit(&scanKeyData,
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(conversionOid));
 
        /* open pg_conversion */
        rel = heap_openr(ConversionRelationName, RowExclusiveLock);
index 21eeb3e6543600abc32867df21a5c5225be65d98..2bdb5b12d8d18e788c74f7d7a56eb0543c7daa38 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.8 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.9 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,6 @@
 #include "catalog/indexing.h"
 #include "catalog/dependency.h"
 #include "catalog/pg_depend.h"
-#include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "utils/fmgroids.h"
 
@@ -139,14 +138,14 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId)
 
        depRel = heap_openr(DependRelationName, RowExclusiveLock);
 
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_depend_classid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(classId), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_depend_objid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(objectId), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_depend_classid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(classId));
+       ScanKeyInit(&key[1],
+                               Anum_pg_depend_objid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(objectId));
 
        scan = systable_beginscan(depRel, DependDependerIndex, true,
                                                          SnapshotNow, 2, key);
@@ -181,15 +180,15 @@ isObjectPinned(const ObjectAddress *object, Relation rel)
        HeapTuple       tup;
        ScanKeyData key[2];
 
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_depend_refclassid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->classId), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_depend_refclassid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
 
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_depend_refobjid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(object->objectId), OIDOID);
+       ScanKeyInit(&key[1],
+                               Anum_pg_depend_refobjid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
 
        scan = systable_beginscan(rel, DependReferenceIndex, true,
                                                          SnapshotNow, 2, key);
index 96f73056cf2ad799302b1e6fb21ee4d582e759fa..022ca67d10e9a6ece6a1904d78502ae414dc690c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.18 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.19 2003/11/12 21:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,6 @@
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_largeobject.h"
-#include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -82,10 +81,10 @@ LargeObjectDrop(Oid loid)
        SysScanDesc sd;
        HeapTuple       tuple;
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_largeobject_loid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(loid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_largeobject_loid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(loid));
 
        pg_largeobject = heap_openr(LargeObjectRelationName, RowExclusiveLock);
 
@@ -120,10 +119,10 @@ LargeObjectExists(Oid loid)
        /*
         * See if we can find any tuples belonging to the specified LO
         */
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_largeobject_loid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(loid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_largeobject_loid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(loid));
 
        pg_largeobject = heap_openr(LargeObjectRelationName, AccessShareLock);
 
index 2cda1f94a97caabb07ba49f02141c3c0c8da5f0e..560a134aa86a556c4741ce737c15d30213fead34 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.103 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.104 2003/11/12 21:15:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,7 +80,6 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_listener.h"
-#include "catalog/pg_type.h"
 #include "commands/async.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
@@ -353,10 +352,10 @@ Async_UnlistenAll(void)
        tdesc = RelationGetDescr(lRel);
 
        /* Find and delete all entries with my listenerPID */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_listener_pid,
-                                                  BTEqualStrategyNumber, F_INT4EQ,
-                                                  Int32GetDatum(MyProcPid), INT4OID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_listener_pid,
+                               BTEqualStrategyNumber, F_INT4EQ,
+                               Int32GetDatum(MyProcPid));
        scan = heap_beginscan(lRel, SnapshotNow, 1, key);
 
        while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
@@ -817,10 +816,10 @@ ProcessIncomingNotify(void)
        tdesc = RelationGetDescr(lRel);
 
        /* Scan only entries with my listenerPID */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_listener_pid,
-                                                  BTEqualStrategyNumber, F_INT4EQ,
-                                                  Int32GetDatum(MyProcPid), INT4OID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_listener_pid,
+                               BTEqualStrategyNumber, F_INT4EQ,
+                               Int32GetDatum(MyProcPid));
        scan = heap_beginscan(lRel, SnapshotNow, 1, key);
 
        /* Prepare data for rewriting 0 into notification field */
index 780a60f7966e548a01360b124e5df01d1a055083..4d5bc491c71dfc4434edda27e9f1b3b86b8e405d 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.117 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.118 2003/11/12 21:15:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,7 +26,6 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
-#include "catalog/pg_type.h"
 #include "commands/cluster.h"
 #include "commands/tablecmds.h"
 #include "miscadmin.h"
@@ -879,10 +878,10 @@ get_tables_to_cluster(MemoryContext cluster_context)
         * when called with one of them as argument.
         */
        indRelation = relation_openr(IndexRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry, 0,
-                                                  Anum_pg_index_indisclustered,
-                                                  BTEqualStrategyNumber, F_BOOLEQ,
-                                                  BoolGetDatum(true), BOOLOID);
+       ScanKeyInit(&entry,
+                               Anum_pg_index_indisclustered,
+                               BTEqualStrategyNumber, F_BOOLEQ,
+                               BoolGetDatum(true));
        scan = heap_beginscan(indRelation, SnapshotNow, 1, &entry);
        while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
        {
index fbce38ca577b04cdc25567127f7b604bb3c71ad4..62765a96e0a2f313f58b56814e9dd7514dc34ee9 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.72 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.73 2003/11/12 21:15:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -156,18 +156,18 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 
        /* Use the index to search for a matching old tuple */
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_description_objoid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(oid), OIDOID);
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_description_classoid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(classoid), OIDOID);
-       ScanKeyEntryInitialize(&skey[2], 0,
-                                                  Anum_pg_description_objsubid,
-                                                  BTEqualStrategyNumber, F_INT4EQ,
-                                                  Int32GetDatum(subid), INT4OID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_description_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(oid));
+       ScanKeyInit(&skey[1],
+                               Anum_pg_description_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(classoid));
+       ScanKeyInit(&skey[2],
+                               Anum_pg_description_objsubid,
+                               BTEqualStrategyNumber, F_INT4EQ,
+                               Int32GetDatum(subid));
 
        description = heap_openr(DescriptionRelationName, RowExclusiveLock);
 
@@ -231,21 +231,21 @@ DeleteComments(Oid oid, Oid classoid, int32 subid)
 
        /* Use the index to search for all matching old tuples */
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_description_objoid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(oid), OIDOID);
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_description_classoid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(classoid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_description_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(oid));
+       ScanKeyInit(&skey[1],
+                               Anum_pg_description_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(classoid));
 
        if (subid != 0)
        {
-               ScanKeyEntryInitialize(&skey[2], 0,
-                                                          Anum_pg_description_objsubid,
-                                                          BTEqualStrategyNumber, F_INT4EQ,
-                                                          Int32GetDatum(subid), INT4OID);
+               ScanKeyInit(&skey[2],
+                                       Anum_pg_description_objsubid,
+                                       BTEqualStrategyNumber, F_INT4EQ,
+                                       Int32GetDatum(subid));
                nkeys = 3;
        }
        else
@@ -538,10 +538,10 @@ CommentRule(List *qualname, char *comment)
                rulename = strVal(lfirst(qualname));
 
                /* Search pg_rewrite for such a rule */
-               ScanKeyEntryInitialize(&scanKeyData, 0,
-                                                          Anum_pg_rewrite_rulename,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          PointerGetDatum(rulename), NAMEOID);
+               ScanKeyInit(&scanKeyData,
+                                       Anum_pg_rewrite_rulename,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       PointerGetDatum(rulename));
 
                RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock);
                scanDesc = heap_beginscan(RewriteRelation, SnapshotNow,
@@ -791,15 +791,14 @@ CommentTrigger(List *qualname, char *comment)
         * because of the unique index.
         */
        pg_trigger = heap_openr(TriggerRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry[0], 0,
-                                                  Anum_pg_trigger_tgrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
-       ScanKeyEntryInitialize(&entry[1], 0,
-                                                  Anum_pg_trigger_tgname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  CStringGetDatum(trigname), NAMEOID);
+       ScanKeyInit(&entry[0],
+                               Anum_pg_trigger_tgrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
+       ScanKeyInit(&entry[1],
+                               Anum_pg_trigger_tgname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               CStringGetDatum(trigname));
        scan = systable_beginscan(pg_trigger, TriggerRelidNameIndex, true,
                                                          SnapshotNow, 2, entry);
        triggertuple = systable_getnext(scan);
@@ -872,11 +871,10 @@ CommentConstraint(List *qualname, char *comment)
         */
        pg_constraint = heap_openr(ConstraintRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_constraint_conrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_constraint_conrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        scan = systable_beginscan(pg_constraint, ConstraintRelidIndex, true,
                                                          SnapshotNow, 1, skey);
index 5ac51bc84d326b24ba885d6b34333d7710842a69..320f1fc0deddf1f54d01980786250bf0ac9f0f9d 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.125 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.126 2003/11/12 21:15:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,6 @@
 #include "catalog/pg_database.h"
 #include "catalog/pg_shadow.h"
 #include "catalog/indexing.h"
-#include "catalog/pg_type.h"
 #include "commands/comment.h"
 #include "commands/dbcommands.h"
 #include "miscadmin.h"
@@ -531,10 +530,10 @@ dropdb(const char *dbname)
        /*
         * Find the database's tuple by OID (should be unique).
         */
-       ScanKeyEntryInitialize(&key, 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(db_id), OIDOID);
+       ScanKeyInit(&key,
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(db_id));
 
        pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndex, true,
                                                                  SnapshotNow, 1, &key);
@@ -616,10 +615,10 @@ RenameDatabase(const char *oldname, const char *newname)
         */
        rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
 
-       ScanKeyEntryInitialize(&key, 0,
-                                                  Anum_pg_database_datname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  NameGetDatum(oldname), NAMEOID);
+       ScanKeyInit(&key,
+                               Anum_pg_database_datname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               NameGetDatum(oldname));
        scan = systable_beginscan(rel, DatabaseNameIndex, true,
                                                          SnapshotNow, 1, &key);
 
@@ -651,10 +650,10 @@ RenameDatabase(const char *oldname, const char *newname)
                                          oldname)));
 
        /* make sure the new name doesn't exist */
-       ScanKeyEntryInitialize(&key2, 0,
-                                                  Anum_pg_database_datname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  NameGetDatum(newname), NAMEOID);
+       ScanKeyInit(&key2,
+                               Anum_pg_database_datname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               NameGetDatum(newname));
        scan2 = systable_beginscan(rel, DatabaseNameIndex, true,
                                                           SnapshotNow, 1, &key2);
        if (HeapTupleIsValid(systable_getnext(scan2)))
@@ -712,10 +711,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
        valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
 
        rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
-       ScanKeyEntryInitialize(&scankey, 0,
-                                                  Anum_pg_database_datname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  NameGetDatum(stmt->dbname), NAMEOID);
+       ScanKeyInit(&scankey,
+                               Anum_pg_database_datname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               NameGetDatum(stmt->dbname));
        scan = systable_beginscan(rel, DatabaseNameIndex, true,
                                                          SnapshotNow, 1, &scankey);
        tuple = systable_getnext(scan);
@@ -795,10 +794,10 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
        /* Caller may wish to grab a better lock on pg_database beforehand... */
        relation = heap_openr(DatabaseRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&scanKey, 0,
-                                                  Anum_pg_database_datname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  NameGetDatum(name), NAMEOID);
+       ScanKeyInit(&scanKey,
+                               Anum_pg_database_datname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               NameGetDatum(name));
 
        scan = systable_beginscan(relation, DatabaseNameIndex, true,
                                                          SnapshotNow, 1, &scanKey);
@@ -1001,10 +1000,10 @@ get_database_oid(const char *dbname)
 
        /* There's no syscache for pg_database, so must look the hard way */
        pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry[0], 0,
-                                                  Anum_pg_database_datname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  CStringGetDatum(dbname), NAMEOID);
+       ScanKeyInit(&entry[0],
+                               Anum_pg_database_datname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               CStringGetDatum(dbname));
        scan = systable_beginscan(pg_database, DatabaseNameIndex, true,
                                                          SnapshotNow, 1, entry);
 
@@ -1041,10 +1040,10 @@ get_database_name(Oid dbid)
 
        /* There's no syscache for pg_database, so must look the hard way */
        pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(dbid), OIDOID);
+       ScanKeyInit(&entry[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(dbid));
        scan = systable_beginscan(pg_database, DatabaseOidIndex, true,
                                                          SnapshotNow, 1, entry);
 
index 9e1e0746f554091101f05789b00b8ea5702af451..7e3c7410a10462aa1841ab0a0d697bddb2dbb6f5 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.39 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.40 2003/11/12 21:15:50 tgl Exp $
  *
  * DESCRIPTION
  *       These routines take the parse tree and pick out the
@@ -1097,10 +1097,10 @@ DropCastById(Oid castOid)
 
        relation = heap_openr(CastRelationName, RowExclusiveLock);
 
-       ScanKeyEntryInitialize(&scankey, 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(castOid), OIDOID);
+       ScanKeyInit(&scankey,
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(castOid));
        scan = systable_beginscan(relation, CastOidIndex, true,
                                                          SnapshotNow, 1, &scankey);
 
index dbbbc376e004280443f338abc8c31b64f66d87fe..2f83e22a276bcb9d0313b86809dc7bac1da22bb9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.114 2003/10/02 06:34:03 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.115 2003/11/12 21:15:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -416,6 +416,9 @@ GetIndexOpClass(List *opclass, Oid attrType,
         * Release 7.2 renames timestamp_ops to timestamptz_ops, so suppress that
         * too for awhile.      I'm starting to think we need a better approach.
         * tgl 2000/10/01
+        *
+        * Release 7.5 removes bigbox_ops (which was dead code for a long while
+        * anyway).  tgl 2003/11/11
         */
        if (length(opclass) == 1)
        {
@@ -425,7 +428,8 @@ GetIndexOpClass(List *opclass, Oid attrType,
                        strcmp(claname, "timespan_ops") == 0 ||
                        strcmp(claname, "datetime_ops") == 0 ||
                        strcmp(claname, "lztext_ops") == 0 ||
-                       strcmp(claname, "timestamp_ops") == 0)
+                       strcmp(claname, "timestamp_ops") == 0 ||
+                       strcmp(claname, "bigbox_ops") == 0)
                        opclass = NIL;
        }
 
index 599d2eb8259d0aa1f77a5e4aa3713d302e2fc551..e251f8577da811c965e2e2aefc1322f54f712006 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.22 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.23 2003/11/12 21:15:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,8 @@
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_opclass.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
 #include "utils/syscache.h"
 
 
-static void storeOperators(Oid opclassoid, int numOperators,
-                          Oid *operators, bool *recheck);
-static void storeProcedures(Oid opclassoid, int numProcs, Oid *procedures);
+/*
+ * We use lists of this struct type to keep track of both operators and
+ * procedures during DefineOpClass.
+ */
+typedef struct
+{
+       Oid                     object;                 /* operator or support proc's OID */
+       int                     number;                 /* strategy or support proc number */
+       Oid                     subtype;                /* subtype */
+       bool            recheck;                /* oper recheck flag (unused for proc) */
+} OpClassMember;
+
+
+static Oid     assignOperSubtype(Oid amoid, Oid typeoid, Oid operOid);
+static Oid     assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid);
+static void addClassMember(List **list, OpClassMember *member, bool isProc);
+static void storeOperators(Oid opclassoid, List *operators);
+static void storeProcedures(Oid opclassoid, List *procedures);
 
 
 /*
@@ -58,10 +75,9 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                opclassoid;             /* oid of opclass we create */
        int                     numOperators,   /* amstrategies value */
                                numProcs;               /* amsupport value */
-       Oid                *operators,          /* oids of operators, by strategy num */
-                          *procedures;         /* oids of support procs */
-       bool       *recheck;            /* do operators need recheck */
-       List       *iteml;
+       List       *operators;          /* OpClassMember list for operators */
+       List       *procedures;         /* OpClassMember list for support procs */
+       List       *l;
        Relation        rel;
        HeapTuple       tup;
        Datum           values[Natts_pg_opclass];
@@ -123,26 +139,21 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                           format_type_be(typeoid));
 #endif
 
+       operators = NIL;
+       procedures = NIL;
+
        /* Storage datatype is optional */
        storageoid = InvalidOid;
 
-       /*
-        * Create work arrays to hold info about operators and procedures. We
-        * do this mainly so that we can detect duplicate strategy numbers and
-        * support-proc numbers.
-        */
-       operators = (Oid *) palloc0(sizeof(Oid) * numOperators);
-       procedures = (Oid *) palloc0(sizeof(Oid) * numProcs);
-       recheck = (bool *) palloc0(sizeof(bool) * numOperators);
-
        /*
         * Scan the "items" list to obtain additional info.
         */
-       foreach(iteml, stmt->items)
+       foreach(l, stmt->items)
        {
-               CreateOpClassItem *item = lfirst(iteml);
+               CreateOpClassItem *item = lfirst(l);
                Oid                     operOid;
                Oid                     funcOid;
+               OpClassMember *member;
                AclResult       aclresult;
 
                Assert(IsA(item, CreateOpClassItem));
@@ -155,11 +166,6 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                                         errmsg("invalid operator number %d,"
                                                                        " must be between 1 and %d",
                                                                        item->number, numOperators)));
-                               if (operators[item->number - 1] != InvalidOid)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                         errmsg("operator number %d appears more than once",
-                                                        item->number)));
                                if (item->args != NIL)
                                {
                                        TypeName   *typeName1 = (TypeName *) lfirst(item->args);
@@ -183,8 +189,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                if (aclresult != ACLCHECK_OK)
                                        aclcheck_error(aclresult, ACL_KIND_PROC,
                                                                   get_func_name(funcOid));
-                               operators[item->number - 1] = operOid;
-                               recheck[item->number - 1] = item->recheck;
+                               /* Save the info */
+                               member = (OpClassMember *) palloc0(sizeof(OpClassMember));
+                               member->object = operOid;
+                               member->number = item->number;
+                               member->subtype = assignOperSubtype(amoid, typeoid, operOid);
+                               member->recheck = item->recheck;
+                               addClassMember(&operators, member, false);
                                break;
                        case OPCLASS_ITEM_FUNCTION:
                                if (item->number <= 0 || item->number > numProcs)
@@ -193,11 +204,6 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                                         errmsg("invalid procedure number %d,"
                                                                        " must be between 1 and %d",
                                                                        item->number, numProcs)));
-                               if (procedures[item->number - 1] != InvalidOid)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                                        errmsg("procedure number %d appears more than once",
-                                                                       item->number)));
                                funcOid = LookupFuncNameTypeNames(item->name, item->args,
                                                                                                  false);
                                /* Caller must have execute permission on functions */
@@ -206,7 +212,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                if (aclresult != ACLCHECK_OK)
                                        aclcheck_error(aclresult, ACL_KIND_PROC,
                                                                   get_func_name(funcOid));
-                               procedures[item->number - 1] = funcOid;
+                               /* Save the info */
+                               member = (OpClassMember *) palloc0(sizeof(OpClassMember));
+                               member->object = funcOid;
+                               member->number = item->number;
+                               member->subtype = assignProcSubtype(amoid, typeoid, funcOid);
+                               addClassMember(&procedures, member, true);
                                break;
                        case OPCLASS_ITEM_STORAGETYPE:
                                if (OidIsValid(storageoid))
@@ -271,10 +282,10 @@ DefineOpClass(CreateOpClassStmt *stmt)
                ScanKeyData skey[1];
                SysScanDesc scan;
 
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_opclass_opcamid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(amoid), OIDOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_opclass_opcamid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(amoid));
 
                scan = systable_beginscan(rel, OpclassAmNameNspIndex, true,
                                                                  SnapshotNow, 1, skey);
@@ -327,8 +338,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
         * Now add tuples to pg_amop and pg_amproc tying in the operators and
         * functions.
         */
-       storeOperators(opclassoid, numOperators, operators, recheck);
-       storeProcedures(opclassoid, numProcs, procedures);
+       storeOperators(opclassoid, operators);
+       storeProcedures(opclassoid, procedures);
 
        /*
         * Create dependencies.  Note: we do not create a dependency link to
@@ -361,22 +372,22 @@ DefineOpClass(CreateOpClassStmt *stmt)
 
        /* dependencies on operators */
        referenced.classId = get_system_catalog_relid(OperatorRelationName);
-       for (i = 0; i < numOperators; i++)
+       foreach(l, operators)
        {
-               if (operators[i] == InvalidOid)
-                       continue;
-               referenced.objectId = operators[i];
+               OpClassMember *op = (OpClassMember *) lfirst(l);
+
+               referenced.objectId = op->object;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
 
        /* dependencies on procedures */
-       for (i = 0; i < numProcs; i++)
+       foreach(l, procedures)
        {
-               if (procedures[i] == InvalidOid)
-                       continue;
+               OpClassMember *proc = (OpClassMember *) lfirst(l);
+
                referenced.classId = RelOid_pg_proc;
-               referenced.objectId = procedures[i];
+               referenced.objectId = proc->object;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
@@ -384,26 +395,159 @@ DefineOpClass(CreateOpClassStmt *stmt)
        heap_close(rel, RowExclusiveLock);
 }
 
+/*
+ * Determine the subtype to assign to an operator, and do any validity
+ * checking we can manage
+ *
+ * Currently this is done using hardwired rules; we don't let the user
+ * specify it directly.
+ */
+static Oid
+assignOperSubtype(Oid amoid, Oid typeoid, Oid operOid)
+{
+       Oid                     subtype;
+       Operator        optup;
+       Form_pg_operator opform;
+
+       /* Subtypes are currently only supported by btree, others use 0 */
+       if (amoid != BTREE_AM_OID)
+               return InvalidOid;
+
+       optup = SearchSysCache(OPEROID,
+                                                  ObjectIdGetDatum(operOid),
+                                                  0, 0, 0);
+       if (optup == NULL)
+               elog(ERROR, "cache lookup failed for operator %u", operOid);
+       opform = (Form_pg_operator) GETSTRUCT(optup);
+       /*
+        * btree operators must be binary ops returning boolean, and the
+        * left-side input type must match the operator class' input type.
+        */
+       if (opform->oprkind != 'b')
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("btree operators must be binary")));
+       if (opform->oprresult != BOOLOID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("btree operators must return boolean")));
+       if (opform->oprleft != typeoid)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("btree operators must have index type as left input")));
+       /*
+        * The subtype is "default" (0) if oprright matches the operator class,
+        * otherwise it is oprright.
+        */
+       if (opform->oprright == typeoid)
+               subtype = InvalidOid;
+       else
+               subtype = opform->oprright;
+       ReleaseSysCache(optup);
+       return subtype;
+}
+
+/*
+ * Determine the subtype to assign to a support procedure, and do any validity
+ * checking we can manage
+ *
+ * Currently this is done using hardwired rules; we don't let the user
+ * specify it directly.
+ */
+static Oid
+assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
+{
+       Oid                     subtype;
+       HeapTuple       proctup;
+       Form_pg_proc procform;
+
+       /* Subtypes are currently only supported by btree, others use 0 */
+       if (amoid != BTREE_AM_OID)
+               return InvalidOid;
+
+       proctup = SearchSysCache(PROCOID,
+                                                        ObjectIdGetDatum(procOid),
+                                                        0, 0, 0);
+       if (proctup == NULL)
+               elog(ERROR, "cache lookup failed for function %u", procOid);
+       procform = (Form_pg_proc) GETSTRUCT(proctup);
+       /*
+        * btree support procs must be 2-arg procs returning int4, and the
+        * first input type must match the operator class' input type.
+        */
+       if (procform->pronargs != 2)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("btree procedures must have two arguments")));
+       if (procform->prorettype != INT4OID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("btree procedures must return integer")));
+       if (procform->proargtypes[0] != typeoid)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("btree procedures must have index type as first input")));
+       /*
+        * The subtype is "default" (0) if second input type matches the operator
+        * class, otherwise it is the second input type.
+        */
+       if (procform->proargtypes[1] == typeoid)
+               subtype = InvalidOid;
+       else
+               subtype = procform->proargtypes[1];
+       ReleaseSysCache(proctup);
+       return subtype;
+}
+
+/*
+ * Add a new class member to the appropriate list, after checking for
+ * duplicated strategy or proc number.
+ */
+static void
+addClassMember(List **list, OpClassMember *member, bool isProc)
+{
+       List       *l;
+
+       foreach(l, *list)
+       {
+               OpClassMember *old = (OpClassMember *) lfirst(l);
+
+               if (old->number == member->number &&
+                       old->subtype == member->subtype)
+               {
+                       if (isProc)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                                errmsg("procedure number %d appears more than once",
+                                                               member->number)));
+                       else
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                                errmsg("operator number %d appears more than once",
+                                                               member->number)));
+               }
+       }
+       *list = lappend(*list, member);
+}
+
 /*
  * Dump the operators to pg_amop
  */
 static void
-storeOperators(Oid opclassoid, int numOperators,
-                          Oid *operators, bool *recheck)
+storeOperators(Oid opclassoid, List *operators)
 {
        Relation        rel;
        Datum           values[Natts_pg_amop];
        char            nulls[Natts_pg_amop];
        HeapTuple       tup;
-       int                     i,
-                               j;
+       List       *l;
+       int                     i;
 
        rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock);
 
-       for (j = 0; j < numOperators; j++)
+       foreach(l, operators)
        {
-               if (operators[j] == InvalidOid)
-                       continue;
+               OpClassMember *op = (OpClassMember *) lfirst(l);
 
                for (i = 0; i < Natts_pg_amop; ++i)
                {
@@ -413,9 +557,10 @@ storeOperators(Oid opclassoid, int numOperators,
 
                i = 0;
                values[i++] = ObjectIdGetDatum(opclassoid);             /* amopclaid */
-               values[i++] = Int16GetDatum(j + 1);             /* amopstrategy */
-               values[i++] = BoolGetDatum(recheck[j]); /* amopreqcheck */
-               values[i++] = ObjectIdGetDatum(operators[j]);   /* amopopr */
+               values[i++] = ObjectIdGetDatum(op->subtype);    /* amopsubtype */
+               values[i++] = Int16GetDatum(op->number);                /* amopstrategy */
+               values[i++] = BoolGetDatum(op->recheck);                /* amopreqcheck */
+               values[i++] = ObjectIdGetDatum(op->object);             /* amopopr */
 
                tup = heap_formtuple(rel->rd_att, values, nulls);
 
@@ -433,21 +578,20 @@ storeOperators(Oid opclassoid, int numOperators,
  * Dump the procedures (support routines) to pg_amproc
  */
 static void
-storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
+storeProcedures(Oid opclassoid, List *procedures)
 {
        Relation        rel;
        Datum           values[Natts_pg_amproc];
        char            nulls[Natts_pg_amproc];
        HeapTuple       tup;
-       int                     i,
-                               j;
+       List       *l;
+       int                     i;
 
        rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock);
 
-       for (j = 0; j < numProcs; j++)
+       foreach(l, procedures)
        {
-               if (procedures[j] == InvalidOid)
-                       continue;
+               OpClassMember *proc = (OpClassMember *) lfirst(l);
 
                for (i = 0; i < Natts_pg_amproc; ++i)
                {
@@ -457,8 +601,9 @@ storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
 
                i = 0;
                values[i++] = ObjectIdGetDatum(opclassoid);             /* amopclaid */
-               values[i++] = Int16GetDatum(j + 1);             /* amprocnum */
-               values[i++] = ObjectIdGetDatum(procedures[j]);  /* amproc */
+               values[i++] = ObjectIdGetDatum(proc->subtype);  /* amprocsubtype */
+               values[i++] = Int16GetDatum(proc->number);              /* amprocnum */
+               values[i++] = ObjectIdGetDatum(proc->object);   /* amproc */
 
                tup = heap_formtuple(rel->rd_att, values, nulls);
 
@@ -590,10 +735,10 @@ RemoveOpClassById(Oid opclassOid)
        /*
         * Remove associated entries in pg_amop.
         */
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_amop_amopclaid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(opclassOid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_amop_amopclaid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(opclassOid));
 
        rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock);
 
@@ -609,10 +754,10 @@ RemoveOpClassById(Oid opclassOid)
        /*
         * Remove associated entries in pg_amproc.
         */
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_amproc_amopclaid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(opclassOid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_amproc_amopclaid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(opclassOid));
 
        rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock);
 
index df441ca476c743aca6ab4b6dea5ede33c485ca1b..feb9720a847765a560ef3796fffafc5fe4b1796b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.92 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.93 2003/11/12 21:15:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1393,20 +1393,20 @@ update_ri_trigger_args(Oid relid,
        tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
        if (fk_scan)
        {
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_trigger_tgconstrrelid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(relid), OIDOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_trigger_tgconstrrelid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(relid));
                trigscan = systable_beginscan(tgrel, TriggerConstrRelidIndex,
                                                                          true, SnapshotNow,
                                                                          1, skey);
        }
        else
        {
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_trigger_tgrelid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(relid), OIDOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_trigger_tgrelid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(relid));
                trigscan = systable_beginscan(tgrel, TriggerRelidNameIndex,
                                                                          true, SnapshotNow,
                                                                          1, skey);
index 80225f8f25f3415951a927d59d86b47dba282172..4788d90e587d27e005277d6a805798ca9628bd4d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.161 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.162 2003/11/12 21:15:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -253,10 +253,10 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
         * relation, so the trigger set won't be changing underneath us.
         */
        tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
-       ScanKeyEntryInitialize(&key, 0,
-                                                  Anum_pg_trigger_tgrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(rel)), OIDOID);
+       ScanKeyInit(&key,
+                               Anum_pg_trigger_tgrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(rel)));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
                                                                SnapshotNow, 1, &key);
        while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
@@ -465,15 +465,15 @@ DropTrigger(Oid relid, const char *trigname, DropBehavior behavior)
         */
        tgrel = heap_openr(TriggerRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_trigger_tgrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_trigger_tgrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
 
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_trigger_tgname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  CStringGetDatum(trigname), NAMEOID);
+       ScanKeyInit(&skey[1],
+                               Anum_pg_trigger_tgname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               CStringGetDatum(trigname));
 
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
                                                                SnapshotNow, 2, skey);
@@ -524,10 +524,10 @@ RemoveTriggerById(Oid trigOid)
        /*
         * Find the trigger to delete.
         */
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(trigOid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(trigOid));
 
        tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
                                                                SnapshotNow, 1, skey);
@@ -641,14 +641,14 @@ renametrig(Oid relid,
        /*
         * First pass -- look for name conflict
         */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_trigger_tgrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_trigger_tgname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  PointerGetDatum(newname), NAMEOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_trigger_tgrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
+       ScanKeyInit(&key[1],
+                               Anum_pg_trigger_tgname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               PointerGetDatum(newname));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
                                                                SnapshotNow, 2, key);
        if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
@@ -661,14 +661,14 @@ renametrig(Oid relid,
        /*
         * Second pass -- look for trigger existing with oldname and update
         */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_trigger_tgrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(relid), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_trigger_tgname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  PointerGetDatum(oldname), NAMEOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_trigger_tgrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(relid));
+       ScanKeyInit(&key[1],
+                               Anum_pg_trigger_tgname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               PointerGetDatum(oldname));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
                                                                SnapshotNow, 2, key);
        if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
@@ -744,11 +744,10 @@ RelationBuildTriggers(Relation relation)
         * emergency-recovery operations (ie, IsIgnoringSystemIndexes). This
         * in turn ensures that triggers will be fired in name order.
         */
-       ScanKeyEntryInitialize(&skey, 0,
-                                                  Anum_pg_trigger_tgrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&skey,
+                               Anum_pg_trigger_tgrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        tgrel = heap_openr(TriggerRelationName, AccessShareLock);
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
@@ -2262,10 +2261,10 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
                        /*
                         * Setup to scan pg_trigger by tgconstrname ...
                         */
-                       ScanKeyEntryInitialize(&skey, 0,
-                                                                  Anum_pg_trigger_tgconstrname,
-                                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                                  PointerGetDatum(cname), NAMEOID);
+                       ScanKeyInit(&skey,
+                                               Anum_pg_trigger_tgconstrname,
+                                               BTEqualStrategyNumber, F_NAMEEQ,
+                                               PointerGetDatum(cname));
 
                        tgscan = systable_beginscan(tgrel, TriggerConstrNameIndex, true,
                                                                                SnapshotNow, 1, &skey);
index 17b4df92179e5c15186dcd8b090f066d82f09c91..896f10470709add84cc60236b559198ade13f0ea 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.49 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.50 2003/11/12 21:15:51 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -1362,10 +1362,10 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha
        conrel = heap_openr(ConstraintRelationName, RowExclusiveLock);
 
        /* Use the index to scan only constraints of the target relation */
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_constraint_contypid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(HeapTupleGetOid(tup)), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_constraint_contypid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(HeapTupleGetOid(tup)));
 
        conscan = systable_beginscan(conrel, ConstraintTypidIndex, true,
                                                                 SnapshotNow, 1, key);
@@ -1615,14 +1615,14 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
         */
        depRel = relation_openr(DependRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_depend_refclassid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelOid_pg_type), OIDOID);
-       ScanKeyEntryInitialize(&key[1], 0,
-                                                  Anum_pg_depend_refobjid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(domainOid), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_depend_refclassid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelOid_pg_type));
+       ScanKeyInit(&key[1],
+                               Anum_pg_depend_refobjid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(domainOid));
 
        depScan = systable_beginscan(depRel, DependReferenceIndex, true,
                                                                 SnapshotNow, 2, key);
@@ -1901,10 +1901,10 @@ GetDomainConstraints(Oid typeOid)
                        notNull = true;
 
                /* Look for CHECK Constraints on this domain */
-               ScanKeyEntryInitialize(&key[0], 0,
-                                                          Anum_pg_constraint_contypid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(typeOid), OIDOID);
+               ScanKeyInit(&key[0],
+                                       Anum_pg_constraint_contypid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(typeOid));
 
                scan = systable_beginscan(conRel, ConstraintTypidIndex, true,
                                                                  SnapshotNow, 1, key);
index 4fad67f43a3f208d5e830959a8f7140ab0f47d1b..869cd84792731c7e906d96601b1b685e2d35e352 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.129 2003/11/09 21:30:36 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.130 2003/11/12 21:15:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1074,10 +1074,10 @@ DropUser(DropUserStmt *stmt)
                pg_rel = heap_openr(DatabaseRelationName, AccessShareLock);
                pg_dsc = RelationGetDescr(pg_rel);
 
-               ScanKeyEntryInitialize(&scankey, 0,
-                                                          Anum_pg_database_datdba,
-                                                          BTEqualStrategyNumber, F_INT4EQ,
-                                                          Int32GetDatum(usesysid), INT4OID);
+               ScanKeyInit(&scankey,
+                                       Anum_pg_database_datdba,
+                                       BTEqualStrategyNumber, F_INT4EQ,
+                                       Int32GetDatum(usesysid));
 
                scan = heap_beginscan(pg_rel, SnapshotNow, 1, &scankey);
 
index a4d6de2282c72b3dc51a87ad438781d54165c00e..c1c5d64ea2fa534ea4ed3f374c5028f482830d63 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.264 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.265 2003/11/12 21:15:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,6 @@
 #include "catalog/namespace.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_index.h"
-#include "catalog/pg_type.h"
 #include "commands/vacuum.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
@@ -400,10 +399,10 @@ getrels(const RangeVar *vacrel, const char *stmttype)
                HeapTuple       tuple;
                ScanKeyData key;
 
-               ScanKeyEntryInitialize(&key, 0,
-                                                          Anum_pg_class_relkind,
-                                                          BTEqualStrategyNumber, F_CHAREQ,
-                                                          CharGetDatum(RELKIND_RELATION), CHAROID);
+               ScanKeyInit(&key,
+                                       Anum_pg_class_relkind,
+                                       BTEqualStrategyNumber, F_CHAREQ,
+                                       CharGetDatum(RELKIND_RELATION));
 
                pgclass = heap_openr(RelationRelationName, AccessShareLock);
 
@@ -583,10 +582,10 @@ vac_update_dbstats(Oid dbid,
        relation = heap_openr(DatabaseRelationName, RowExclusiveLock);
 
        /* Must use a heap scan, since there's no syscache for pg_database */
-       ScanKeyEntryInitialize(&entry[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(dbid), OIDOID);
+       ScanKeyInit(&entry[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(dbid));
 
        scan = heap_beginscan(relation, SnapshotNow, 1, entry);
 
index 54114ad92459f2e5b5187d63ee07f3df1d3fee84..98158a00c9c674c5b7c8915adadd2b50dd696470 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.85 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.86 2003/11/12 21:15:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,6 @@
 #include "miscadmin.h"
 #include "nodes/nodeFuncs.h"
 #include "optimizer/clauses.h"
-#include "parser/parse_expr.h"
 #include "parser/parsetree.h"
 
 
@@ -615,6 +614,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
        IndexScanState *indexstate;
        List       *indxqual;
        List       *indxstrategy;
+       List       *indxsubtype;
        List       *indxid;
        int                     i;
        int                     numIndices;
@@ -711,10 +711,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
         */
        indxqual = node->indxqual;
        indxstrategy = node->indxstrategy;
+       indxsubtype = node->indxsubtype;
        for (i = 0; i < numIndices; i++)
        {
                List       *quals;
                List       *strategies;
+               List       *subtypes;
                int                     n_keys;
                ScanKey         scan_keys;
                ExprState **run_keys;
@@ -724,6 +726,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
                indxqual = lnext(indxqual);
                strategies = lfirst(indxstrategy);
                indxstrategy = lnext(indxstrategy);
+               subtypes = lfirst(indxsubtype);
+               indxsubtype = lnext(indxsubtype);
                n_keys = length(quals);
                scan_keys = (n_keys <= 0) ? (ScanKey) NULL :
                        (ScanKey) palloc(n_keys * sizeof(ScanKeyData));
@@ -742,9 +746,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
                        int                     flags = 0;
                        AttrNumber      varattno;               /* att number used in scan */
                        StrategyNumber strategy;        /* op's strategy number */
+                       Oid                     subtype;                /* op's strategy subtype */
                        RegProcedure opfuncid;          /* operator proc id used in scan */
                        Datum           scanvalue;              /* value used in scan (if const) */
-                       Oid                     rhstype;                /* datatype of comparison value */
 
                        /*
                         * extract clause information from the qualification
@@ -753,6 +757,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
                        quals = lnext(quals);
                        strategy = lfirsti(strategies);
                        strategies = lnext(strategies);
+                       subtype = lfirsto(subtypes);
+                       subtypes = lnext(subtypes);
 
                        if (!IsA(clause, OpExpr))
                                elog(ERROR, "indxqual is not an OpExpr");
@@ -795,8 +801,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
                         */
                        rightop = (Expr *) get_rightop((Expr *) clause);
 
-                       rhstype = exprType((Node *) rightop);
-
                        if (rightop && IsA(rightop, RelabelType))
                                rightop = ((RelabelType *) rightop)->arg;
 
@@ -832,9 +836,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
                                                                   varattno,    /* attribute number to
                                                                                                 * scan */
                                                                   strategy,    /* op's strategy */
+                                                                  subtype,             /* strategy subtype */
                                                                   opfuncid,    /* reg proc to use */
-                                                                  scanvalue,   /* constant */
-                                                                  rhstype);    /* constant's type */
+                                                                  scanvalue);  /* constant */
                }
 
                /*
index c02270fa2e71cd2535cc109d6731901716a53646..6cf8450567aa20e5567e64d996896d4b7502559a 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.266 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.267 2003/11/12 21:15:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -273,6 +273,17 @@ _copyIndexScan(IndexScan *from)
                }
                newnode->indxstrategy = newstrat;
        }
+       /* this can become COPY_NODE_FIELD when OID lists are normal objects: */
+       {
+               List    *newsubtype = NIL;
+               List    *tmp;
+
+               foreach(tmp, from->indxsubtype)
+               {
+                       newsubtype = lappend(newsubtype, listCopy(lfirst(tmp)));
+               }
+               newnode->indxsubtype = newsubtype;
+       }
        COPY_SCALAR_FIELD(indxorderdir);
 
        return newnode;
index b2fa96bd5d26da5674947cd4aeb684f4450b2929..cb875bd6769c446da3ffaebb6cd1360573699d0f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.219 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.220 2003/11/12 21:15:52 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -346,6 +346,16 @@ _outIndexScan(StringInfo str, IndexScan *node)
                        _outIntList(str, lfirst(tmp));
                }
        }
+       /* this can become WRITE_NODE_FIELD when OID lists are normal objects: */
+       {
+               List    *tmp;
+
+               appendStringInfo(str, " :indxsubtype ");
+               foreach(tmp, node->indxsubtype)
+               {
+                       _outOidList(str, lfirst(tmp));
+               }
+       }
        WRITE_ENUM_FIELD(indxorderdir, ScanDirection);
 }
 
index 563bd17f41d2a4ae6784f555d766014df93aac82..9c57f12ca62a654c9b91b0fcf6735dfd91453d08 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.147 2003/08/04 02:40:00 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.148 2003/11/12 21:15:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1072,7 +1072,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
  *
  *      If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you
  *      want to determine whether "ATTR target_op CONST2" must also be true, then
- *      you can use "CONST1 test_op CONST2" as a test.  If this test returns true,
+ *      you can use "CONST2 test_op CONST1" as a test.  If this test returns true,
  *      then the target expression must be true; if the test returns false, then
  *      the target expression may be false.
  *
@@ -1082,11 +1082,11 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
 
 static const StrategyNumber
                        BT_implic_table[BTMaxStrategyNumber][BTMaxStrategyNumber] = {
-       {2, 2, 0, 0, 0},
-       {1, 2, 0, 0, 0},
-       {1, 2, 3, 4, 5},
-       {0, 0, 0, 4, 5},
-       {0, 0, 0, 4, 4}
+       {4, 4, 0, 0, 0},
+       {5, 4, 0, 0, 0},
+       {5, 4, 3, 2, 1},
+       {0, 0, 0, 2, 1},
+       {0, 0, 0, 2, 2}
 };
 
 
@@ -1118,12 +1118,13 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
                           *clause_const;
        Oid                     pred_op,
                                clause_op,
-                               test_op;
-       Oid                     opclass_id = InvalidOid;
+                               test_op = InvalidOid;
+       Oid                     opclass_id;
        bool            found = false;
-       StrategyNumber pred_strategy = 0,
-                               clause_strategy = 0,
+       StrategyNumber pred_strategy,
+                               clause_strategy,
                                test_strategy;
+       Oid                     clause_subtype;
        Expr       *test_expr;
        ExprState  *test_exprstate;
        Datum           test_result;
@@ -1140,7 +1141,9 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
        /*
         * Can't do anything more unless they are both binary opclauses with a
         * Var on the left and a Const on the right.  (XXX someday try to
-        * commute Const/Var cases?)
+        * commute Const/Var cases?)  Note we don't have to think about binary
+        * relabeling of the Const node, since that would have been folded right
+        * into the Const.
         */
        if (!is_opclause(predicate))
                return false;
@@ -1173,14 +1176,20 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
        clause_op = ((OpExpr *) clause)->opno;
 
        /*
-        * 1. Find "btree" strategy numbers for the pred_op and clause_op.
+        * Try to find a btree opclass containing the needed operators.
         *
         * We must find a btree opclass that contains both operators, else the
-        * implication can't be determined.  If there are multiple such
-        * opclasses, assume we can use any one to determine the logical
-        * relationship of the two operators and the correct corresponding
-        * test operator.  This should work for any logically consistent
-        * opclasses.
+        * implication can't be determined.  Also, the pred_op has to be of
+        * default subtype (implying left and right input datatypes are the same);
+        * otherwise it's unsafe to put the pred_const on the left side of the
+        * test.  Also, the opclass must contain a suitable test operator
+        * matching the clause_const's type (which we take to mean that it has
+        * the same subtype as the original clause_operator).
+        *
+        * If there are multiple matching opclasses, assume we can use any one to
+        * determine the logical relationship of the two operators and the correct
+        * corresponding test operator.  This should work for any logically
+        * consistent opclasses.
         */
        catlist = SearchSysCacheList(AMOPOPID, 1,
                                                                 ObjectIdGetDatum(pred_op),
@@ -1192,7 +1201,13 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
                Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple);
                HeapTuple       clause_tuple;
 
-               if (!opclass_is_btree(pred_form->amopclaid))
+               opclass_id = pred_form->amopclaid;
+
+               /* must be btree */
+               if (!opclass_is_btree(opclass_id))
+                       continue;
+               /* predicate operator must be default within this opclass */
+               if (pred_form->amopsubtype != InvalidOid)
                        continue;
 
                /* Get the predicate operator's btree strategy number */
@@ -1200,12 +1215,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
                Assert(pred_strategy >= 1 && pred_strategy <= 5);
 
                /*
-                * Remember which operator class this strategy number came from
-                */
-               opclass_id = pred_form->amopclaid;
-
-               /*
-                * From the same opclass, find a strategy num for the clause_op,
+                * From the same opclass, find a strategy number for the clause_op,
                 * if possible
                 */
                clause_tuple = SearchSysCache(AMOPOPID,
@@ -1216,13 +1226,35 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
                {
                        Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple);
 
-                       /* Get the restriction clause operator's strategy number */
+                       /* Get the restriction clause operator's strategy/subtype */
                        clause_strategy = (StrategyNumber) clause_form->amopstrategy;
                        Assert(clause_strategy >= 1 && clause_strategy <= 5);
+                       clause_subtype = clause_form->amopsubtype;
 
+                       /* done with clause_tuple */
                        ReleaseSysCache(clause_tuple);
-                       found = true;
-                       break;
+
+                       /*
+                        * Look up the "test" strategy number in the implication table
+                        */
+                       test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
+                       if (test_strategy == 0)
+                       {
+                               /* Can't determine implication using this interpretation */
+                               continue;
+                       }
+
+                       /*
+                        * See if opclass has an operator for the test strategy and the
+                        * clause datatype.
+                        */
+                       test_op = get_opclass_member(opclass_id, clause_subtype,
+                                                                                test_strategy);
+                       if (OidIsValid(test_op))
+                       {
+                               found = true;
+                               break;
+                       }
                }
        }
 
@@ -1235,25 +1267,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
        }
 
        /*
-        * 2. Look up the "test" strategy number in the implication table
-        */
-       test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
-       if (test_strategy == 0)
-               return false;                   /* the implication cannot be determined */
-
-       /*
-        * 3. From the same opclass, find the operator for the test strategy
-        */
-       test_op = get_opclass_member(opclass_id, test_strategy);
-       if (!OidIsValid(test_op))
-       {
-               /* This should not fail, else pg_amop entry is missing */
-               elog(ERROR, "missing pg_amop entry for opclass %u strategy %d",
-                        opclass_id, test_strategy);
-       }
-
-       /*
-        * 4. Evaluate the test.  For this we need an EState.
+        * Evaluate the test.  For this we need an EState.
         */
        estate = CreateExecutorState();
 
@@ -1264,8 +1278,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
        test_expr = make_opclause(test_op,
                                                          BOOLOID,
                                                          false,
-                                                         (Expr *) clause_const,
-                                                         (Expr *) pred_const);
+                                                         (Expr *) pred_const,
+                                                         (Expr *) clause_const);
 
        /* Prepare it for execution */
        test_exprstate = ExecPrepareExpr(test_expr, estate);
@@ -1907,7 +1921,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
  * (The latter is not depended on by any part of the planner, so far as I can
  * tell; but some parts of the executor do assume that the indxqual list
  * ultimately delivered to the executor is so ordered. One such place is
- * _bt_orderkeys() in the btree support.  Perhaps that ought to be fixed
+ * _bt_preprocess_keys() in the btree support.  Perhaps that ought to be fixed
  * someday --- tgl 7/00)
  */
 List *
@@ -2103,7 +2117,8 @@ prefix_quals(Node *leftop, Oid opclass,
         */
        if (pstatus == Pattern_Prefix_Exact)
        {
-               oproid = get_opclass_member(opclass, BTEqualStrategyNumber);
+               oproid = get_opclass_member(opclass, InvalidOid,
+                                                                       BTEqualStrategyNumber);
                if (oproid == InvalidOid)
                        elog(ERROR, "no = operator for opclass %u", opclass);
                expr = make_opclause(oproid, BOOLOID, false,
@@ -2117,7 +2132,8 @@ prefix_quals(Node *leftop, Oid opclass,
         *
         * We can always say "x >= prefix".
         */
-       oproid = get_opclass_member(opclass, BTGreaterEqualStrategyNumber);
+       oproid = get_opclass_member(opclass, InvalidOid,
+                                                               BTGreaterEqualStrategyNumber);
        if (oproid == InvalidOid)
                elog(ERROR, "no >= operator for opclass %u", opclass);
        expr = make_opclause(oproid, BOOLOID, false,
@@ -2132,7 +2148,8 @@ prefix_quals(Node *leftop, Oid opclass,
        greaterstr = make_greater_string(prefix_const);
        if (greaterstr)
        {
-               oproid = get_opclass_member(opclass, BTLessStrategyNumber);
+               oproid = get_opclass_member(opclass, InvalidOid,
+                                                                       BTLessStrategyNumber);
                if (oproid == InvalidOid)
                        elog(ERROR, "no < operator for opclass %u", opclass);
                expr = make_opclause(oproid, BOOLOID, false,
@@ -2189,13 +2206,15 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
         */
        if (is_eq)
        {
-               opr1oid = get_opclass_member(opclass, BTGreaterEqualStrategyNumber);
+               opr1oid = get_opclass_member(opclass, InvalidOid,
+                                                                        BTGreaterEqualStrategyNumber);
                if (opr1oid == InvalidOid)
                        elog(ERROR, "no >= operator for opclass %u", opclass);
        }
        else
        {
-               opr1oid = get_opclass_member(opclass, BTGreaterStrategyNumber);
+               opr1oid = get_opclass_member(opclass, InvalidOid,
+                                                                        BTGreaterStrategyNumber);
                if (opr1oid == InvalidOid)
                        elog(ERROR, "no > operator for opclass %u", opclass);
        }
@@ -2210,7 +2229,8 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
 
        /* create clause "key <= network_scan_last( rightop )" */
 
-       opr2oid = get_opclass_member(opclass, BTLessEqualStrategyNumber);
+       opr2oid = get_opclass_member(opclass, InvalidOid,
+                                                                BTLessEqualStrategyNumber);
        if (opr2oid == InvalidOid)
                elog(ERROR, "no <= operator for opclass %u", opclass);
 
index 37478d7de0ae11ca6b59c386d2ccc54143352121..a5efcb339e0a3f06f3efcd09e7b4affb2988a4c8 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.158 2003/11/09 21:30:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.159 2003/11/12 21:15:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,13 +63,15 @@ static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path,
 static void fix_indxqual_references(List *indexquals, IndexPath *index_path,
                                                List **fixed_indexquals,
                                                List **recheck_indexquals,
-                                               List **indxstrategy);
+                                               List **indxstrategy,
+                                               List **indxsubtype);
 static void fix_indxqual_sublist(List *indexqual,
                                         Relids baserelids, int baserelid,
                                         IndexOptInfo *index,
                                         List **fixed_quals,
                                         List **recheck_quals,
-                                        List **strategy);
+                                        List **strategy,
+                                        List **subtype);
 static Node *fix_indxqual_operand(Node *node, int baserelid,
                                         IndexOptInfo *index,
                                         Oid *opclass);
@@ -79,8 +81,8 @@ static void copy_path_costsize(Plan *dest, Path *src);
 static void copy_plan_costsize(Plan *dest, Plan *src);
 static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
-                          List *indxid, List *indxqual,
-                          List *indxqualorig, List *indxstrategy,
+                          List *indxid, List *indxqual, List *indxqualorig,
+                          List *indxstrategy, List *indxsubtype,
                           ScanDirection indexscandir);
 static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
                         List *tideval);
@@ -704,6 +706,7 @@ create_indexscan_plan(Query *root,
        List       *fixed_indxqual;
        List       *recheck_indxqual;
        List       *indxstrategy;
+       List       *indxsubtype;
        FastList        indexids;
        List       *ixinfo;
        IndexScan  *scan_plan;
@@ -771,7 +774,7 @@ create_indexscan_plan(Query *root,
         */
        fix_indxqual_references(indxqual, best_path,
                                                        &fixed_indxqual, &recheck_indxqual,
-                                                       &indxstrategy);
+                                                       &indxstrategy, &indxsubtype);
 
        /*
         * If there were any "lossy" operators, need to add back the
@@ -804,6 +807,7 @@ create_indexscan_plan(Query *root,
                                                           fixed_indxqual,
                                                           indxqual,
                                                           indxstrategy,
+                                                          indxsubtype,
                                                           best_path->indexscandir);
 
        copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
@@ -1151,8 +1155,8 @@ create_hashjoin_plan(Query *root,
  *       must add (the original form of) the indexqual clause to the "qpquals"
  *       of the indexscan node, where the operator will be re-evaluated to
  *       ensure it passes.
- *     * We must construct a list of operator strategy numbers corresponding
- *       to the top-level operators of each index clause.
+ *     * We must construct lists of operator strategy numbers and subtypes for
+ *       the top-level operators of each index clause.
  *
  * Both the input list and the output lists have the form of lists of sublists
  * of qual clauses --- the top-level list has one entry for each indexscan
@@ -1167,11 +1171,12 @@ create_hashjoin_plan(Query *root,
  * need rechecking.
  *
  * indxstrategy receives a list of integer sublists of strategy numbers.
+ * indxsubtype receives a list of OID sublists of strategy subtypes.
  */
 static void
 fix_indxqual_references(List *indexquals, IndexPath *index_path,
                                                List **fixed_indexquals, List **recheck_indexquals,
-                                               List **indxstrategy)
+                                               List **indxstrategy, List **indxsubtype)
 {
        FastList        fixed_quals;
        FastList        recheck_quals;
@@ -1183,6 +1188,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
        FastListInit(&fixed_quals);
        FastListInit(&recheck_quals);
        *indxstrategy = NIL;
+       *indxsubtype = NIL;
        foreach(i, indexquals)
        {
                List       *indexqual = lfirst(i);
@@ -1190,13 +1196,16 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
                List       *fixed_qual;
                List       *recheck_qual;
                List       *strategy;
+               List       *subtype;
 
                fix_indxqual_sublist(indexqual, baserelids, baserelid, index,
-                                                        &fixed_qual, &recheck_qual, &strategy);
+                                                        &fixed_qual, &recheck_qual,
+                                                        &strategy, &subtype);
                FastAppend(&fixed_quals, fixed_qual);
                if (recheck_qual != NIL)
                        FastAppend(&recheck_quals, recheck_qual);
                *indxstrategy = lappend(*indxstrategy, strategy);
+               *indxsubtype = lappend(*indxsubtype, subtype);
 
                ixinfo = lnext(ixinfo);
        }
@@ -1211,12 +1220,15 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
  * For each qual clause, commute if needed to put the indexkey operand on the
  * left, and then fix its varattno.  (We do not need to change the other side
  * of the clause.)     Also change the operator if necessary, check for
- * lossy index behavior, and determine the operator's strategy number.
+ * lossy index behavior, and determine the operator's strategy number and
+ * subtype number.
  *
- * Returns three lists: the list of fixed indexquals, the list (usually
- * empty) of original clauses that must be rechecked as qpquals because
- * the index is lossy for this operator type, and the integer list of
- * strategy numbers.
+ * Returns four lists:
+ *             the list of fixed indexquals
+ *             the list (usually empty) of original clauses that must be rechecked
+ *                     as qpquals because the index is lossy for this operator type
+ *             the integer list of strategy numbers
+ *             the OID list of strategy subtypes
  */
 static void
 fix_indxqual_sublist(List *indexqual,
@@ -1224,7 +1236,8 @@ fix_indxqual_sublist(List *indexqual,
                                         IndexOptInfo *index,
                                         List **fixed_quals,
                                         List **recheck_quals,
-                                        List **strategy)
+                                        List **strategy,
+                                        List **subtype)
 {
        FastList        fixed_qual;
        FastList        recheck_qual;
@@ -1233,6 +1246,7 @@ fix_indxqual_sublist(List *indexqual,
        FastListInit(&fixed_qual);
        FastListInit(&recheck_qual);
        *strategy = NIL;
+       *subtype = NIL;
        foreach(i, indexqual)
        {
                OpExpr     *clause = (OpExpr *) lfirst(i);
@@ -1240,6 +1254,7 @@ fix_indxqual_sublist(List *indexqual,
                Relids          leftvarnos;
                Oid                     opclass;
                int                     stratno;
+               Oid                     stratsubtype;
                bool            recheck;
 
                if (!IsA(clause, OpExpr) ||
@@ -1278,13 +1293,14 @@ fix_indxqual_sublist(List *indexqual,
 
                /*
                 * Look up the operator in the operator class to get its strategy
-                * number and the recheck indicator.  This also double-checks that
+                * numbers and the recheck indicator.  This also double-checks that
                 * we found an operator matching the index.
                 */
                get_op_opclass_properties(newclause->opno, opclass,
-                                                                 &stratno, &recheck);
+                                                                 &stratno, &stratsubtype, &recheck);
 
                *strategy = lappendi(*strategy, stratno);
+               *subtype = lappendo(*subtype, stratsubtype);
 
                /*
                 * If index is lossy for this operator, add (a copy of) original form
@@ -1540,6 +1556,7 @@ make_indexscan(List *qptlist,
                           List *indxqual,
                           List *indxqualorig,
                           List *indxstrategy,
+                          List *indxsubtype,
                           ScanDirection indexscandir)
 {
        IndexScan  *node = makeNode(IndexScan);
@@ -1555,6 +1572,7 @@ make_indexscan(List *qptlist,
        node->indxqual = indxqual;
        node->indxqualorig = indxqualorig;
        node->indxstrategy = indxstrategy;
+       node->indxsubtype = indxsubtype;
        node->indxorderdir = indexscandir;
 
        return node;
index 8e621dd063a7f324544a4a88e657d145d626a64e..8c42b431aa33a00b2994be5c4cadf5c2669cdcc5 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.88 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.89 2003/11/12 21:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,7 +23,6 @@
 #include "catalog/pg_amop.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/pg_index.h"
-#include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
 #include "optimizer/plancat.h"
@@ -329,10 +328,10 @@ find_inheritance_children(Oid inhparent)
        if (!has_subclass(inhparent))
                return NIL;
 
-       ScanKeyEntryInitialize(&key[0], 0,
-                                                  Anum_pg_inherits_inhparent,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(inhparent), OIDOID);
+       ScanKeyInit(&key[0],
+                               Anum_pg_inherits_inhparent,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(inhparent));
        relation = heap_openr(InheritsRelationName, AccessShareLock);
        scan = heap_beginscan(relation, SnapshotNow, 1, key);
        while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
index 95b5dc37cc62afe3b7060875ec700302e5a3ec40..1068f036d1b0b969f3b332fac254a7190aad242e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.162 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.163 2003/11/12 21:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1039,10 +1039,10 @@ find_inheritors(Oid relid, Oid **supervec)
        {
                /* find all types this relid inherits from, and add them to queue */
 
-               ScanKeyEntryInitialize(&skey, 0,
-                                                          Anum_pg_inherits_inhrelid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(relid), OIDOID);
+               ScanKeyInit(&skey,
+                                       Anum_pg_inherits_inhrelid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(relid));
 
                inhscan = heap_beginscan(inhrel, SnapshotNow, 1, &skey);
 
index 53f94137e1643418d95cb504c76353e6a36f0829..0c36b127a1e944c757edb5721b2790d86fc681fa 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.57 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.58 2003/11/12 21:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,6 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_rewrite.h"
-#include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "rewrite/rewriteRemove.h"
 #include "rewrite/rewriteSupport.h"
@@ -105,10 +104,10 @@ RemoveRewriteRuleById(Oid ruleOid)
        /*
         * Find the tuple for the target rule.
         */
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(ruleOid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(ruleOid));
 
        rcscan = systable_beginscan(RewriteRelation, RewriteOidIndex, true,
                                                                SnapshotNow, 1, skey);
index 33e40109d3edf0cd39f3b4cd7b8c02d030ce6094..f777fb33b95a776a957a1d6bc20f95672975e17b 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.99 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.100 2003/11/12 21:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,10 +202,10 @@ inv_getsize(LargeObjectDesc *obj_desc)
 
        Assert(PointerIsValid(obj_desc));
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_largeobject_loid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(obj_desc->id), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_largeobject_loid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(obj_desc->id));
 
        sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
                                                 SnapshotNow, 1, skey);
@@ -306,15 +306,15 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
        if (nbytes <= 0)
                return 0;
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_largeobject_loid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(obj_desc->id), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_largeobject_loid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(obj_desc->id));
 
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_largeobject_pageno,
-                                                  BTGreaterEqualStrategyNumber, F_INT4GE,
-                                                  Int32GetDatum(pageno), INT4OID);
+       ScanKeyInit(&skey[1],
+                               Anum_pg_largeobject_pageno,
+                               BTGreaterEqualStrategyNumber, F_INT4GE,
+                               Int32GetDatum(pageno));
 
        sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
                                                 SnapshotNow, 2, skey);
@@ -413,15 +413,15 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 
        indstate = CatalogOpenIndexes(obj_desc->heap_r);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_largeobject_loid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(obj_desc->id), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_largeobject_loid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(obj_desc->id));
 
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_largeobject_pageno,
-                                                  BTGreaterEqualStrategyNumber, F_INT4GE,
-                                                  Int32GetDatum(pageno), INT4OID);
+       ScanKeyInit(&skey[1],
+                               Anum_pg_largeobject_pageno,
+                               BTGreaterEqualStrategyNumber, F_INT4GE,
+                               Int32GetDatum(pageno));
 
        sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
                                                 SnapshotNow, 2, skey);
index 9f0fa0de32d2e971588841c72935cb8404b66d97..1493a58de742058947aa20f0cfc9471360f83e9d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.94 2003/09/25 06:58:03 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.95 2003/11/12 21:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -839,6 +839,26 @@ btfloat8cmp(PG_FUNCTION_ARGS)
        PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
 }
 
+Datum
+btfloat48cmp(PG_FUNCTION_ARGS)
+{
+       float4          arg1 = PG_GETARG_FLOAT4(0);
+       float8          arg2 = PG_GETARG_FLOAT8(1);
+
+       /* widen float4 to float8 and then compare */
+       PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
+}
+
+Datum
+btfloat84cmp(PG_FUNCTION_ARGS)
+{
+       float8          arg1 = PG_GETARG_FLOAT8(0);
+       float4          arg2 = PG_GETARG_FLOAT4(1);
+
+       /* widen float4 to float8 and then compare */
+       PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
+}
+
 
 /*
  *             ===================
index 211549afeaf633d78c320c2bc5348ebb3f75c09d..ee8a00912a26763aee46c2ca53b86efb782088f4 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.83 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.84 2003/11/12 21:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,10 +92,10 @@ regprocin(PG_FUNCTION_ARGS)
                SysScanDesc sysscan;
                HeapTuple       tuple;
 
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_proc_proname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          CStringGetDatum(pro_name_or_oid), NAMEOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_proc_proname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       CStringGetDatum(pro_name_or_oid));
 
                hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
                sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
@@ -442,10 +442,10 @@ regoperin(PG_FUNCTION_ARGS)
                SysScanDesc sysscan;
                HeapTuple       tuple;
 
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_operator_oprname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          CStringGetDatum(opr_name_or_oid), NAMEOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_operator_oprname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       CStringGetDatum(opr_name_or_oid));
 
                hdesc = heap_openr(OperatorRelationName, AccessShareLock);
                sysscan = systable_beginscan(hdesc, OperatorNameNspIndex, true,
@@ -820,10 +820,10 @@ regclassin(PG_FUNCTION_ARGS)
                SysScanDesc sysscan;
                HeapTuple       tuple;
 
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_class_relname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          CStringGetDatum(class_name_or_oid), NAMEOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_class_relname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       CStringGetDatum(class_name_or_oid));
 
                hdesc = heap_openr(RelationRelationName, AccessShareLock);
                sysscan = systable_beginscan(hdesc, ClassNameNspIndex, true,
@@ -986,10 +986,10 @@ regtypein(PG_FUNCTION_ARGS)
                SysScanDesc sysscan;
                HeapTuple       tuple;
 
-               ScanKeyEntryInitialize(&skey[0], 0,
-                                                          Anum_pg_type_typname,
-                                                          BTEqualStrategyNumber, F_NAMEEQ,
-                                                          CStringGetDatum(typ_name_or_oid), NAMEOID);
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_type_typname,
+                                       BTEqualStrategyNumber, F_NAMEEQ,
+                                       CStringGetDatum(typ_name_or_oid));
 
                hdesc = heap_openr(TypeRelationName, AccessShareLock);
                sysscan = systable_beginscan(hdesc, TypeNameNspIndex, true,
index fe749cc9b12a9950117e4881f56e09d0aa6f332a..70d5626948a2802e21c4b5c9810fc94db46f2507 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.158 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.159 2003/11/12 21:15:55 tgl Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -488,10 +488,10 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
         */
        tgrel = heap_openr(TriggerRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(trigid), OIDOID);
+       ScanKeyInit(&skey[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(trigid));
 
        tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
                                                                SnapshotNow, 1, skey);
@@ -886,10 +886,10 @@ pg_get_constraintdef_worker(Oid constraintId, int prettyFlags)
         */
        conDesc = heap_openr(ConstraintRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  ObjectIdAttributeNumber,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(constraintId), OIDOID);
+       ScanKeyInit(&skey[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(constraintId));
 
        conscan = systable_beginscan(conDesc, ConstraintOidIndex, true,
                                                                 SnapshotNow, 1, skey);
index 978c0201466b60ef6578a21431b9219deb8e6374..3c4b780c56ce35c121a633b3697283212e9e5169 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.147 2003/10/16 21:37:54 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.148 2003/11/12 21:15:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -952,7 +952,8 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
                /*
                 * Pattern specifies an exact match, so pretend operator is '='
                 */
-               Oid                     eqopr = get_opclass_member(opclass, BTEqualStrategyNumber);
+               Oid                     eqopr = get_opclass_member(opclass, InvalidOid,
+                                                                                          BTEqualStrategyNumber);
                List       *eqargs;
 
                if (eqopr == InvalidOid)
@@ -3382,7 +3383,8 @@ prefix_selectivity(Query *root, Var *var, Oid opclass, Const *prefixcon)
        List       *cmpargs;
        Const      *greaterstrcon;
 
-       cmpopr = get_opclass_member(opclass, BTGreaterEqualStrategyNumber);
+       cmpopr = get_opclass_member(opclass, InvalidOid,
+                                                               BTGreaterEqualStrategyNumber);
        if (cmpopr == InvalidOid)
                elog(ERROR, "no >= operator for opclass %u", opclass);
        cmpargs = makeList2(var, prefixcon);
@@ -3403,7 +3405,8 @@ prefix_selectivity(Query *root, Var *var, Oid opclass, Const *prefixcon)
        {
                Selectivity topsel;
 
-               cmpopr = get_opclass_member(opclass, BTLessStrategyNumber);
+               cmpopr = get_opclass_member(opclass, InvalidOid,
+                                                                       BTLessStrategyNumber);
                if (cmpopr == InvalidOid)
                        elog(ERROR, "no < operator for opclass %u", opclass);
                cmpargs = makeList2(var, greaterstrcon);
index 640629c3a04fc17933587809b21261b13b76045e..36125c2374ae0693a7cdec9a9d29abbbdea923ff 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.109 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.110 2003/11/12 21:15:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -967,9 +967,9 @@ CatalogCacheInitializeCache(CatCache *cache)
                /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
                cache->cc_skey[i].sk_attno = cache->cc_key[i];
 
-               /* Fill in sk_strategy and sk_argtype correctly as well */
+               /* Fill in sk_strategy as well --- always standard equality */
                cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber;
-               cache->cc_skey[i].sk_argtype = keytype;
+               cache->cc_skey[i].sk_subtype = InvalidOid;
 
                CACHE4_elog(DEBUG2, "CatalogCacheInit %s %d %p",
                                        cache->cc_relname,
index bed4fcdbce68d250b9b71c95b49bbbc729b9214c..20c10802bc4346dfd99387f1f1ad054e9f690895 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.109 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.110 2003/11/12 21:15:55 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -55,7 +55,7 @@ op_in_opclass(Oid opno, Oid opclass)
 /*
  * get_op_opclass_properties
  *
- *             Get the operator's strategy number and recheck (lossy) flag
+ *             Get the operator's strategy number, subtype, and recheck (lossy) flag
  *             within the specified opclass.
  *
  * Caller should already have verified that opno is a member of opclass,
@@ -63,7 +63,7 @@ op_in_opclass(Oid opno, Oid opclass)
  */
 void
 get_op_opclass_properties(Oid opno, Oid opclass,
-                                                 int *strategy, bool *recheck)
+                                                 int *strategy, Oid *subtype, bool *recheck)
 {
        HeapTuple       tp;
        Form_pg_amop amop_tup;
@@ -77,6 +77,7 @@ get_op_opclass_properties(Oid opno, Oid opclass,
                         opno, opclass);
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
        *strategy = amop_tup->amopstrategy;
+       *subtype = amop_tup->amopsubtype;
        *recheck = amop_tup->amopreqcheck;
        ReleaseSysCache(tp);
 }
@@ -84,12 +85,12 @@ get_op_opclass_properties(Oid opno, Oid opclass,
 /*
  * get_opclass_member
  *             Get the OID of the operator that implements the specified strategy
- *             for the specified opclass.
+ *             with the specified subtype for the specified opclass.
  *
  * Returns InvalidOid if there is no pg_amop entry for the given keys.
  */
 Oid
-get_opclass_member(Oid opclass, int16 strategy)
+get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
 {
        HeapTuple       tp;
        Form_pg_amop amop_tup;
@@ -97,8 +98,9 @@ get_opclass_member(Oid opclass, int16 strategy)
 
        tp = SearchSysCache(AMOPSTRATEGY,
                                                ObjectIdGetDatum(opclass),
+                                               ObjectIdGetDatum(subtype),
                                                Int16GetDatum(strategy),
-                                               0, 0);
+                                               0);
        if (!HeapTupleIsValid(tp))
                return InvalidOid;
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
@@ -149,8 +151,8 @@ get_op_hash_function(Oid opno)
 
        if (OidIsValid(opclass))
        {
-               /* Found a suitable opclass, get its hash support function */
-               return get_opclass_proc(opclass, HASHPROC);
+               /* Found a suitable opclass, get its default hash support function */
+               return get_opclass_proc(opclass, InvalidOid, HASHPROC);
        }
 
        /* Didn't find a match... */
@@ -163,12 +165,12 @@ get_op_hash_function(Oid opno)
 /*
  * get_opclass_proc
  *             Get the OID of the specified support function
- *             for the specified opclass.
+ *             for the specified opclass and subtype.
  *
  * Returns InvalidOid if there is no pg_amproc entry for the given keys.
  */
 Oid
-get_opclass_proc(Oid opclass, int16 procnum)
+get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
 {
        HeapTuple       tp;
        Form_pg_amproc amproc_tup;
@@ -176,8 +178,9 @@ get_opclass_proc(Oid opclass, int16 procnum)
 
        tp = SearchSysCache(AMPROCNUM,
                                                ObjectIdGetDatum(opclass),
+                                               ObjectIdGetDatum(subtype),
                                                Int16GetDatum(procnum),
-                                               0, 0);
+                                               0);
        if (!HeapTupleIsValid(tp))
                return InvalidOid;
        amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
index 88c8cbb1418154691e06adfa4a83c09b0f155a20..ac5e53a91ae5d967f0985bf3c9013835af4c881c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.191 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.192 2003/11/12 21:15:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -262,7 +262,7 @@ do { \
 /*
  * Special cache for opclass-related information
  *
- * Note: only non-cross-type operators and support procs get cached
+ * Note: only default-subtype operators and support procs get cached
  */
 typedef struct opclasscacheent
 {
@@ -336,26 +336,23 @@ ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK)
        switch (buildinfo.infotype)
        {
                case INFO_RELID:
-                       ScanKeyEntryInitialize(&key[0], 0,
-                                                                  ObjectIdAttributeNumber,
-                                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                                  ObjectIdGetDatum(buildinfo.i.info_id),
-                                                                  OIDOID);
+                       ScanKeyInit(&key[0],
+                                               ObjectIdAttributeNumber,
+                                               BTEqualStrategyNumber, F_OIDEQ,
+                                               ObjectIdGetDatum(buildinfo.i.info_id));
                        nkeys = 1;
                        indexRelname = ClassOidIndex;
                        break;
 
                case INFO_RELNAME:
-                       ScanKeyEntryInitialize(&key[0], 0,
-                                                                  Anum_pg_class_relname,
-                                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                                  NameGetDatum(buildinfo.i.info_name),
-                                                                  NAMEOID);
-                       ScanKeyEntryInitialize(&key[1], 0,
-                                                                  Anum_pg_class_relnamespace,
-                                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                                  ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
-                                                                  OIDOID);
+                       ScanKeyInit(&key[0],
+                                               Anum_pg_class_relname,
+                                               BTEqualStrategyNumber, F_NAMEEQ,
+                                               NameGetDatum(buildinfo.i.info_name));
+                       ScanKeyInit(&key[1],
+                                               Anum_pg_class_relnamespace,
+                                               BTEqualStrategyNumber, F_OIDEQ,
+                                               ObjectIdGetDatum(PG_CATALOG_NAMESPACE));
                        nkeys = 2;
                        indexRelname = ClassNameNspIndex;
                        break;
@@ -483,15 +480,14 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
         * (Eliminating system attribute rows at the index level is lots
         * faster than fetching them.)
         */
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_attribute_attrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
-       ScanKeyEntryInitialize(&skey[1], 0,
-                                                  Anum_pg_attribute_attnum,
-                                                  BTGreaterStrategyNumber, F_INT2GT,
-                                                  Int16GetDatum(0), INT2OID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_attribute_attrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
+       ScanKeyInit(&skey[1],
+                               Anum_pg_attribute_attnum,
+                               BTGreaterStrategyNumber, F_INT2GT,
+                               Int16GetDatum(0));
 
        /*
         * Open pg_attribute and begin a scan.  Force heap scan if we haven't
@@ -673,11 +669,10 @@ RelationBuildRuleLock(Relation relation)
        /*
         * form a scan key
         */
-       ScanKeyEntryInitialize(&key, 0,
-                                                  Anum_pg_rewrite_ev_class,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&key,
+                               Anum_pg_rewrite_ev_class,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        /*
         * open pg_rewrite and begin a scan
@@ -1058,7 +1053,7 @@ RelationInitIndexAccessInfo(Relation relation)
 
 /*
  * IndexSupportInitialize
- *             Initializes an index's cached lists of operators and support procs,
+ *             Initializes an index's cached opclass information,
  *             given the index's pg_index tuple.
  *
  * Data is returned into *indexOperator and *indexSupport, which are arrays
@@ -1131,11 +1126,9 @@ LookupOpclassInfo(Oid operatorClassOid,
 {
        OpClassCacheEnt *opcentry;
        bool            found;
-       Relation        pg_amop_desc;
-       Relation        pg_amproc_desc;
-       SysScanDesc pg_amop_scan;
-       SysScanDesc pg_amproc_scan;
-       ScanKeyData key;
+       Relation        rel;
+       SysScanDesc scan;
+       ScanKeyData skey[2];
        HeapTuple       htup;
        bool            indexOK;
 
@@ -1191,7 +1184,7 @@ LookupOpclassInfo(Oid operatorClassOid,
                opcentry->supportProcs = NULL;
 
        /*
-        * To avoid infinite recursion during startup, force a heap scan if
+        * To avoid infinite recursion during startup, force heap scans if
         * we're looking up info for the opclasses used by the indexes we
         * would like to reference here.
         */
@@ -1200,24 +1193,25 @@ LookupOpclassInfo(Oid operatorClassOid,
                 operatorClassOid != INT2_BTREE_OPS_OID);
 
        /*
-        * Scan pg_amop to obtain operators for the opclass
+        * Scan pg_amop to obtain operators for the opclass.  We only fetch
+        * the default ones (those with subtype zero).
         */
        if (numStrats > 0)
        {
-               ScanKeyEntryInitialize(&key, 0,
-                                                          Anum_pg_amop_amopclaid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(operatorClassOid),
-                                                          OIDOID);
-               pg_amop_desc = heap_openr(AccessMethodOperatorRelationName,
-                                                                 AccessShareLock);
-               pg_amop_scan = systable_beginscan(pg_amop_desc,
-                                                                                 AccessMethodStrategyIndex,
-                                                                                 indexOK,
-                                                                                 SnapshotNow,
-                                                                                 1, &key);
-
-               while (HeapTupleIsValid(htup = systable_getnext(pg_amop_scan)))
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_amop_amopclaid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(operatorClassOid));
+               ScanKeyInit(&skey[1],
+                                       Anum_pg_amop_amopsubtype,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(InvalidOid));
+               rel = heap_openr(AccessMethodOperatorRelationName,
+                                                AccessShareLock);
+               scan = systable_beginscan(rel, AccessMethodStrategyIndex, indexOK,
+                                                                 SnapshotNow, 2, skey);
+
+               while (HeapTupleIsValid(htup = systable_getnext(scan)))
                {
                        Form_pg_amop amopform = (Form_pg_amop) GETSTRUCT(htup);
 
@@ -1229,29 +1223,30 @@ LookupOpclassInfo(Oid operatorClassOid,
                                amopform->amopopr;
                }
 
-               systable_endscan(pg_amop_scan);
-               heap_close(pg_amop_desc, AccessShareLock);
+               systable_endscan(scan);
+               heap_close(rel, AccessShareLock);
        }
 
        /*
-        * Scan pg_amproc to obtain support procs for the opclass
+        * Scan pg_amproc to obtain support procs for the opclass.  We only fetch
+        * the default ones (those with subtype zero).
         */
        if (numSupport > 0)
        {
-               ScanKeyEntryInitialize(&key, 0,
-                                                          Anum_pg_amproc_amopclaid,
-                                                          BTEqualStrategyNumber, F_OIDEQ,
-                                                          ObjectIdGetDatum(operatorClassOid),
-                                                          OIDOID);
-               pg_amproc_desc = heap_openr(AccessMethodProcedureRelationName,
-                                                                       AccessShareLock);
-               pg_amproc_scan = systable_beginscan(pg_amproc_desc,
-                                                                                       AccessMethodProcedureIndex,
-                                                                                       indexOK,
-                                                                                       SnapshotNow,
-                                                                                       1, &key);
-
-               while (HeapTupleIsValid(htup = systable_getnext(pg_amproc_scan)))
+               ScanKeyInit(&skey[0],
+                                       Anum_pg_amproc_amopclaid,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(operatorClassOid));
+               ScanKeyInit(&skey[1],
+                                       Anum_pg_amproc_amprocsubtype,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(InvalidOid));
+               rel = heap_openr(AccessMethodProcedureRelationName,
+                                                AccessShareLock);
+               scan = systable_beginscan(rel, AccessMethodProcedureIndex, indexOK,
+                                                                 SnapshotNow, 2, skey);
+
+               while (HeapTupleIsValid(htup = systable_getnext(scan)))
                {
                        Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
 
@@ -1264,8 +1259,8 @@ LookupOpclassInfo(Oid operatorClassOid,
                                amprocform->amproc;
                }
 
-               systable_endscan(pg_amproc_scan);
-               heap_close(pg_amproc_desc, AccessShareLock);
+               systable_endscan(scan);
+               heap_close(rel, AccessShareLock);
        }
 
        opcentry->valid = true;
@@ -2483,16 +2478,14 @@ AttrDefaultFetch(Relation relation)
        int                     found;
        int                     i;
 
-       ScanKeyEntryInitialize(&skey, 0,
-                                                  Anum_pg_attrdef_adrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&skey,
+                               Anum_pg_attrdef_adrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
        adscan = systable_beginscan(adrel, AttrDefaultIndex, true,
-                                                               SnapshotNow,
-                                                               1, &skey);
+                                                               SnapshotNow, 1, &skey);
        found = 0;
 
        while (HeapTupleIsValid(htup = systable_getnext(adscan)))
@@ -2550,11 +2543,10 @@ CheckConstraintFetch(Relation relation)
        bool            isnull;
        int                     found = 0;
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_constraint_conrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_constraint_conrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        conrel = heap_openr(ConstraintRelationName, AccessShareLock);
        conscan = systable_beginscan(conrel, ConstraintRelidIndex, true,
@@ -2642,16 +2634,14 @@ RelationGetIndexList(Relation relation)
        result = NIL;
 
        /* Prepare to scan pg_index for entries having indrelid = this rel. */
-       ScanKeyEntryInitialize(&skey, 0,
-                                                  Anum_pg_index_indrelid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(RelationGetRelid(relation)),
-                                                  OIDOID);
+       ScanKeyInit(&skey,
+                               Anum_pg_index_indrelid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(RelationGetRelid(relation)));
 
        indrel = heap_openr(IndexRelationName, AccessShareLock);
        indscan = systable_beginscan(indrel, IndexIndrelidIndex, true,
-                                                                SnapshotNow,
-                                                                1, &skey);
+                                                                SnapshotNow, 1, &skey);
 
        while (HeapTupleIsValid(htup = systable_getnext(indscan)))
        {
index 9b250eef62ec3c52a0d277a15bbf613b572a017e..eb2f6eb1af7bbd5b3722a3637399a07590c52481 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.91 2003/09/24 18:54:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.92 2003/11/12 21:15:56 tgl Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
@@ -136,21 +136,21 @@ static const struct cachedesc cacheinfo[] = {
        {AccessMethodOperatorRelationName,      /* AMOPSTRATEGY */
                AccessMethodStrategyIndex,
                0,
-               2,
+               3,
                {
                        Anum_pg_amop_amopclaid,
+                       Anum_pg_amop_amopsubtype,
                        Anum_pg_amop_amopstrategy,
-                       0,
                        0
        }},
        {AccessMethodProcedureRelationName, /* AMPROCNUM */
                AccessMethodProcedureIndex,
                0,
-               2,
+               3,
                {
                        Anum_pg_amproc_amopclaid,
+                       Anum_pg_amproc_amprocsubtype,
                        Anum_pg_amproc_amprocnum,
-                       0,
                        0
        }},
        {AttributeRelationName,         /* ATTNAME */
index 9b7620b0f0afc248fbae301771df4bc07d2154f7..12d295c5a593727f09f81ce19d8b7516d030dcfe 100644 (file)
@@ -33,7 +33,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/typcache.c,v 1.2 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/typcache.c,v 1.3 2003/11/12 21:15:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -158,22 +158,26 @@ lookup_type_cache(Oid type_id, int flags)
        {
                if (typentry->btree_opc != InvalidOid)
                        typentry->eq_opr = get_opclass_member(typentry->btree_opc,
+                                                                                                 InvalidOid,
                                                                                                  BTEqualStrategyNumber);
                if (typentry->eq_opr == InvalidOid &&
                        typentry->hash_opc != InvalidOid)
                        typentry->eq_opr = get_opclass_member(typentry->hash_opc,
+                                                                                                 InvalidOid,
                                                                                                  HTEqualStrategyNumber);
        }
        if ((flags & TYPECACHE_LT_OPR) && typentry->lt_opr == InvalidOid)
        {
                if (typentry->btree_opc != InvalidOid)
                        typentry->lt_opr = get_opclass_member(typentry->btree_opc,
+                                                                                                 InvalidOid,
                                                                                                  BTLessStrategyNumber);
        }
        if ((flags & TYPECACHE_GT_OPR) && typentry->gt_opr == InvalidOid)
        {
                if (typentry->btree_opc != InvalidOid)
                        typentry->gt_opr = get_opclass_member(typentry->btree_opc,
+                                                                                                 InvalidOid,
                                                                                                  BTGreaterStrategyNumber);
        }
        if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
@@ -181,6 +185,7 @@ lookup_type_cache(Oid type_id, int flags)
        {
                if (typentry->btree_opc != InvalidOid)
                        typentry->cmp_proc = get_opclass_proc(typentry->btree_opc,
+                                                                                                 InvalidOid,
                                                                                                  BTORDER_PROC);
        }
 
@@ -248,10 +253,10 @@ lookup_default_opclass(Oid type_id, Oid am_id)
         */
        rel = heap_openr(OperatorClassRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&skey[0], 0,
-                                                  Anum_pg_opclass_opcamid,
-                                                  BTEqualStrategyNumber, F_OIDEQ,
-                                                  ObjectIdGetDatum(am_id), OIDOID);
+       ScanKeyInit(&skey[0],
+                               Anum_pg_opclass_opcamid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(am_id));
 
        scan = systable_beginscan(rel, OpclassAmNameNspIndex, true,
                                                          SnapshotNow, 1, skey);
index 21e2efdda75ed8e049c6972d95fce5903ee002c3..54175189df500b270aff37ee4a9744d228f3eb21 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.128 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.129 2003/11/12 21:15:56 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -26,7 +26,6 @@
 #include "catalog/namespace.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_shadow.h"
-#include "catalog/pg_type.h"
 #include "commands/trigger.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
@@ -92,10 +91,10 @@ ReverifyMyDatabase(const char *name)
         */
        pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock);
 
-       ScanKeyEntryInitialize(&key, 0,
-                                                  Anum_pg_database_datname,
-                                                  BTEqualStrategyNumber, F_NAMEEQ,
-                                                  NameGetDatum(name), NAMEOID);
+       ScanKeyInit(&key,
+                               Anum_pg_database_datname,
+                               BTEqualStrategyNumber, F_NAMEEQ,
+                               NameGetDatum(name));
 
        pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
 
index 9b3c0bb4075eb0bd6e7acec6dba2c2d43b5c993c..a6accb5db4d8c3ad0c379b34e20072680a4d9603 100644 (file)
@@ -78,7 +78,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.38 2003/11/09 21:30:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.39 2003/11/12 21:15:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -472,15 +472,14 @@ tuplesort_begin_heap(TupleDesc tupDesc,
                                                   &state->sortFnKinds[i]);
 
                /*
-                * We needn't fill in sk_strategy or sk_argtype since these scankeys
+                * We needn't fill in sk_strategy or sk_subtype since these scankeys
                 * will never be passed to an index.
                 */
-               ScanKeyEntryInitialize(&state->scanKeys[i], 0,
-                                                          attNums[i],
-                                                          InvalidStrategy,
-                                                          sortFunction,
-                                                          (Datum) 0,
-                                                          InvalidOid);
+               ScanKeyInit(&state->scanKeys[i],
+                                       attNums[i],
+                                       InvalidStrategy,
+                                       sortFunction,
+                                       (Datum) 0);
        }
 
        return state;
@@ -1739,6 +1738,10 @@ SelectSortFunction(Oid sortOperator,
 
                if (!opclass_is_btree(aform->amopclaid))
                        continue;
+               /* must be of default subtype, too */
+               if (aform->amopsubtype != InvalidOid)
+                       continue;
+
                if (aform->amopstrategy == BTLessStrategyNumber)
                {
                        opclass = aform->amopclaid;
@@ -1757,8 +1760,8 @@ SelectSortFunction(Oid sortOperator,
 
        if (OidIsValid(opclass))
        {
-               /* Found a suitable opclass, get its comparator support function */
-               *sortFunction = get_opclass_proc(opclass, BTORDER_PROC);
+               /* Found a suitable opclass, get its default comparator function */
+               *sortFunction = get_opclass_proc(opclass, InvalidOid, BTORDER_PROC);
                Assert(RegProcedureIsValid(*sortFunction));
                return;
        }
index 80d412a52e59004c0b7f055ef28d027026cc246f..2d75fa5b23f01d218f20f3d8fb1d36bee3d0eecb 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nbtree.h,v 1.72 2003/11/09 21:30:37 tgl Exp $
+ * $Id: nbtree.h,v 1.73 2003/11/12 21:15:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -341,7 +341,7 @@ typedef struct xl_btree_newpage
 
 /*
  *     Operator strategy numbers for B-tree have been moved to access/skey.h,
- *     because many places need to use them in ScanKeyEntryInitialize() calls.
+ *     because many places need to use them in ScanKeyInit() calls.
  */
 
 /*
@@ -404,12 +404,12 @@ typedef struct BTScanOpaqueData
        Buffer          btso_mrkbuf;
        ItemPointerData curHeapIptr;
        ItemPointerData mrkHeapIptr;
-       /* these fields are set by _bt_orderkeys(), which see for more info: */
+       /* these fields are set by _bt_preprocess_keys(): */
        bool            qual_ok;                /* false if qual can never be satisfied */
-       int                     numberOfKeys;   /* number of scan keys */
+       int                     numberOfKeys;   /* number of preprocessed scan keys */
        int                     numberOfRequiredKeys;   /* number of keys that must be
                                                                                 * matched to continue the scan */
-       ScanKey         keyData;                /* array of scan keys */
+       ScanKey         keyData;                /* array of preprocessed scan keys */
 } BTScanOpaqueData;
 
 typedef BTScanOpaqueData *BTScanOpaque;
@@ -424,7 +424,6 @@ extern Datum btinsert(PG_FUNCTION_ARGS);
 extern Datum btgettuple(PG_FUNCTION_ARGS);
 extern Datum btbeginscan(PG_FUNCTION_ARGS);
 extern Datum btrescan(PG_FUNCTION_ARGS);
-extern void btmovescan(IndexScanDesc scan, Datum v);
 extern Datum btendscan(PG_FUNCTION_ARGS);
 extern Datum btmarkpos(PG_FUNCTION_ARGS);
 extern Datum btrestrpos(PG_FUNCTION_ARGS);
@@ -480,7 +479,7 @@ extern ScanKey _bt_mkscankey(Relation rel, IndexTuple itup);
 extern ScanKey _bt_mkscankey_nodata(Relation rel);
 extern void _bt_freeskey(ScanKey skey);
 extern void _bt_freestack(BTStack stack);
-extern void _bt_orderkeys(IndexScanDesc scan);
+extern void _bt_preprocess_keys(IndexScanDesc scan);
 extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
                          ScanDirection dir, bool *continuescan);
 extern BTItem _bt_formitem(IndexTuple itup);
index b7373dd641064655de278c7b1a43c80c1d0f55e0..5cce3249fb57fa1f5acf8f5e07513a4d2e44766e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: skey.h,v 1.23 2003/11/09 21:30:37 tgl Exp $
+ * $Id: skey.h,v 1.24 2003/11/12 21:15:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,8 @@
 
 /*
  * Strategy numbers identify the semantics that particular operators have
- * with respect to particular operator classes.
+ * with respect to particular operator classes.  In some cases a strategy
+ * subtype (an OID) is used as further information.
  */
 typedef uint16 StrategyNumber;
 
@@ -47,23 +48,23 @@ typedef uint16 StrategyNumber;
  * (The data structure can support unary indexable operators too; in that
  * case sk_argument would go unused.  This is not currently implemented.)
  *
- * For an index scan, sk_strategy must be set correctly for the operator.
- * When using a ScanKey in a heap scan, sk_strategy is not used and may be
- * set to InvalidStrategy.
+ * For an index scan, sk_strategy and sk_subtype must be set correctly for
+ * the operator.  When using a ScanKey in a heap scan, these fields are not
+ * used and may be set to InvalidStrategy/InvalidOid.
  *
  * Note: in some places, ScanKeys are used as a convenient representation
  * for the invocation of an access method support procedure.  In this case
- * sk_strategy is not meaningful, and sk_func may refer to a function that
- * returns something other than boolean.
+ * sk_strategy/sk_subtype are not meaningful, and sk_func may refer to a
+ * function that returns something other than boolean.
  */
 typedef struct ScanKeyData
 {
        int                     sk_flags;               /* flags, see below */
        AttrNumber      sk_attno;               /* table or index column number */
        StrategyNumber sk_strategy;     /* operator strategy number */
+       Oid                     sk_subtype;             /* strategy subtype */
        FmgrInfo        sk_func;                /* lookup info for function to call */
        Datum           sk_argument;    /* data to compare */
-       Oid                     sk_argtype;             /* datatype of sk_argument */
 } ScanKeyData;
 
 typedef ScanKeyData *ScanKey;
@@ -76,19 +77,24 @@ typedef ScanKeyData *ScanKey;
 /*
  * prototypes for functions in access/common/scankey.c
  */
+extern void ScanKeyInit(ScanKey entry,
+                                               AttrNumber attributeNumber,
+                                               StrategyNumber strategy,
+                                               RegProcedure procedure,
+                                               Datum argument);
 extern void ScanKeyEntryInitialize(ScanKey entry,
                                                                   int flags,
                                                                   AttrNumber attributeNumber,
                                                                   StrategyNumber strategy,
+                                                                  Oid subtype,
                                                                   RegProcedure procedure,
-                                                                  Datum argument,
-                                                                  Oid argtype);
+                                                                  Datum argument);
 extern void ScanKeyEntryInitializeWithInfo(ScanKey entry,
                                                                                   int flags,
                                                                                   AttrNumber attributeNumber,
                                                                                   StrategyNumber strategy,
+                                                                                  Oid subtype,
                                                                                   FmgrInfo *finfo,
-                                                                                  Datum argument,
-                                                                                  Oid argtype);
+                                                                                  Datum argument);
 
 #endif   /* SKEY_H */
index 9efcfe447d5bf03ff41e86d9bd5f0060f8b26c5e..8209b34880d9027e40a47fea09cf4ba009de938e 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.210 2003/10/21 16:23:16 tgl Exp $
+ * $Id: catversion.h,v 1.211 2003/11/12 21:15:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200310211
+#define CATALOG_VERSION_NO     200311101
 
 #endif
index 1150f1e47c5a3f1db1172d0ea12e7c6b5db2da14..720c8eec0a9e56aa41589c19c2995ba07f75c084 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.79 2003/08/04 02:40:10 momjian Exp $
+ * $Id: indexing.h,v 1.80 2003/11/12 21:15:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,8 +24,8 @@
  * macros rather than hardwiring the actual index name.
  */
 #define AccessMethodOperatorIndex      "pg_amop_opr_opc_index"
-#define AccessMethodStrategyIndex      "pg_amop_opc_strategy_index"
-#define AccessMethodProcedureIndex     "pg_amproc_opc_procnum_index"
+#define AccessMethodStrategyIndex      "pg_amop_opc_strat_index"
+#define AccessMethodProcedureIndex     "pg_amproc_opc_proc_index"
 #define AggregateFnoidIndex                    "pg_aggregate_fnoid_index"
 #define AmNameIndex                                    "pg_am_name_index"
 #define AmOidIndex                                     "pg_am_oid_index"
@@ -115,9 +115,9 @@ extern void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple);
 DECLARE_UNIQUE_INDEX(pg_aggregate_fnoid_index on pg_aggregate using btree(aggfnoid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_am_name_index on pg_am using btree(amname name_ops));
 DECLARE_UNIQUE_INDEX(pg_am_oid_index on pg_am using btree(oid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_opc_strat_index on pg_amop using btree(amopclaid oid_ops, amopsubtype oid_ops, amopstrategy int2_ops));
 DECLARE_UNIQUE_INDEX(pg_amop_opr_opc_index on pg_amop using btree(amopopr oid_ops, amopclaid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_amop_opc_strategy_index on pg_amop using btree(amopclaid oid_ops, amopstrategy int2_ops));
-DECLARE_UNIQUE_INDEX(pg_amproc_opc_procnum_index on pg_amproc using btree(amopclaid oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_opc_proc_index on pg_amproc using btree(amopclaid oid_ops, amprocsubtype oid_ops, amprocnum int2_ops));
 DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
 DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index on pg_attrdef using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops));
index 7e70d726d14832c1e761039828e4b16256d111ca..746b9bfb6d1d9188e6e490730cb567dba34e045e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: namespace.h,v 1.27 2003/08/04 02:40:10 momjian Exp $
+ * $Id: namespace.h,v 1.28 2003/11/12 21:15:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,9 +42,9 @@ typedef struct _OpclassCandidateList
        char       *opcname_tmp;        /* for internal use of namespace lookup */
        int                     pathpos;                /* for internal use of namespace lookup */
        Oid                     oid;                    /* the opclass's OID */
-       Oid                     opcintype;              /* type of input data for opclass */
+       Oid                     opcintype;              /* type of data indexed by opclass */
        bool            opcdefault;             /* T if opclass is default for opcintype */
-       Oid                     opckeytype;             /* type of index data, or InvalidOid */
+       Oid                     opckeytype;             /* type of data in index, or InvalidOid */
 }      *OpclassCandidateList;
 
 
index bff4b21700341afa95aedeb7b11872a72cc1493a..1bab599fdb42ec44a29f42d51b68428d3a706888 100644 (file)
@@ -6,17 +6,24 @@
  *
  * The amop table identifies the operators associated with each index opclass.
  *
- * Note: the primary key for this table is <amopclaid, amopstrategy>.
+ * The primary key for this table is <amopclaid, amopsubtype, amopstrategy>.
+ * amopsubtype is equal to zero for an opclass's "default" operators
+ * (which normally are those that accept the opclass's opcintype on both
+ * left and right sides).  Some index AMs allow nondefault operators to
+ * exist for a single strategy --- for example, in the btree AM nondefault
+ * operators can have right-hand input data types different from opcintype,
+ * and their amopsubtype is equal to the right-hand input data type.
+ *
  * We also keep a unique index on <amopclaid, amopopr>, so that we can
  * use a syscache to quickly answer questions of the form "is this operator
  * in this opclass?".  This implies that the same operator cannot be listed
- * for multiple strategy numbers of a single opclass.
+ * for multiple subtypes or strategy numbers of a single opclass.
  *
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amop.h,v 1.55 2003/08/17 19:58:06 tgl Exp $
+ * $Id: pg_amop.h,v 1.56 2003/11/12 21:15:57 tgl Exp $
  *
  * NOTES
  *      the genbki.sh script reads this file and generates .bki
@@ -42,6 +49,7 @@
 CATALOG(pg_amop) BKI_WITHOUT_OIDS
 {
        Oid                     amopclaid;              /* the index opclass this entry is for */
+       Oid                     amopsubtype;    /* operator subtype, or zero if default */
        int2            amopstrategy;   /* operator strategy number */
        bool            amopreqcheck;   /* index hit must be rechecked */
        Oid                     amopopr;                /* the operator's pg_operator OID */
@@ -58,11 +66,12 @@ typedef FormData_pg_amop *Form_pg_amop;
  *             compiler constants for pg_amop
  * ----------------
  */
-#define Natts_pg_amop                                  4
+#define Natts_pg_amop                                  5
 #define Anum_pg_amop_amopclaid                 1
-#define Anum_pg_amop_amopstrategy              2
-#define Anum_pg_amop_amopreqcheck              3
-#define Anum_pg_amop_amopopr                   4
+#define Anum_pg_amop_amopsubtype               2
+#define Anum_pg_amop_amopstrategy              3
+#define Anum_pg_amop_amopreqcheck              4
+#define Anum_pg_amop_amopopr                   5
 
 /* ----------------
  *             initial contents of pg_amop
@@ -73,460 +82,495 @@ typedef FormData_pg_amop *Form_pg_amop;
  *     rtree box_ops
  */
 
-DATA(insert (   425 1 f  493 ));
-DATA(insert (   425 2 f  494 ));
-DATA(insert (   425 3 f  500 ));
-DATA(insert (   425 4 f  495 ));
-DATA(insert (   425 5 f  496 ));
-DATA(insert (   425 6 f  499 ));
-DATA(insert (   425 7 f  498 ));
-DATA(insert (   425 8 f  497 ));
-
-/*
- *     rtree bigbox_ops
- */
-
-DATA(insert (   422 1 f  493 ));
-DATA(insert (   422 2 f  494 ));
-DATA(insert (   422 3 f  500 ));
-DATA(insert (   422 4 f  495 ));
-DATA(insert (   422 5 f  496 ));
-DATA(insert (   422 6 f  499 ));
-DATA(insert (   422 7 f  498 ));
-DATA(insert (   422 8 f  497 ));
+DATA(insert (   425    0 1 f  493 ));
+DATA(insert (   425    0 2 f  494 ));
+DATA(insert (   425    0 3 f  500 ));
+DATA(insert (   425    0 4 f  495 ));
+DATA(insert (   425    0 5 f  496 ));
+DATA(insert (   425    0 6 f  499 ));
+DATA(insert (   425    0 7 f  498 ));
+DATA(insert (   425    0 8 f  497 ));
 
 /*
  *     rtree poly_ops (supports polygons)
  */
 
-DATA(insert (  1993 1 f  485 ));
-DATA(insert (  1993 2 f  486 ));
-DATA(insert (  1993 3 f  492 ));
-DATA(insert (  1993 4 f  487 ));
-DATA(insert (  1993 5 f  488 ));
-DATA(insert (  1993 6 f  491 ));
-DATA(insert (  1993 7 f  490 ));
-DATA(insert (  1993 8 f  489 ));
+DATA(insert (  1993    0 1 f  485 ));
+DATA(insert (  1993    0 2 f  486 ));
+DATA(insert (  1993    0 3 f  492 ));
+DATA(insert (  1993    0 4 f  487 ));
+DATA(insert (  1993    0 5 f  488 ));
+DATA(insert (  1993    0 6 f  491 ));
+DATA(insert (  1993    0 7 f  490 ));
+DATA(insert (  1993    0 8 f  489 ));
 
 /*
  *     btree int2_ops
  */
 
-DATA(insert (  1976 1 f   95 ));
-DATA(insert (  1976 2 f  522 ));
-DATA(insert (  1976 3 f   94 ));
-DATA(insert (  1976 4 f  524 ));
-DATA(insert (  1976 5 f  520 ));
+DATA(insert (  1976    0 1 f   95 ));
+DATA(insert (  1976    0 2 f  522 ));
+DATA(insert (  1976    0 3 f   94 ));
+DATA(insert (  1976    0 4 f  524 ));
+DATA(insert (  1976    0 5 f  520 ));
+/* crosstype operators int24 */
+DATA(insert (  1976   23 1 f  534 ));
+DATA(insert (  1976   23 2 f  540 ));
+DATA(insert (  1976   23 3 f  532 ));
+DATA(insert (  1976   23 4 f  542 ));
+DATA(insert (  1976   23 5 f  536 ));
+/* crosstype operators int28 */
+DATA(insert (  1976   20 1 f  1864 ));
+DATA(insert (  1976   20 2 f  1866 ));
+DATA(insert (  1976   20 3 f  1862 ));
+DATA(insert (  1976   20 4 f  1867 ));
+DATA(insert (  1976   20 5 f  1865 ));
 
 /*
  *     btree int4_ops
  */
 
-DATA(insert (  1978 1 f   97 ));
-DATA(insert (  1978 2 f  523 ));
-DATA(insert (  1978 3 f   96 ));
-DATA(insert (  1978 4 f  525 ));
-DATA(insert (  1978 5 f  521 ));
+DATA(insert (  1978    0 1 f   97 ));
+DATA(insert (  1978    0 2 f  523 ));
+DATA(insert (  1978    0 3 f   96 ));
+DATA(insert (  1978    0 4 f  525 ));
+DATA(insert (  1978    0 5 f  521 ));
+/* crosstype operators int42 */
+DATA(insert (  1978   21 1 f  535 ));
+DATA(insert (  1978   21 2 f  541 ));
+DATA(insert (  1978   21 3 f  533 ));
+DATA(insert (  1978   21 4 f  543 ));
+DATA(insert (  1978   21 5 f  537 ));
+/* crosstype operators int48 */
+DATA(insert (  1978   20 1 f   37 ));
+DATA(insert (  1978   20 2 f   80 ));
+DATA(insert (  1978   20 3 f   15 ));
+DATA(insert (  1978   20 4 f   82 ));
+DATA(insert (  1978   20 5 f   76 ));
 
 /*
  *     btree int8_ops
  */
 
-DATA(insert (  1980 1 f  412 ));
-DATA(insert (  1980 2 f  414 ));
-DATA(insert (  1980 3 f  410 ));
-DATA(insert (  1980 4 f  415 ));
-DATA(insert (  1980 5 f  413 ));
+DATA(insert (  1980    0 1 f  412 ));
+DATA(insert (  1980    0 2 f  414 ));
+DATA(insert (  1980    0 3 f  410 ));
+DATA(insert (  1980    0 4 f  415 ));
+DATA(insert (  1980    0 5 f  413 ));
+/* crosstype operators int82 */
+DATA(insert (  1980   21 1 f  1870 ));
+DATA(insert (  1980   21 2 f  1872 ));
+DATA(insert (  1980   21 3 f  1868 ));
+DATA(insert (  1980   21 4 f  1873 ));
+DATA(insert (  1980   21 5 f  1871 ));
+/* crosstype operators int84 */
+DATA(insert (  1980   23 1 f  418 ));
+DATA(insert (  1980   23 2 f  420 ));
+DATA(insert (  1980   23 3 f  416 ));
+DATA(insert (  1980   23 4 f  430 ));
+DATA(insert (  1980   23 5 f  419 ));
 
 /*
  *     btree oid_ops
  */
 
-DATA(insert (  1989 1 f  609 ));
-DATA(insert (  1989 2 f  611 ));
-DATA(insert (  1989 3 f  607 ));
-DATA(insert (  1989 4 f  612 ));
-DATA(insert (  1989 5 f  610 ));
+DATA(insert (  1989    0 1 f  609 ));
+DATA(insert (  1989    0 2 f  611 ));
+DATA(insert (  1989    0 3 f  607 ));
+DATA(insert (  1989    0 4 f  612 ));
+DATA(insert (  1989    0 5 f  610 ));
 
 /*
  *     btree oidvector_ops
  */
 
-DATA(insert (  1991 1 f  645 ));
-DATA(insert (  1991 2 f  647 ));
-DATA(insert (  1991 3 f  649 ));
-DATA(insert (  1991 4 f  648 ));
-DATA(insert (  1991 5 f  646 ));
+DATA(insert (  1991    0 1 f  645 ));
+DATA(insert (  1991    0 2 f  647 ));
+DATA(insert (  1991    0 3 f  649 ));
+DATA(insert (  1991    0 4 f  648 ));
+DATA(insert (  1991    0 5 f  646 ));
 
 /*
  *     btree float4_ops
  */
 
-DATA(insert (  1970 1 f  622 ));
-DATA(insert (  1970 2 f  624 ));
-DATA(insert (  1970 3 f  620 ));
-DATA(insert (  1970 4 f  625 ));
-DATA(insert (  1970 5 f  623 ));
+DATA(insert (  1970    0 1 f  622 ));
+DATA(insert (  1970    0 2 f  624 ));
+DATA(insert (  1970    0 3 f  620 ));
+DATA(insert (  1970    0 4 f  625 ));
+DATA(insert (  1970    0 5 f  623 ));
+/* crosstype operators float48 */
+DATA(insert (  1970  701 1 f  1122 ));
+DATA(insert (  1970  701 2 f  1124 ));
+DATA(insert (  1970  701 3 f  1120 ));
+DATA(insert (  1970  701 4 f  1125 ));
+DATA(insert (  1970  701 5 f  1123 ));
 
 /*
  *     btree float8_ops
  */
 
-DATA(insert (  1972 1 f  672 ));
-DATA(insert (  1972 2 f  673 ));
-DATA(insert (  1972 3 f  670 ));
-DATA(insert (  1972 4 f  675 ));
-DATA(insert (  1972 5 f  674 ));
+DATA(insert (  1972    0 1 f  672 ));
+DATA(insert (  1972    0 2 f  673 ));
+DATA(insert (  1972    0 3 f  670 ));
+DATA(insert (  1972    0 4 f  675 ));
+DATA(insert (  1972    0 5 f  674 ));
+/* crosstype operators float84 */
+DATA(insert (  1972  700 1 f  1132 ));
+DATA(insert (  1972  700 2 f  1134 ));
+DATA(insert (  1972  700 3 f  1130 ));
+DATA(insert (  1972  700 4 f  1135 ));
+DATA(insert (  1972  700 5 f  1133 ));
 
 /*
  *     btree char_ops
  */
 
-DATA(insert (   429 1 f  631 ));
-DATA(insert (   429 2 f  632 ));
-DATA(insert (   429 3 f   92 ));
-DATA(insert (   429 4 f  634 ));
-DATA(insert (   429 5 f  633 ));
+DATA(insert (   429    0 1 f  631 ));
+DATA(insert (   429    0 2 f  632 ));
+DATA(insert (   429    0 3 f   92 ));
+DATA(insert (   429    0 4 f  634 ));
+DATA(insert (   429    0 5 f  633 ));
 
 /*
  *     btree name_ops
  */
 
-DATA(insert (  1986 1 f  660 ));
-DATA(insert (  1986 2 f  661 ));
-DATA(insert (  1986 3 f   93 ));
-DATA(insert (  1986 4 f  663 ));
-DATA(insert (  1986 5 f  662 ));
+DATA(insert (  1986    0 1 f  660 ));
+DATA(insert (  1986    0 2 f  661 ));
+DATA(insert (  1986    0 3 f   93 ));
+DATA(insert (  1986    0 4 f  663 ));
+DATA(insert (  1986    0 5 f  662 ));
 
 /*
  *     btree text_ops
  */
 
-DATA(insert (  1994 1 f  664 ));
-DATA(insert (  1994 2 f  665 ));
-DATA(insert (  1994 3 f   98 ));
-DATA(insert (  1994 4 f  667 ));
-DATA(insert (  1994 5 f  666 ));
+DATA(insert (  1994    0 1 f  664 ));
+DATA(insert (  1994    0 2 f  665 ));
+DATA(insert (  1994    0 3 f   98 ));
+DATA(insert (  1994    0 4 f  667 ));
+DATA(insert (  1994    0 5 f  666 ));
 
 /*
  *     btree bpchar_ops
  */
 
-DATA(insert (   426 1 f 1058 ));
-DATA(insert (   426 2 f 1059 ));
-DATA(insert (   426 3 f 1054 ));
-DATA(insert (   426 4 f 1061 ));
-DATA(insert (   426 5 f 1060 ));
+DATA(insert (   426    0 1 f 1058 ));
+DATA(insert (   426    0 2 f 1059 ));
+DATA(insert (   426    0 3 f 1054 ));
+DATA(insert (   426    0 4 f 1061 ));
+DATA(insert (   426    0 5 f 1060 ));
 
 /*
  *     btree varchar_ops (same operators as text_ops)
  */
 
-DATA(insert (  2003 1 f 664 ));
-DATA(insert (  2003 2 f 665 ));
-DATA(insert (  2003 3 f  98 ));
-DATA(insert (  2003 4 f 667 ));
-DATA(insert (  2003 5 f 666 ));
+DATA(insert (  2003    0 1 f 664 ));
+DATA(insert (  2003    0 2 f 665 ));
+DATA(insert (  2003    0 3 f  98 ));
+DATA(insert (  2003    0 4 f 667 ));
+DATA(insert (  2003    0 5 f 666 ));
 
 /*
  *     btree bytea_ops
  */
 
-DATA(insert (   428 1 f 1957 ));
-DATA(insert (   428 2 f 1958 ));
-DATA(insert (   428 3 f 1955 ));
-DATA(insert (   428 4 f 1960 ));
-DATA(insert (   428 5 f 1959 ));
+DATA(insert (   428    0 1 f 1957 ));
+DATA(insert (   428    0 2 f 1958 ));
+DATA(insert (   428    0 3 f 1955 ));
+DATA(insert (   428    0 4 f 1960 ));
+DATA(insert (   428    0 5 f 1959 ));
 
 /*
  *     btree abstime_ops
  */
 
-DATA(insert (   421 1 f  562 ));
-DATA(insert (   421 2 f  564 ));
-DATA(insert (   421 3 f  560 ));
-DATA(insert (   421 4 f  565 ));
-DATA(insert (   421 5 f  563 ));
+DATA(insert (   421    0 1 f  562 ));
+DATA(insert (   421    0 2 f  564 ));
+DATA(insert (   421    0 3 f  560 ));
+DATA(insert (   421    0 4 f  565 ));
+DATA(insert (   421    0 5 f  563 ));
 
 /*
  *     btree date_ops
  */
 
-DATA(insert (   434 1 f 1095 ));
-DATA(insert (   434 2 f 1096 ));
-DATA(insert (   434 3 f 1093 ));
-DATA(insert (   434 4 f 1098 ));
-DATA(insert (   434 5 f 1097 ));
+DATA(insert (   434    0 1 f 1095 ));
+DATA(insert (   434    0 2 f 1096 ));
+DATA(insert (   434    0 3 f 1093 ));
+DATA(insert (   434    0 4 f 1098 ));
+DATA(insert (   434    0 5 f 1097 ));
 
 /*
  *     btree time_ops
  */
 
-DATA(insert (  1996 1 f 1110 ));
-DATA(insert (  1996 2 f 1111 ));
-DATA(insert (  1996 3 f 1108 ));
-DATA(insert (  1996 4 f 1113 ));
-DATA(insert (  1996 5 f 1112 ));
+DATA(insert (  1996    0 1 f 1110 ));
+DATA(insert (  1996    0 2 f 1111 ));
+DATA(insert (  1996    0 3 f 1108 ));
+DATA(insert (  1996    0 4 f 1113 ));
+DATA(insert (  1996    0 5 f 1112 ));
 
 /*
  *     btree timetz_ops
  */
 
-DATA(insert (  2000 1 f 1552 ));
-DATA(insert (  2000 2 f 1553 ));
-DATA(insert (  2000 3 f 1550 ));
-DATA(insert (  2000 4 f 1555 ));
-DATA(insert (  2000 5 f 1554 ));
+DATA(insert (  2000    0 1 f 1552 ));
+DATA(insert (  2000    0 2 f 1553 ));
+DATA(insert (  2000    0 3 f 1550 ));
+DATA(insert (  2000    0 4 f 1555 ));
+DATA(insert (  2000    0 5 f 1554 ));
 
 /*
  *     btree timestamp_ops
  */
 
-DATA(insert (  2039 1 f 2062 ));
-DATA(insert (  2039 2 f 2063 ));
-DATA(insert (  2039 3 f 2060 ));
-DATA(insert (  2039 4 f 2065 ));
-DATA(insert (  2039 5 f 2064 ));
+DATA(insert (  2039    0 1 f 2062 ));
+DATA(insert (  2039    0 2 f 2063 ));
+DATA(insert (  2039    0 3 f 2060 ));
+DATA(insert (  2039    0 4 f 2065 ));
+DATA(insert (  2039    0 5 f 2064 ));
 
 /*
  *     btree timestamptz_ops
  */
 
-DATA(insert (  1998 1 f 1322 ));
-DATA(insert (  1998 2 f 1323 ));
-DATA(insert (  1998 3 f 1320 ));
-DATA(insert (  1998 4 f 1325 ));
-DATA(insert (  1998 5 f 1324 ));
+DATA(insert (  1998    0 1 f 1322 ));
+DATA(insert (  1998    0 2 f 1323 ));
+DATA(insert (  1998    0 3 f 1320 ));
+DATA(insert (  1998    0 4 f 1325 ));
+DATA(insert (  1998    0 5 f 1324 ));
 
 /*
  *     btree interval_ops
  */
 
-DATA(insert (  1982 1 f 1332 ));
-DATA(insert (  1982 2 f 1333 ));
-DATA(insert (  1982 3 f 1330 ));
-DATA(insert (  1982 4 f 1335 ));
-DATA(insert (  1982 5 f 1334 ));
+DATA(insert (  1982    0 1 f 1332 ));
+DATA(insert (  1982    0 2 f 1333 ));
+DATA(insert (  1982    0 3 f 1330 ));
+DATA(insert (  1982    0 4 f 1335 ));
+DATA(insert (  1982    0 5 f 1334 ));
 
 /*
  *     btree macaddr
  */
 
-DATA(insert (  1984 1 f 1222 ));
-DATA(insert (  1984 2 f 1223 ));
-DATA(insert (  1984 3 f 1220 ));
-DATA(insert (  1984 4 f 1225 ));
-DATA(insert (  1984 5 f 1224 ));
+DATA(insert (  1984    0 1 f 1222 ));
+DATA(insert (  1984    0 2 f 1223 ));
+DATA(insert (  1984    0 3 f 1220 ));
+DATA(insert (  1984    0 4 f 1225 ));
+DATA(insert (  1984    0 5 f 1224 ));
 
 /*
  *     btree inet
  */
 
-DATA(insert (  1974 1 f 1203 ));
-DATA(insert (  1974 2 f 1204 ));
-DATA(insert (  1974 3 f 1201 ));
-DATA(insert (  1974 4 f 1206 ));
-DATA(insert (  1974 5 f 1205 ));
+DATA(insert (  1974    0 1 f 1203 ));
+DATA(insert (  1974    0 2 f 1204 ));
+DATA(insert (  1974    0 3 f 1201 ));
+DATA(insert (  1974    0 4 f 1206 ));
+DATA(insert (  1974    0 5 f 1205 ));
 
 /*
  *     btree cidr
  */
 
-DATA(insert (   432 1 f  822 ));
-DATA(insert (   432 2 f  823 ));
-DATA(insert (   432 3 f  820 ));
-DATA(insert (   432 4 f  825 ));
-DATA(insert (   432 5 f  824 ));
+DATA(insert (   432    0 1 f  822 ));
+DATA(insert (   432    0 2 f  823 ));
+DATA(insert (   432    0 3 f  820 ));
+DATA(insert (   432    0 4 f  825 ));
+DATA(insert (   432    0 5 f  824 ));
 
 /*
  *     btree numeric
  */
 
-DATA(insert (  1988 1 f 1754 ));
-DATA(insert (  1988 2 f 1755 ));
-DATA(insert (  1988 3 f 1752 ));
-DATA(insert (  1988 4 f 1757 ));
-DATA(insert (  1988 5 f 1756 ));
+DATA(insert (  1988    0 1 f 1754 ));
+DATA(insert (  1988    0 2 f 1755 ));
+DATA(insert (  1988    0 3 f 1752 ));
+DATA(insert (  1988    0 4 f 1757 ));
+DATA(insert (  1988    0 5 f 1756 ));
 
 /*
  *     btree bool
  */
 
-DATA(insert (   424 1 f   58 ));
-DATA(insert (   424 2 f 1694 ));
-DATA(insert (   424 3 f   91 ));
-DATA(insert (   424 4 f 1695 ));
-DATA(insert (   424 5 f   59 ));
+DATA(insert (   424    0 1 f   58 ));
+DATA(insert (   424    0 2 f 1694 ));
+DATA(insert (   424    0 3 f   91 ));
+DATA(insert (   424    0 4 f 1695 ));
+DATA(insert (   424    0 5 f   59 ));
 
 /*
  *     btree bit
  */
 
-DATA(insert (   423 1 f 1786 ));
-DATA(insert (   423 2 f 1788 ));
-DATA(insert (   423 3 f 1784 ));
-DATA(insert (   423 4 f 1789 ));
-DATA(insert (   423 5 f 1787 ));
+DATA(insert (   423    0 1 f 1786 ));
+DATA(insert (   423    0 2 f 1788 ));
+DATA(insert (   423    0 3 f 1784 ));
+DATA(insert (   423    0 4 f 1789 ));
+DATA(insert (   423    0 5 f 1787 ));
 
 /*
  *     btree varbit
  */
 
-DATA(insert (  2002 1 f 1806 ));
-DATA(insert (  2002 2 f 1808 ));
-DATA(insert (  2002 3 f 1804 ));
-DATA(insert (  2002 4 f 1809 ));
-DATA(insert (  2002 5 f 1807 ));
+DATA(insert (  2002    0 1 f 1806 ));
+DATA(insert (  2002    0 2 f 1808 ));
+DATA(insert (  2002    0 3 f 1804 ));
+DATA(insert (  2002    0 4 f 1809 ));
+DATA(insert (  2002    0 5 f 1807 ));
 
 /*
  *     btree text pattern
  */
 
-DATA(insert (  2095 1 f 2314 ));
-DATA(insert (  2095 2 f 2315 ));
-DATA(insert (  2095 3 f 2316 ));
-DATA(insert (  2095 4 f 2317 ));
-DATA(insert (  2095 5 f 2318 ));
+DATA(insert (  2095    0 1 f 2314 ));
+DATA(insert (  2095    0 2 f 2315 ));
+DATA(insert (  2095    0 3 f 2316 ));
+DATA(insert (  2095    0 4 f 2317 ));
+DATA(insert (  2095    0 5 f 2318 ));
 
 /*
  *     btree varchar pattern (same operators as text)
  */
 
-DATA(insert (  2096 1 f 2314 ));
-DATA(insert (  2096 2 f 2315 ));
-DATA(insert (  2096 3 f 2316 ));
-DATA(insert (  2096 4 f 2317 ));
-DATA(insert (  2096 5 f 2318 ));
+DATA(insert (  2096    0 1 f 2314 ));
+DATA(insert (  2096    0 2 f 2315 ));
+DATA(insert (  2096    0 3 f 2316 ));
+DATA(insert (  2096    0 4 f 2317 ));
+DATA(insert (  2096    0 5 f 2318 ));
 
 /*
  *     btree bpchar pattern
  */
 
-DATA(insert (  2097 1 f 2326 ));
-DATA(insert (  2097 2 f 2327 ));
-DATA(insert (  2097 3 f 2328 ));
-DATA(insert (  2097 4 f 2329 ));
-DATA(insert (  2097 5 f 2330 ));
+DATA(insert (  2097    0 1 f 2326 ));
+DATA(insert (  2097    0 2 f 2327 ));
+DATA(insert (  2097    0 3 f 2328 ));
+DATA(insert (  2097    0 4 f 2329 ));
+DATA(insert (  2097    0 5 f 2330 ));
 
 /*
  *     btree name pattern
  */
 
-DATA(insert (  2098 1 f 2332 ));
-DATA(insert (  2098 2 f 2333 ));
-DATA(insert (  2098 3 f 2334 ));
-DATA(insert (  2098 4 f 2335 ));
-DATA(insert (  2098 5 f 2336 ));
+DATA(insert (  2098    0 1 f 2332 ));
+DATA(insert (  2098    0 2 f 2333 ));
+DATA(insert (  2098    0 3 f 2334 ));
+DATA(insert (  2098    0 4 f 2335 ));
+DATA(insert (  2098    0 5 f 2336 ));
 
 /*
  *     btree money_ops
  */
 
-DATA(insert (  2099 1 f  902 ));
-DATA(insert (  2099 2 f  904 ));
-DATA(insert (  2099 3 f  900 ));
-DATA(insert (  2099 4 f  905 ));
-DATA(insert (  2099 5 f  903 ));
+DATA(insert (  2099    0 1 f  902 ));
+DATA(insert (  2099    0 2 f  904 ));
+DATA(insert (  2099    0 3 f  900 ));
+DATA(insert (  2099    0 4 f  905 ));
+DATA(insert (  2099    0 5 f  903 ));
 
 /*
  *     btree reltime_ops
  */
 
-DATA(insert (  2233 1 f  568 ));
-DATA(insert (  2233 2 f  570 ));
-DATA(insert (  2233 3 f  566 ));
-DATA(insert (  2233 4 f  569 ));
-DATA(insert (  2233 5 f  571 ));
+DATA(insert (  2233    0 1 f  568 ));
+DATA(insert (  2233    0 2 f  570 ));
+DATA(insert (  2233    0 3 f  566 ));
+DATA(insert (  2233    0 4 f  571 ));
+DATA(insert (  2233    0 5 f  569 ));
 
 /*
  *     btree tinterval_ops
  */
 
-DATA(insert (  2234 1 f  813 ));
-DATA(insert (  2234 2 f  815 ));
-DATA(insert (  2234 3 f  811 ));
-DATA(insert (  2234 4 f  814 ));
-DATA(insert (  2234 5 f  816 ));
+DATA(insert (  2234    0 1 f  813 ));
+DATA(insert (  2234    0 2 f  815 ));
+DATA(insert (  2234    0 3 f  811 ));
+DATA(insert (  2234    0 4 f  816 ));
+DATA(insert (  2234    0 5 f  814 ));
 
 /*
  *     btree array_ops
  */
 
-DATA(insert (   397 1 f 1072 ));
-DATA(insert (   397 2 f 1074 ));
-DATA(insert (   397 3 f 1070 ));
-DATA(insert (   397 4 f 1075 ));
-DATA(insert (   397 5 f 1073 ));
+DATA(insert (   397    0 1 f 1072 ));
+DATA(insert (   397    0 2 f 1074 ));
+DATA(insert (   397    0 3 f 1070 ));
+DATA(insert (   397    0 4 f 1075 ));
+DATA(insert (   397    0 5 f 1073 ));
 
 /*
  *     hash index _ops
  */
 
 /* bpchar_ops */
-DATA(insert (   427 1 f 1054 ));
+DATA(insert (   427    0 1 f 1054 ));
 /* char_ops */
-DATA(insert (   431 1 f   92 ));
+DATA(insert (   431    0 1 f   92 ));
 /* cidr_ops */
-DATA(insert (   433 1 f  820 ));
+DATA(insert (   433    0 1 f  820 ));
 /* date_ops */
-DATA(insert (   435 1 f 1093 ));
+DATA(insert (   435    0 1 f 1093 ));
 /* float4_ops */
-DATA(insert (  1971 1 f  620 ));
+DATA(insert (  1971    0 1 f  620 ));
 /* float8_ops */
-DATA(insert (  1973 1 f  670 ));
+DATA(insert (  1973    0 1 f  670 ));
 /* inet_ops */
-DATA(insert (  1975 1 f 1201 ));
+DATA(insert (  1975    0 1 f 1201 ));
 /* int2_ops */
-DATA(insert (  1977 1 f   94 ));
+DATA(insert (  1977    0 1 f   94 ));
 /* int4_ops */
-DATA(insert (  1979 1 f   96 ));
+DATA(insert (  1979    0 1 f   96 ));
 /* int8_ops */
-DATA(insert (  1981 1 f  410 ));
+DATA(insert (  1981    0 1 f  410 ));
 /* interval_ops */
-DATA(insert (  1983 1 f 1330 ));
+DATA(insert (  1983    0 1 f 1330 ));
 /* macaddr_ops */
-DATA(insert (  1985 1 f 1220 ));
+DATA(insert (  1985    0 1 f 1220 ));
 /* name_ops */
-DATA(insert (  1987 1 f   93 ));
+DATA(insert (  1987    0 1 f   93 ));
 /* oid_ops */
-DATA(insert (  1990 1 f  607 ));
+DATA(insert (  1990    0 1 f  607 ));
 /* oidvector_ops */
-DATA(insert (  1992 1 f  649 ));
+DATA(insert (  1992    0 1 f  649 ));
 /* text_ops */
-DATA(insert (  1995 1 f   98 ));
+DATA(insert (  1995    0 1 f   98 ));
 /* time_ops */
-DATA(insert (  1997 1 f 1108 ));
+DATA(insert (  1997    0 1 f 1108 ));
 /* timestamptz_ops */
-DATA(insert (  1999 1 f 1320 ));
+DATA(insert (  1999    0 1 f 1320 ));
 /* timetz_ops */
-DATA(insert (  2001 1 f 1550 ));
+DATA(insert (  2001    0 1 f 1550 ));
 /* varchar_ops */
-DATA(insert (  2004 1 f   98 ));
+DATA(insert (  2004    0 1 f   98 ));
 /* timestamp_ops */
-DATA(insert (  2040 1 f 2060 ));
+DATA(insert (  2040    0 1 f 2060 ));
 /* bool_ops */
-DATA(insert (  2222 1 f   91 ));
+DATA(insert (  2222    0 1 f   91 ));
 /* bytea_ops */
-DATA(insert (  2223 1 f 1955 ));
+DATA(insert (  2223    0 1 f 1955 ));
 /* int2vector_ops */
-DATA(insert (  2224 1 f  386 ));
+DATA(insert (  2224    0 1 f  386 ));
 /* xid_ops */
-DATA(insert (  2225 1 f  352 ));
+DATA(insert (  2225    0 1 f  352 ));
 /* cid_ops */
-DATA(insert (  2226 1 f  385 ));
+DATA(insert (  2226    0 1 f  385 ));
 /* abstime_ops */
-DATA(insert (  2227 1 f  560 ));
+DATA(insert (  2227    0 1 f  560 ));
 /* reltime_ops */
-DATA(insert (  2228 1 f  566 ));
+DATA(insert (  2228    0 1 f  566 ));
 /* text_pattern_ops */
-DATA(insert (  2229 1 f 2316 ));
+DATA(insert (  2229    0 1 f 2316 ));
 /* varchar_pattern_ops */
-DATA(insert (  2230 1 f 2316 ));
+DATA(insert (  2230    0 1 f 2316 ));
 /* bpchar_pattern_ops */
-DATA(insert (  2231 1 f 2328 ));
+DATA(insert (  2231    0 1 f 2328 ));
 /* name_pattern_ops */
-DATA(insert (  2232 1 f 2334 ));
+DATA(insert (  2232    0 1 f 2334 ));
 /* aclitem_ops */
-DATA(insert (  2235 1 f  974 ));
+DATA(insert (  2235    0 1 f  974 ));
 
 #endif   /* PG_AMOP_H */
index a2607db5eb8b9f77719789c246d7ced2a6e74ff5..e284dedbf0d23c8db3e73621bf8247cc14e1b5e4 100644 (file)
@@ -6,15 +6,20 @@
  *
  * The amproc table identifies support procedures associated with index
  * opclasses.  These procedures can't be listed in pg_amop since they are
- * not associated with indexable operators for the opclass.
+ * not the implementation of any indexable operator for the opclass.
  *
- * Note: the primary key for this table is <amopclaid, amprocnum>.
+ * The primary key for this table is <amopclaid, amprocsubtype, amprocnum>.
+ * amprocsubtype is equal to zero for an opclass's "default" procedures.
+ * Usually a nondefault amprocsubtype indicates a support procedure to be
+ * used with operators having the same nondefault amopsubtype.  The exact
+ * behavior depends on the index AM, however, and some don't pay attention
+ * to subtype at all.
  *
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amproc.h,v 1.44 2003/08/17 19:58:06 tgl Exp $
+ * $Id: pg_amproc.h,v 1.45 2003/11/12 21:15:57 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -40,6 +45,7 @@
 CATALOG(pg_amproc) BKI_WITHOUT_OIDS
 {
        Oid                     amopclaid;              /* the index opclass this entry is for */
+       Oid                     amprocsubtype;  /* procedure subtype, or zero if default */
        int2            amprocnum;              /* support procedure index */
        regproc         amproc;                 /* OID of the proc */
 } FormData_pg_amproc;
@@ -55,10 +61,11 @@ typedef FormData_pg_amproc *Form_pg_amproc;
  *             compiler constants for pg_amproc
  * ----------------
  */
-#define Natts_pg_amproc                                        3
+#define Natts_pg_amproc                                        4
 #define Anum_pg_amproc_amopclaid               1
-#define Anum_pg_amproc_amprocnum               2
-#define Anum_pg_amproc_amproc                  3
+#define Anum_pg_amproc_amprocsubtype   2
+#define Anum_pg_amproc_amprocnum               3
+#define Anum_pg_amproc_amproc                  4
 
 /* ----------------
  *             initial contents of pg_amproc
@@ -66,88 +73,93 @@ typedef FormData_pg_amproc *Form_pg_amproc;
  */
 
 /* rtree */
-DATA(insert (   422 1  193 ));
-DATA(insert (   422 2  194 ));
-DATA(insert (   422 3  196 ));
-DATA(insert (   425 1  193 ));
-DATA(insert (   425 2  194 ));
-DATA(insert (   425 3  195 ));
-DATA(insert (  1993 1  197 ));
-DATA(insert (  1993 2  198 ));
-DATA(insert (  1993 3  199 ));
+DATA(insert (   425    0 1     193 ));
+DATA(insert (   425    0 2     194 ));
+DATA(insert (   425    0 3     195 ));
+DATA(insert (  1993    0 1     197 ));
+DATA(insert (  1993    0 2     198 ));
+DATA(insert (  1993    0 3     199 ));
 
 
 /* btree */
-DATA(insert (   397 1  382 ));
-DATA(insert (   421 1  357 ));
-DATA(insert (   423 1 1596 ));
-DATA(insert (   424 1 1693 ));
-DATA(insert (   426 1 1078 ));
-DATA(insert (   428 1 1954 ));
-DATA(insert (   429 1  358 ));
-DATA(insert (   432 1  926 ));
-DATA(insert (   434 1 1092 ));
-DATA(insert (  1970 1  354 ));
-DATA(insert (  1972 1  355 ));
-DATA(insert (  1974 1  926 ));
-DATA(insert (  1976 1  350 ));
-DATA(insert (  1978 1  351 ));
-DATA(insert (  1980 1  842 ));
-DATA(insert (  1982 1 1315 ));
-DATA(insert (  1984 1  836 ));
-DATA(insert (  1986 1  359 ));
-DATA(insert (  1988 1 1769 ));
-DATA(insert (  1989 1  356 ));
-DATA(insert (  1991 1  404 ));
-DATA(insert (  1994 1  360 ));
-DATA(insert (  1996 1 1107 ));
-DATA(insert (  1998 1 1314 ));
-DATA(insert (  2000 1 1358 ));
-DATA(insert (  2002 1 1672 ));
-DATA(insert (  2003 1  360 ));
-DATA(insert (  2039 1 2045 ));
-DATA(insert (  2095 1 2166 ));
-DATA(insert (  2096 1 2166 ));
-DATA(insert (  2097 1 2180 ));
-DATA(insert (  2098 1 2187 ));
-DATA(insert (  2099 1  377 ));
-DATA(insert (  2233 1  380 ));
-DATA(insert (  2234 1  381 ));
+DATA(insert (   397    0 1     382 ));
+DATA(insert (   421    0 1     357 ));
+DATA(insert (   423    0 1 1596 ));
+DATA(insert (   424    0 1 1693 ));
+DATA(insert (   426    0 1 1078 ));
+DATA(insert (   428    0 1 1954 ));
+DATA(insert (   429    0 1     358 ));
+DATA(insert (   432    0 1     926 ));
+DATA(insert (   434    0 1 1092 ));
+DATA(insert (  1970    0 1     354 ));
+DATA(insert (  1970  701 1     2194 ));
+DATA(insert (  1972    0 1     355 ));
+DATA(insert (  1972  700 1     2195 ));
+DATA(insert (  1974    0 1     926 ));
+DATA(insert (  1976    0 1     350 ));
+DATA(insert (  1976   23 1     2190 ));
+DATA(insert (  1976   20 1     2192 ));
+DATA(insert (  1978    0 1     351 ));
+DATA(insert (  1978   20 1     2188 ));
+DATA(insert (  1978   21 1     2191 ));
+DATA(insert (  1980    0 1     842 ));
+DATA(insert (  1980   23 1     2189 ));
+DATA(insert (  1980   21 1     2193 ));
+DATA(insert (  1982    0 1 1315 ));
+DATA(insert (  1984    0 1     836 ));
+DATA(insert (  1986    0 1     359 ));
+DATA(insert (  1988    0 1 1769 ));
+DATA(insert (  1989    0 1     356 ));
+DATA(insert (  1991    0 1     404 ));
+DATA(insert (  1994    0 1     360 ));
+DATA(insert (  1996    0 1 1107 ));
+DATA(insert (  1998    0 1 1314 ));
+DATA(insert (  2000    0 1 1358 ));
+DATA(insert (  2002    0 1 1672 ));
+DATA(insert (  2003    0 1     360 ));
+DATA(insert (  2039    0 1 2045 ));
+DATA(insert (  2095    0 1 2166 ));
+DATA(insert (  2096    0 1 2166 ));
+DATA(insert (  2097    0 1 2180 ));
+DATA(insert (  2098    0 1 2187 ));
+DATA(insert (  2099    0 1  377 ));
+DATA(insert (  2233    0 1  380 ));
+DATA(insert (  2234    0 1  381 ));
 
 
 /* hash */
-DATA(insert (   427 1 1080 ));
-DATA(insert (   431 1  454 ));
-DATA(insert (   433 1  456 ));
-DATA(insert (   435 1  450 ));
-DATA(insert (  1971 1  451 ));
-DATA(insert (  1973 1  452 ));
-DATA(insert (  1975 1  456 ));
-DATA(insert (  1977 1  449 ));
-DATA(insert (  1979 1  450 ));
-DATA(insert (  1981 1  949 ));
-DATA(insert (  1983 1 1697 ));
-DATA(insert (  1985 1  399 ));
-DATA(insert (  1987 1  455 ));
-DATA(insert (  1990 1  453 ));
-DATA(insert (  1992 1  457 ));
-DATA(insert (  1995 1  400 ));
-DATA(insert (  1997 1  452 ));
-DATA(insert (  1999 1  452 ));
-DATA(insert (  2001 1 1696 ));
-DATA(insert (  2004 1  400 ));
-DATA(insert (  2040 1  452 ));
-DATA(insert (  2222 1  454 ));
-DATA(insert (  2223 1  456 ));
-DATA(insert (  2224 1  398 ));
-DATA(insert (  2225 1  450 ));
-DATA(insert (  2226 1  450 ));
-DATA(insert (  2227 1  450 ));
-DATA(insert (  2228 1  450 ));
-DATA(insert (  2229 1  456 ));
-DATA(insert (  2230 1  456 ));
-DATA(insert (  2231 1  456 ));
-DATA(insert (  2232 1  455 ));
-DATA(insert (  2235 1  329 ));
+DATA(insert (   427    0 1 1080 ));
+DATA(insert (   431    0 1     454 ));
+DATA(insert (   433    0 1     456 ));
+DATA(insert (   435    0 1     450 ));
+DATA(insert (  1971    0 1     451 ));
+DATA(insert (  1973    0 1     452 ));
+DATA(insert (  1975    0 1     456 ));
+DATA(insert (  1977    0 1     449 ));
+DATA(insert (  1979    0 1     450 ));
+DATA(insert (  1981    0 1     949 ));
+DATA(insert (  1983    0 1 1697 ));
+DATA(insert (  1985    0 1     399 ));
+DATA(insert (  1987    0 1     455 ));
+DATA(insert (  1990    0 1     453 ));
+DATA(insert (  1992    0 1     457 ));
+DATA(insert (  1995    0 1     400 ));
+DATA(insert (  1997    0 1     452 ));
+DATA(insert (  1999    0 1     452 ));
+DATA(insert (  2001    0 1 1696 ));
+DATA(insert (  2004    0 1     400 ));
+DATA(insert (  2040    0 1     452 ));
+DATA(insert (  2222    0 1     454 ));
+DATA(insert (  2223    0 1     456 ));
+DATA(insert (  2224    0 1     398 ));
+DATA(insert (  2225    0 1     450 ));
+DATA(insert (  2226    0 1     450 ));
+DATA(insert (  2227    0 1     450 ));
+DATA(insert (  2228    0 1     450 ));
+DATA(insert (  2229    0 1     456 ));
+DATA(insert (  2230    0 1     456 ));
+DATA(insert (  2231    0 1     456 ));
+DATA(insert (  2232    0 1     455 ));
+DATA(insert (  2235    0 1     329 ));
 
 #endif   /* PG_AMPROC_H */
index af277ad687aec114506435da31a52d136c08e267..0f196de19fc82fa71966a6264f7b1a9a45664717 100644 (file)
  * such an index.
  *
  * Normally opckeytype = InvalidOid (zero), indicating that the data stored
- * in the index is the same as the input data. If opckeytype is nonzero
- * then it indicates that a conversion step is needed to produce the stored
- * index data, which will be of type opckeytype (which might be the same or
- * different from the input data).     Performing such a conversion is the
- * responsibility of the index access method --- not all AMs support this.
+ * in the index is the same as the data in the indexed column.  If opckeytype
+ * is nonzero then it indicates that a conversion step is needed to produce
+ * the stored index data, which will be of type opckeytype (which might be
+ * the same or different from the input datatype).  Performing such a
+ * conversion is the responsibility of the index access method --- not all
+ * AMs support this.
  *
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_opclass.h,v 1.57 2003/08/17 19:58:06 tgl Exp $
+ * $Id: pg_opclass.h,v 1.58 2003/11/12 21:15:57 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -56,9 +57,9 @@ CATALOG(pg_opclass)
        NameData        opcname;                /* name of this opclass */
        Oid                     opcnamespace;   /* namespace of this opclass */
        int4            opcowner;               /* opclass owner */
-       Oid                     opcintype;              /* type of input data for opclass */
+       Oid                     opcintype;              /* type of data indexed by opclass */
        bool            opcdefault;             /* T if opclass is default for opcintype */
-       Oid                     opckeytype;             /* type of index data, or InvalidOid */
+       Oid                     opckeytype;             /* type of data in index, or InvalidOid */
 } FormData_pg_opclass;
 
 /* ----------------
@@ -89,7 +90,6 @@ typedef FormData_pg_opclass *Form_pg_opclass;
 DATA(insert OID =  421 (       403             abstime_ops             PGNSP PGUID  702 t 0 ));
 DATA(insert OID =  397 (       403             array_ops               PGNSP PGUID 2277 t 0 ));
 #define ARRAY_BTREE_OPS_OID 397
-DATA(insert OID =  422 (       402             bigbox_ops              PGNSP PGUID  603 f 0 ));
 DATA(insert OID =  423 (       403             bit_ops                 PGNSP PGUID 1560 t 0 ));
 DATA(insert OID =  424 (       403             bool_ops                PGNSP PGUID   16 t 0 ));
 DATA(insert OID =  425 (       402             box_ops                 PGNSP PGUID  603 t 0 ));
index 4128d5f164314b7aa0adf042d016fce2bb750d6e..50b363eda34439246fc5fc0ff6bd67b9cb2d031d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.314 2003/10/21 16:23:16 tgl Exp $
+ * $Id: pg_proc.h,v 1.315 2003/11/12 21:15:57 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -400,8 +400,6 @@ DATA(insert OID = 194 (  rt_box_inter          PGNSP PGUID 12 f f t f i 2 2278 "603 60
 DESCR("r-tree");
 DATA(insert OID = 195 (  rt_box_size      PGNSP PGUID 12 f f t f i 2 2278 "603 2281"  rt_box_size - _null_ ));
 DESCR("r-tree");
-DATA(insert OID = 196 (  rt_bigbox_size    PGNSP PGUID 12 f f t f i 2 2278 "603 2281"  rt_bigbox_size - _null_ ));
-DESCR("r-tree");
 DATA(insert OID = 197 (  rt_poly_union    PGNSP PGUID 12 f f t f i 2 604 "604 604"  rt_poly_union - _null_ ));
 DESCR("r-tree");
 DATA(insert OID = 198 (  rt_poly_inter    PGNSP PGUID 12 f f t f i 2 2278 "604 604"  rt_poly_inter - _null_ ));
@@ -3075,6 +3073,15 @@ DATA(insert OID = 2185 ( name_pattern_gt PGNSP PGUID 12 f f t f i 2 16 "19 19" n
 DATA(insert OID = 2186 ( name_pattern_ne       PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_ne - _null_ ));
 DATA(insert OID = 2187 ( btname_pattern_cmp PGNSP PGUID 12 f f t f i 2 23 "19 19" btname_pattern_cmp - _null_ ));
 
+DATA(insert OID = 2188 ( btint48cmp         PGNSP PGUID 12 f f t f i 2 23 "23 20" btint48cmp - _null_ ));
+DATA(insert OID = 2189 ( btint84cmp         PGNSP PGUID 12 f f t f i 2 23 "20 23" btint84cmp - _null_ ));
+DATA(insert OID = 2190 ( btint24cmp         PGNSP PGUID 12 f f t f i 2 23 "21 23" btint24cmp - _null_ ));
+DATA(insert OID = 2191 ( btint42cmp         PGNSP PGUID 12 f f t f i 2 23 "23 21" btint42cmp - _null_ ));
+DATA(insert OID = 2192 ( btint28cmp         PGNSP PGUID 12 f f t f i 2 23 "21 20" btint28cmp - _null_ ));
+DATA(insert OID = 2193 ( btint82cmp         PGNSP PGUID 12 f f t f i 2 23 "20 21" btint82cmp - _null_ ));
+DATA(insert OID = 2194 ( btfloat48cmp       PGNSP PGUID 12 f f t f i 2 23 "700 701" btfloat48cmp - _null_ ));
+DATA(insert OID = 2195 ( btfloat84cmp       PGNSP PGUID 12 f f t f i 2 23 "701 700" btfloat84cmp - _null_ ));
+
 
 DATA(insert OID = 2212 (  regprocedurein       PGNSP PGUID 12 f f t f s 1 2202 "2275"  regprocedurein - _null_ ));
 DESCR("I/O");
@@ -3157,7 +3164,6 @@ DATA(insert OID = 2273 (  has_schema_privilege               PGNSP PGUID 12 f f t f s 2 16
 DESCR("current user privilege on schema by schema oid");
 
 
-
 DATA(insert OID = 2290 (  record_in                    PGNSP PGUID 12 f f t f i 1 2249 "2275"  record_in - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2291 (  record_out           PGNSP PGUID 12 f f t f i 1 2275 "2249"  record_out - _null_ ));
index 2312c0562e3cddbed6ba5b1684a7be5cb4d3a122..669ce93e70a51ed9d9d95df2cd42b5bfbde0d497 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: plannodes.h,v 1.69 2003/11/09 21:30:37 tgl Exp $
+ * $Id: plannodes.h,v 1.70 2003/11/12 21:15:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,6 +165,7 @@ typedef struct IndexScan
        List       *indxqual;           /* list of sublists of index quals */
        List       *indxqualorig;       /* the same in original form */
        List       *indxstrategy;       /* list of sublists of strategy numbers */
+       List       *indxsubtype;        /* list of sublists of strategy subtypes */
        ScanDirection indxorderdir;     /* forward or backward or don't care */
 } IndexScan;
 
index 71615b6610f001f45b26a4245ec276cfa8de6b25..602553114777948067b1695f23b65dc83ec84e78 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.228 2003/08/17 19:58:06 tgl Exp $
+ * $Id: builtins.h,v 1.229 2003/11/12 21:15:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,6 +219,14 @@ extern Datum btint4cmp(PG_FUNCTION_ARGS);
 extern Datum btint8cmp(PG_FUNCTION_ARGS);
 extern Datum btfloat4cmp(PG_FUNCTION_ARGS);
 extern Datum btfloat8cmp(PG_FUNCTION_ARGS);
+extern Datum btint48cmp(PG_FUNCTION_ARGS);
+extern Datum btint84cmp(PG_FUNCTION_ARGS);
+extern Datum btint24cmp(PG_FUNCTION_ARGS);
+extern Datum btint42cmp(PG_FUNCTION_ARGS);
+extern Datum btint28cmp(PG_FUNCTION_ARGS);
+extern Datum btint82cmp(PG_FUNCTION_ARGS);
+extern Datum btfloat48cmp(PG_FUNCTION_ARGS);
+extern Datum btfloat84cmp(PG_FUNCTION_ARGS);
 extern Datum btoidcmp(PG_FUNCTION_ARGS);
 extern Datum btoidvectorcmp(PG_FUNCTION_ARGS);
 extern Datum btabstimecmp(PG_FUNCTION_ARGS);
index e029c136b85e88ed08c0b58b970c6f3de0001539..8b945885095015d5e26e8c301cbf0057c7ce2785 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geo_decls.h,v 1.41 2003/08/04 02:40:15 momjian Exp $
+ * $Id: geo_decls.h,v 1.42 2003/11/12 21:15:59 tgl Exp $
  *
  * NOTE
  *       These routines do *not* use the float types from adt/.
@@ -399,7 +399,6 @@ extern Datum circle_area(PG_FUNCTION_ARGS);
 extern Datum rt_box_union(PG_FUNCTION_ARGS);
 extern Datum rt_box_inter(PG_FUNCTION_ARGS);
 extern Datum rt_box_size(PG_FUNCTION_ARGS);
-extern Datum rt_bigbox_size(PG_FUNCTION_ARGS);
 extern Datum rt_poly_size(PG_FUNCTION_ARGS);
 extern Datum rt_poly_union(PG_FUNCTION_ARGS);
 extern Datum rt_poly_inter(PG_FUNCTION_ARGS);
index 36146f23d11fc9f234287e9aa2a0e2dbd5858f81..2f017db844ae1828b7c5d5c93a7bae90e7a4cb22 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.83 2003/11/09 21:30:38 tgl Exp $
+ * $Id: lsyscache.h,v 1.84 2003/11/12 21:15:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,10 +26,11 @@ typedef enum IOFuncSelector
 
 extern bool op_in_opclass(Oid opno, Oid opclass);
 extern void get_op_opclass_properties(Oid opno, Oid opclass,
-                                                                         int *strategy, bool *recheck);
-extern Oid     get_opclass_member(Oid opclass, int16 strategy);
+                                                                         int *strategy, Oid *subtype,
+                                                                         bool *recheck);
+extern Oid     get_opclass_member(Oid opclass, Oid subtype, int16 strategy);
 extern Oid     get_op_hash_function(Oid opno);
-extern Oid     get_opclass_proc(Oid opclass, int16 procnum);
+extern Oid     get_opclass_proc(Oid opclass, Oid subtype, int16 procnum);
 extern char *get_attname(Oid relid, AttrNumber attnum);
 extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
 extern AttrNumber get_attnum(Oid relid, const char *attname);
index f08d6c0f1f8b38e59d85ab921e31b775aafe297c..eb24cf839ffed8b0354d27e14f02dc16e30dd035 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rel.h,v 1.69 2003/11/09 21:30:38 tgl Exp $
+ * $Id: rel.h,v 1.70 2003/11/12 21:15:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -139,8 +139,8 @@ typedef struct RelationData
        /*
         * index access support info (used only for an index relation)
         *
-        * Note: only operators and support procs for the index's own datatype
-        * are cached, not any cross-type operators.  The arrays are indexed by
+        * Note: only default operators and support procs for each opclass are
+        * cached, namely those with subtype zero.  The arrays are indexed by
         * strategy or support number, which is a sufficient identifier given
         * that restriction.
         */
index 464ab8d7e8c96ad3432a70609f64a219718ba312..46d2657d015fc796dbf595c4cabc3990bceaedbe 100644 (file)
@@ -47,7 +47,7 @@ CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
 -- in the regression test (we check them using the sequoia 2000
 -- benchmark).
 --
-CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base bigbox_ops);
+CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base);
 -- there's no easy way to check that this command actually is using
 -- the index, unfortunately.  (EXPLAIN would work, but its output
 -- changes too often for me to want to put an EXPLAIN in the test...)
index 0bdecf5ed1b22c069bb89550f94f1e330be9c1d8..21628b6e69b8a087c1bba50adbde81abd2e731be 100644 (file)
@@ -129,6 +129,14 @@ WHERE      amopclaid != 0 AND
 ------+-----------
 (0 rows)
 
+SELECT ctid, amopsubtype 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amopsubtype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amopsubtype);
+ ctid | amopsubtype 
+------+-------------
+(0 rows)
+
 SELECT ctid, amopopr 
 FROM   pg_catalog.pg_amop fk 
 WHERE  amopopr != 0 AND 
@@ -145,6 +153,14 @@ WHERE      amopclaid != 0 AND
 ------+-----------
 (0 rows)
 
+SELECT ctid, amprocsubtype 
+FROM   pg_catalog.pg_amproc fk 
+WHERE  amprocsubtype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amprocsubtype);
+ ctid | amprocsubtype 
+------+---------------
+(0 rows)
+
 SELECT ctid, amproc 
 FROM   pg_catalog.pg_amproc fk 
 WHERE  amproc != 0 AND 
index 985e06595e74c1731dcd525a9908642ee8297b1e..4e2c76de5c2fb7041f40862219ad22a5851007cf 100644 (file)
@@ -685,30 +685,61 @@ WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
 -----------+---------+-----+--------
 (0 rows)
 
--- Detect missing pg_amop entries: should have as many strategy functions
--- as AM expects for each opclass for the AM
-SELECT p1.oid, p1.amname, p2.oid, p2.opcname
-FROM pg_am AS p1, pg_opclass AS p2
-WHERE p2.opcamid = p1.oid AND
-    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
-                        WHERE p3.amopclaid = p2.oid);
- oid | amname | oid | opcname 
------+--------+-----+---------
+-- Detect missing pg_amop entries: should have as many strategy operators
+-- as AM expects for each opclass for the AM.  When nondefault subtypes are
+-- present, enforce condition separately for each subtype.
+SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amopsubtype
+FROM pg_am AS p1, pg_opclass AS p2, pg_amop AS p3
+WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
+    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4
+                        WHERE p4.amopclaid = p2.oid AND
+                              p4.amopsubtype = p3.amopsubtype);
+ oid | amname | oid | opcname | amopsubtype 
+-----+--------+-----+---------+-------------
 (0 rows)
 
 -- Check that amopopr points at a reasonable-looking operator, ie a binary
 -- operator yielding boolean.
--- NOTE: for 7.1, add restriction that operator inputs are of same type.
--- We used to have opclasses like "int24_ops" but these were broken.
 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
 FROM pg_amop AS p1, pg_operator AS p2
 WHERE p1.amopopr = p2.oid AND
-    (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype OR
-     p2.oprleft != p2.oprright);
+    (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype);
  amopclaid | amopopr | oid | oprname 
 -----------+---------+-----+---------
 (0 rows)
 
+-- Make a list of all the distinct operator names being used in particular
+-- strategy slots.  This is a bit hokey, since the list might need to change
+-- in future releases, but it's an effective way of spotting mistakes such as
+-- swapping two operators within a class.
+SELECT DISTINCT opcamid, amopstrategy, oprname
+FROM pg_amop p1 LEFT JOIN pg_opclass p2 ON amopclaid = p2.oid
+                LEFT JOIN pg_operator p3 ON amopopr = p3.oid
+ORDER BY 1, 2, 3;
+ opcamid | amopstrategy | oprname 
+---------+--------------+---------
+     402 |            1 | <<
+     402 |            2 | &<
+     402 |            3 | &&
+     402 |            4 | &>
+     402 |            5 | >>
+     402 |            6 | ~=
+     402 |            7 | ~
+     402 |            8 | @
+     403 |            1 | <
+     403 |            1 | ~<~
+     403 |            2 | <=
+     403 |            2 | ~<=~
+     403 |            3 | =
+     403 |            3 | ~=~
+     403 |            4 | >=
+     403 |            4 | ~>=~
+     403 |            5 | >
+     403 |            5 | ~>~
+     405 |            1 | =
+     405 |            1 | ~=~
+(20 rows)
+
 -- Check that all operators linked to by opclass entries have selectivity
 -- estimators.  This is not absolutely required, but it seems a reasonable
 -- thing to insist on for all standard datatypes.
@@ -721,11 +752,31 @@ WHERE p1.amopopr = p2.oid AND
 (0 rows)
 
 -- Check that operator input types match the opclass
+-- For 7.5, we require that oprleft match opcintype (possibly by coercion).
+-- When amopsubtype is zero (default), oprright must equal oprleft;
+-- when amopsubtype is not zero, oprright must equal amopsubtype.
+SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
+FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
+WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
+    NOT binary_coercible(p3.opcintype, p2.oprleft);
+ amopclaid | amopopr | oid | oprname | opcname 
+-----------+---------+-----+---------+---------
+(0 rows)
+
 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
 FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
-    (NOT binary_coercible(p3.opcintype, p2.oprleft) OR
-     p2.oprleft != p2.oprright);
+    p1.amopsubtype = 0 AND
+    p2.oprleft != p2.oprright;
+ amopclaid | amopopr | oid | oprname | opcname 
+-----------+---------+-----+---------+---------
+(0 rows)
+
+SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
+FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
+WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
+    p1.amopsubtype != 0 AND
+    p1.amopsubtype != p2.oprright;
  amopclaid | amopopr | oid | oprname | opcname 
 -----------+---------+-----+---------+---------
 (0 rows)
@@ -749,14 +800,16 @@ WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
 (0 rows)
 
 -- Detect missing pg_amproc entries: should have as many support functions
--- as AM expects for each opclass for the AM
-SELECT p1.oid, p1.amname, p2.oid, p2.opcname
-FROM pg_am AS p1, pg_opclass AS p2
-WHERE p2.opcamid = p1.oid AND
-    p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
-                     WHERE p3.amopclaid = p2.oid);
- oid | amname | oid | opcname 
------+--------+-----+---------
+-- as AM expects for each opclass for the AM.  When nondefault subtypes are
+-- present, enforce condition separately for each subtype.
+SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amprocsubtype
+FROM pg_am AS p1, pg_opclass AS p2, pg_amproc AS p3
+WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
+    p1.amsupport != (SELECT count(*) FROM pg_amproc AS p4
+                     WHERE p4.amopclaid = p2.oid AND
+                           p4.amprocsubtype = p3.amprocsubtype);
+ oid | amname | oid | opcname | amprocsubtype 
+-----+--------+-----+---------+---------------
 (0 rows)
 
 -- Unfortunately, we can't check the amproc link very well because the
@@ -782,13 +835,15 @@ WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
 (0 rows)
 
 -- For btree, though, we can do better since we know the support routines
--- must be of the form cmp(input, input) returns int4.
+-- must be of the form cmp(input, input) returns int4 in the default case
+-- (subtype = 0), and cmp(input, subtype) returns int4 when subtype != 0.
 SELECT p1.amopclaid, p1.amprocnum,
        p2.oid, p2.proname,
        p3.opcname
 FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3
 WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
     AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
+    amprocsubtype = 0 AND
     (opckeytype != 0
      OR amprocnum != 1
      OR proretset
@@ -800,6 +855,24 @@ WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
 -----------+-----------+-----+---------+---------
 (0 rows)
 
+SELECT p1.amopclaid, p1.amprocnum,
+       p2.oid, p2.proname,
+       p3.opcname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3
+WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
+    AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
+    amprocsubtype != 0 AND
+    (opckeytype != 0
+     OR amprocnum != 1
+     OR proretset
+     OR prorettype != 23
+     OR pronargs != 2
+     OR NOT binary_coercible(opcintype, proargtypes[0])
+     OR proargtypes[1] != amprocsubtype);
+ amopclaid | amprocnum | oid | proname | opcname 
+-----------+-----------+-----+---------+---------
+(0 rows)
+
 -- For hash we can also do a little better: the support routines must be
 -- of the form hash(something) returns int4.  Ideally we'd check that the
 -- opcintype is binary-coercible to the function's input, but there are
index 8400a3bb3334ad8b096a57c0eb5a85a6e4a63496..d904bacd66bc7cbe974ee7d0e739fab09edf3481 100644 (file)
@@ -68,7 +68,7 @@ CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
 -- in the regression test (we check them using the sequoia 2000
 -- benchmark).
 --
-CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base bigbox_ops);
+CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base);
 
 -- there's no easy way to check that this command actually is using
 -- the index, unfortunately.  (EXPLAIN would work, but its output
index 5e8323bc11b0db227181159f3b60523b67a0bfe3..d822aaf4e5546267774a8e68ffeb2e0c453133ab 100644 (file)
@@ -65,6 +65,10 @@ SELECT       ctid, amopclaid
 FROM   pg_catalog.pg_amop fk 
 WHERE  amopclaid != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opclass pk WHERE pk.oid = fk.amopclaid);
+SELECT ctid, amopsubtype 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amopsubtype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amopsubtype);
 SELECT ctid, amopopr 
 FROM   pg_catalog.pg_amop fk 
 WHERE  amopopr != 0 AND 
@@ -73,6 +77,10 @@ SELECT       ctid, amopclaid
 FROM   pg_catalog.pg_amproc fk 
 WHERE  amopclaid != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opclass pk WHERE pk.oid = fk.amopclaid);
+SELECT ctid, amprocsubtype 
+FROM   pg_catalog.pg_amproc fk 
+WHERE  amprocsubtype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amprocsubtype);
 SELECT ctid, amproc 
 FROM   pg_catalog.pg_amproc fk 
 WHERE  amproc != 0 AND 
index 9cba48b4296d515f8710b9f34bb613c11edf691b..448f3ff0c5b74463029aae2648b238144464540e 100644 (file)
@@ -574,25 +574,34 @@ FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3
 WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
     p1.amopstrategy > p2.amstrategies;
 
--- Detect missing pg_amop entries: should have as many strategy functions
--- as AM expects for each opclass for the AM
+-- Detect missing pg_amop entries: should have as many strategy operators
+-- as AM expects for each opclass for the AM.  When nondefault subtypes are
+-- present, enforce condition separately for each subtype.
 
-SELECT p1.oid, p1.amname, p2.oid, p2.opcname
-FROM pg_am AS p1, pg_opclass AS p2
-WHERE p2.opcamid = p1.oid AND
-    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
-                        WHERE p3.amopclaid = p2.oid);
+SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amopsubtype
+FROM pg_am AS p1, pg_opclass AS p2, pg_amop AS p3
+WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
+    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4
+                        WHERE p4.amopclaid = p2.oid AND
+                              p4.amopsubtype = p3.amopsubtype);
 
 -- Check that amopopr points at a reasonable-looking operator, ie a binary
 -- operator yielding boolean.
--- NOTE: for 7.1, add restriction that operator inputs are of same type.
--- We used to have opclasses like "int24_ops" but these were broken.
 
 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
 FROM pg_amop AS p1, pg_operator AS p2
 WHERE p1.amopopr = p2.oid AND
-    (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype OR
-     p2.oprleft != p2.oprright);
+    (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype);
+
+-- Make a list of all the distinct operator names being used in particular
+-- strategy slots.  This is a bit hokey, since the list might need to change
+-- in future releases, but it's an effective way of spotting mistakes such as
+-- swapping two operators within a class.
+
+SELECT DISTINCT opcamid, amopstrategy, oprname
+FROM pg_amop p1 LEFT JOIN pg_opclass p2 ON amopclaid = p2.oid
+                LEFT JOIN pg_operator p3 ON amopopr = p3.oid
+ORDER BY 1, 2, 3;
 
 -- Check that all operators linked to by opclass entries have selectivity
 -- estimators.  This is not absolutely required, but it seems a reasonable
@@ -604,12 +613,26 @@ WHERE p1.amopopr = p2.oid AND
     (p2.oprrest = 0 OR p2.oprjoin = 0);
 
 -- Check that operator input types match the opclass
+-- For 7.5, we require that oprleft match opcintype (possibly by coercion).
+-- When amopsubtype is zero (default), oprright must equal oprleft;
+-- when amopsubtype is not zero, oprright must equal amopsubtype.
+
+SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
+FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
+WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
+    NOT binary_coercible(p3.opcintype, p2.oprleft);
 
 SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
 FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
-    (NOT binary_coercible(p3.opcintype, p2.oprleft) OR
-     p2.oprleft != p2.oprright);
+    p1.amopsubtype = 0 AND
+    p2.oprleft != p2.oprright;
+
+SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname
+FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
+WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
+    p1.amopsubtype != 0 AND
+    p1.amopsubtype != p2.oprright;
 
 -- **************** pg_amproc ****************
 
@@ -627,13 +650,15 @@ WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
     p1.amprocnum > p2.amsupport;
 
 -- Detect missing pg_amproc entries: should have as many support functions
--- as AM expects for each opclass for the AM
+-- as AM expects for each opclass for the AM.  When nondefault subtypes are
+-- present, enforce condition separately for each subtype.
 
-SELECT p1.oid, p1.amname, p2.oid, p2.opcname
-FROM pg_am AS p1, pg_opclass AS p2
-WHERE p2.opcamid = p1.oid AND
-    p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3
-                     WHERE p3.amopclaid = p2.oid);
+SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amprocsubtype
+FROM pg_am AS p1, pg_opclass AS p2, pg_amproc AS p3
+WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
+    p1.amsupport != (SELECT count(*) FROM pg_amproc AS p4
+                     WHERE p4.amopclaid = p2.oid AND
+                           p4.amprocsubtype = p3.amprocsubtype);
 
 -- Unfortunately, we can't check the amproc link very well because the
 -- signature of the function may be different for different support routines
@@ -656,7 +681,8 @@ WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
     (p2.proretset OR p5.proretset OR p2.pronargs != p5.pronargs);
 
 -- For btree, though, we can do better since we know the support routines
--- must be of the form cmp(input, input) returns int4.
+-- must be of the form cmp(input, input) returns int4 in the default case
+-- (subtype = 0), and cmp(input, subtype) returns int4 when subtype != 0.
 
 SELECT p1.amopclaid, p1.amprocnum,
        p2.oid, p2.proname,
@@ -664,6 +690,7 @@ SELECT p1.amopclaid, p1.amprocnum,
 FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3
 WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
     AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
+    amprocsubtype = 0 AND
     (opckeytype != 0
      OR amprocnum != 1
      OR proretset
@@ -672,6 +699,21 @@ WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
      OR NOT binary_coercible(opcintype, proargtypes[0])
      OR proargtypes[0] != proargtypes[1]);
 
+SELECT p1.amopclaid, p1.amprocnum,
+       p2.oid, p2.proname,
+       p3.opcname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3
+WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree')
+    AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
+    amprocsubtype != 0 AND
+    (opckeytype != 0
+     OR amprocnum != 1
+     OR proretset
+     OR prorettype != 23
+     OR pronargs != 2
+     OR NOT binary_coercible(opcintype, proargtypes[0])
+     OR proargtypes[1] != amprocsubtype);
+
 -- For hash we can also do a little better: the support routines must be
 -- of the form hash(something) returns int4.  Ideally we'd check that the
 -- opcintype is binary-coercible to the function's input, but there are