OSDN Git Service

Restructure operator classes to allow improved handling of cross-data-type
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 23 Dec 2006 00:43:13 +0000 (00:43 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 23 Dec 2006 00:43:13 +0000 (00:43 +0000)
cases.  Operator classes now exist within "operator families".  While most
families are equivalent to a single class, related classes can be grouped
into one family to represent the fact that they are semantically compatible.
Cross-type operators are now naturally adjunct parts of a family, without
having to wedge them into a particular opclass as we had done originally.

This commit restructures the catalogs and cleans up enough of the fallout so
that everything still works at least as well as before, but most of the work
needed to actually improve the planner's behavior will come later.  Also,
there are not yet CREATE/DROP/ALTER OPERATOR FAMILY commands; the only way
to create a new family right now is to allow CREATE OPERATOR CLASS to make
one by default.  I owe some more documentation work, too.  But that can all
be done in smaller pieces once this infrastructure is in place.

76 files changed:
contrib/intarray/_int.sql.in
contrib/intarray/uninstall__int.sql
doc/src/sgml/catalogs.sgml
doc/src/sgml/indexam.sgml
doc/src/sgml/indices.sgml
doc/src/sgml/ref/create_operator.sgml
doc/src/sgml/xoper.sgml
src/backend/access/hash/hashfunc.c
src/backend/access/index/indexam.c
src/backend/access/nbtree/nbtsearch.c
src/backend/catalog/Makefile
src/backend/catalog/dependency.c
src/backend/catalog/namespace.c
src/backend/catalog/pg_operator.c
src/backend/commands/indexcmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/operatorcmds.c
src/backend/commands/tablecmds.c
src/backend/executor/execQual.c
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeMergejoin.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/joinpath.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planagg.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/plancat.c
src/backend/optimizer/util/predtest.c
src/backend/optimizer/util/restrictinfo.c
src/backend/parser/parse_expr.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/sort/tuplesort.c
src/bin/initdb/initdb.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/dependency.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_operator.h
src/include/catalog/pg_opfamily.h [new file with mode: 0644]
src/include/commands/defrem.h
src/include/nodes/parsenodes.h
src/include/nodes/plannodes.h
src/include/nodes/primnodes.h
src/include/nodes/relation.h
src/include/optimizer/pathnode.h
src/include/utils/lsyscache.h
src/include/utils/rel.h
src/include/utils/selfuncs.h
src/include/utils/syscache.h
src/include/utils/typcache.h
src/test/regress/expected/oidjoins.out
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/rowtypes.out
src/test/regress/expected/sanity_check.out
src/test/regress/sql/oidjoins.sql
src/test/regress/sql/opr_sanity.sql
src/tools/findoidjoins/README
src/tutorial/syscat.source

index 37530a9..44efc85 100644 (file)
@@ -459,9 +459,9 @@ AS
 
 --GIN
 --mark built-in gin's _int4_ops as non default
-update pg_opclass set opcdefault = 'f' where 
-       pg_opclass.opcamid = (select pg_am.oid from pg_am where amname='gin') and
-       opcname = '_int4_ops';
+update pg_catalog.pg_opclass set opcdefault = 'f'
+where opcmethod = (select oid from pg_catalog.pg_am where amname='gin') and
+      opcname = '_int4_ops';
 
 CREATE FUNCTION ginint4_queryextract(internal, internal, int2)
 RETURNS internal
index 6f5b863..2f3b20f 100644 (file)
@@ -124,7 +124,7 @@ DROP FUNCTION querytree(query_int);
 
 DROP TYPE query_int CASCADE;
 
-update pg_opclass set opcdefault = 't' where
-    pg_opclass.opcamid = (select pg_am.oid from pg_am where amname='gin') and
-       opcname = '_int4_ops';
-
+--mark built-in gin's _int4_ops as default again
+update pg_catalog.pg_opclass set opcdefault = 't'
+where opcmethod = (select oid from pg_catalog.pg_am where amname='gin') and
+      opcname = '_int4_ops';
index ee5896b..a906623 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.138 2006/12/18 18:56:28 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.139 2006/12/23 00:43:08 tgl Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
 
      <row>
       <entry><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link></entry>
-      <entry>index access method operator classes</entry>
+      <entry>access method operator classes</entry>
      </row>
 
      <row>
      </row>
 
      <row>
+      <entry><link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link></entry>
+      <entry>access method operator families</entry>
+     </row>
+
+     <row>
       <entry><link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link></entry>
       <entry>template data for procedural languages</entry>
      </row>
   </indexterm>
 
   <para>
-   The catalog <structname>pg_amop</structname> stores information about operators
-   associated with index access method operator classes.  There is one
-   row for each operator that is a member of an operator class.
+   The catalog <structname>pg_amop</structname> stores information about
+   operators associated with access method operator families.  There is one
+   row for each operator that is a member of an operator family.  An operator
+   can appear in more than one family, but may not appear in more than one
+   position within a family.
   </para>
 
   <table>
     <tbody>
 
      <row>
-      <entry><structfield>amopclaid</structfield></entry>
+      <entry><structfield>amopfamily</structfield></entry>
       <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
-      <entry>The index operator class this entry is for</entry>
+      <entry><literal><link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link>.oid</literal></entry>
+      <entry>The operator family this entry is for</entry>
      </row>
 
      <row>
-      <entry><structfield>amopsubtype</structfield></entry>
+      <entry><structfield>amoplefttype</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>
+      <entry>Left-hand input data type of operator</entry>
+     </row>
+
+     <row>
+      <entry><structfield>amoprighttype</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
+      <entry>Right-hand input data type of operator</entry>
      </row>
 
      <row>
       <entry>OID of the operator</entry>
      </row>
 
+     <row>
+      <entry><structfield>amopmethod</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-am"><structname>pg_am</structname></link>.oid</literal></entry>
+      <entry>Index access method operator family is for</entry>
+     </row>
+
     </tbody>
    </tgroup>
   </table>
 
+  <para>
+   An entry's <structfield>amopmethod</> must match the
+   <structname>opfmethod</> of its containing operator family (including
+   <structfield>amopmethod</> here is an intentional denormalization of the
+   catalog structure for performance reasons).  Also,
+   <structfield>amoplefttype</> and <structfield>amoprighttype</> must match
+   the <structfield>oprleft</> and <structfield>oprright</> fields of the
+   referenced <structname>pg_operator</> entry.
+  </para>
+
  </sect1>
 
 
   </indexterm>
 
   <para>
-   The catalog <structname>pg_amproc</structname> stores information about support
-   procedures
-   associated with index access method operator classes.  There is one
-   row for each support procedure belonging to an operator class.
+   The catalog <structname>pg_amproc</structname> stores information about
+   support procedures associated with access method operator families.  There
+   is one row for each support procedure belonging to an operator family.
   </para>
 
   <table>
     <tbody>
 
      <row>
-      <entry><structfield>amopclaid</structfield></entry>
+      <entry><structfield>amprocfamily</structfield></entry>
       <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
-      <entry>The index operator class this entry is for</entry>
+      <entry><literal><link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link>.oid</literal></entry>
+      <entry>The operator family this entry is for</entry>
+     </row>
+
+     <row>
+      <entry><structfield>amproclefttype</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-type"><structname>pg_type</structname></link>.oid</literal></entry>
+      <entry>Left-hand input data type of associated operator</entry>
      </row>
 
      <row>
-      <entry><structfield>amprocsubtype</structfield></entry>
+      <entry><structfield>amprocrighttype</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>
+      <entry>Right-hand input data type of associated operator</entry>
      </row>
 
      <row>
    </tgroup>
   </table>
 
+  <para>
+   The usual interpretation of the
+   <structfield>amproclefttype</> and <structfield>amprocrighttype</> fields
+   is that they identify the left and right input types of the operator(s)
+   that a particular support procedure supports.  For some access methods
+   these match the input data type(s) of the support procedure itself, for
+   others not.  There is a notion of <quote>default</> support procedures for
+   an index, which are those with <structfield>amproclefttype</> and
+   <structfield>amprocrighttype</> both equal to the index opclass's
+   <structfield>opcintype</>.
+  </para>
+
  </sect1>
 
 
    The catalog <structname>pg_opclass</structname> defines
    index access method operator classes.  Each operator class defines
    semantics for index columns of a particular data type and a particular
-   index access method.  Note that there can be multiple operator classes
-   for a given data type/access method combination, thus supporting multiple
-   behaviors.
+   index access method.  An operator class essentially specifies that a
+   particular operator family is applicable to a particular indexable column
+   data type.  The set of operators from the family that are actually usable
+   with the indexed column are whichever ones accept the column's data type
+   as their lefthand input.
   </para>
 
   <para>
     <tbody>
 
      <row>
-      <entry><structfield>opcamid</structfield></entry>
+      <entry><structfield>opcmethod</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-am"><structname>pg_am</structname></link>.oid</literal></entry>
       <entry>Index access method operator class is for</entry>
      </row>
 
      <row>
+      <entry><structfield>opcfamily</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link>.oid</literal></entry>
+      <entry>Operator family containing the operator class</entry>
+     </row>
+
+     <row>
       <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>
   </table>
 
   <para>
-   The majority of the information defining an operator class is actually
-   not in its <structname>pg_opclass</structname> row, but in the associated
-   rows in <structname>pg_amop</structname> and
-   <structname>pg_amproc</structname>.  Those rows are considered to be
-   part of the operator class definition &mdash; this is not unlike the way
-   that a relation is defined by a single <structname>pg_class</structname>
-   row plus associated rows in <structname>pg_attribute</structname> and
-   other tables.
+   An operator class's <structfield>opcmethod</> must match the
+   <structname>opfmethod</> of its containing operator family.
+   Also, there must be no more than one <structname>pg_opclass</structname>
+   row having <structname>opcdefault</> true for any given combination of
+   <structname>opcmethod</> and <structname>opcintype</>.
   </para>
 
  </sect1>
      </row>
 
      <row>
+      <entry><structfield>oprcanmerge</structfield></entry>
+      <entry><type>bool</type></entry>
+      <entry></entry>
+      <entry>This operator supports merge joins</entry>
+     </row>
+
+     <row>
       <entry><structfield>oprcanhash</structfield></entry>
       <entry><type>bool</type></entry>
       <entry></entry>
      </row>
 
      <row>
-      <entry><structfield>oprlsortop</structfield></entry>
-      <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry>
-      <entry>
-       If this operator supports merge joins, the operator that sorts
-       the type of the left-hand operand (<literal>L&lt;L</>)
-      </entry>
-     </row>
-
-     <row>
-      <entry><structfield>oprrsortop</structfield></entry>
-      <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry>
-      <entry>
-       If this operator supports merge joins, the operator that sorts
-       the type of the right-hand operand (<literal>R&lt;R</>)
-      </entry>
-     </row>
-
-     <row>
-      <entry><structfield>oprltcmpop</structfield></entry>
-      <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry>
-      <entry>
-       If this operator supports merge joins, the less-than operator that
-       compares the left and right operand types (<literal>L&lt;R</>)
-      </entry>
-     </row>
-
-     <row>
-      <entry><structfield>oprgtcmpop</structfield></entry>
-      <entry><type>oid</type></entry>
-      <entry><literal><link linkend="catalog-pg-operator"><structname>pg_operator</structname></link>.oid</literal></entry>
-      <entry>
-       If this operator supports merge joins, the greater-than operator that
-       compares the left and right operand types (<literal>L&gt;R</>)
-      </entry>
-     </row>
-
-     <row>
       <entry><structfield>oprcode</structfield></entry>
       <entry><type>regproc</type></entry>
       <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
  </sect1>
 
 
+ <sect1 id="catalog-pg-opfamily">
+  <title><structname>pg_opfamily</structname></title>
+
+  <indexterm zone="catalog-pg-opfamily">
+   <primary>pg_opfamily</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_opfamily</structname> defines operator families.
+   Each operator family is a collection of operators and associated
+   support routines that implement the semantics specified for a particular
+   index access method.  Furthermore, the operators in a family are all
+   <quote>compatible</>, in a way that depends on the access method.
+   The operator family concept allows cross-data-type operators to be used
+   with indexes and to be reasoned about using knowledge of access method
+   semantics.
+  </para>
+
+  <para>
+   Operator families are described at length in <xref linkend="xindex">.
+  </para>
+
+  <table>
+   <title><structname>pg_opfamily</> Columns</title>
+
+   <tgroup cols=4>
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+    <tbody>
+
+     <row>
+      <entry><structfield>opfmethod</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-am"><structname>pg_am</structname></link>.oid</literal></entry>
+      <entry>Index access method operator family is for</entry>
+     </row>
+
+     <row>
+      <entry><structfield>opfname</structfield></entry>
+      <entry><type>name</type></entry>
+      <entry></entry>
+      <entry>Name of this operator family</entry>
+     </row>
+
+     <row>
+      <entry><structfield>opfnamespace</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link>.oid</literal></entry>
+      <entry>Namespace of this operator family</entry>
+     </row>
+
+     <row>
+      <entry><structfield>opfowner</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
+      <entry>Owner of the operator family</entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+  <para>
+   The majority of the information defining an operator family is not in its
+   <structname>pg_opfamily</structname> row, but in the associated rows in
+   <link linkend="catalog-pg-amop"><structname>pg_amop</structname></link>,
+   <link linkend="catalog-pg-amproc"><structname>pg_amproc</structname></link>,
+   and
+   <link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.
+  </para>
+
+ </sect1>
+
+
  <sect1 id="catalog-pg-pltemplate">
   <title><structname>pg_pltemplate</structname></title>
 
index 44dac11..658cdd7 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.18 2006/09/16 00:30:14 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.19 2006/12/23 00:43:08 tgl Exp $ -->
 
 <chapter id="indexam">
  <title>Index Access Method Interface Definition</title>
 
   <para>
    To be useful, an index access method must also have one or more
+   <firstterm>operator families</> and
    <firstterm>operator classes</> defined in
+   <link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link>,
    <link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>,
    <link linkend="catalog-pg-amop"><structname>pg_amop</structname></link>, and
    <link linkend="catalog-pg-amproc"><structname>pg_amproc</structname></link>.
    These entries allow the planner
    to determine what kinds of query qualifications can be used with
-   indexes of this access method.  Operator classes are described
+   indexes of this access method.  Operator families and classes are described
    in <xref linkend="xindex">, which is prerequisite material for reading
    this chapter.
   </para>
@@ -409,14 +411,14 @@ amrestrpos (IndexScanDesc scan);
    A scan key is the internal representation of a <literal>WHERE</> clause of
    the form <replaceable>index_key</> <replaceable>operator</>
    <replaceable>constant</>, where the index key is one of the columns of the
-   index and the operator is one of the members of the operator class
+   index and the operator is one of the members of the operator family
    associated with that index column.  An index scan has zero or more scan
    keys, which are implicitly ANDed &mdash; the returned tuples are expected
    to satisfy all the indicated conditions.
   </para>
 
   <para>
-   The operator class may indicate that the index is <firstterm>lossy</> for a
+   The operator family may indicate that the index is <firstterm>lossy</> for a
    particular operator; this implies that the index scan will return all the
    entries that pass the scan key, plus possibly additional entries that do
    not.  The core system's index-scan machinery will then apply that operator
@@ -429,7 +431,7 @@ amrestrpos (IndexScanDesc scan);
    Note that it is entirely up to the access method to ensure that it
    correctly finds all and only the entries passing all the given scan keys.
    Also, the core system will simply hand off all the <literal>WHERE</>
-   clauses that match the index keys and operator classes, without any
+   clauses that match the index keys and operator families, without any
    semantic analysis to determine whether they are redundant or
    contradictory.  As an example, given
    <literal>WHERE x &gt; 4 AND x &gt; 14</> where <literal>x</> is a b-tree
index 1edceeb..6ff9c4d 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.66 2006/12/01 23:46:46 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.67 2006/12/23 00:43:08 tgl Exp $ -->
 
 <chapter id="indexes">
  <title id="indexes-title">Indexes</title>
@@ -784,12 +784,16 @@ CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
 
 
  <sect1 id="indexes-opclass">
-  <title>Operator Classes</title>
+  <title>Operator Classes and Operator Families</title>
 
   <indexterm zone="indexes-opclass">
    <primary>operator class</primary>
   </indexterm>
 
+  <indexterm zone="indexes-opclass">
+   <primary>operator family</primary>
+  </indexterm>
+
   <para>
    An index definition may specify an <firstterm>operator
    class</firstterm> for each column of an index.
@@ -854,20 +858,32 @@ CREATE INDEX test_index ON test_table (col varchar_pattern_ops);
 SELECT am.amname AS index_method,
        opc.opcname AS opclass_name
     FROM pg_am am, pg_opclass opc
-    WHERE opc.opcamid = am.oid
+    WHERE opc.opcmethod = am.oid
     ORDER BY index_method, opclass_name;
 </programlisting>
+  </para>
 
-    It can be extended to show all the operators included in each class:
+  <para>
+   An operator class is actually just a subset of a larger structure called an
+   <firstterm>operator family</>.  In cases where several data types have
+   similar behaviors, it is frequently useful to define cross-data-type
+   operators and allow these to work with indexes.  To do this, the operator
+   classes for each of the types must be grouped into the same operator
+   family.  The cross-type operators are members of the family, but are not
+   associated with any single class within the family.
+  </para>
+
+  <para>
+    This query shows all defined operator families and all
+    the operators included in each family:
 <programlisting>
 SELECT am.amname AS index_method,
-       opc.opcname AS opclass_name,
-       opr.oid::regoperator AS opclass_operator
-    FROM pg_am am, pg_opclass opc, pg_amop amop, pg_operator opr
-    WHERE opc.opcamid = am.oid AND
-          amop.amopclaid = opc.oid AND
-          amop.amopopr = opr.oid
-    ORDER BY index_method, opclass_name, opclass_operator;
+       opf.opfname AS opfamily_name,
+       amop.amopopr::regoperator AS opfamily_operator
+    FROM pg_am am, pg_opfamily opf, pg_amop amop
+    WHERE opf.opfmethod = am.oid AND
+          amop.amopfamily = opf.oid
+    ORDER BY index_method, opfamily_name, opfamily_operator;
 </programlisting>
   </para>
  </sect1>
index 023a9e7..955d9db 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.45 2006/09/16 00:30:17 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.46 2006/12/23 00:43:08 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -26,8 +26,6 @@ CREATE OPERATOR <replaceable>name</replaceable> (
     [, COMMUTATOR = <replaceable class="parameter">com_op</replaceable> ] [, NEGATOR = <replaceable class="parameter">neg_op</replaceable> ]
     [, RESTRICT = <replaceable class="parameter">res_proc</replaceable> ] [, JOIN = <replaceable class="parameter">join_proc</replaceable> ]
     [, HASHES ] [, MERGES ]
-    [, SORT1 = <replaceable class="parameter">left_sort_op</replaceable> ] [, SORT2 = <replaceable class="parameter">right_sort_op</replaceable> ]
-    [, LTCMP = <replaceable class="parameter">less_than_op</replaceable> ] [, GTCMP = <replaceable class="parameter">greater_than_op</replaceable> ]
 )
 </synopsis>
  </refsynopsisdiv>
@@ -202,46 +200,6 @@ CREATE OPERATOR <replaceable>name</replaceable> (
        </para>
       </listitem>
      </varlistentry>
-
-     <varlistentry>
-      <term><replaceable class="parameter">left_sort_op</replaceable></term>
-      <listitem>
-       <para>
-        If this operator can support a merge join, the less-than
-        operator that sorts the left-hand data type of this operator.
-       </para>
-      </listitem>
-     </varlistentry>
-
-     <varlistentry>
-      <term><replaceable class="parameter">right_sort_op</replaceable></term>
-      <listitem>
-       <para>
-        If this operator can support a merge join, the less-than
-        operator that sorts the right-hand data type of this operator.
-       </para>
-      </listitem>
-     </varlistentry>
-
-     <varlistentry>
-      <term><replaceable class="parameter">less_than_op</replaceable></term>
-      <listitem>
-       <para>
-        If this operator can support a merge join, the less-than
-        operator that compares the input data types of this operator.
-       </para>
-      </listitem>
-     </varlistentry>
-
-     <varlistentry>
-      <term><replaceable class="parameter">greater_than_op</replaceable></term>
-      <listitem>
-       <para>
-        If this operator can support a merge join, the greater-than
-        operator that compares the input data types of this operator.
-       </para>
-      </listitem>
-     </varlistentry>
     </variablelist>
 
   <para>
@@ -262,6 +220,16 @@ COMMUTATOR = OPERATOR(myschema.===) ,
   </para>
 
   <para>
+   The obsolete options <literal>SORT1</>, <literal>SORT2</>,
+   <literal>LTCMP</>, and <literal>GTCMP</> were formerly used to
+   specify the names of sort operators associated with a mergejoinable
+   operator.  This is no longer necessary, since information about
+   associated operators is found by looking at btree operator families
+   instead.  If one of these options is given, it is ignored except
+   for implicitly setting <literal>MERGES</> true.
+  </para>
+
+  <para>
    Use <xref linkend="sql-dropoperator"
    endterm="sql-dropoperator-title"> to delete user-defined operators
    from a database.  Use <xref linkend="sql-alteroperator"
@@ -285,11 +253,7 @@ CREATE OPERATOR === (
     NEGATOR = !==,
     RESTRICT = area_restriction_procedure,
     JOIN = area_join_procedure,
-    HASHES,
-    SORT1 = &lt;&lt;&lt;,
-    SORT2 = &lt;&lt;&lt;
-    -- Since sort operators were given, MERGES is implied.
-    -- LTCMP and GTCMP are assumed to be &lt; and &gt; respectively
+    HASHES, MERGES
 );
 </programlisting>  
   </para>
index 8a98018..5f84393 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/xoper.sgml,v 1.36 2006/09/16 00:30:16 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/xoper.sgml,v 1.37 2006/12/23 00:43:08 tgl Exp $ -->
 
  <sect1 id="xoper">
   <title>User-Defined Operators</title>
@@ -342,13 +342,13 @@ table1.column1 OP table2.column2
 
     <para>
      To be marked <literal>HASHES</literal>, the join operator must appear
-     in a hash index operator class.  This is not enforced when you create
-     the operator, since of course the referencing operator class couldn't
+     in a hash index operator family.  This is not enforced when you create
+     the operator, since of course the referencing operator family couldn't
      exist yet.  But attempts to use the operator in hash joins will fail
-     at run time if no such operator class exists.  The system needs the
-     operator class to find the data-type-specific hash function for the
+     at run time if no such operator family exists.  The system needs the
+     operator family to find the data-type-specific hash function for the
      operator's input data type.  Of course, you must also supply a suitable
-     hash function before you can create the operator class.
+     hash function before you can create the operator family.
     </para>
 
     <para>
@@ -390,7 +390,7 @@ table1.column1 OP table2.column2
    </sect2>
 
    <sect2>
-    <title><literal>MERGES</> (<literal>SORT1</>, <literal>SORT2</>, <literal>LTCMP</>, <literal>GTCMP</>)</title>
+    <title><literal>MERGES</></title>
 
     <para>
      The <literal>MERGES</literal> clause, if present, tells the system that
@@ -418,36 +418,13 @@ table1.column1 OP table2.column2
     </para>
 
     <para>
-     Execution of a merge join requires that the system be able to identify
-     four operators related to the merge-join equality operator: less-than
-     comparison for the left operand data type, less-than comparison for the
-     right operand data type, less-than comparison between the two data types, and
-     greater-than comparison between the two data types.  (These are actually
-     four distinct operators if the merge-joinable operator has two different
-     operand data types; but when the operand types are the same the three
-     less-than operators are all the same operator.)
-     It is possible to
-     specify these operators individually by name, as the <literal>SORT1</>,
-     <literal>SORT2</>, <literal>LTCMP</>, and <literal>GTCMP</> options
-     respectively.  The system will fill in the default names
-     <literal>&lt;</>, <literal>&lt;</>, <literal>&lt;</>, <literal>&gt;</>
-     respectively if any of these are omitted when <literal>MERGES</> is
-     specified.  Also, <literal>MERGES</> will be assumed to be implied if any
-     of these four operator options appear, so it is possible to specify
-     just some of them and let the system fill in the rest.
-    </para>
-
-    <para>
-     The operand data types of the four comparison operators can be deduced
-     from the operand types of the merge-joinable operator, so just as with
-     <literal>COMMUTATOR</>, only the operator names need be given in these
-     clauses.  Unless you are using peculiar choices of operator names,
-     it's sufficient to write <literal>MERGES</> and let the system fill in
-     the details.
-     (As with <literal>COMMUTATOR</> and <literal>NEGATOR</>, the system is
-     able to make dummy
-     operator entries if you happen to define the equality operator before
-     the other ones.)
+     To be marked <literal>MERGES</literal>, the join operator must appear
+     in a btree index operator family.  This is not enforced when you create
+     the operator, since of course the referencing operator family couldn't
+     exist yet.  But the operator will not actually be used for merge joins
+     unless a matching operator family can be found.  The
+     <literal>MERGES</literal> flag thus acts as a hint to the planner that
+     it's worth looking for a matching operator family.
     </para>
 
     <para>
@@ -474,13 +451,6 @@ table1.column1 OP table2.column2
        be transitive.
        </para>
       </listitem>
-
-      <listitem>
-       <para>
-        Bizarre results will ensue at run time if the four comparison
-       operators you name do not sort the data values compatibly.
-       </para>
-      </listitem>
      </itemizedlist>
     </para>
 
@@ -491,17 +461,5 @@ table1.column1 OP table2.column2
      attempt to use the operator for a merge join.
     </para>
     </note>
-
-    <note>
-    <para>
-     In <productname>PostgreSQL</productname> versions before 7.3,
-     the <literal>MERGES</> shorthand was not available: to make a
-     merge-joinable operator one had to write both <literal>SORT1</> and
-     <literal>SORT2</> explicitly.  Also, the <literal>LTCMP</> and
-     <literal>GTCMP</>
-     options did not exist; the names of those operators were hardwired as
-     <literal>&lt;</> and <literal>&gt;</> respectively.
-    </para>
-    </note>
    </sect2>
   </sect1>
index 1e2d779..f6b39ba 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.48 2006/10/04 00:29:48 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.49 2006/12/23 00:43:08 tgl Exp $
  *
  * NOTES
  *       These functions are stored in pg_amproc.      For each operator class
@@ -46,11 +46,11 @@ hashint8(PG_FUNCTION_ARGS)
 {
        /*
         * The idea here is to produce a hash value compatible with the values
-        * produced by hashint4 and hashint2 for logically equivalent inputs; this
-        * is necessary if we ever hope to support cross-type hash joins across
-        * these input types.  Since all three types are signed, we can xor the
-        * high half of the int8 value if the sign is positive, or the complement
-        * of the high half when the sign is negative.
+        * produced by hashint4 and hashint2 for logically equal inputs; this is
+        * necessary to support cross-type hash joins across these input types.
+        * Since all three types are signed, we can xor the high half of the int8
+        * value if the sign is positive, or the complement of the high half when
+        * the sign is negative.
         */
 #ifndef INT64_IS_BUSTED
        int64           val = PG_GETARG_INT64(0);
@@ -76,16 +76,26 @@ Datum
 hashfloat4(PG_FUNCTION_ARGS)
 {
        float4          key = PG_GETARG_FLOAT4(0);
+       float8          key8;
 
        /*
         * On IEEE-float machines, minus zero and zero have different bit patterns
         * but should compare as equal.  We must ensure that they have the same
-        * hash value, which is most easily done this way:
+        * hash value, which is most reliably done this way:
         */
        if (key == (float4) 0)
                PG_RETURN_UINT32(0);
 
-       return hash_any((unsigned char *) &key, sizeof(key));
+       /*
+        * To support cross-type hashing of float8 and float4, we want to return
+        * the same hash value hashfloat8 would produce for an equal float8 value.
+        * So, widen the value to float8 and hash that.  (We must do this rather
+        * than have hashfloat8 try to narrow its value to float4; that could
+        * fail on overflow.)
+        */
+       key8 = key;
+
+       return hash_any((unsigned char *) &key8, sizeof(key8));
 }
 
 Datum
@@ -96,7 +106,7 @@ hashfloat8(PG_FUNCTION_ARGS)
        /*
         * On IEEE-float machines, minus zero and zero have different bit patterns
         * but should compare as equal.  We must ensure that they have the same
-        * hash value, which is most easily done this way:
+        * hash value, which is most reliably done this way:
         */
        if (key == (float8) 0)
                PG_RETURN_UINT32(0);
index 493e9f0..6d60f46 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.95 2006/10/04 00:29:48 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.96 2006/12/23 00:43:08 tgl Exp $
  *
  * INTERFACE ROUTINES
  *             index_open              - open an index relation by relation OID
@@ -608,17 +608,27 @@ index_vacuum_cleanup(IndexVacuumInfo *info,
 /* ----------------
  *             index_getprocid
  *
- *             Some indexed access methods may require support routines that are
- *             not in the operator class/operator model imposed by pg_am.      These
- *             access methods may store the OIDs of registered procedures they
- *             need in pg_amproc.      These registered procedure OIDs are ordered in
- *             a way that makes sense to the access method, and used only by the
- *             access method.  The general index code doesn't know anything about
- *             the routines involved; it just builds an ordered list of them for
+ *             Index access methods typically require support routines that are
+ *             not directly the implementation of any WHERE-clause query operator
+ *             and so cannot be kept in pg_amop.  Instead, such routines are kept
+ *             in pg_amproc.  These registered procedure OIDs are assigned numbers
+ *             according to a convention established by the access method.
+ *             The general index code doesn't know anything about the routines
+ *             involved; it just builds an ordered list of them for
  *             each attribute on which an index is defined.
  *
- *             This routine returns the requested procedure OID for a particular
- *             indexed attribute.
+ *             As of Postgres 8.3, support routines within an operator family
+ *             are further subdivided by the "left type" and "right type" of the
+ *             query operator(s) that they support.  The "default" functions for a
+ *             particular indexed attribute are those with both types equal to
+ *             the index opclass' opcintype (note that this is subtly different
+ *             from the indexed attribute's own type: it may be a binary-compatible
+ *             type instead).  Only the default functions are stored in relcache
+ *             entries --- access methods can use the syscache to look up non-default
+ *             functions.
+ *
+ *             This routine returns the requested default procedure OID for a
+ *             particular indexed attribute.
  * ----------------
  */
 RegProcedure
@@ -647,7 +657,8 @@ index_getprocid(Relation irel,
  *             index_getprocinfo
  *
  *             This routine allows index AMs to keep fmgr lookup info for
- *             support procs in the relcache.
+ *             support procs in the relcache.  As above, only the "default"
+ *             functions for any particular indexed attribute are cached.
  *
  * Note: the return value points into cached data that will be lost during
  * any relcache rebuild!  Therefore, either use the callinfo right away,
index 6d9be1b..284b92e 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.107 2006/10/04 00:29:49 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.108 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -658,11 +658,14 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                         * to an insertion scan key by replacing the sk_func with the
                         * appropriate btree comparison function.
                         *
-                        * If scankey operator is of default subtype, we can use the
-                        * cached comparison function; otherwise gotta look it up in the
-                        * catalogs.
+                        * If scankey operator is of the default type for the index, we
+                        * can use the cached comparison function; otherwise gotta look it
+                        * up in the catalogs.  Also, we support the convention that
+                        * sk_subtype == 0 means the default type; this is a hack to
+                        * simplify life for ScanKeyInit().
                         */
-                       if (cur->sk_subtype == InvalidOid)
+                       if (cur->sk_subtype == rel->rd_opcintype[i] ||
+                               cur->sk_subtype == InvalidOid)
                        {
                                FmgrInfo   *procinfo;
 
@@ -671,7 +674,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                                                                                           cur->sk_flags,
                                                                                           cur->sk_attno,
                                                                                           InvalidStrategy,
-                                                                                          InvalidOid,
+                                                                                          cur->sk_subtype,
                                                                                           procinfo,
                                                                                           cur->sk_argument);
                        }
@@ -679,9 +682,14 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
                        {
                                RegProcedure cmp_proc;
 
-                               cmp_proc = get_opclass_proc(rel->rd_indclass->values[i],
-                                                                                       cur->sk_subtype,
-                                                                                       BTORDER_PROC);
+                               cmp_proc = get_opfamily_proc(rel->rd_opfamily[i],
+                                                                                        rel->rd_opcintype[i],
+                                                                                        cur->sk_subtype,
+                                                                                        BTORDER_PROC);
+                               if (!RegProcedureIsValid(cmp_proc))
+                                       elog(ERROR, "missing support function %d(%u,%u) for attribute %d of index \"%s\"",
+                                                BTORDER_PROC, rel->rd_opcintype[i], cur->sk_subtype,
+                                                cur->sk_attno, RelationGetRelationName(rel));
                                ScanKeyEntryInitialize(scankeys + i,
                                                                           cur->sk_flags,
                                                                           cur->sk_attno,
index 2e2d885..1106194 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.60 2006/07/31 01:16:36 tgl Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.61 2006/12/23 00:43:09 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -28,8 +28,8 @@ SUBSYS.o: $(OBJS)
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
        pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_autovacuum.h \
-       pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \
-       pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
+       pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h pg_operator.h \
+       pg_opfamily.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
        pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
        pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
        pg_namespace.h pg_conversion.h pg_depend.h \
index cab4f10..770b189 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.60 2006/10/04 00:29:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.61 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,8 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_amop.h"
+#include "catalog/pg_amproc.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_cast.h"
@@ -33,6 +35,7 @@
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_tablespace.h"
@@ -78,19 +81,25 @@ typedef struct
  * See also getObjectClass().
  */
 static const Oid object_classes[MAX_OCLASS] = {
-       RelationRelationId,                     /* OCLASS_CLASS */
-       ProcedureRelationId,            /* OCLASS_PROC */
-       TypeRelationId,                         /* OCLASS_TYPE */
-       CastRelationId,                         /* OCLASS_CAST */
-       ConstraintRelationId,           /* OCLASS_CONSTRAINT */
-       ConversionRelationId,           /* OCLASS_CONVERSION */
-       AttrDefaultRelationId,          /* OCLASS_DEFAULT */
-       LanguageRelationId,                     /* OCLASS_LANGUAGE */
-       OperatorRelationId,                     /* OCLASS_OPERATOR */
-       OperatorClassRelationId,        /* OCLASS_OPCLASS */
-       RewriteRelationId,                      /* OCLASS_REWRITE */
-       TriggerRelationId,                      /* OCLASS_TRIGGER */
-       NamespaceRelationId                     /* OCLASS_SCHEMA */
+       RelationRelationId,                                     /* OCLASS_CLASS */
+       ProcedureRelationId,                            /* OCLASS_PROC */
+       TypeRelationId,                                         /* OCLASS_TYPE */
+       CastRelationId,                                         /* OCLASS_CAST */
+       ConstraintRelationId,                           /* OCLASS_CONSTRAINT */
+       ConversionRelationId,                           /* OCLASS_CONVERSION */
+       AttrDefaultRelationId,                          /* OCLASS_DEFAULT */
+       LanguageRelationId,                                     /* OCLASS_LANGUAGE */
+       OperatorRelationId,                                     /* OCLASS_OPERATOR */
+       OperatorClassRelationId,                        /* OCLASS_OPCLASS */
+       OperatorFamilyRelationId,                       /* OCLASS_OPFAMILY */
+       AccessMethodOperatorRelationId,         /* OCLASS_AMOP */
+       AccessMethodProcedureRelationId,        /* OCLASS_AMPROC */
+       RewriteRelationId,                                      /* OCLASS_REWRITE */
+       TriggerRelationId,                                      /* OCLASS_TRIGGER */
+       NamespaceRelationId,                            /* OCLASS_SCHEMA */
+       AuthIdRelationId,                                       /* OCLASS_ROLE */
+       DatabaseRelationId,                                     /* OCLASS_DATABASE */
+       TableSpaceRelationId                            /* OCLASS_TBLSPACE */
 };
 
 
@@ -122,6 +131,7 @@ static int  object_address_comparator(const void *a, const void *b);
 static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
                                   ObjectAddresses *addrs);
 static void getRelationDescription(StringInfo buffer, Oid relid);
+static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
 
 
 /*
@@ -185,7 +195,7 @@ performDeletion(const ObjectAddress *object,
  * filled with some objects.  Also, the deleted objects are saved in the
  * alreadyDeleted list.
  *
- * XXX performDeletion could be refactored to be a thin wrapper to this
+ * XXX performDeletion could be refactored to be a thin wrapper around this
  * function.
  */
 static void
@@ -954,6 +964,18 @@ doDeletion(const ObjectAddress *object)
                        RemoveOpClassById(object->objectId);
                        break;
 
+               case OCLASS_OPFAMILY:
+                       RemoveOpFamilyById(object->objectId);
+                       break;
+
+               case OCLASS_AMOP:
+                       RemoveAmOpEntryById(object->objectId);
+                       break;
+
+               case OCLASS_AMPROC:
+                       RemoveAmProcEntryById(object->objectId);
+                       break;
+
                case OCLASS_REWRITE:
                        RemoveRewriteRuleById(object->objectId);
                        break;
@@ -966,6 +988,8 @@ doDeletion(const ObjectAddress *object)
                        RemoveSchemaById(object->objectId);
                        break;
 
+               /* OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE not handled */
+
                default:
                        elog(ERROR, "unrecognized object class: %u",
                                 object->classId);
@@ -1316,9 +1340,9 @@ find_expr_references_walker(Node *node,
                        add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
                                                           context->addrs);
                }
-               foreach(l, rcexpr->opclasses)
+               foreach(l, rcexpr->opfamilies)
                {
-                       add_object_address(OCLASS_OPCLASS, lfirst_oid(l), 0,
+                       add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
                                                           context->addrs);
                }
                /* fall through to examine arguments */
@@ -1623,6 +1647,18 @@ getObjectClass(const ObjectAddress *object)
                        Assert(object->objectSubId == 0);
                        return OCLASS_OPCLASS;
 
+               case OperatorFamilyRelationId:
+                       Assert(object->objectSubId == 0);
+                       return OCLASS_OPFAMILY;
+
+               case AccessMethodOperatorRelationId:
+                       Assert(object->objectSubId == 0);
+                       return OCLASS_AMOP;
+
+               case AccessMethodProcedureRelationId:
+                       Assert(object->objectSubId == 0);
+                       return OCLASS_AMPROC;
+
                case RewriteRelationId:
                        Assert(object->objectSubId == 0);
                        return OCLASS_REWRITE;
@@ -1856,11 +1892,11 @@ getObjectDescription(const ObjectAddress *object)
                                opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
 
                                amTup = SearchSysCache(AMOID,
-                                                                          ObjectIdGetDatum(opcForm->opcamid),
+                                                                          ObjectIdGetDatum(opcForm->opcmethod),
                                                                           0, 0, 0);
                                if (!HeapTupleIsValid(amTup))
                                        elog(ERROR, "cache lookup failed for access method %u",
-                                                opcForm->opcamid);
+                                                opcForm->opcmethod);
                                amForm = (Form_pg_am) GETSTRUCT(amTup);
 
                                /* Qualify the name if not visible in search path */
@@ -1879,6 +1915,84 @@ getObjectDescription(const ObjectAddress *object)
                                break;
                        }
 
+               case OCLASS_OPFAMILY:
+                       getOpFamilyDescription(&buffer, object->objectId);
+                       break;
+
+               case OCLASS_AMOP:
+                       {
+                               Relation        amopDesc;
+                               ScanKeyData skey[1];
+                               SysScanDesc amscan;
+                               HeapTuple       tup;
+                               Form_pg_amop amopForm;
+
+                               amopDesc = heap_open(AccessMethodOperatorRelationId,
+                                                                        AccessShareLock);
+
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
+
+                               amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
+                                                                                       SnapshotNow, 1, skey);
+
+                               tup = systable_getnext(amscan);
+
+                               if (!HeapTupleIsValid(tup))
+                                       elog(ERROR, "could not find tuple for amop entry %u",
+                                                object->objectId);
+
+                               amopForm = (Form_pg_amop) GETSTRUCT(tup);
+
+                               appendStringInfo(&buffer, _("operator %d %s of "),
+                                                                amopForm->amopstrategy,
+                                                                format_operator(amopForm->amopopr));
+                               getOpFamilyDescription(&buffer, amopForm->amopfamily);
+
+                               systable_endscan(amscan);
+                               heap_close(amopDesc, AccessShareLock);
+                               break;
+                       }
+
+               case OCLASS_AMPROC:
+                       {
+                               Relation        amprocDesc;
+                               ScanKeyData skey[1];
+                               SysScanDesc amscan;
+                               HeapTuple       tup;
+                               Form_pg_amproc amprocForm;
+
+                               amprocDesc = heap_open(AccessMethodProcedureRelationId,
+                                                                          AccessShareLock);
+
+                               ScanKeyInit(&skey[0],
+                                                       ObjectIdAttributeNumber,
+                                                       BTEqualStrategyNumber, F_OIDEQ,
+                                                       ObjectIdGetDatum(object->objectId));
+
+                               amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
+                                                                                       SnapshotNow, 1, skey);
+
+                               tup = systable_getnext(amscan);
+
+                               if (!HeapTupleIsValid(tup))
+                                       elog(ERROR, "could not find tuple for amproc entry %u",
+                                                object->objectId);
+
+                               amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
+
+                               appendStringInfo(&buffer, _("function %d %s of "),
+                                                                amprocForm->amprocnum,
+                                                                format_procedure(amprocForm->amproc));
+                               getOpFamilyDescription(&buffer, amprocForm->amprocfamily);
+
+                               systable_endscan(amscan);
+                               heap_close(amprocDesc, AccessShareLock);
+                               break;
+                       }
+
                case OCLASS_REWRITE:
                        {
                                Relation        ruleDesc;
@@ -2068,3 +2182,45 @@ getRelationDescription(StringInfo buffer, Oid relid)
 
        ReleaseSysCache(relTup);
 }
+
+/*
+ * subroutine for getObjectDescription: describe an operator family
+ */
+static void
+getOpFamilyDescription(StringInfo buffer, Oid opfid)
+{
+       HeapTuple       opfTup;
+       Form_pg_opfamily opfForm;
+       HeapTuple       amTup;
+       Form_pg_am      amForm;
+       char       *nspname;
+
+       opfTup = SearchSysCache(OPFAMILYOID,
+                                                       ObjectIdGetDatum(opfid),
+                                                       0, 0, 0);
+       if (!HeapTupleIsValid(opfTup))
+               elog(ERROR, "cache lookup failed for opfamily %u", opfid);
+       opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+       amTup = SearchSysCache(AMOID,
+                                                  ObjectIdGetDatum(opfForm->opfmethod),
+                                                  0, 0, 0);
+       if (!HeapTupleIsValid(amTup))
+               elog(ERROR, "cache lookup failed for access method %u",
+                        opfForm->opfmethod);
+       amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+       /* Qualify the name if not visible in search path */
+       if (OpfamilyIsVisible(opfid))
+               nspname = NULL;
+       else
+               nspname = get_namespace_name(opfForm->opfnamespace);
+
+       appendStringInfo(buffer, _("operator family %s for access method %s"),
+                                        quote_qualified_identifier(nspname,
+                                                                                               NameStr(opfForm->opfname)),
+                                        NameStr(amForm->amname));
+
+       ReleaseSysCache(amTup);
+       ReleaseSysCache(opfTup);
+}
index 1d6162c..5c661a0 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.88 2006/10/04 00:29:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.89 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/dbcommands.h"
@@ -1062,7 +1063,7 @@ OpclassIsVisible(Oid opcid)
                 */
                char       *opcname = NameStr(opcform->opcname);
 
-               visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
+               visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
        }
 
        ReleaseSysCache(opctup);
@@ -1071,6 +1072,89 @@ OpclassIsVisible(Oid opcid)
 }
 
 /*
+ * OpfamilynameGetOpfid
+ *             Try to resolve an unqualified index opfamily name.
+ *             Returns OID if opfamily found in search path, else InvalidOid.
+ *
+ * This is essentially the same as TypenameGetTypid, but we have to have
+ * an extra argument for the index AM OID.
+ */
+Oid
+OpfamilynameGetOpfid(Oid amid, const char *opfname)
+{
+       Oid                     opfid;
+       ListCell   *l;
+
+       recomputeNamespacePath();
+
+       foreach(l, namespaceSearchPath)
+       {
+               Oid                     namespaceId = lfirst_oid(l);
+
+               opfid = GetSysCacheOid(OPFAMILYAMNAMENSP,
+                                                          ObjectIdGetDatum(amid),
+                                                          PointerGetDatum(opfname),
+                                                          ObjectIdGetDatum(namespaceId),
+                                                          0);
+               if (OidIsValid(opfid))
+                       return opfid;
+       }
+
+       /* Not found in path */
+       return InvalidOid;
+}
+
+/*
+ * OpfamilyIsVisible
+ *             Determine whether an opfamily (identified by OID) is visible in the
+ *             current search path.  Visible means "would be found by searching
+ *             for the unqualified opfamily name".
+ */
+bool
+OpfamilyIsVisible(Oid opfid)
+{
+       HeapTuple       opftup;
+       Form_pg_opfamily opfform;
+       Oid                     opfnamespace;
+       bool            visible;
+
+       opftup = SearchSysCache(OPFAMILYOID,
+                                                       ObjectIdGetDatum(opfid),
+                                                       0, 0, 0);
+       if (!HeapTupleIsValid(opftup))
+               elog(ERROR, "cache lookup failed for opfamily %u", opfid);
+       opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
+
+       recomputeNamespacePath();
+
+       /*
+        * Quick check: if it ain't in the path at all, it ain't visible. Items in
+        * the system namespace are surely in the path and so we needn't even do
+        * list_member_oid() for them.
+        */
+       opfnamespace = opfform->opfnamespace;
+       if (opfnamespace != PG_CATALOG_NAMESPACE &&
+               !list_member_oid(namespaceSearchPath, opfnamespace))
+               visible = false;
+       else
+       {
+               /*
+                * If it is in the path, it might still not be visible; it could be
+                * hidden by another opfamily of the same name earlier in the path. So
+                * we must do a slow check to see if this opfamily would be found by
+                * OpfamilynameGetOpfid.
+                */
+               char       *opfname = NameStr(opfform->opfname);
+
+               visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
+       }
+
+       ReleaseSysCache(opftup);
+
+       return visible;
+}
+
+/*
  * ConversionGetConid
  *             Try to resolve an unqualified conversion name.
  *             Returns OID if conversion found in search path, else InvalidOid.
index 13efb72..65ecb65 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.98 2006/07/14 14:52:18 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.99 2006/12/23 00:43:09 tgl Exp $
  *
  * NOTES
  *       these routines moved here from commands/define.c and somewhat cleaned up.
@@ -238,16 +238,13 @@ OperatorShellMake(const char *operatorName,
        values[i++] = ObjectIdGetDatum(operatorNamespace);      /* oprnamespace */
        values[i++] = ObjectIdGetDatum(GetUserId());            /* oprowner */
        values[i++] = CharGetDatum(leftTypeId ? (rightTypeId ? 'b' : 'r') : 'l');       /* oprkind */
+       values[i++] = BoolGetDatum(false);      /* oprcanmerge */
        values[i++] = BoolGetDatum(false);      /* oprcanhash */
        values[i++] = ObjectIdGetDatum(leftTypeId); /* oprleft */
        values[i++] = ObjectIdGetDatum(rightTypeId);            /* oprright */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* oprresult */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* oprcom */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* oprnegate */
-       values[i++] = ObjectIdGetDatum(InvalidOid); /* oprlsortop */
-       values[i++] = ObjectIdGetDatum(InvalidOid); /* oprrsortop */
-       values[i++] = ObjectIdGetDatum(InvalidOid); /* oprltcmpop */
-       values[i++] = ObjectIdGetDatum(InvalidOid); /* oprgtcmpop */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* oprcode */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* oprrest */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* oprjoin */
@@ -296,11 +293,8 @@ OperatorShellMake(const char *operatorName,
  *             negatorName                             X negator operator
  *             restrictionName                 X restriction sel. procedure
  *             joinName                                X join sel. procedure
+ *             canMerge                                merge join can be used with this operator
  *             canHash                                 hash join can be used with this operator
- *             leftSortName                    X left sort operator (for merge join)
- *             rightSortName                   X right sort operator (for merge join)
- *             ltCompareName                   X L<R compare operator (for merge join)
- *             gtCompareName                   X L>R compare operator (for merge join)
  *
  * This routine gets complicated because it allows the user to
  * specify operators that do not exist.  For example, if operator
@@ -326,6 +320,7 @@ OperatorShellMake(const char *operatorName,
  *      operatorName
  *      owner id (simply the user id of the caller)
  *      operator "kind" either "b" for binary or "l" for left unary
+ *      canMerge boolean
  *      canHash boolean
  *      leftTypeObjectId -- type must already be defined
  *      rightTypeObjectId -- this is optional, enter ObjectId=0 if none specified
@@ -341,8 +336,6 @@ OperatorShellMake(const char *operatorName,
  *                                             (We are creating a self-commutating operator.)
  *                                             The link will be fixed later by OperatorUpd.
  *      negatorObjectId   -- same as for commutatorObjectId
- *      leftSortObjectId  -- same as for commutatorObjectId
- *      rightSortObjectId -- same as for commutatorObjectId
  *      operatorProcedure -- must access the pg_procedure catalog to get the
  *                                ObjectId of the procedure that actually does the operator
  *                                actions this is required.  Do a lookup to find out the
@@ -369,11 +362,8 @@ OperatorCreate(const char *operatorName,
                           List *negatorName,
                           List *restrictionName,
                           List *joinName,
-                          bool canHash,
-                          List *leftSortName,
-                          List *rightSortName,
-                          List *ltCompareName,
-                          List *gtCompareName)
+                          bool canMerge,
+                          bool canHash)
 {
        Relation        pg_operator_desc;
        HeapTuple       tup;
@@ -386,10 +376,6 @@ OperatorCreate(const char *operatorName,
        Oid                     operResultType;
        Oid                     commutatorId,
                                negatorId,
-                               leftSortId,
-                               rightSortId,
-                               ltCompareId,
-                               gtCompareId,
                                restOid,
                                joinOid;
        bool            selfCommutator = false;
@@ -424,14 +410,14 @@ OperatorCreate(const char *operatorName,
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                 errmsg("only binary operators can have join selectivity")));
-               if (canHash)
+               if (canMerge)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-                                        errmsg("only binary operators can hash")));
-               if (leftSortName || rightSortName || ltCompareName || gtCompareName)
+                                        errmsg("only binary operators can merge join")));
+               if (canHash)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-                                        errmsg("only binary operators can merge join")));
+                                        errmsg("only binary operators can hash")));
        }
 
        operatorObjectId = OperatorGet(operatorName,
@@ -522,6 +508,7 @@ OperatorCreate(const char *operatorName,
        values[i++] = ObjectIdGetDatum(operatorNamespace);      /* oprnamespace */
        values[i++] = ObjectIdGetDatum(GetUserId());            /* oprowner */
        values[i++] = CharGetDatum(leftTypeId ? (rightTypeId ? 'b' : 'r') : 'l');       /* oprkind */
+       values[i++] = BoolGetDatum(canMerge);           /* oprcanmerge */
        values[i++] = BoolGetDatum(canHash);            /* oprcanhash */
        values[i++] = ObjectIdGetDatum(leftTypeId); /* oprleft */
        values[i++] = ObjectIdGetDatum(rightTypeId);            /* oprright */
@@ -565,58 +552,6 @@ OperatorCreate(const char *operatorName,
                negatorId = InvalidOid;
        values[i++] = ObjectIdGetDatum(negatorId);      /* oprnegate */
 
-       if (leftSortName)
-       {
-               /* left sort op takes left-side data type */
-               leftSortId = get_other_operator(leftSortName,
-                                                                               leftTypeId, leftTypeId,
-                                                                               operatorName, operatorNamespace,
-                                                                               leftTypeId, rightTypeId,
-                                                                               false);
-       }
-       else
-               leftSortId = InvalidOid;
-       values[i++] = ObjectIdGetDatum(leftSortId); /* oprlsortop */
-
-       if (rightSortName)
-       {
-               /* right sort op takes right-side data type */
-               rightSortId = get_other_operator(rightSortName,
-                                                                                rightTypeId, rightTypeId,
-                                                                                operatorName, operatorNamespace,
-                                                                                leftTypeId, rightTypeId,
-                                                                                false);
-       }
-       else
-               rightSortId = InvalidOid;
-       values[i++] = ObjectIdGetDatum(rightSortId);            /* oprrsortop */
-
-       if (ltCompareName)
-       {
-               /* comparator has same arg types */
-               ltCompareId = get_other_operator(ltCompareName,
-                                                                                leftTypeId, rightTypeId,
-                                                                                operatorName, operatorNamespace,
-                                                                                leftTypeId, rightTypeId,
-                                                                                false);
-       }
-       else
-               ltCompareId = InvalidOid;
-       values[i++] = ObjectIdGetDatum(ltCompareId);            /* oprltcmpop */
-
-       if (gtCompareName)
-       {
-               /* comparator has same arg types */
-               gtCompareId = get_other_operator(gtCompareName,
-                                                                                leftTypeId, rightTypeId,
-                                                                                operatorName, operatorNamespace,
-                                                                                leftTypeId, rightTypeId,
-                                                                                false);
-       }
-       else
-               gtCompareId = InvalidOid;
-       values[i++] = ObjectIdGetDatum(gtCompareId);            /* oprgtcmpop */
-
        values[i++] = ObjectIdGetDatum(procOid);        /* oprcode */
        values[i++] = ObjectIdGetDatum(restOid);        /* oprrest */
        values[i++] = ObjectIdGetDatum(joinOid);        /* oprjoin */
@@ -930,12 +865,11 @@ makeOperatorDependencies(HeapTuple tuple)
 
        /*
         * NOTE: we do not consider the operator to depend on the associated
-        * operators oprcom, oprnegate, oprlsortop, oprrsortop, oprltcmpop,
-        * oprgtcmpop.  We would not want to delete this operator if those go
-        * away, but only reset the link fields; which is not a function that the
-        * dependency code can presently handle.  (Something could perhaps be done
-        * with objectSubId though.)  For now, it's okay to let those links dangle
-        * if a referenced operator is removed.
+        * operators oprcom and oprnegate. We would not want to delete this
+        * operator if those go away, but only reset the link fields; which is not
+        * a function that the dependency code can presently handle.  (Something
+        * could perhaps be done with objectSubId though.)  For now, it's okay to
+        * let those links dangle if a referenced operator is removed.
         */
 
        /* Dependency on implementation function */
index 5f54f66..a5cc047 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.149 2006/10/04 00:29:51 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.150 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -802,31 +802,37 @@ GetIndexOpClass(List *opclass, Oid attrType,
 Oid
 GetDefaultOpClass(Oid type_id, Oid am_id)
 {
+       Oid                     result = InvalidOid;
        int                     nexact = 0;
        int                     ncompatible = 0;
-       Oid                     exactOid = InvalidOid;
-       Oid                     compatibleOid = InvalidOid;
+       int                     ncompatiblepreferred = 0;
        Relation        rel;
        ScanKeyData skey[1];
        SysScanDesc scan;
        HeapTuple       tup;
+       CATEGORY        tcategory;
 
        /* If it's a domain, look at the base type instead */
        type_id = getBaseType(type_id);
 
+       tcategory = TypeCategory(type_id);
+
        /*
         * We scan through all the opclasses available for the access method,
         * looking for one that is marked default and matches the target type
         * (either exactly or binary-compatibly, but prefer an exact match).
         *
-        * We could find more than one binary-compatible match, in which case we
-        * require the user to specify which one he wants.      If we find more than
-        * one exact match, then someone put bogus entries in pg_opclass.
+        * We could find more than one binary-compatible match.  If just one is
+        * for a preferred type, use that one; otherwise we fail, forcing the user
+        * to specify which one he wants.  (The preferred-type special case is a
+        * kluge for varchar: it's binary-compatible to both text and bpchar, so
+        * we need a tiebreaker.)  If we find more than one exact match, then
+        * someone put bogus entries in pg_opclass.
         */
        rel = heap_open(OperatorClassRelationId, AccessShareLock);
 
        ScanKeyInit(&skey[0],
-                               Anum_pg_opclass_opcamid,
+                               Anum_pg_opclass_opcmethod,
                                BTEqualStrategyNumber, F_OIDEQ,
                                ObjectIdGetDatum(am_id));
 
@@ -837,17 +843,26 @@ GetDefaultOpClass(Oid type_id, Oid am_id)
        {
                Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
 
-               if (opclass->opcdefault)
+               /* ignore altogether if not a default opclass */
+               if (!opclass->opcdefault)
+                       continue;
+               if (opclass->opcintype == type_id)
                {
-                       if (opclass->opcintype == type_id)
+                       nexact++;
+                       result = HeapTupleGetOid(tup);
+               }
+               else if (nexact == 0 &&
+                                IsBinaryCoercible(type_id, opclass->opcintype))
+               {
+                       if (IsPreferredType(tcategory, opclass->opcintype))
                        {
-                               nexact++;
-                               exactOid = HeapTupleGetOid(tup);
+                               ncompatiblepreferred++;
+                               result = HeapTupleGetOid(tup);
                        }
-                       else if (IsBinaryCoercible(type_id, opclass->opcintype))
+                       else if (ncompatiblepreferred == 0)
                        {
                                ncompatible++;
-                               compatibleOid = HeapTupleGetOid(tup);
+                               result = HeapTupleGetOid(tup);
                        }
                }
        }
@@ -856,15 +871,17 @@ GetDefaultOpClass(Oid type_id, Oid am_id)
 
        heap_close(rel, AccessShareLock);
 
-       if (nexact == 1)
-               return exactOid;
-       if (nexact != 0)
+       /* raise error if pg_opclass contains inconsistent data */
+       if (nexact > 1)
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
                errmsg("there are multiple default operator classes for data type %s",
                           format_type_be(type_id))));
-       if (ncompatible == 1)
-               return compatibleOid;
+
+       if (nexact == 1 ||
+               ncompatiblepreferred == 1 ||
+               (ncompatiblepreferred == 0 && ncompatible == 1))
+               return result;
 
        return InvalidOid;
 }
index d4dec74..8b1b27e 100644 (file)
@@ -2,14 +2,14 @@
  *
  * opclasscmds.c
  *
- *       Routines for opclass manipulation commands
+ *       Routines for opclass (and opfamily) manipulation commands
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.50 2006/12/18 18:56:28 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.51 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 
 /*
  * We use lists of this struct type to keep track of both operators and
- * procedures during DefineOpClass.
+ * procedures while building or adding to an opfamily.
  */
 typedef struct
 {
        Oid                     object;                 /* operator or support proc's OID */
        int                     number;                 /* strategy or support proc number */
-       Oid                     subtype;                /* subtype */
+       Oid                     lefttype;               /* lefttype */
+       Oid                     righttype;              /* righttype */
        bool            recheck;                /* oper recheck flag (unused for proc) */
-} OpClassMember;
+} OpFamilyMember;
 
 
-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);
+static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid);
+static void assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid);
+static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc);
+static void storeOperators(Oid amoid, Oid opfamilyoid, Oid opclassoid,
+                                                  List *operators);
+static void storeProcedures(Oid amoid, Oid opfamilyoid, Oid opclassoid,
+                                                       List *procedures);
 static void AlterOpClassOwner_internal(Relation rel, HeapTuple tuple,
                                                   Oid newOwnerId);
 
 
 /*
+ * OpFamilyCacheLookup
+ *             Look up an existing opfamily by name.
+ *
+ * Returns a syscache tuple reference, or NULL if not found.
+ */
+static HeapTuple
+OpFamilyCacheLookup(Oid amID, List *opfamilyname)
+{
+       char       *schemaname;
+       char       *opfname;
+
+       /* deconstruct the name list */
+       DeconstructQualifiedName(opfamilyname, &schemaname, &opfname);
+
+       if (schemaname)
+       {
+               /* Look in specific schema only */
+               Oid                     namespaceId;
+
+               namespaceId = LookupExplicitNamespace(schemaname);
+               return SearchSysCache(OPFAMILYAMNAMENSP,
+                                                         ObjectIdGetDatum(amID),
+                                                         PointerGetDatum(opfname),
+                                                         ObjectIdGetDatum(namespaceId),
+                                                         0);
+       }
+       else
+       {
+               /* Unqualified opfamily name, so search the search path */
+               Oid             opfID = OpfamilynameGetOpfid(amID, opfname);
+
+               if (!OidIsValid(opfID))
+                       return NULL;
+               return SearchSysCache(OPFAMILYOID,
+                                                         ObjectIdGetDatum(opfID),
+                                                         0, 0, 0);
+       }
+}
+
+/*
+ * OpClassCacheLookup
+ *             Look up an existing opclass by name.
+ *
+ * Returns a syscache tuple reference, or NULL if not found.
+ */
+static HeapTuple
+OpClassCacheLookup(Oid amID, List *opclassname)
+{
+       char       *schemaname;
+       char       *opcname;
+
+       /* deconstruct the name list */
+       DeconstructQualifiedName(opclassname, &schemaname, &opcname);
+
+       if (schemaname)
+       {
+               /* Look in specific schema only */
+               Oid                     namespaceId;
+
+               namespaceId = LookupExplicitNamespace(schemaname);
+               return SearchSysCache(CLAAMNAMENSP,
+                                                         ObjectIdGetDatum(amID),
+                                                         PointerGetDatum(opcname),
+                                                         ObjectIdGetDatum(namespaceId),
+                                                         0);
+       }
+       else
+       {
+               /* Unqualified opclass name, so search the search path */
+               Oid             opcID = OpclassnameGetOpcid(amID, opcname);
+
+               if (!OidIsValid(opcID))
+                       return NULL;
+               return SearchSysCache(CLAOID,
+                                                         ObjectIdGetDatum(opcID),
+                                                         0, 0, 0);
+       }
+}
+
+/*
+ * CreateOpFamily
+ *             Internal routine to make the catalog entry for a new operator family.
+ *
+ * Caller must have done permissions checks etc. already.
+ */
+static Oid
+CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
+{
+       Oid                     opfamilyoid;
+       Relation        rel;
+       HeapTuple       tup;
+       Datum           values[Natts_pg_opfamily];
+       char            nulls[Natts_pg_opfamily];
+       NameData        opfName;
+       ObjectAddress myself,
+                               referenced;
+
+       rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+
+       /*
+        * Make sure there is no existing opfamily of this name (this is just to
+        * give a more friendly error message than "duplicate key").
+        */
+       if (SearchSysCacheExists(OPFAMILYAMNAMENSP,
+                                                        ObjectIdGetDatum(amoid),
+                                                        CStringGetDatum(opfname),
+                                                        ObjectIdGetDatum(namespaceoid),
+                                                        0))
+               ereport(ERROR,
+                               (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                errmsg("operator family \"%s\" for access method \"%s\" already exists",
+                                               opfname, amname)));
+
+       /*
+        * Okay, let's create the pg_opfamily entry.
+        */
+       memset(values, 0, sizeof(values));
+       memset(nulls, ' ', sizeof(nulls));
+
+       values[Anum_pg_opfamily_opfmethod - 1] = ObjectIdGetDatum(amoid);
+       namestrcpy(&opfName, opfname);
+       values[Anum_pg_opfamily_opfname - 1] = NameGetDatum(&opfName);
+       values[Anum_pg_opfamily_opfnamespace - 1] = ObjectIdGetDatum(namespaceoid);
+       values[Anum_pg_opfamily_opfowner - 1] = ObjectIdGetDatum(GetUserId());
+
+       tup = heap_formtuple(rel->rd_att, values, nulls);
+
+       opfamilyoid = simple_heap_insert(rel, tup);
+
+       CatalogUpdateIndexes(rel, tup);
+
+       heap_freetuple(tup);
+
+       /*
+        * Create dependencies for the opfamily proper.  Note: we do not create a
+        * dependency link to the AM, because we don't currently support DROP
+        * ACCESS METHOD.
+        */
+       myself.classId = OperatorFamilyRelationId;
+       myself.objectId = opfamilyoid;
+       myself.objectSubId = 0;
+
+       /* dependency on namespace */
+       referenced.classId = NamespaceRelationId;
+       referenced.objectId = namespaceoid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* dependency on owner */
+       recordDependencyOnOwner(OperatorFamilyRelationId, opfamilyoid, GetUserId());
+
+       heap_close(rel, RowExclusiveLock);
+
+       return opfamilyoid;
+}
+
+/*
  * DefineOpClass
  *             Define a new index operator class.
  */
@@ -74,12 +235,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                typeoid,                /* indexable datatype oid */
                                storageoid,             /* storage datatype oid, if any */
                                namespaceoid,   /* namespace to create opclass in */
+                               opfamilyoid,    /* oid of containing opfamily */
                                opclassoid;             /* oid of opclass we create */
        int                     maxOpNumber,    /* amstrategies value */
                                maxProcNumber;  /* amsupport value */
        bool            amstorage;              /* amstorage flag */
-       List       *operators;          /* OpClassMember list for operators */
-       List       *procedures;         /* OpClassMember list for support procs */
+       List       *operators;          /* OpFamilyMember list for operators */
+       List       *procedures;         /* OpFamilyMember list for support procs */
        ListCell   *l;
        Relation        rel;
        HeapTuple       tup;
@@ -88,7 +250,6 @@ DefineOpClass(CreateOpClassStmt *stmt)
        char            nulls[Natts_pg_opclass];
        AclResult       aclresult;
        NameData        opcName;
-       int                     i;
        ObjectAddress myself,
                                referenced;
 
@@ -161,6 +322,52 @@ DefineOpClass(CreateOpClassStmt *stmt)
                                           format_type_be(typeoid));
 #endif
 
+       /*
+        * Look up the containing operator family, or create one if FAMILY option
+        * was omitted and there's not a match already.
+        */
+       if (stmt->opfamilyname)
+       {
+               tup = OpFamilyCacheLookup(amoid, stmt->opfamilyname);
+               if (!HeapTupleIsValid(tup))
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                        errmsg("operator family \"%s\" does not exist for access method \"%s\"",
+                                                       NameListToString(stmt->opfamilyname), stmt->amname)));
+               opfamilyoid = HeapTupleGetOid(tup);
+               /*
+                * XXX given the superuser check above, there's no need for an
+                * ownership check here
+                */
+               ReleaseSysCache(tup);
+       }
+       else
+       {
+               /* Lookup existing family of same name and namespace */
+               tup = SearchSysCache(OPFAMILYAMNAMENSP,
+                                                        ObjectIdGetDatum(amoid),
+                                                        PointerGetDatum(opcname),
+                                                        ObjectIdGetDatum(namespaceoid),
+                                                        0);
+               if (HeapTupleIsValid(tup))
+               {
+                       opfamilyoid = HeapTupleGetOid(tup);
+                       /*
+                        * XXX given the superuser check above, there's no need for an
+                        * ownership check here
+                        */
+                       ReleaseSysCache(tup);
+               }
+               else
+               {
+                       /*
+                        * Create it ... again no need for more permissions ...
+                        */
+                       opfamilyoid = CreateOpFamily(stmt->amname, opcname,
+                                                                                namespaceoid, amoid);
+               }
+       }
+
        operators = NIL;
        procedures = NIL;
 
@@ -175,7 +382,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
                CreateOpClassItem *item = lfirst(l);
                Oid                     operOid;
                Oid                     funcOid;
-               OpClassMember *member;
+               OpFamilyMember *member;
 
                Assert(IsA(item, CreateOpClassItem));
                switch (item->itemtype)
@@ -217,12 +424,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
 #endif
 
                                /* Save the info */
-                               member = (OpClassMember *) palloc0(sizeof(OpClassMember));
+                               member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
                                member->object = operOid;
                                member->number = item->number;
-                               member->subtype = assignOperSubtype(amoid, typeoid, operOid);
                                member->recheck = item->recheck;
-                               addClassMember(&operators, member, false);
+                               assignOperTypes(member, amoid, typeoid);
+                               addFamilyMember(&operators, member, false);
                                break;
                        case OPCLASS_ITEM_FUNCTION:
                                if (item->number <= 0 || item->number > maxProcNumber)
@@ -242,11 +449,11 @@ DefineOpClass(CreateOpClassStmt *stmt)
 #endif
 
                                /* Save the info */
-                               member = (OpClassMember *) palloc0(sizeof(OpClassMember));
+                               member = (OpFamilyMember *) palloc0(sizeof(OpFamilyMember));
                                member->object = funcOid;
                                member->number = item->number;
-                               member->subtype = assignProcSubtype(amoid, typeoid, funcOid);
-                               addClassMember(&procedures, member, true);
+                               assignProcTypes(member, amoid, typeoid);
+                               addFamilyMember(&procedures, member, true);
                                break;
                        case OPCLASS_ITEM_STORAGETYPE:
                                if (OidIsValid(storageoid))
@@ -311,7 +518,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
                SysScanDesc scan;
 
                ScanKeyInit(&skey[0],
-                                       Anum_pg_opclass_opcamid,
+                                       Anum_pg_opclass_opcmethod,
                                        BTEqualStrategyNumber, F_OIDEQ,
                                        ObjectIdGetDatum(amoid));
 
@@ -338,21 +545,18 @@ DefineOpClass(CreateOpClassStmt *stmt)
        /*
         * Okay, let's create the pg_opclass entry.
         */
-       for (i = 0; i < Natts_pg_opclass; ++i)
-       {
-               nulls[i] = ' ';
-               values[i] = (Datum) NULL;               /* redundant, but safe */
-       }
+       memset(values, 0, sizeof(values));
+       memset(nulls, ' ', sizeof(nulls));
 
-       i = 0;
-       values[i++] = ObjectIdGetDatum(amoid);          /* opcamid */
+       values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid);
        namestrcpy(&opcName, opcname);
-       values[i++] = NameGetDatum(&opcName);           /* opcname */
-       values[i++] = ObjectIdGetDatum(namespaceoid);           /* opcnamespace */
-       values[i++] = ObjectIdGetDatum(GetUserId());            /* opcowner */
-       values[i++] = ObjectIdGetDatum(typeoid);        /* opcintype */
-       values[i++] = BoolGetDatum(stmt->isDefault);            /* opcdefault */
-       values[i++] = ObjectIdGetDatum(storageoid); /* opckeytype */
+       values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName);
+       values[Anum_pg_opclass_opcnamespace - 1] = ObjectIdGetDatum(namespaceoid);
+       values[Anum_pg_opclass_opcowner - 1] = ObjectIdGetDatum(GetUserId());
+       values[Anum_pg_opclass_opcfamily - 1] = ObjectIdGetDatum(opfamilyoid);
+       values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid);
+       values[Anum_pg_opclass_opcdefault - 1] = BoolGetDatum(stmt->isDefault);
+       values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid);
 
        tup = heap_formtuple(rel->rd_att, values, nulls);
 
@@ -364,14 +568,15 @@ DefineOpClass(CreateOpClassStmt *stmt)
 
        /*
         * Now add tuples to pg_amop and pg_amproc tying in the operators and
-        * functions.
+        * functions.  Dependencies on them are inserted, too.
         */
-       storeOperators(opclassoid, operators);
-       storeProcedures(opclassoid, procedures);
+       storeOperators(amoid, opfamilyoid, opclassoid, operators);
+       storeProcedures(amoid, opfamilyoid, opclassoid, procedures);
 
        /*
-        * Create dependencies.  Note: we do not create a dependency link to the
-        * AM, because we don't currently support DROP ACCESS METHOD.
+        * Create dependencies for the opclass proper.  Note: we do not create a
+        * dependency link to the AM, because we don't currently support DROP
+        * ACCESS METHOD.
         */
        myself.classId = OperatorClassRelationId;
        myself.objectId = opclassoid;
@@ -383,6 +588,12 @@ DefineOpClass(CreateOpClassStmt *stmt)
        referenced.objectSubId = 0;
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 
+       /* dependency on opfamily */
+       referenced.classId = OperatorFamilyRelationId;
+       referenced.objectId = opfamilyoid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
        /* dependency on indexed datatype */
        referenced.classId = TypeRelationId;
        referenced.objectId = typeoid;
@@ -398,28 +609,6 @@ DefineOpClass(CreateOpClassStmt *stmt)
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
 
-       /* dependencies on operators */
-       foreach(l, operators)
-       {
-               OpClassMember *op = (OpClassMember *) lfirst(l);
-
-               referenced.classId = OperatorRelationId;
-               referenced.objectId = op->object;
-               referenced.objectSubId = 0;
-               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-       }
-
-       /* dependencies on procedures */
-       foreach(l, procedures)
-       {
-               OpClassMember *proc = (OpClassMember *) lfirst(l);
-
-               referenced.classId = ProcedureRelationId;
-               referenced.objectId = proc->object;
-               referenced.objectSubId = 0;
-               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-       }
-
        /* dependency on owner */
        recordDependencyOnOwner(OperatorClassRelationId, opclassoid, GetUserId());
 
@@ -427,139 +616,158 @@ DefineOpClass(CreateOpClassStmt *stmt)
 }
 
 /*
- * 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.
+ * Determine the lefttype/righttype to assign to an operator,
+ * and do any validity checking we can manage.
  */
-static Oid
-assignOperSubtype(Oid amoid, Oid typeoid, Oid operOid)
+static void
+assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
 {
-       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;
-
+       /* Fetch the operator definition */
        optup = SearchSysCache(OPEROID,
-                                                  ObjectIdGetDatum(operOid),
+                                                  ObjectIdGetDatum(member->object),
                                                   0, 0, 0);
        if (optup == NULL)
-               elog(ERROR, "cache lookup failed for operator %u", operOid);
+               elog(ERROR, "cache lookup failed for operator %u", member->object);
        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.
+        * Opfamily operators must be binary ops returning boolean.
         */
        if (opform->oprkind != 'b')
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                errmsg("btree operators must be binary")));
+                                errmsg("index 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")));
+                                errmsg("index operators must return boolean")));
 
        /*
-        * The subtype is "default" (0) if oprright matches the operator class,
-        * otherwise it is oprright.
+        * If lefttype/righttype isn't specified, use the operator's input types
         */
-       if (opform->oprright == typeoid)
-               subtype = InvalidOid;
-       else
-               subtype = opform->oprright;
+       if (!OidIsValid(member->lefttype))
+               member->lefttype = opform->oprleft;
+       if (!OidIsValid(member->righttype))
+               member->righttype = 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.
+ * Determine the lefttype/righttype to assign to a support procedure,
+ * and do any validity checking we can manage.
  */
-static Oid
-assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid)
+static void
+assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
 {
-       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;
-
+       /* Fetch the procedure definition */
        proctup = SearchSysCache(PROCOID,
-                                                        ObjectIdGetDatum(procOid),
+                                                        ObjectIdGetDatum(member->object),
                                                         0, 0, 0);
        if (proctup == NULL)
-               elog(ERROR, "cache lookup failed for function %u", procOid);
+               elog(ERROR, "cache lookup failed for function %u", member->object);
        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.
+        * btree support procs must be 2-arg procs returning int4; hash support
+        * procs must be 1-arg procs returning int4; otherwise we don't know.
         */
-       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.values[0] != typeoid)
-               ereport(ERROR,
-                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                       errmsg("btree procedures must have index type as first input")));
+       if (amoid == BTREE_AM_OID)
+       {
+               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")));
 
-       /*
-        * The subtype is "default" (0) if second input type matches the operator
-        * class, otherwise it is the second input type.
-        */
-       if (procform->proargtypes.values[1] == typeoid)
-               subtype = InvalidOid;
+               /*
+                * If lefttype/righttype isn't specified, use the proc's input types
+                */
+               if (!OidIsValid(member->lefttype))
+                       member->lefttype = procform->proargtypes.values[0];
+               if (!OidIsValid(member->righttype))
+                       member->righttype = procform->proargtypes.values[1];
+       }
+       else if (amoid == HASH_AM_OID)
+       {
+               if (procform->pronargs != 1)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("hash procedures must have one argument")));
+               if (procform->prorettype != INT4OID)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("hash procedures must return integer")));
+
+               /*
+                * If lefttype/righttype isn't specified, use the proc's input type
+                */
+               if (!OidIsValid(member->lefttype))
+                       member->lefttype = procform->proargtypes.values[0];
+               if (!OidIsValid(member->righttype))
+                       member->righttype = procform->proargtypes.values[0];
+       }
        else
-               subtype = procform->proargtypes.values[1];
+       {
+               /*
+                * The default for GiST and GIN in CREATE OPERATOR CLASS is to use
+                * the class' opcintype as lefttype and righttype.  In CREATE or
+                * ALTER OPERATOR FAMILY, opcintype isn't available, so make the
+                * user specify the types.
+                */
+               if (!OidIsValid(member->lefttype))
+                       member->lefttype = typeoid;
+               if (!OidIsValid(member->righttype))
+                       member->righttype = typeoid;
+               if (!OidIsValid(member->lefttype) || !OidIsValid(member->righttype))
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("associated data types must be specified for index support procedure")));
+       }
+
        ReleaseSysCache(proctup);
-       return subtype;
 }
 
 /*
- * Add a new class member to the appropriate list, after checking for
+ * Add a new family member to the appropriate list, after checking for
  * duplicated strategy or proc number.
  */
 static void
-addClassMember(List **list, OpClassMember *member, bool isProc)
+addFamilyMember(List **list, OpFamilyMember *member, bool isProc)
 {
        ListCell   *l;
 
        foreach(l, *list)
        {
-               OpClassMember *old = (OpClassMember *) lfirst(l);
+               OpFamilyMember *old = (OpFamilyMember *) lfirst(l);
 
                if (old->number == member->number &&
-                       old->subtype == member->subtype)
+                       old->lefttype == member->lefttype &&
+                       old->righttype == member->righttype)
                {
                        if (isProc)
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                                errmsg("procedure number %d appears more than once",
-                                                               member->number)));
+                                                errmsg("procedure number %d for (%s,%s) appears more than once",
+                                                               member->number,
+                                                               format_type_be(member->lefttype),
+                                                               format_type_be(member->righttype))));
                        else
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                                errmsg("operator number %d appears more than once",
-                                                               member->number)));
+                                                errmsg("operator number %d for (%s,%s) appears more than once",
+                                                               member->number,
+                                                               format_type_be(member->lefttype),
+                                                               format_type_be(member->righttype))));
                }
        }
        *list = lappend(*list, member);
@@ -567,43 +775,80 @@ addClassMember(List **list, OpClassMember *member, bool isProc)
 
 /*
  * Dump the operators to pg_amop
+ *
+ * We also make dependency entries in pg_depend for the opfamily entries.
+ * If opclassoid is valid then make an INTERNAL dependency on that opclass,
+ * else make an AUTO dependency on the opfamily.
  */
 static void
-storeOperators(Oid opclassoid, List *operators)
+storeOperators(Oid amoid, Oid opfamilyoid, Oid opclassoid, List *operators)
 {
        Relation        rel;
        Datum           values[Natts_pg_amop];
        char            nulls[Natts_pg_amop];
        HeapTuple       tup;
+       Oid                     entryoid;
+       ObjectAddress myself,
+                               referenced;
        ListCell   *l;
-       int                     i;
 
        rel = heap_open(AccessMethodOperatorRelationId, RowExclusiveLock);
 
        foreach(l, operators)
        {
-               OpClassMember *op = (OpClassMember *) lfirst(l);
+               OpFamilyMember *op = (OpFamilyMember *) lfirst(l);
 
-               for (i = 0; i < Natts_pg_amop; ++i)
-               {
-                       nulls[i] = ' ';
-                       values[i] = (Datum) NULL;
-               }
+               /* Create the pg_amop entry */
+               memset(values, 0, sizeof(values));
+               memset(nulls, ' ', sizeof(nulls));
 
-               i = 0;
-               values[i++] = ObjectIdGetDatum(opclassoid);             /* amopclaid */
-               values[i++] = ObjectIdGetDatum(op->subtype);    /* amopsubtype */
-               values[i++] = Int16GetDatum(op->number);                /* amopstrategy */
-               values[i++] = BoolGetDatum(op->recheck);                /* amopreqcheck */
-               values[i++] = ObjectIdGetDatum(op->object);             /* amopopr */
+               values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid);
+               values[Anum_pg_amop_amoplefttype - 1] = ObjectIdGetDatum(op->lefttype);
+               values[Anum_pg_amop_amoprighttype - 1] = ObjectIdGetDatum(op->righttype);
+               values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number);
+               values[Anum_pg_amop_amopreqcheck - 1] = BoolGetDatum(op->recheck);
+               values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object);
+               values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid);
 
                tup = heap_formtuple(rel->rd_att, values, nulls);
 
-               simple_heap_insert(rel, tup);
+               entryoid = simple_heap_insert(rel, tup);
 
                CatalogUpdateIndexes(rel, tup);
 
                heap_freetuple(tup);
+
+               /* Make its dependencies */
+               myself.classId = AccessMethodOperatorRelationId;
+               myself.objectId = entryoid;
+               myself.objectSubId = 0;
+
+               referenced.classId = OperatorRelationId;
+               referenced.objectId = op->object;
+               referenced.objectSubId = 0;
+
+               if (OidIsValid(opclassoid))
+               {
+                       /* if contained in an opclass, use a NORMAL dep on operator */
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+                       /* ... and an INTERNAL dep on the opclass */
+                       referenced.classId = OperatorClassRelationId;
+                       referenced.objectId = opclassoid;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+               }
+               else
+               {
+                       /* if "loose" in the opfamily, use a AUTO dep on operator */
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+                       /* ... and an AUTO dep on the opfamily */
+                       referenced.classId = OperatorFamilyRelationId;
+                       referenced.objectId = opfamilyoid;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+               }
        }
 
        heap_close(rel, RowExclusiveLock);
@@ -611,42 +856,78 @@ storeOperators(Oid opclassoid, List *operators)
 
 /*
  * Dump the procedures (support routines) to pg_amproc
+ *
+ * We also make dependency entries in pg_depend for the opfamily entries.
+ * If opclassoid is valid then make an INTERNAL dependency on that opclass,
+ * else make an AUTO dependency on the opfamily.
  */
 static void
-storeProcedures(Oid opclassoid, List *procedures)
+storeProcedures(Oid amoid, Oid opfamilyoid, Oid opclassoid, List *procedures)
 {
        Relation        rel;
        Datum           values[Natts_pg_amproc];
        char            nulls[Natts_pg_amproc];
        HeapTuple       tup;
+       Oid                     entryoid;
+       ObjectAddress myself,
+                               referenced;
        ListCell   *l;
-       int                     i;
 
        rel = heap_open(AccessMethodProcedureRelationId, RowExclusiveLock);
 
        foreach(l, procedures)
        {
-               OpClassMember *proc = (OpClassMember *) lfirst(l);
+               OpFamilyMember *proc = (OpFamilyMember *) lfirst(l);
 
-               for (i = 0; i < Natts_pg_amproc; ++i)
-               {
-                       nulls[i] = ' ';
-                       values[i] = (Datum) NULL;
-               }
+               /* Create the pg_amproc entry */
+               memset(values, 0, sizeof(values));
+               memset(nulls, ' ', sizeof(nulls));
 
-               i = 0;
-               values[i++] = ObjectIdGetDatum(opclassoid);             /* amopclaid */
-               values[i++] = ObjectIdGetDatum(proc->subtype);  /* amprocsubtype */
-               values[i++] = Int16GetDatum(proc->number);              /* amprocnum */
-               values[i++] = ObjectIdGetDatum(proc->object);   /* amproc */
+               values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid);
+               values[Anum_pg_amproc_amproclefttype - 1] = ObjectIdGetDatum(proc->lefttype);
+               values[Anum_pg_amproc_amprocrighttype - 1] = ObjectIdGetDatum(proc->righttype);
+               values[Anum_pg_amproc_amprocnum - 1] = Int16GetDatum(proc->number);
+               values[Anum_pg_amproc_amproc - 1] = ObjectIdGetDatum(proc->object);
 
                tup = heap_formtuple(rel->rd_att, values, nulls);
 
-               simple_heap_insert(rel, tup);
+               entryoid = simple_heap_insert(rel, tup);
 
                CatalogUpdateIndexes(rel, tup);
 
                heap_freetuple(tup);
+
+               /* Make its dependencies */
+               myself.classId = AccessMethodProcedureRelationId;
+               myself.objectId = entryoid;
+               myself.objectSubId = 0;
+
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = proc->object;
+               referenced.objectSubId = 0;
+
+               if (OidIsValid(opclassoid))
+               {
+                       /* if contained in an opclass, use a NORMAL dep on procedure */
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+                       /* ... and an INTERNAL dep on the opclass */
+                       referenced.classId = OperatorClassRelationId;
+                       referenced.objectId = opclassoid;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+               }
+               else
+               {
+                       /* if "loose" in the opfamily, use a AUTO dep on procedure */
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+                       /* ... and an AUTO dep on the opfamily */
+                       referenced.classId = OperatorFamilyRelationId;
+                       referenced.objectId = opfamilyoid;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+               }
        }
 
        heap_close(rel, RowExclusiveLock);
@@ -662,8 +943,6 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
 {
        Oid                     amID,
                                opcID;
-       char       *schemaname;
-       char       *opcname;
        HeapTuple       tuple;
        ObjectAddress object;
 
@@ -682,49 +961,9 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
        /*
         * Look up the opclass.
         */
-
-       /* deconstruct the name list */
-       DeconstructQualifiedName(stmt->opclassname, &schemaname, &opcname);
-
-       if (schemaname)
-       {
-               /* Look in specific schema only */
-               Oid                     namespaceId;
-
-               namespaceId = LookupExplicitNamespace(schemaname);
-               tuple = SearchSysCache(CLAAMNAMENSP,
-                                                          ObjectIdGetDatum(amID),
-                                                          PointerGetDatum(opcname),
-                                                          ObjectIdGetDatum(namespaceId),
-                                                          0);
-       }
-       else
-       {
-               /* Unqualified opclass name, so search the search path */
-               opcID = OpclassnameGetOpcid(amID, opcname);
-               if (!OidIsValid(opcID))
-               {
-                       if (!stmt->missing_ok)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                                                errmsg("operator class \"%s\" does not exist for access method \"%s\"",
-                                                               opcname, stmt->amname)));
-                       else
-                               ereport(NOTICE,
-                                               (errmsg("operator class \"%s\" does not exist for access method \"%s\"",
-                                                               opcname, stmt->amname)));
-
-                       return;
-               }
-
-               tuple = SearchSysCache(CLAOID,
-                                                          ObjectIdGetDatum(opcID),
-                                                          0, 0, 0);
-       }
-
+       tuple = OpClassCacheLookup(amID, stmt->opclassname);
        if (!HeapTupleIsValid(tuple))
        {
-
                if (!stmt->missing_ok)
                        ereport(ERROR,
                                        (errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -759,19 +998,35 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
 }
 
 /*
- * Guts of opclass deletion.
+ * Deletion subroutines for use by dependency.c.
  */
 void
+RemoveOpFamilyById(Oid opfamilyOid)
+{
+       Relation        rel;
+       HeapTuple       tup;
+
+       rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
+
+       tup = SearchSysCache(OPFAMILYOID,
+                                                ObjectIdGetDatum(opfamilyOid),
+                                                0, 0, 0);
+       if (!HeapTupleIsValid(tup)) /* should not happen */
+               elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
+
+       simple_heap_delete(rel, &tup->t_self);
+
+       ReleaseSysCache(tup);
+
+       heap_close(rel, RowExclusiveLock);
+}
+
+void
 RemoveOpClassById(Oid opclassOid)
 {
        Relation        rel;
        HeapTuple       tup;
-       ScanKeyData skey[1];
-       SysScanDesc scan;
 
-       /*
-        * First remove the pg_opclass entry itself.
-        */
        rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
 
        tup = SearchSysCache(CLAOID,
@@ -785,41 +1040,61 @@ RemoveOpClassById(Oid opclassOid)
        ReleaseSysCache(tup);
 
        heap_close(rel, RowExclusiveLock);
+}
+
+void
+RemoveAmOpEntryById(Oid entryOid)
+{
+       Relation        rel;
+       HeapTuple       tup;
+       ScanKeyData skey[1];
+       SysScanDesc scan;
 
-       /*
-        * Remove associated entries in pg_amop.
-        */
        ScanKeyInit(&skey[0],
-                               Anum_pg_amop_amopclaid,
+                               ObjectIdAttributeNumber,
                                BTEqualStrategyNumber, F_OIDEQ,
-                               ObjectIdGetDatum(opclassOid));
+                               ObjectIdGetDatum(entryOid));
 
        rel = heap_open(AccessMethodOperatorRelationId, RowExclusiveLock);
 
-       scan = systable_beginscan(rel, AccessMethodStrategyIndexId, true,
+       scan = systable_beginscan(rel, AccessMethodOperatorOidIndexId, true,
                                                          SnapshotNow, 1, skey);
 
-       while (HeapTupleIsValid(tup = systable_getnext(scan)))
-               simple_heap_delete(rel, &tup->t_self);
+       /* we expect exactly one match */
+       tup = systable_getnext(scan);
+       if (!HeapTupleIsValid(tup))
+               elog(ERROR, "could not find tuple for amop entry %u", entryOid);
+
+       simple_heap_delete(rel, &tup->t_self);
 
        systable_endscan(scan);
        heap_close(rel, RowExclusiveLock);
+}
+
+void
+RemoveAmProcEntryById(Oid entryOid)
+{
+       Relation        rel;
+       HeapTuple       tup;
+       ScanKeyData skey[1];
+       SysScanDesc scan;
 
-       /*
-        * Remove associated entries in pg_amproc.
-        */
        ScanKeyInit(&skey[0],
-                               Anum_pg_amproc_amopclaid,
+                               ObjectIdAttributeNumber,
                                BTEqualStrategyNumber, F_OIDEQ,
-                               ObjectIdGetDatum(opclassOid));
+                               ObjectIdGetDatum(entryOid));
 
        rel = heap_open(AccessMethodProcedureRelationId, RowExclusiveLock);
 
-       scan = systable_beginscan(rel, AccessMethodProcedureIndexId, true,
+       scan = systable_beginscan(rel, AccessMethodProcedureOidIndexId, true,
                                                          SnapshotNow, 1, skey);
 
-       while (HeapTupleIsValid(tup = systable_getnext(scan)))
-               simple_heap_delete(rel, &tup->t_self);
+       /* we expect exactly one match */
+       tup = systable_getnext(scan);
+       if (!HeapTupleIsValid(tup))
+               elog(ERROR, "could not find tuple for amproc entry %u", entryOid);
+
+       simple_heap_delete(rel, &tup->t_self);
 
        systable_endscan(scan);
        heap_close(rel, RowExclusiveLock);
@@ -1022,7 +1297,7 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
 
 /*
  * The first parameter is pg_opclass, opened and suitably locked.  The second
- * parameter is the tuple from pg_opclass we want to modify.
+ * parameter is a copy of the tuple from pg_opclass we want to modify.
  */
 static void
 AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
index 76884e8..a84feee 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.33 2006/10/04 00:29:51 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.34 2006/12/23 00:43:09 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -64,8 +64,8 @@ DefineOperator(List *names, List *parameters)
        char       *oprName;
        Oid                     oprNamespace;
        AclResult       aclresult;
-       bool            canHash = false;        /* operator hashes */
        bool            canMerge = false;               /* operator merges */
+       bool            canHash = false;                /* operator hashes */
        List       *functionName = NIL;         /* function for operator */
        TypeName   *typeName1 = NULL;           /* first type name */
        TypeName   *typeName2 = NULL;           /* second type name */
@@ -75,10 +75,6 @@ DefineOperator(List *names, List *parameters)
        List       *negatorName = NIL;          /* optional negator operator name */
        List       *restrictionName = NIL;      /* optional restrict. sel. procedure */
        List       *joinName = NIL; /* optional join sel. procedure */
-       List       *leftSortName = NIL;         /* optional left sort operator */
-       List       *rightSortName = NIL;        /* optional right sort operator */
-       List       *ltCompareName = NIL;        /* optional < compare operator */
-       List       *gtCompareName = NIL;        /* optional > compare operator */
        ListCell   *pl;
 
        /* Convert list of names to a name and namespace */
@@ -127,14 +123,15 @@ DefineOperator(List *names, List *parameters)
                        canHash = defGetBoolean(defel);
                else if (pg_strcasecmp(defel->defname, "merges") == 0)
                        canMerge = defGetBoolean(defel);
+               /* These obsolete options are taken as meaning canMerge */
                else if (pg_strcasecmp(defel->defname, "sort1") == 0)
-                       leftSortName = defGetQualifiedName(defel);
+                       canMerge = true;
                else if (pg_strcasecmp(defel->defname, "sort2") == 0)
-                       rightSortName = defGetQualifiedName(defel);
+                       canMerge = true;
                else if (pg_strcasecmp(defel->defname, "ltcmp") == 0)
-                       ltCompareName = defGetQualifiedName(defel);
+                       canMerge = true;
                else if (pg_strcasecmp(defel->defname, "gtcmp") == 0)
-                       gtCompareName = defGetQualifiedName(defel);
+                       canMerge = true;
                else
                        ereport(WARNING,
                                        (errcode(ERRCODE_SYNTAX_ERROR),
@@ -157,26 +154,6 @@ DefineOperator(List *names, List *parameters)
                typeId2 = typenameTypeId(NULL, typeName2);
 
        /*
-        * If any of the mergejoin support operators were given, then canMerge is
-        * implicit.  If canMerge is specified or implicit, fill in default
-        * operator names for any missing mergejoin support operators.
-        */
-       if (leftSortName || rightSortName || ltCompareName || gtCompareName)
-               canMerge = true;
-
-       if (canMerge)
-       {
-               if (!leftSortName)
-                       leftSortName = list_make1(makeString("<"));
-               if (!rightSortName)
-                       rightSortName = list_make1(makeString("<"));
-               if (!ltCompareName)
-                       ltCompareName = list_make1(makeString("<"));
-               if (!gtCompareName)
-                       gtCompareName = list_make1(makeString(">"));
-       }
-
-       /*
         * now have OperatorCreate do all the work..
         */
        OperatorCreate(oprName,         /* operator name */
@@ -188,11 +165,8 @@ DefineOperator(List *names, List *parameters)
                                   negatorName, /* optional negator operator name */
                                   restrictionName,             /* optional restrict. sel. procedure */
                                   joinName,    /* optional join sel. procedure name */
-                                  canHash,             /* operator hashes */
-                                  leftSortName,        /* optional left sort operator */
-                                  rightSortName,               /* optional right sort operator */
-                                  ltCompareName,               /* optional < comparison op */
-                                  gtCompareName);              /* optional < comparison op */
+                                  canMerge,    /* operator merges */
+                                  canHash);    /* operator hashes */
 }
 
 
index ea80c4e..2a1116f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.206 2006/10/13 21:43:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.207 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4145,7 +4145,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
                 * generate a warning if not, since otherwise costly seqscans will be
                 * incurred to check FK validity.
                 */
-               if (!op_in_opclass(oprid(o), opclasses[i]))
+               if (!op_in_opfamily(oprid(o), get_opclass_family(opclasses[i])))
                        ereport(WARNING,
                                        (errmsg("foreign key constraint \"%s\" "
                                                        "will require costly sequential scans",
index 10b02b4..1e9865c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.200 2006/12/21 16:05:13 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.201 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3700,21 +3700,28 @@ ExecInitExpr(Expr *node, PlanState *parent)
                                        outlist = lappend(outlist, estate);
                                }
                                rstate->rargs = outlist;
-                               Assert(list_length(rcexpr->opclasses) == nopers);
+                               Assert(list_length(rcexpr->opfamilies) == nopers);
                                rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
                                i = 0;
-                               forboth(l, rcexpr->opnos, l2, rcexpr->opclasses)
+                               forboth(l, rcexpr->opnos, l2, rcexpr->opfamilies)
                                {
                                        Oid                     opno = lfirst_oid(l);
-                                       Oid                     opclass = lfirst_oid(l2);
+                                       Oid                     opfamily = lfirst_oid(l2);
                                        int                     strategy;
-                                       Oid                     subtype;
+                                       Oid                     lefttype;
+                                       Oid                     righttype;
                                        bool            recheck;
                                        Oid                     proc;
 
-                                       get_op_opclass_properties(opno, opclass,
-                                                                                         &strategy, &subtype, &recheck);
-                                       proc = get_opclass_proc(opclass, subtype, BTORDER_PROC);
+                                       get_op_opfamily_properties(opno, opfamily,
+                                                                                          &strategy,
+                                                                                          &lefttype,
+                                                                                          &righttype,
+                                                                                          &recheck);
+                                       proc = get_opfamily_proc(opfamily,
+                                                                                        lefttype,
+                                                                                        righttype,
+                                                                                        BTORDER_PROC);
 
                                        /*
                                         * If we enforced permissions checks on index support
index 9773f23..4371fc1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.117 2006/10/04 00:29:52 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.118 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -797,9 +797,10 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
                                int                     flags = SK_ROW_MEMBER;
                                Datum           scanvalue;
                                Oid                     opno;
-                               Oid                     opclass;
+                               Oid                     opfamily;
                                int                     op_strategy;
-                               Oid                     op_subtype;
+                               Oid                     op_lefttype;
+                               Oid                     op_righttype;
                                bool            op_recheck;
 
                                /*
@@ -857,15 +858,21 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
                                if (index->rd_rel->relam != BTREE_AM_OID ||
                                        varattno < 1 || varattno > index->rd_index->indnatts)
                                        elog(ERROR, "bogus RowCompare index qualification");
-                               opclass = index->rd_indclass->values[varattno - 1];
+                               opfamily = index->rd_opfamily[varattno - 1];
 
-                               get_op_opclass_properties(opno, opclass,
-                                                                        &op_strategy, &op_subtype, &op_recheck);
+                               get_op_opfamily_properties(opno, opfamily,
+                                                                                  &op_strategy,
+                                                                                  &op_lefttype,
+                                                                                  &op_righttype,
+                                                                                  &op_recheck);
 
                                if (op_strategy != rc->rctype)
                                        elog(ERROR, "RowCompare index qualification contains wrong operator");
 
-                               opfuncid = get_opclass_proc(opclass, op_subtype, BTORDER_PROC);
+                               opfuncid = get_opfamily_proc(opfamily,
+                                                                                        op_lefttype,
+                                                                                        op_righttype,
+                                                                                        BTORDER_PROC);
 
                                /*
                                 * initialize the subsidiary scan key's fields appropriately
@@ -874,7 +881,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
                                                                           flags,
                                                                           varattno,            /* attribute number */
                                                                           op_strategy,         /* op's strategy */
-                                                                          op_subtype,          /* strategy subtype */
+                                                                          op_righttype,        /* strategy subtype */
                                                                           opfuncid,            /* reg proc to use */
                                                                           scanvalue);          /* constant */
                                extra_scan_keys++;
index 8a9f6fe..9782492 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.82 2006/10/04 00:29:52 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.83 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  * Comparison strategies supported by MJCompare
  *
- * XXX eventually should extend these to support descending-order sorts.
+ * XXX eventually should extend MJCompare to support descending-order sorts.
  * There are some tricky issues however about being sure we are on the same
  * page as the underlying sort or index as to which end NULLs sort to.
  */
 typedef enum
 {
-       MERGEFUNC_LT,                           /* raw "<" operator */
-       MERGEFUNC_CMP                           /* -1 / 0 / 1 three-way comparator */
+       MERGEFUNC_CMP,                          /* -1 / 0 / 1 three-way comparator */
+       MERGEFUNC_REV_CMP                       /* same, reversing the sense of the result */
 } MergeFunctionKind;
 
 /* Runtime data for each mergejoin clause */
@@ -133,19 +133,10 @@ typedef struct MergeJoinClauseData
        bool            risnull;
 
        /*
-        * Remember whether mergejoin operator is strict (usually it will be).
-        * NOTE: if it's not strict, we still assume it cannot return true for one
-        * null and one non-null input.
-        */
-       bool            mergestrict;
-
-       /*
         * The comparison strategy in use, and the lookup info to let us call the
-        * needed comparison routines.  eqfinfo is the "=" operator itself.
-        * cmpfinfo is either the btree comparator or the "<" operator.
+        * btree comparison support function.
         */
        MergeFunctionKind cmpstrategy;
-       FmgrInfo        eqfinfo;
        FmgrInfo        cmpfinfo;
 } MergeJoinClauseData;
 
@@ -164,34 +155,51 @@ typedef struct MergeJoinClauseData
  * we will need at runtime.  Each struct essentially tells us how to compare
  * the two expressions from the original clause.
  *
- * The best, most efficient way to compare two expressions is to use a btree
- * comparison support routine, since that requires only one function call
- * per comparison.     Hence we try to find a btree opclass that matches the
- * mergejoinable operator.     If we cannot find one, we'll have to call both
- * the "=" and (often) the "<" operator for each comparison.
+ * In addition to the expressions themselves, the planner passes the btree
+ * opfamily OID and btree strategy number (BTLessStrategyNumber or
+ * BTGreaterStrategyNumber) that identify the intended merge semantics for
+ * each merge key.  The mergejoinable operator is an equality operator in
+ * this opfamily, and the two inputs are guaranteed to be ordered in either
+ * increasing or decreasing (respectively) order according to this opfamily.
+ * This allows us to obtain the needed comparison functions from the opfamily.
  */
 static MergeJoinClause
-MJExamineQuals(List *qualList, PlanState *parent)
+MJExamineQuals(List *mergeclauses, List *mergefamilies, List *mergestrategies,
+                          PlanState *parent)
 {
        MergeJoinClause clauses;
-       int                     nClauses = list_length(qualList);
+       int                     nClauses = list_length(mergeclauses);
        int                     iClause;
-       ListCell   *l;
+       ListCell   *cl;
+       ListCell   *cf;
+       ListCell   *cs;
 
        clauses = (MergeJoinClause) palloc0(nClauses * sizeof(MergeJoinClauseData));
 
        iClause = 0;
-       foreach(l, qualList)
+       cf = list_head(mergefamilies);
+       cs = list_head(mergestrategies);
+       foreach(cl, mergeclauses)
        {
-               OpExpr     *qual = (OpExpr *) lfirst(l);
+               OpExpr     *qual = (OpExpr *) lfirst(cl);
                MergeJoinClause clause = &clauses[iClause];
-               Oid                     ltop;
-               Oid                     gtop;
-               RegProcedure ltproc;
-               RegProcedure gtproc;
+               Oid                     opfamily;
+               StrategyNumber opstrategy;
+               int                     op_strategy;
+               Oid                     op_lefttype;
+               Oid                     op_righttype;
+               bool            op_recheck;
+               RegProcedure cmpproc;
                AclResult       aclresult;
-               CatCList   *catlist;
-               int                     i;
+
+               opfamily = lfirst_oid(cf);
+               cf = lnext(cf);
+               opstrategy = lfirst_int(cs);
+               cs = lnext(cs);
+
+               /* Later we'll support both ascending and descending sort... */
+               Assert(opstrategy == BTLessStrategyNumber);
+               clause->cmpstrategy = MERGEFUNC_CMP;
 
                if (!IsA(qual, OpExpr))
                        elog(ERROR, "mergejoin clause is not an OpExpr");
@@ -202,77 +210,30 @@ MJExamineQuals(List *qualList, PlanState *parent)
                clause->lexpr = ExecInitExpr((Expr *) linitial(qual->args), parent);
                clause->rexpr = ExecInitExpr((Expr *) lsecond(qual->args), parent);
 
-               /*
-                * Check permission to call the mergejoinable operator. For
-                * predictability, we check this even if we end up not using it.
-                */
-               aclresult = pg_proc_aclcheck(qual->opfuncid, GetUserId(), ACL_EXECUTE);
-               if (aclresult != ACLCHECK_OK)
-                       aclcheck_error(aclresult, ACL_KIND_PROC,
-                                                  get_func_name(qual->opfuncid));
-
-               /* Set up the fmgr lookup information */
-               fmgr_info(qual->opfuncid, &(clause->eqfinfo));
-
-               /* And remember strictness */
-               clause->mergestrict = clause->eqfinfo.fn_strict;
-
-               /*
-                * Lookup the comparison operators that go with the mergejoinable
-                * top-level operator.  (This will elog if the operator isn't
-                * mergejoinable, which would be the planner's mistake.)
-                */
-               op_mergejoin_crossops(qual->opno,
-                                                         &ltop,
-                                                         &gtop,
-                                                         &ltproc,
-                                                         &gtproc);
-
-               clause->cmpstrategy = MERGEFUNC_LT;
-
-               /*
-                * Look for a btree opclass including all three operators. This is
-                * much like SelectSortFunction except we insist on matching all the
-                * operators provided, and it can be a cross-type opclass.
-                *
-                * XXX for now, insist on forward sort so that NULLs can be counted on
-                * to be high.
-                */
-               catlist = SearchSysCacheList(AMOPOPID, 1,
-                                                                        ObjectIdGetDatum(qual->opno),
-                                                                        0, 0, 0);
-
-               for (i = 0; i < catlist->n_members; i++)
-               {
-                       HeapTuple       tuple = &catlist->members[i]->tuple;
-                       Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
-                       Oid                     opcid = aform->amopclaid;
-
-                       if (aform->amopstrategy != BTEqualStrategyNumber)
-                               continue;
-                       if (!opclass_is_btree(opcid))
-                               continue;
-                       if (get_op_opclass_strategy(ltop, opcid) == BTLessStrategyNumber &&
-                        get_op_opclass_strategy(gtop, opcid) == BTGreaterStrategyNumber)
-                       {
-                               clause->cmpstrategy = MERGEFUNC_CMP;
-                               ltproc = get_opclass_proc(opcid, aform->amopsubtype,
-                                                                                 BTORDER_PROC);
-                               Assert(RegProcedureIsValid(ltproc));
-                               break;                  /* done looking */
-                       }
-               }
-
-               ReleaseSysCacheList(catlist);
-
-               /* Check permission to call "<" operator or cmp function */
-               aclresult = pg_proc_aclcheck(ltproc, GetUserId(), ACL_EXECUTE);
+               /* Extract the operator's declared left/right datatypes */
+               get_op_opfamily_properties(qual->opno, opfamily,
+                                                                  &op_strategy,
+                                                                  &op_lefttype,
+                                                                  &op_righttype,
+                                                                  &op_recheck);
+               Assert(op_strategy == BTEqualStrategyNumber);
+               Assert(!op_recheck);
+
+               /* And get the matching support procedure (comparison function) */
+               cmpproc = get_opfamily_proc(opfamily,
+                                                                       op_lefttype,
+                                                                       op_righttype,
+                                                                       BTORDER_PROC);
+               Assert(RegProcedureIsValid(cmpproc));
+
+               /* Check permission to call cmp function */
+               aclresult = pg_proc_aclcheck(cmpproc, GetUserId(), ACL_EXECUTE);
                if (aclresult != ACLCHECK_OK)
                        aclcheck_error(aclresult, ACL_KIND_PROC,
-                                                  get_func_name(ltproc));
+                                                  get_func_name(cmpproc));
 
                /* Set up the fmgr lookup information */
-               fmgr_info(ltproc, &(clause->cmpfinfo));
+               fmgr_info(cmpproc, &(clause->cmpfinfo));
 
                iClause++;
        }
@@ -286,7 +247,7 @@ MJExamineQuals(List *qualList, PlanState *parent)
  * Compute the values of the mergejoined expressions for the current
  * outer tuple.  We also detect whether it's impossible for the current
  * outer tuple to match anything --- this is true if it yields a NULL
- * input for any strict mergejoin operator.
+ * input, since we assume mergejoin operators are strict.
  *
  * We evaluate the values in OuterEContext, which can be reset each
  * time we move to a new tuple.
@@ -311,7 +272,7 @@ MJEvalOuterValues(MergeJoinState *mergestate)
 
                clause->ldatum = ExecEvalExpr(clause->lexpr, econtext,
                                                                          &clause->lisnull, NULL);
-               if (clause->lisnull && clause->mergestrict)
+               if (clause->lisnull)
                        canmatch = false;
        }
 
@@ -347,7 +308,7 @@ MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
 
                clause->rdatum = ExecEvalExpr(clause->rexpr, econtext,
                                                                          &clause->risnull, NULL);
-               if (clause->risnull && clause->mergestrict)
+               if (clause->risnull)
                        canmatch = false;
        }
 
@@ -391,32 +352,11 @@ MJCompare(MergeJoinState *mergestate)
 
                /*
                 * Deal with null inputs.  We treat NULL as sorting after non-NULL.
-                *
-                * If both inputs are NULL, and the comparison function isn't strict,
-                * then we call it and check for a true result (this allows operators
-                * that behave like IS NOT DISTINCT to be mergejoinable). If the
-                * function is strict or returns false, we temporarily pretend NULL ==
-                * NULL and contine checking remaining columns.
                 */
                if (clause->lisnull)
                {
                        if (clause->risnull)
                        {
-                               if (!clause->eqfinfo.fn_strict)
-                               {
-                                       InitFunctionCallInfoData(fcinfo, &(clause->eqfinfo), 2,
-                                                                                        NULL, NULL);
-                                       fcinfo.arg[0] = clause->ldatum;
-                                       fcinfo.arg[1] = clause->rdatum;
-                                       fcinfo.argnull[0] = true;
-                                       fcinfo.argnull[1] = true;
-                                       fresult = FunctionCallInvoke(&fcinfo);
-                                       if (!fcinfo.isnull && DatumGetBool(fresult))
-                                       {
-                                               /* treat nulls as really equal */
-                                               continue;
-                                       }
-                               }
                                nulleqnull = true;
                                continue;
                        }
@@ -431,38 +371,26 @@ MJCompare(MergeJoinState *mergestate)
                        break;
                }
 
-               if (clause->cmpstrategy == MERGEFUNC_LT)
+               InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,
+                                                                NULL, NULL);
+               fcinfo.arg[0] = clause->ldatum;
+               fcinfo.arg[1] = clause->rdatum;
+               fcinfo.argnull[0] = false;
+               fcinfo.argnull[1] = false;
+               fresult = FunctionCallInvoke(&fcinfo);
+               if (fcinfo.isnull)
                {
-                       InitFunctionCallInfoData(fcinfo, &(clause->eqfinfo), 2,
-                                                                        NULL, NULL);
-                       fcinfo.arg[0] = clause->ldatum;
-                       fcinfo.arg[1] = clause->rdatum;
-                       fcinfo.argnull[0] = false;
-                       fcinfo.argnull[1] = false;
-                       fresult = FunctionCallInvoke(&fcinfo);
-                       if (fcinfo.isnull)
-                       {
-                               nulleqnull = true;
-                               continue;
-                       }
-                       else if (DatumGetBool(fresult))
-                       {
-                               /* equal */
-                               continue;
-                       }
-                       InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,
-                                                                        NULL, NULL);
-                       fcinfo.arg[0] = clause->ldatum;
-                       fcinfo.arg[1] = clause->rdatum;
-                       fcinfo.argnull[0] = false;
-                       fcinfo.argnull[1] = false;
-                       fresult = FunctionCallInvoke(&fcinfo);
-                       if (fcinfo.isnull)
-                       {
-                               nulleqnull = true;
-                               continue;
-                       }
-                       else if (DatumGetBool(fresult))
+                       nulleqnull = true;
+                       continue;
+               }
+               if (DatumGetInt32(fresult) == 0)
+               {
+                       /* equal */
+                       continue;
+               }
+               if (clause->cmpstrategy == MERGEFUNC_CMP)
+               {
+                       if (DatumGetInt32(fresult) < 0)
                        {
                                /* less than */
                                result = -1;
@@ -476,26 +404,9 @@ MJCompare(MergeJoinState *mergestate)
                        }
                }
                else
-                       /* must be MERGEFUNC_CMP */
                {
-                       InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,
-                                                                        NULL, NULL);
-                       fcinfo.arg[0] = clause->ldatum;
-                       fcinfo.arg[1] = clause->rdatum;
-                       fcinfo.argnull[0] = false;
-                       fcinfo.argnull[1] = false;
-                       fresult = FunctionCallInvoke(&fcinfo);
-                       if (fcinfo.isnull)
-                       {
-                               nulleqnull = true;
-                               continue;
-                       }
-                       else if (DatumGetInt32(fresult) == 0)
-                       {
-                               /* equal */
-                               continue;
-                       }
-                       else if (DatumGetInt32(fresult) < 0)
+                       /* reverse the sort order */
+                       if (DatumGetInt32(fresult) > 0)
                        {
                                /* less than */
                                result = -1;
@@ -1614,6 +1525,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
         */
        mergestate->mj_NumClauses = list_length(node->mergeclauses);
        mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
+                                                                                       node->mergefamilies,
+                                                                                       node->mergestrategies,
                                                                                        (PlanState *) mergestate);
 
        /*
index 3bb95b6..ca841cb 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.355 2006/12/21 16:05:13 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.356 2006/12/23 00:43:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -449,6 +449,8 @@ _copyMergeJoin(MergeJoin *from)
         * copy remainder of node
         */
        COPY_NODE_FIELD(mergeclauses);
+       COPY_NODE_FIELD(mergefamilies);
+       COPY_NODE_FIELD(mergestrategies);
 
        return newnode;
 }
@@ -1055,7 +1057,7 @@ _copyRowCompareExpr(RowCompareExpr *from)
 
        COPY_SCALAR_FIELD(rctype);
        COPY_NODE_FIELD(opnos);
-       COPY_NODE_FIELD(opclasses);
+       COPY_NODE_FIELD(opfamilies);
        COPY_NODE_FIELD(largs);
        COPY_NODE_FIELD(rargs);
 
@@ -1307,6 +1309,7 @@ _copyRestrictInfo(RestrictInfo *from)
        COPY_SCALAR_FIELD(mergejoinoperator);
        COPY_SCALAR_FIELD(left_sortop);
        COPY_SCALAR_FIELD(right_sortop);
+       COPY_SCALAR_FIELD(mergeopfamily);
 
        /*
         * Do not copy pathkeys, since they'd not be canonical in a copied query
@@ -2291,6 +2294,7 @@ _copyCreateOpClassStmt(CreateOpClassStmt *from)
        CreateOpClassStmt *newnode = makeNode(CreateOpClassStmt);
 
        COPY_NODE_FIELD(opclassname);
+       COPY_NODE_FIELD(opfamilyname);
        COPY_STRING_FIELD(amname);
        COPY_NODE_FIELD(datatype);
        COPY_NODE_FIELD(items);
index ef21e67..a7c4ef4 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.289 2006/12/21 16:05:13 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.290 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -428,7 +428,7 @@ _equalRowCompareExpr(RowCompareExpr *a, RowCompareExpr *b)
 {
        COMPARE_SCALAR_FIELD(rctype);
        COMPARE_NODE_FIELD(opnos);
-       COMPARE_NODE_FIELD(opclasses);
+       COMPARE_NODE_FIELD(opfamilies);
        COMPARE_NODE_FIELD(largs);
        COMPARE_NODE_FIELD(rargs);
 
@@ -1163,6 +1163,7 @@ static bool
 _equalCreateOpClassStmt(CreateOpClassStmt *a, CreateOpClassStmt *b)
 {
        COMPARE_NODE_FIELD(opclassname);
+       COMPARE_NODE_FIELD(opfamilyname);
        COMPARE_STRING_FIELD(amname);
        COMPARE_NODE_FIELD(datatype);
        COMPARE_NODE_FIELD(items);
index 5ddf60d..b18b698 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.287 2006/12/21 16:05:13 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.288 2006/12/23 00:43:10 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -442,6 +442,8 @@ _outMergeJoin(StringInfo str, MergeJoin *node)
        _outJoinPlanInfo(str, (Join *) node);
 
        WRITE_NODE_FIELD(mergeclauses);
+       WRITE_NODE_FIELD(mergefamilies);
+       WRITE_NODE_FIELD(mergestrategies);
 }
 
 static void
@@ -866,7 +868,7 @@ _outRowCompareExpr(StringInfo str, RowCompareExpr *node)
 
        WRITE_ENUM_FIELD(rctype, RowCompareType);
        WRITE_NODE_FIELD(opnos);
-       WRITE_NODE_FIELD(opclasses);
+       WRITE_NODE_FIELD(opfamilies);
        WRITE_NODE_FIELD(largs);
        WRITE_NODE_FIELD(rargs);
 }
@@ -1167,6 +1169,8 @@ _outMergePath(StringInfo str, MergePath *node)
        _outJoinPathInfo(str, (JoinPath *) node);
 
        WRITE_NODE_FIELD(path_mergeclauses);
+       WRITE_NODE_FIELD(path_mergefamilies);
+       WRITE_NODE_FIELD(path_mergestrategies);
        WRITE_NODE_FIELD(outersortkeys);
        WRITE_NODE_FIELD(innersortkeys);
 }
@@ -1281,6 +1285,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
        WRITE_OID_FIELD(mergejoinoperator);
        WRITE_OID_FIELD(left_sortop);
        WRITE_OID_FIELD(right_sortop);
+       WRITE_OID_FIELD(mergeopfamily);
        WRITE_NODE_FIELD(left_pathkey);
        WRITE_NODE_FIELD(right_pathkey);
        WRITE_OID_FIELD(hashjoinoperator);
index 689cef3..37b3943 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.197 2006/12/21 16:05:13 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.198 2006/12/23 00:43:10 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -672,7 +672,7 @@ _readRowCompareExpr(void)
 
        READ_ENUM_FIELD(rctype, RowCompareType);
        READ_NODE_FIELD(opnos);
-       READ_NODE_FIELD(opclasses);
+       READ_NODE_FIELD(opfamilies);
        READ_NODE_FIELD(largs);
        READ_NODE_FIELD(rargs);
 
index 7168564..fbcf7d2 100644 (file)
@@ -54,7 +54,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.170 2006/12/15 18:42:26 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.171 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1258,6 +1258,8 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
        Path       *outer_path = path->jpath.outerjoinpath;
        Path       *inner_path = path->jpath.innerjoinpath;
        List       *mergeclauses = path->path_mergeclauses;
+       List       *mergefamilies = path->path_mergefamilies;
+       List       *mergestrategies = path->path_mergestrategies;
        List       *outersortkeys = path->outersortkeys;
        List       *innersortkeys = path->innersortkeys;
        Cost            startup_cost = 0;
@@ -1347,13 +1349,16 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
         *
         * Since this calculation is somewhat expensive, and will be the same for
         * all mergejoin paths associated with the merge clause, we cache the
-        * results in the RestrictInfo node.
+        * results in the RestrictInfo node.  XXX that won't work anymore once
+        * we support multiple possible orderings!
         */
        if (mergeclauses && path->jpath.jointype != JOIN_FULL)
        {
                firstclause = (RestrictInfo *) linitial(mergeclauses);
                if (firstclause->left_mergescansel < 0) /* not computed yet? */
                        mergejoinscansel(root, (Node *) firstclause->clause,
+                                                        linitial_oid(mergefamilies),
+                                                        linitial_int(mergestrategies),
                                                         &firstclause->left_mergescansel,
                                                         &firstclause->right_mergescansel);
 
index b15affa..af081b8 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.212 2006/10/04 00:29:54 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.213 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,8 +19,8 @@
 
 #include "access/skey.h"
 #include "catalog/pg_am.h"
-#include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
 /*
  * DoneMatchingIndexKeys() - MACRO
  */
-#define DoneMatchingIndexKeys(classes) (classes[0] == InvalidOid)
+#define DoneMatchingIndexKeys(families)        (families[0] == InvalidOid)
 
-#define IsBooleanOpclass(opclass) \
-       ((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID)
+#define IsBooleanOpfamily(opfamily) \
+       ((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
 
 
 static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
@@ -61,15 +61,15 @@ static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel,
 static List *pull_indexpath_quals(Path *bitmapqual);
 static bool lists_intersect_ptr(List *list1, List *list2);
 static bool match_clause_to_indexcol(IndexOptInfo *index,
-                                                int indexcol, Oid opclass,
+                                                int indexcol, Oid opfamily,
                                                 RestrictInfo *rinfo,
                                                 Relids outer_relids,
                                                 SaOpControl saop_control);
-static bool is_indexable_operator(Oid expr_op, Oid opclass,
+static bool is_indexable_operator(Oid expr_op, Oid opfamily,
                                          bool indexkey_on_left);
 static bool match_rowcompare_to_indexcol(IndexOptInfo *index,
                                                         int indexcol,
-                                                        Oid opclass,
+                                                        Oid opfamily,
                                                         RowCompareExpr *clause,
                                                         Relids outer_relids);
 static Relids indexable_outerrelids(RelOptInfo *rel);
@@ -89,17 +89,17 @@ static bool match_index_to_query_keys(PlannerInfo *root,
                                                  List *ignorables);
 static bool match_boolean_index_clause(Node *clause, int indexcol,
                                                   IndexOptInfo *index);
-static bool match_special_index_operator(Expr *clause, Oid opclass,
+static bool match_special_index_operator(Expr *clause, Oid opfamily,
                                                         bool indexkey_on_left);
 static Expr *expand_boolean_index_clause(Node *clause, int indexcol,
                                                        IndexOptInfo *index);
-static List *expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass);
+static List *expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily);
 static RestrictInfo *expand_indexqual_rowcompare(RestrictInfo *rinfo,
                                                        IndexOptInfo *index,
                                                        int indexcol);
-static List *prefix_quals(Node *leftop, Oid opclass,
+static List *prefix_quals(Node *leftop, Oid opfamily,
                         Const *prefix, Pattern_Prefix_Status pstatus);
-static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass,
+static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily,
                                         Datum rightop);
 static Datum string_to_datum(const char *str, Oid datatype);
 static Const *string_to_const(const char *str, Oid datatype);
@@ -858,7 +858,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
        List       *clausegroup_list = NIL;
        bool            found_outer_clause = false;
        int                     indexcol = 0;
-       Oid                *classes = index->classlist;
+       Oid                *families = index->opfamily;
 
        *found_clause = false;          /* default result */
 
@@ -867,7 +867,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
 
        do
        {
-               Oid                     curClass = classes[0];
+               Oid                     curFamily = families[0];
                List       *clausegroup = NIL;
                ListCell   *l;
 
@@ -879,7 +879,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
                        Assert(IsA(rinfo, RestrictInfo));
                        if (match_clause_to_indexcol(index,
                                                                                 indexcol,
-                                                                                curClass,
+                                                                                curFamily,
                                                                                 rinfo,
                                                                                 outer_relids,
                                                                                 saop_control))
@@ -899,7 +899,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
                        Assert(IsA(rinfo, RestrictInfo));
                        if (match_clause_to_indexcol(index,
                                                                                 indexcol,
-                                                                                curClass,
+                                                                                curFamily,
                                                                                 rinfo,
                                                                                 outer_relids,
                                                                                 saop_control))
@@ -918,9 +918,9 @@ group_clauses_by_indexkey(IndexOptInfo *index,
                clausegroup_list = lappend(clausegroup_list, clausegroup);
 
                indexcol++;
-               classes++;
+               families++;
 
-       } while (!DoneMatchingIndexKeys(classes));
+       } while (!DoneMatchingIndexKeys(families));
 
        if (!*found_clause && !found_outer_clause)
                return NIL;                             /* no indexable clauses anywhere */
@@ -937,7 +937,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
  *
  *       (1)  must be in the form (indexkey op const) or (const op indexkey);
  *                and
- *       (2)  must contain an operator which is in the same class as the index
+ *       (2)  must contain an operator which is in the same family as the index
  *                operator for this column, or is a "special" operator as recognized
  *                by match_special_index_operator().
  *
@@ -978,7 +978,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
  *
  * 'index' is the index of interest.
  * 'indexcol' is a column number of 'index' (counting from 0).
- * 'opclass' is the corresponding operator class.
+ * 'opfamily' is the corresponding operator family.
  * 'rinfo' is the clause to be tested (as a RestrictInfo node).
  * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used.
  *
@@ -990,7 +990,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
 static bool
 match_clause_to_indexcol(IndexOptInfo *index,
                                                 int indexcol,
-                                                Oid opclass,
+                                                Oid opfamily,
                                                 RestrictInfo *rinfo,
                                                 Relids outer_relids,
                                                 SaOpControl saop_control)
@@ -1013,7 +1013,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
                return false;
 
        /* First check for boolean-index cases. */
-       if (IsBooleanOpclass(opclass))
+       if (IsBooleanOpfamily(opfamily))
        {
                if (match_boolean_index_clause((Node *) clause, indexcol, index))
                        return true;
@@ -1052,7 +1052,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
        }
        else if (clause && IsA(clause, RowCompareExpr))
        {
-               return match_rowcompare_to_indexcol(index, indexcol, opclass,
+               return match_rowcompare_to_indexcol(index, indexcol, opfamily,
                                                                                        (RowCompareExpr *) clause,
                                                                                        outer_relids);
        }
@@ -1067,15 +1067,15 @@ match_clause_to_indexcol(IndexOptInfo *index,
                bms_is_subset(right_relids, outer_relids) &&
                !contain_volatile_functions(rightop))
        {
-               if (is_indexable_operator(expr_op, opclass, true))
+               if (is_indexable_operator(expr_op, opfamily, true))
                        return true;
 
                /*
-                * If we didn't find a member of the index's opclass, see whether it
+                * If we didn't find a member of the index's opfamily, see whether it
                 * is a "special" indexable operator.
                 */
                if (plain_op &&
-                       match_special_index_operator(clause, opclass, true))
+                       match_special_index_operator(clause, opfamily, true))
                        return true;
                return false;
        }
@@ -1085,14 +1085,14 @@ match_clause_to_indexcol(IndexOptInfo *index,
                bms_is_subset(left_relids, outer_relids) &&
                !contain_volatile_functions(leftop))
        {
-               if (is_indexable_operator(expr_op, opclass, false))
+               if (is_indexable_operator(expr_op, opfamily, false))
                        return true;
 
                /*
-                * If we didn't find a member of the index's opclass, see whether it
+                * If we didn't find a member of the index's opfamily, see whether it
                 * is a "special" indexable operator.
                 */
-               if (match_special_index_operator(clause, opclass, false))
+               if (match_special_index_operator(clause, opfamily, false))
                        return true;
                return false;
        }
@@ -1102,14 +1102,14 @@ match_clause_to_indexcol(IndexOptInfo *index,
 
 /*
  * is_indexable_operator
- *       Does the operator match the specified index opclass?
+ *       Does the operator match the specified index opfamily?
  *
  * If the indexkey is on the right, what we actually want to know
  * is whether the operator has a commutator operator that matches
- * the opclass.
+ * the opfamily.
  */
 static bool
-is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left)
+is_indexable_operator(Oid expr_op, Oid opfamily, bool indexkey_on_left)
 {
        /* Get the commuted operator if necessary */
        if (!indexkey_on_left)
@@ -1119,8 +1119,8 @@ is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left)
                        return false;
        }
 
-       /* OK if the (commuted) operator is a member of the index's opclass */
-       return op_in_opclass(expr_op, opclass);
+       /* OK if the (commuted) operator is a member of the index's opfamily */
+       return op_in_opfamily(expr_op, opfamily);
 }
 
 /*
@@ -1131,7 +1131,7 @@ is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left)
 static bool
 match_rowcompare_to_indexcol(IndexOptInfo *index,
                                                         int indexcol,
-                                                        Oid opclass,
+                                                        Oid opfamily,
                                                         RowCompareExpr *clause,
                                                         Relids outer_relids)
 {
@@ -1144,13 +1144,14 @@ match_rowcompare_to_indexcol(IndexOptInfo *index,
                return false;
 
        /*
-        * We could do the matching on the basis of insisting that the opclass
-        * shown in the RowCompareExpr be the same as the index column's opclass,
-        * but that does not work well for cross-type comparisons (the opclass
-        * could be for the other datatype).  Also it would fail to handle indexes
-        * using reverse-sort opclasses.  Instead, match if the operator listed in
-        * the RowCompareExpr is the < <= > or >= member of the index opclass
-        * (after commutation, if the indexkey is on the right).
+        * We could do the matching on the basis of insisting that the opfamily
+        * shown in the RowCompareExpr be the same as the index column's opfamily,
+        * but that could fail in the presence of reverse-sort opfamilies: it'd
+        * be a matter of chance whether RowCompareExpr had picked the forward
+        * or reverse-sort family.  So look only at the operator, and match
+        * if it is a member of the index's opfamily (after commutation, if the
+        * indexkey is on the right).  We'll worry later about whether any
+        * additional operators are matchable to the index.
         */
        leftop = (Node *) linitial(clause->largs);
        rightop = (Node *) linitial(clause->rargs);
@@ -1177,8 +1178,8 @@ match_rowcompare_to_indexcol(IndexOptInfo *index,
        else
                return false;
 
-       /* We're good if the operator is the right type of opclass member */
-       switch (get_op_opclass_strategy(expr_op, opclass))
+       /* We're good if the operator is the right type of opfamily member */
+       switch (get_op_opfamily_strategy(expr_op, opfamily))
        {
                case BTLessStrategyNumber:
                case BTLessEqualStrategyNumber:
@@ -1316,23 +1317,23 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids)
        {
                IndexOptInfo *index = (IndexOptInfo *) lfirst(l);
                int                     indexcol = 0;
-               Oid                *classes = index->classlist;
+               Oid                *families = index->opfamily;
 
                do
                {
-                       Oid                     curClass = classes[0];
+                       Oid                     curFamily = families[0];
 
                        if (match_clause_to_indexcol(index,
                                                                                 indexcol,
-                                                                                curClass,
+                                                                                curFamily,
                                                                                 rinfo,
                                                                                 outer_relids,
                                                                                 SAOP_ALLOW))
                                return true;
 
                        indexcol++;
-                       classes++;
-               } while (!DoneMatchingIndexKeys(classes));
+                       families++;
+               } while (!DoneMatchingIndexKeys(families));
        }
 
        return false;
@@ -1601,11 +1602,11 @@ find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
  * Note: it would be possible to similarly ignore useless ORDER BY items;
  * that is, an index on just y could be considered to match the ordering of
  *             ... WHERE x = 42 ORDER BY x, y;
- * But proving that this is safe would require finding a btree opclass
+ * But proving that this is safe would require finding a btree opfamily
  * containing both the = operator and the < or > operator in the ORDER BY
  * item.  That's significantly more expensive than what we do here, since
  * we'd have to look at restriction clauses unrelated to the current index
- * and search for opclasses without any hint from the index.  The practical
+ * and search for opfamilies without any hint from the index.  The practical
  * use-cases seem to be mostly covered by ignoring index columns, so that's
  * all we do for now.
  *
@@ -1627,7 +1628,7 @@ match_variant_ordering(PlannerInfo *root,
 
        /*
         * Forget the whole thing if not a btree index; our check for ignorable
-        * columns assumes we are dealing with btree opclasses.  (It'd be possible
+        * columns assumes we are dealing with btree opfamilies.  (It'd be possible
         * to factor out just the try for backwards indexscan, but considering
         * that we presently have no orderable indexes except btrees anyway, it's
         * hardly worth contorting this code for that case.)
@@ -1685,7 +1686,7 @@ identify_ignorable_ordering_cols(PlannerInfo *root,
        foreach(l, restrictclauses)
        {
                List       *sublist = (List *) lfirst(l);
-               Oid                     opclass = index->classlist[indexcol];
+               Oid                     opfamily = index->opfamily[indexcol];
                ListCell   *l2;
 
                foreach(l2, sublist)
@@ -1698,7 +1699,7 @@ identify_ignorable_ordering_cols(PlannerInfo *root,
                        bool            ispc;
 
                        /* First check for boolean-index cases. */
-                       if (IsBooleanOpclass(opclass))
+                       if (IsBooleanOpfamily(opfamily))
                        {
                                if (match_boolean_index_clause((Node *) clause, indexcol,
                                                                                           index))
@@ -1729,18 +1730,18 @@ identify_ignorable_ordering_cols(PlannerInfo *root,
                        {
                                Assert(match_index_to_operand(lsecond(clause->args), indexcol,
                                                                                          index));
-                               /* Must flip operator to get the opclass member */
+                               /* Must flip operator to get the opfamily member */
                                clause_op = get_commutator(clause_op);
                                varonleft = false;
                        }
                        if (!OidIsValid(clause_op))
                                continue;               /* ignore non match, per next comment */
-                       op_strategy = get_op_opclass_strategy(clause_op, opclass);
+                       op_strategy = get_op_opfamily_strategy(clause_op, opfamily);
 
                        /*
                         * You might expect to see Assert(op_strategy != 0) here, but you
                         * won't: the clause might contain a special indexable operator
-                        * rather than an ordinary opclass member.      Currently none of the
+                        * rather than an ordinary opfamily member.     Currently none of the
                         * special operators are very likely to expand to an equality
                         * operator; we do not bother to check, but just assume no match.
                         */
@@ -1968,7 +1969,7 @@ match_index_to_operand(Node *operand,
  *
  * match_special_index_operator() is just an auxiliary function for
  * match_clause_to_indexcol(); after the latter fails to recognize a
- * restriction opclause's operator as a member of an index's opclass,
+ * restriction opclause's operator as a member of an index's opfamily,
  * it asks match_special_index_operator() whether the clause should be
  * considered an indexqual anyway.
  *
@@ -1978,7 +1979,7 @@ match_index_to_operand(Node *operand,
  * expand_indexqual_conditions() converts a list of lists of RestrictInfo
  * nodes (with implicit AND semantics across list elements) into
  * a list of clauses that the executor can actually handle.  For operators
- * that are members of the index's opclass this transformation is a no-op,
+ * that are members of the index's opfamily this transformation is a no-op,
  * but clauses recognized by match_special_index_operator() or
  * match_boolean_index_clause() must be converted into one or more "regular"
  * indexqual conditions.
@@ -1989,8 +1990,8 @@ match_index_to_operand(Node *operand,
  * match_boolean_index_clause
  *       Recognize restriction clauses that can be matched to a boolean index.
  *
- * This should be called only when IsBooleanOpclass() recognizes the
- * index's operator class.  We check to see if the clause matches the
+ * This should be called only when IsBooleanOpfamily() recognizes the
+ * index's operator family.  We check to see if the clause matches the
  * index's key.
  */
 static bool
@@ -2034,11 +2035,11 @@ match_boolean_index_clause(Node *clause,
  *
  * The given clause is already known to be a binary opclause having
  * the form (indexkey OP pseudoconst) or (pseudoconst OP indexkey),
- * but the OP proved not to be one of the index's opclass operators.
+ * but the OP proved not to be one of the index's opfamily operators.
  * Return 'true' if we can do something with it anyway.
  */
 static bool
-match_special_index_operator(Expr *clause, Oid opclass,
+match_special_index_operator(Expr *clause, Oid opfamily,
                                                         bool indexkey_on_left)
 {
        bool            isIndexable = false;
@@ -2122,12 +2123,12 @@ match_special_index_operator(Expr *clause, Oid opclass,
                return false;
 
        /*
-        * Must also check that index's opclass supports the operators we will
+        * Must also check that index's opfamily supports the operators we will
         * want to apply.  (A hash index, for example, will not support ">=".)
         * Currently, only btree supports the operators we need.
         *
-        * We insist on the opclass being the specific one we expect, else we'd do
-        * the wrong thing if someone were to make a reverse-sort opclass with the
+        * We insist on the opfamily being the specific one we expect, else we'd do
+        * the wrong thing if someone were to make a reverse-sort opfamily with the
         * same operators.
         */
        switch (expr_op)
@@ -2136,12 +2137,9 @@ match_special_index_operator(Expr *clause, Oid opclass,
                case OID_TEXT_ICLIKE_OP:
                case OID_TEXT_REGEXEQ_OP:
                case OID_TEXT_ICREGEXEQ_OP:
-                       /* text operators will be used for varchar inputs, too */
                        isIndexable =
-                               (opclass == TEXT_PATTERN_BTREE_OPS_OID) ||
-                               (opclass == TEXT_BTREE_OPS_OID && lc_collate_is_c()) ||
-                               (opclass == VARCHAR_PATTERN_BTREE_OPS_OID) ||
-                               (opclass == VARCHAR_BTREE_OPS_OID && lc_collate_is_c());
+                               (opfamily == TEXT_PATTERN_BTREE_FAM_OID) ||
+                               (opfamily == TEXT_BTREE_FAM_OID && lc_collate_is_c());
                        break;
 
                case OID_BPCHAR_LIKE_OP:
@@ -2149,8 +2147,8 @@ match_special_index_operator(Expr *clause, Oid opclass,
                case OID_BPCHAR_REGEXEQ_OP:
                case OID_BPCHAR_ICREGEXEQ_OP:
                        isIndexable =
-                               (opclass == BPCHAR_PATTERN_BTREE_OPS_OID) ||
-                               (opclass == BPCHAR_BTREE_OPS_OID && lc_collate_is_c());
+                               (opfamily == BPCHAR_PATTERN_BTREE_FAM_OID) ||
+                               (opfamily == BPCHAR_BTREE_FAM_OID && lc_collate_is_c());
                        break;
 
                case OID_NAME_LIKE_OP:
@@ -2158,18 +2156,17 @@ match_special_index_operator(Expr *clause, Oid opclass,
                case OID_NAME_REGEXEQ_OP:
                case OID_NAME_ICREGEXEQ_OP:
                        isIndexable =
-                               (opclass == NAME_PATTERN_BTREE_OPS_OID) ||
-                               (opclass == NAME_BTREE_OPS_OID && lc_collate_is_c());
+                               (opfamily == NAME_PATTERN_BTREE_FAM_OID) ||
+                               (opfamily == NAME_BTREE_FAM_OID && lc_collate_is_c());
                        break;
 
                case OID_BYTEA_LIKE_OP:
-                       isIndexable = (opclass == BYTEA_BTREE_OPS_OID);
+                       isIndexable = (opfamily == BYTEA_BTREE_FAM_OID);
                        break;
 
                case OID_INET_SUB_OP:
                case OID_INET_SUBEQ_OP:
-                       isIndexable = (opclass == INET_BTREE_OPS_OID ||
-                                                  opclass == CIDR_BTREE_OPS_OID);
+                       isIndexable = (opfamily == NETWORK_BTREE_FAM_OID);
                        break;
        }
 
@@ -2180,7 +2177,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
  * expand_indexqual_conditions
  *       Given a list of sublists of RestrictInfo nodes, produce a flat list
  *       of index qual clauses.  Standard qual clauses (those in the index's
- *       opclass) are passed through unchanged.  Boolean clauses and "special"
+ *       opfamily) are passed through unchanged.  Boolean clauses and "special"
  *       index operators are expanded into clauses that the indexscan machinery
  *       will know what to do with.  RowCompare clauses are simplified if
  *       necessary to create a clause that is fully checkable by the index.
@@ -2196,7 +2193,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
        List       *resultquals = NIL;
        ListCell   *clausegroup_item;
        int                     indexcol = 0;
-       Oid                *classes = index->classlist;
+       Oid                *families = index->opfamily;
 
        if (clausegroups == NIL)
                return NIL;
@@ -2204,7 +2201,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
        clausegroup_item = list_head(clausegroups);
        do
        {
-               Oid                     curClass = classes[0];
+               Oid                     curFamily = families[0];
                ListCell   *l;
 
                foreach(l, (List *) lfirst(clausegroup_item))
@@ -2213,7 +2210,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
                        Expr       *clause = rinfo->clause;
 
                        /* First check for boolean cases */
-                       if (IsBooleanOpclass(curClass))
+                       if (IsBooleanOpfamily(curFamily))
                        {
                                Expr       *boolqual;
 
@@ -2240,7 +2237,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
                        {
                                resultquals = list_concat(resultquals,
                                                                                  expand_indexqual_opclause(rinfo,
-                                                                                                                                 curClass));
+                                                                                                                                 curFamily));
                        }
                        else if (IsA(clause, ScalarArrayOpExpr))
                        {
@@ -2262,8 +2259,8 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
                clausegroup_item = lnext(clausegroup_item);
 
                indexcol++;
-               classes++;
-       } while (clausegroup_item != NULL && !DoneMatchingIndexKeys(classes));
+               families++;
+       } while (clausegroup_item != NULL && !DoneMatchingIndexKeys(families));
 
        Assert(clausegroup_item == NULL);       /* else more groups than indexkeys */
 
@@ -2337,7 +2334,7 @@ expand_boolean_index_clause(Node *clause,
  * The input is a single RestrictInfo, the output a list of RestrictInfos
  */
 static List *
-expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
+expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily)
 {
        Expr       *clause = rinfo->clause;
 
@@ -2354,7 +2351,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
        switch (expr_op)
        {
                        /*
-                        * LIKE and regex operators are not members of any index opclass,
+                        * LIKE and regex operators are not members of any index opfamily,
                         * so if we find one in an indexqual list we can assume that it
                         * was accepted by match_special_index_operator().
                         */
@@ -2364,7 +2361,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
                case OID_BYTEA_LIKE_OP:
                        pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like,
                                                                                   &prefix, &rest);
-                       result = prefix_quals(leftop, opclass, prefix, pstatus);
+                       result = prefix_quals(leftop, opfamily, prefix, pstatus);
                        break;
 
                case OID_TEXT_ICLIKE_OP:
@@ -2373,7 +2370,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
                        /* the right-hand const is type text for all of these */
                        pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
                                                                                   &prefix, &rest);
-                       result = prefix_quals(leftop, opclass, prefix, pstatus);
+                       result = prefix_quals(leftop, opfamily, prefix, pstatus);
                        break;
 
                case OID_TEXT_REGEXEQ_OP:
@@ -2382,7 +2379,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
                        /* the right-hand const is type text for all of these */
                        pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex,
                                                                                   &prefix, &rest);
-                       result = prefix_quals(leftop, opclass, prefix, pstatus);
+                       result = prefix_quals(leftop, opfamily, prefix, pstatus);
                        break;
 
                case OID_TEXT_ICREGEXEQ_OP:
@@ -2391,12 +2388,12 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
                        /* the right-hand const is type text for all of these */
                        pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
                                                                                   &prefix, &rest);
-                       result = prefix_quals(leftop, opclass, prefix, pstatus);
+                       result = prefix_quals(leftop, opfamily, prefix, pstatus);
                        break;
 
                case OID_INET_SUB_OP:
                case OID_INET_SUBEQ_OP:
-                       result = network_prefix_quals(leftop, expr_op, opclass,
+                       result = network_prefix_quals(leftop, expr_op, opfamily,
                                                                                  patt->constvalue);
                        break;
 
@@ -2416,7 +2413,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
  * the specified column of the index.  We can use additional columns of the
  * row comparison as index qualifications, so long as they match the index
  * in the "same direction", ie, the indexkeys are all on the same side of the
- * clause and the operators are all the same-type members of the opclasses.
+ * clause and the operators are all the same-type members of the opfamilies.
  * If all the columns of the RowCompareExpr match in this way, we just use it
  * as-is.  Otherwise, we build a shortened RowCompareExpr (if more than one
  * column matches) or a simple OpExpr (if the first-column match is all
@@ -2433,12 +2430,14 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
        RowCompareExpr *clause = (RowCompareExpr *) rinfo->clause;
        bool            var_on_left;
        int                     op_strategy;
-       Oid                     op_subtype;
+       Oid                     op_lefttype;
+       Oid                     op_righttype;
        bool            op_recheck;
        int                     matching_cols;
        Oid                     expr_op;
-       List       *opclasses;
-       List       *subtypes;
+       List       *opfamilies;
+       List       *lefttypes;
+       List       *righttypes;
        List       *new_ops;
        ListCell   *largs_cell;
        ListCell   *rargs_cell;
@@ -2453,11 +2452,15 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
        expr_op = linitial_oid(clause->opnos);
        if (!var_on_left)
                expr_op = get_commutator(expr_op);
-       get_op_opclass_properties(expr_op, index->classlist[indexcol],
-                                                         &op_strategy, &op_subtype, &op_recheck);
-       /* Build lists of the opclasses and operator subtypes in case needed */
-       opclasses = list_make1_oid(index->classlist[indexcol]);
-       subtypes = list_make1_oid(op_subtype);
+       get_op_opfamily_properties(expr_op, index->opfamily[indexcol],
+                                                          &op_strategy,
+                                                          &op_lefttype,
+                                                          &op_righttype,
+                                                          &op_recheck);
+       /* Build lists of the opfamilies and operator datatypes in case needed */
+       opfamilies = list_make1_oid(index->opfamily[indexcol]);
+       lefttypes = list_make1_oid(op_lefttype);
+       righttypes = list_make1_oid(op_righttype);
 
        /*
         * See how many of the remaining columns match some index column in the
@@ -2513,15 +2516,19 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
                        break;                          /* no match found */
 
                /* Now, do we have the right operator for this column? */
-               if (get_op_opclass_strategy(expr_op, index->classlist[i])
+               if (get_op_opfamily_strategy(expr_op, index->opfamily[i])
                        != op_strategy)
                        break;
 
-               /* Add opclass and subtype to lists */
-               get_op_opclass_properties(expr_op, index->classlist[i],
-                                                                 &op_strategy, &op_subtype, &op_recheck);
-               opclasses = lappend_oid(opclasses, index->classlist[i]);
-               subtypes = lappend_oid(subtypes, op_subtype);
+               /* Add opfamily and datatypes to lists */
+               get_op_opfamily_properties(expr_op, index->opfamily[i],
+                                                                  &op_strategy,
+                                                                  &op_lefttype,
+                                                                  &op_righttype,
+                                                                  &op_recheck);
+               opfamilies = lappend_oid(opfamilies, index->opfamily[i]);
+               lefttypes = lappend_oid(lefttypes, op_lefttype);
+               righttypes = lappend_oid(righttypes, op_righttype);
 
                /* This column matches, keep scanning */
                matching_cols++;
@@ -2547,8 +2554,9 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
        }
        else
        {
-               ListCell   *opclasses_cell;
-               ListCell   *subtypes_cell;
+               ListCell   *opfamilies_cell;
+               ListCell   *lefttypes_cell;
+               ListCell   *righttypes_cell;
 
                if (op_strategy == BTLessStrategyNumber)
                        op_strategy = BTLessEqualStrategyNumber;
@@ -2557,23 +2565,30 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
                else
                        elog(ERROR, "unexpected strategy number %d", op_strategy);
                new_ops = NIL;
-               forboth(opclasses_cell, opclasses, subtypes_cell, subtypes)
+               lefttypes_cell = list_head(lefttypes);
+               righttypes_cell = list_head(righttypes);
+               foreach(opfamilies_cell, opfamilies)
                {
-                       expr_op = get_opclass_member(lfirst_oid(opclasses_cell),
-                                                                                lfirst_oid(subtypes_cell),
-                                                                                op_strategy);
+                       Oid             opfam = lfirst_oid(opfamilies_cell);
+                       Oid             lefttype = lfirst_oid(lefttypes_cell);
+                       Oid             righttype = lfirst_oid(righttypes_cell);
+
+                       expr_op = get_opfamily_member(opfam, lefttype, righttype,
+                                                                                 op_strategy);
                        if (!OidIsValid(expr_op))       /* should not happen */
-                               elog(ERROR, "could not find member %d of opclass %u",
-                                        op_strategy, lfirst_oid(opclasses_cell));
+                               elog(ERROR, "could not find member %d(%u,%u) of opfamily %u",
+                                        op_strategy, lefttype, righttype, opfam);
                        if (!var_on_left)
                        {
                                expr_op = get_commutator(expr_op);
                                if (!OidIsValid(expr_op))               /* should not happen */
-                                       elog(ERROR, "could not find commutator of member %d of opclass %u",
-                                                op_strategy, lfirst_oid(opclasses_cell));
+                                       elog(ERROR, "could not find commutator of member %d(%u,%u) of opfamily %u",
+                                                op_strategy, lefttype, righttype, opfam);
                        }
                        new_ops = lappend_oid(new_ops, expr_op);
                }
+               lefttypes_cell = lnext(lefttypes_cell);
+               righttypes_cell = lnext(righttypes_cell);
        }
 
        /* If we have more than one matching col, create a subset rowcompare */
@@ -2587,8 +2602,8 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
                        rc->rctype = (op_strategy == BTLessEqualStrategyNumber) ?
                                ROWCOMPARE_GE : ROWCOMPARE_LE;
                rc->opnos = new_ops;
-               rc->opclasses = list_truncate(list_copy(clause->opclasses),
-                                                                         matching_cols);
+               rc->opfamilies = list_truncate(list_copy(clause->opfamilies),
+                                                                          matching_cols);
                rc->largs = list_truncate((List *) copyObject(clause->largs),
                                                                  matching_cols);
                rc->rargs = list_truncate((List *) copyObject(clause->rargs),
@@ -2608,12 +2623,12 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
 
 /*
  * Given a fixed prefix that all the "leftop" values must have,
- * generate suitable indexqual condition(s).  opclass is the index
- * operator class; we use it to deduce the appropriate comparison
+ * generate suitable indexqual condition(s).  opfamily is the index
+ * operator family; we use it to deduce the appropriate comparison
  * operators and operand datatypes.
  */
 static List *
-prefix_quals(Node *leftop, Oid opclass,
+prefix_quals(Node *leftop, Oid opfamily,
                         Const *prefix_const, Pattern_Prefix_Status pstatus)
 {
        List       *result;
@@ -2624,35 +2639,30 @@ prefix_quals(Node *leftop, Oid opclass,
 
        Assert(pstatus != Pattern_Prefix_None);
 
-       switch (opclass)
+       switch (opfamily)
        {
-               case TEXT_BTREE_OPS_OID:
-               case TEXT_PATTERN_BTREE_OPS_OID:
+               case TEXT_BTREE_FAM_OID:
+               case TEXT_PATTERN_BTREE_FAM_OID:
                        datatype = TEXTOID;
                        break;
 
-               case VARCHAR_BTREE_OPS_OID:
-               case VARCHAR_PATTERN_BTREE_OPS_OID:
-                       datatype = VARCHAROID;
-                       break;
-
-               case BPCHAR_BTREE_OPS_OID:
-               case BPCHAR_PATTERN_BTREE_OPS_OID:
+               case BPCHAR_BTREE_FAM_OID:
+               case BPCHAR_PATTERN_BTREE_FAM_OID:
                        datatype = BPCHAROID;
                        break;
 
-               case NAME_BTREE_OPS_OID:
-               case NAME_PATTERN_BTREE_OPS_OID:
+               case NAME_BTREE_FAM_OID:
+               case NAME_PATTERN_BTREE_FAM_OID:
                        datatype = NAMEOID;
                        break;
 
-               case BYTEA_BTREE_OPS_OID:
+               case BYTEA_BTREE_FAM_OID:
                        datatype = BYTEAOID;
                        break;
 
                default:
                        /* shouldn't get here */
-                       elog(ERROR, "unexpected opclass: %u", opclass);
+                       elog(ERROR, "unexpected opfamily: %u", opfamily);
                        return NIL;
        }
 
@@ -2688,10 +2698,10 @@ prefix_quals(Node *leftop, Oid opclass,
         */
        if (pstatus == Pattern_Prefix_Exact)
        {
-               oproid = get_opclass_member(opclass, InvalidOid,
-                                                                       BTEqualStrategyNumber);
+               oproid = get_opfamily_member(opfamily, datatype, datatype,
+                                                                        BTEqualStrategyNumber);
                if (oproid == InvalidOid)
-                       elog(ERROR, "no = operator for opclass %u", opclass);
+                       elog(ERROR, "no = operator for opfamily %u", opfamily);
                expr = make_opclause(oproid, BOOLOID, false,
                                                         (Expr *) leftop, (Expr *) prefix_const);
                result = list_make1(make_restrictinfo(expr, true, false, false, NULL));
@@ -2703,10 +2713,10 @@ prefix_quals(Node *leftop, Oid opclass,
         *
         * We can always say "x >= prefix".
         */
-       oproid = get_opclass_member(opclass, InvalidOid,
-                                                               BTGreaterEqualStrategyNumber);
+       oproid = get_opfamily_member(opfamily, datatype, datatype,
+                                                                BTGreaterEqualStrategyNumber);
        if (oproid == InvalidOid)
-               elog(ERROR, "no >= operator for opclass %u", opclass);
+               elog(ERROR, "no >= operator for opfamily %u", opfamily);
        expr = make_opclause(oproid, BOOLOID, false,
                                                 (Expr *) leftop, (Expr *) prefix_const);
        result = list_make1(make_restrictinfo(expr, true, false, false, NULL));
@@ -2719,10 +2729,10 @@ prefix_quals(Node *leftop, Oid opclass,
        greaterstr = make_greater_string(prefix_const);
        if (greaterstr)
        {
-               oproid = get_opclass_member(opclass, InvalidOid,
-                                                                       BTLessStrategyNumber);
+               oproid = get_opfamily_member(opfamily, datatype, datatype,
+                                                                        BTLessStrategyNumber);
                if (oproid == InvalidOid)
-                       elog(ERROR, "no < operator for opclass %u", opclass);
+                       elog(ERROR, "no < operator for opfamily %u", opfamily);
                expr = make_opclause(oproid, BOOLOID, false,
                                                         (Expr *) leftop, (Expr *) greaterstr);
                result = lappend(result,
@@ -2733,12 +2743,12 @@ prefix_quals(Node *leftop, Oid opclass,
 }
 
 /*
- * Given a leftop and a rightop, and a inet-class sup/sub operator,
+ * Given a leftop and a rightop, and a inet-family sup/sub operator,
  * generate suitable indexqual condition(s).  expr_op is the original
- * operator, and opclass is the index opclass.
+ * operator, and opfamily is the index opfamily.
  */
 static List *
-network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
+network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
 {
        bool            is_eq;
        Oid                     datatype;
@@ -2770,17 +2780,17 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
         */
        if (is_eq)
        {
-               opr1oid = get_opclass_member(opclass, InvalidOid,
-                                                                        BTGreaterEqualStrategyNumber);
+               opr1oid = get_opfamily_member(opfamily, datatype, datatype,
+                                                                         BTGreaterEqualStrategyNumber);
                if (opr1oid == InvalidOid)
-                       elog(ERROR, "no >= operator for opclass %u", opclass);
+                       elog(ERROR, "no >= operator for opfamily %u", opfamily);
        }
        else
        {
-               opr1oid = get_opclass_member(opclass, InvalidOid,
-                                                                        BTGreaterStrategyNumber);
+               opr1oid = get_opfamily_member(opfamily, datatype, datatype,
+                                                                         BTGreaterStrategyNumber);
                if (opr1oid == InvalidOid)
-                       elog(ERROR, "no > operator for opclass %u", opclass);
+                       elog(ERROR, "no > operator for opfamily %u", opfamily);
        }
 
        opr1right = network_scan_first(rightop);
@@ -2793,10 +2803,10 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
 
        /* create clause "key <= network_scan_last( rightop )" */
 
-       opr2oid = get_opclass_member(opclass, InvalidOid,
-                                                                BTLessEqualStrategyNumber);
+       opr2oid = get_opfamily_member(opfamily, datatype, datatype,
+                                                                 BTLessEqualStrategyNumber);
        if (opr2oid == InvalidOid)
-               elog(ERROR, "no <= operator for opclass %u", opclass);
+               elog(ERROR, "no <= operator for opfamily %u", opfamily);
 
        opr2right = network_scan_last(rightop);
 
index 6882439..06022b3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.107 2006/10/04 00:29:54 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.108 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include <math.h>
 
+#include "access/skey.h"
 #include "optimizer/cost.h"
 #include "optimizer/pathnode.h"
 #include "optimizer/paths.h"
@@ -39,6 +40,8 @@ static List *select_mergejoin_clauses(RelOptInfo *joinrel,
                                                 RelOptInfo *innerrel,
                                                 List *restrictlist,
                                                 JoinType jointype);
+static void build_mergejoin_strat_lists(List *mergeclauses,
+                                                       List **mergefamilies, List **mergestrategies);
 
 
 /*
@@ -225,6 +228,8 @@ sort_inner_and_outer(PlannerInfo *root,
                List       *front_pathkey = (List *) lfirst(l);
                List       *cur_pathkeys;
                List       *cur_mergeclauses;
+               List       *mergefamilies;
+               List       *mergestrategies;
                List       *outerkeys;
                List       *innerkeys;
                List       *merge_pathkeys;
@@ -269,6 +274,10 @@ sort_inner_and_outer(PlannerInfo *root,
                merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
                                                                                         outerkeys);
 
+               /* Build opfamily info for execution */
+               build_mergejoin_strat_lists(cur_mergeclauses,
+                                                                       &mergefamilies, &mergestrategies);
+
                /*
                 * And now we can make the path.
                 */
@@ -281,6 +290,8 @@ sort_inner_and_outer(PlannerInfo *root,
                                                                           restrictlist,
                                                                           merge_pathkeys,
                                                                           cur_mergeclauses,
+                                                                          mergefamilies,
+                                                                          mergestrategies,
                                                                           outerkeys,
                                                                           innerkeys));
        }
@@ -410,6 +421,8 @@ match_unsorted_outer(PlannerInfo *root,
                Path       *outerpath = (Path *) lfirst(l);
                List       *merge_pathkeys;
                List       *mergeclauses;
+               List       *mergefamilies;
+               List       *mergestrategies;
                List       *innersortkeys;
                List       *trialsortkeys;
                Path       *cheapest_startup_inner;
@@ -516,6 +529,10 @@ match_unsorted_outer(PlannerInfo *root,
                                                                                                           mergeclauses,
                                                                                                           innerrel);
 
+               /* Build opfamily info for execution */
+               build_mergejoin_strat_lists(mergeclauses,
+                                                                       &mergefamilies, &mergestrategies);
+
                /*
                 * Generate a mergejoin on the basis of sorting the cheapest inner.
                 * Since a sort will be needed, only cheapest total cost matters. (But
@@ -531,6 +548,8 @@ match_unsorted_outer(PlannerInfo *root,
                                                                           restrictlist,
                                                                           merge_pathkeys,
                                                                           mergeclauses,
+                                                                          mergefamilies,
+                                                                          mergestrategies,
                                                                           NIL,
                                                                           innersortkeys));
 
@@ -589,6 +608,11 @@ match_unsorted_outer(PlannerInfo *root,
                                }
                                else
                                        newclauses = mergeclauses;
+
+                               /* Build opfamily info for execution */
+                               build_mergejoin_strat_lists(newclauses,
+                                                                                       &mergefamilies, &mergestrategies);
+
                                add_path(joinrel, (Path *)
                                                 create_mergejoin_path(root,
                                                                                           joinrel,
@@ -598,6 +622,8 @@ match_unsorted_outer(PlannerInfo *root,
                                                                                           restrictlist,
                                                                                           merge_pathkeys,
                                                                                           newclauses,
+                                                                                          mergefamilies,
+                                                                                          mergestrategies,
                                                                                           NIL,
                                                                                           NIL));
                                cheapest_total_inner = innerpath;
@@ -633,6 +659,11 @@ match_unsorted_outer(PlannerInfo *root,
                                                else
                                                        newclauses = mergeclauses;
                                        }
+
+                                       /* Build opfamily info for execution */
+                                       build_mergejoin_strat_lists(newclauses,
+                                                                                               &mergefamilies, &mergestrategies);
+
                                        add_path(joinrel, (Path *)
                                                         create_mergejoin_path(root,
                                                                                                   joinrel,
@@ -642,6 +673,8 @@ match_unsorted_outer(PlannerInfo *root,
                                                                                                   restrictlist,
                                                                                                   merge_pathkeys,
                                                                                                   newclauses,
+                                                                                                  mergefamilies,
+                                                                                                  mergestrategies,
                                                                                                   NIL,
                                                                                                   NIL));
                                }
@@ -946,3 +979,35 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
 
        return result_list;
 }
+
+/*
+ * Temporary hack to build opfamily and strategy lists needed for mergejoin
+ * by the executor.  We need to rethink the planner's handling of merge
+ * planning so that it can deal with multiple possible merge orders, but
+ * that's not done yet.
+ */
+static void
+build_mergejoin_strat_lists(List *mergeclauses,
+                                                       List **mergefamilies, List **mergestrategies)
+{
+       ListCell   *l;
+
+       *mergefamilies = NIL;
+       *mergestrategies = NIL;
+
+       foreach(l, mergeclauses)
+       {
+               RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
+
+               /*
+                * We do not need to worry about whether the mergeclause will be
+                * commuted at runtime --- it's the same opfamily either way.
+                */
+               *mergefamilies = lappend_oid(*mergefamilies, restrictinfo->mergeopfamily);
+               /*
+                * For the moment, strategy must always be LessThan --- see
+                * hack version of get_op_mergejoin_info
+                */
+               *mergestrategies = lappend_int(*mergestrategies, BTLessStrategyNumber);
+       }
+}
index 14f1f1a..f924994 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.217 2006/10/04 00:29:54 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.218 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,7 +73,7 @@ static void fix_indexqual_references(List *indexquals, IndexPath *index_path,
                                                 List **indexstrategy,
                                                 List **indexsubtype);
 static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index,
-                                         Oid *opclass);
+                                         Oid *opfamily);
 static List *get_switched_clauses(List *clauses, Relids outerrelids);
 static List *order_qual_clauses(PlannerInfo *root, List *clauses);
 static void copy_path_costsize(Plan *dest, Path *src);
@@ -113,7 +113,7 @@ static HashJoin *make_hashjoin(List *tlist,
 static Hash *make_hash(Plan *lefttree);
 static MergeJoin *make_mergejoin(List *tlist,
                           List *joinclauses, List *otherclauses,
-                          List *mergeclauses,
+                          List *mergeclauses, List *mergefamilies, List *mergestrategies,
                           Plan *lefttree, Plan *righttree,
                           JoinType jointype);
 static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
@@ -1540,6 +1540,8 @@ create_mergejoin_plan(PlannerInfo *root,
                                                           joinclauses,
                                                           otherclauses,
                                                           mergeclauses,
+                                                          best_path->path_mergefamilies,
+                                                          best_path->path_mergestrategies,
                                                           outer_plan,
                                                           inner_plan,
                                                           best_path->jpath.jointype);
@@ -1676,9 +1678,10 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
                RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
                Expr       *clause;
                Oid                     clause_op;
-               Oid                     opclass;
+               Oid                     opfamily;
                int                     stratno;
-               Oid                     stratsubtype;
+               Oid                     stratlefttype;
+               Oid                     stratrighttype;
                bool            recheck;
 
                Assert(IsA(rinfo, RestrictInfo));
@@ -1709,11 +1712,11 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
 
                        /*
                         * Now, determine which index attribute this is, change the
-                        * indexkey operand as needed, and get the index opclass.
+                        * indexkey operand as needed, and get the index opfamily.
                         */
                        linitial(op->args) = fix_indexqual_operand(linitial(op->args),
                                                                                                           index,
-                                                                                                          &opclass);
+                                                                                                          &opfamily);
                        clause_op = op->opno;
                }
                else if (IsA(clause, RowCompareExpr))
@@ -1734,20 +1737,20 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
                         * For each column in the row comparison, determine which index
                         * attribute this is and change the indexkey operand as needed.
                         *
-                        * Save the index opclass for only the first column.  We will
-                        * return the operator and opclass info for just the first column
+                        * Save the index opfamily for only the first column.  We will
+                        * return the operator and opfamily info for just the first column
                         * of the row comparison; the executor will have to look up the
                         * rest if it needs them.
                         */
                        foreach(lc, rc->largs)
                        {
-                               Oid                     tmp_opclass;
+                               Oid                     tmp_opfamily;
 
                                lfirst(lc) = fix_indexqual_operand(lfirst(lc),
                                                                                                   index,
-                                                                                                  &tmp_opclass);
+                                                                                                  &tmp_opfamily);
                                if (lc == list_head(rc->largs))
-                                       opclass = tmp_opclass;
+                                       opfamily = tmp_opfamily;
                        }
                        clause_op = linitial_oid(rc->opnos);
                }
@@ -1759,11 +1762,11 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
 
                        /*
                         * Now, determine which index attribute this is, change the
-                        * indexkey operand as needed, and get the index opclass.
+                        * indexkey operand as needed, and get the index opfamily.
                         */
                        linitial(saop->args) = fix_indexqual_operand(linitial(saop->args),
                                                                                                                 index,
-                                                                                                                &opclass);
+                                                                                                                &opfamily);
                        clause_op = saop->opno;
                }
                else
@@ -1776,15 +1779,18 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
                *fixed_indexquals = lappend(*fixed_indexquals, clause);
 
                /*
-                * Look up the (possibly commuted) operator in the operator class to
-                * get its strategy numbers and the recheck indicator.  This also
+                * Look up the (possibly commuted) operator in the operator family to
+                * get its strategy number and the recheck indicator.   This also
                 * double-checks that we found an operator matching the index.
                 */
-               get_op_opclass_properties(clause_op, opclass,
-                                                                 &stratno, &stratsubtype, &recheck);
+               get_op_opfamily_properties(clause_op, opfamily,
+                                                                  &stratno,
+                                                                  &stratlefttype,
+                                                                  &stratrighttype,
+                                                                  &recheck);
 
                *indexstrategy = lappend_int(*indexstrategy, stratno);
-               *indexsubtype = lappend_oid(*indexsubtype, stratsubtype);
+               *indexsubtype = lappend_oid(*indexsubtype, stratrighttype);
 
                /* If it's not lossy, add to nonlossy_indexquals */
                if (!recheck)
@@ -1793,7 +1799,7 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
 }
 
 static Node *
-fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
+fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opfamily)
 {
        /*
         * We represent index keys by Var nodes having the varno of the base table
@@ -1826,8 +1832,8 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
                                {
                                        result = (Var *) copyObject(node);
                                        result->varattno = pos + 1;
-                                       /* return the correct opclass, too */
-                                       *opclass = index->classlist[pos];
+                                       /* return the correct opfamily, too */
+                                       *opfamily = index->opfamily[pos];
                                        return (Node *) result;
                                }
                        }
@@ -1853,8 +1859,8 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
                                result = makeVar(index->rel->relid, pos + 1,
                                                                 exprType(lfirst(indexpr_item)), -1,
                                                                 0);
-                               /* return the correct opclass, too */
-                               *opclass = index->classlist[pos];
+                               /* return the correct opfamily, too */
+                               *opfamily = index->opfamily[pos];
                                return (Node *) result;
                        }
                        indexpr_item = lnext(indexpr_item);
@@ -1863,7 +1869,7 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
 
        /* Ooops... */
        elog(ERROR, "node is not an index attribute");
-       *opclass = InvalidOid;          /* keep compiler quiet */
+       *opfamily = InvalidOid;         /* keep compiler quiet */
        return NULL;
 }
 
@@ -2327,6 +2333,8 @@ make_mergejoin(List *tlist,
                           List *joinclauses,
                           List *otherclauses,
                           List *mergeclauses,
+                          List *mergefamilies,
+                          List *mergestrategies,
                           Plan *lefttree,
                           Plan *righttree,
                           JoinType jointype)
@@ -2340,6 +2348,8 @@ make_mergejoin(List *tlist,
        plan->lefttree = lefttree;
        plan->righttree = righttree;
        node->mergeclauses = mergeclauses;
+       node->mergefamilies = mergefamilies;
+       node->mergestrategies = mergestrategies;
        node->join.jointype = jointype;
        node->join.joinqual = joinclauses;
 
index da321a6..229b779 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.124 2006/12/07 19:33:40 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.125 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1109,10 +1109,10 @@ process_implied_equality(PlannerInfo *root,
 
        /*
         * Let's just make sure this appears to be a compatible operator.
+        *
+        * XXX needs work
         */
-       if (pgopform->oprlsortop != sortop1 ||
-               pgopform->oprrsortop != sortop2 ||
-               pgopform->oprresult != BOOLOID)
+       if (pgopform->oprresult != BOOLOID)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
                                 errmsg("equality operator for types %s and %s should be merge-joinable, but isn't",
@@ -1276,6 +1276,7 @@ check_mergejoinable(RestrictInfo *restrictinfo)
        Oid                     opno,
                                leftOp,
                                rightOp;
+       Oid                     opfamily;
 
        if (restrictinfo->pseudoconstant)
                return;
@@ -1286,14 +1287,17 @@ check_mergejoinable(RestrictInfo *restrictinfo)
 
        opno = ((OpExpr *) clause)->opno;
 
-       if (op_mergejoinable(opno,
-                                                &leftOp,
-                                                &rightOp) &&
+       if (op_mergejoinable(opno) &&
                !contain_volatile_functions((Node *) clause))
        {
-               restrictinfo->mergejoinoperator = opno;
-               restrictinfo->left_sortop = leftOp;
-               restrictinfo->right_sortop = rightOp;
+               /* XXX for the moment, continue to force use of particular sortops */
+               if (get_op_mergejoin_info(opno, &leftOp, &rightOp, &opfamily))
+               {
+                       restrictinfo->mergejoinoperator = opno;
+                       restrictinfo->left_sortop = leftOp;
+                       restrictinfo->right_sortop = rightOp;
+                       restrictinfo->mergeopfamily = opfamily;
+               }
        }
 }
 
index e64340e..fcc8d51 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.22 2006/10/04 00:29:54 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.23 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -340,8 +340,8 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info)
 
                                Assert(is_opclause(rinfo->clause));
                                strategy =
-                                       get_op_opclass_strategy(((OpExpr *) rinfo->clause)->opno,
-                                                                                       index->classlist[prevcol]);
+                                       get_op_opfamily_strategy(((OpExpr *) rinfo->clause)->opno,
+                                                                                        index->opfamily[prevcol]);
                                if (strategy == BTEqualStrategyNumber)
                                        break;
                        }
@@ -390,10 +390,10 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info)
  *             Does an aggregate match an index column?
  *
  * It matches if its argument is equal to the index column's data and its
- * sortop is either the LessThan or GreaterThan member of the column's opclass.
+ * sortop is either a LessThan or GreaterThan member of the column's opfamily.
  *
- * We return ForwardScanDirection if match the LessThan member,
- * BackwardScanDirection if match the GreaterThan member,
+ * We return ForwardScanDirection if match a LessThan member,
+ * BackwardScanDirection if match a GreaterThan member,
  * and NoMovementScanDirection if there's no match.
  */
 static ScanDirection
@@ -405,9 +405,9 @@ match_agg_to_index_col(MinMaxAggInfo *info, IndexOptInfo *index, int indexcol)
        if (!match_index_to_operand((Node *) info->target, indexcol, index))
                return NoMovementScanDirection;
 
-       /* Look up the operator in the opclass */
-       strategy = get_op_opclass_strategy(info->aggsortop,
-                                                                          index->classlist[indexcol]);
+       /* Look up the operator in the opfamily */
+       strategy = get_op_opfamily_strategy(info->aggsortop,
+                                                                               index->opfamily[indexcol]);
        if (strategy == BTLessStrategyNumber)
                return ForwardScanDirection;
        if (strategy == BTGreaterStrategyNumber)
index 7793d07..f42a28c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.114 2006/12/10 22:13:26 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.115 2006/12/23 00:43:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -689,11 +689,11 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
                return NULL;
        if (sublink->testexpr && IsA(sublink->testexpr, OpExpr))
        {
-               List       *opclasses;
+               List       *opfamilies;
                List       *opstrats;
 
                get_op_btree_interpretation(((OpExpr *) sublink->testexpr)->opno,
-                                                                       &opclasses, &opstrats);
+                                                                       &opfamilies, &opstrats);
                if (!list_member_int(opstrats, ROWCOMPARE_EQ))
                        return NULL;
        }
index 73ad926..0f720c4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.224 2006/12/21 16:05:13 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.225 2006/12/23 00:43:10 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -1294,13 +1294,9 @@ CommuteRowCompareExpr(RowCompareExpr *clause)
        clause->opnos = newops;
 
        /*
-        * Note: we don't bother to update the opclasses list, but just set it to
-        * empty.  This is OK since this routine is currently only used for index
-        * quals, and the index machinery won't use the opclass information.  The
-        * original opclass list is NOT valid if we have commuted any cross-type
-        * comparisons, so don't leave it in place.
+        * Note: we need not change the opfamilies list; we assume any btree
+        * opfamily containing an operator will also contain its commutator.
         */
-       clause->opclasses = NIL;        /* XXX */
 
        temp = clause->largs;
        clause->largs = clause->rargs;
index 01f3151..5042a3f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.133 2006/10/04 00:29:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.134 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1152,6 +1152,10 @@ create_nestloop_path(PlannerInfo *root,
  * 'pathkeys' are the path keys of the new join path
  * 'mergeclauses' are the RestrictInfo nodes to use as merge clauses
  *             (this should be a subset of the restrict_clauses list)
+ * 'mergefamilies' are the btree opfamily OIDs identifying the merge
+ *             ordering for each merge clause
+ * 'mergestrategies' are the btree operator strategies identifying the merge
+ *             ordering for each merge clause
  * 'outersortkeys' are the sort varkeys for the outer relation
  * 'innersortkeys' are the sort varkeys for the inner relation
  */
@@ -1164,6 +1168,8 @@ create_mergejoin_path(PlannerInfo *root,
                                          List *restrict_clauses,
                                          List *pathkeys,
                                          List *mergeclauses,
+                                         List *mergefamilies,
+                                         List *mergestrategies,
                                          List *outersortkeys,
                                          List *innersortkeys)
 {
@@ -1204,6 +1210,8 @@ create_mergejoin_path(PlannerInfo *root,
        pathnode->jpath.joinrestrictinfo = restrict_clauses;
        pathnode->jpath.path.pathkeys = pathkeys;
        pathnode->path_mergeclauses = mergeclauses;
+       pathnode->path_mergefamilies = mergefamilies;
+       pathnode->path_mergestrategies = mergestrategies;
        pathnode->outersortkeys = outersortkeys;
        pathnode->innersortkeys = innersortkeys;
 
index 70a77bd..5b80991 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.128 2006/12/18 18:56:28 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.129 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -169,16 +169,16 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
                        info->ncolumns = ncolumns = index->indnatts;
 
                        /*
-                        * Need to make classlist and ordering arrays large enough to put
+                        * Need to make opfamily and ordering arrays large enough to put
                         * a terminating 0 at the end of each one.
                         */
                        info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
-                       info->classlist = (Oid *) palloc0(sizeof(Oid) * (ncolumns + 1));
+                       info->opfamily = (Oid *) palloc0(sizeof(Oid) * (ncolumns + 1));
                        info->ordering = (Oid *) palloc0(sizeof(Oid) * (ncolumns + 1));
 
                        for (i = 0; i < ncolumns; i++)
                        {
-                               info->classlist[i] = indexRelation->rd_indclass->values[i];
+                               info->opfamily[i] = indexRelation->rd_opfamily[i];
                                info->indexkeys[i] = index->indkey.values[i];
                        }
 
index 4a2609a..5f81cae 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.10 2006/10/04 00:29:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.11 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -939,7 +939,7 @@ arrayexpr_cleanup_fn(PredIterInfo info)
  * already known immutable, so the clause will certainly always fail.)
  *
  * Finally, we may be able to deduce something using knowledge about btree
- * operator classes; this is encapsulated in btree_predicate_proof().
+ * operator families; this is encapsulated in btree_predicate_proof().
  *----------
  */
 static bool
@@ -989,7 +989,7 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
  * that has "foo" as an input. See notes for implication case.
  *
  * Finally, we may be able to deduce something using knowledge about btree
- * operator classes; this is encapsulated in btree_predicate_proof().
+ * operator families; this is encapsulated in btree_predicate_proof().
  *----------
  */
 static bool
@@ -1062,8 +1062,8 @@ extract_not_arg(Node *clause)
  * The strategy numbers defined by btree indexes (see access/skey.h) are:
  *             (1) <   (2) <=   (3) =   (4) >=   (5) >
  * and in addition we use (6) to represent <>. <> is not a btree-indexable
- * operator, but we assume here that if the equality operator of a btree
- * opclass has a negator operator, the negator behaves as <> for the opclass.
+ * operator, but we assume here that if an equality operator of a btree
+ * opfamily has a negator operator, the negator behaves as <> for the opfamily.
  *
  * The interpretation of:
  *
@@ -1146,10 +1146,10 @@ static const StrategyNumber BT_refute_table[6][6] = {
  * What we look for here is binary boolean opclauses of the form
  * "foo op constant", where "foo" is the same in both clauses. The operators
  * and constants can be different but the operators must be in the same btree
- * operator class.     We use the above operator implication tables to
+ * operator family.  We use the above operator implication tables to
  * derive implications between nonidentical clauses.  (Note: "foo" is known
  * immutable, and constants are surely immutable, but we have to check that
- * the operators are too.  As of 8.0 it's possible for opclasses to contain
+ * the operators are too.  As of 8.0 it's possible for opfamilies to contain
  * operators that are merely stable, and we dare not make deductions with
  * these.)
  *----------
@@ -1171,12 +1171,12 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
                                pred_op_negator,
                                clause_op_negator,
                                test_op = InvalidOid;
-       Oid                     opclass_id;
+       Oid                     opfamily_id;
        bool            found = false;
        StrategyNumber pred_strategy,
                                clause_strategy,
                                test_strategy;
-       Oid                     clause_subtype;
+       Oid                     clause_righttype;
        Expr       *test_expr;
        ExprState  *test_exprstate;
        Datum           test_result;
@@ -1272,28 +1272,30 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
        }
 
        /*
-        * Try to find a btree opclass containing the needed operators.
+        * Try to find a btree opfamily containing the needed operators.
         *
-        * We must find a btree opclass that contains both operators, else the
+        * XXX this needs work!!!!!!!!!!!!!!!!!!!!!!!
+        *
+        * We must find a btree opfamily that contains both operators, else the
         * 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
+        * test.  Also, the opfamily 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
+        * If there are multiple matching opfamilies, 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.
+        * consistent opfamilies.
         */
        catlist = SearchSysCacheList(AMOPOPID, 1,
                                                                 ObjectIdGetDatum(pred_op),
                                                                 0, 0, 0);
 
        /*
-        * If we couldn't find any opclass containing the pred_op, perhaps it is a
-        * <> operator.  See if it has a negator that is in an opclass.
+        * If we couldn't find any opfamily containing the pred_op, perhaps it is a
+        * <> operator.  See if it has a negator that is in an opfamily.
         */
        pred_op_negated = false;
        if (catlist->n_members == 0)
@@ -1312,23 +1314,22 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
        /* Also may need the clause_op's negator */
        clause_op_negator = get_negator(clause_op);
 
-       /* Now search the opclasses */
+       /* Now search the opfamilies */
        for (i = 0; i < catlist->n_members; i++)
        {
                HeapTuple       pred_tuple = &catlist->members[i]->tuple;
                Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple);
                HeapTuple       clause_tuple;
 
-               opclass_id = pred_form->amopclaid;
-
                /* must be btree */
-               if (!opclass_is_btree(opclass_id))
+               if (pred_form->amopmethod != BTREE_AM_OID)
                        continue;
-               /* predicate operator must be default within this opclass */
-               if (pred_form->amopsubtype != InvalidOid)
+               /* predicate operator must be default within this opfamily */
+               if (pred_form->amoplefttype != pred_form->amoprighttype)
                        continue;
 
                /* Get the predicate operator's btree strategy number */
+               opfamily_id = pred_form->amopfamily;
                pred_strategy = (StrategyNumber) pred_form->amopstrategy;
                Assert(pred_strategy >= 1 && pred_strategy <= 5);
 
@@ -1341,37 +1342,39 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
                }
 
                /*
-                * From the same opclass, find a strategy number for the clause_op, if
-                * possible
+                * From the same opfamily, find a strategy number for the clause_op,
+                * if possible
                 */
                clause_tuple = SearchSysCache(AMOPOPID,
                                                                          ObjectIdGetDatum(clause_op),
-                                                                         ObjectIdGetDatum(opclass_id),
+                                                                         ObjectIdGetDatum(opfamily_id),
                                                                          0, 0);
                if (HeapTupleIsValid(clause_tuple))
                {
                        Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple);
 
-                       /* Get the restriction clause operator's strategy/subtype */
+                       /* Get the restriction clause operator's strategy/datatype */
                        clause_strategy = (StrategyNumber) clause_form->amopstrategy;
                        Assert(clause_strategy >= 1 && clause_strategy <= 5);
-                       clause_subtype = clause_form->amopsubtype;
+                       Assert(clause_form->amoplefttype == pred_form->amoplefttype);
+                       clause_righttype = clause_form->amoprighttype;
                        ReleaseSysCache(clause_tuple);
                }
                else if (OidIsValid(clause_op_negator))
                {
                        clause_tuple = SearchSysCache(AMOPOPID,
                                                                                  ObjectIdGetDatum(clause_op_negator),
-                                                                                 ObjectIdGetDatum(opclass_id),
+                                                                                 ObjectIdGetDatum(opfamily_id),
                                                                                  0, 0);
                        if (HeapTupleIsValid(clause_tuple))
                        {
                                Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple);
 
-                               /* Get the restriction clause operator's strategy/subtype */
+                               /* Get the restriction clause operator's strategy/datatype */
                                clause_strategy = (StrategyNumber) clause_form->amopstrategy;
                                Assert(clause_strategy >= 1 && clause_strategy <= 5);
-                               clause_subtype = clause_form->amopsubtype;
+                               Assert(clause_form->amoplefttype == pred_form->amoplefttype);
+                               clause_righttype = clause_form->amoprighttype;
                                ReleaseSysCache(clause_tuple);
 
                                /* Only consider negators that are = */
@@ -1400,20 +1403,24 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
                }
 
                /*
-                * See if opclass has an operator for the test strategy and the clause
-                * datatype.
+                * See if opfamily has an operator for the test strategy and the
+                * datatypes.
                 */
                if (test_strategy == BTNE)
                {
-                       test_op = get_opclass_member(opclass_id, clause_subtype,
-                                                                                BTEqualStrategyNumber);
+                       test_op = get_opfamily_member(opfamily_id,
+                                                                                 pred_form->amoprighttype,
+                                                                                 clause_righttype,
+                                                                                 BTEqualStrategyNumber);
                        if (OidIsValid(test_op))
                                test_op = get_negator(test_op);
                }
                else
                {
-                       test_op = get_opclass_member(opclass_id, clause_subtype,
-                                                                                test_strategy);
+                       test_op = get_opfamily_member(opfamily_id,
+                                                                                 pred_form->amoprighttype,
+                                                                                 clause_righttype,
+                                                                                 test_strategy);
                }
                if (OidIsValid(test_op))
                {
@@ -1423,7 +1430,7 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
                         * Note that we require only the test_op to be immutable, not the
                         * original clause_op.  (pred_op is assumed to have been checked
                         * immutable by the caller.)  Essentially we are assuming that the
-                        * opclass is consistent even if it contains operators that are
+                        * opfamily is consistent even if it contains operators that are
                         * merely stable.
                         */
                        if (op_volatile(test_op) == PROVOLATILE_IMMUTABLE)
@@ -1438,7 +1445,7 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it)
 
        if (!found)
        {
-               /* couldn't find a btree opclass to interpret the operators */
+               /* couldn't find a btree opfamily to interpret the operators */
                return false;
        }
 
index 9176ae1..adfd9e4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.49 2006/10/04 00:29:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.50 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -342,6 +342,7 @@ make_restrictinfo_internal(Expr *clause,
        restrictinfo->mergejoinoperator = InvalidOid;
        restrictinfo->left_sortop = InvalidOid;
        restrictinfo->right_sortop = InvalidOid;
+       restrictinfo->mergeopfamily = InvalidOid;
 
        restrictinfo->left_pathkey = NIL;
        restrictinfo->right_pathkey = NIL;
index 234a15b..2a48741 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.200 2006/12/21 16:05:14 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.201 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2014,10 +2014,10 @@ make_row_comparison_op(ParseState *pstate, List *opname,
        RowCompareType rctype;
        List       *opexprs;
        List       *opnos;
-       List       *opclasses;
+       List       *opfamilies;
        ListCell   *l,
                           *r;
-       List      **opclass_lists;
+       List      **opfamily_lists;
        List      **opstrat_lists;
        Bitmapset  *strats;
        int                     nopers;
@@ -2057,7 +2057,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
                /*
                 * We don't use coerce_to_boolean here because we insist on the
                 * operator yielding boolean directly, not via coercion.  If it
-                * doesn't yield bool it won't be in any index opclasses...
+                * doesn't yield bool it won't be in any index opfamilies...
                 */
                if (cmp->opresulttype != BOOLOID)
                        ereport(ERROR,
@@ -2084,21 +2084,22 @@ make_row_comparison_op(ParseState *pstate, List *opname,
 
        /*
         * Now we must determine which row comparison semantics (= <> < <= > >=)
-        * apply to this set of operators.      We look for btree opclasses containing
+        * apply to this set of operators.      We look for btree opfamilies containing
         * the operators, and see which interpretations (strategy numbers) exist
         * for each operator.
         */
-       opclass_lists = (List **) palloc(nopers * sizeof(List *));
+       opfamily_lists = (List **) palloc(nopers * sizeof(List *));
        opstrat_lists = (List **) palloc(nopers * sizeof(List *));
        strats = NULL;
        i = 0;
        foreach(l, opexprs)
        {
+               Oid                     opno = ((OpExpr *) lfirst(l))->opno;
                Bitmapset  *this_strats;
                ListCell   *j;
 
-               get_op_btree_interpretation(((OpExpr *) lfirst(l))->opno,
-                                                                       &opclass_lists[i], &opstrat_lists[i]);
+               get_op_btree_interpretation(opno,
+                                                                       &opfamily_lists[i], &opstrat_lists[i]);
 
                /*
                 * convert strategy number list to a Bitmapset to make the
@@ -2116,68 +2117,23 @@ make_row_comparison_op(ParseState *pstate, List *opname,
                i++;
        }
 
-       switch (bms_membership(strats))
+       /*
+        * If there are multiple common interpretations, we may use any one of
+        * them ... this coding arbitrarily picks the lowest btree strategy
+        * number.
+        */
+       i = bms_first_member(strats);
+       if (i < 0)
        {
-               case BMS_EMPTY_SET:
-                       /* No common interpretation, so fail */
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        errmsg("could not determine interpretation of row comparison operator %s",
-                                                       strVal(llast(opname))),
-                                        errhint("Row comparison operators must be associated with btree operator classes."),
-                                        parser_errposition(pstate, location)));
-                       rctype = 0;                     /* keep compiler quiet */
-                       break;
-               case BMS_SINGLETON:
-                       /* Simple case: just one possible interpretation */
-                       rctype = bms_singleton_member(strats);
-                       break;
-               case BMS_MULTIPLE:
-               default:                                /* keep compiler quiet */
-                       {
-                               /*
-                                * Prefer the interpretation with the most default opclasses.
-                                */
-                               int                     best_defaults = 0;
-                               bool            multiple_best = false;
-                               int                     this_rctype;
-
-                               rctype = 0;             /* keep compiler quiet */
-                               while ((this_rctype = bms_first_member(strats)) >= 0)
-                               {
-                                       int                     ndefaults = 0;
-
-                                       for (i = 0; i < nopers; i++)
-                                       {
-                                               forboth(l, opclass_lists[i], r, opstrat_lists[i])
-                                               {
-                                                       Oid                     opclass = lfirst_oid(l);
-                                                       int                     opstrat = lfirst_int(r);
-
-                                                       if (opstrat == this_rctype &&
-                                                               opclass_is_default(opclass))
-                                                               ndefaults++;
-                                               }
-                                       }
-                                       if (ndefaults > best_defaults)
-                                       {
-                                               best_defaults = ndefaults;
-                                               rctype = this_rctype;
-                                               multiple_best = false;
-                                       }
-                                       else if (ndefaults == best_defaults)
-                                               multiple_best = true;
-                               }
-                               if (best_defaults == 0 || multiple_best)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                        errmsg("could not determine interpretation of row comparison operator %s",
-                                                                       strVal(llast(opname))),
-                                                        errdetail("There are multiple equally-plausible candidates."),
-                                                        parser_errposition(pstate, location)));
-                               break;
-                       }
+               /* No common interpretation, so fail */
+               ereport(ERROR,
+                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                errmsg("could not determine interpretation of row comparison operator %s",
+                                               strVal(llast(opname))),
+                                errhint("Row comparison operators must be associated with btree operator families."),
+                                parser_errposition(pstate, location)));
        }
+       rctype = (RowCompareType) i;
 
        /*
         * For = and <> cases, we just combine the pairwise operators with AND or
@@ -2193,34 +2149,27 @@ make_row_comparison_op(ParseState *pstate, List *opname,
                return (Node *) makeBoolExpr(OR_EXPR, opexprs);
 
        /*
-        * Otherwise we need to determine exactly which opclass to associate with
+        * Otherwise we need to choose exactly which opfamily to associate with
         * each operator.
         */
-       opclasses = NIL;
+       opfamilies = NIL;
        for (i = 0; i < nopers; i++)
        {
-               Oid                     best_opclass = 0;
-               int                     ndefault = 0;
-               int                     nmatch = 0;
+               Oid                     opfamily = InvalidOid;
 
-               forboth(l, opclass_lists[i], r, opstrat_lists[i])
+               forboth(l, opfamily_lists[i], r, opstrat_lists[i])
                {
-                       Oid                     opclass = lfirst_oid(l);
                        int                     opstrat = lfirst_int(r);
 
                        if (opstrat == rctype)
                        {
-                               if (ndefault == 0)
-                                       best_opclass = opclass;
-                               if (opclass_is_default(opclass))
-                                       ndefault++;
-                               else
-                                       nmatch++;
+                               opfamily = lfirst_oid(l);
+                               break;
                        }
                }
-               if (ndefault == 1 || (ndefault == 0 && nmatch == 1))
-                       opclasses = lappend_oid(opclasses, best_opclass);
-               else
+               if (OidIsValid(opfamily))
+                       opfamilies = lappend_oid(opfamilies, opfamily);
+               else                                    /* should not happen */
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                         errmsg("could not determine interpretation of row comparison operator %s",
@@ -2250,7 +2199,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
        rcexpr = makeNode(RowCompareExpr);
        rcexpr->rctype = rctype;
        rcexpr->opnos = opnos;
-       rcexpr->opclasses = opclasses;
+       rcexpr->opfamilies = opfamilies;
        rcexpr->largs = largs;
        rcexpr->rargs = rargs;
 
index a999420..b2ff95f 100644 (file)
@@ -2,7 +2,7 @@
  * ruleutils.c - Functions to convert stored expressions/querytrees
  *                             back to source text
  *
- *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.236 2006/12/21 16:05:15 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.237 2006/12/23 00:43:11 tgl Exp $
  **********************************************************************/
 
 #include "postgres.h"
@@ -19,6 +19,7 @@
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_trigger.h"
+#include "commands/defrem.h"
 #include "executor/spi.h"
 #include "funcapi.h"
 #include "nodes/makefuncs.h"
@@ -4717,11 +4718,6 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
        Form_pg_opclass opcrec;
        char       *opcname;
        char       *nspname;
-       bool            isvisible;
-
-       /* Domains use their base type's default opclass */
-       if (OidIsValid(actual_datatype))
-               actual_datatype = getBaseType(actual_datatype);
 
        ht_opc = SearchSysCache(CLAOID,
                                                        ObjectIdGetDatum(opclass),
@@ -4730,25 +4726,12 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
                elog(ERROR, "cache lookup failed for opclass %u", opclass);
        opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
 
-       /*
-        * Special case for ARRAY_OPS: pretend it is default for any array type
-        */
-       if (OidIsValid(actual_datatype))
-       {
-               if (opcrec->opcintype == ANYARRAYOID &&
-                       OidIsValid(get_element_type(actual_datatype)))
-                       actual_datatype = opcrec->opcintype;
-       }
-
-       /* Must force use of opclass name if not in search path */
-       isvisible = OpclassIsVisible(opclass);
-
-       if (actual_datatype != opcrec->opcintype || !opcrec->opcdefault ||
-               !isvisible)
+       if (!OidIsValid(actual_datatype) ||
+               GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass)
        {
                /* Okay, we need the opclass name.      Do we need to qualify it? */
                opcname = NameStr(opcrec->opcname);
-               if (isvisible)
+               if (OpclassIsVisible(opclass))
                        appendStringInfo(buf, " %s", quote_identifier(opcname));
                else
                {
index 230ce54..73e82cd 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.215 2006/12/15 18:42:26 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.216 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,7 +76,7 @@
 #include <ctype.h>
 #include <math.h>
 
-#include "catalog/pg_opclass.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_statistic.h"
 #include "catalog/pg_type.h"
 #include "mb/pg_wchar.h"
@@ -128,7 +128,7 @@ static double convert_timevalue_to_scalar(Datum value, Oid typid);
 static bool get_variable_maximum(PlannerInfo *root, VariableStatData *vardata,
                                         Oid sortop, Datum *max);
 static Selectivity prefix_selectivity(VariableStatData *vardata,
-                                  Oid opclass, Const *prefixcon);
+                                  Oid vartype, Oid opfamily, Const *prefixcon);
 static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
 static Datum string_to_datum(const char *str, Oid datatype);
 static Const *string_to_const(const char *str, Oid datatype);
@@ -911,7 +911,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
        Datum           constval;
        Oid                     consttype;
        Oid                     vartype;
-       Oid                     opclass;
+       Oid                     opfamily;
        Pattern_Prefix_Status pstatus;
        Const      *patt = NULL;
        Const      *prefix = NULL;
@@ -960,9 +960,9 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
         * Similarly, the exposed type of the left-hand side should be one of
         * those we know.  (Do not look at vardata.atttype, which might be
         * something binary-compatible but different.)  We can use it to choose
-        * the index opclass from which we must draw the comparison operators.
+        * the index opfamily from which we must draw the comparison operators.
         *
-        * NOTE: It would be more correct to use the PATTERN opclasses than the
+        * NOTE: It would be more correct to use the PATTERN opfamilies than the
         * simple ones, but at the moment ANALYZE will not generate statistics for
         * the PATTERN operators.  But our results are so approximate anyway that
         * it probably hardly matters.
@@ -972,19 +972,16 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
        switch (vartype)
        {
                case TEXTOID:
-                       opclass = TEXT_BTREE_OPS_OID;
-                       break;
-               case VARCHAROID:
-                       opclass = VARCHAR_BTREE_OPS_OID;
+                       opfamily = TEXT_BTREE_FAM_OID;
                        break;
                case BPCHAROID:
-                       opclass = BPCHAR_BTREE_OPS_OID;
+                       opfamily = BPCHAR_BTREE_FAM_OID;
                        break;
                case NAMEOID:
-                       opclass = NAME_BTREE_OPS_OID;
+                       opfamily = NAME_BTREE_FAM_OID;
                        break;
                case BYTEAOID:
-                       opclass = BYTEA_BTREE_OPS_OID;
+                       opfamily = BYTEA_BTREE_FAM_OID;
                        break;
                default:
                        ReleaseVariableStats(vardata);
@@ -1028,12 +1025,12 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
                /*
                 * Pattern specifies an exact match, so pretend operator is '='
                 */
-               Oid                     eqopr = get_opclass_member(opclass, InvalidOid,
-                                                                                          BTEqualStrategyNumber);
+               Oid                     eqopr = get_opfamily_member(opfamily, vartype, vartype,
+                                                                                               BTEqualStrategyNumber);
                List       *eqargs;
 
                if (eqopr == InvalidOid)
-                       elog(ERROR, "no = operator for opclass %u", opclass);
+                       elog(ERROR, "no = operator for opfamily %u", opfamily);
                eqargs = list_make2(variable, prefix);
                result = DatumGetFloat8(DirectFunctionCall4(eqsel,
                                                                                                        PointerGetDatum(root),
@@ -1074,7 +1071,8 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
                        Selectivity restsel;
 
                        if (pstatus == Pattern_Prefix_Partial)
-                               prefixsel = prefix_selectivity(&vardata, opclass, prefix);
+                               prefixsel = prefix_selectivity(&vardata, vartype,
+                                                                                          opfamily, prefix);
                        else
                                prefixsel = 1.0;
                        restsel = pattern_selectivity(rest, ptype);
@@ -2114,7 +2112,8 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
  * we can estimate how much of the input will actually be read.  This
  * can have a considerable impact on the cost when using indexscans.
  *
- * clause should be a clause already known to be mergejoinable.
+ * clause should be a clause already known to be mergejoinable.  opfamily and
+ * strategy specify the sort ordering being used.
  *
  * *leftscan is set to the fraction of the left-hand variable expected
  * to be scanned (0 to 1), and similarly *rightscan for the right-hand
@@ -2122,6 +2121,7 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
  */
 void
 mergejoinscansel(PlannerInfo *root, Node *clause,
+                                Oid opfamily, int strategy,
                                 Selectivity *leftscan,
                                 Selectivity *rightscan)
 {
@@ -2129,15 +2129,14 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
                           *right;
        VariableStatData leftvar,
                                rightvar;
-       Oid                     lefttype,
-                               righttype;
+       int                     op_strategy;
+       Oid                     op_lefttype;
+       Oid                     op_righttype;
+       bool            op_recheck;
        Oid                     opno,
                                lsortop,
                                rsortop,
-                               ltop,
-                               gtop,
                                leop,
-                               revgtop,
                                revleop;
        Datum           leftmax,
                                rightmax;
@@ -2159,15 +2158,51 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
        examine_variable(root, left, 0, &leftvar);
        examine_variable(root, right, 0, &rightvar);
 
-       /* Get the direct input types of the operator */
-       lefttype = exprType(left);
-       righttype = exprType(right);
+       /* Extract the operator's declared left/right datatypes */
+       get_op_opfamily_properties(opno, opfamily,
+                                                          &op_strategy,
+                                                          &op_lefttype,
+                                                          &op_righttype,
+                                                          &op_recheck);
+       Assert(op_strategy == BTEqualStrategyNumber);
+       Assert(!op_recheck);
+
+       /*
+        * Look up the various operators we need.  If we don't find them all,
+        * it probably means the opfamily is broken, but we cope anyway.
+        */
+       switch (strategy)
+       {
+               case BTLessStrategyNumber:
+                       lsortop = get_opfamily_member(opfamily, op_lefttype, op_lefttype,
+                                                                                 BTLessStrategyNumber);
+                       rsortop = get_opfamily_member(opfamily, op_righttype, op_righttype,
+                                                                                 BTLessStrategyNumber);
+                       leop = get_opfamily_member(opfamily, op_lefttype, op_righttype,
+                                                                          BTLessEqualStrategyNumber);
+                       revleop = get_opfamily_member(opfamily, op_righttype, op_lefttype,
+                                                                                 BTLessEqualStrategyNumber);
+                       break;
+               case BTGreaterStrategyNumber:
+                       /* descending-order case */
+                       lsortop = get_opfamily_member(opfamily, op_lefttype, op_lefttype,
+                                                                                 BTGreaterStrategyNumber);
+                       rsortop = get_opfamily_member(opfamily, op_righttype, op_righttype,
+                                                                                 BTGreaterStrategyNumber);
+                       leop = get_opfamily_member(opfamily, op_lefttype, op_righttype,
+                                                                          BTGreaterEqualStrategyNumber);
+                       revleop = get_opfamily_member(opfamily, op_righttype, op_lefttype,
+                                                                                 BTGreaterEqualStrategyNumber);
+                       break;
+               default:
+                       goto fail;                      /* shouldn't get here */
+       }
 
-       /* Verify mergejoinability and get left and right "<" operators */
-       if (!op_mergejoinable(opno,
-                                                 &lsortop,
-                                                 &rsortop))
-               goto fail;                              /* shouldn't happen */
+       if (!OidIsValid(lsortop) ||
+               !OidIsValid(rsortop) ||
+               !OidIsValid(leop) ||
+               !OidIsValid(revleop))
+               goto fail;                              /* insufficient info in catalogs */
 
        /* Try to get maximum values of both inputs */
        if (!get_variable_maximum(root, &leftvar, lsortop, &leftmax))
@@ -2176,37 +2211,19 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
        if (!get_variable_maximum(root, &rightvar, rsortop, &rightmax))
                goto fail;                              /* no max available from stats */
 
-       /* Look up the "left < right" and "left > right" operators */
-       op_mergejoin_crossops(opno, &ltop, &gtop, NULL, NULL);
-
-       /* Look up the "left <= right" operator */
-       leop = get_negator(gtop);
-       if (!OidIsValid(leop))
-               goto fail;                              /* insufficient info in catalogs */
-
-       /* Look up the "right > left" operator */
-       revgtop = get_commutator(ltop);
-       if (!OidIsValid(revgtop))
-               goto fail;                              /* insufficient info in catalogs */
-
-       /* Look up the "right <= left" operator */
-       revleop = get_negator(revgtop);
-       if (!OidIsValid(revleop))
-               goto fail;                              /* insufficient info in catalogs */
-
        /*
         * Now, the fraction of the left variable that will be scanned is the
         * fraction that's <= the right-side maximum value.  But only believe
         * non-default estimates, else stick with our 1.0.
         */
        selec = scalarineqsel(root, leop, false, &leftvar,
-                                                 rightmax, righttype);
+                                                 rightmax, op_righttype);
        if (selec != DEFAULT_INEQ_SEL)
                *leftscan = selec;
 
        /* And similarly for the right variable. */
        selec = scalarineqsel(root, revleop, false, &rightvar,
-                                                 leftmax, lefttype);
+                                                 leftmax, op_lefttype);
        if (selec != DEFAULT_INEQ_SEL)
                *rightscan = selec;
 
@@ -3486,7 +3503,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
                 * statistics.
                 *
                 * XXX it's conceivable that there are multiple matches with different
-                * index opclasses; if so, we need to pick one that matches the
+                * index opfamilies; if so, we need to pick one that matches the
                 * operator we are estimating for.      FIXME later.
                 */
                ListCell   *ilist;
@@ -4100,7 +4117,7 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
  * population represented by the histogram --- the caller must fold this
  * together with info about MCVs and NULLs.
  *
- * We use the >= and < operators from the specified btree opclass to do the
+ * We use the >= and < operators from the specified btree opfamily to do the
  * estimation. The given variable and Const must be of the associated
  * datatype.
  *
@@ -4110,17 +4127,18 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
  * more useful to use the upper-bound code than not.
  */
 static Selectivity
-prefix_selectivity(VariableStatData *vardata, Oid opclass, Const *prefixcon)
+prefix_selectivity(VariableStatData *vardata,
+                                  Oid vartype, Oid opfamily, Const *prefixcon)
 {
        Selectivity prefixsel;
        Oid                     cmpopr;
        FmgrInfo        opproc;
        Const      *greaterstrcon;
 
-       cmpopr = get_opclass_member(opclass, InvalidOid,
-                                                               BTGreaterEqualStrategyNumber);
+       cmpopr = get_opfamily_member(opfamily, vartype, vartype,
+                                                                BTGreaterEqualStrategyNumber);
        if (cmpopr == InvalidOid)
-               elog(ERROR, "no >= operator for opclass %u", opclass);
+               elog(ERROR, "no >= operator for opfamily %u", opfamily);
        fmgr_info(get_opcode(cmpopr), &opproc);
 
        prefixsel = ineq_histogram_selectivity(vardata, &opproc, true,
@@ -4143,10 +4161,10 @@ prefix_selectivity(VariableStatData *vardata, Oid opclass, Const *prefixcon)
        {
                Selectivity topsel;
 
-               cmpopr = get_opclass_member(opclass, InvalidOid,
-                                                                       BTLessStrategyNumber);
+               cmpopr = get_opfamily_member(opfamily, vartype, vartype,
+                                                                        BTLessStrategyNumber);
                if (cmpopr == InvalidOid)
-                       elog(ERROR, "no < operator for opclass %u", opclass);
+                       elog(ERROR, "no < operator for opfamily %u", opfamily);
                fmgr_info(get_opcode(cmpopr), &opproc);
 
                topsel = ineq_histogram_selectivity(vardata, &opproc, false,
@@ -4921,7 +4939,7 @@ btcostestimate(PG_FUNCTION_ARGS)
                }
                else if (match_index_to_operand(rightop, indexcol, index))
                {
-                       /* Must flip operator to get the opclass member */
+                       /* Must flip operator to get the opfamily member */
                        clause_op = get_commutator(clause_op);
                }
                else
@@ -4937,7 +4955,7 @@ btcostestimate(PG_FUNCTION_ARGS)
                        }
                        else if (match_index_to_operand(rightop, indexcol, index))
                        {
-                               /* Must flip operator to get the opclass member */
+                               /* Must flip operator to get the opfamily member */
                                clause_op = get_commutator(clause_op);
                        }
                        else
@@ -4946,9 +4964,9 @@ btcostestimate(PG_FUNCTION_ARGS)
                                break;
                        }
                }
-               op_strategy = get_op_opclass_strategy(clause_op,
-                                                                                         index->classlist[indexcol]);
-               Assert(op_strategy != 0);               /* not a member of opclass?? */
+               op_strategy = get_op_opfamily_strategy(clause_op,
+                                                                                          index->opfamily[indexcol]);
+               Assert(op_strategy != 0);               /* not a member of opfamily?? */
                if (op_strategy == BTEqualStrategyNumber)
                        eqQualHere = true;
                /* count up number of SA scans induced by indexBoundQuals only */
index 55b9d5b..1a1d19f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.134 2006/10/06 18:23:35 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.135 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1033,9 +1033,10 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey)
        if (cache->id == INDEXRELID)
        {
                /*
-                * Since the OIDs of indexes aren't hardwired, it's painful to figure
-                * out which is which.  Just force all pg_index searches to be heap
-                * scans while building the relcaches.
+                * Rather than tracking exactly which indexes have to be loaded
+                * before we can use indexscans (which changes from time to time),
+                * just force all pg_index searches to be heap scans until we've
+                * built the critical relcaches.
                 */
                if (!criticalRelcachesBuilt)
                        return false;
@@ -1051,17 +1052,6 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey)
                 */
                return false;
        }
-       else if (cache->id == OPEROID)
-       {
-               if (!criticalRelcachesBuilt)
-               {
-                       /* Looking for an OID comparison function? */
-                       Oid                     lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument);
-
-                       if (lookup_oid >= MIN_OIDCMP && lookup_oid <= MAX_OIDCMP)
-                               return false;
-               }
-       }
 
        /* Normal case, allow index scan */
        return true;
index fdc31e0..824ef4a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.138 2006/10/04 00:30:00 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.139 2006/12/23 00:43:11 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
 /*                             ---------- AMOP CACHES ----------                                                */
 
 /*
- * op_in_opclass
+ * op_in_opfamily
  *
- *             Return t iff operator 'opno' is in operator class 'opclass'.
+ *             Return t iff operator 'opno' is in operator family 'opfamily'.
  */
 bool
-op_in_opclass(Oid opno, Oid opclass)
+op_in_opfamily(Oid opno, Oid opfamily)
 {
        return SearchSysCacheExists(AMOPOPID,
                                                                ObjectIdGetDatum(opno),
-                                                               ObjectIdGetDatum(opclass),
+                                                               ObjectIdGetDatum(opfamily),
                                                                0, 0);
 }
 
 /*
- * get_op_opclass_strategy
+ * get_op_opfamily_strategy
  *
- *             Get the operator's strategy number within the specified opclass,
- *             or 0 if it's not a member of the opclass.
+ *             Get the operator's strategy number within the specified opfamily,
+ *             or 0 if it's not a member of the opfamily.
  */
 int
-get_op_opclass_strategy(Oid opno, Oid opclass)
+get_op_opfamily_strategy(Oid opno, Oid opfamily)
 {
        HeapTuple       tp;
        Form_pg_amop amop_tup;
@@ -65,7 +65,7 @@ get_op_opclass_strategy(Oid opno, Oid opclass)
 
        tp = SearchSysCache(AMOPOPID,
                                                ObjectIdGetDatum(opno),
-                                               ObjectIdGetDatum(opclass),
+                                               ObjectIdGetDatum(opfamily),
                                                0, 0);
        if (!HeapTupleIsValid(tp))
                return 0;
@@ -76,54 +76,59 @@ get_op_opclass_strategy(Oid opno, Oid opclass)
 }
 
 /*
- * get_op_opclass_properties
+ * get_op_opfamily_properties
  *
- *             Get the operator's strategy number, subtype, and recheck (lossy) flag
- *             within the specified opclass.
+ *             Get the operator's strategy number, input types, and recheck (lossy)
+ *             flag within the specified opfamily.
  *
- * Caller should already have verified that opno is a member of opclass,
+ * Caller should already have verified that opno is a member of opfamily,
  * therefore we raise an error if the tuple is not found.
  */
 void
-get_op_opclass_properties(Oid opno, Oid opclass,
-                                                 int *strategy, Oid *subtype, bool *recheck)
+get_op_opfamily_properties(Oid opno, Oid opfamily,
+                                                  int *strategy,
+                                                  Oid *lefttype,
+                                                  Oid *righttype,
+                                                  bool *recheck)
 {
        HeapTuple       tp;
        Form_pg_amop amop_tup;
 
        tp = SearchSysCache(AMOPOPID,
                                                ObjectIdGetDatum(opno),
-                                               ObjectIdGetDatum(opclass),
+                                               ObjectIdGetDatum(opfamily),
                                                0, 0);
        if (!HeapTupleIsValid(tp))
-               elog(ERROR, "operator %u is not a member of opclass %u",
-                        opno, opclass);
+               elog(ERROR, "operator %u is not a member of opfamily %u",
+                        opno, opfamily);
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
        *strategy = amop_tup->amopstrategy;
-       *subtype = amop_tup->amopsubtype;
+       *lefttype = amop_tup->amoplefttype;
+       *righttype = amop_tup->amoprighttype;
        *recheck = amop_tup->amopreqcheck;
        ReleaseSysCache(tp);
 }
 
 /*
- * get_opclass_member
+ * get_opfamily_member
  *             Get the OID of the operator that implements the specified strategy
- *             with the specified subtype for the specified opclass.
+ *             with the specified datatypes for the specified opfamily.
  *
  * Returns InvalidOid if there is no pg_amop entry for the given keys.
  */
 Oid
-get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
+get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
+                                       int16 strategy)
 {
        HeapTuple       tp;
        Form_pg_amop amop_tup;
        Oid                     result;
 
        tp = SearchSysCache(AMOPSTRATEGY,
-                                               ObjectIdGetDatum(opclass),
-                                               ObjectIdGetDatum(subtype),
-                                               Int16GetDatum(strategy),
-                                               0);
+                                               ObjectIdGetDatum(opfamily),
+                                               ObjectIdGetDatum(lefttype),
+                                               ObjectIdGetDatum(righttype),
+                                               Int16GetDatum(strategy));
        if (!HeapTupleIsValid(tp))
                return InvalidOid;
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
@@ -133,10 +138,160 @@ get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
 }
 
 /*
+ * get_op_mergejoin_info
+ *             Given the OIDs of a (putatively) mergejoinable equality operator
+ *             and a sortop defining the sort ordering of the lefthand input of
+ *             the merge clause, determine whether this sort ordering is actually
+ *             usable for merging.  If so, return the required sort ordering op
+ *             for the righthand input, as well as the btree opfamily OID containing
+ *             these operators and the operator strategy number of the two sortops
+ *             (either BTLessStrategyNumber or BTGreaterStrategyNumber).
+ *
+ * We can mergejoin if we find the two operators in the same opfamily as
+ * equality and either less-than or greater-than respectively.  If there
+ * are multiple such opfamilies, assume we can use any one.
+ */
+#ifdef NOT_YET
+/* eventually should look like this */
+bool
+get_op_mergejoin_info(Oid eq_op, Oid left_sortop,
+                                         Oid *right_sortop, Oid *opfamily, int *opstrategy)
+{
+       bool            result = false;
+       Oid                     lefttype;
+       Oid                     righttype;
+       CatCList   *catlist;
+       int                     i;
+
+       /* Make sure output args are initialized even on failure */
+       *right_sortop = InvalidOid;
+       *opfamily = InvalidOid;
+       *opstrategy = 0;
+
+       /* Need the righthand input datatype */
+       op_input_types(eq_op, &lefttype, &righttype);
+
+       /*
+        * Search through all the pg_amop entries containing the equality operator
+        */
+       catlist = SearchSysCacheList(AMOPOPID, 1,
+                                                                ObjectIdGetDatum(eq_op),
+                                                                0, 0, 0);
+
+       for (i = 0; i < catlist->n_members; i++)
+       {
+               HeapTuple       op_tuple = &catlist->members[i]->tuple;
+               Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
+               Oid                     opfamily_id;
+               StrategyNumber op_strategy;
+
+               /* must be btree */
+               if (op_form->amopmethod != BTREE_AM_OID)
+                       continue;
+               /* must use the operator as equality */
+               if (op_form->amopstrategy != BTEqualStrategyNumber)
+                       continue;
+
+               /* See if sort operator is also in this opclass with OK semantics */
+               opfamily_id = op_form->amopfamily;
+               op_strategy = get_op_opfamily_strategy(left_sortop, opfamily_id);
+               if (op_strategy == BTLessStrategyNumber ||
+                       op_strategy == BTGreaterStrategyNumber)
+               {
+                       /* Yes, so find the corresponding righthand sortop */
+                       *right_sortop = get_opfamily_member(opfamily_id,
+                                                                                               righttype,
+                                                                                               righttype,
+                                                                                               op_strategy);
+                       if (OidIsValid(*right_sortop))
+                       {
+                               /* Found a workable mergejoin semantics */
+                               *opfamily = opfamily_id;
+                               *opstrategy = op_strategy;
+                               result = true;
+                               break;
+                       }
+               }
+       }
+
+       ReleaseSysCacheList(catlist);
+
+       return result;
+}
+#else
+/* temp implementation until planner gets smarter: left_sortop is output */
+bool
+get_op_mergejoin_info(Oid eq_op, Oid *left_sortop,
+                                         Oid *right_sortop, Oid *opfamily)
+{
+       bool            result = false;
+       Oid                     lefttype;
+       Oid                     righttype;
+       CatCList   *catlist;
+       int                     i;
+
+       /* Make sure output args are initialized even on failure */
+       *left_sortop = InvalidOid;
+       *right_sortop = InvalidOid;
+       *opfamily = InvalidOid;
+
+       /* Need the input datatypes */
+       op_input_types(eq_op, &lefttype, &righttype);
+
+       /*
+        * Search through all the pg_amop entries containing the equality operator
+        */
+       catlist = SearchSysCacheList(AMOPOPID, 1,
+                                                                ObjectIdGetDatum(eq_op),
+                                                                0, 0, 0);
+
+       for (i = 0; i < catlist->n_members; i++)
+       {
+               HeapTuple       op_tuple = &catlist->members[i]->tuple;
+               Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
+               Oid                     opfamily_id;
+
+               /* must be btree */
+               if (op_form->amopmethod != BTREE_AM_OID)
+                       continue;
+               /* must use the operator as equality */
+               if (op_form->amopstrategy != BTEqualStrategyNumber)
+                       continue;
+
+               opfamily_id = op_form->amopfamily;
+
+               /* Find the matching sortops */
+               *left_sortop = get_opfamily_member(opfamily_id,
+                                                                                  lefttype,
+                                                                                  lefttype,
+                                                                                  BTLessStrategyNumber);
+               *right_sortop = get_opfamily_member(opfamily_id,
+                                                                                       righttype,
+                                                                                       righttype,
+                                                                                       BTLessStrategyNumber);
+               if (OidIsValid(*left_sortop) && OidIsValid(*right_sortop))
+               {
+                       /* Found a workable mergejoin semantics */
+                       *opfamily = opfamily_id;
+                       result = true;
+                       break;
+               }
+       }
+
+       ReleaseSysCacheList(catlist);
+
+       return result;
+}
+#endif
+
+/*
  * get_op_hash_function
  *             Get the OID of the datatype-specific hash function associated with
  *             a hashable equality operator.
  *
+ * XXX API needs to be generalized for the case of different left and right
+ * datatypes.
+ *
  * Returns InvalidOid if no hash function can be found.  (This indicates
  * that the operator should not have been marked oprcanhash.)
  */
@@ -145,12 +300,12 @@ get_op_hash_function(Oid opno)
 {
        CatCList   *catlist;
        int                     i;
-       Oid                     opclass = InvalidOid;
+       Oid                     result = InvalidOid;
 
        /*
         * Search pg_amop to see if the target operator is registered as the "="
-        * operator of any hash opclass.  If the operator is registered in
-        * multiple opclasses, assume we can use the associated hash function from
+        * operator of any hash opfamily.  If the operator is registered in
+        * multiple opfamilies, assume we can use the associated hash function from
         * any one.
         */
        catlist = SearchSysCacheList(AMOPOPID, 1,
@@ -162,58 +317,44 @@ get_op_hash_function(Oid opno)
                HeapTuple       tuple = &catlist->members[i]->tuple;
                Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
 
-               if (aform->amopstrategy == HTEqualStrategyNumber &&
-                       opclass_is_hash(aform->amopclaid))
+               if (aform->amopmethod == HASH_AM_OID &&
+                       aform->amopstrategy == HTEqualStrategyNumber)
                {
-                       opclass = aform->amopclaid;
+                       /* Found a suitable opfamily, get matching hash support function */
+                       result = get_opfamily_proc(aform->amopfamily,
+                                                                          aform->amoplefttype,
+                                                                          aform->amoprighttype,
+                                                                          HASHPROC);
                        break;
                }
        }
 
        ReleaseSysCacheList(catlist);
 
-       if (OidIsValid(opclass))
-       {
-               /* Found a suitable opclass, get its default hash support function */
-               return get_opclass_proc(opclass, InvalidOid, HASHPROC);
-       }
-
-       /* Didn't find a match... */
-       return InvalidOid;
+       return result;
 }
 
 /*
  * get_op_btree_interpretation
- *             Given an operator's OID, find out which btree opclasses it belongs to,
+ *             Given an operator's OID, find out which btree opfamilies it belongs to,
  *             and what strategy number it has within each one.  The results are
  *             returned as an OID list and a parallel integer list.
  *
  * In addition to the normal btree operators, we consider a <> operator to be
- * a "member" of an opclass if its negator is the opclass' equality operator.
- * ROWCOMPARE_NE is returned as the strategy number for this case.
+ * a "member" of an opfamily if its negator is an equality operator of the
+ * opfamily.  ROWCOMPARE_NE is returned as the strategy number for this case.
  */
 void
-get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats)
+get_op_btree_interpretation(Oid opno, List **opfamilies, List **opstrats)
 {
-       Oid                     lefttype,
-                               righttype;
        CatCList   *catlist;
        bool            op_negated;
        int                     i;
 
-       *opclasses = NIL;
+       *opfamilies = NIL;
        *opstrats = NIL;
 
        /*
-        * Get the nominal left-hand input type of the operator; we will ignore
-        * opclasses that don't have that as the expected input datatype.  This is
-        * a kluge to avoid being confused by binary-compatible opclasses (such as
-        * text_ops and varchar_ops, which share the same operators).
-        */
-       op_input_types(opno, &lefttype, &righttype);
-       Assert(OidIsValid(lefttype));
-
-       /*
         * Find all the pg_amop entries containing the operator.
         */
        catlist = SearchSysCacheList(AMOPOPID, 1,
@@ -221,8 +362,8 @@ get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats)
                                                                 0, 0, 0);
 
        /*
-        * If we can't find any opclass containing the op, perhaps it is a <>
-        * operator.  See if it has a negator that is in an opclass.
+        * If we can't find any opfamily containing the op, perhaps it is a <>
+        * operator.  See if it has a negator that is in an opfamily.
         */
        op_negated = false;
        if (catlist->n_members == 0)
@@ -239,25 +380,20 @@ get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats)
                }
        }
 
-       /* Now search the opclasses */
+       /* Now search the opfamilies */
        for (i = 0; i < catlist->n_members; i++)
        {
                HeapTuple       op_tuple = &catlist->members[i]->tuple;
                Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
-               Oid                     opclass_id;
+               Oid                     opfamily_id;
                StrategyNumber op_strategy;
 
-               opclass_id = op_form->amopclaid;
-
                /* must be btree */
-               if (!opclass_is_btree(opclass_id))
-                       continue;
-
-               /* must match operator input type exactly */
-               if (get_opclass_input_type(opclass_id) != lefttype)
+               if (op_form->amopmethod != BTREE_AM_OID)
                        continue;
 
                /* Get the operator's btree strategy number */
+               opfamily_id = op_form->amopfamily;
                op_strategy = (StrategyNumber) op_form->amopstrategy;
                Assert(op_strategy >= 1 && op_strategy <= 5);
 
@@ -269,7 +405,7 @@ get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats)
                        op_strategy = ROWCOMPARE_NE;
                }
 
-               *opclasses = lappend_oid(*opclasses, opclass_id);
+               *opfamilies = lappend_oid(*opfamilies, opfamily_id);
                *opstrats = lappend_int(*opstrats, op_strategy);
        }
 
@@ -280,24 +416,24 @@ get_op_btree_interpretation(Oid opno, List **opclasses, List **opstrats)
 /*                             ---------- AMPROC CACHES ----------                                              */
 
 /*
- * get_opclass_proc
+ * get_opfamily_proc
  *             Get the OID of the specified support function
- *             for the specified opclass and subtype.
+ *             for the specified opfamily and datatypes.
  *
  * Returns InvalidOid if there is no pg_amproc entry for the given keys.
  */
 Oid
-get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
+get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
 {
        HeapTuple       tp;
        Form_pg_amproc amproc_tup;
        RegProcedure result;
 
        tp = SearchSysCache(AMPROCNUM,
-                                               ObjectIdGetDatum(opclass),
-                                               ObjectIdGetDatum(subtype),
-                                               Int16GetDatum(procnum),
-                                               0);
+                                               ObjectIdGetDatum(opfamily),
+                                               ObjectIdGetDatum(lefttype),
+                                               ObjectIdGetDatum(righttype),
+                                               Int16GetDatum(procnum));
        if (!HeapTupleIsValid(tp))
                return InvalidOid;
        amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
@@ -477,67 +613,16 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
 /*                             ---------- OPCLASS CACHE ----------                                              */
 
 /*
- * opclass_is_btree
+ * get_opclass_family
  *
- *             Returns TRUE iff the specified opclass is associated with the
- *             btree index access method.
+ *             Returns the OID of the operator family the opclass belongs to.
  */
-bool
-opclass_is_btree(Oid opclass)
-{
-       HeapTuple       tp;
-       Form_pg_opclass cla_tup;
-       bool            result;
-
-       tp = SearchSysCache(CLAOID,
-                                               ObjectIdGetDatum(opclass),
-                                               0, 0, 0);
-       if (!HeapTupleIsValid(tp))
-               elog(ERROR, "cache lookup failed for opclass %u", opclass);
-       cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
-
-       result = (cla_tup->opcamid == BTREE_AM_OID);
-       ReleaseSysCache(tp);
-       return result;
-}
-
-/*
- * opclass_is_hash
- *
- *             Returns TRUE iff the specified opclass is associated with the
- *             hash index access method.
- */
-bool
-opclass_is_hash(Oid opclass)
-{
-       HeapTuple       tp;
-       Form_pg_opclass cla_tup;
-       bool            result;
-
-       tp = SearchSysCache(CLAOID,
-                                               ObjectIdGetDatum(opclass),
-                                               0, 0, 0);
-       if (!HeapTupleIsValid(tp))
-               elog(ERROR, "cache lookup failed for opclass %u", opclass);
-       cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
-
-       result = (cla_tup->opcamid == HASH_AM_OID);
-       ReleaseSysCache(tp);
-       return result;
-}
-
-/*
- * opclass_is_default
- *
- *             Returns TRUE iff the specified opclass is the default for its
- *             index access method and input data type.
- */
-bool
-opclass_is_default(Oid opclass)
+Oid
+get_opclass_family(Oid opclass)
 {
        HeapTuple       tp;
        Form_pg_opclass cla_tup;
-       bool            result;
+       Oid                     result;
 
        tp = SearchSysCache(CLAOID,
                                                ObjectIdGetDatum(opclass),
@@ -546,7 +631,7 @@ opclass_is_default(Oid opclass)
                elog(ERROR, "cache lookup failed for opclass %u", opclass);
        cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
 
-       result = cla_tup->opcdefault;
+       result = cla_tup->opcfamily;
        ReleaseSysCache(tp);
        return result;
 }
@@ -657,11 +742,13 @@ op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
 /*
  * op_mergejoinable
  *
- *             Returns the left and right sort operators corresponding to a
- *             mergejoinable operator, or false if the operator is not mergejoinable.
+ * Returns true if the operator is potentially mergejoinable.  (The planner
+ * will fail to find any mergejoin plans unless there are suitable btree
+ * opfamily entries for this operator and associated sortops.  The pg_operator
+ * flag is just a hint to tell the planner whether to bother looking.)
  */
 bool
-op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
+op_mergejoinable(Oid opno)
 {
        HeapTuple       tp;
        bool            result = false;
@@ -673,65 +760,17 @@ op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
        {
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
-               if (optup->oprlsortop &&
-                       optup->oprrsortop)
-               {
-                       *leftOp = optup->oprlsortop;
-                       *rightOp = optup->oprrsortop;
-                       result = true;
-               }
+               result = optup->oprcanmerge;
                ReleaseSysCache(tp);
        }
        return result;
 }
 
 /*
- * op_mergejoin_crossops
- *
- *             Returns the cross-type comparison operators (ltype "<" rtype and
- *             ltype ">" rtype) for an operator previously determined to be
- *             mergejoinable.  Optionally, fetches the regproc ids of these
- *             operators, as well as their operator OIDs.
- */
-void
-op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
-                                         RegProcedure *ltproc, RegProcedure *gtproc)
-{
-       HeapTuple       tp;
-       Form_pg_operator optup;
-
-       /*
-        * Get the declared comparison operators of the operator.
-        */
-       tp = SearchSysCache(OPEROID,
-                                               ObjectIdGetDatum(opno),
-                                               0, 0, 0);
-       if (!HeapTupleIsValid(tp))      /* shouldn't happen */
-               elog(ERROR, "cache lookup failed for operator %u", opno);
-       optup = (Form_pg_operator) GETSTRUCT(tp);
-       *ltop = optup->oprltcmpop;
-       *gtop = optup->oprgtcmpop;
-       ReleaseSysCache(tp);
-
-       /* Check < op provided */
-       if (!OidIsValid(*ltop))
-               elog(ERROR, "mergejoin operator %u has no matching < operator",
-                        opno);
-       if (ltproc)
-               *ltproc = get_opcode(*ltop);
-
-       /* Check > op provided */
-       if (!OidIsValid(*gtop))
-               elog(ERROR, "mergejoin operator %u has no matching > operator",
-                        opno);
-       if (gtproc)
-               *gtproc = get_opcode(*gtop);
-}
-
-/*
  * op_hashjoinable
  *
- * Returns true if the operator is hashjoinable.
+ * Returns true if the operator is hashjoinable.  (There must be a suitable
+ * hash opfamily entry for this operator if it is so marked.)
  */
 bool
 op_hashjoinable(Oid opno)
index 65cd1e7..be5fb60 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.250 2006/11/05 23:40:30 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.251 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -69,7 +69,7 @@
  */
 #define RELCACHE_INIT_FILENAME "pg_internal.init"
 
-#define RELCACHE_INIT_FILEMAGIC                0x573263        /* version ID value */
+#define RELCACHE_INIT_FILEMAGIC                0x573264        /* version ID value */
 
 /*
  *             hardcoded tuple descriptors.  see include/catalog/pg_attribute.h
@@ -159,7 +159,8 @@ do { \
 /*
  * Special cache for opclass-related information
  *
- * Note: only default-subtype operators and support procs get cached
+ * Note: only default operators and support procs get cached, ie, those with
+ * lefttype = righttype = opcintype.
  */
 typedef struct opclasscacheent
 {
@@ -167,6 +168,8 @@ typedef struct opclasscacheent
        bool            valid;                  /* set TRUE after successful fill-in */
        StrategyNumber numStrats;       /* max # of strategies (from pg_am) */
        StrategyNumber numSupport;      /* max # of support procs (from pg_am) */
+       Oid                     opcfamily;              /* OID of opclass's family */
+       Oid                     opcintype;              /* OID of opclass's declared input type */
        Oid                *operatorOids;       /* strategy operators' OIDs */
        RegProcedure *supportProcs; /* support procs */
 } OpClassCacheEnt;
@@ -201,6 +204,8 @@ static List *insert_ordered_oid(List *list, Oid datum);
 static void IndexSupportInitialize(oidvector *indclass,
                                           Oid *indexOperator,
                                           RegProcedure *indexSupport,
+                                          Oid *opFamily,
+                                          Oid *opcInType,
                                           StrategyNumber maxStrategyNumber,
                                           StrategyNumber maxSupportNumber,
                                           AttrNumber maxAttributeNumber);
@@ -921,11 +926,9 @@ RelationInitIndexAccessInfo(Relation relation)
        Form_pg_am      aform;
        Datum           indclassDatum;
        bool            isnull;
+       oidvector  *indclass;
        MemoryContext indexcxt;
        MemoryContext oldcontext;
-       Oid                *operator;
-       RegProcedure *support;
-       FmgrInfo   *supportinfo;
        int                     natts;
        uint16          amstrategies;
        uint16          amsupport;
@@ -948,18 +951,6 @@ RelationInitIndexAccessInfo(Relation relation)
        ReleaseSysCache(tuple);
 
        /*
-        * indclass cannot be referenced directly through the C struct, because it
-        * is after the variable-width indkey field.  Therefore we extract the
-        * datum the hard way and provide a direct link in the relcache.
-        */
-       indclassDatum = fastgetattr(relation->rd_indextuple,
-                                                               Anum_pg_index_indclass,
-                                                               GetPgIndexDescriptor(),
-                                                               &isnull);
-       Assert(!isnull);
-       relation->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum);
-
-       /*
         * Make a copy of the pg_am entry for the index's access method
         */
        tuple = SearchSysCache(AMOID,
@@ -1001,38 +992,53 @@ RelationInitIndexAccessInfo(Relation relation)
        relation->rd_aminfo = (RelationAmInfo *)
                MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
 
+       relation->rd_opfamily = (Oid *)
+               MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+       relation->rd_opcintype = (Oid *)
+               MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+
        if (amstrategies > 0)
-               operator = (Oid *)
+               relation->rd_operator = (Oid *)
                        MemoryContextAllocZero(indexcxt,
                                                                   natts * amstrategies * sizeof(Oid));
        else
-               operator = NULL;
+               relation->rd_operator = NULL;
 
        if (amsupport > 0)
        {
                int                     nsupport = natts * amsupport;
 
-               support = (RegProcedure *)
+               relation->rd_support = (RegProcedure *)
                        MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
-               supportinfo = (FmgrInfo *)
+               relation->rd_supportinfo = (FmgrInfo *)
                        MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
        }
        else
        {
-               support = NULL;
-               supportinfo = NULL;
+               relation->rd_support = NULL;
+               relation->rd_supportinfo = NULL;
        }
 
-       relation->rd_operator = operator;
-       relation->rd_support = support;
-       relation->rd_supportinfo = supportinfo;
+       /*
+        * indclass cannot be referenced directly through the C struct, because it
+        * comes after the variable-width indkey field.  Must extract the
+        * datum the hard way...
+        */
+       indclassDatum = fastgetattr(relation->rd_indextuple,
+                                                               Anum_pg_index_indclass,
+                                                               GetPgIndexDescriptor(),
+                                                               &isnull);
+       Assert(!isnull);
+       indclass = (oidvector *) DatumGetPointer(indclassDatum);
 
        /*
-        * Fill the operator and support procedure OID arrays.  (aminfo and
+        * Fill the operator and support procedure OID arrays, as well as the
+        * info about opfamilies and opclass input types.  (aminfo and
         * supportinfo are left as zeroes, and are filled on-the-fly when used)
         */
-       IndexSupportInitialize(relation->rd_indclass,
-                                                  operator, support,
+       IndexSupportInitialize(indclass,
+                                                  relation->rd_operator, relation->rd_support,
+                                                  relation->rd_opfamily, relation->rd_opcintype,
                                                   amstrategies, amsupport, natts);
 
        /*
@@ -1048,8 +1054,8 @@ RelationInitIndexAccessInfo(Relation relation)
  *             Initializes an index's cached opclass information,
  *             given the index's pg_index.indclass entry.
  *
- * Data is returned into *indexOperator and *indexSupport, which are arrays
- * allocated by the caller.
+ * Data is returned into *indexOperator, *indexSupport, *opFamily, and
+ * *opcInType, which are arrays allocated by the caller.
  *
  * The caller also passes maxStrategyNumber, maxSupportNumber, and
  * maxAttributeNumber, since these indicate the size of the arrays
@@ -1061,6 +1067,8 @@ static void
 IndexSupportInitialize(oidvector *indclass,
                                           Oid *indexOperator,
                                           RegProcedure *indexSupport,
+                                          Oid *opFamily,
+                                          Oid *opcInType,
                                           StrategyNumber maxStrategyNumber,
                                           StrategyNumber maxSupportNumber,
                                           AttrNumber maxAttributeNumber)
@@ -1080,6 +1088,8 @@ IndexSupportInitialize(oidvector *indclass,
                                                                         maxSupportNumber);
 
                /* copy cached data into relcache entry */
+               opFamily[attIndex] = opcentry->opcfamily;
+               opcInType[attIndex] = opcentry->opcintype;
                if (maxStrategyNumber > 0)
                        memcpy(&indexOperator[attIndex * maxStrategyNumber],
                                   opcentry->operatorOids,
@@ -1116,7 +1126,7 @@ LookupOpclassInfo(Oid operatorClassOid,
        bool            found;
        Relation        rel;
        SysScanDesc scan;
-       ScanKeyData skey[2];
+       ScanKeyData skey[3];
        HeapTuple       htup;
        bool            indexOK;
 
@@ -1177,22 +1187,54 @@ LookupOpclassInfo(Oid operatorClassOid,
                 operatorClassOid != INT2_BTREE_OPS_OID);
 
        /*
+        * We have to fetch the pg_opclass row to determine its opfamily and
+        * opcintype, which are needed to look up the operators and functions.
+        * It'd be convenient to use the syscache here, but that probably doesn't
+        * work while bootstrapping.
+        */
+       ScanKeyInit(&skey[0],
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(operatorClassOid));
+       rel = heap_open(OperatorClassRelationId, AccessShareLock);
+       scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
+                                                         SnapshotNow, 1, skey);
+
+       if (HeapTupleIsValid(htup = systable_getnext(scan)))
+       {
+               Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
+
+               opcentry->opcfamily = opclassform->opcfamily;
+               opcentry->opcintype = opclassform->opcintype;
+       }
+       else
+               elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
+
+       systable_endscan(scan);
+       heap_close(rel, AccessShareLock);
+
+
+       /*
         * Scan pg_amop to obtain operators for the opclass.  We only fetch the
-        * default ones (those with subtype zero).
+        * default ones (those with lefttype = righttype = opcintype).
         */
        if (numStrats > 0)
        {
                ScanKeyInit(&skey[0],
-                                       Anum_pg_amop_amopclaid,
+                                       Anum_pg_amop_amopfamily,
                                        BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(operatorClassOid));
+                                       ObjectIdGetDatum(opcentry->opcfamily));
                ScanKeyInit(&skey[1],
-                                       Anum_pg_amop_amopsubtype,
+                                       Anum_pg_amop_amoplefttype,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(opcentry->opcintype));
+               ScanKeyInit(&skey[2],
+                                       Anum_pg_amop_amoprighttype,
                                        BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(InvalidOid));
+                                       ObjectIdGetDatum(opcentry->opcintype));
                rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock);
                scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK,
-                                                                 SnapshotNow, 2, skey);
+                                                                 SnapshotNow, 3, skey);
 
                while (HeapTupleIsValid(htup = systable_getnext(scan)))
                {
@@ -1212,21 +1254,25 @@ LookupOpclassInfo(Oid operatorClassOid,
 
        /*
         * Scan pg_amproc to obtain support procs for the opclass.      We only fetch
-        * the default ones (those with subtype zero).
+        * the default ones (those with lefttype = righttype = opcintype).
         */
        if (numSupport > 0)
        {
                ScanKeyInit(&skey[0],
-                                       Anum_pg_amproc_amopclaid,
+                                       Anum_pg_amproc_amprocfamily,
                                        BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(operatorClassOid));
+                                       ObjectIdGetDatum(opcentry->opcfamily));
                ScanKeyInit(&skey[1],
-                                       Anum_pg_amproc_amprocsubtype,
+                                       Anum_pg_amproc_amproclefttype,
                                        BTEqualStrategyNumber, F_OIDEQ,
-                                       ObjectIdGetDatum(InvalidOid));
+                                       ObjectIdGetDatum(opcentry->opcintype));
+               ScanKeyInit(&skey[2],
+                                       Anum_pg_amproc_amprocrighttype,
+                                       BTEqualStrategyNumber, F_OIDEQ,
+                                       ObjectIdGetDatum(opcentry->opcintype));
                rel = heap_open(AccessMethodProcedureRelationId, AccessShareLock);
                scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
-                                                                 SnapshotNow, 2, skey);
+                                                                 SnapshotNow, 3, skey);
 
                while (HeapTupleIsValid(htup = systable_getnext(scan)))
                {
@@ -3097,8 +3143,6 @@ load_relcache_init_file(void)
                Relation        rel;
                Form_pg_class relform;
                bool            has_not_null;
-               Datum           indclassDatum;
-               bool            isnull;
 
                /* first read the relation descriptor length */
                if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
@@ -3187,6 +3231,8 @@ load_relcache_init_file(void)
                {
                        Form_pg_am      am;
                        MemoryContext indexcxt;
+                       Oid                *opfamily;
+                       Oid                *opcintype;
                        Oid                *operator;
                        RegProcedure *support;
                        int                     nsupport;
@@ -3207,14 +3253,6 @@ load_relcache_init_file(void)
                        rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
                        rel->rd_index = (Form_pg_index) GETSTRUCT(rel->rd_indextuple);
 
-                       /* fix up indclass pointer too */
-                       indclassDatum = fastgetattr(rel->rd_indextuple,
-                                                                               Anum_pg_index_indclass,
-                                                                               GetPgIndexDescriptor(),
-                                                                               &isnull);
-                       Assert(!isnull);
-                       rel->rd_indclass = (oidvector *) DatumGetPointer(indclassDatum);
-
                        /* next, read the access method tuple form */
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
                                goto read_failed;
@@ -3235,6 +3273,26 @@ load_relcache_init_file(void)
                                                                                         ALLOCSET_SMALL_MAXSIZE);
                        rel->rd_indexcxt = indexcxt;
 
+                       /* next, read the vector of opfamily OIDs */
+                       if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
+                               goto read_failed;
+
+                       opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
+                       if ((nread = fread(opfamily, 1, len, fp)) != len)
+                               goto read_failed;
+
+                       rel->rd_opfamily = opfamily;
+
+                       /* next, read the vector of opcintype OIDs */
+                       if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
+                               goto read_failed;
+
+                       opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
+                       if ((nread = fread(opcintype, 1, len, fp)) != len)
+                               goto read_failed;
+
+                       rel->rd_opcintype = opcintype;
+
                        /* next, read the vector of operator OIDs */
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
                                goto read_failed;
@@ -3269,10 +3327,11 @@ load_relcache_init_file(void)
 
                        Assert(rel->rd_index == NULL);
                        Assert(rel->rd_indextuple == NULL);
-                       Assert(rel->rd_indclass == NULL);
                        Assert(rel->rd_am == NULL);
                        Assert(rel->rd_indexcxt == NULL);
                        Assert(rel->rd_aminfo == NULL);
+                       Assert(rel->rd_opfamily == NULL);
+                       Assert(rel->rd_opcintype == NULL);
                        Assert(rel->rd_operator == NULL);
                        Assert(rel->rd_support == NULL);
                        Assert(rel->rd_supportinfo == NULL);
@@ -3450,6 +3509,16 @@ write_relcache_init_file(void)
                        /* next, write the access method tuple form */
                        write_item(am, sizeof(FormData_pg_am), fp);
 
+                       /* next, write the vector of opfamily OIDs */
+                       write_item(rel->rd_opfamily,
+                                          relform->relnatts * sizeof(Oid),
+                                          fp);
+
+                       /* next, write the vector of opcintype OIDs */
+                       write_item(rel->rd_opcintype,
+                                          relform->relnatts * sizeof(Oid),
+                                          fp);
+
                        /* next, write the vector of operator OIDs */
                        write_item(rel->rd_operator,
                                           relform->relnatts * (am->amstrategies * sizeof(Oid)),
index e19fba0..f2fb079 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.108 2006/10/06 18:23:35 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.109 2006/12/23 00:43:11 tgl Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
 #include "catalog/pg_cast.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_database.h"
-#include "catalog/pg_inherits.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_statistic.h"
@@ -135,7 +135,7 @@ static const struct cachedesc cacheinfo[] = {
                2,
                {
                        Anum_pg_amop_amopopr,
-                       Anum_pg_amop_amopclaid,
+                       Anum_pg_amop_amopfamily,
                        0,
                        0
                },
@@ -144,24 +144,24 @@ static const struct cachedesc cacheinfo[] = {
        {AccessMethodOperatorRelationId,        /* AMOPSTRATEGY */
                AccessMethodStrategyIndexId,
                0,
-               3,
+               4,
                {
-                       Anum_pg_amop_amopclaid,
-                       Anum_pg_amop_amopsubtype,
-                       Anum_pg_amop_amopstrategy,
-                       0
+                       Anum_pg_amop_amopfamily,
+                       Anum_pg_amop_amoplefttype,
+                       Anum_pg_amop_amoprighttype,
+                       Anum_pg_amop_amopstrategy
                },
                64
        },
        {AccessMethodProcedureRelationId,       /* AMPROCNUM */
                AccessMethodProcedureIndexId,
                0,
-               3,
+               4,
                {
-                       Anum_pg_amproc_amopclaid,
-                       Anum_pg_amproc_amprocsubtype,
-                       Anum_pg_amproc_amprocnum,
-                       0
+                       Anum_pg_amproc_amprocfamily,
+                       Anum_pg_amproc_amproclefttype,
+                       Anum_pg_amproc_amprocrighttype,
+                       Anum_pg_amproc_amprocnum
                },
                64
        },
@@ -255,7 +255,7 @@ static const struct cachedesc cacheinfo[] = {
                0,
                3,
                {
-                       Anum_pg_opclass_opcamid,
+                       Anum_pg_opclass_opcmethod,
                        Anum_pg_opclass_opcname,
                        Anum_pg_opclass_opcnamespace,
                        0
@@ -334,18 +334,6 @@ static const struct cachedesc cacheinfo[] = {
                },
                1024
        },
-       {InheritsRelationId,            /* INHRELID */
-               InheritsRelidSeqnoIndexId,
-               Anum_pg_inherits_inhrelid,
-               2,
-               {
-                       Anum_pg_inherits_inhrelid,
-                       Anum_pg_inherits_inhseqno,
-                       0,
-                       0
-               },
-               256
-       },
        {LanguageRelationId,            /* LANGNAME */
                LanguageNameIndexId,
                0,
@@ -418,6 +406,30 @@ static const struct cachedesc cacheinfo[] = {
                },
                1024
        },
+       {OperatorFamilyRelationId,      /* OPFAMILYAMNAMENSP */
+               OpfamilyAmNameNspIndexId,
+               0,
+               3,
+               {
+                       Anum_pg_opfamily_opfmethod,
+                       Anum_pg_opfamily_opfname,
+                       Anum_pg_opfamily_opfnamespace,
+                       0
+               },
+               64
+       },
+       {OperatorFamilyRelationId,      /* OPFAMILYOID */
+               OpfamilyOidIndexId,
+               0,
+               1,
+               {
+                       ObjectIdAttributeNumber,
+                       0,
+                       0,
+                       0
+               },
+               64
+       },
        {ProcedureRelationId,           /* PROCNAMEARGSNSP */
                ProcedureNameArgsNspIndexId,
                0,
index c5a0272..192675c 100644 (file)
@@ -36,7 +36,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.22 2006/10/04 00:30:01 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.23 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,17 +165,30 @@ lookup_type_cache(Oid type_id, int flags)
        /* If we haven't already found the opclass, try to do so */
        if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_LT_OPR | TYPECACHE_GT_OPR |
                                  TYPECACHE_CMP_PROC |
-                                 TYPECACHE_EQ_OPR_FINFO | TYPECACHE_CMP_PROC_FINFO)) &&
-               typentry->btree_opc == InvalidOid)
+                                 TYPECACHE_EQ_OPR_FINFO | TYPECACHE_CMP_PROC_FINFO |
+                                 TYPECACHE_BTREE_OPFAMILY)) &&
+               typentry->btree_opf == InvalidOid)
        {
-               typentry->btree_opc = GetDefaultOpClass(type_id,
-                                                                                               BTREE_AM_OID);
+               Oid             opclass;
+
+               opclass = GetDefaultOpClass(type_id, BTREE_AM_OID);
+               if (OidIsValid(opclass))
+               {
+                       typentry->btree_opf = get_opclass_family(opclass);
+                       typentry->btree_opintype = get_opclass_input_type(opclass);
+               }
                /* Only care about hash opclass if no btree opclass... */
-               if (typentry->btree_opc == InvalidOid)
+               if (typentry->btree_opf == InvalidOid)
                {
-                       if (typentry->hash_opc == InvalidOid)
-                               typentry->hash_opc = GetDefaultOpClass(type_id,
-                                                                                                          HASH_AM_OID);
+                       if (typentry->hash_opf == InvalidOid)
+                       {
+                               opclass = GetDefaultOpClass(type_id, HASH_AM_OID);
+                               if (OidIsValid(opclass))
+                               {
+                                       typentry->hash_opf = get_opclass_family(opclass);
+                                       typentry->hash_opintype = get_opclass_input_type(opclass);
+                               }
+                       }
                }
                else
                {
@@ -193,37 +206,42 @@ lookup_type_cache(Oid type_id, int flags)
        if ((flags & (TYPECACHE_EQ_OPR | TYPECACHE_EQ_OPR_FINFO)) &&
                typentry->eq_opr == InvalidOid)
        {
-               if (typentry->btree_opc != InvalidOid)
-                       typentry->eq_opr = get_opclass_member(typentry->btree_opc,
-                                                                                                 InvalidOid,
-                                                                                                 BTEqualStrategyNumber);
+               if (typentry->btree_opf != InvalidOid)
+                       typentry->eq_opr = get_opfamily_member(typentry->btree_opf,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  BTEqualStrategyNumber);
                if (typentry->eq_opr == InvalidOid &&
-                       typentry->hash_opc != InvalidOid)
-                       typentry->eq_opr = get_opclass_member(typentry->hash_opc,
-                                                                                                 InvalidOid,
-                                                                                                 HTEqualStrategyNumber);
+                       typentry->hash_opf != InvalidOid)
+                       typentry->eq_opr = get_opfamily_member(typentry->hash_opf,
+                                                                                                  typentry->hash_opintype,
+                                                                                                  typentry->hash_opintype,
+                                                                                                  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 (typentry->btree_opf != InvalidOid)
+                       typentry->lt_opr = get_opfamily_member(typentry->btree_opf,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  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 (typentry->btree_opf != InvalidOid)
+                       typentry->gt_opr = get_opfamily_member(typentry->btree_opf,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  BTGreaterStrategyNumber);
        }
        if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) &&
                typentry->cmp_proc == InvalidOid)
        {
-               if (typentry->btree_opc != InvalidOid)
-                       typentry->cmp_proc = get_opclass_proc(typentry->btree_opc,
-                                                                                                 InvalidOid,
-                                                                                                 BTORDER_PROC);
+               if (typentry->btree_opf != InvalidOid)
+                       typentry->cmp_proc = get_opfamily_proc(typentry->btree_opf,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  typentry->btree_opintype,
+                                                                                                  BTORDER_PROC);
        }
 
        /*
index 652f9a2..dceaf5a 100644 (file)
@@ -91,7 +91,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.70 2006/10/04 00:30:04 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.71 2006/12/23 00:43:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2104,15 +2104,16 @@ SelectSortFunction(Oid sortOperator,
        int                     i;
        HeapTuple       tuple;
        Form_pg_operator optup;
-       Oid                     opclass = InvalidOid;
+       Oid                     opfamily = InvalidOid;
+       Oid                     opinputtype = InvalidOid;
 
        /*
-        * Search pg_amop to see if the target operator is registered as the "<"
-        * or ">" operator of any btree opclass.  It's possible that it might be
+        * Search pg_amop to see if the target operator is registered as a "<"
+        * or ">" operator of any btree opfamily.  It's possible that it might be
         * registered both ways (eg, if someone were to build a "reverse sort"
-        * opclass for some reason); prefer the "<" case if so. If the operator is
-        * registered the same way in multiple opclasses, assume we can use the
-        * associated comparator function from any one.
+        * opfamily); prefer the "<" case if so. If the operator is registered the
+        * same way in multiple opfamilies, assume we can use the associated
+        * comparator function from any one.
         */
        catlist = SearchSysCacheList(AMOPOPID, 1,
                                                                 ObjectIdGetDatum(sortOperator),
@@ -2125,21 +2126,24 @@ SelectSortFunction(Oid sortOperator,
                tuple = &catlist->members[i]->tuple;
                aform = (Form_pg_amop) GETSTRUCT(tuple);
 
-               if (!opclass_is_btree(aform->amopclaid))
+               /* must be btree */
+               if (aform->amopmethod != BTREE_AM_OID)
                        continue;
-               /* must be of default subtype, too */
-               if (aform->amopsubtype != InvalidOid)
+               /* mustn't be cross-datatype, either */
+               if (aform->amoplefttype != aform->amoprighttype)
                        continue;
 
                if (aform->amopstrategy == BTLessStrategyNumber)
                {
-                       opclass = aform->amopclaid;
+                       opfamily = aform->amopfamily;
+                       opinputtype = aform->amoplefttype;
                        *kind = SORTFUNC_CMP;
                        break;                          /* done looking */
                }
                else if (aform->amopstrategy == BTGreaterStrategyNumber)
                {
-                       opclass = aform->amopclaid;
+                       opfamily = aform->amopfamily;
+                       opinputtype = aform->amoplefttype;
                        *kind = SORTFUNC_REVCMP;
                        /* keep scanning in hopes of finding a BTLess entry */
                }
@@ -2147,10 +2151,13 @@ SelectSortFunction(Oid sortOperator,
 
        ReleaseSysCacheList(catlist);
 
-       if (OidIsValid(opclass))
+       if (OidIsValid(opfamily))
        {
-               /* Found a suitable opclass, get its default comparator function */
-               *sortFunction = get_opclass_proc(opclass, InvalidOid, BTORDER_PROC);
+               /* Found a suitable opfamily, get the matching comparator function */
+               *sortFunction = get_opfamily_proc(opfamily,
+                                                                                 opinputtype,
+                                                                                 opinputtype,
+                                                                                 BTORDER_PROC);
                Assert(RegProcedureIsValid(*sortFunction));
                return;
        }
index ce5439a..cd31e13 100644 (file)
@@ -42,7 +42,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  * Portions taken from FreeBSD.
  *
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.125 2006/10/04 18:58:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.126 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1590,7 +1590,8 @@ setup_depend(void)
                 * dependencies seems hard.
                 *
                 * Note that we deliberately do not pin the system views, which
-                * haven't been created yet.
+                * haven't been created yet.  Also, no conversions, databases,
+                * or tablespaces are pinned.
                 *
                 * First delete any already-made entries; PINs override all else, and
                 * must be the only entries for their objects.
@@ -1619,6 +1620,12 @@ setup_depend(void)
                "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
                " FROM pg_opclass;\n",
                "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
+               " FROM pg_opfamily;\n",
+               "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
+               " FROM pg_amop;\n",
+               "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
+               " FROM pg_amproc;\n",
+               "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
                " FROM pg_rewrite;\n",
                "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
                " FROM pg_trigger;\n",
index c4df030..ae8d549 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.453 2006/10/09 23:36:59 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.454 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -6219,11 +6219,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        int                     i_oprnegate;
        int                     i_oprrest;
        int                     i_oprjoin;
+       int                     i_oprcanmerge;
        int                     i_oprcanhash;
-       int                     i_oprlsortop;
-       int                     i_oprrsortop;
-       int                     i_oprltcmpop;
-       int                     i_oprgtcmpop;
        char       *oprkind;
        char       *oprcode;
        char       *oprleft;
@@ -6232,11 +6229,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        char       *oprnegate;
        char       *oprrest;
        char       *oprjoin;
+       char       *oprcanmerge;
        char       *oprcanhash;
-       char       *oprlsortop;
-       char       *oprrsortop;
-       char       *oprltcmpop;
-       char       *oprgtcmpop;
 
        /* Skip if not to be dumped */
        if (!oprinfo->dobj.dump || dataOnly)
@@ -6258,7 +6252,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        /* Make sure we are in proper schema so regoperator works correctly */
        selectSourceSchema(oprinfo->dobj.namespace->dobj.name);
 
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80300)
        {
                appendPQExpBuffer(query, "SELECT oprkind, "
                                                  "oprcode::pg_catalog.regprocedure, "
@@ -6268,11 +6262,23 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "oprnegate::pg_catalog.regoperator, "
                                                  "oprrest::pg_catalog.regprocedure, "
                                                  "oprjoin::pg_catalog.regprocedure, "
-                                                 "oprcanhash, "
-                                                 "oprlsortop::pg_catalog.regoperator, "
-                                                 "oprrsortop::pg_catalog.regoperator, "
-                                                 "oprltcmpop::pg_catalog.regoperator, "
-                                                 "oprgtcmpop::pg_catalog.regoperator "
+                                                 "oprcanmerge, oprcanhash "
+                                                 "from pg_catalog.pg_operator "
+                                                 "where oid = '%u'::pg_catalog.oid",
+                                                 oprinfo->dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 70300)
+       {
+               appendPQExpBuffer(query, "SELECT oprkind, "
+                                                 "oprcode::pg_catalog.regprocedure, "
+                                                 "oprleft::pg_catalog.regtype, "
+                                                 "oprright::pg_catalog.regtype, "
+                                                 "oprcom::pg_catalog.regoperator, "
+                                                 "oprnegate::pg_catalog.regoperator, "
+                                                 "oprrest::pg_catalog.regprocedure, "
+                                                 "oprjoin::pg_catalog.regprocedure, "
+                                                 "(oprlsortop != 0) as oprcanmerge, "
+                                                 "oprcanhash "
                                                  "from pg_catalog.pg_operator "
                                                  "where oid = '%u'::pg_catalog.oid",
                                                  oprinfo->dobj.catId.oid);
@@ -6285,8 +6291,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "CASE WHEN oprright = 0 THEN '-' "
                                                  "ELSE format_type(oprright, NULL) END as oprright, "
                                                  "oprcom, oprnegate, oprrest, oprjoin, "
-                                                 "oprcanhash, oprlsortop, oprrsortop, "
-                                                 "0 as oprltcmpop, 0 as oprgtcmpop "
+                                                 "(oprlsortop != 0) as oprcanmerge, "
+                                                 "oprcanhash "
                                                  "from pg_operator "
                                                  "where oid = '%u'::oid",
                                                  oprinfo->dobj.catId.oid);
@@ -6299,8 +6305,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "CASE WHEN oprright = 0 THEN '-'::name "
                                                  "ELSE (select typname from pg_type where oid = oprright) END as oprright, "
                                                  "oprcom, oprnegate, oprrest, oprjoin, "
-                                                 "oprcanhash, oprlsortop, oprrsortop, "
-                                                 "0 as oprltcmpop, 0 as oprgtcmpop "
+                                                 "(oprlsortop != 0) as oprcanmerge, "
+                                                 "oprcanhash "
                                                  "from pg_operator "
                                                  "where oid = '%u'::oid",
                                                  oprinfo->dobj.catId.oid);
@@ -6326,11 +6332,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        i_oprnegate = PQfnumber(res, "oprnegate");
        i_oprrest = PQfnumber(res, "oprrest");
        i_oprjoin = PQfnumber(res, "oprjoin");
+       i_oprcanmerge = PQfnumber(res, "oprcanmerge");
        i_oprcanhash = PQfnumber(res, "oprcanhash");
-       i_oprlsortop = PQfnumber(res, "oprlsortop");
-       i_oprrsortop = PQfnumber(res, "oprrsortop");
-       i_oprltcmpop = PQfnumber(res, "oprltcmpop");
-       i_oprgtcmpop = PQfnumber(res, "oprgtcmpop");
 
        oprkind = PQgetvalue(res, 0, i_oprkind);
        oprcode = PQgetvalue(res, 0, i_oprcode);
@@ -6340,11 +6343,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        oprnegate = PQgetvalue(res, 0, i_oprnegate);
        oprrest = PQgetvalue(res, 0, i_oprrest);
        oprjoin = PQgetvalue(res, 0, i_oprjoin);
+       oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge);
        oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
-       oprlsortop = PQgetvalue(res, 0, i_oprlsortop);
-       oprrsortop = PQgetvalue(res, 0, i_oprrsortop);
-       oprltcmpop = PQgetvalue(res, 0, i_oprltcmpop);
-       oprgtcmpop = PQgetvalue(res, 0, i_oprgtcmpop);
 
        appendPQExpBuffer(details, "    PROCEDURE = %s",
                                          convertRegProcReference(oprcode));
@@ -6390,6 +6390,9 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        if (name)
                appendPQExpBuffer(details, ",\n    NEGATOR = %s", name);
 
+       if (strcmp(oprcanmerge, "t") == 0)
+               appendPQExpBuffer(details, ",\n    MERGES");
+
        if (strcmp(oprcanhash, "t") == 0)
                appendPQExpBuffer(details, ",\n    HASHES");
 
@@ -6401,22 +6404,6 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        if (name)
                appendPQExpBuffer(details, ",\n    JOIN = %s", name);
 
-       name = convertOperatorReference(oprlsortop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    SORT1 = %s", name);
-
-       name = convertOperatorReference(oprrsortop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    SORT2 = %s", name);
-
-       name = convertOperatorReference(oprltcmpop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    LTCMP = %s", name);
-
-       name = convertOperatorReference(oprgtcmpop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    GTCMP = %s", name);
-
        /*
         * DROP must be fully qualified in case same name appears in pg_catalog
         */
@@ -6608,13 +6595,26 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        selectSourceSchema(opcinfo->dobj.namespace->dobj.name);
 
        /* Get additional fields from the pg_opclass row */
-       appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
-                                         "opckeytype::pg_catalog.regtype, "
-                                         "opcdefault, "
-          "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
-                                         "FROM pg_catalog.pg_opclass "
-                                         "WHERE oid = '%u'::pg_catalog.oid",
-                                         opcinfo->dobj.catId.oid);
+       if (g_fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
+                                                 "opckeytype::pg_catalog.regtype, "
+                                                 "opcdefault, "
+                                                 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
+                                                 "FROM pg_catalog.pg_opclass "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
+                                                 "opckeytype::pg_catalog.regtype, "
+                                                 "opcdefault, "
+                                                 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
+                                                 "FROM pg_catalog.pg_opclass "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 opcinfo->dobj.catId.oid);
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6674,12 +6674,31 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
         */
        resetPQExpBuffer(query);
 
-       appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
-                                         "amopopr::pg_catalog.regoperator "
-                                         "FROM pg_catalog.pg_amop "
-                                         "WHERE amopclaid = '%u'::pg_catalog.oid "
-                                         "ORDER BY amopstrategy",
-                                         opcinfo->dobj.catId.oid);
+       if (g_fout->remoteVersion >= 80300)
+       {
+               /*
+                * Print only those opfamily members that are tied to the opclass
+                * by pg_depend entries.
+                */
+               appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+                                                 "amopopr::pg_catalog.regoperator "
+                                                 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+                                                 "WHERE refclassid = 'pg_catalog.pg_opclass'::regclass "
+                                                 "AND refobjid = '%u'::pg_catalog.oid "
+                                                 "AND classid = 'pg_catalog.pg_amop'::regclass "
+                                                 "AND objid = ao.oid "
+                                                 "ORDER BY amopstrategy",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+                                                 "amopopr::pg_catalog.regoperator "
+                                                 "FROM pg_catalog.pg_amop "
+                                                 "WHERE amopclaid = '%u'::pg_catalog.oid "
+                                                 "ORDER BY amopstrategy",
+                                                 opcinfo->dobj.catId.oid);
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6714,12 +6733,31 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
         */
        resetPQExpBuffer(query);
 
-       appendPQExpBuffer(query, "SELECT amprocnum, "
-                                         "amproc::pg_catalog.regprocedure "
-                                         "FROM pg_catalog.pg_amproc "
-                                         "WHERE amopclaid = '%u'::pg_catalog.oid "
-                                         "ORDER BY amprocnum",
-                                         opcinfo->dobj.catId.oid);
+       if (g_fout->remoteVersion >= 80300)
+       {
+               /*
+                * Print only those opfamily members that are tied to the opclass
+                * by pg_depend entries.
+                */
+               appendPQExpBuffer(query, "SELECT amprocnum, "
+                                                 "amproc::pg_catalog.regprocedure "
+                                                 "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
+                                                 "WHERE refclassid = 'pg_catalog.pg_opclass'::regclass "
+                                                 "AND refobjid = '%u'::pg_catalog.oid "
+                                                 "AND classid = 'pg_catalog.pg_amproc'::regclass "
+                                                 "AND objid = ap.oid "
+                                                 "ORDER BY amprocnum",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT amprocnum, "
+                                                 "amproc::pg_catalog.regprocedure "
+                                                 "FROM pg_catalog.pg_amproc "
+                                                 "WHERE amopclaid = '%u'::pg_catalog.oid "
+                                                 "ORDER BY amprocnum",
+                                                 opcinfo->dobj.catId.oid);
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
index 945c9a1..f0a840a 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.364 2006/12/21 18:32:56 petere Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.365 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200612201
+#define CATALOG_VERSION_NO     200612221
 
 #endif
index da7d7ac..b3ec0cc 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.27 2006/08/21 00:57:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.28 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -131,6 +131,9 @@ typedef enum ObjectClass
        OCLASS_LANGUAGE,                        /* pg_language */
        OCLASS_OPERATOR,                        /* pg_operator */
        OCLASS_OPCLASS,                         /* pg_opclass */
+       OCLASS_OPFAMILY,                        /* pg_opfamily */
+       OCLASS_AMOP,                            /* pg_amop */
+       OCLASS_AMPROC,                          /* pg_amproc */
        OCLASS_REWRITE,                         /* pg_rewrite */
        OCLASS_TRIGGER,                         /* pg_trigger */
        OCLASS_SCHEMA,                          /* pg_namespace */
index 6587b34..215119a 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.95 2006/07/13 17:47:01 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.96 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -65,13 +65,17 @@ DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, on pg_am using btree(amname name_op
 DECLARE_UNIQUE_INDEX(pg_am_oid_index, 2652, on pg_am using btree(oid oid_ops));
 #define AmOidIndexId  2652
 
-DECLARE_UNIQUE_INDEX(pg_amop_opc_strat_index, 2653, on pg_amop using btree(amopclaid oid_ops, amopsubtype oid_ops, amopstrategy int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, on pg_amop using btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
 #define AccessMethodStrategyIndexId  2653
-DECLARE_UNIQUE_INDEX(pg_amop_opr_opc_index, 2654, on pg_amop using btree(amopopr oid_ops, amopclaid oid_ops));
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, on pg_amop using btree(amopopr oid_ops, amopfamily oid_ops));
 #define AccessMethodOperatorIndexId  2654
+DECLARE_UNIQUE_INDEX(pg_amop_oid_index, 2756, on pg_amop using btree(oid oid_ops));
+#define AccessMethodOperatorOidIndexId  2756
 
-DECLARE_UNIQUE_INDEX(pg_amproc_opc_proc_index, 2655, on pg_amproc using btree(amopclaid oid_ops, amprocsubtype oid_ops, amprocnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, on pg_amproc using btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
 #define AccessMethodProcedureIndexId  2655
+DECLARE_UNIQUE_INDEX(pg_amproc_oid_index, 2757, on pg_amproc using btree(oid oid_ops));
+#define AccessMethodProcedureOidIndexId  2757
 
 DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index, 2656, on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
 #define AttrDefaultIndexId     2656
@@ -164,7 +168,7 @@ DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, on pg_namespace using btr
 DECLARE_UNIQUE_INDEX(pg_namespace_oid_index, 2685, on pg_namespace using btree(oid oid_ops));
 #define NamespaceOidIndexId  2685
 
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, on pg_opclass using btree(opcamid oid_ops, opcname name_ops, opcnamespace oid_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, on pg_opclass using btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
 #define OpclassAmNameNspIndexId  2686
 DECLARE_UNIQUE_INDEX(pg_opclass_oid_index, 2687, on pg_opclass using btree(oid oid_ops));
 #define OpclassOidIndexId  2687
@@ -174,6 +178,11 @@ DECLARE_UNIQUE_INDEX(pg_operator_oid_index, 2688, on pg_operator using btree(oid
 DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
 #define OperatorNameNspIndexId 2689
 
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, on pg_opfamily using btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
+#define OpfamilyAmNameNspIndexId  2754
+DECLARE_UNIQUE_INDEX(pg_opfamily_oid_index, 2755, on pg_opfamily using btree(oid oid_ops));
+#define OpfamilyOidIndexId  2755
+
 DECLARE_UNIQUE_INDEX(pg_pltemplate_name_index, 1137, on pg_pltemplate using btree(tmplname name_ops));
 #define PLTemplateNameIndexId  1137
 
index ab354f5..e1d9b19 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.42 2006/05/01 23:22:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.43 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,6 +51,9 @@ extern bool OperatorIsVisible(Oid oprid);
 extern Oid     OpclassnameGetOpcid(Oid amid, const char *opcname);
 extern bool OpclassIsVisible(Oid opcid);
 
+extern Oid     OpfamilynameGetOpfid(Oid amid, const char *opfname);
+extern bool OpfamilyIsVisible(Oid opfid);
+
 extern Oid     ConversionGetConid(const char *conname);
 extern bool ConversionIsVisible(Oid conid);
 
index 1203434..6907547 100644 (file)
@@ -4,26 +4,32 @@
  *       definition of the system "amop" relation (pg_amop)
  *       along with the relation's initial contents.
  *
- * The amop table identifies the operators associated with each index opclass.
+ * The amop table identifies the operators associated with each index operator
+ * family and operator class (classes are subsets of families).
  *
- * 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.
+ * The primary key for this table is <amopfamily, amoplefttype, amoprighttype,
+ * amopstrategy>.  amoplefttype and amoprighttype are just copies of the
+ * operator's oprleft/oprright, ie its declared input data types.  The
+ * "default" operators for a particular opclass within the family are those
+ * with amoplefttype = amoprighttype = opclass's opcintype.  An opfamily may
+ * also contain other operators, typically cross-data-type operators.  All the
+ * operators within a family are supposed to be compatible, in a way that is
+ * defined by each individual index AM.
  *
- * 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 subtypes or strategy numbers of a single opclass.
+ * We also keep a unique index on <amopfamily, amopopr>, so that we can use a
+ * syscache to quickly answer questions of the form "is this operator in this
+ * opfamily, and if so what are its semantics with respect to the family?"
+ * This implies that the same operator cannot be listed for multiple strategy
+ * numbers within a single opfamily.
+ *
+ * amopmethod is a copy of the owning opfamily's opfmethod field.  This is an
+ * intentional denormalization of the catalogs to buy lookup speed.
  *
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.75 2006/10/04 00:30:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.76 2006/12/23 00:43:12 tgl Exp $
  *
  * NOTES
  *      the genbki.sh script reads this file and generates .bki
  */
 #define AccessMethodOperatorRelationId 2602
 
-CATALOG(pg_amop,2602) BKI_WITHOUT_OIDS
+CATALOG(pg_amop,2602)
 {
-       Oid                     amopclaid;              /* the index opclass this entry is for */
-       Oid                     amopsubtype;    /* operator subtype, or zero if default */
+       Oid                     amopfamily;             /* the index opfamily this entry is for */
+       Oid                     amoplefttype;   /* operator's left input data type */
+       Oid                     amoprighttype;  /* operator's right input data type */
        int2            amopstrategy;   /* operator strategy number */
        bool            amopreqcheck;   /* index hit must be rechecked */
        Oid                     amopopr;                /* the operator's pg_operator OID */
+       Oid                     amopmethod;             /* the index access method this entry is for */
 } FormData_pg_amop;
 
 /* ----------------
@@ -68,12 +76,14 @@ typedef FormData_pg_amop *Form_pg_amop;
  *             compiler constants for pg_amop
  * ----------------
  */
-#define Natts_pg_amop                                  5
-#define Anum_pg_amop_amopclaid                 1
-#define Anum_pg_amop_amopsubtype               2
-#define Anum_pg_amop_amopstrategy              3
-#define Anum_pg_amop_amopreqcheck              4
-#define Anum_pg_amop_amopopr                   5
+#define Natts_pg_amop                                  7
+#define Anum_pg_amop_amopfamily                        1
+#define Anum_pg_amop_amoplefttype              2
+#define Anum_pg_amop_amoprighttype             3
+#define Anum_pg_amop_amopstrategy              4
+#define Anum_pg_amop_amopreqcheck              5
+#define Anum_pg_amop_amopopr                   6
+#define Anum_pg_amop_amopmethod                        7
 
 /* ----------------
  *             initial contents of pg_amop
@@ -81,815 +91,528 @@ typedef FormData_pg_amop *Form_pg_amop;
  */
 
 /*
- *     btree int2_ops
+ *     btree integer_ops
  */
 
-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 ));
+/* default operators int2 */
+DATA(insert (  1976   21 21 1 f  95    403 ));
+DATA(insert (  1976   21 21 2 f  522   403 ));
+DATA(insert (  1976   21 21 3 f  94    403 ));
+DATA(insert (  1976   21 21 4 f  524   403 ));
+DATA(insert (  1976   21 21 5 f  520   403 ));
 /* 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 ));
+DATA(insert (  1976   21 23 1 f  534   403 ));
+DATA(insert (  1976   21 23 2 f  540   403 ));
+DATA(insert (  1976   21 23 3 f  532   403 ));
+DATA(insert (  1976   21 23 4 f  542   403 ));
+DATA(insert (  1976   21 23 5 f  536   403 ));
 /* 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    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 ));
+DATA(insert (  1976   21 20 1 f  1864  403 ));
+DATA(insert (  1976   21 20 2 f  1866  403 ));
+DATA(insert (  1976   21 20 3 f  1862  403 ));
+DATA(insert (  1976   21 20 4 f  1867  403 ));
+DATA(insert (  1976   21 20 5 f  1865  403 ));
+/* default operators int4 */
+DATA(insert (  1976   23 23 1 f  97    403 ));
+DATA(insert (  1976   23 23 2 f  523   403 ));
+DATA(insert (  1976   23 23 3 f  96    403 ));
+DATA(insert (  1976   23 23 4 f  525   403 ));
+DATA(insert (  1976   23 23 5 f  521   403 ));
 /* 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 ));
+DATA(insert (  1976   23 21 1 f  535   403 ));
+DATA(insert (  1976   23 21 2 f  541   403 ));
+DATA(insert (  1976   23 21 3 f  533   403 ));
+DATA(insert (  1976   23 21 4 f  543   403 ));
+DATA(insert (  1976   23 21 5 f  537   403 ));
 /* 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    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 ));
+DATA(insert (  1976   23 20 1 f  37    403 ));
+DATA(insert (  1976   23 20 2 f  80    403 ));
+DATA(insert (  1976   23 20 3 f  15    403 ));
+DATA(insert (  1976   23 20 4 f  82    403 ));
+DATA(insert (  1976   23 20 5 f  76    403 ));
+/* default operators int8 */
+DATA(insert (  1976   20 20 1 f  412   403 ));
+DATA(insert (  1976   20 20 2 f  414   403 ));
+DATA(insert (  1976   20 20 3 f  410   403 ));
+DATA(insert (  1976   20 20 4 f  415   403 ));
+DATA(insert (  1976   20 20 5 f  413   403 ));
 /* 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 ));
+DATA(insert (  1976   20 21 1 f  1870  403 ));
+DATA(insert (  1976   20 21 2 f  1872  403 ));
+DATA(insert (  1976   20 21 3 f  1868  403 ));
+DATA(insert (  1976   20 21 4 f  1873  403 ));
+DATA(insert (  1976   20 21 5 f  1871  403 ));
 /* 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 ));
+DATA(insert (  1976   20 23 1 f  418   403 ));
+DATA(insert (  1976   20 23 2 f  420   403 ));
+DATA(insert (  1976   20 23 3 f  416   403 ));
+DATA(insert (  1976   20 23 4 f  430   403 ));
+DATA(insert (  1976   20 23 5 f  419   403 ));
 
 /*
  *     btree oid_ops
  */
 
-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 ));
+DATA(insert (  1989   26 26 1 f  609   403 ));
+DATA(insert (  1989   26 26 2 f  611   403 ));
+DATA(insert (  1989   26 26 3 f  607   403 ));
+DATA(insert (  1989   26 26 4 f  612   403 ));
+DATA(insert (  1989   26 26 5 f  610   403 ));
 
 /*
  * btree tid_ops
  */
 
-DATA(insert (  2789    0 1 f 2799 ));
-DATA(insert (  2789    0 2 f 2801 ));
-DATA(insert (  2789    0 3 f 387  ));
-DATA(insert (  2789    0 4 f 2802 ));
-DATA(insert (  2789    0 5 f 2800 ));
+DATA(insert (  2789   27 27 1 f 2799   403 ));
+DATA(insert (  2789   27 27 2 f 2801   403 ));
+DATA(insert (  2789   27 27 3 f 387    403 ));
+DATA(insert (  2789   27 27 4 f 2802   403 ));
+DATA(insert (  2789   27 27 5 f 2800   403 ));
 
 /*
  *     btree oidvector_ops
  */
 
-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 ));
+DATA(insert (  1991   30 30 1 f  645   403 ));
+DATA(insert (  1991   30 30 2 f  647   403 ));
+DATA(insert (  1991   30 30 3 f  649   403 ));
+DATA(insert (  1991   30 30 4 f  648   403 ));
+DATA(insert (  1991   30 30 5 f  646   403 ));
 
 /*
- *     btree float4_ops
+ *     btree float_ops
  */
 
-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 ));
+/* default operators float4 */
+DATA(insert (  1970   700 700 1 f  622 403 ));
+DATA(insert (  1970   700 700 2 f  624 403 ));
+DATA(insert (  1970   700 700 3 f  620 403 ));
+DATA(insert (  1970   700 700 4 f  625 403 ));
+DATA(insert (  1970   700 700 5 f  623 403 ));
 /* 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    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 ));
+DATA(insert (  1970   700 701 1 f  1122 403 ));
+DATA(insert (  1970   700 701 2 f  1124 403 ));
+DATA(insert (  1970   700 701 3 f  1120 403 ));
+DATA(insert (  1970   700 701 4 f  1125 403 ));
+DATA(insert (  1970   700 701 5 f  1123 403 ));
+/* default operators float8 */
+DATA(insert (  1970   701 701 1 f  672 403 ));
+DATA(insert (  1970   701 701 2 f  673 403 ));
+DATA(insert (  1970   701 701 3 f  670 403 ));
+DATA(insert (  1970   701 701 4 f  675 403 ));
+DATA(insert (  1970   701 701 5 f  674 403 ));
 /* 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 ));
+DATA(insert (  1970   701 700 1 f  1132 403 ));
+DATA(insert (  1970   701 700 2 f  1134 403 ));
+DATA(insert (  1970   701 700 3 f  1130 403 ));
+DATA(insert (  1970   701 700 4 f  1135 403 ));
+DATA(insert (  1970   701 700 5 f  1133 403 ));
 
 /*
  *     btree char_ops
  */
 
-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 ));
+DATA(insert (  429   18 18 1 f  631    403 ));
+DATA(insert (  429   18 18 2 f  632    403 ));
+DATA(insert (  429   18 18 3 f 92      403 ));
+DATA(insert (  429   18 18 4 f  634    403 ));
+DATA(insert (  429   18 18 5 f  633    403 ));
 
 /*
  *     btree name_ops
  */
 
-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 ));
+DATA(insert (  1986   19 19 1 f  660   403 ));
+DATA(insert (  1986   19 19 2 f  661   403 ));
+DATA(insert (  1986   19 19 3 f        93      403 ));
+DATA(insert (  1986   19 19 4 f  663   403 ));
+DATA(insert (  1986   19 19 5 f  662   403 ));
 
 /*
  *     btree text_ops
  */
 
-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 ));
+DATA(insert (  1994   25 25 1 f  664   403 ));
+DATA(insert (  1994   25 25 2 f  665   403 ));
+DATA(insert (  1994   25 25 3 f        98      403 ));
+DATA(insert (  1994   25 25 4 f  667   403 ));
+DATA(insert (  1994   25 25 5 f  666   403 ));
 
 /*
  *     btree bpchar_ops
  */
 
-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    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 ));
+DATA(insert (  426   1042 1042 1 f 1058        403 ));
+DATA(insert (  426   1042 1042 2 f 1059        403 ));
+DATA(insert (  426   1042 1042 3 f 1054        403 ));
+DATA(insert (  426   1042 1042 4 f 1061        403 ));
+DATA(insert (  426   1042 1042 5 f 1060        403 ));
 
 /*
  *     btree bytea_ops
  */
 
-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 ));
+DATA(insert (  428   17 17 1 f 1957    403 ));
+DATA(insert (  428   17 17 2 f 1958    403 ));
+DATA(insert (  428   17 17 3 f 1955    403 ));
+DATA(insert (  428   17 17 4 f 1960    403 ));
+DATA(insert (  428   17 17 5 f 1959    403 ));
 
 /*
  *     btree abstime_ops
  */
 
-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 ));
+DATA(insert (  421   702 702 1 f  562  403 ));
+DATA(insert (  421   702 702 2 f  564  403 ));
+DATA(insert (  421   702 702 3 f  560  403 ));
+DATA(insert (  421   702 702 4 f  565  403 ));
+DATA(insert (  421   702 702 5 f  563  403 ));
 
 /*
- *     btree date_ops
+ *     btree datetime_ops
  */
 
-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 ));
+/* default operators date */
+DATA(insert (  434   1082 1082 1 f 1095        403 ));
+DATA(insert (  434   1082 1082 2 f 1096        403 ));
+DATA(insert (  434   1082 1082 3 f 1093        403 ));
+DATA(insert (  434   1082 1082 4 f 1098        403 ));
+DATA(insert (  434   1082 1082 5 f 1097        403 ));
 /* crosstype operators vs timestamp */
-DATA(insert (   434 1114 1 f 2345 ));
-DATA(insert (   434 1114 2 f 2346 ));
-DATA(insert (   434 1114 3 f 2347 ));
-DATA(insert (   434 1114 4 f 2348 ));
-DATA(insert (   434 1114 5 f 2349 ));
+DATA(insert (  434   1082 1114 1 f 2345        403 ));
+DATA(insert (  434   1082 1114 2 f 2346        403 ));
+DATA(insert (  434   1082 1114 3 f 2347        403 ));
+DATA(insert (  434   1082 1114 4 f 2348        403 ));
+DATA(insert (  434   1082 1114 5 f 2349        403 ));
 /* crosstype operators vs timestamptz */
-DATA(insert (   434 1184 1 f 2358 ));
-DATA(insert (   434 1184 2 f 2359 ));
-DATA(insert (   434 1184 3 f 2360 ));
-DATA(insert (   434 1184 4 f 2361 ));
-DATA(insert (   434 1184 5 f 2362 ));
+DATA(insert (  434   1082 1184 1 f 2358        403 ));
+DATA(insert (  434   1082 1184 2 f 2359        403 ));
+DATA(insert (  434   1082 1184 3 f 2360        403 ));
+DATA(insert (  434   1082 1184 4 f 2361        403 ));
+DATA(insert (  434   1082 1184 5 f 2362        403 ));
+/* default operators timestamp */
+DATA(insert (  434   1114 1114 1 f 2062        403 ));
+DATA(insert (  434   1114 1114 2 f 2063        403 ));
+DATA(insert (  434   1114 1114 3 f 2060        403 ));
+DATA(insert (  434   1114 1114 4 f 2065        403 ));
+DATA(insert (  434   1114 1114 5 f 2064        403 ));
+/* crosstype operators vs date */
+DATA(insert (  434   1114 1082 1 f 2371        403 ));
+DATA(insert (  434   1114 1082 2 f 2372        403 ));
+DATA(insert (  434   1114 1082 3 f 2373        403 ));
+DATA(insert (  434   1114 1082 4 f 2374        403 ));
+DATA(insert (  434   1114 1082 5 f 2375        403 ));
+/* crosstype operators vs timestamptz */
+DATA(insert (  434   1114 1184 1 f 2534        403 ));
+DATA(insert (  434   1114 1184 2 f 2535        403 ));
+DATA(insert (  434   1114 1184 3 f 2536        403 ));
+DATA(insert (  434   1114 1184 4 f 2537        403 ));
+DATA(insert (  434   1114 1184 5 f 2538        403 ));
+/* default operators timestamptz */
+DATA(insert (  434   1184 1184 1 f 1322        403 ));
+DATA(insert (  434   1184 1184 2 f 1323        403 ));
+DATA(insert (  434   1184 1184 3 f 1320        403 ));
+DATA(insert (  434   1184 1184 4 f 1325        403 ));
+DATA(insert (  434   1184 1184 5 f 1324        403 ));
+/* crosstype operators vs date */
+DATA(insert (  434   1184 1082 1 f 2384        403 ));
+DATA(insert (  434   1184 1082 2 f 2385        403 ));
+DATA(insert (  434   1184 1082 3 f 2386        403 ));
+DATA(insert (  434   1184 1082 4 f 2387        403 ));
+DATA(insert (  434   1184 1082 5 f 2388        403 ));
+/* crosstype operators vs timestamp */
+DATA(insert (  434   1184 1114 1 f 2540        403 ));
+DATA(insert (  434   1184 1114 2 f 2541        403 ));
+DATA(insert (  434   1184 1114 3 f 2542        403 ));
+DATA(insert (  434   1184 1114 4 f 2543        403 ));
+DATA(insert (  434   1184 1114 5 f 2544        403 ));
 
 /*
  *     btree time_ops
  */
 
-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 ));
+DATA(insert (  1996   1083 1083 1 f 1110       403 ));
+DATA(insert (  1996   1083 1083 2 f 1111       403 ));
+DATA(insert (  1996   1083 1083 3 f 1108       403 ));
+DATA(insert (  1996   1083 1083 4 f 1113       403 ));
+DATA(insert (  1996   1083 1083 5 f 1112       403 ));
 
 /*
  *     btree timetz_ops
  */
 
-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    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 ));
-/* crosstype operators vs date */
-DATA(insert (  2039 1082 1 f 2371 ));
-DATA(insert (  2039 1082 2 f 2372 ));
-DATA(insert (  2039 1082 3 f 2373 ));
-DATA(insert (  2039 1082 4 f 2374 ));
-DATA(insert (  2039 1082 5 f 2375 ));
-/* crosstype operators vs timestamptz */
-DATA(insert (  2039 1184 1 f 2534 ));
-DATA(insert (  2039 1184 2 f 2535 ));
-DATA(insert (  2039 1184 3 f 2536 ));
-DATA(insert (  2039 1184 4 f 2537 ));
-DATA(insert (  2039 1184 5 f 2538 ));
-
-/*
- *     btree timestamptz_ops
- */
-
-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 ));
-/* crosstype operators vs date */
-DATA(insert (  1998 1082 1 f 2384 ));
-DATA(insert (  1998 1082 2 f 2385 ));
-DATA(insert (  1998 1082 3 f 2386 ));
-DATA(insert (  1998 1082 4 f 2387 ));
-DATA(insert (  1998 1082 5 f 2388 ));
-/* crosstype operators vs timestamp */
-DATA(insert (  1998 1114 1 f 2540 ));
-DATA(insert (  1998 1114 2 f 2541 ));
-DATA(insert (  1998 1114 3 f 2542 ));
-DATA(insert (  1998 1114 4 f 2543 ));
-DATA(insert (  1998 1114 5 f 2544 ));
+DATA(insert (  2000   1266 1266 1 f 1552       403 ));
+DATA(insert (  2000   1266 1266 2 f 1553       403 ));
+DATA(insert (  2000   1266 1266 3 f 1550       403 ));
+DATA(insert (  2000   1266 1266 4 f 1555       403 ));
+DATA(insert (  2000   1266 1266 5 f 1554       403 ));
 
 /*
  *     btree interval_ops
  */
 
-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 ));
+DATA(insert (  1982   1186 1186 1 f 1332       403 ));
+DATA(insert (  1982   1186 1186 2 f 1333       403 ));
+DATA(insert (  1982   1186 1186 3 f 1330       403 ));
+DATA(insert (  1982   1186 1186 4 f 1335       403 ));
+DATA(insert (  1982   1186 1186 5 f 1334       403 ));
 
 /*
  *     btree macaddr
  */
 
-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 ));
+DATA(insert (  1984   829 829 1 f 1222 403 ));
+DATA(insert (  1984   829 829 2 f 1223 403 ));
+DATA(insert (  1984   829 829 3 f 1220 403 ));
+DATA(insert (  1984   829 829 4 f 1225 403 ));
+DATA(insert (  1984   829 829 5 f 1224 403 ));
 
 /*
- *     btree inet
+ *     btree network
  */
 
-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    0 1 f 1203 ));
-DATA(insert (   432    0 2 f 1204 ));
-DATA(insert (   432    0 3 f 1201 ));
-DATA(insert (   432    0 4 f 1206 ));
-DATA(insert (   432    0 5 f 1205 ));
+DATA(insert (  1974   869 869 1 f 1203 403 ));
+DATA(insert (  1974   869 869 2 f 1204 403 ));
+DATA(insert (  1974   869 869 3 f 1201 403 ));
+DATA(insert (  1974   869 869 4 f 1206 403 ));
+DATA(insert (  1974   869 869 5 f 1205 403 ));
 
 /*
  *     btree numeric
  */
 
-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 ));
+DATA(insert (  1988   1700 1700 1 f 1754       403 ));
+DATA(insert (  1988   1700 1700 2 f 1755       403 ));
+DATA(insert (  1988   1700 1700 3 f 1752       403 ));
+DATA(insert (  1988   1700 1700 4 f 1757       403 ));
+DATA(insert (  1988   1700 1700 5 f 1756       403 ));
 
 /*
  *     btree bool
  */
 
-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 ));
+DATA(insert (  424   16 16 1 f 58      403 ));
+DATA(insert (  424   16 16 2 f 1694    403 ));
+DATA(insert (  424   16 16 3 f 91      403 ));
+DATA(insert (  424   16 16 4 f 1695    403 ));
+DATA(insert (  424   16 16 5 f 59      403 ));
 
 /*
  *     btree bit
  */
 
-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 ));
+DATA(insert (  423   1560 1560 1 f 1786        403 ));
+DATA(insert (  423   1560 1560 2 f 1788        403 ));
+DATA(insert (  423   1560 1560 3 f 1784        403 ));
+DATA(insert (  423   1560 1560 4 f 1789        403 ));
+DATA(insert (  423   1560 1560 5 f 1787        403 ));
 
 /*
  *     btree varbit
  */
 
-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 ));
+DATA(insert (  2002   1562 1562 1 f 1806       403 ));
+DATA(insert (  2002   1562 1562 2 f 1808       403 ));
+DATA(insert (  2002   1562 1562 3 f 1804       403 ));
+DATA(insert (  2002   1562 1562 4 f 1809       403 ));
+DATA(insert (  2002   1562 1562 5 f 1807       403 ));
 
 /*
  *     btree text pattern
  */
 
-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    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 ));
+DATA(insert (  2095   25 25 1 f 2314   403 ));
+DATA(insert (  2095   25 25 2 f 2315   403 ));
+DATA(insert (  2095   25 25 3 f 2316   403 ));
+DATA(insert (  2095   25 25 4 f 2317   403 ));
+DATA(insert (  2095   25 25 5 f 2318   403 ));
 
 /*
  *     btree bpchar pattern
  */
 
-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 ));
+DATA(insert (  2097   1042 1042 1 f 2326       403 ));
+DATA(insert (  2097   1042 1042 2 f 2327       403 ));
+DATA(insert (  2097   1042 1042 3 f 2328       403 ));
+DATA(insert (  2097   1042 1042 4 f 2329       403 ));
+DATA(insert (  2097   1042 1042 5 f 2330       403 ));
 
 /*
  *     btree name pattern
  */
 
-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 ));
+DATA(insert (  2098   19 19 1 f 2332   403 ));
+DATA(insert (  2098   19 19 2 f 2333   403 ));
+DATA(insert (  2098   19 19 3 f 2334   403 ));
+DATA(insert (  2098   19 19 4 f 2335   403 ));
+DATA(insert (  2098   19 19 5 f 2336   403 ));
 
 /*
  *     btree money_ops
  */
 
-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 ));
+DATA(insert (  2099   790 790 1 f  902 403 ));
+DATA(insert (  2099   790 790 2 f  904 403 ));
+DATA(insert (  2099   790 790 3 f  900 403 ));
+DATA(insert (  2099   790 790 4 f  905 403 ));
+DATA(insert (  2099   790 790 5 f  903 403 ));
 
 /*
  *     btree reltime_ops
  */
 
-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 ));
+DATA(insert (  2233   703 703 1 f  568 403 ));
+DATA(insert (  2233   703 703 2 f  570 403 ));
+DATA(insert (  2233   703 703 3 f  566 403 ));
+DATA(insert (  2233   703 703 4 f  571 403 ));
+DATA(insert (  2233   703 703 5 f  569 403 ));
 
 /*
  *     btree tinterval_ops
  */
 
-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 ));
+DATA(insert (  2234   704 704 1 f  813 403 ));
+DATA(insert (  2234   704 704 2 f  815 403 ));
+DATA(insert (  2234   704 704 3 f  811 403 ));
+DATA(insert (  2234   704 704 4 f  816 403 ));
+DATA(insert (  2234   704 704 5 f  814 403 ));
 
 /*
  *     btree array_ops
  */
 
-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 ));
+DATA(insert (  397   2277 2277 1 f 1072        403 ));
+DATA(insert (  397   2277 2277 2 f 1074        403 ));
+DATA(insert (  397   2277 2277 3 f 1070        403 ));
+DATA(insert (  397   2277 2277 4 f 1075        403 ));
+DATA(insert (  397   2277 2277 5 f 1073        403 ));
 
 /*
  *     hash index _ops
  */
 
 /* bpchar_ops */
-DATA(insert (   427    0 1 f 1054 ));
+DATA(insert (  427   1042 1042 1 f 1054        405 ));
 /* char_ops */
-DATA(insert (   431    0 1 f   92 ));
-/* cidr_ops */
-DATA(insert (   433    0 1 f 1201 ));
+DATA(insert (  431   18 18 1 f 92      405 ));
 /* date_ops */
-DATA(insert (   435    0 1 f 1093 ));
-/* float4_ops */
-DATA(insert (  1971    0 1 f  620 ));
-/* float8_ops */
-DATA(insert (  1973    0 1 f  670 ));
-/* inet_ops */
-DATA(insert (  1975    0 1 f 1201 ));
-/* int2_ops */
-DATA(insert (  1977    0 1 f   94 ));
-/* int4_ops */
-DATA(insert (  1979    0 1 f   96 ));
-/* int8_ops */
-DATA(insert (  1981    0 1 f  410 ));
+DATA(insert (  435   1082 1082 1 f 1093        405 ));
+/* float_ops */
+DATA(insert (  1971   700 700 1 f  620 405 ));
+DATA(insert (  1971   701 701 1 f  670 405 ));
+/* network_ops */
+DATA(insert (  1975   869 869 1 f 1201 405 ));
+/* integer_ops */
+DATA(insert (  1977   21 21 1 f        94      405 ));
+DATA(insert (  1977   23 23 1 f        96      405 ));
+DATA(insert (  1977   20 20 1 f        410     405 ));
 /* interval_ops */
-DATA(insert (  1983    0 1 f 1330 ));
+DATA(insert (  1983   1186 1186 1 f 1330       405 ));
 /* macaddr_ops */
-DATA(insert (  1985    0 1 f 1220 ));
+DATA(insert (  1985   829 829 1 f 1220 405 ));
 /* name_ops */
-DATA(insert (  1987    0 1 f   93 ));
+DATA(insert (  1987   19 19 1 f        93      405 ));
 /* oid_ops */
-DATA(insert (  1990    0 1 f  607 ));
+DATA(insert (  1990   26 26 1 f  607   405 ));
 /* oidvector_ops */
-DATA(insert (  1992    0 1 f  649 ));
+DATA(insert (  1992   30 30 1 f  649   405 ));
 /* text_ops */
-DATA(insert (  1995    0 1 f   98 ));
+DATA(insert (  1995   25 25 1 f        98      405 ));
 /* time_ops */
-DATA(insert (  1997    0 1 f 1108 ));
+DATA(insert (  1997   1083 1083 1 f 1108       405 ));
 /* timestamptz_ops */
-DATA(insert (  1999    0 1 f 1320 ));
+DATA(insert (  1999   1184 1184 1 f 1320       405 ));
 /* timetz_ops */
-DATA(insert (  2001    0 1 f 1550 ));
-/* varchar_ops */
-DATA(insert (  2004    0 1 f   98 ));
+DATA(insert (  2001   1266 1266 1 f 1550       405 ));
 /* timestamp_ops */
-DATA(insert (  2040    0 1 f 2060 ));
+DATA(insert (  2040   1114 1114 1 f 2060       405 ));
 /* bool_ops */
-DATA(insert (  2222    0 1 f   91 ));
+DATA(insert (  2222   16 16 1 f        91      405 ));
 /* bytea_ops */
-DATA(insert (  2223    0 1 f 1955 ));
+DATA(insert (  2223   17 17 1 f 1955   405 ));
 /* int2vector_ops */
-DATA(insert (  2224    0 1 f  386 ));
+DATA(insert (  2224   22 22 1 f  386   405 ));
 /* xid_ops */
-DATA(insert (  2225    0 1 f  352 ));
+DATA(insert (  2225   28 28 1 f  352   405 ));
 /* cid_ops */
-DATA(insert (  2226    0 1 f  385 ));
+DATA(insert (  2226   29 29 1 f  385   405 ));
 /* abstime_ops */
-DATA(insert (  2227    0 1 f  560 ));
+DATA(insert (  2227   702 702 1 f  560 405 ));
 /* reltime_ops */
-DATA(insert (  2228    0 1 f  566 ));
+DATA(insert (  2228   703 703 1 f  566 405 ));
 /* text_pattern_ops */
-DATA(insert (  2229    0 1 f 2316 ));
-/* varchar_pattern_ops */
-DATA(insert (  2230    0 1 f 2316 ));
+DATA(insert (  2229   25 25 1 f 2316   405 ));
 /* bpchar_pattern_ops */
-DATA(insert (  2231    0 1 f 2328 ));
+DATA(insert (  2231   1042 1042 1 f 2328       405 ));
 /* name_pattern_ops */
-DATA(insert (  2232    0 1 f 2334 ));
+DATA(insert (  2232   19 19 1 f 2334   405 ));
 /* aclitem_ops */
-DATA(insert (  2235    0 1 f  974 ));
+DATA(insert (  2235   1033 1033 1 f  974       405 ));
 
 /*
  *     gist box_ops
  */
 
-DATA(insert (  2593    0 1  f  493 ));
-DATA(insert (  2593    0 2  f  494 ));
-DATA(insert (  2593    0 3  f  500 ));
-DATA(insert (  2593    0 4  f  495 ));
-DATA(insert (  2593    0 5  f  496 ));
-DATA(insert (  2593    0 6  f  499 ));
-DATA(insert (  2593    0 7  f  498 ));
-DATA(insert (  2593    0 8  f  497 ));
-DATA(insert (  2593    0 9  f  2571 ));
-DATA(insert (  2593    0 10 f  2570 ));
-DATA(insert (  2593    0 11 f  2573 ));
-DATA(insert (  2593    0 12 f  2572 ));
-DATA(insert (  2593    0 13 f  2863 ));
-DATA(insert (  2593    0 14 f  2862 ));
+DATA(insert (  2593   603 603 1  f     493     783 ));
+DATA(insert (  2593   603 603 2  f     494     783 ));
+DATA(insert (  2593   603 603 3  f     500     783 ));
+DATA(insert (  2593   603 603 4  f     495     783 ));
+DATA(insert (  2593   603 603 5  f     496     783 ));
+DATA(insert (  2593   603 603 6  f     499     783 ));
+DATA(insert (  2593   603 603 7  f     498     783 ));
+DATA(insert (  2593   603 603 8  f     497     783 ));
+DATA(insert (  2593   603 603 9  f     2571    783 ));
+DATA(insert (  2593   603 603 10 f     2570    783 ));
+DATA(insert (  2593   603 603 11 f     2573    783 ));
+DATA(insert (  2593   603 603 12 f     2572    783 ));
+DATA(insert (  2593   603 603 13 f     2863    783 ));
+DATA(insert (  2593   603 603 14 f     2862    783 ));
 
 /*
  *     gist poly_ops (supports polygons)
  */
 
-DATA(insert (  2594    0 1  t  485 ));
-DATA(insert (  2594    0 2  t  486 ));
-DATA(insert (  2594    0 3  t  492 ));
-DATA(insert (  2594    0 4  t  487 ));
-DATA(insert (  2594    0 5  t  488 ));
-DATA(insert (  2594    0 6  t  491 ));
-DATA(insert (  2594    0 7  t  490 ));
-DATA(insert (  2594    0 8  t  489 ));
-DATA(insert (  2594    0 9  t  2575 ));
-DATA(insert (  2594    0 10 t  2574 ));
-DATA(insert (  2594    0 11 t  2577 ));
-DATA(insert (  2594    0 12 t  2576 ));
-DATA(insert (  2594    0 13 t  2861 ));
-DATA(insert (  2594    0 14 t  2860 ));
+DATA(insert (  2594   604 604 1  t     485     783 ));
+DATA(insert (  2594   604 604 2  t     486     783 ));
+DATA(insert (  2594   604 604 3  t     492     783 ));
+DATA(insert (  2594   604 604 4  t     487     783 ));
+DATA(insert (  2594   604 604 5  t     488     783 ));
+DATA(insert (  2594   604 604 6  t     491     783 ));
+DATA(insert (  2594   604 604 7  t     490     783 ));
+DATA(insert (  2594   604 604 8  t     489     783 ));
+DATA(insert (  2594   604 604 9  t     2575    783 ));
+DATA(insert (  2594   604 604 10 t     2574    783 ));
+DATA(insert (  2594   604 604 11 t     2577    783 ));
+DATA(insert (  2594   604 604 12 t     2576    783 ));
+DATA(insert (  2594   604 604 13 t     2861    783 ));
+DATA(insert (  2594   604 604 14 t     2860    783 ));
 
 /*
  *     gist circle_ops
  */
 
-DATA(insert (  2595    0 1  t  1506 ));
-DATA(insert (  2595    0 2  t  1507 ));
-DATA(insert (  2595    0 3  t  1513 ));
-DATA(insert (  2595    0 4  t  1508 ));
-DATA(insert (  2595    0 5  t  1509 ));
-DATA(insert (  2595    0 6  t  1512 ));
-DATA(insert (  2595    0 7  t  1511 ));
-DATA(insert (  2595    0 8  t  1510 ));
-DATA(insert (  2595    0 9  t  2589 ));
-DATA(insert (  2595    0 10 t  1515 ));
-DATA(insert (  2595    0 11 t  1514 ));
-DATA(insert (  2595    0 12 t  2590 ));
-DATA(insert (  2595    0 13 t  2865 ));
-DATA(insert (  2595    0 14 t  2864 ));
-
-/*
- * gin _int4_ops
- */
-DATA(insert (  2745    0 1  f  2750 ));
-DATA(insert (  2745    0 2  f  2751 ));
-DATA(insert (  2745    0 3  t  2752 ));
-DATA(insert (  2745    0 4  t  1070 ));
-
-/*
- * gin _text_ops
- */
-DATA(insert (  2746    0 1  f  2750 ));
-DATA(insert (  2746    0 2  f  2751 ));
-DATA(insert (  2746    0 3  t  2752 ));
-DATA(insert (  2746    0 4  t  1070 ));
-
-/*
- * gin _abstime_ops
- */
-DATA(insert (  2753    0 1  f  2750 ));
-DATA(insert (  2753    0 2  f  2751 ));
-DATA(insert (  2753    0 3  t  2752 ));
-DATA(insert (  2753    0 4  t  1070 ));
-
-/*
- * gin _bit_ops
- */
-DATA(insert (  2754    0 1  f  2750 ));
-DATA(insert (  2754    0 2  f  2751 ));
-DATA(insert (  2754    0 3  t  2752 ));
-DATA(insert (  2754    0 4  t  1070 ));
-
-/*
- * gin _bool_ops
- */
-DATA(insert (  2755    0 1  f  2750 ));
-DATA(insert (  2755    0 2  f  2751 ));
-DATA(insert (  2755    0 3  t  2752 ));
-DATA(insert (  2755    0 4  t  1070 ));
-
-/*
- * gin _bpchar_ops
- */
-DATA(insert (  2756    0 1  f  2750 ));
-DATA(insert (  2756    0 2  f  2751 ));
-DATA(insert (  2756    0 3  t  2752 ));
-DATA(insert (  2756    0 4  t  1070 ));
-
-/*
- * gin _bytea_ops
- */
-DATA(insert (  2757    0 1  f  2750 ));
-DATA(insert (  2757    0 2  f  2751 ));
-DATA(insert (  2757    0 3  t  2752 ));
-DATA(insert (  2757    0 4  t  1070 ));
-
-/*
- * gin _char_ops
- */
-DATA(insert (  2758    0 1  f  2750 ));
-DATA(insert (  2758    0 2  f  2751 ));
-DATA(insert (  2758    0 3  t  2752 ));
-DATA(insert (  2758    0 4  t  1070 ));
-
-/*
- * gin _cidr_ops
- */
-DATA(insert (  2759    0 1  f  2750 ));
-DATA(insert (  2759    0 2  f  2751 ));
-DATA(insert (  2759    0 3  t  2752 ));
-DATA(insert (  2759    0 4  t  1070 ));
-
-/*
- * gin _date_ops
- */
-DATA(insert (  2760    0 1  f  2750 ));
-DATA(insert (  2760    0 2  f  2751 ));
-DATA(insert (  2760    0 3  t  2752 ));
-DATA(insert (  2760    0 4  t  1070 ));
-
-/*
- * gin _float4_ops
- */
-DATA(insert (  2761    0 1  f  2750 ));
-DATA(insert (  2761    0 2  f  2751 ));
-DATA(insert (  2761    0 3  t  2752 ));
-DATA(insert (  2761    0 4  t  1070 ));
-
-/*
- * gin _float8_ops
- */
-DATA(insert (  2762    0 1  f  2750 ));
-DATA(insert (  2762    0 2  f  2751 ));
-DATA(insert (  2762    0 3  t  2752 ));
-DATA(insert (  2762    0 4  t  1070 ));
-
-/*
- * gin _inet_ops
- */
-DATA(insert (  2763    0 1  f  2750 ));
-DATA(insert (  2763    0 2  f  2751 ));
-DATA(insert (  2763    0 3  t  2752 ));
-DATA(insert (  2763    0 4  t  1070 ));
-
-/*
- * gin _int2_ops
- */
-DATA(insert (  2764    0 1  f  2750 ));
-DATA(insert (  2764    0 2  f  2751 ));
-DATA(insert (  2764    0 3  t  2752 ));
-DATA(insert (  2764    0 4  t  1070 ));
-
-/*
- * gin _int8_ops
- */
-DATA(insert (  2765    0 1  f  2750 ));
-DATA(insert (  2765    0 2  f  2751 ));
-DATA(insert (  2765    0 3  t  2752 ));
-DATA(insert (  2765    0 4  t  1070 ));
-
-/*
- * gin _interval_ops
- */
-DATA(insert (  2766    0 1  f  2750 ));
-DATA(insert (  2766    0 2  f  2751 ));
-DATA(insert (  2766    0 3  t  2752 ));
-DATA(insert (  2766    0 4  t  1070 ));
-
-/*
- * gin _macaddr_ops
- */
-DATA(insert (  2767    0 1  f  2750 ));
-DATA(insert (  2767    0 2  f  2751 ));
-DATA(insert (  2767    0 3  t  2752 ));
-DATA(insert (  2767    0 4  t  1070 ));
-
-/*
- * gin _name_ops
- */
-DATA(insert (  2768    0 1  f  2750 ));
-DATA(insert (  2768    0 2  f  2751 ));
-DATA(insert (  2768    0 3  t  2752 ));
-DATA(insert (  2768    0 4  t  1070 ));
-
-/*
- * gin _numeric_ops
- */
-DATA(insert (  2769    0 1  f  2750 ));
-DATA(insert (  2769    0 2  f  2751 ));
-DATA(insert (  2769    0 3  t  2752 ));
-DATA(insert (  2769    0 4  t  1070 ));
-
-/*
- * gin _oid_ops
- */
-DATA(insert (  2770    0 1  f  2750 ));
-DATA(insert (  2770    0 2  f  2751 ));
-DATA(insert (  2770    0 3  t  2752 ));
-DATA(insert (  2770    0 4  t  1070 ));
-
-/*
- * gin _oidvector_ops
- */
-DATA(insert (  2771    0 1  f  2750 ));
-DATA(insert (  2771    0 2  f  2751 ));
-DATA(insert (  2771    0 3  t  2752 ));
-DATA(insert (  2771    0 4  t  1070 ));
-
-/*
- * gin _time_ops
- */
-DATA(insert (  2772    0 1  f  2750 ));
-DATA(insert (  2772    0 2  f  2751 ));
-DATA(insert (  2772    0 3  t  2752 ));
-DATA(insert (  2772    0 4  t  1070 ));
-
-/*
- * gin _timestamptz_ops
- */
-DATA(insert (  2773    0 1  f  2750 ));
-DATA(insert (  2773    0 2  f  2751 ));
-DATA(insert (  2773    0 3  t  2752 ));
-DATA(insert (  2773    0 4  t  1070 ));
-
-/*
- * gin _timetz_ops
- */
-DATA(insert (  2774    0 1  f  2750 ));
-DATA(insert (  2774    0 2  f  2751 ));
-DATA(insert (  2774    0 3  t  2752 ));
-DATA(insert (  2774    0 4  t  1070 ));
-
-/*
- * gin _varbit_ops
- */
-DATA(insert (  2775    0 1  f  2750 ));
-DATA(insert (  2775    0 2  f  2751 ));
-DATA(insert (  2775    0 3  t  2752 ));
-DATA(insert (  2775    0 4  t  1070 ));
-
-/*
- * gin _varchar_ops
- */
-DATA(insert (  2776    0 1  f  2750 ));
-DATA(insert (  2776    0 2  f  2751 ));
-DATA(insert (  2776    0 3  t  2752 ));
-DATA(insert (  2776    0 4  t  1070 ));
-
-/*
- * gin _timestamp_ops
- */
-DATA(insert (  2777    0 1  f  2750 ));
-DATA(insert (  2777    0 2  f  2751 ));
-DATA(insert (  2777    0 3  t  2752 ));
-DATA(insert (  2777    0 4  t  1070 ));
-
-/*
- * gin _money_ops
- */
-DATA(insert (  2778    0 1  f  2750 ));
-DATA(insert (  2778    0 2  f  2751 ));
-DATA(insert (  2778    0 3  t  2752 ));
-DATA(insert (  2778    0 4  t  1070 ));
-
-/*
- * gin _reltime_ops
- */
-DATA(insert (  2779    0 1  f  2750 ));
-DATA(insert (  2779    0 2  f  2751 ));
-DATA(insert (  2779    0 3  t  2752 ));
-DATA(insert (  2779    0 4  t  1070 ));
-
-/*
- * gin _tinterval_ops
- */
-DATA(insert (  2780    0 1  f  2750 ));
-DATA(insert (  2780    0 2  f  2751 ));
-DATA(insert (  2780    0 3  t  2752 ));
-DATA(insert (  2780    0 4  t  1070 ));
+DATA(insert (  2595   718 718 1  t     1506    783 ));
+DATA(insert (  2595   718 718 2  t     1507    783 ));
+DATA(insert (  2595   718 718 3  t     1513    783 ));
+DATA(insert (  2595   718 718 4  t     1508    783 ));
+DATA(insert (  2595   718 718 5  t     1509    783 ));
+DATA(insert (  2595   718 718 6  t     1512    783 ));
+DATA(insert (  2595   718 718 7  t     1511    783 ));
+DATA(insert (  2595   718 718 8  t     1510    783 ));
+DATA(insert (  2595   718 718 9  t     2589    783 ));
+DATA(insert (  2595   718 718 10 t     1515    783 ));
+DATA(insert (  2595   718 718 11 t     1514    783 ));
+DATA(insert (  2595   718 718 12 t     2590    783 ));
+DATA(insert (  2595   718 718 13 t     2865    783 ));
+DATA(insert (  2595   718 718 14 t     2864    783 ));
+
+/*
+ * gin array_ops (these anyarray operators are used with all the opclasses
+ * of the family)
+ */
+DATA(insert (  2745   2277 2277 1  f   2750    2742 ));
+DATA(insert (  2745   2277 2277 2  f   2751    2742 ));
+DATA(insert (  2745   2277 2277 3  t   2752    2742 ));
+DATA(insert (  2745   2277 2277 4  t   1070    2742 ));
 
 #endif   /* PG_AMOP_H */
index 291931b..1f81ff7 100644 (file)
@@ -5,21 +5,24 @@
  *       along with the relation's initial contents.
  *
  * The amproc table identifies support procedures associated with index
- * opclasses.  These procedures can't be listed in pg_amop since they are
- * not the implementation of any indexable operator for the opclass.
+ * operator families and classes.  These procedures can't be listed in pg_amop
+ * since they are not the implementation of any indexable operator.
  *
- * 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.
+ * The primary key for this table is <amprocfamily, amproclefttype,
+ * amprocrighttype, amprocnum>.  The "default" support functions for a
+ * particular opclass within the family are those with amproclefttype =
+ * amprocrighttype = opclass's opcintype.  These are the ones loaded into the
+ * relcache for an index and typically used for internal index operations.
+ * Other support functions are typically used to handle cross-type indexable
+ * operators with oprleft/oprright matching the entry's amproclefttype and
+ * amprocrighttype. The exact behavior depends on the index AM, however, and
+ * some don't pay attention to non-default functions at all.
  *
  *
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.60 2006/10/04 00:30:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.61 2006/12/23 00:43:12 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
  */
 #define AccessMethodProcedureRelationId  2603
 
-CATALOG(pg_amproc,2603) BKI_WITHOUT_OIDS
+CATALOG(pg_amproc,2603)
 {
-       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 */
+       Oid                     amprocfamily;           /* the index opfamily this entry is for */
+       Oid                     amproclefttype;         /* procedure's left input data type */
+       Oid                     amprocrighttype;        /* procedure's right input data type */
+       int2            amprocnum;                      /* support procedure index */
+       regproc         amproc;                         /* OID of the proc */
 } FormData_pg_amproc;
 
 /* ----------------
@@ -63,11 +67,12 @@ typedef FormData_pg_amproc *Form_pg_amproc;
  *             compiler constants for pg_amproc
  * ----------------
  */
-#define Natts_pg_amproc                                        4
-#define Anum_pg_amproc_amopclaid               1
-#define Anum_pg_amproc_amprocsubtype   2
-#define Anum_pg_amproc_amprocnum               3
-#define Anum_pg_amproc_amproc                  4
+#define Natts_pg_amproc                                        5
+#define Anum_pg_amproc_amprocfamily            1
+#define Anum_pg_amproc_amproclefttype  2
+#define Anum_pg_amproc_amprocrighttype 3
+#define Anum_pg_amproc_amprocnum               4
+#define Anum_pg_amproc_amproc                  5
 
 /* ----------------
  *             initial contents of pg_amproc
@@ -75,237 +80,223 @@ typedef FormData_pg_amproc *Form_pg_amproc;
  */
 
 /* btree */
-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 (   434 1114 1 2344 ));
-DATA(insert (   434 1184 1 2357 ));
-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 (  1998 1082 1 2383 ));
-DATA(insert (  1998 1114 1 2533 ));
-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 (  2039 1082 1 2370 ));
-DATA(insert (  2039 1184 1 2526 ));
-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 ));
-DATA(insert (  2789    0 1 2794 ));
+DATA(insert (  397   2277 2277 1 382 ));
+DATA(insert (  421   702 702 1 357 ));
+DATA(insert (  423   1560 1560 1 1596 ));
+DATA(insert (  424   16 16 1 1693 ));
+DATA(insert (  426   1042 1042 1 1078 ));
+DATA(insert (  428   17 17 1 1954 ));
+DATA(insert (  429   18 18 1 358 ));
+DATA(insert (  434   1082 1082 1 1092 ));
+DATA(insert (  434   1082 1114 1 2344 ));
+DATA(insert (  434   1082 1184 1 2357 ));
+DATA(insert (  434   1114 1114 1 2045 ));
+DATA(insert (  434   1114 1082 1 2370 ));
+DATA(insert (  434   1114 1184 1 2526 ));
+DATA(insert (  434   1184 1184 1 1314 ));
+DATA(insert (  434   1184 1082 1 2383 ));
+DATA(insert (  434   1184 1114 1 2533 ));
+DATA(insert (  1970   700 700 1 354 ));
+DATA(insert (  1970   700 701 1 2194 ));
+DATA(insert (  1970   701 701 1 355 ));
+DATA(insert (  1970   701 700 1 2195 ));
+DATA(insert (  1974   869 869 1 926 ));
+DATA(insert (  1976   21 21 1 350 ));
+DATA(insert (  1976   21 23 1 2190 ));
+DATA(insert (  1976   21 20 1 2192 ));
+DATA(insert (  1976   23 23 1 351 ));
+DATA(insert (  1976   23 20 1 2188 ));
+DATA(insert (  1976   23 21 1 2191 ));
+DATA(insert (  1976   20 20 1 842 ));
+DATA(insert (  1976   20 23 1 2189 ));
+DATA(insert (  1976   20 21 1 2193 ));
+DATA(insert (  1982   1186 1186 1 1315 ));
+DATA(insert (  1984   829 829 1 836 ));
+DATA(insert (  1986   19 19 1 359 ));
+DATA(insert (  1988   1700 1700 1 1769 ));
+DATA(insert (  1989   26 26 1 356 ));
+DATA(insert (  1991   30 30 1 404 ));
+DATA(insert (  1994   25 25 1 360 ));
+DATA(insert (  1996   1083 1083 1 1107 ));
+DATA(insert (  2000   1266 1266 1 1358 ));
+DATA(insert (  2002   1562 1562 1 1672 ));
+DATA(insert (  2095   25 25 1 2166 ));
+DATA(insert (  2097   1042 1042 1 2180 ));
+DATA(insert (  2098   19 19 1 2187 ));
+DATA(insert (  2099   790 790 1  377 ));
+DATA(insert (  2233   703 703 1  380 ));
+DATA(insert (  2234   704 704 1  381 ));
+DATA(insert (  2789   27 27 1 2794 ));
 
 
 /* hash */
-DATA(insert (   427    0 1 1080 ));
-DATA(insert (   431    0 1 454 ));
-DATA(insert (   433    0 1 422 ));
-DATA(insert (   435    0 1 450 ));
-DATA(insert (  1971    0 1 451 ));
-DATA(insert (  1973    0 1 452 ));
-DATA(insert (  1975    0 1 422 ));
-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 ));
+DATA(insert (  427   1042 1042 1 1080 ));
+DATA(insert (  431   18 18 1 454 ));
+DATA(insert (  435   1082 1082 1 450 ));
+DATA(insert (  1971   700 700 1 451 ));
+DATA(insert (  1971   701 701 1 452 ));
+DATA(insert (  1975   869 869 1 422 ));
+DATA(insert (  1977   21 21 1 449 ));
+DATA(insert (  1977   23 23 1 450 ));
+DATA(insert (  1977   20 20 1 949 ));
+DATA(insert (  1983   1186 1186 1 1697 ));
+DATA(insert (  1985   829 829 1 399 ));
+DATA(insert (  1987   19 19 1 455 ));
+DATA(insert (  1990   26 26 1 453 ));
+DATA(insert (  1992   30 30 1 457 ));
+DATA(insert (  1995   25 25 1 400 ));
+DATA(insert (  1997   1083 1083 1 452 ));
+DATA(insert (  1999   1184 1184 1 452 ));
+DATA(insert (  2001   1266 1266 1 1696 ));
+DATA(insert (  2040   1114 1114 1 452 ));
+DATA(insert (  2222   16 16 1 454 ));
+DATA(insert (  2223   17 17 1 456 ));
+DATA(insert (  2224   22 22 1 398 ));
+DATA(insert (  2225   28 28 1 450 ));
+DATA(insert (  2226   29 29 1 450 ));
+DATA(insert (  2227   702 702 1 450 ));
+DATA(insert (  2228   703 703 1 450 ));
+DATA(insert (  2229   25 25 1 456 ));
+DATA(insert (  2231   1042 1042 1 456 ));
+DATA(insert (  2232   19 19 1 455 ));
+DATA(insert (  2235   1033 1033 1 329 ));
 
 
 /* gist */
-DATA(insert (  2593    0 1 2578 ));
-DATA(insert (  2593    0 2 2583 ));
-DATA(insert (  2593    0 3 2579 ));
-DATA(insert (  2593    0 4 2580 ));
-DATA(insert (  2593    0 5 2581 ));
-DATA(insert (  2593    0 6 2582 ));
-DATA(insert (  2593    0 7 2584 ));
-DATA(insert (  2594    0 1 2585 ));
-DATA(insert (  2594    0 2 2583 ));
-DATA(insert (  2594    0 3 2586 ));
-DATA(insert (  2594    0 4 2580 ));
-DATA(insert (  2594    0 5 2581 ));
-DATA(insert (  2594    0 6 2582 ));
-DATA(insert (  2594    0 7 2584 ));
-DATA(insert (  2595    0 1 2591 ));
-DATA(insert (  2595    0 2 2583 ));
-DATA(insert (  2595    0 3 2592 ));
-DATA(insert (  2595    0 4 2580 ));
-DATA(insert (  2595    0 5 2581 ));
-DATA(insert (  2595    0 6 2582 ));
-DATA(insert (  2595    0 7 2584 ));
+DATA(insert (  2593   603 603 1 2578 ));
+DATA(insert (  2593   603 603 2 2583 ));
+DATA(insert (  2593   603 603 3 2579 ));
+DATA(insert (  2593   603 603 4 2580 ));
+DATA(insert (  2593   603 603 5 2581 ));
+DATA(insert (  2593   603 603 6 2582 ));
+DATA(insert (  2593   603 603 7 2584 ));
+DATA(insert (  2594   604 604 1 2585 ));
+DATA(insert (  2594   604 604 2 2583 ));
+DATA(insert (  2594   604 604 3 2586 ));
+DATA(insert (  2594   604 604 4 2580 ));
+DATA(insert (  2594   604 604 5 2581 ));
+DATA(insert (  2594   604 604 6 2582 ));
+DATA(insert (  2594   604 604 7 2584 ));
+DATA(insert (  2595   718 718 1 2591 ));
+DATA(insert (  2595   718 718 2 2583 ));
+DATA(insert (  2595   718 718 3 2592 ));
+DATA(insert (  2595   718 718 4 2580 ));
+DATA(insert (  2595   718 718 5 2581 ));
+DATA(insert (  2595   718 718 6 2582 ));
+DATA(insert (  2595   718 718 7 2584 ));
 
 /* gin */
-DATA(insert (  2745    0 1  351 ));
-DATA(insert (  2745    0 2 2743 ));
-DATA(insert (  2745    0 3 2743 ));
-DATA(insert (  2745    0 4 2744 ));
-DATA(insert (  2746    0 1  360 ));
-DATA(insert (  2746    0 2 2743 ));
-DATA(insert (  2746    0 3 2743 ));
-DATA(insert (  2746    0 4 2744 ));
-DATA(insert (  2753    0 1 357 ));
-DATA(insert (  2753    0 2 2743 ));
-DATA(insert (  2753    0 3 2743 ));
-DATA(insert (  2753    0 4 2744 ));
-DATA(insert (  2754    0 1 1596 ));
-DATA(insert (  2754    0 2 2743 ));
-DATA(insert (  2754    0 3 2743 ));
-DATA(insert (  2754    0 4 2744 ));
-DATA(insert (  2755    0 1 1693 ));
-DATA(insert (  2755    0 2 2743 ));
-DATA(insert (  2755    0 3 2743 ));
-DATA(insert (  2755    0 4 2744 ));
-DATA(insert (  2756    0 1 1078 ));
-DATA(insert (  2756    0 2 2743 ));
-DATA(insert (  2756    0 3 2743 ));
-DATA(insert (  2756    0 4 2744 ));
-DATA(insert (  2757    0 1 1954 ));
-DATA(insert (  2757    0 2 2743 ));
-DATA(insert (  2757    0 3 2743 ));
-DATA(insert (  2757    0 4 2744 ));
-DATA(insert (  2758    0 1 358 ));
-DATA(insert (  2758    0 2 2743 ));
-DATA(insert (  2758    0 3 2743 ));
-DATA(insert (  2758    0 4 2744 ));
-DATA(insert (  2759    0 1 926 ));
-DATA(insert (  2759    0 2 2743 ));
-DATA(insert (  2759    0 3 2743 ));
-DATA(insert (  2759    0 4 2744 ));
-DATA(insert (  2760    0 1 1092 ));
-DATA(insert (  2760    0 2 2743 ));
-DATA(insert (  2760    0 3 2743 ));
-DATA(insert (  2760    0 4 2744 ));
-DATA(insert (  2761    0 1 354 ));
-DATA(insert (  2761    0 2 2743 ));
-DATA(insert (  2761    0 3 2743 ));
-DATA(insert (  2761    0 4 2744 ));
-DATA(insert (  2762    0 1 355 ));
-DATA(insert (  2762    0 2 2743 ));
-DATA(insert (  2762    0 3 2743 ));
-DATA(insert (  2762    0 4 2744 ));
-DATA(insert (  2763    0 1 926 ));
-DATA(insert (  2763    0 2 2743 ));
-DATA(insert (  2763    0 3 2743 ));
-DATA(insert (  2763    0 4 2744 ));
-DATA(insert (  2764    0 1 350 ));
-DATA(insert (  2764    0 2 2743 ));
-DATA(insert (  2764    0 3 2743 ));
-DATA(insert (  2764    0 4 2744 ));
-DATA(insert (  2765    0 1 842 ));
-DATA(insert (  2765    0 2 2743 ));
-DATA(insert (  2765    0 3 2743 ));
-DATA(insert (  2765    0 4 2744 ));
-DATA(insert (  2766    0 1 1315 ));
-DATA(insert (  2766    0 2 2743 ));
-DATA(insert (  2766    0 3 2743 ));
-DATA(insert (  2766    0 4 2744 ));
-DATA(insert (  2767    0 1 836 ));
-DATA(insert (  2767    0 2 2743 ));
-DATA(insert (  2767    0 3 2743 ));
-DATA(insert (  2767    0 4 2744 ));
-DATA(insert (  2768    0 1 359 ));
-DATA(insert (  2768    0 2 2743 ));
-DATA(insert (  2768    0 3 2743 ));
-DATA(insert (  2768    0 4 2744 ));
-DATA(insert (  2769    0 1 1769 ));
-DATA(insert (  2769    0 2 2743 ));
-DATA(insert (  2769    0 3 2743 ));
-DATA(insert (  2769    0 4 2744 ));
-DATA(insert (  2770    0 1 356 ));
-DATA(insert (  2770    0 2 2743 ));
-DATA(insert (  2770    0 3 2743 ));
-DATA(insert (  2770    0 4 2744 ));
-DATA(insert (  2771    0 1 404 ));
-DATA(insert (  2771    0 2 2743 ));
-DATA(insert (  2771    0 3 2743 ));
-DATA(insert (  2771    0 4 2744 ));
-DATA(insert (  2772    0 1 1107 ));
-DATA(insert (  2772    0 2 2743 ));
-DATA(insert (  2772    0 3 2743 ));
-DATA(insert (  2772    0 4 2744 ));
-DATA(insert (  2773    0 1 1314 ));
-DATA(insert (  2773    0 2 2743 ));
-DATA(insert (  2773    0 3 2743 ));
-DATA(insert (  2773    0 4 2744 ));
-DATA(insert (  2774    0 1 1358 ));
-DATA(insert (  2774    0 2 2743 ));
-DATA(insert (  2774    0 3 2743 ));
-DATA(insert (  2774    0 4 2744 ));
-DATA(insert (  2775    0 1 1672 ));
-DATA(insert (  2775    0 2 2743 ));
-DATA(insert (  2775    0 3 2743 ));
-DATA(insert (  2775    0 4 2744 ));
-DATA(insert (  2776    0 1 360 ));
-DATA(insert (  2776    0 2 2743 ));
-DATA(insert (  2776    0 3 2743 ));
-DATA(insert (  2776    0 4 2744 ));
-DATA(insert (  2777    0 1 2045 ));
-DATA(insert (  2777    0 2 2743 ));
-DATA(insert (  2777    0 3 2743 ));
-DATA(insert (  2777    0 4 2744 ));
-DATA(insert (  2778    0 1 377 ));
-DATA(insert (  2778    0 2 2743 ));
-DATA(insert (  2778    0 3 2743 ));
-DATA(insert (  2778    0 4 2744 ));
-DATA(insert (  2779    0 1 380 ));
-DATA(insert (  2779    0 2 2743 ));
-DATA(insert (  2779    0 3 2743 ));
-DATA(insert (  2779    0 4 2744 ));
-DATA(insert (  2780    0 1 381 ));
-DATA(insert (  2780    0 2 2743 ));
-DATA(insert (  2780    0 3 2743 ));
-DATA(insert (  2780    0 4 2744 ));
+DATA(insert (  2745   1007 1007 1  351 ));
+DATA(insert (  2745   1007 1007 2 2743 ));
+DATA(insert (  2745   1007 1007 3 2743 ));
+DATA(insert (  2745   1007 1007 4 2744 ));
+DATA(insert (  2745   1009 1009 1  360 ));
+DATA(insert (  2745   1009 1009 2 2743 ));
+DATA(insert (  2745   1009 1009 3 2743 ));
+DATA(insert (  2745   1009 1009 4 2744 ));
+DATA(insert (  2745   1023 1023 1 357 ));
+DATA(insert (  2745   1023 1023 2 2743 ));
+DATA(insert (  2745   1023 1023 3 2743 ));
+DATA(insert (  2745   1023 1023 4 2744 ));
+DATA(insert (  2745   1561 1561 1 1596 ));
+DATA(insert (  2745   1561 1561 2 2743 ));
+DATA(insert (  2745   1561 1561 3 2743 ));
+DATA(insert (  2745   1561 1561 4 2744 ));
+DATA(insert (  2745   1000 1000 1 1693 ));
+DATA(insert (  2745   1000 1000 2 2743 ));
+DATA(insert (  2745   1000 1000 3 2743 ));
+DATA(insert (  2745   1000 1000 4 2744 ));
+DATA(insert (  2745   1014 1014 1 1078 ));
+DATA(insert (  2745   1014 1014 2 2743 ));
+DATA(insert (  2745   1014 1014 3 2743 ));
+DATA(insert (  2745   1014 1014 4 2744 ));
+DATA(insert (  2745   1001 1001 1 1954 ));
+DATA(insert (  2745   1001 1001 2 2743 ));
+DATA(insert (  2745   1001 1001 3 2743 ));
+DATA(insert (  2745   1001 1001 4 2744 ));
+DATA(insert (  2745   1002 1002 1 358 ));
+DATA(insert (  2745   1002 1002 2 2743 ));
+DATA(insert (  2745   1002 1002 3 2743 ));
+DATA(insert (  2745   1002 1002 4 2744 ));
+DATA(insert (  2745   1182 1182 1 1092 ));
+DATA(insert (  2745   1182 1182 2 2743 ));
+DATA(insert (  2745   1182 1182 3 2743 ));
+DATA(insert (  2745   1182 1182 4 2744 ));
+DATA(insert (  2745   1021 1021 1 354 ));
+DATA(insert (  2745   1021 1021 2 2743 ));
+DATA(insert (  2745   1021 1021 3 2743 ));
+DATA(insert (  2745   1021 1021 4 2744 ));
+DATA(insert (  2745   1022 1022 1 355 ));
+DATA(insert (  2745   1022 1022 2 2743 ));
+DATA(insert (  2745   1022 1022 3 2743 ));
+DATA(insert (  2745   1022 1022 4 2744 ));
+DATA(insert (  2745   1041 1041 1 926 ));
+DATA(insert (  2745   1041 1041 2 2743 ));
+DATA(insert (  2745   1041 1041 3 2743 ));
+DATA(insert (  2745   1041 1041 4 2744 ));
+DATA(insert (  2745   1005 1005 1 350 ));
+DATA(insert (  2745   1005 1005 2 2743 ));
+DATA(insert (  2745   1005 1005 3 2743 ));
+DATA(insert (  2745   1005 1005 4 2744 ));
+DATA(insert (  2745   1016 1016 1 842 ));
+DATA(insert (  2745   1016 1016 2 2743 ));
+DATA(insert (  2745   1016 1016 3 2743 ));
+DATA(insert (  2745   1016 1016 4 2744 ));
+DATA(insert (  2745   1187 1187 1 1315 ));
+DATA(insert (  2745   1187 1187 2 2743 ));
+DATA(insert (  2745   1187 1187 3 2743 ));
+DATA(insert (  2745   1187 1187 4 2744 ));
+DATA(insert (  2745   1040 1040 1 836 ));
+DATA(insert (  2745   1040 1040 2 2743 ));
+DATA(insert (  2745   1040 1040 3 2743 ));
+DATA(insert (  2745   1040 1040 4 2744 ));
+DATA(insert (  2745   1003 1003 1 359 ));
+DATA(insert (  2745   1003 1003 2 2743 ));
+DATA(insert (  2745   1003 1003 3 2743 ));
+DATA(insert (  2745   1003 1003 4 2744 ));
+DATA(insert (  2745   1231 1231 1 1769 ));
+DATA(insert (  2745   1231 1231 2 2743 ));
+DATA(insert (  2745   1231 1231 3 2743 ));
+DATA(insert (  2745   1231 1231 4 2744 ));
+DATA(insert (  2745   1028 1028 1 356 ));
+DATA(insert (  2745   1028 1028 2 2743 ));
+DATA(insert (  2745   1028 1028 3 2743 ));
+DATA(insert (  2745   1028 1028 4 2744 ));
+DATA(insert (  2745   1013 1013 1 404 ));
+DATA(insert (  2745   1013 1013 2 2743 ));
+DATA(insert (  2745   1013 1013 3 2743 ));
+DATA(insert (  2745   1013 1013 4 2744 ));
+DATA(insert (  2745   1183 1183 1 1107 ));
+DATA(insert (  2745   1183 1183 2 2743 ));
+DATA(insert (  2745   1183 1183 3 2743 ));
+DATA(insert (  2745   1183 1183 4 2744 ));
+DATA(insert (  2745   1185 1185 1 1314 ));
+DATA(insert (  2745   1185 1185 2 2743 ));
+DATA(insert (  2745   1185 1185 3 2743 ));
+DATA(insert (  2745   1185 1185 4 2744 ));
+DATA(insert (  2745   1270 1270 1 1358 ));
+DATA(insert (  2745   1270 1270 2 2743 ));
+DATA(insert (  2745   1270 1270 3 2743 ));
+DATA(insert (  2745   1270 1270 4 2744 ));
+DATA(insert (  2745   1563 1563 1 1672 ));
+DATA(insert (  2745   1563 1563 2 2743 ));
+DATA(insert (  2745   1563 1563 3 2743 ));
+DATA(insert (  2745   1563 1563 4 2744 ));
+DATA(insert (  2745   1115 1115 1 2045 ));
+DATA(insert (  2745   1115 1115 2 2743 ));
+DATA(insert (  2745   1115 1115 3 2743 ));
+DATA(insert (  2745   1115 1115 4 2744 ));
+DATA(insert (  2745   791 791 1 377 ));
+DATA(insert (  2745   791 791 2 2743 ));
+DATA(insert (  2745   791 791 3 2743 ));
+DATA(insert (  2745   791 791 4 2744 ));
+DATA(insert (  2745   1024 1024 1 380 ));
+DATA(insert (  2745   1024 1024 2 2743 ));
+DATA(insert (  2745   1024 1024 3 2743 ));
+DATA(insert (  2745   1024 1024 4 2744 ));
+DATA(insert (  2745   1025 1025 1 381 ));
+DATA(insert (  2745   1025 1025 2 2743 ));
+DATA(insert (  2745   1025 1025 3 2743 ));
+DATA(insert (  2745   1025 1025 4 2744 ));
 
 #endif   /* PG_AMPROC_H */
index cee9f75..8aa9ea3 100644 (file)
@@ -4,16 +4,17 @@
  *       definition of the system "opclass" relation (pg_opclass)
  *       along with the relation's initial contents.
  *
- * New definition for Postgres 7.2: the primary key for this table is
- * <opcamid, opcname> --- that is, there is a row for each valid combination
- * of opclass name and index access method type.  This row specifies the
- * expected input data type for the opclass (the type of the heap column,
- * or the expression output type in the case of an index expression).  Note
- * that types binary-coercible to the specified type will be accepted too.
+ * The primary key for this table is <opcmethod, opcname, opcnamespace> ---
+ * that is, there is a row for each valid combination of opclass name and
+ * index access method type.  This row specifies the expected input data type
+ * for the opclass (the type of the heap column, or the expression output type
+ * in the case of an index expression).  Note that types binary-coercible to
+ * the specified type will be accepted too.
  *
- * For a given <opcamid, opcintype> pair, there can be at most one row that
+ * For a given <opcmethod, opcintype> pair, there can be at most one row that
  * has opcdefault = true; this row is the default opclass for such data in
- * such an index.
+ * such an index.  (This is not currently enforced by an index, because we
+ * don't support partial indexes on system catalogs.)
  *
  * Normally opckeytype = InvalidOid (zero), indicating that the data stored
  * in the index is the same as the data in the indexed column. If opckeytype
@@ -27,7 +28,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.71 2006/07/21 20:51:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.72 2006/12/23 00:43:12 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
 
 CATALOG(pg_opclass,2616)
 {
-       Oid                     opcamid;                /* index access method opclass is for */
+       Oid                     opcmethod;              /* index access method opclass is for */
        NameData        opcname;                /* name of this opclass */
        Oid                     opcnamespace;   /* namespace of this opclass */
        Oid                     opcowner;               /* opclass owner */
+       Oid                     opcfamily;              /* containing operator family */
        Oid                     opcintype;              /* type of data indexed by opclass */
        bool            opcdefault;             /* T if opclass is default for opcintype */
        Oid                     opckeytype;             /* type of data in index, or InvalidOid */
@@ -74,138 +76,129 @@ typedef FormData_pg_opclass *Form_pg_opclass;
  *             compiler constants for pg_opclass
  * ----------------
  */
-#define Natts_pg_opclass                               7
-#define Anum_pg_opclass_opcamid                        1
+#define Natts_pg_opclass                               8
+#define Anum_pg_opclass_opcmethod              1
 #define Anum_pg_opclass_opcname                        2
 #define Anum_pg_opclass_opcnamespace   3
 #define Anum_pg_opclass_opcowner               4
-#define Anum_pg_opclass_opcintype              5
-#define Anum_pg_opclass_opcdefault             6
-#define Anum_pg_opclass_opckeytype             7
+#define Anum_pg_opclass_opcfamily              5
+#define Anum_pg_opclass_opcintype              6
+#define Anum_pg_opclass_opcdefault             7
+#define Anum_pg_opclass_opckeytype             8
 
 /* ----------------
  *             initial contents of pg_opclass
+ *
+ * Note: we hard-wire an OID only for a few entries that have to be explicitly
+ * referenced in the C code for bootstrapping purposes.  The rest get OIDs
+ * assigned on-the-fly during initdb.
  * ----------------
  */
 
-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 =  423 (       403             bit_ops                 PGNSP PGUID 1560 t 0 ));
-DATA(insert OID =  424 (       403             bool_ops                PGNSP PGUID   16 t 0 ));
-#define BOOL_BTREE_OPS_OID 424
-DATA(insert OID =  426 (       403             bpchar_ops              PGNSP PGUID 1042 t 0 ));
-#define BPCHAR_BTREE_OPS_OID 426
-DATA(insert OID =  427 (       405             bpchar_ops              PGNSP PGUID 1042 t 0 ));
-DATA(insert OID =  428 (       403             bytea_ops               PGNSP PGUID   17 t 0 ));
-#define BYTEA_BTREE_OPS_OID 428
-DATA(insert OID =  429 (       403             char_ops                PGNSP PGUID   18 t 0 ));
-DATA(insert OID =  431 (       405             char_ops                PGNSP PGUID   18 t 0 ));
-DATA(insert OID =  432 (       403             cidr_ops                PGNSP PGUID  650 t 0 ));
-#define CIDR_BTREE_OPS_OID 432
-DATA(insert OID =  433 (       405             cidr_ops                PGNSP PGUID  650 t 0 ));
-DATA(insert OID =  434 (       403             date_ops                PGNSP PGUID 1082 t 0 ));
-DATA(insert OID =  435 (       405             date_ops                PGNSP PGUID 1082 t 0 ));
-DATA(insert OID = 1970 (       403             float4_ops              PGNSP PGUID  700 t 0 ));
-DATA(insert OID = 1971 (       405             float4_ops              PGNSP PGUID  700 t 0 ));
-DATA(insert OID = 1972 (       403             float8_ops              PGNSP PGUID  701 t 0 ));
-DATA(insert OID = 1973 (       405             float8_ops              PGNSP PGUID  701 t 0 ));
-DATA(insert OID = 1974 (       403             inet_ops                PGNSP PGUID  869 t 0 ));
-#define INET_BTREE_OPS_OID 1974
-DATA(insert OID = 1975 (       405             inet_ops                PGNSP PGUID  869 t 0 ));
-DATA(insert OID = 1976 (       403             int2_ops                PGNSP PGUID   21 t 0 ));
-#define INT2_BTREE_OPS_OID 1976
-DATA(insert OID = 1977 (       405             int2_ops                PGNSP PGUID   21 t 0 ));
-DATA(insert OID = 1978 (       403             int4_ops                PGNSP PGUID   23 t 0 ));
+DATA(insert (  403             abstime_ops                     PGNSP PGUID  421  702 t 0 ));
+DATA(insert (  403             array_ops                       PGNSP PGUID  397 2277 t 0 ));
+DATA(insert (  403             bit_ops                         PGNSP PGUID  423 1560 t 0 ));
+DATA(insert (  403             bool_ops                        PGNSP PGUID  424   16 t 0 ));
+DATA(insert (  403             bpchar_ops                      PGNSP PGUID  426 1042 t 0 ));
+DATA(insert (  405             bpchar_ops                      PGNSP PGUID  427 1042 t 0 ));
+DATA(insert (  403             bytea_ops                       PGNSP PGUID  428   17 t 0 ));
+DATA(insert (  403             char_ops                        PGNSP PGUID  429   18 t 0 ));
+DATA(insert (  405             char_ops                        PGNSP PGUID  431   18 t 0 ));
+DATA(insert (  403             cidr_ops                        PGNSP PGUID 1974  869 f 0 ));
+DATA(insert (  405             cidr_ops                        PGNSP PGUID 1975  869 f 0 ));
+DATA(insert (  403             date_ops                        PGNSP PGUID  434 1082 t 0 ));
+DATA(insert (  405             date_ops                        PGNSP PGUID  435 1082 t 0 ));
+DATA(insert (  403             float4_ops                      PGNSP PGUID 1970  700 t 0 ));
+DATA(insert (  405             float4_ops                      PGNSP PGUID 1971  700 t 0 ));
+DATA(insert (  403             float8_ops                      PGNSP PGUID 1970  701 t 0 ));
+DATA(insert (  405             float8_ops                      PGNSP PGUID 1971  701 t 0 ));
+DATA(insert (  403             inet_ops                        PGNSP PGUID 1974  869 t 0 ));
+DATA(insert (  405             inet_ops                        PGNSP PGUID 1975  869 t 0 ));
+DATA(insert OID = 1979 ( 403   int2_ops        PGNSP PGUID 1976   21 t 0 ));
+#define INT2_BTREE_OPS_OID 1979
+DATA(insert (  405             int2_ops                        PGNSP PGUID 1977   21 t 0 ));
+DATA(insert OID = 1978 ( 403   int4_ops        PGNSP PGUID 1976   23 t 0 ));
 #define INT4_BTREE_OPS_OID 1978
-DATA(insert OID = 1979 (       405             int4_ops                PGNSP PGUID   23 t 0 ));
-DATA(insert OID = 1980 (       403             int8_ops                PGNSP PGUID   20 t 0 ));
-DATA(insert OID = 1981 (       405             int8_ops                PGNSP PGUID   20 t 0 ));
-DATA(insert OID = 1982 (       403             interval_ops    PGNSP PGUID 1186 t 0 ));
-DATA(insert OID = 1983 (       405             interval_ops    PGNSP PGUID 1186 t 0 ));
-DATA(insert OID = 1984 (       403             macaddr_ops             PGNSP PGUID  829 t 0 ));
-DATA(insert OID = 1985 (       405             macaddr_ops             PGNSP PGUID  829 t 0 ));
-DATA(insert OID = 1986 (       403             name_ops                PGNSP PGUID   19 t 0 ));
-#define NAME_BTREE_OPS_OID 1986
-DATA(insert OID = 1987 (       405             name_ops                PGNSP PGUID   19 t 0 ));
-DATA(insert OID = 1988 (       403             numeric_ops             PGNSP PGUID 1700 t 0 ));
-DATA(insert OID = 1989 (       403             oid_ops                 PGNSP PGUID   26 t 0 ));
-#define OID_BTREE_OPS_OID 1989
-DATA(insert OID = 1990 (       405             oid_ops                 PGNSP PGUID   26 t 0 ));
-DATA(insert OID = 1991 (       403             oidvector_ops   PGNSP PGUID   30 t 0 ));
-DATA(insert OID = 1992 (       405             oidvector_ops   PGNSP PGUID   30 t 0 ));
-DATA(insert OID = 1994 (       403             text_ops                PGNSP PGUID   25 t 0 ));
-#define TEXT_BTREE_OPS_OID 1994
-DATA(insert OID = 1995 (       405             text_ops                PGNSP PGUID   25 t 0 ));
-DATA(insert OID = 1996 (       403             time_ops                PGNSP PGUID 1083 t 0 ));
-DATA(insert OID = 1997 (       405             time_ops                PGNSP PGUID 1083 t 0 ));
-DATA(insert OID = 1998 (       403             timestamptz_ops PGNSP PGUID 1184 t 0 ));
-DATA(insert OID = 1999 (       405             timestamptz_ops PGNSP PGUID 1184 t 0 ));
-DATA(insert OID = 2000 (       403             timetz_ops              PGNSP PGUID 1266 t 0 ));
-DATA(insert OID = 2001 (       405             timetz_ops              PGNSP PGUID 1266 t 0 ));
-DATA(insert OID = 2002 (       403             varbit_ops              PGNSP PGUID 1562 t 0 ));
-DATA(insert OID = 2003 (       403             varchar_ops             PGNSP PGUID 1043 t 0 ));
-#define VARCHAR_BTREE_OPS_OID 2003
-DATA(insert OID = 2004 (       405             varchar_ops             PGNSP PGUID 1043 t 0 ));
-DATA(insert OID = 2039 (       403             timestamp_ops   PGNSP PGUID 1114 t 0 ));
-DATA(insert OID = 2040 (       405             timestamp_ops   PGNSP PGUID 1114 t 0 ));
-DATA(insert OID = 2095 (       403             text_pattern_ops        PGNSP PGUID   25 f 0 ));
-#define TEXT_PATTERN_BTREE_OPS_OID 2095
-DATA(insert OID = 2096 (       403             varchar_pattern_ops PGNSP PGUID 1043 f 0 ));
-#define VARCHAR_PATTERN_BTREE_OPS_OID 2096
-DATA(insert OID = 2097 (       403             bpchar_pattern_ops      PGNSP PGUID 1042 f 0 ));
-#define BPCHAR_PATTERN_BTREE_OPS_OID 2097
-DATA(insert OID = 2098 (       403             name_pattern_ops        PGNSP PGUID   19 f 0 ));
-#define NAME_PATTERN_BTREE_OPS_OID 2098
-DATA(insert OID = 2099 (       403             money_ops               PGNSP PGUID  790 t 0 ));
-DATA(insert OID = 2222 (       405             bool_ops                PGNSP PGUID   16 t 0 ));
-#define BOOL_HASH_OPS_OID 2222
-DATA(insert OID = 2223 (       405             bytea_ops               PGNSP PGUID   17 t 0 ));
-DATA(insert OID = 2224 (       405             int2vector_ops  PGNSP PGUID   22 t 0 ));
-DATA(insert OID = 2789 (       403             tid_ops                 PGNSP PGUID   27 t 0 ));
-DATA(insert OID = 2225 (       405             xid_ops                 PGNSP PGUID   28 t 0 ));
-DATA(insert OID = 2226 (       405             cid_ops                 PGNSP PGUID   29 t 0 ));
-DATA(insert OID = 2227 (       405             abstime_ops             PGNSP PGUID  702 t 0 ));
-DATA(insert OID = 2228 (       405             reltime_ops             PGNSP PGUID  703 t 0 ));
-DATA(insert OID = 2229 (       405             text_pattern_ops        PGNSP PGUID   25 f 0 ));
-DATA(insert OID = 2230 (       405             varchar_pattern_ops PGNSP PGUID 1043 f 0 ));
-DATA(insert OID = 2231 (       405             bpchar_pattern_ops      PGNSP PGUID 1042 f 0 ));
-DATA(insert OID = 2232 (       405             name_pattern_ops        PGNSP PGUID   19 f 0 ));
-DATA(insert OID = 2233 (       403             reltime_ops             PGNSP PGUID  703 t 0 ));
-DATA(insert OID = 2234 (       403             tinterval_ops   PGNSP PGUID  704 t 0 ));
-DATA(insert OID = 2235 (       405             aclitem_ops             PGNSP PGUID 1033 t 0 ));
-DATA(insert OID = 2593 (       783             box_ops                 PGNSP PGUID  603 t 0 ));
-DATA(insert OID = 2594 (       783             poly_ops                PGNSP PGUID  604 t 603 ));
-DATA(insert OID = 2595 (       783             circle_ops              PGNSP PGUID  718 t 603 ));
-DATA(insert OID = 2745 (       2742    _int4_ops               PGNSP PGUID  1007 t 23 ));
-DATA(insert OID = 2746 (       2742    _text_ops               PGNSP PGUID  1009 t 25 ));
-DATA(insert OID = 2753 (       2742    _abstime_ops    PGNSP PGUID  1023 t 702 ));
-DATA(insert OID = 2754 (       2742    _bit_ops                PGNSP PGUID  1561 t 1560 ));
-DATA(insert OID = 2755 (       2742    _bool_ops               PGNSP PGUID  1000 t 16 ));
-DATA(insert OID = 2756 (       2742    _bpchar_ops             PGNSP PGUID  1014 t 1042 ));
-DATA(insert OID = 2757 (       2742    _bytea_ops              PGNSP PGUID  1001 t 17 ));
-DATA(insert OID = 2758 (       2742    _char_ops               PGNSP PGUID  1002 t 18 ));
-DATA(insert OID = 2759 (       2742    _cidr_ops               PGNSP PGUID  651 t 650 ));
-DATA(insert OID = 2760 (       2742    _date_ops               PGNSP PGUID  1182 t 1082 ));
-DATA(insert OID = 2761 (       2742    _float4_ops             PGNSP PGUID  1021 t 700 ));
-DATA(insert OID = 2762 (       2742    _float8_ops             PGNSP PGUID  1022 t 701 ));
-DATA(insert OID = 2763 (       2742    _inet_ops               PGNSP PGUID  1041 t 869 ));
-DATA(insert OID = 2764 (       2742    _int2_ops               PGNSP PGUID  1005 t 21 ));
-DATA(insert OID = 2765 (       2742    _int8_ops               PGNSP PGUID  1016 t 20 ));
-DATA(insert OID = 2766 (       2742    _interval_ops   PGNSP PGUID  1187 t 1186 ));
-DATA(insert OID = 2767 (       2742    _macaddr_ops    PGNSP PGUID  1040 t 829 ));
-DATA(insert OID = 2768 (       2742    _name_ops               PGNSP PGUID  1003 t 19 ));
-DATA(insert OID = 2769 (       2742    _numeric_ops    PGNSP PGUID  1231 t 1700 ));
-DATA(insert OID = 2770 (       2742    _oid_ops                PGNSP PGUID  1028 t 26 ));
-DATA(insert OID = 2771 (       2742    _oidvector_ops  PGNSP PGUID  1013 t 30 ));
-DATA(insert OID = 2772 (       2742    _time_ops               PGNSP PGUID  1183 t 1083 ));
-DATA(insert OID = 2773 (       2742    _timestamptz_ops        PGNSP PGUID  1185 t 1184 ));
-DATA(insert OID = 2774 (       2742    _timetz_ops             PGNSP PGUID  1270 t 1266 ));
-DATA(insert OID = 2775 (       2742    _varbit_ops             PGNSP PGUID  1563 t 1562 ));
-DATA(insert OID = 2776 (       2742    _varchar_ops    PGNSP PGUID  1015 t 1043 ));
-DATA(insert OID = 2777 (       2742    _timestamp_ops  PGNSP PGUID  1115 t 1114 ));
-DATA(insert OID = 2778 (       2742    _money_ops              PGNSP PGUID  791 t 790 ));
-DATA(insert OID = 2779 (       2742    _reltime_ops    PGNSP PGUID  1024 t 703 ));
-DATA(insert OID = 2780 (       2742    _tinterval_ops  PGNSP PGUID  1025 t 704 ));
+DATA(insert (  405             int4_ops                        PGNSP PGUID 1977   23 t 0 ));
+DATA(insert (  403             int8_ops                        PGNSP PGUID 1976   20 t 0 ));
+DATA(insert (  405             int8_ops                        PGNSP PGUID 1977   20 t 0 ));
+DATA(insert (  403             interval_ops            PGNSP PGUID 1982 1186 t 0 ));
+DATA(insert (  405             interval_ops            PGNSP PGUID 1983 1186 t 0 ));
+DATA(insert (  403             macaddr_ops                     PGNSP PGUID 1984  829 t 0 ));
+DATA(insert (  405             macaddr_ops                     PGNSP PGUID 1985  829 t 0 ));
+DATA(insert (  403             name_ops                        PGNSP PGUID 1986   19 t 0 ));
+DATA(insert (  405             name_ops                        PGNSP PGUID 1987   19 t 0 ));
+DATA(insert (  403             numeric_ops                     PGNSP PGUID 1988 1700 t 0 ));
+DATA(insert OID = 1981 ( 403   oid_ops         PGNSP PGUID 1989   26 t 0 ));
+#define OID_BTREE_OPS_OID 1981
+DATA(insert (  405             oid_ops                         PGNSP PGUID 1990   26 t 0 ));
+DATA(insert (  403             oidvector_ops           PGNSP PGUID 1991   30 t 0 ));
+DATA(insert (  405             oidvector_ops           PGNSP PGUID 1992   30 t 0 ));
+DATA(insert (  403             text_ops                        PGNSP PGUID 1994   25 t 0 ));
+DATA(insert (  405             text_ops                        PGNSP PGUID 1995   25 t 0 ));
+DATA(insert (  403             time_ops                        PGNSP PGUID 1996 1083 t 0 ));
+DATA(insert (  405             time_ops                        PGNSP PGUID 1997 1083 t 0 ));
+DATA(insert (  403             timestamptz_ops         PGNSP PGUID  434 1184 t 0 ));
+DATA(insert (  405             timestamptz_ops         PGNSP PGUID 1999 1184 t 0 ));
+DATA(insert (  403             timetz_ops                      PGNSP PGUID 2000 1266 t 0 ));
+DATA(insert (  405             timetz_ops                      PGNSP PGUID 2001 1266 t 0 ));
+DATA(insert (  403             varbit_ops                      PGNSP PGUID 2002 1562 t 0 ));
+DATA(insert (  403             varchar_ops                     PGNSP PGUID 1994   25 f 0 ));
+DATA(insert (  405             varchar_ops                     PGNSP PGUID 1995   25 f 0 ));
+DATA(insert (  403             timestamp_ops           PGNSP PGUID  434 1114 t 0 ));
+DATA(insert (  405             timestamp_ops           PGNSP PGUID 2040 1114 t 0 ));
+DATA(insert (  403             text_pattern_ops        PGNSP PGUID 2095   25 f 0 ));
+DATA(insert (  403             varchar_pattern_ops PGNSP PGUID 2095   25 f 0 ));
+DATA(insert (  403             bpchar_pattern_ops      PGNSP PGUID 2097 1042 f 0 ));
+DATA(insert (  403             name_pattern_ops        PGNSP PGUID 2098   19 f 0 ));
+DATA(insert (  403             money_ops                       PGNSP PGUID 2099  790 t 0 ));
+DATA(insert (  405             bool_ops                        PGNSP PGUID 2222   16 t 0 ));
+DATA(insert (  405             bytea_ops                       PGNSP PGUID 2223   17 t 0 ));
+DATA(insert (  405             int2vector_ops          PGNSP PGUID 2224   22 t 0 ));
+DATA(insert (  403             tid_ops                         PGNSP PGUID 2789   27 t 0 ));
+DATA(insert (  405             xid_ops                         PGNSP PGUID 2225   28 t 0 ));
+DATA(insert (  405             cid_ops                         PGNSP PGUID 2226   29 t 0 ));
+DATA(insert (  405             abstime_ops                     PGNSP PGUID 2227  702 t 0 ));
+DATA(insert (  405             reltime_ops                     PGNSP PGUID 2228  703 t 0 ));
+DATA(insert (  405             text_pattern_ops        PGNSP PGUID 2229   25 f 0 ));
+DATA(insert (  405             varchar_pattern_ops PGNSP PGUID 2229   25 f 0 ));
+DATA(insert (  405             bpchar_pattern_ops      PGNSP PGUID 2231 1042 f 0 ));
+DATA(insert (  405             name_pattern_ops        PGNSP PGUID 2232   19 f 0 ));
+DATA(insert (  403             reltime_ops                     PGNSP PGUID 2233  703 t 0 ));
+DATA(insert (  403             tinterval_ops           PGNSP PGUID 2234  704 t 0 ));
+DATA(insert (  405             aclitem_ops                     PGNSP PGUID 2235 1033 t 0 ));
+DATA(insert (  783             box_ops                         PGNSP PGUID 2593  603 t 0 ));
+DATA(insert (  783             poly_ops                        PGNSP PGUID 2594  604 t 603 ));
+DATA(insert (  783             circle_ops                      PGNSP PGUID 2595  718 t 603 ));
+DATA(insert (  2742    _int4_ops                       PGNSP PGUID 2745  1007 t 23 ));
+DATA(insert (  2742    _text_ops                       PGNSP PGUID 2745  1009 t 25 ));
+DATA(insert (  2742    _abstime_ops            PGNSP PGUID 2745  1023 t 702 ));
+DATA(insert (  2742    _bit_ops                        PGNSP PGUID 2745  1561 t 1560 ));
+DATA(insert (  2742    _bool_ops                       PGNSP PGUID 2745  1000 t 16 ));
+DATA(insert (  2742    _bpchar_ops                     PGNSP PGUID 2745  1014 t 1042 ));
+DATA(insert (  2742    _bytea_ops                      PGNSP PGUID 2745  1001 t 17 ));
+DATA(insert (  2742    _char_ops                       PGNSP PGUID 2745  1002 t 18 ));
+DATA(insert (  2742    _cidr_ops                       PGNSP PGUID 2745  651 t 650 ));
+DATA(insert (  2742    _date_ops                       PGNSP PGUID 2745  1182 t 1082 ));
+DATA(insert (  2742    _float4_ops                     PGNSP PGUID 2745  1021 t 700 ));
+DATA(insert (  2742    _float8_ops                     PGNSP PGUID 2745  1022 t 701 ));
+DATA(insert (  2742    _inet_ops                       PGNSP PGUID 2745  1041 t 869 ));
+DATA(insert (  2742    _int2_ops                       PGNSP PGUID 2745  1005 t 21 ));
+DATA(insert (  2742    _int8_ops                       PGNSP PGUID 2745  1016 t 20 ));
+DATA(insert (  2742    _interval_ops           PGNSP PGUID 2745  1187 t 1186 ));
+DATA(insert (  2742    _macaddr_ops            PGNSP PGUID 2745  1040 t 829 ));
+DATA(insert (  2742    _name_ops                       PGNSP PGUID 2745  1003 t 19 ));
+DATA(insert (  2742    _numeric_ops            PGNSP PGUID 2745  1231 t 1700 ));
+DATA(insert (  2742    _oid_ops                        PGNSP PGUID 2745  1028 t 26 ));
+DATA(insert (  2742    _oidvector_ops          PGNSP PGUID 2745  1013 t 30 ));
+DATA(insert (  2742    _time_ops                       PGNSP PGUID 2745  1183 t 1083 ));
+DATA(insert (  2742    _timestamptz_ops        PGNSP PGUID 2745  1185 t 1184 ));
+DATA(insert (  2742    _timetz_ops                     PGNSP PGUID 2745  1270 t 1266 ));
+DATA(insert (  2742    _varbit_ops                     PGNSP PGUID 2745  1563 t 1562 ));
+DATA(insert (  2742    _varchar_ops            PGNSP PGUID 2745  1015 t 1043 ));
+DATA(insert (  2742    _timestamp_ops          PGNSP PGUID 2745  1115 t 1114 ));
+DATA(insert (  2742    _money_ops                      PGNSP PGUID 2745  791 t 790 ));
+DATA(insert (  2742    _reltime_ops            PGNSP PGUID 2745  1024 t 703 ));
+DATA(insert (  2742    _tinterval_ops          PGNSP PGUID 2745  1025 t 704 ));
 
 #endif   /* PG_OPCLASS_H */
index b64b3c5..b2acdc4 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.146 2006/10/04 00:30:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.147 2006/12/23 00:43:12 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -44,16 +44,13 @@ CATALOG(pg_operator,2617)
        Oid                     oprnamespace;   /* OID of namespace containing this oper */
        Oid                     oprowner;               /* operator owner */
        char            oprkind;                /* 'l', 'r', or 'b' */
+       bool            oprcanmerge;    /* can be used in merge join? */
        bool            oprcanhash;             /* can be used in hash join? */
        Oid                     oprleft;                /* left arg type, or 0 if 'l' oprkind */
        Oid                     oprright;               /* right arg type, or 0 if 'r' oprkind */
        Oid                     oprresult;              /* result datatype */
        Oid                     oprcom;                 /* OID of commutator oper, or 0 if none */
        Oid                     oprnegate;              /* OID of negator oper, or 0 if none */
-       Oid                     oprlsortop;             /* OID of left sortop, if mergejoinable */
-       Oid                     oprrsortop;             /* OID of right sortop, if mergejoinable */
-       Oid                     oprltcmpop;             /* OID of "l<r" oper, if mergejoinable */
-       Oid                     oprgtcmpop;             /* OID of "l>r" oper, if mergejoinable */
        regproc         oprcode;                /* OID of underlying function */
        regproc         oprrest;                /* OID of restriction estimator, or 0 */
        regproc         oprjoin;                /* OID of join estimator, or 0 */
@@ -71,837 +68,832 @@ typedef FormData_pg_operator *Form_pg_operator;
  * ----------------
  */
 
-#define Natts_pg_operator                              17
+#define Natts_pg_operator                              14
 #define Anum_pg_operator_oprname               1
 #define Anum_pg_operator_oprnamespace  2
 #define Anum_pg_operator_oprowner              3
 #define Anum_pg_operator_oprkind               4
-#define Anum_pg_operator_oprcanhash            5
-#define Anum_pg_operator_oprleft               6
-#define Anum_pg_operator_oprright              7
-#define Anum_pg_operator_oprresult             8
-#define Anum_pg_operator_oprcom                        9
-#define Anum_pg_operator_oprnegate             10
-#define Anum_pg_operator_oprlsortop            11
-#define Anum_pg_operator_oprrsortop            12
-#define Anum_pg_operator_oprltcmpop            13
-#define Anum_pg_operator_oprgtcmpop            14
-#define Anum_pg_operator_oprcode               15
-#define Anum_pg_operator_oprrest               16
-#define Anum_pg_operator_oprjoin               17
+#define Anum_pg_operator_oprcanmerge   5
+#define Anum_pg_operator_oprcanhash            6
+#define Anum_pg_operator_oprleft               7
+#define Anum_pg_operator_oprright              8
+#define Anum_pg_operator_oprresult             9
+#define Anum_pg_operator_oprcom                        10
+#define Anum_pg_operator_oprnegate             11
+#define Anum_pg_operator_oprcode               12
+#define Anum_pg_operator_oprrest               13
+#define Anum_pg_operator_oprjoin               14
 
 /* ----------------
  *             initial contents of pg_operator
  * ----------------
  */
 
-DATA(insert OID =  15 ( "="               PGNSP PGUID b f      23      20      16 416  36      97 412  37      76 int48eq eqsel eqjoinsel ));
-DATA(insert OID =  36 ( "<>"      PGNSP PGUID b f      23      20      16 417  15       0       0       0       0 int48ne neqsel neqjoinsel ));
-DATA(insert OID =  37 ( "<"               PGNSP PGUID b f      23      20      16 419  82       0       0       0       0 int48lt scalarltsel scalarltjoinsel ));
-DATA(insert OID =  76 ( ">"               PGNSP PGUID b f      23      20      16 418  80       0       0       0       0 int48gt scalargtsel scalargtjoinsel ));
-DATA(insert OID =  80 ( "<="      PGNSP PGUID b f      23      20      16 430  76       0       0       0       0 int48le scalarltsel scalarltjoinsel ));
-DATA(insert OID =  82 ( ">="      PGNSP PGUID b f      23      20      16 420  37       0       0       0       0 int48ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID =  58 ( "<"               PGNSP PGUID b f      16      16      16      59       1695   0       0       0       0 boollt scalarltsel scalarltjoinsel ));
-DATA(insert OID =  59 ( ">"               PGNSP PGUID b f      16      16      16      58       1694   0       0       0       0 boolgt scalargtsel scalargtjoinsel ));
-DATA(insert OID =  85 ( "<>"      PGNSP PGUID b f      16      16      16      85      91       0       0       0       0 boolne neqsel neqjoinsel ));
-DATA(insert OID =  91 ( "="               PGNSP PGUID b t      16      16      16      91      85      58      58      58      59 booleq eqsel eqjoinsel ));
+DATA(insert OID =  15 ( "="               PGNSP PGUID b t f    23      20      16 416  36 int48eq eqsel eqjoinsel ));
+DATA(insert OID =  36 ( "<>"      PGNSP PGUID b f f    23      20      16 417  15 int48ne neqsel neqjoinsel ));
+DATA(insert OID =  37 ( "<"               PGNSP PGUID b f f    23      20      16 419  82 int48lt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  76 ( ">"               PGNSP PGUID b f f    23      20      16 418  80 int48gt scalargtsel scalargtjoinsel ));
+DATA(insert OID =  80 ( "<="      PGNSP PGUID b f f    23      20      16 430  76 int48le scalarltsel scalarltjoinsel ));
+DATA(insert OID =  82 ( ">="      PGNSP PGUID b f f    23      20      16 420  37 int48ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID =  58 ( "<"               PGNSP PGUID b f f    16      16      16      59      1695 boollt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  59 ( ">"               PGNSP PGUID b f f    16      16      16      58      1694 boolgt scalargtsel scalargtjoinsel ));
+DATA(insert OID =  85 ( "<>"      PGNSP PGUID b f f    16      16      16      85      91 boolne neqsel neqjoinsel ));
+DATA(insert OID =  91 ( "="               PGNSP PGUID b t t    16      16      16      91      85 booleq eqsel eqjoinsel ));
 #define BooleanEqualOperator   91
-DATA(insert OID = 1694 (  "<="    PGNSP PGUID b f      16      16      16 1695 59      0  0   0   0 boolle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1695 (  ">="    PGNSP PGUID b f      16      16      16 1694 58      0  0   0   0 boolge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID =  92 ( "="               PGNSP PGUID b t      18      18      16      92 630 631 631 631 633 chareq eqsel eqjoinsel ));
-DATA(insert OID =  93 ( "="               PGNSP PGUID b t      19      19      16      93 643 660 660 660 662 nameeq eqsel eqjoinsel ));
-DATA(insert OID =  94 ( "="               PGNSP PGUID b t      21      21      16      94 519  95      95      95 520 int2eq eqsel eqjoinsel ));
-DATA(insert OID =  95 ( "<"               PGNSP PGUID b f      21      21      16 520 524       0       0       0       0 int2lt scalarltsel scalarltjoinsel ));
-DATA(insert OID =  96 ( "="               PGNSP PGUID b t      23      23      16      96 518  97      97      97 521 int4eq eqsel eqjoinsel ));
-DATA(insert OID =  97 ( "<"               PGNSP PGUID b f      23      23      16 521 525       0       0       0       0 int4lt scalarltsel scalarltjoinsel ));
-DATA(insert OID =  98 ( "="               PGNSP PGUID b t      25      25      16      98 531 664 664 664 666 texteq eqsel eqjoinsel ));
-
-DATA(insert OID = 349 (  "||"     PGNSP PGUID b f 2277 2283 2277       0 0 0 0 0 0 array_append   -       -     ));
-DATA(insert OID = 374 (  "||"     PGNSP PGUID b f 2283 2277 2277       0 0 0 0 0 0 array_prepend  -       -     ));
-DATA(insert OID = 375 (  "||"     PGNSP PGUID b f 2277 2277 2277       0 0 0 0 0 0 array_cat      -       -     ));
-
-DATA(insert OID = 352 (  "="      PGNSP PGUID b t      28      28      16 352   0       0       0       0       0 xideq eqsel eqjoinsel ));
-DATA(insert OID = 353 (  "="      PGNSP PGUID b f      28      23      16       0       0       0       0       0       0 xideqint4 eqsel eqjoinsel ));
-DATA(insert OID = 388 (  "!"      PGNSP PGUID r f      20       0      1700   0   0   0   0  0   0 numeric_fac - - ));
-DATA(insert OID = 389 (  "!!"     PGNSP PGUID l f       0      20      1700   0   0   0   0  0   0 numeric_fac - - ));
-DATA(insert OID = 385 (  "="      PGNSP PGUID b t      29      29      16 385   0       0       0       0       0 cideq eqsel eqjoinsel ));
-DATA(insert OID = 386 (  "="      PGNSP PGUID b t      22      22      16 386   0       0       0       0       0 int2vectoreq eqsel eqjoinsel ));
-
-DATA(insert OID = 387 (  "="      PGNSP PGUID b f      27      27      16 387 402 2799 2799 2799 2800 tideq eqsel eqjoinsel ));
+DATA(insert OID = 1694 (  "<="    PGNSP PGUID b f f    16      16      16 1695 59 boolle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1695 (  ">="    PGNSP PGUID b f f    16      16      16 1694 58 boolge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID =  92 ( "="               PGNSP PGUID b t t    18      18      16      92 630 chareq eqsel eqjoinsel ));
+DATA(insert OID =  93 ( "="               PGNSP PGUID b t t    19      19      16      93 643 nameeq eqsel eqjoinsel ));
+DATA(insert OID =  94 ( "="               PGNSP PGUID b t t    21      21      16      94 519 int2eq eqsel eqjoinsel ));
+DATA(insert OID =  95 ( "<"               PGNSP PGUID b f f    21      21      16 520 524 int2lt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  96 ( "="               PGNSP PGUID b t t    23      23      16      96 518 int4eq eqsel eqjoinsel ));
+DATA(insert OID =  97 ( "<"               PGNSP PGUID b f f    23      23      16 521 525 int4lt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  98 ( "="               PGNSP PGUID b t t    25      25      16      98 531 texteq eqsel eqjoinsel ));
+
+DATA(insert OID = 349 (  "||"     PGNSP PGUID b f f 2277 2283 2277     0 0 array_append   -       -     ));
+DATA(insert OID = 374 (  "||"     PGNSP PGUID b f f 2283 2277 2277     0 0 array_prepend  -       -     ));
+DATA(insert OID = 375 (  "||"     PGNSP PGUID b f f 2277 2277 2277     0 0 array_cat      -       -     ));
+
+DATA(insert OID = 352 (  "="      PGNSP PGUID b f t    28      28      16 352   0 xideq eqsel eqjoinsel ));
+DATA(insert OID = 353 (  "="      PGNSP PGUID b f f    28      23      16       0       0 xideqint4 eqsel eqjoinsel ));
+DATA(insert OID = 388 (  "!"      PGNSP PGUID r f f    20       0      1700  0  0 numeric_fac - - ));
+DATA(insert OID = 389 (  "!!"     PGNSP PGUID l f f     0      20      1700  0  0 numeric_fac - - ));
+DATA(insert OID = 385 (  "="      PGNSP PGUID b f t    29      29      16 385   0 cideq eqsel eqjoinsel ));
+DATA(insert OID = 386 (  "="      PGNSP PGUID b f t    22      22      16 386   0 int2vectoreq eqsel eqjoinsel ));
+
+DATA(insert OID = 387 (  "="      PGNSP PGUID b t f    27      27      16 387 402 tideq eqsel eqjoinsel ));
 #define TIDEqualOperator   387
-DATA(insert OID = 402 (  "<>"     PGNSP PGUID b f      27      27      16 402 387 0 0 0 0 tidne neqsel neqjoinsel ));
-DATA(insert OID = 2799 (  "<"     PGNSP PGUID b f      27      27      16 2800 2802 0 0 0 0 tidlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 402 (  "<>"     PGNSP PGUID b f f    27      27      16 402 387 tidne neqsel neqjoinsel ));
+DATA(insert OID = 2799 (  "<"     PGNSP PGUID b f f    27      27      16 2800 2802 tidlt scalarltsel scalarltjoinsel ));
 #define TIDLessOperator    2799
-DATA(insert OID = 2800 (  ">"     PGNSP PGUID b f      27      27      16 2799 2801 0 0 0 0 tidgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2801 (  "<="    PGNSP PGUID b f      27      27      16 2802 2800 0 0 0 0 tidle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2802 (  ">="    PGNSP PGUID b f      27      27      16 2801 2799 0 0 0 0 tidge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 410 ( "="               PGNSP PGUID b t      20      20      16 410 411 412 412 412 413 int8eq eqsel eqjoinsel ));
-DATA(insert OID = 411 ( "<>"      PGNSP PGUID b f      20      20      16 411 410 0 0 0 0 int8ne neqsel neqjoinsel ));
-DATA(insert OID = 412 ( "<"               PGNSP PGUID b f      20      20      16 413 415 0 0 0 0 int8lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 413 ( ">"               PGNSP PGUID b f      20      20      16 412 414 0 0 0 0 int8gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 414 ( "<="      PGNSP PGUID b f      20      20      16 415 413 0 0 0 0 int8le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 415 ( ">="      PGNSP PGUID b f      20      20      16 414 412 0 0 0 0 int8ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 416 ( "="               PGNSP PGUID b f      20      23      16      15 417 412 97 418 419 int84eq eqsel eqjoinsel ));
-DATA(insert OID = 417 ( "<>"      PGNSP PGUID b f      20      23      16      36 416 0 0 0 0 int84ne neqsel neqjoinsel ));
-DATA(insert OID = 418 ( "<"               PGNSP PGUID b f      20      23      16      76 430 0 0 0 0 int84lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 419 ( ">"               PGNSP PGUID b f      20      23      16      37 420 0 0 0 0 int84gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 420 ( "<="      PGNSP PGUID b f      20      23      16      82 419 0 0 0 0 int84le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 430 ( ">="      PGNSP PGUID b f      20      23      16      80 418 0 0 0 0 int84ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 439 (  "%"      PGNSP PGUID b f      20      20      20       0       0 0 0 0 0 int8mod - - ));
-DATA(insert OID = 473 (  "@"      PGNSP PGUID l f       0      20      20       0       0 0 0 0 0 int8abs - - ));
-
-DATA(insert OID = 484 (  "-"      PGNSP PGUID l f       0      20      20       0       0       0       0       0       0 int8um - - ));
-DATA(insert OID = 485 (  "<<"     PGNSP PGUID b f 604 604      16       0       0       0       0       0       0 poly_left positionsel positionjoinsel ));
-DATA(insert OID = 486 (  "&<"     PGNSP PGUID b f 604 604      16       0       0       0       0       0       0 poly_overleft positionsel positionjoinsel ));
-DATA(insert OID = 487 (  "&>"     PGNSP PGUID b f 604 604      16       0       0       0       0       0       0 poly_overright positionsel positionjoinsel ));
-DATA(insert OID = 488 (  ">>"     PGNSP PGUID b f 604 604      16       0       0       0       0       0       0 poly_right positionsel positionjoinsel ));
-DATA(insert OID = 489 (  "<@"     PGNSP PGUID b f 604 604      16 490   0       0       0       0       0 poly_contained contsel contjoinsel ));
-DATA(insert OID = 490 (  "@>"     PGNSP PGUID b f 604 604      16 489   0       0       0       0       0 poly_contain contsel contjoinsel ));
-DATA(insert OID = 491 (  "~="     PGNSP PGUID b f 604 604      16 491   0       0       0       0       0 poly_same eqsel eqjoinsel ));
-DATA(insert OID = 492 (  "&&"     PGNSP PGUID b f 604 604      16 492   0       0       0       0       0 poly_overlap areasel areajoinsel ));
-DATA(insert OID = 493 (  "<<"     PGNSP PGUID b f 603 603      16       0       0       0       0       0       0 box_left positionsel positionjoinsel ));
-DATA(insert OID = 494 (  "&<"     PGNSP PGUID b f 603 603      16       0       0       0       0       0       0 box_overleft positionsel positionjoinsel ));
-DATA(insert OID = 495 (  "&>"     PGNSP PGUID b f 603 603      16       0       0       0       0       0       0 box_overright positionsel positionjoinsel ));
-DATA(insert OID = 496 (  ">>"     PGNSP PGUID b f 603 603      16       0       0       0       0       0       0 box_right positionsel positionjoinsel ));
-DATA(insert OID = 497 (  "<@"     PGNSP PGUID b f 603 603      16 498   0       0       0       0       0 box_contained contsel contjoinsel ));
-DATA(insert OID = 498 (  "@>"     PGNSP PGUID b f 603 603      16 497   0       0       0       0       0 box_contain contsel contjoinsel ));
-DATA(insert OID = 499 (  "~="     PGNSP PGUID b f 603 603      16 499   0       0       0       0       0 box_same eqsel eqjoinsel ));
-DATA(insert OID = 500 (  "&&"     PGNSP PGUID b f 603 603      16 500   0       0       0       0       0 box_overlap areasel areajoinsel ));
-DATA(insert OID = 501 (  ">="     PGNSP PGUID b f 603 603      16 505 504       0       0       0       0 box_ge areasel areajoinsel ));
-DATA(insert OID = 502 (  ">"      PGNSP PGUID b f 603 603      16 504 505       0       0       0       0 box_gt areasel areajoinsel ));
-DATA(insert OID = 503 (  "="      PGNSP PGUID b f 603 603      16 503   0 504 504 504 502 box_eq eqsel eqjoinsel ));
-DATA(insert OID = 504 (  "<"      PGNSP PGUID b f 603 603      16 502 501       0       0       0       0 box_lt areasel areajoinsel ));
-DATA(insert OID = 505 (  "<="     PGNSP PGUID b f 603 603      16 501 502       0       0       0       0 box_le areasel areajoinsel ));
-DATA(insert OID = 506 (  ">^"     PGNSP PGUID b f 600 600      16       0       0       0       0       0       0 point_above positionsel positionjoinsel ));
-DATA(insert OID = 507 (  "<<"     PGNSP PGUID b f 600 600      16       0       0       0       0       0       0 point_left positionsel positionjoinsel ));
-DATA(insert OID = 508 (  ">>"     PGNSP PGUID b f 600 600      16       0       0       0       0       0       0 point_right positionsel positionjoinsel ));
-DATA(insert OID = 509 (  "<^"     PGNSP PGUID b f 600 600      16       0       0       0       0       0       0 point_below positionsel positionjoinsel ));
-DATA(insert OID = 510 (  "~="     PGNSP PGUID b f 600 600      16 510 713       0       0       0       0 point_eq eqsel eqjoinsel ));
-DATA(insert OID = 511 (  "<@"     PGNSP PGUID b f 600 603      16       0       0       0       0       0       0 on_pb - - ));
-DATA(insert OID = 512 (  "<@"     PGNSP PGUID b f 600 602      16 755   0       0       0       0       0 on_ppath - - ));
-DATA(insert OID = 513 (  "@@"     PGNSP PGUID l f       0 603 600       0       0       0       0       0       0 box_center - - ));
-DATA(insert OID = 514 (  "*"      PGNSP PGUID b f      23      23      23 514   0       0       0       0       0 int4mul - - ));
-DATA(insert OID = 517 (  "<->"    PGNSP PGUID b f 600 600 701 517       0       0       0       0       0 point_distance - - ));
-DATA(insert OID = 518 (  "<>"     PGNSP PGUID b f      23      23      16 518  96      0  0   0   0 int4ne neqsel neqjoinsel ));
-DATA(insert OID = 519 (  "<>"     PGNSP PGUID b f      21      21      16 519  94      0  0   0   0 int2ne neqsel neqjoinsel ));
-DATA(insert OID = 520 (  ">"      PGNSP PGUID b f      21      21      16      95 522  0  0   0   0 int2gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 521 (  ">"      PGNSP PGUID b f      23      23      16      97 523  0  0   0   0 int4gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 522 (  "<="     PGNSP PGUID b f      21      21      16 524 520      0  0   0   0 int2le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 523 (  "<="     PGNSP PGUID b f      23      23      16 525 521      0  0   0   0 int4le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 524 (  ">="     PGNSP PGUID b f      21      21      16 522  95      0  0   0   0 int2ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 525 (  ">="     PGNSP PGUID b f      23      23      16 523  97      0  0   0   0 int4ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 526 (  "*"      PGNSP PGUID b f      21      21      21 526   0      0  0   0   0 int2mul - - ));
-DATA(insert OID = 527 (  "/"      PGNSP PGUID b f      21      21      21       0       0      0  0   0   0 int2div - - ));
-DATA(insert OID = 528 (  "/"      PGNSP PGUID b f      23      23      23       0       0      0  0   0   0 int4div - - ));
-DATA(insert OID = 529 (  "%"      PGNSP PGUID b f      21      21      21       0       0      0  0   0   0 int2mod - - ));
-DATA(insert OID = 530 (  "%"      PGNSP PGUID b f      23      23      23       0       0      0  0   0   0 int4mod - - ));
-DATA(insert OID = 531 (  "<>"     PGNSP PGUID b f      25      25      16 531  98      0       0       0       0 textne neqsel neqjoinsel ));
-DATA(insert OID = 532 (  "="      PGNSP PGUID b f      21      23      16 533 538       95  97 534 536 int24eq eqsel eqjoinsel ));
-DATA(insert OID = 533 (  "="      PGNSP PGUID b f      23      21      16 532 539       97  95 535 537 int42eq eqsel eqjoinsel ));
-DATA(insert OID = 534 (  "<"      PGNSP PGUID b f      21      23      16 537 542      0  0   0   0 int24lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 535 (  "<"      PGNSP PGUID b f      23      21      16 536 543      0  0   0   0 int42lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 536 (  ">"      PGNSP PGUID b f      21      23      16 535 540      0  0   0   0 int24gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 537 (  ">"      PGNSP PGUID b f      23      21      16 534 541      0  0   0   0 int42gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 538 (  "<>"     PGNSP PGUID b f      21      23      16 539 532      0  0   0   0 int24ne neqsel neqjoinsel ));
-DATA(insert OID = 539 (  "<>"     PGNSP PGUID b f      23      21      16 538 533      0  0   0   0 int42ne neqsel neqjoinsel ));
-DATA(insert OID = 540 (  "<="     PGNSP PGUID b f      21      23      16 543 536      0  0   0   0 int24le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 541 (  "<="     PGNSP PGUID b f      23      21      16 542 537      0  0   0   0 int42le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 542 (  ">="     PGNSP PGUID b f      21      23      16 541 534      0  0   0   0 int24ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 543 (  ">="     PGNSP PGUID b f      23      21      16 540 535      0  0   0   0 int42ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 544 (  "*"      PGNSP PGUID b f      21      23      23 545   0       0       0       0       0 int24mul - - ));
-DATA(insert OID = 545 (  "*"      PGNSP PGUID b f      23      21      23 544   0       0       0       0       0 int42mul - - ));
-DATA(insert OID = 546 (  "/"      PGNSP PGUID b f      21      23      23       0       0       0       0       0       0 int24div - - ));
-DATA(insert OID = 547 (  "/"      PGNSP PGUID b f      23      21      23       0       0       0       0       0       0 int42div - - ));
-DATA(insert OID = 548 (  "%"      PGNSP PGUID b f      21      23      23       0       0       0       0       0       0 int24mod - - ));
-DATA(insert OID = 549 (  "%"      PGNSP PGUID b f      23      21      23       0       0       0       0       0       0 int42mod - - ));
-DATA(insert OID = 550 (  "+"      PGNSP PGUID b f      21      21      21 550   0       0       0       0       0 int2pl - - ));
-DATA(insert OID = 551 (  "+"      PGNSP PGUID b f      23      23      23 551   0       0       0       0       0 int4pl - - ));
-DATA(insert OID = 552 (  "+"      PGNSP PGUID b f      21      23      23 553   0       0       0       0       0 int24pl - - ));
-DATA(insert OID = 553 (  "+"      PGNSP PGUID b f      23      21      23 552   0       0       0       0       0 int42pl - - ));
-DATA(insert OID = 554 (  "-"      PGNSP PGUID b f      21      21      21       0       0       0       0       0       0 int2mi - - ));
-DATA(insert OID = 555 (  "-"      PGNSP PGUID b f      23      23      23       0       0       0       0       0       0 int4mi - - ));
-DATA(insert OID = 556 (  "-"      PGNSP PGUID b f      21      23      23       0       0       0       0       0       0 int24mi - - ));
-DATA(insert OID = 557 (  "-"      PGNSP PGUID b f      23      21      23       0       0       0       0       0       0 int42mi - - ));
-DATA(insert OID = 558 (  "-"      PGNSP PGUID l f       0      23      23       0       0       0       0       0       0 int4um - - ));
-DATA(insert OID = 559 (  "-"      PGNSP PGUID l f       0      21      21       0       0       0       0       0       0 int2um - - ));
-DATA(insert OID = 560 (  "="      PGNSP PGUID b t 702 702      16 560 561 562 562 562 563 abstimeeq eqsel eqjoinsel ));
-DATA(insert OID = 561 (  "<>"     PGNSP PGUID b f 702 702      16 561 560 0 0 0 0 abstimene neqsel neqjoinsel ));
-DATA(insert OID = 562 (  "<"      PGNSP PGUID b f 702 702      16 563 565 0 0 0 0 abstimelt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 563 (  ">"      PGNSP PGUID b f 702 702      16 562 564 0 0 0 0 abstimegt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 564 (  "<="     PGNSP PGUID b f 702 702      16 565 563 0 0 0 0 abstimele scalarltsel scalarltjoinsel ));
-DATA(insert OID = 565 (  ">="     PGNSP PGUID b f 702 702      16 564 562 0 0 0 0 abstimege scalargtsel scalargtjoinsel ));
-DATA(insert OID = 566 (  "="      PGNSP PGUID b t 703 703      16 566 567 568 568 568 569 reltimeeq eqsel eqjoinsel ));
-DATA(insert OID = 567 (  "<>"     PGNSP PGUID b f 703 703      16 567 566 0 0 0 0 reltimene neqsel neqjoinsel ));
-DATA(insert OID = 568 (  "<"      PGNSP PGUID b f 703 703      16 569 571 0 0 0 0 reltimelt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 569 (  ">"      PGNSP PGUID b f 703 703      16 568 570 0 0 0 0 reltimegt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 570 (  "<="     PGNSP PGUID b f 703 703      16 571 569 0 0 0 0 reltimele scalarltsel scalarltjoinsel ));
-DATA(insert OID = 571 (  ">="     PGNSP PGUID b f 703 703      16 570 568 0 0 0 0 reltimege scalargtsel scalargtjoinsel ));
-DATA(insert OID = 572 (  "~="     PGNSP PGUID b f 704 704      16 572   0       0       0       0       0 tintervalsame eqsel eqjoinsel ));
-DATA(insert OID = 573 (  "<<"     PGNSP PGUID b f 704 704      16       0       0       0       0       0       0 tintervalct - - ));
-DATA(insert OID = 574 (  "&&"     PGNSP PGUID b f 704 704      16 574   0       0       0       0       0 tintervalov - - ));
-DATA(insert OID = 575 (  "#="     PGNSP PGUID b f 704 703      16       0 576   0       0       0       0 tintervalleneq - - ));
-DATA(insert OID = 576 (  "#<>"    PGNSP PGUID b f 704 703      16       0 575   0       0       0       0 tintervallenne - - ));
-DATA(insert OID = 577 (  "#<"     PGNSP PGUID b f 704 703      16       0 580   0       0       0       0 tintervallenlt - - ));
-DATA(insert OID = 578 (  "#>"     PGNSP PGUID b f 704 703      16       0 579   0       0       0       0 tintervallengt - - ));
-DATA(insert OID = 579 (  "#<="    PGNSP PGUID b f 704 703      16       0 578   0       0       0       0 tintervallenle - - ));
-DATA(insert OID = 580 (  "#>="    PGNSP PGUID b f 704 703      16       0 577   0       0       0       0 tintervallenge - - ));
-DATA(insert OID = 581 (  "+"      PGNSP PGUID b f 702 703 702   0       0 0 0 0 0 timepl - - ));
-DATA(insert OID = 582 (  "-"      PGNSP PGUID b f 702 703 702   0       0 0 0 0 0 timemi - - ));
-DATA(insert OID = 583 (  "<?>"    PGNSP PGUID b f 702 704      16       0       0       0       0       0       0 intinterval - - ));
-DATA(insert OID = 584 (  "-"      PGNSP PGUID l f       0 700 700       0       0       0       0       0       0 float4um - - ));
-DATA(insert OID = 585 (  "-"      PGNSP PGUID l f       0 701 701       0       0       0       0       0       0 float8um - - ));
-DATA(insert OID = 586 (  "+"      PGNSP PGUID b f 700 700 700 586       0       0       0       0       0 float4pl - - ));
-DATA(insert OID = 587 (  "-"      PGNSP PGUID b f 700 700 700   0       0       0       0       0       0 float4mi - - ));
-DATA(insert OID = 588 (  "/"      PGNSP PGUID b f 700 700 700   0       0       0       0       0       0 float4div - - ));
-DATA(insert OID = 589 (  "*"      PGNSP PGUID b f 700 700 700 589       0       0       0       0       0 float4mul - - ));
-DATA(insert OID = 590 (  "@"      PGNSP PGUID l f       0 700 700       0       0       0       0       0       0 float4abs - - ));
-DATA(insert OID = 591 (  "+"      PGNSP PGUID b f 701 701 701 591       0       0       0       0       0 float8pl - - ));
-DATA(insert OID = 592 (  "-"      PGNSP PGUID b f 701 701 701   0       0       0       0       0       0 float8mi - - ));
-DATA(insert OID = 593 (  "/"      PGNSP PGUID b f 701 701 701   0       0       0       0       0       0 float8div - - ));
-DATA(insert OID = 594 (  "*"      PGNSP PGUID b f 701 701 701 594       0       0       0       0       0 float8mul - - ));
-DATA(insert OID = 595 (  "@"      PGNSP PGUID l f       0 701 701       0       0       0       0       0       0 float8abs - - ));
-DATA(insert OID = 596 (  "|/"     PGNSP PGUID l f       0 701 701       0       0       0       0       0       0 dsqrt - - ));
-DATA(insert OID = 597 (  "||/"    PGNSP PGUID l f       0 701 701       0       0       0       0       0       0 dcbrt - - ));
-DATA(insert OID = 1284 (  "|"     PGNSP PGUID l f       0 704 702      0  0   0   0   0   0 tintervalstart - - ));
-DATA(insert OID = 606 (  "<#>"    PGNSP PGUID b f 702 702 704  0  0   0   0   0   0 mktinterval - - ));
-
-DATA(insert OID = 607 (  "="      PGNSP PGUID b t      26      26      16 607 608 609 609 609 610 oideq eqsel eqjoinsel ));
-#define MIN_OIDCMP 607                 /* used by cache code */
-DATA(insert OID = 608 (  "<>"     PGNSP PGUID b f      26      26      16 608 607      0  0   0   0 oidne neqsel neqjoinsel ));
-DATA(insert OID = 609 (  "<"      PGNSP PGUID b f      26      26      16 610 612      0  0   0   0 oidlt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 610 (  ">"      PGNSP PGUID b f      26      26      16 609 611      0  0   0   0 oidgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 611 (  "<="     PGNSP PGUID b f      26      26      16 612 610      0  0   0   0 oidle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 612 (  ">="     PGNSP PGUID b f      26      26      16 611 609      0  0   0   0 oidge scalargtsel scalargtjoinsel ));
-#define MAX_OIDCMP 612                 /* used by cache code */
-
-DATA(insert OID = 644 (  "<>"     PGNSP PGUID b f      30      30      16 644 649       0       0       0       0 oidvectorne neqsel neqjoinsel ));
-DATA(insert OID = 645 (  "<"      PGNSP PGUID b f      30      30      16 646 648       0       0       0       0 oidvectorlt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 646 (  ">"      PGNSP PGUID b f      30      30      16 645 647       0       0       0       0 oidvectorgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 647 (  "<="     PGNSP PGUID b f      30      30      16 648 646       0       0       0       0 oidvectorle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 648 (  ">="     PGNSP PGUID b f      30      30      16 647 645       0       0       0       0 oidvectorge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 649 (  "="      PGNSP PGUID b t      30      30      16 649 644 645 645 645 646 oidvectoreq eqsel eqjoinsel ));
-
-DATA(insert OID = 613 (  "<->"    PGNSP PGUID b f 600 628 701   0       0      0  0   0   0 dist_pl - - ));
-DATA(insert OID = 614 (  "<->"    PGNSP PGUID b f 600 601 701   0       0      0  0   0   0 dist_ps - - ));
-DATA(insert OID = 615 (  "<->"    PGNSP PGUID b f 600 603 701   0       0      0  0   0   0 dist_pb - - ));
-DATA(insert OID = 616 (  "<->"    PGNSP PGUID b f 601 628 701   0       0      0  0   0   0 dist_sl - - ));
-DATA(insert OID = 617 (  "<->"    PGNSP PGUID b f 601 603 701   0       0      0  0   0   0 dist_sb - - ));
-DATA(insert OID = 618 (  "<->"    PGNSP PGUID b f 600 602 701   0       0      0  0   0   0 dist_ppath - - ));
-
-DATA(insert OID = 620 (  "="      PGNSP PGUID b t      700  700        16 620 621      622 622 622 623 float4eq eqsel eqjoinsel ));
-DATA(insert OID = 621 (  "<>"     PGNSP PGUID b f      700  700        16 621 620      0 0   0   0 float4ne neqsel neqjoinsel ));
-DATA(insert OID = 622 (  "<"      PGNSP PGUID b f      700  700        16 623 625      0 0   0   0 float4lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 623 (  ">"      PGNSP PGUID b f      700  700        16 622 624      0 0   0   0 float4gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 624 (  "<="     PGNSP PGUID b f      700  700        16 625 623      0 0   0   0 float4le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 625 (  ">="     PGNSP PGUID b f      700  700        16 624 622      0 0   0   0 float4ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 626 (  "!!="    PGNSP PGUID b f      23       25 16 0   0    0       0       0       0       int4notin - - ));
-DATA(insert OID = 627 (  "!!="    PGNSP PGUID b f      26       25 16 0   0    0       0       0       0       oidnotin - - ));
-DATA(insert OID = 630 (  "<>"     PGNSP PGUID b f      18      18      16 630  92      0 0 0 0 charne neqsel neqjoinsel ));
-
-DATA(insert OID = 631 (  "<"      PGNSP PGUID b f      18      18      16 633 634      0 0 0 0 charlt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 632 (  "<="     PGNSP PGUID b f      18      18      16 634 633      0 0 0 0 charle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 633 (  ">"      PGNSP PGUID b f      18      18      16 631 632      0 0 0 0 chargt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 634 (  ">="     PGNSP PGUID b f      18      18      16 632 631      0 0 0 0 charge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 639 (  "~"      PGNSP PGUID b f      19      25      16 0 640        0 0   0   0 nameregexeq regexeqsel regexeqjoinsel ));
+DATA(insert OID = 2800 (  ">"     PGNSP PGUID b f f    27      27      16 2799 2801 tidgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2801 (  "<="    PGNSP PGUID b f f    27      27      16 2802 2800 tidle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2802 (  ">="    PGNSP PGUID b f f    27      27      16 2801 2799 tidge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 410 ( "="               PGNSP PGUID b t t    20      20      16 410 411 int8eq eqsel eqjoinsel ));
+DATA(insert OID = 411 ( "<>"      PGNSP PGUID b f f    20      20      16 411 410 int8ne neqsel neqjoinsel ));
+DATA(insert OID = 412 ( "<"               PGNSP PGUID b f f    20      20      16 413 415 int8lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 413 ( ">"               PGNSP PGUID b f f    20      20      16 412 414 int8gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 414 ( "<="      PGNSP PGUID b f f    20      20      16 415 413 int8le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 415 ( ">="      PGNSP PGUID b f f    20      20      16 414 412 int8ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 416 ( "="               PGNSP PGUID b t f    20      23      16      15 417 int84eq eqsel eqjoinsel ));
+DATA(insert OID = 417 ( "<>"      PGNSP PGUID b f f    20      23      16      36 416 int84ne neqsel neqjoinsel ));
+DATA(insert OID = 418 ( "<"               PGNSP PGUID b f f    20      23      16      76 430 int84lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 419 ( ">"               PGNSP PGUID b f f    20      23      16      37 420 int84gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 420 ( "<="      PGNSP PGUID b f f    20      23      16      82 419 int84le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 430 ( ">="      PGNSP PGUID b f f    20      23      16      80 418 int84ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 439 (  "%"      PGNSP PGUID b f f    20      20      20       0       0 int8mod - - ));
+DATA(insert OID = 473 (  "@"      PGNSP PGUID l f f     0      20      20       0       0 int8abs - - ));
+
+DATA(insert OID = 484 (  "-"      PGNSP PGUID l f f     0      20      20       0       0 int8um - - ));
+DATA(insert OID = 485 (  "<<"     PGNSP PGUID b f f 604 604    16       0       0 poly_left positionsel positionjoinsel ));
+DATA(insert OID = 486 (  "&<"     PGNSP PGUID b f f 604 604    16       0       0 poly_overleft positionsel positionjoinsel ));
+DATA(insert OID = 487 (  "&>"     PGNSP PGUID b f f 604 604    16       0       0 poly_overright positionsel positionjoinsel ));
+DATA(insert OID = 488 (  ">>"     PGNSP PGUID b f f 604 604    16       0       0 poly_right positionsel positionjoinsel ));
+DATA(insert OID = 489 (  "<@"     PGNSP PGUID b f f 604 604    16 490   0 poly_contained contsel contjoinsel ));
+DATA(insert OID = 490 (  "@>"     PGNSP PGUID b f f 604 604    16 489   0 poly_contain contsel contjoinsel ));
+DATA(insert OID = 491 (  "~="     PGNSP PGUID b f f 604 604    16 491   0 poly_same eqsel eqjoinsel ));
+DATA(insert OID = 492 (  "&&"     PGNSP PGUID b f f 604 604    16 492   0 poly_overlap areasel areajoinsel ));
+DATA(insert OID = 493 (  "<<"     PGNSP PGUID b f f 603 603    16       0       0 box_left positionsel positionjoinsel ));
+DATA(insert OID = 494 (  "&<"     PGNSP PGUID b f f 603 603    16       0       0 box_overleft positionsel positionjoinsel ));
+DATA(insert OID = 495 (  "&>"     PGNSP PGUID b f f 603 603    16       0       0 box_overright positionsel positionjoinsel ));
+DATA(insert OID = 496 (  ">>"     PGNSP PGUID b f f 603 603    16       0       0 box_right positionsel positionjoinsel ));
+DATA(insert OID = 497 (  "<@"     PGNSP PGUID b f f 603 603    16 498   0 box_contained contsel contjoinsel ));
+DATA(insert OID = 498 (  "@>"     PGNSP PGUID b f f 603 603    16 497   0 box_contain contsel contjoinsel ));
+DATA(insert OID = 499 (  "~="     PGNSP PGUID b f f 603 603    16 499   0 box_same eqsel eqjoinsel ));
+DATA(insert OID = 500 (  "&&"     PGNSP PGUID b f f 603 603    16 500   0 box_overlap areasel areajoinsel ));
+DATA(insert OID = 501 (  ">="     PGNSP PGUID b f f 603 603    16 505 504 box_ge areasel areajoinsel ));
+DATA(insert OID = 502 (  ">"      PGNSP PGUID b f f 603 603    16 504 505 box_gt areasel areajoinsel ));
+DATA(insert OID = 503 (  "="      PGNSP PGUID b f f 603 603    16 503   0 box_eq eqsel eqjoinsel ));
+DATA(insert OID = 504 (  "<"      PGNSP PGUID b f f 603 603    16 502 501 box_lt areasel areajoinsel ));
+DATA(insert OID = 505 (  "<="     PGNSP PGUID b f f 603 603    16 501 502 box_le areasel areajoinsel ));
+DATA(insert OID = 506 (  ">^"     PGNSP PGUID b f f 600 600    16       0       0 point_above positionsel positionjoinsel ));
+DATA(insert OID = 507 (  "<<"     PGNSP PGUID b f f 600 600    16       0       0 point_left positionsel positionjoinsel ));
+DATA(insert OID = 508 (  ">>"     PGNSP PGUID b f f 600 600    16       0       0 point_right positionsel positionjoinsel ));
+DATA(insert OID = 509 (  "<^"     PGNSP PGUID b f f 600 600    16       0       0 point_below positionsel positionjoinsel ));
+DATA(insert OID = 510 (  "~="     PGNSP PGUID b f f 600 600    16 510 713 point_eq eqsel eqjoinsel ));
+DATA(insert OID = 511 (  "<@"     PGNSP PGUID b f f 600 603    16       0       0 on_pb - - ));
+DATA(insert OID = 512 (  "<@"     PGNSP PGUID b f f 600 602    16 755   0 on_ppath - - ));
+DATA(insert OID = 513 (  "@@"     PGNSP PGUID l f f     0 603 600       0       0 box_center - - ));
+DATA(insert OID = 514 (  "*"      PGNSP PGUID b f f    23      23      23 514   0 int4mul - - ));
+DATA(insert OID = 517 (  "<->"    PGNSP PGUID b f f 600 600 701 517     0 point_distance - - ));
+DATA(insert OID = 518 (  "<>"     PGNSP PGUID b f f    23      23      16 518  96 int4ne neqsel neqjoinsel ));
+DATA(insert OID = 519 (  "<>"     PGNSP PGUID b f f    21      21      16 519  94 int2ne neqsel neqjoinsel ));
+DATA(insert OID = 520 (  ">"      PGNSP PGUID b f f    21      21      16      95 522 int2gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 521 (  ">"      PGNSP PGUID b f f    23      23      16      97 523 int4gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 522 (  "<="     PGNSP PGUID b f f    21      21      16 524 520 int2le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 523 (  "<="     PGNSP PGUID b f f    23      23      16 525 521 int4le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 524 (  ">="     PGNSP PGUID b f f    21      21      16 522  95 int2ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 525 (  ">="     PGNSP PGUID b f f    23      23      16 523  97 int4ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 526 (  "*"      PGNSP PGUID b f f    21      21      21 526   0 int2mul - - ));
+DATA(insert OID = 527 (  "/"      PGNSP PGUID b f f    21      21      21       0       0 int2div - - ));
+DATA(insert OID = 528 (  "/"      PGNSP PGUID b f f    23      23      23       0       0 int4div - - ));
+DATA(insert OID = 529 (  "%"      PGNSP PGUID b f f    21      21      21       0       0 int2mod - - ));
+DATA(insert OID = 530 (  "%"      PGNSP PGUID b f f    23      23      23       0       0 int4mod - - ));
+DATA(insert OID = 531 (  "<>"     PGNSP PGUID b f f    25      25      16 531  98 textne neqsel neqjoinsel ));
+DATA(insert OID = 532 (  "="      PGNSP PGUID b t f    21      23      16 533 538 int24eq eqsel eqjoinsel ));
+DATA(insert OID = 533 (  "="      PGNSP PGUID b t f    23      21      16 532 539 int42eq eqsel eqjoinsel ));
+DATA(insert OID = 534 (  "<"      PGNSP PGUID b f f    21      23      16 537 542 int24lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 535 (  "<"      PGNSP PGUID b f f    23      21      16 536 543 int42lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 536 (  ">"      PGNSP PGUID b f f    21      23      16 535 540 int24gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 537 (  ">"      PGNSP PGUID b f f    23      21      16 534 541 int42gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 538 (  "<>"     PGNSP PGUID b f f    21      23      16 539 532 int24ne neqsel neqjoinsel ));
+DATA(insert OID = 539 (  "<>"     PGNSP PGUID b f f    23      21      16 538 533 int42ne neqsel neqjoinsel ));
+DATA(insert OID = 540 (  "<="     PGNSP PGUID b f f    21      23      16 543 536 int24le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 541 (  "<="     PGNSP PGUID b f f    23      21      16 542 537 int42le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 542 (  ">="     PGNSP PGUID b f f    21      23      16 541 534 int24ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 543 (  ">="     PGNSP PGUID b f f    23      21      16 540 535 int42ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 544 (  "*"      PGNSP PGUID b f f    21      23      23 545   0 int24mul - - ));
+DATA(insert OID = 545 (  "*"      PGNSP PGUID b f f    23      21      23 544   0 int42mul - - ));
+DATA(insert OID = 546 (  "/"      PGNSP PGUID b f f    21      23      23       0       0 int24div - - ));
+DATA(insert OID = 547 (  "/"      PGNSP PGUID b f f    23      21      23       0       0 int42div - - ));
+DATA(insert OID = 548 (  "%"      PGNSP PGUID b f f    21      23      23       0       0 int24mod - - ));
+DATA(insert OID = 549 (  "%"      PGNSP PGUID b f f    23      21      23       0       0 int42mod - - ));
+DATA(insert OID = 550 (  "+"      PGNSP PGUID b f f    21      21      21 550   0 int2pl - - ));
+DATA(insert OID = 551 (  "+"      PGNSP PGUID b f f    23      23      23 551   0 int4pl - - ));
+DATA(insert OID = 552 (  "+"      PGNSP PGUID b f f    21      23      23 553   0 int24pl - - ));
+DATA(insert OID = 553 (  "+"      PGNSP PGUID b f f    23      21      23 552   0 int42pl - - ));
+DATA(insert OID = 554 (  "-"      PGNSP PGUID b f f    21      21      21       0       0 int2mi - - ));
+DATA(insert OID = 555 (  "-"      PGNSP PGUID b f f    23      23      23       0       0 int4mi - - ));
+DATA(insert OID = 556 (  "-"      PGNSP PGUID b f f    21      23      23       0       0 int24mi - - ));
+DATA(insert OID = 557 (  "-"      PGNSP PGUID b f f    23      21      23       0       0 int42mi - - ));
+DATA(insert OID = 558 (  "-"      PGNSP PGUID l f f     0      23      23       0       0 int4um - - ));
+DATA(insert OID = 559 (  "-"      PGNSP PGUID l f f     0      21      21       0       0 int2um - - ));
+DATA(insert OID = 560 (  "="      PGNSP PGUID b t t 702 702    16 560 561 abstimeeq eqsel eqjoinsel ));
+DATA(insert OID = 561 (  "<>"     PGNSP PGUID b f f 702 702    16 561 560 abstimene neqsel neqjoinsel ));
+DATA(insert OID = 562 (  "<"      PGNSP PGUID b f f 702 702    16 563 565 abstimelt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 563 (  ">"      PGNSP PGUID b f f 702 702    16 562 564 abstimegt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 564 (  "<="     PGNSP PGUID b f f 702 702    16 565 563 abstimele scalarltsel scalarltjoinsel ));
+DATA(insert OID = 565 (  ">="     PGNSP PGUID b f f 702 702    16 564 562 abstimege scalargtsel scalargtjoinsel ));
+DATA(insert OID = 566 (  "="      PGNSP PGUID b t t 703 703    16 566 567 reltimeeq eqsel eqjoinsel ));
+DATA(insert OID = 567 (  "<>"     PGNSP PGUID b f f 703 703    16 567 566 reltimene neqsel neqjoinsel ));
+DATA(insert OID = 568 (  "<"      PGNSP PGUID b f f 703 703    16 569 571 reltimelt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 569 (  ">"      PGNSP PGUID b f f 703 703    16 568 570 reltimegt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 570 (  "<="     PGNSP PGUID b f f 703 703    16 571 569 reltimele scalarltsel scalarltjoinsel ));
+DATA(insert OID = 571 (  ">="     PGNSP PGUID b f f 703 703    16 570 568 reltimege scalargtsel scalargtjoinsel ));
+DATA(insert OID = 572 (  "~="     PGNSP PGUID b f f 704 704    16 572   0 tintervalsame eqsel eqjoinsel ));
+DATA(insert OID = 573 (  "<<"     PGNSP PGUID b f f 704 704    16       0       0 tintervalct - - ));
+DATA(insert OID = 574 (  "&&"     PGNSP PGUID b f f 704 704    16 574   0 tintervalov - - ));
+DATA(insert OID = 575 (  "#="     PGNSP PGUID b f f 704 703    16       0 576 tintervalleneq - - ));
+DATA(insert OID = 576 (  "#<>"    PGNSP PGUID b f f 704 703    16       0 575 tintervallenne - - ));
+DATA(insert OID = 577 (  "#<"     PGNSP PGUID b f f 704 703    16       0 580 tintervallenlt - - ));
+DATA(insert OID = 578 (  "#>"     PGNSP PGUID b f f 704 703    16       0 579 tintervallengt - - ));
+DATA(insert OID = 579 (  "#<="    PGNSP PGUID b f f 704 703    16       0 578 tintervallenle - - ));
+DATA(insert OID = 580 (  "#>="    PGNSP PGUID b f f 704 703    16       0 577 tintervallenge - - ));
+DATA(insert OID = 581 (  "+"      PGNSP PGUID b f f 702 703 702         0       0 timepl - - ));
+DATA(insert OID = 582 (  "-"      PGNSP PGUID b f f 702 703 702         0       0 timemi - - ));
+DATA(insert OID = 583 (  "<?>"    PGNSP PGUID b f f 702 704    16       0       0 intinterval - - ));
+DATA(insert OID = 584 (  "-"      PGNSP PGUID l f f     0 700 700       0       0 float4um - - ));
+DATA(insert OID = 585 (  "-"      PGNSP PGUID l f f     0 701 701       0       0 float8um - - ));
+DATA(insert OID = 586 (  "+"      PGNSP PGUID b f f 700 700 700 586     0 float4pl - - ));
+DATA(insert OID = 587 (  "-"      PGNSP PGUID b f f 700 700 700         0       0 float4mi - - ));
+DATA(insert OID = 588 (  "/"      PGNSP PGUID b f f 700 700 700         0       0 float4div - - ));
+DATA(insert OID = 589 (  "*"      PGNSP PGUID b f f 700 700 700 589     0 float4mul - - ));
+DATA(insert OID = 590 (  "@"      PGNSP PGUID l f f     0 700 700       0       0 float4abs - - ));
+DATA(insert OID = 591 (  "+"      PGNSP PGUID b f f 701 701 701 591     0 float8pl - - ));
+DATA(insert OID = 592 (  "-"      PGNSP PGUID b f f 701 701 701         0       0 float8mi - - ));
+DATA(insert OID = 593 (  "/"      PGNSP PGUID b f f 701 701 701         0       0 float8div - - ));
+DATA(insert OID = 594 (  "*"      PGNSP PGUID b f f 701 701 701 594     0 float8mul - - ));
+DATA(insert OID = 595 (  "@"      PGNSP PGUID l f f     0 701 701       0       0 float8abs - - ));
+DATA(insert OID = 596 (  "|/"     PGNSP PGUID l f f     0 701 701       0       0 dsqrt - - ));
+DATA(insert OID = 597 (  "||/"    PGNSP PGUID l f f     0 701 701       0       0 dcbrt - - ));
+DATA(insert OID = 1284 (  "|"     PGNSP PGUID l f f     0 704 702       0   0 tintervalstart - - ));
+DATA(insert OID = 606 (  "<#>"    PGNSP PGUID b f f 702 702 704         0   0 mktinterval - - ));
+
+DATA(insert OID = 607 (  "="      PGNSP PGUID b t t    26      26      16 607 608 oideq eqsel eqjoinsel ));
+DATA(insert OID = 608 (  "<>"     PGNSP PGUID b f f    26      26      16 608 607 oidne neqsel neqjoinsel ));
+DATA(insert OID = 609 (  "<"      PGNSP PGUID b f f    26      26      16 610 612 oidlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 610 (  ">"      PGNSP PGUID b f f    26      26      16 609 611 oidgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 611 (  "<="     PGNSP PGUID b f f    26      26      16 612 610 oidle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 612 (  ">="     PGNSP PGUID b f f    26      26      16 611 609 oidge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 644 (  "<>"     PGNSP PGUID b f f    30      30      16 644 649 oidvectorne neqsel neqjoinsel ));
+DATA(insert OID = 645 (  "<"      PGNSP PGUID b f f    30      30      16 646 648 oidvectorlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 646 (  ">"      PGNSP PGUID b f f    30      30      16 645 647 oidvectorgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 647 (  "<="     PGNSP PGUID b f f    30      30      16 648 646 oidvectorle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 648 (  ">="     PGNSP PGUID b f f    30      30      16 647 645 oidvectorge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 649 (  "="      PGNSP PGUID b t t    30      30      16 649 644 oidvectoreq eqsel eqjoinsel ));
+
+DATA(insert OID = 613 (  "<->"    PGNSP PGUID b f f 600 628 701         0       0 dist_pl - - ));
+DATA(insert OID = 614 (  "<->"    PGNSP PGUID b f f 600 601 701         0       0 dist_ps - - ));
+DATA(insert OID = 615 (  "<->"    PGNSP PGUID b f f 600 603 701         0       0 dist_pb - - ));
+DATA(insert OID = 616 (  "<->"    PGNSP PGUID b f f 601 628 701         0       0 dist_sl - - ));
+DATA(insert OID = 617 (  "<->"    PGNSP PGUID b f f 601 603 701         0       0 dist_sb - - ));
+DATA(insert OID = 618 (  "<->"    PGNSP PGUID b f f 600 602 701         0       0 dist_ppath - - ));
+
+DATA(insert OID = 620 (  "="      PGNSP PGUID b t t    700  700        16 620 621 float4eq eqsel eqjoinsel ));
+DATA(insert OID = 621 (  "<>"     PGNSP PGUID b f f    700  700        16 621 620 float4ne neqsel neqjoinsel ));
+DATA(insert OID = 622 (  "<"      PGNSP PGUID b f f    700  700        16 623 625 float4lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 623 (  ">"      PGNSP PGUID b f f    700  700        16 622 624 float4gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 624 (  "<="     PGNSP PGUID b f f    700  700        16 625 623 float4le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 625 (  ">="     PGNSP PGUID b f f    700  700        16 624 622 float4ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 626 (  "!!="    PGNSP PGUID b f f    23       25             16 0   0        int4notin - - ));
+DATA(insert OID = 627 (  "!!="    PGNSP PGUID b f f    26       25             16 0   0        oidnotin - - ));
+DATA(insert OID = 630 (  "<>"     PGNSP PGUID b f f    18      18              16 630  92      charne neqsel neqjoinsel ));
+
+DATA(insert OID = 631 (  "<"      PGNSP PGUID b f f    18      18      16 633 634 charlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 632 (  "<="     PGNSP PGUID b f f    18      18      16 634 633 charle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 633 (  ">"      PGNSP PGUID b f f    18      18      16 631 632 chargt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 634 (  ">="     PGNSP PGUID b f f    18      18      16 632 631 charge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 639 (  "~"      PGNSP PGUID b f f    19      25      16 0 640 nameregexeq regexeqsel regexeqjoinsel ));
 #define OID_NAME_REGEXEQ_OP            639
-DATA(insert OID = 640 (  "!~"     PGNSP PGUID b f      19      25      16 0 639        0 0   0   0 nameregexne regexnesel regexnejoinsel ));
-DATA(insert OID = 641 (  "~"      PGNSP PGUID b f      25      25      16 0 642        0 0   0   0 textregexeq regexeqsel regexeqjoinsel ));
+DATA(insert OID = 640 (  "!~"     PGNSP PGUID b f f    19      25      16 0 639 nameregexne regexnesel regexnejoinsel ));
+DATA(insert OID = 641 (  "~"      PGNSP PGUID b f f    25      25      16 0 642 textregexeq regexeqsel regexeqjoinsel ));
 #define OID_TEXT_REGEXEQ_OP            641
-DATA(insert OID = 642 (  "!~"     PGNSP PGUID b f      25      25      16 0 641        0 0   0   0 textregexne regexnesel regexnejoinsel ));
-DATA(insert OID = 643 (  "<>"     PGNSP PGUID b f      19      19      16 643 93 0 0 0 0 namene neqsel neqjoinsel ));
-DATA(insert OID = 654 (  "||"     PGNSP PGUID b f      25      25      25       0 0    0 0   0   0 textcat - - ));
-
-DATA(insert OID = 660 (  "<"      PGNSP PGUID b f      19      19      16 662 663      0 0 0 0 namelt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 661 (  "<="     PGNSP PGUID b f      19      19      16 663 662      0 0 0 0 namele scalarltsel scalarltjoinsel ));
-DATA(insert OID = 662 (  ">"      PGNSP PGUID b f      19      19      16 660 661      0 0 0 0 namegt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 663 (  ">="     PGNSP PGUID b f      19      19      16 661 660      0 0 0 0 namege scalargtsel scalargtjoinsel ));
-DATA(insert OID = 664 (  "<"      PGNSP PGUID b f      25      25      16 666 667      0 0 0 0 text_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 665 (  "<="     PGNSP PGUID b f      25      25      16 667 666      0 0 0 0 text_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 666 (  ">"      PGNSP PGUID b f      25      25      16 664 665      0 0 0 0 text_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 667 (  ">="     PGNSP PGUID b f      25      25      16 665 664      0 0 0 0 text_ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 670 (  "="      PGNSP PGUID b t      701  701        16 670 671 672 672 672 674 float8eq eqsel eqjoinsel ));
-DATA(insert OID = 671 (  "<>"     PGNSP PGUID b f      701  701        16 671 670      0 0   0   0 float8ne neqsel neqjoinsel ));
-DATA(insert OID = 672 (  "<"      PGNSP PGUID b f      701  701        16 674 675      0 0   0   0 float8lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 673 (  "<="     PGNSP PGUID b f      701  701        16 675 674      0 0   0   0 float8le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 674 (  ">"      PGNSP PGUID b f      701  701        16 672 673      0 0   0   0 float8gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 675 (  ">="     PGNSP PGUID b f      701  701        16 673 672      0 0   0   0 float8ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 682 (  "@"      PGNSP PGUID l f       0      21      21       0       0       0       0       0       0 int2abs - - ));
-DATA(insert OID = 684 (  "+"      PGNSP PGUID b f      20      20      20 684   0       0       0       0       0 int8pl - - ));
-DATA(insert OID = 685 (  "-"      PGNSP PGUID b f      20      20      20       0       0       0       0       0       0 int8mi - - ));
-DATA(insert OID = 686 (  "*"      PGNSP PGUID b f      20      20      20 686   0       0       0       0       0 int8mul - - ));
-DATA(insert OID = 687 (  "/"      PGNSP PGUID b f      20      20      20       0       0       0       0       0       0 int8div - - ));
-DATA(insert OID = 688 (  "+"      PGNSP PGUID b f      20      23      20 692   0       0       0       0       0 int84pl - - ));
-DATA(insert OID = 689 (  "-"      PGNSP PGUID b f      20      23      20       0       0       0       0       0       0 int84mi - - ));
-DATA(insert OID = 690 (  "*"      PGNSP PGUID b f      20      23      20 694   0       0       0       0       0 int84mul - - ));
-DATA(insert OID = 691 (  "/"      PGNSP PGUID b f      20      23      20       0       0       0       0       0       0 int84div - - ));
-DATA(insert OID = 692 (  "+"      PGNSP PGUID b f      23      20      20 688   0       0       0       0       0 int48pl - - ));
-DATA(insert OID = 693 (  "-"      PGNSP PGUID b f      23      20      20       0       0       0       0       0       0 int48mi - - ));
-DATA(insert OID = 694 (  "*"      PGNSP PGUID b f      23      20      20 690   0       0       0       0       0 int48mul - - ));
-DATA(insert OID = 695 (  "/"      PGNSP PGUID b f      23      20      20       0       0       0       0       0       0 int48div - - ));
-
-DATA(insert OID = 706 (  "<->"    PGNSP PGUID b f 603 603 701 706       0      0  0   0   0 box_distance - - ));
-DATA(insert OID = 707 (  "<->"    PGNSP PGUID b f 602 602 701 707       0      0  0   0   0 path_distance - - ));
-DATA(insert OID = 708 (  "<->"    PGNSP PGUID b f 628 628 701 708       0      0  0   0   0 line_distance - - ));
-DATA(insert OID = 709 (  "<->"    PGNSP PGUID b f 601 601 701 709       0      0  0   0   0 lseg_distance - - ));
-DATA(insert OID = 712 (  "<->"    PGNSP PGUID b f 604 604 701 712       0      0  0   0   0 poly_distance - - ));
-
-DATA(insert OID = 713 (  "<>"     PGNSP PGUID b f 600 600      16 713 510      0  0   0   0 point_ne neqsel neqjoinsel ));
+DATA(insert OID = 642 (  "!~"     PGNSP PGUID b f f    25      25      16 0 641 textregexne regexnesel regexnejoinsel ));
+DATA(insert OID = 643 (  "<>"     PGNSP PGUID b f f    19      19      16 643 93 namene neqsel neqjoinsel ));
+DATA(insert OID = 654 (  "||"     PGNSP PGUID b f f    25      25      25       0 0 textcat - - ));
+
+DATA(insert OID = 660 (  "<"      PGNSP PGUID b f f    19      19      16 662 663 namelt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 661 (  "<="     PGNSP PGUID b f f    19      19      16 663 662 namele scalarltsel scalarltjoinsel ));
+DATA(insert OID = 662 (  ">"      PGNSP PGUID b f f    19      19      16 660 661 namegt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 663 (  ">="     PGNSP PGUID b f f    19      19      16 661 660 namege scalargtsel scalargtjoinsel ));
+DATA(insert OID = 664 (  "<"      PGNSP PGUID b f f    25      25      16 666 667 text_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 665 (  "<="     PGNSP PGUID b f f    25      25      16 667 666 text_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 666 (  ">"      PGNSP PGUID b f f    25      25      16 664 665 text_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 667 (  ">="     PGNSP PGUID b f f    25      25      16 665 664 text_ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 670 (  "="      PGNSP PGUID b t t    701  701        16 670 671 float8eq eqsel eqjoinsel ));
+DATA(insert OID = 671 (  "<>"     PGNSP PGUID b f f    701  701        16 671 670 float8ne neqsel neqjoinsel ));
+DATA(insert OID = 672 (  "<"      PGNSP PGUID b f f    701  701        16 674 675 float8lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 673 (  "<="     PGNSP PGUID b f f    701  701        16 675 674 float8le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 674 (  ">"      PGNSP PGUID b f f    701  701        16 672 673 float8gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 675 (  ">="     PGNSP PGUID b f f    701  701        16 673 672 float8ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 682 (  "@"      PGNSP PGUID l f f     0      21      21       0       0 int2abs - - ));
+DATA(insert OID = 684 (  "+"      PGNSP PGUID b f f    20      20      20 684   0 int8pl - - ));
+DATA(insert OID = 685 (  "-"      PGNSP PGUID b f f    20      20      20       0       0 int8mi - - ));
+DATA(insert OID = 686 (  "*"      PGNSP PGUID b f f    20      20      20 686   0 int8mul - - ));
+DATA(insert OID = 687 (  "/"      PGNSP PGUID b f f    20      20      20       0       0 int8div - - ));
+DATA(insert OID = 688 (  "+"      PGNSP PGUID b f f    20      23      20 692   0 int84pl - - ));
+DATA(insert OID = 689 (  "-"      PGNSP PGUID b f f    20      23      20       0       0 int84mi - - ));
+DATA(insert OID = 690 (  "*"      PGNSP PGUID b f f    20      23      20 694   0 int84mul - - ));
+DATA(insert OID = 691 (  "/"      PGNSP PGUID b f f    20      23      20       0       0 int84div - - ));
+DATA(insert OID = 692 (  "+"      PGNSP PGUID b f f    23      20      20 688   0 int48pl - - ));
+DATA(insert OID = 693 (  "-"      PGNSP PGUID b f f    23      20      20       0       0 int48mi - - ));
+DATA(insert OID = 694 (  "*"      PGNSP PGUID b f f    23      20      20 690   0 int48mul - - ));
+DATA(insert OID = 695 (  "/"      PGNSP PGUID b f f    23      20      20       0       0 int48div - - ));
+
+DATA(insert OID = 706 (  "<->"    PGNSP PGUID b f f 603 603 701 706     0 box_distance - - ));
+DATA(insert OID = 707 (  "<->"    PGNSP PGUID b f f 602 602 701 707     0 path_distance - - ));
+DATA(insert OID = 708 (  "<->"    PGNSP PGUID b f f 628 628 701 708     0 line_distance - - ));
+DATA(insert OID = 709 (  "<->"    PGNSP PGUID b f f 601 601 701 709     0 lseg_distance - - ));
+DATA(insert OID = 712 (  "<->"    PGNSP PGUID b f f 604 604 701 712     0 poly_distance - - ));
+
+DATA(insert OID = 713 (  "<>"     PGNSP PGUID b f f 600 600    16 713 510 point_ne neqsel neqjoinsel ));
 
 /* add translation/rotation/scaling operators for geometric types. - thomas 97/05/10 */
-DATA(insert OID = 731 (  "+"      PGNSP PGUID b f      600  600        600  731  0 0 0 0 0 point_add - - ));
-DATA(insert OID = 732 (  "-"      PGNSP PGUID b f      600  600        600    0  0 0 0 0 0 point_sub - - ));
-DATA(insert OID = 733 (  "*"      PGNSP PGUID b f      600  600        600  733  0 0 0 0 0 point_mul - - ));
-DATA(insert OID = 734 (  "/"      PGNSP PGUID b f      600  600        600    0  0 0 0 0 0 point_div - - ));
-DATA(insert OID = 735 (  "+"      PGNSP PGUID b f      602  602        602  735  0 0 0 0 0 path_add - - ));
-DATA(insert OID = 736 (  "+"      PGNSP PGUID b f      602  600        602    0  0 0 0 0 0 path_add_pt - - ));
-DATA(insert OID = 737 (  "-"      PGNSP PGUID b f      602  600        602    0  0 0 0 0 0 path_sub_pt - - ));
-DATA(insert OID = 738 (  "*"      PGNSP PGUID b f      602  600        602    0  0 0 0 0 0 path_mul_pt - - ));
-DATA(insert OID = 739 (  "/"      PGNSP PGUID b f      602  600        602    0  0 0 0 0 0 path_div_pt - - ));
-DATA(insert OID = 755 (  "@>"     PGNSP PGUID b f      602  600         16  512  0 0 0 0 0 path_contain_pt - - ));
-DATA(insert OID = 756 (  "<@"     PGNSP PGUID b f      600  604         16  757  0 0 0 0 0 pt_contained_poly - - ));
-DATA(insert OID = 757 (  "@>"     PGNSP PGUID b f      604  600         16  756  0 0 0 0 0 poly_contain_pt - - ));
-DATA(insert OID = 758 (  "<@"     PGNSP PGUID b f      600  718         16  759  0 0 0 0 0 pt_contained_circle - - ));
-DATA(insert OID = 759 (  "@>"     PGNSP PGUID b f      718  600         16  758  0 0 0 0 0 circle_contain_pt - - ));
-
-DATA(insert OID = 773 (  "@"      PGNSP PGUID l f       0      23      23       0       0       0       0       0       0 int4abs - - ));
+DATA(insert OID = 731 (  "+"      PGNSP PGUID b f f    600  600        600  731  0 point_add - - ));
+DATA(insert OID = 732 (  "-"      PGNSP PGUID b f f    600  600        600    0  0 point_sub - - ));
+DATA(insert OID = 733 (  "*"      PGNSP PGUID b f f    600  600        600  733  0 point_mul - - ));
+DATA(insert OID = 734 (  "/"      PGNSP PGUID b f f    600  600        600    0  0 point_div - - ));
+DATA(insert OID = 735 (  "+"      PGNSP PGUID b f f    602  602        602  735  0 path_add - - ));
+DATA(insert OID = 736 (  "+"      PGNSP PGUID b f f    602  600        602    0  0 path_add_pt - - ));
+DATA(insert OID = 737 (  "-"      PGNSP PGUID b f f    602  600        602    0  0 path_sub_pt - - ));
+DATA(insert OID = 738 (  "*"      PGNSP PGUID b f f    602  600        602    0  0 path_mul_pt - - ));
+DATA(insert OID = 739 (  "/"      PGNSP PGUID b f f    602  600        602    0  0 path_div_pt - - ));
+DATA(insert OID = 755 (  "@>"     PGNSP PGUID b f f    602  600         16  512  0 path_contain_pt - - ));
+DATA(insert OID = 756 (  "<@"     PGNSP PGUID b f f    600  604         16  757  0 pt_contained_poly - - ));
+DATA(insert OID = 757 (  "@>"     PGNSP PGUID b f f    604  600         16  756  0 poly_contain_pt - - ));
+DATA(insert OID = 758 (  "<@"     PGNSP PGUID b f f    600  718         16  759  0 pt_contained_circle - - ));
+DATA(insert OID = 759 (  "@>"     PGNSP PGUID b f f    718  600         16  758  0 circle_contain_pt - - ));
+
+DATA(insert OID = 773 (  "@"      PGNSP PGUID l f f     0      23      23       0       0 int4abs - - ));
 
 /* additional operators for geometric types - thomas 1997-07-09 */
-DATA(insert OID =  792 (  "="     PGNSP PGUID b f      602  602         16  792  0 0 0 0 0 path_n_eq eqsel eqjoinsel ));
-DATA(insert OID =  793 (  "<"     PGNSP PGUID b f      602  602         16  794  0 0 0 0 0 path_n_lt - - ));
-DATA(insert OID =  794 (  ">"     PGNSP PGUID b f      602  602         16  793  0 0 0 0 0 path_n_gt - - ));
-DATA(insert OID =  795 (  "<="    PGNSP PGUID b f      602  602         16  796  0 0 0 0 0 path_n_le - - ));
-DATA(insert OID =  796 (  ">="    PGNSP PGUID b f      602  602         16  795  0 0 0 0 0 path_n_ge - - ));
-DATA(insert OID =  797 (  "#"     PGNSP PGUID l f      0  602   23    0  0 0 0 0 0 path_npoints - - ));
-DATA(insert OID =  798 (  "?#"    PGNSP PGUID b f      602  602         16    0  0 0 0 0 0 path_inter - - ));
-DATA(insert OID =  799 (  "@-@"    PGNSP PGUID l f     0  602  701    0  0 0 0 0 0 path_length - - ));
-DATA(insert OID =  800 (  ">^"    PGNSP PGUID b f      603  603         16    0  0 0 0 0 0 box_above_eq positionsel positionjoinsel ));
-DATA(insert OID =  801 (  "<^"    PGNSP PGUID b f      603  603         16    0  0 0 0 0 0 box_below_eq positionsel positionjoinsel ));
-DATA(insert OID =  802 (  "?#"    PGNSP PGUID b f      603  603         16    0  0 0 0 0 0 box_overlap areasel areajoinsel ));
-DATA(insert OID =  803 (  "#"     PGNSP PGUID b f      603  603        603    0  0 0 0 0 0 box_intersect - - ));
-DATA(insert OID =  804 (  "+"     PGNSP PGUID b f      603  600        603    0  0 0 0 0 0 box_add - - ));
-DATA(insert OID =  805 (  "-"     PGNSP PGUID b f      603  600        603    0  0 0 0 0 0 box_sub - - ));
-DATA(insert OID =  806 (  "*"     PGNSP PGUID b f      603  600        603    0  0 0 0 0 0 box_mul - - ));
-DATA(insert OID =  807 (  "/"     PGNSP PGUID b f      603  600        603    0  0 0 0 0 0 box_div - - ));
-DATA(insert OID =  808 (  "?-"    PGNSP PGUID b f      600  600         16  808  0 0 0 0 0 point_horiz - - ));
-DATA(insert OID =  809 (  "?|"    PGNSP PGUID b f      600  600         16  809  0 0 0 0 0 point_vert - - ));
-
-DATA(insert OID = 811 (  "="      PGNSP PGUID b f 704 704      16 811 812       0       0       0       0 tintervaleq eqsel eqjoinsel ));
-DATA(insert OID = 812 (  "<>"     PGNSP PGUID b f 704 704      16 812 811       0       0       0       0 tintervalne neqsel neqjoinsel ));
-DATA(insert OID = 813 (  "<"      PGNSP PGUID b f 704 704      16 814 816       0       0       0       0 tintervallt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 814 (  ">"      PGNSP PGUID b f 704 704      16 813 815       0       0       0       0 tintervalgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 815 (  "<="     PGNSP PGUID b f 704 704      16 816 814       0       0       0       0 tintervalle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 816 (  ">="     PGNSP PGUID b f 704 704      16 815 813       0       0       0       0 tintervalge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 843 (  "*"      PGNSP PGUID b f      790  700        790 845   0   0   0   0   0 cash_mul_flt4 - - ));
-DATA(insert OID = 844 (  "/"      PGNSP PGUID b f      790  700        790   0   0   0   0   0   0 cash_div_flt4 - - ));
-DATA(insert OID = 845 (  "*"      PGNSP PGUID b f      700  790        790 843   0   0   0   0   0 flt4_mul_cash - - ));
-
-DATA(insert OID = 900 (  "="      PGNSP PGUID b f      790  790        16 900 901      902 902 902 903 cash_eq eqsel eqjoinsel ));
-DATA(insert OID = 901 (  "<>"     PGNSP PGUID b f      790  790        16 901 900      0 0   0   0 cash_ne neqsel neqjoinsel ));
-DATA(insert OID = 902 (  "<"      PGNSP PGUID b f      790  790        16 903 905      0 0   0   0 cash_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 903 (  ">"      PGNSP PGUID b f      790  790        16 902 904      0 0   0   0 cash_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 904 (  "<="     PGNSP PGUID b f      790  790        16 905 903      0 0   0   0 cash_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 905 (  ">="     PGNSP PGUID b f      790  790        16 904 902      0 0   0   0 cash_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 906 (  "+"      PGNSP PGUID b f      790  790        790 906   0   0   0   0   0 cash_pl - - ));
-DATA(insert OID = 907 (  "-"      PGNSP PGUID b f      790  790        790   0   0   0   0   0   0 cash_mi - - ));
-DATA(insert OID = 908 (  "*"      PGNSP PGUID b f      790  701        790 916   0   0   0   0   0 cash_mul_flt8 - - ));
-DATA(insert OID = 909 (  "/"      PGNSP PGUID b f      790  701        790   0   0   0   0   0   0 cash_div_flt8 - - ));
-DATA(insert OID = 912 (  "*"      PGNSP PGUID b f      790  23 790 917   0   0   0   0   0 cash_mul_int4 - - ));
-DATA(insert OID = 913 (  "/"      PGNSP PGUID b f      790  23 790   0   0   0   0   0   0 cash_div_int4 - - ));
-DATA(insert OID = 914 (  "*"      PGNSP PGUID b f      790  21 790 918   0   0   0   0   0 cash_mul_int2 - - ));
-DATA(insert OID = 915 (  "/"      PGNSP PGUID b f      790  21 790   0   0   0   0   0   0 cash_div_int2 - - ));
-DATA(insert OID = 916 (  "*"      PGNSP PGUID b f      701  790        790 908   0   0   0   0   0 flt8_mul_cash - - ));
-DATA(insert OID = 917 (  "*"      PGNSP PGUID b f      23      790 790 912   0   0   0   0   0 int4_mul_cash - - ));
-DATA(insert OID = 918 (  "*"      PGNSP PGUID b f      21      790 790 914   0   0   0   0   0 int2_mul_cash - - ));
-
-DATA(insert OID = 965 (  "^"      PGNSP PGUID b f      701  701        701 0 0 0 0 0 0 dpow - - ));
-DATA(insert OID = 966 (  "+"      PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclinsert - - ));
-DATA(insert OID = 967 (  "-"      PGNSP PGUID b f 1034 1033 1034 0 0 0 0 0 0 aclremove - - ));
-DATA(insert OID = 968 (  "@>"     PGNSP PGUID b f 1034 1033     16 0 0 0 0 0 0 aclcontains - - ));
-DATA(insert OID = 974 (  "="      PGNSP PGUID b t 1033 1033     16 974 0 0 0 0 0 aclitemeq eqsel eqjoinsel ));
+DATA(insert OID =  792 (  "="     PGNSP PGUID b f f    602  602         16  792  0 path_n_eq eqsel eqjoinsel ));
+DATA(insert OID =  793 (  "<"     PGNSP PGUID b f f    602  602         16  794  0 path_n_lt - - ));
+DATA(insert OID =  794 (  ">"     PGNSP PGUID b f f    602  602         16  793  0 path_n_gt - - ));
+DATA(insert OID =  795 (  "<="    PGNSP PGUID b f f    602  602         16  796  0 path_n_le - - ));
+DATA(insert OID =  796 (  ">="    PGNSP PGUID b f f    602  602         16  795  0 path_n_ge - - ));
+DATA(insert OID =  797 (  "#"     PGNSP PGUID l f f    0    602         23    0  0 path_npoints - - ));
+DATA(insert OID =  798 (  "?#"    PGNSP PGUID b f f    602  602         16    0  0 path_inter - - ));
+DATA(insert OID =  799 (  "@-@"    PGNSP PGUID l f f   0    602        701    0  0 path_length - - ));
+DATA(insert OID =  800 (  ">^"    PGNSP PGUID b f f    603  603         16    0  0 box_above_eq positionsel positionjoinsel ));
+DATA(insert OID =  801 (  "<^"    PGNSP PGUID b f f    603  603         16    0  0 box_below_eq positionsel positionjoinsel ));
+DATA(insert OID =  802 (  "?#"    PGNSP PGUID b f f    603  603         16    0  0 box_overlap areasel areajoinsel ));
+DATA(insert OID =  803 (  "#"     PGNSP PGUID b f f    603  603        603    0  0 box_intersect - - ));
+DATA(insert OID =  804 (  "+"     PGNSP PGUID b f f    603  600        603    0  0 box_add - - ));
+DATA(insert OID =  805 (  "-"     PGNSP PGUID b f f    603  600        603    0  0 box_sub - - ));
+DATA(insert OID =  806 (  "*"     PGNSP PGUID b f f    603  600        603    0  0 box_mul - - ));
+DATA(insert OID =  807 (  "/"     PGNSP PGUID b f f    603  600        603    0  0 box_div - - ));
+DATA(insert OID =  808 (  "?-"    PGNSP PGUID b f f    600  600         16  808  0 point_horiz - - ));
+DATA(insert OID =  809 (  "?|"    PGNSP PGUID b f f    600  600         16  809  0 point_vert - - ));
+
+DATA(insert OID = 811 (  "="      PGNSP PGUID b t f 704 704    16 811 812 tintervaleq eqsel eqjoinsel ));
+DATA(insert OID = 812 (  "<>"     PGNSP PGUID b f f 704 704    16 812 811 tintervalne neqsel neqjoinsel ));
+DATA(insert OID = 813 (  "<"      PGNSP PGUID b f f 704 704    16 814 816 tintervallt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 814 (  ">"      PGNSP PGUID b f f 704 704    16 813 815 tintervalgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 815 (  "<="     PGNSP PGUID b f f 704 704    16 816 814 tintervalle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 816 (  ">="     PGNSP PGUID b f f 704 704    16 815 813 tintervalge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 843 (  "*"      PGNSP PGUID b f f    790  700        790 845   0 cash_mul_flt4 - - ));
+DATA(insert OID = 844 (  "/"      PGNSP PGUID b f f    790  700        790   0   0 cash_div_flt4 - - ));
+DATA(insert OID = 845 (  "*"      PGNSP PGUID b f f    700  790        790 843   0 flt4_mul_cash - - ));
+
+DATA(insert OID = 900 (  "="      PGNSP PGUID b t f    790  790        16 900 901 cash_eq eqsel eqjoinsel ));
+DATA(insert OID = 901 (  "<>"     PGNSP PGUID b f f    790  790        16 901 900 cash_ne neqsel neqjoinsel ));
+DATA(insert OID = 902 (  "<"      PGNSP PGUID b f f    790  790        16 903 905 cash_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 903 (  ">"      PGNSP PGUID b f f    790  790        16 902 904 cash_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 904 (  "<="     PGNSP PGUID b f f    790  790        16 905 903 cash_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 905 (  ">="     PGNSP PGUID b f f    790  790        16 904 902 cash_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 906 (  "+"      PGNSP PGUID b f f    790  790        790 906   0 cash_pl - - ));
+DATA(insert OID = 907 (  "-"      PGNSP PGUID b f f    790  790        790   0   0 cash_mi - - ));
+DATA(insert OID = 908 (  "*"      PGNSP PGUID b f f    790  701        790 916   0 cash_mul_flt8 - - ));
+DATA(insert OID = 909 (  "/"      PGNSP PGUID b f f    790  701        790   0   0 cash_div_flt8 - - ));
+DATA(insert OID = 912 (  "*"      PGNSP PGUID b f f    790  23         790 917   0 cash_mul_int4 - - ));
+DATA(insert OID = 913 (  "/"      PGNSP PGUID b f f    790  23         790   0   0 cash_div_int4 - - ));
+DATA(insert OID = 914 (  "*"      PGNSP PGUID b f f    790  21         790 918   0 cash_mul_int2 - - ));
+DATA(insert OID = 915 (  "/"      PGNSP PGUID b f f    790  21         790   0   0 cash_div_int2 - - ));
+DATA(insert OID = 916 (  "*"      PGNSP PGUID b f f    701  790        790 908   0 flt8_mul_cash - - ));
+DATA(insert OID = 917 (  "*"      PGNSP PGUID b f f    23      790             790 912   0 int4_mul_cash - - ));
+DATA(insert OID = 918 (  "*"      PGNSP PGUID b f f    21      790             790 914   0 int2_mul_cash - - ));
+
+DATA(insert OID = 965 (  "^"      PGNSP PGUID b f f    701  701        701 0 0 dpow - - ));
+DATA(insert OID = 966 (  "+"      PGNSP PGUID b f f 1034 1033 1034 0 0 aclinsert - - ));
+DATA(insert OID = 967 (  "-"      PGNSP PGUID b f f 1034 1033 1034 0 0 aclremove - - ));
+DATA(insert OID = 968 (  "@>"     PGNSP PGUID b f f 1034 1033   16 0 0 aclcontains - - ));
+DATA(insert OID = 974 (  "="      PGNSP PGUID b f t 1033 1033   16 974 0 aclitemeq eqsel eqjoinsel ));
 
 /* additional geometric operators - thomas 1997-07-09 */
-DATA(insert OID =  969 (  "@@"    PGNSP PGUID l f      0  601  600    0  0 0 0 0 0 lseg_center - - ));
-DATA(insert OID =  970 (  "@@"    PGNSP PGUID l f      0  602  600    0  0 0 0 0 0 path_center - - ));
-DATA(insert OID =  971 (  "@@"    PGNSP PGUID l f      0  604  600    0  0 0 0 0 0 poly_center - - ));
+DATA(insert OID =  969 (  "@@"    PGNSP PGUID l f f    0  601  600    0  0 lseg_center - - ));
+DATA(insert OID =  970 (  "@@"    PGNSP PGUID l f f    0  602  600    0  0 path_center - - ));
+DATA(insert OID =  971 (  "@@"    PGNSP PGUID l f f    0  604  600    0  0 poly_center - - ));
 
-DATA(insert OID = 1054 ( "="      PGNSP PGUID b t 1042 1042     16 1054 1057 1058 1058 1058 1060 bpchareq eqsel eqjoinsel ));
-DATA(insert OID = 1055 ( "~"      PGNSP PGUID b f 1042 25       16    0 1056  0 0 0 0 bpcharregexeq regexeqsel regexeqjoinsel ));
+DATA(insert OID = 1054 ( "="      PGNSP PGUID b t t 1042 1042   16 1054 1057 bpchareq eqsel eqjoinsel ));
+DATA(insert OID = 1055 ( "~"      PGNSP PGUID b f f 1042 25     16    0 1056 bpcharregexeq regexeqsel regexeqjoinsel ));
 #define OID_BPCHAR_REGEXEQ_OP          1055
-DATA(insert OID = 1056 ( "!~"     PGNSP PGUID b f 1042 25       16    0 1055  0 0 0 0 bpcharregexne regexnesel regexnejoinsel ));
-DATA(insert OID = 1057 ( "<>"     PGNSP PGUID b f 1042 1042     16 1057 1054  0 0 0 0 bpcharne neqsel neqjoinsel ));
-DATA(insert OID = 1058 ( "<"      PGNSP PGUID b f 1042 1042     16 1060 1061  0 0 0 0 bpcharlt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1059 ( "<="     PGNSP PGUID b f 1042 1042     16 1061 1060  0 0 0 0 bpcharle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1060 ( ">"      PGNSP PGUID b f 1042 1042     16 1058 1059  0 0 0 0 bpchargt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1061 ( ">="     PGNSP PGUID b f 1042 1042     16 1059 1058  0 0 0 0 bpcharge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1056 ( "!~"     PGNSP PGUID b f f 1042 25     16    0 1055 bpcharregexne regexnesel regexnejoinsel ));
+DATA(insert OID = 1057 ( "<>"     PGNSP PGUID b f f 1042 1042   16 1057 1054 bpcharne neqsel neqjoinsel ));
+DATA(insert OID = 1058 ( "<"      PGNSP PGUID b f f 1042 1042   16 1060 1061 bpcharlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1059 ( "<="     PGNSP PGUID b f f 1042 1042   16 1061 1060 bpcharle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1060 ( ">"      PGNSP PGUID b f f 1042 1042   16 1058 1059 bpchargt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1061 ( ">="     PGNSP PGUID b f f 1042 1042   16 1059 1058 bpcharge scalargtsel scalargtjoinsel ));
 
 /* generic array comparison operators */
-DATA(insert OID = 1070 (  "="     PGNSP PGUID b f 2277 2277 16 1070 1071  1072 1072 1072 1073 array_eq eqsel eqjoinsel ));
+DATA(insert OID = 1070 (  "="     PGNSP PGUID b t f 2277 2277 16 1070 1071 array_eq eqsel eqjoinsel ));
 #define ARRAY_EQ_OP 1070
-DATA(insert OID = 1071 (  "<>"    PGNSP PGUID b f 2277 2277 16 1071 1070  0 0 0 0 array_ne neqsel neqjoinsel ));
-DATA(insert OID = 1072 (  "<"     PGNSP PGUID b f 2277 2277 16 1073 1075  0 0 0 0 array_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1071 (  "<>"    PGNSP PGUID b f f 2277 2277 16 1071 1070 array_ne neqsel neqjoinsel ));
+DATA(insert OID = 1072 (  "<"     PGNSP PGUID b f f 2277 2277 16 1073 1075 array_lt scalarltsel scalarltjoinsel ));
 #define ARRAY_LT_OP 1072
-DATA(insert OID = 1073 (  ">"     PGNSP PGUID b f 2277 2277 16 1072 1074  0 0 0 0 array_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1073 (  ">"     PGNSP PGUID b f f 2277 2277 16 1072 1074 array_gt scalargtsel scalargtjoinsel ));
 #define ARRAY_GT_OP 1073
-DATA(insert OID = 1074 (  "<="    PGNSP PGUID b f 2277 2277 16 1075 1073  0 0 0 0 array_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1075 (  ">="    PGNSP PGUID b f 2277 2277 16 1074 1072  0 0 0 0 array_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1074 (  "<="    PGNSP PGUID b f f 2277 2277 16 1075 1073 array_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1075 (  ">="    PGNSP PGUID b f f 2277 2277 16 1074 1072 array_ge scalargtsel scalargtjoinsel ));
 
 /* date operators */
-DATA(insert OID = 1076 ( "+"      PGNSP PGUID b f      1082    1186 1114 2551 0 0 0 0 0 date_pl_interval - - ));
-DATA(insert OID = 1077 ( "-"      PGNSP PGUID b f      1082    1186 1114 0 0 0 0 0 0 date_mi_interval - - ));
-DATA(insert OID = 1093 ( "="      PGNSP PGUID b t      1082    1082   16 1093 1094 1095 1095 1095 1097 date_eq eqsel eqjoinsel ));
-DATA(insert OID = 1094 ( "<>"     PGNSP PGUID b f      1082    1082   16 1094 1093  0 0 0 0 date_ne neqsel neqjoinsel ));
-DATA(insert OID = 1095 ( "<"      PGNSP PGUID b f      1082    1082   16 1097 1098  0 0 0 0 date_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1096 ( "<="     PGNSP PGUID b f      1082    1082   16 1098 1097  0 0 0 0 date_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1097 ( ">"      PGNSP PGUID b f      1082    1082   16 1095 1096  0 0 0 0 date_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1098 ( ">="     PGNSP PGUID b f      1082    1082   16 1096 1095  0 0 0 0 date_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1099 ( "-"      PGNSP PGUID b f      1082    1082   23 0 0 0 0 0 0 date_mi - - ));
-DATA(insert OID = 1100 ( "+"      PGNSP PGUID b f      1082      23 1082 2555 0 0 0 0 0 date_pli - - ));
-DATA(insert OID = 1101 ( "-"      PGNSP PGUID b f      1082      23 1082 0 0 0 0 0 0 date_mii - - ));
+DATA(insert OID = 1076 ( "+"      PGNSP PGUID b f f    1082    1186 1114 2551 0 date_pl_interval - - ));
+DATA(insert OID = 1077 ( "-"      PGNSP PGUID b f f    1082    1186 1114 0 0 date_mi_interval - - ));
+DATA(insert OID = 1093 ( "="      PGNSP PGUID b t t    1082    1082   16 1093 1094 date_eq eqsel eqjoinsel ));
+DATA(insert OID = 1094 ( "<>"     PGNSP PGUID b f f    1082    1082   16 1094 1093 date_ne neqsel neqjoinsel ));
+DATA(insert OID = 1095 ( "<"      PGNSP PGUID b f f    1082    1082   16 1097 1098 date_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1096 ( "<="     PGNSP PGUID b f f    1082    1082   16 1098 1097 date_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1097 ( ">"      PGNSP PGUID b f f    1082    1082   16 1095 1096 date_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1098 ( ">="     PGNSP PGUID b f f    1082    1082   16 1096 1095 date_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1099 ( "-"      PGNSP PGUID b f f    1082    1082   23 0 0 date_mi - - ));
+DATA(insert OID = 1100 ( "+"      PGNSP PGUID b f f    1082      23 1082 2555 0 date_pli - - ));
+DATA(insert OID = 1101 ( "-"      PGNSP PGUID b f f    1082      23 1082 0 0 date_mii - - ));
 
 /* time operators */
-DATA(insert OID = 1108 ( "="      PGNSP PGUID b t      1083    1083  16 1108 1109 1110 1110 1110 1112 time_eq eqsel eqjoinsel ));
-DATA(insert OID = 1109 ( "<>"     PGNSP PGUID b f      1083    1083  16 1109 1108      0 0   0   0 time_ne neqsel neqjoinsel ));
-DATA(insert OID = 1110 ( "<"      PGNSP PGUID b f      1083    1083  16 1112 1113      0 0   0   0 time_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1111 ( "<="     PGNSP PGUID b f      1083    1083  16 1113 1112      0 0   0   0 time_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1112 ( ">"      PGNSP PGUID b f      1083    1083  16 1110 1111      0 0   0   0 time_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1113 ( ">="     PGNSP PGUID b f      1083    1083  16 1111 1110      0 0   0   0 time_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1108 ( "="      PGNSP PGUID b t t    1083    1083  16 1108 1109 time_eq eqsel eqjoinsel ));
+DATA(insert OID = 1109 ( "<>"     PGNSP PGUID b f f    1083    1083  16 1109 1108 time_ne neqsel neqjoinsel ));
+DATA(insert OID = 1110 ( "<"      PGNSP PGUID b f f    1083    1083  16 1112 1113 time_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1111 ( "<="     PGNSP PGUID b f f    1083    1083  16 1113 1112 time_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1112 ( ">"      PGNSP PGUID b f f    1083    1083  16 1110 1111 time_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1113 ( ">="     PGNSP PGUID b f f    1083    1083  16 1111 1110 time_ge scalargtsel scalargtjoinsel ));
 
 /* timetz operators */
-DATA(insert OID = 1550 ( "="      PGNSP PGUID b t      1266 1266       16 1550 1551 1552 1552 1552 1554 timetz_eq eqsel eqjoinsel ));
-DATA(insert OID = 1551 ( "<>"     PGNSP PGUID b f      1266 1266       16 1551 1550    0 0   0   0 timetz_ne neqsel neqjoinsel ));
-DATA(insert OID = 1552 ( "<"      PGNSP PGUID b f      1266 1266       16 1554 1555    0 0   0   0 timetz_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1553 ( "<="     PGNSP PGUID b f      1266 1266       16 1555 1554    0 0   0   0 timetz_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1554 ( ">"      PGNSP PGUID b f      1266 1266       16 1552 1553    0 0   0   0 timetz_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1555 ( ">="     PGNSP PGUID b f      1266 1266       16 1553 1552    0 0   0   0 timetz_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1550 ( "="      PGNSP PGUID b t t    1266 1266       16 1550 1551 timetz_eq eqsel eqjoinsel ));
+DATA(insert OID = 1551 ( "<>"     PGNSP PGUID b f f    1266 1266       16 1551 1550 timetz_ne neqsel neqjoinsel ));
+DATA(insert OID = 1552 ( "<"      PGNSP PGUID b f f    1266 1266       16 1554 1555 timetz_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1553 ( "<="     PGNSP PGUID b f f    1266 1266       16 1555 1554 timetz_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1554 ( ">"      PGNSP PGUID b f f    1266 1266       16 1552 1553 timetz_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1555 ( ">="     PGNSP PGUID b f f    1266 1266       16 1553 1552 timetz_ge scalargtsel scalargtjoinsel ));
 
 /* float48 operators */
-DATA(insert OID = 1116 (  "+"          PGNSP PGUID b f 700 701 701 1126         0       0       0       0       0 float48pl - - ));
-DATA(insert OID = 1117 (  "-"          PGNSP PGUID b f 700 701 701  0   0       0       0       0       0 float48mi - - ));
-DATA(insert OID = 1118 (  "/"          PGNSP PGUID b f 700 701 701  0   0       0       0       0       0 float48div - - ));
-DATA(insert OID = 1119 (  "*"          PGNSP PGUID b f 700 701 701 1129         0       0       0       0       0 float48mul - - ));
-DATA(insert OID = 1120 (  "="          PGNSP PGUID b f  700    701  16 1130 1121  622  672 1122 1123 float48eq eqsel eqjoinsel ));
-DATA(insert OID = 1121 (  "<>"         PGNSP PGUID b f  700    701  16 1131 1120  0 0 0 0 float48ne neqsel neqjoinsel ));
-DATA(insert OID = 1122 (  "<"          PGNSP PGUID b f  700    701  16 1133 1125  0 0 0 0 float48lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1123 (  ">"          PGNSP PGUID b f  700    701  16 1132 1124  0 0 0 0 float48gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1124 (  "<="         PGNSP PGUID b f  700    701  16 1135 1123  0 0 0 0 float48le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1125 (  ">="         PGNSP PGUID b f  700    701  16 1134 1122  0 0 0 0 float48ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1116 (  "+"          PGNSP PGUID b f f 700 701 701 1126       0 float48pl - - ));
+DATA(insert OID = 1117 (  "-"          PGNSP PGUID b f f 700 701 701  0         0 float48mi - - ));
+DATA(insert OID = 1118 (  "/"          PGNSP PGUID b f f 700 701 701  0         0 float48div - - ));
+DATA(insert OID = 1119 (  "*"          PGNSP PGUID b f f 700 701 701 1129       0 float48mul - - ));
+DATA(insert OID = 1120 (  "="          PGNSP PGUID b t f  700  701  16 1130 1121 float48eq eqsel eqjoinsel ));
+DATA(insert OID = 1121 (  "<>"         PGNSP PGUID b f f  700  701  16 1131 1120 float48ne neqsel neqjoinsel ));
+DATA(insert OID = 1122 (  "<"          PGNSP PGUID b f f  700  701  16 1133 1125 float48lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1123 (  ">"          PGNSP PGUID b f f  700  701  16 1132 1124 float48gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1124 (  "<="         PGNSP PGUID b f f  700  701  16 1135 1123 float48le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1125 (  ">="         PGNSP PGUID b f f  700  701  16 1134 1122 float48ge scalargtsel scalargtjoinsel ));
 
 /* float84 operators */
-DATA(insert OID = 1126 (  "+"          PGNSP PGUID b f 701 700 701 1116         0       0       0       0       0 float84pl - - ));
-DATA(insert OID = 1127 (  "-"          PGNSP PGUID b f 701 700 701  0   0       0       0       0       0 float84mi - - ));
-DATA(insert OID = 1128 (  "/"          PGNSP PGUID b f 701 700 701  0   0       0       0       0       0 float84div - - ));
-DATA(insert OID = 1129 (  "*"          PGNSP PGUID b f 701 700 701 1119         0       0       0       0       0 float84mul - - ));
-DATA(insert OID = 1130 (  "="          PGNSP PGUID b f  701    700  16 1120 1131  672 622 1132 1133 float84eq eqsel eqjoinsel ));
-DATA(insert OID = 1131 (  "<>"         PGNSP PGUID b f  701    700  16 1121 1130  0 0 0 0 float84ne neqsel neqjoinsel ));
-DATA(insert OID = 1132 (  "<"          PGNSP PGUID b f  701    700  16 1123 1135  0 0 0 0 float84lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1133 (  ">"          PGNSP PGUID b f  701    700  16 1122 1134  0 0 0 0 float84gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1134 (  "<="         PGNSP PGUID b f  701    700  16 1125 1133  0 0 0 0 float84le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1135 (  ">="         PGNSP PGUID b f  701    700  16 1124 1132  0 0 0 0 float84ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1126 (  "+"          PGNSP PGUID b f f 701 700 701 1116       0 float84pl - - ));
+DATA(insert OID = 1127 (  "-"          PGNSP PGUID b f f 701 700 701  0         0 float84mi - - ));
+DATA(insert OID = 1128 (  "/"          PGNSP PGUID b f f 701 700 701  0         0 float84div - - ));
+DATA(insert OID = 1129 (  "*"          PGNSP PGUID b f f 701 700 701 1119       0 float84mul - - ));
+DATA(insert OID = 1130 (  "="          PGNSP PGUID b t f  701  700  16 1120 1131 float84eq eqsel eqjoinsel ));
+DATA(insert OID = 1131 (  "<>"         PGNSP PGUID b f f  701  700  16 1121 1130 float84ne neqsel neqjoinsel ));
+DATA(insert OID = 1132 (  "<"          PGNSP PGUID b f f  701  700  16 1123 1135 float84lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1133 (  ">"          PGNSP PGUID b f f  701  700  16 1122 1134 float84gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1134 (  "<="         PGNSP PGUID b f f  701  700  16 1125 1133 float84le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1135 (  ">="         PGNSP PGUID b f f  701  700  16 1124 1132 float84ge scalargtsel scalargtjoinsel ));
 
 
 /* LIKE hacks by Keith Parks. */
-DATA(insert OID = 1207 (  "~~"   PGNSP PGUID b f  19   25      16 0 1208 0 0 0 0 namelike likesel likejoinsel ));
+DATA(insert OID = 1207 (  "~~"   PGNSP PGUID b f f  19 25      16 0 1208 namelike likesel likejoinsel ));
 #define OID_NAME_LIKE_OP               1207
-DATA(insert OID = 1208 (  "!~~"   PGNSP PGUID b f  19  25      16 0 1207 0 0 0 0 namenlike nlikesel nlikejoinsel ));
-DATA(insert OID = 1209 (  "~~"   PGNSP PGUID b f  25   25      16 0 1210 0 0 0 0 textlike likesel likejoinsel ));
+DATA(insert OID = 1208 (  "!~~"   PGNSP PGUID b f f  19        25      16 0 1207 namenlike nlikesel nlikejoinsel ));
+DATA(insert OID = 1209 (  "~~"   PGNSP PGUID b f f  25 25      16 0 1210 textlike likesel likejoinsel ));
 #define OID_TEXT_LIKE_OP               1209
-DATA(insert OID = 1210 (  "!~~"   PGNSP PGUID b f  25  25      16 0 1209 0 0 0 0 textnlike nlikesel nlikejoinsel ));
-DATA(insert OID = 1211 (  "~~"   PGNSP PGUID b f  1042 25      16 0 1212 0 0 0 0 bpcharlike likesel likejoinsel ));
+DATA(insert OID = 1210 (  "!~~"   PGNSP PGUID b f f  25        25      16 0 1209 textnlike nlikesel nlikejoinsel ));
+DATA(insert OID = 1211 (  "~~"   PGNSP PGUID b f f  1042 25    16 0 1212 bpcharlike likesel likejoinsel ));
 #define OID_BPCHAR_LIKE_OP             1211
-DATA(insert OID = 1212 (  "!~~"   PGNSP PGUID b f  1042 25     16 0 1211 0 0 0 0 bpcharnlike nlikesel nlikejoinsel ));
+DATA(insert OID = 1212 (  "!~~"   PGNSP PGUID b f f  1042 25   16 0 1211 bpcharnlike nlikesel nlikejoinsel ));
 
 /* case-insensitive regex hacks */
-DATA(insert OID = 1226 (  "~*"          PGNSP PGUID b f        19      25      16 0 1227  0 0 0 0 nameicregexeq icregexeqsel icregexeqjoinsel ));
+DATA(insert OID = 1226 (  "~*"          PGNSP PGUID b f f      19      25      16 0 1227 nameicregexeq icregexeqsel icregexeqjoinsel ));
 #define OID_NAME_ICREGEXEQ_OP          1226
-DATA(insert OID = 1227 (  "!~*"                 PGNSP PGUID b f        19      25      16 0 1226  0 0 0 0 nameicregexne icregexnesel icregexnejoinsel ));
-DATA(insert OID = 1228 (  "~*"          PGNSP PGUID b f        25      25      16 0 1229  0 0 0 0 texticregexeq icregexeqsel icregexeqjoinsel ));
+DATA(insert OID = 1227 (  "!~*"                 PGNSP PGUID b f f      19      25      16 0 1226 nameicregexne icregexnesel icregexnejoinsel ));
+DATA(insert OID = 1228 (  "~*"          PGNSP PGUID b f f      25      25      16 0 1229 texticregexeq icregexeqsel icregexeqjoinsel ));
 #define OID_TEXT_ICREGEXEQ_OP          1228
-DATA(insert OID = 1229 (  "!~*"                 PGNSP PGUID b f        25      25      16 0 1228  0 0 0 0 texticregexne icregexnesel icregexnejoinsel ));
-DATA(insert OID = 1234 (  "~*"         PGNSP PGUID b f  1042  25  16 0 1235    0 0   0   0 bpcharicregexeq icregexeqsel icregexeqjoinsel ));
+DATA(insert OID = 1229 (  "!~*"                 PGNSP PGUID b f f      25      25      16 0 1228 texticregexne icregexnesel icregexnejoinsel ));
+DATA(insert OID = 1234 (  "~*"         PGNSP PGUID b f f  1042  25  16 0 1235 bpcharicregexeq icregexeqsel icregexeqjoinsel ));
 #define OID_BPCHAR_ICREGEXEQ_OP                1234
-DATA(insert OID = 1235 ( "!~*"         PGNSP PGUID b f  1042  25  16 0 1234    0 0   0   0 bpcharicregexne icregexnesel icregexnejoinsel ));
+DATA(insert OID = 1235 ( "!~*"         PGNSP PGUID b f f  1042  25  16 0 1234 bpcharicregexne icregexnesel icregexnejoinsel ));
 
 /* timestamptz operators */
-DATA(insert OID = 1320 (  "="     PGNSP PGUID b t 1184 1184     16 1320 1321 1322 1322 1322 1324 timestamptz_eq eqsel eqjoinsel ));
-DATA(insert OID = 1321 (  "<>"    PGNSP PGUID b f 1184 1184     16 1321 1320 0 0 0 0 timestamptz_ne neqsel neqjoinsel ));
-DATA(insert OID = 1322 (  "<"     PGNSP PGUID b f 1184 1184     16 1324 1325 0 0 0 0 timestamptz_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1323 (  "<="    PGNSP PGUID b f 1184 1184     16 1325 1324 0 0 0 0 timestamptz_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1324 (  ">"     PGNSP PGUID b f 1184 1184     16 1322 1323 0 0 0 0 timestamptz_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1325 (  ">="    PGNSP PGUID b f 1184 1184     16 1323 1322 0 0 0 0 timestamptz_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1327 (  "+"     PGNSP PGUID b f 1184 1186 1184        2554 0 0 0 0 0 timestamptz_pl_interval - - ));
-DATA(insert OID = 1328 (  "-"     PGNSP PGUID b f 1184 1184 1186        0      0 0 0 0 0 timestamptz_mi - - ));
-DATA(insert OID = 1329 (  "-"     PGNSP PGUID b f 1184 1186 1184        0      0 0 0 0 0 timestamptz_mi_interval - - ));
+DATA(insert OID = 1320 (  "="     PGNSP PGUID b t t 1184 1184   16 1320 1321 timestamptz_eq eqsel eqjoinsel ));
+DATA(insert OID = 1321 (  "<>"    PGNSP PGUID b f f 1184 1184   16 1321 1320 timestamptz_ne neqsel neqjoinsel ));
+DATA(insert OID = 1322 (  "<"     PGNSP PGUID b f f 1184 1184   16 1324 1325 timestamptz_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1323 (  "<="    PGNSP PGUID b f f 1184 1184   16 1325 1324 timestamptz_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1324 (  ">"     PGNSP PGUID b f f 1184 1184   16 1322 1323 timestamptz_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1325 (  ">="    PGNSP PGUID b f f 1184 1184   16 1323 1322 timestamptz_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1327 (  "+"     PGNSP PGUID b f f 1184 1186 1184      2554 0 timestamptz_pl_interval - - ));
+DATA(insert OID = 1328 (  "-"     PGNSP PGUID b f f 1184 1184 1186      0      0 timestamptz_mi - - ));
+DATA(insert OID = 1329 (  "-"     PGNSP PGUID b f f 1184 1186 1184      0      0 timestamptz_mi_interval - - ));
 
 /* interval operators */
-DATA(insert OID = 1330 (  "="     PGNSP PGUID b t 1186 1186     16 1330 1331 1332 1332 1332 1334 interval_eq eqsel eqjoinsel ));
-DATA(insert OID = 1331 (  "<>"    PGNSP PGUID b f 1186 1186     16 1331 1330 0 0 0 0 interval_ne neqsel neqjoinsel ));
-DATA(insert OID = 1332 (  "<"     PGNSP PGUID b f 1186 1186     16 1334 1335 0 0 0 0 interval_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1333 (  "<="    PGNSP PGUID b f 1186 1186     16 1335 1334 0 0 0 0 interval_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1334 (  ">"     PGNSP PGUID b f 1186 1186     16 1332 1333 0 0 0 0 interval_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1335 (  ">="    PGNSP PGUID b f 1186 1186     16 1333 1332 0 0 0 0 interval_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1330 (  "="     PGNSP PGUID b t t 1186 1186   16 1330 1331 interval_eq eqsel eqjoinsel ));
+DATA(insert OID = 1331 (  "<>"    PGNSP PGUID b f f 1186 1186   16 1331 1330 interval_ne neqsel neqjoinsel ));
+DATA(insert OID = 1332 (  "<"     PGNSP PGUID b f f 1186 1186   16 1334 1335 interval_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1333 (  "<="    PGNSP PGUID b f f 1186 1186   16 1335 1334 interval_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1334 (  ">"     PGNSP PGUID b f f 1186 1186   16 1332 1333 interval_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1335 (  ">="    PGNSP PGUID b f f 1186 1186   16 1333 1332 interval_ge scalargtsel scalargtjoinsel ));
 
-DATA(insert OID = 1336 (  "-"     PGNSP PGUID l f      0 1186 1186    0        0 0 0 0 0 interval_um - - ));
-DATA(insert OID = 1337 (  "+"     PGNSP PGUID b f 1186 1186 1186 1337  0 0 0 0 0 interval_pl - - ));
-DATA(insert OID = 1338 (  "-"     PGNSP PGUID b f 1186 1186 1186        0      0 0 0 0 0 interval_mi - - ));
+DATA(insert OID = 1336 (  "-"     PGNSP PGUID l f f    0 1186 1186    0        0 interval_um - - ));
+DATA(insert OID = 1337 (  "+"     PGNSP PGUID b f f 1186 1186 1186 1337        0 interval_pl - - ));
+DATA(insert OID = 1338 (  "-"     PGNSP PGUID b f f 1186 1186 1186    0        0 interval_mi - - ));
 
-DATA(insert OID = 1360 (  "+"     PGNSP PGUID b f 1082 1083 1114       1363 0 0 0 0 0 datetime_pl - - ));
-DATA(insert OID = 1361 (  "+"     PGNSP PGUID b f 1082 1266 1184       1366 0 0 0 0 0 datetimetz_pl - - ));
-DATA(insert OID = 1363 (  "+"     PGNSP PGUID b f 1083 1082 1114       1360 0 0 0 0 0 timedate_pl - - ));
-DATA(insert OID = 1366 (  "+"     PGNSP PGUID b f 1266 1082 1184       1361 0 0 0 0 0 timetzdate_pl - - ));
+DATA(insert OID = 1360 (  "+"     PGNSP PGUID b f f 1082 1083 1114     1363 0 datetime_pl - - ));
+DATA(insert OID = 1361 (  "+"     PGNSP PGUID b f f 1082 1266 1184     1366 0 datetimetz_pl - - ));
+DATA(insert OID = 1363 (  "+"     PGNSP PGUID b f f 1083 1082 1114     1360 0 timedate_pl - - ));
+DATA(insert OID = 1366 (  "+"     PGNSP PGUID b f f 1266 1082 1184     1361 0 timetzdate_pl - - ));
 
-DATA(insert OID = 1399 (  "-"     PGNSP PGUID b f 1083 1083 1186        0      0 0 0 0 0 time_mi_time - - ));
+DATA(insert OID = 1399 (  "-"     PGNSP PGUID b f f 1083 1083 1186      0      0 time_mi_time - - ));
 
 /* additional geometric operators - thomas 97/04/18 */
-DATA(insert OID = 1420 (  "@@"   PGNSP PGUID l f        0      718 600   0    0        0        0       0       0 circle_center - - ));
-DATA(insert OID = 1500 (  "="    PGNSP PGUID b f  718  718 16 1500 1501 1502 1502 1502 1503 circle_eq eqsel eqjoinsel ));
-DATA(insert OID = 1501 (  "<>"   PGNSP PGUID b f  718  718 16 1501 1500        0        0       0       0 circle_ne neqsel neqjoinsel ));
-DATA(insert OID = 1502 (  "<"    PGNSP PGUID b f  718  718 16 1503 1505        0        0       0       0 circle_lt areasel areajoinsel ));
-DATA(insert OID = 1503 (  ">"    PGNSP PGUID b f  718  718 16 1502 1504        0        0       0       0 circle_gt areasel areajoinsel ));
-DATA(insert OID = 1504 (  "<="   PGNSP PGUID b f  718  718 16 1505 1503        0        0       0       0 circle_le areasel areajoinsel ));
-DATA(insert OID = 1505 (  ">="   PGNSP PGUID b f  718  718 16 1504 1502        0        0       0       0 circle_ge areasel areajoinsel ));
-
-DATA(insert OID = 1506 (  "<<"   PGNSP PGUID b f  718  718 16    0    0        0        0       0       0 circle_left positionsel positionjoinsel ));
-DATA(insert OID = 1507 (  "&<"   PGNSP PGUID b f  718  718 16    0    0        0        0       0       0 circle_overleft positionsel positionjoinsel ));
-DATA(insert OID = 1508 (  "&>"   PGNSP PGUID b f  718  718 16    0    0        0        0       0       0 circle_overright positionsel positionjoinsel ));
-DATA(insert OID = 1509 (  ">>"   PGNSP PGUID b f  718  718 16    0    0        0        0       0       0 circle_right positionsel positionjoinsel ));
-DATA(insert OID = 1510 (  "<@"   PGNSP PGUID b f  718  718 16 1511    0        0        0       0       0 circle_contained contsel contjoinsel ));
-DATA(insert OID = 1511 (  "@>"   PGNSP PGUID b f  718  718 16 1510    0        0        0       0       0 circle_contain contsel contjoinsel ));
-DATA(insert OID = 1512 (  "~="   PGNSP PGUID b f  718  718 16 1512    0        0        0       0       0 circle_same eqsel eqjoinsel ));
-DATA(insert OID = 1513 (  "&&"   PGNSP PGUID b f  718  718 16 1513    0        0        0       0       0 circle_overlap areasel areajoinsel ));
-DATA(insert OID = 1514 (  "|>>"   PGNSP PGUID b f  718 718 16    0    0        0        0       0       0 circle_above positionsel positionjoinsel ));
-DATA(insert OID = 1515 (  "<<|"   PGNSP PGUID b f  718 718 16    0    0        0        0       0       0 circle_below positionsel positionjoinsel ));
-
-DATA(insert OID = 1516 (  "+"    PGNSP PGUID b f  718  600  718          0    0        0        0       0       0 circle_add_pt - - ));
-DATA(insert OID = 1517 (  "-"    PGNSP PGUID b f  718  600  718          0    0        0        0       0       0 circle_sub_pt - - ));
-DATA(insert OID = 1518 (  "*"    PGNSP PGUID b f  718  600  718          0    0        0        0       0       0 circle_mul_pt - - ));
-DATA(insert OID = 1519 (  "/"    PGNSP PGUID b f  718  600  718          0    0        0        0       0       0 circle_div_pt - - ));
-
-DATA(insert OID = 1520 (  "<->"   PGNSP PGUID b f  718 718  701 1520    0      0        0       0       0 circle_distance - - ));
-DATA(insert OID = 1521 (  "#"    PGNSP PGUID l f        0      604 23    0    0        0        0       0       0 poly_npoints - - ));
-DATA(insert OID = 1522 (  "<->"   PGNSP PGUID b f  600 718  701          0    0        0        0       0       0 dist_pc - - ));
-DATA(insert OID = 1523 (  "<->"   PGNSP PGUID b f  718 604  701          0    0        0        0       0       0 dist_cpoly - - ));
+DATA(insert OID = 1420 (  "@@"   PGNSP PGUID l f f      0      718 600   0    0 circle_center - - ));
+DATA(insert OID = 1500 (  "="    PGNSP PGUID b f f  718        718 16 1500 1501 circle_eq eqsel eqjoinsel ));
+DATA(insert OID = 1501 (  "<>"   PGNSP PGUID b f f  718        718 16 1501 1500 circle_ne neqsel neqjoinsel ));
+DATA(insert OID = 1502 (  "<"    PGNSP PGUID b f f  718        718 16 1503 1505 circle_lt areasel areajoinsel ));
+DATA(insert OID = 1503 (  ">"    PGNSP PGUID b f f  718        718 16 1502 1504 circle_gt areasel areajoinsel ));
+DATA(insert OID = 1504 (  "<="   PGNSP PGUID b f f  718        718 16 1505 1503 circle_le areasel areajoinsel ));
+DATA(insert OID = 1505 (  ">="   PGNSP PGUID b f f  718        718 16 1504 1502 circle_ge areasel areajoinsel ));
+
+DATA(insert OID = 1506 (  "<<"   PGNSP PGUID b f f  718        718 16    0    0 circle_left positionsel positionjoinsel ));
+DATA(insert OID = 1507 (  "&<"   PGNSP PGUID b f f  718        718 16    0    0 circle_overleft positionsel positionjoinsel ));
+DATA(insert OID = 1508 (  "&>"   PGNSP PGUID b f f  718        718 16    0    0 circle_overright positionsel positionjoinsel ));
+DATA(insert OID = 1509 (  ">>"   PGNSP PGUID b f f  718        718 16    0    0 circle_right positionsel positionjoinsel ));
+DATA(insert OID = 1510 (  "<@"   PGNSP PGUID b f f  718        718 16 1511    0 circle_contained contsel contjoinsel ));
+DATA(insert OID = 1511 (  "@>"   PGNSP PGUID b f f  718        718 16 1510    0 circle_contain contsel contjoinsel ));
+DATA(insert OID = 1512 (  "~="   PGNSP PGUID b f f  718        718 16 1512    0 circle_same eqsel eqjoinsel ));
+DATA(insert OID = 1513 (  "&&"   PGNSP PGUID b f f  718        718 16 1513    0 circle_overlap areasel areajoinsel ));
+DATA(insert OID = 1514 (  "|>>"   PGNSP PGUID b f f  718       718 16    0    0 circle_above positionsel positionjoinsel ));
+DATA(insert OID = 1515 (  "<<|"   PGNSP PGUID b f f  718       718 16    0    0 circle_below positionsel positionjoinsel ));
+
+DATA(insert OID = 1516 (  "+"    PGNSP PGUID b f f  718        600  718          0    0 circle_add_pt - - ));
+DATA(insert OID = 1517 (  "-"    PGNSP PGUID b f f  718        600  718          0    0 circle_sub_pt - - ));
+DATA(insert OID = 1518 (  "*"    PGNSP PGUID b f f  718        600  718          0    0 circle_mul_pt - - ));
+DATA(insert OID = 1519 (  "/"    PGNSP PGUID b f f  718        600  718          0    0 circle_div_pt - - ));
+
+DATA(insert OID = 1520 (  "<->"   PGNSP PGUID b f f  718       718  701   1520    0 circle_distance - - ));
+DATA(insert OID = 1521 (  "#"    PGNSP PGUID l f f      0              604   23          0    0 poly_npoints - - ));
+DATA(insert OID = 1522 (  "<->"   PGNSP PGUID b f f  600       718  701          0    0 dist_pc - - ));
+DATA(insert OID = 1523 (  "<->"   PGNSP PGUID b f f  718       604  701          0    0 dist_cpoly - - ));
 
 /* additional geometric operators - thomas 1997-07-09 */
-DATA(insert OID = 1524 (  "<->"   PGNSP PGUID b f  628 603  701          0  0 0 0 0 0 dist_lb - - ));
-
-DATA(insert OID = 1525 (  "?#"   PGNSP PGUID b f  601  601 16 1525  0 0 0 0 0 lseg_intersect - - ));
-DATA(insert OID = 1526 (  "?||"   PGNSP PGUID b f  601 601 16 1526  0 0 0 0 0 lseg_parallel - - ));
-DATA(insert OID = 1527 (  "?-|"   PGNSP PGUID b f  601 601 16 1527  0 0 0 0 0 lseg_perp - - ));
-DATA(insert OID = 1528 (  "?-"   PGNSP PGUID l f        0      601 16    0  0 0 0 0 0 lseg_horizontal - - ));
-DATA(insert OID = 1529 (  "?|"   PGNSP PGUID l f        0      601 16    0  0 0 0 0 0 lseg_vertical - - ));
-DATA(insert OID = 1535 (  "="    PGNSP PGUID b f  601  601 16 1535 1586 0 0 0 0 lseg_eq eqsel eqjoinsel ));
-DATA(insert OID = 1536 (  "#"    PGNSP PGUID b f  601  601  600 1536  0 0 0 0 0 lseg_interpt - - ));
-DATA(insert OID = 1537 (  "?#"   PGNSP PGUID b f  601  628 16    0  0 0 0 0 0 inter_sl - - ));
-DATA(insert OID = 1538 (  "?#"   PGNSP PGUID b f  601  603 16    0  0 0 0 0 0 inter_sb - - ));
-DATA(insert OID = 1539 (  "?#"   PGNSP PGUID b f  628  603 16    0  0 0 0 0 0 inter_lb - - ));
-
-DATA(insert OID = 1546 (  "<@"   PGNSP PGUID b f  600  628 16    0  0 0 0 0 0 on_pl - - ));
-DATA(insert OID = 1547 (  "<@"   PGNSP PGUID b f  600  601 16    0  0 0 0 0 0 on_ps - - ));
-DATA(insert OID = 1548 (  "<@"   PGNSP PGUID b f  601  628 16    0  0 0 0 0 0 on_sl - - ));
-DATA(insert OID = 1549 (  "<@"   PGNSP PGUID b f  601  603 16    0  0 0 0 0 0 on_sb - - ));
-
-DATA(insert OID = 1557 (  "##"   PGNSP PGUID b f  600  628  600          0  0 0 0 0 0 close_pl - - ));
-DATA(insert OID = 1558 (  "##"   PGNSP PGUID b f  600  601  600          0  0 0 0 0 0 close_ps - - ));
-DATA(insert OID = 1559 (  "##"   PGNSP PGUID b f  600  603  600          0  0 0 0 0 0 close_pb - - ));
-
-DATA(insert OID = 1566 (  "##"   PGNSP PGUID b f  601  628  600          0  0 0 0 0 0 close_sl - - ));
-DATA(insert OID = 1567 (  "##"   PGNSP PGUID b f  601  603  600          0  0 0 0 0 0 close_sb - - ));
-DATA(insert OID = 1568 (  "##"   PGNSP PGUID b f  628  603  600          0  0 0 0 0 0 close_lb - - ));
-DATA(insert OID = 1577 (  "##"   PGNSP PGUID b f  628  601  600          0  0 0 0 0 0 close_ls - - ));
-DATA(insert OID = 1578 (  "##"   PGNSP PGUID b f  601  601  600          0  0 0 0 0 0 close_lseg - - ));
-DATA(insert OID = 1583 (  "*"    PGNSP PGUID b f 1186  701 1186        1584 0 0 0 0 0 interval_mul - - ));
-DATA(insert OID = 1584 (  "*"    PGNSP PGUID b f  701 1186 1186        1583 0 0 0 0 0 mul_d_interval - - ));
-DATA(insert OID = 1585 (  "/"    PGNSP PGUID b f 1186  701 1186          0  0 0 0 0 0 interval_div - - ));
-
-DATA(insert OID = 1586 (  "<>"   PGNSP PGUID b f  601  601 16 1586 1535 0 0 0 0 lseg_ne neqsel neqjoinsel ));
-DATA(insert OID = 1587 (  "<"    PGNSP PGUID b f  601  601 16 1589 1590 0 0 0 0 lseg_lt - - ));
-DATA(insert OID = 1588 (  "<="   PGNSP PGUID b f  601  601 16 1590 1589 0 0 0 0 lseg_le - - ));
-DATA(insert OID = 1589 (  ">"    PGNSP PGUID b f  601  601 16 1587 1588 0 0 0 0 lseg_gt - - ));
-DATA(insert OID = 1590 (  ">="   PGNSP PGUID b f  601  601 16 1588 1587 0 0 0 0 lseg_ge - - ));
-
-DATA(insert OID = 1591 (  "@-@"   PGNSP PGUID l f 0  601       701    0  0 0 0 0 0 lseg_length - - ));
-
-DATA(insert OID = 1611 (  "?#"   PGNSP PGUID b f  628  628 16 1611  0 0 0 0 0 line_intersect - - ));
-DATA(insert OID = 1612 (  "?||"   PGNSP PGUID b f  628 628 16 1612  0 0 0 0 0 line_parallel - - ));
-DATA(insert OID = 1613 (  "?-|"   PGNSP PGUID b f  628 628 16 1613  0 0 0 0 0 line_perp - - ));
-DATA(insert OID = 1614 (  "?-"   PGNSP PGUID l f        0      628 16    0  0 0 0 0 0 line_horizontal - - ));
-DATA(insert OID = 1615 (  "?|"   PGNSP PGUID l f        0      628 16    0  0 0 0 0 0 line_vertical - - ));
-DATA(insert OID = 1616 (  "="    PGNSP PGUID b f  628  628 16 1616  0 0 0 0 0 line_eq eqsel eqjoinsel ));
-DATA(insert OID = 1617 (  "#"    PGNSP PGUID b f  628  628  600 1617  0 0 0 0 0 line_interpt - - ));
+DATA(insert OID = 1524 (  "<->"   PGNSP PGUID b f f  628       603  701          0  0 dist_lb - - ));
+
+DATA(insert OID = 1525 (  "?#"   PGNSP PGUID b f f  601        601 16 1525  0 lseg_intersect - - ));
+DATA(insert OID = 1526 (  "?||"   PGNSP PGUID b f f  601       601 16 1526  0 lseg_parallel - - ));
+DATA(insert OID = 1527 (  "?-|"   PGNSP PGUID b f f  601       601 16 1527  0 lseg_perp - - ));
+DATA(insert OID = 1528 (  "?-"   PGNSP PGUID l f f      0      601 16    0  0 lseg_horizontal - - ));
+DATA(insert OID = 1529 (  "?|"   PGNSP PGUID l f f      0      601 16    0  0 lseg_vertical - - ));
+DATA(insert OID = 1535 (  "="    PGNSP PGUID b f f  601        601 16 1535 1586 lseg_eq eqsel eqjoinsel ));
+DATA(insert OID = 1536 (  "#"    PGNSP PGUID b f f  601        601  600 1536  0 lseg_interpt - - ));
+DATA(insert OID = 1537 (  "?#"   PGNSP PGUID b f f  601        628 16    0  0 inter_sl - - ));
+DATA(insert OID = 1538 (  "?#"   PGNSP PGUID b f f  601        603 16    0  0 inter_sb - - ));
+DATA(insert OID = 1539 (  "?#"   PGNSP PGUID b f f  628        603 16    0  0 inter_lb - - ));
+
+DATA(insert OID = 1546 (  "<@"   PGNSP PGUID b f f  600        628 16    0  0 on_pl - - ));
+DATA(insert OID = 1547 (  "<@"   PGNSP PGUID b f f  600        601 16    0  0 on_ps - - ));
+DATA(insert OID = 1548 (  "<@"   PGNSP PGUID b f f  601        628 16    0  0 on_sl - - ));
+DATA(insert OID = 1549 (  "<@"   PGNSP PGUID b f f  601        603 16    0  0 on_sb - - ));
+
+DATA(insert OID = 1557 (  "##"   PGNSP PGUID b f f  600        628  600          0  0 close_pl - - ));
+DATA(insert OID = 1558 (  "##"   PGNSP PGUID b f f  600        601  600          0  0 close_ps - - ));
+DATA(insert OID = 1559 (  "##"   PGNSP PGUID b f f  600        603  600          0  0 close_pb - - ));
+
+DATA(insert OID = 1566 (  "##"   PGNSP PGUID b f f  601        628  600          0  0 close_sl - - ));
+DATA(insert OID = 1567 (  "##"   PGNSP PGUID b f f  601        603  600          0  0 close_sb - - ));
+DATA(insert OID = 1568 (  "##"   PGNSP PGUID b f f  628        603  600          0  0 close_lb - - ));
+DATA(insert OID = 1577 (  "##"   PGNSP PGUID b f f  628        601  600          0  0 close_ls - - ));
+DATA(insert OID = 1578 (  "##"   PGNSP PGUID b f f  601        601  600          0  0 close_lseg - - ));
+DATA(insert OID = 1583 (  "*"    PGNSP PGUID b f f 1186        701 1186        1584 0 interval_mul - - ));
+DATA(insert OID = 1584 (  "*"    PGNSP PGUID b f f  701 1186 1186      1583 0 mul_d_interval - - ));
+DATA(insert OID = 1585 (  "/"    PGNSP PGUID b f f 1186        701 1186          0  0 interval_div - - ));
+
+DATA(insert OID = 1586 (  "<>"   PGNSP PGUID b f f  601        601 16 1586 1535 lseg_ne neqsel neqjoinsel ));
+DATA(insert OID = 1587 (  "<"    PGNSP PGUID b f f  601        601 16 1589 1590 lseg_lt - - ));
+DATA(insert OID = 1588 (  "<="   PGNSP PGUID b f f  601        601 16 1590 1589 lseg_le - - ));
+DATA(insert OID = 1589 (  ">"    PGNSP PGUID b f f  601        601 16 1587 1588 lseg_gt - - ));
+DATA(insert OID = 1590 (  ">="   PGNSP PGUID b f f  601        601 16 1588 1587 lseg_ge - - ));
+
+DATA(insert OID = 1591 (  "@-@"   PGNSP PGUID l f f 0  601     701    0  0 lseg_length - - ));
+
+DATA(insert OID = 1611 (  "?#"   PGNSP PGUID b f f  628        628 16 1611  0 line_intersect - - ));
+DATA(insert OID = 1612 (  "?||"   PGNSP PGUID b f f  628       628 16 1612  0 line_parallel - - ));
+DATA(insert OID = 1613 (  "?-|"   PGNSP PGUID b f f  628       628 16 1613  0 line_perp - - ));
+DATA(insert OID = 1614 (  "?-"   PGNSP PGUID l f f      0      628 16    0  0 line_horizontal - - ));
+DATA(insert OID = 1615 (  "?|"   PGNSP PGUID l f f      0      628 16    0  0 line_vertical - - ));
+DATA(insert OID = 1616 (  "="    PGNSP PGUID b f f  628        628 16 1616  0 line_eq eqsel eqjoinsel ));
+DATA(insert OID = 1617 (  "#"    PGNSP PGUID b f f  628        628  600 1617  0 line_interpt - - ));
 
 /* MAC type */
-DATA(insert OID = 1220 (  "="     PGNSP PGUID b t 829 829       16 1220 1221 1222 1222 1222 1224 macaddr_eq eqsel eqjoinsel ));
-DATA(insert OID = 1221 (  "<>"    PGNSP PGUID b f 829 829       16 1221 1220    0        0   0   0 macaddr_ne neqsel neqjoinsel ));
-DATA(insert OID = 1222 (  "<"     PGNSP PGUID b f 829 829       16 1224 1225    0        0   0   0 macaddr_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1223 (  "<="    PGNSP PGUID b f 829 829       16 1225 1224    0        0   0   0 macaddr_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1224 (  ">"     PGNSP PGUID b f 829 829       16 1222 1223    0        0   0   0 macaddr_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1225 (  ">="    PGNSP PGUID b f 829 829       16 1223 1222    0        0   0   0 macaddr_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1220 (  "="     PGNSP PGUID b t t 829 829     16 1220 1221 macaddr_eq eqsel eqjoinsel ));
+DATA(insert OID = 1221 (  "<>"    PGNSP PGUID b f f 829 829     16 1221 1220 macaddr_ne neqsel neqjoinsel ));
+DATA(insert OID = 1222 (  "<"     PGNSP PGUID b f f 829 829     16 1224 1225 macaddr_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1223 (  "<="    PGNSP PGUID b f f 829 829     16 1225 1224 macaddr_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1224 (  ">"     PGNSP PGUID b f f 829 829     16 1222 1223 macaddr_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1225 (  ">="    PGNSP PGUID b f f 829 829     16 1223 1222 macaddr_ge scalargtsel scalargtjoinsel ));
 
 /* INET type (these also support CIDR via implicit cast) */
-DATA(insert OID = 1201 (  "="     PGNSP PGUID b t 869 869       16 1201 1202 1203 1203 1203 1205 network_eq eqsel eqjoinsel ));
-DATA(insert OID = 1202 (  "<>"    PGNSP PGUID b f 869 869       16 1202 1201    0        0   0   0 network_ne neqsel neqjoinsel ));
-DATA(insert OID = 1203 (  "<"     PGNSP PGUID b f 869 869       16 1205 1206    0        0   0   0 network_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1204 (  "<="    PGNSP PGUID b f 869 869       16 1206 1205    0        0   0   0 network_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1205 (  ">"     PGNSP PGUID b f 869 869       16 1203 1204    0        0   0   0 network_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1206 (  ">="    PGNSP PGUID b f 869 869       16 1204 1203    0        0   0   0 network_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 931  (  "<<"    PGNSP PGUID b f 869 869       16 933         0        0        0   0   0 network_sub - - ));
+DATA(insert OID = 1201 (  "="     PGNSP PGUID b t t 869 869     16 1201 1202 network_eq eqsel eqjoinsel ));
+DATA(insert OID = 1202 (  "<>"    PGNSP PGUID b f f 869 869     16 1202 1201 network_ne neqsel neqjoinsel ));
+DATA(insert OID = 1203 (  "<"     PGNSP PGUID b f f 869 869     16 1205 1206 network_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1204 (  "<="    PGNSP PGUID b f f 869 869     16 1206 1205 network_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1205 (  ">"     PGNSP PGUID b f f 869 869     16 1203 1204 network_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1206 (  ">="    PGNSP PGUID b f f 869 869     16 1204 1203 network_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 931  (  "<<"    PGNSP PGUID b f f 869 869     16 933         0 network_sub - - ));
 #define OID_INET_SUB_OP                                  931
-DATA(insert OID = 932  (  "<<="    PGNSP PGUID b f 869 869      16 934         0        0        0   0   0 network_subeq - - ));
+DATA(insert OID = 932  (  "<<="    PGNSP PGUID b f f 869 869    16 934         0 network_subeq - - ));
 #define OID_INET_SUBEQ_OP                              932
-DATA(insert OID = 933  (  ">>"    PGNSP PGUID b f 869 869       16 931         0        0        0   0   0 network_sup - - ));
+DATA(insert OID = 933  (  ">>"    PGNSP PGUID b f f 869 869     16 931         0 network_sup - - ));
 #define OID_INET_SUP_OP                                  933
-DATA(insert OID = 934  (  ">>="    PGNSP PGUID b f 869 869      16 932         0        0        0   0   0 network_supeq - - ));
+DATA(insert OID = 934  (  ">>="    PGNSP PGUID b f f 869 869    16 932         0 network_supeq - - ));
 #define OID_INET_SUPEQ_OP                              934
 
-DATA(insert OID = 2634 (  "~"     PGNSP PGUID l f      0 869 869 0 0 0 0 0 0 inetnot - - ));
-DATA(insert OID = 2635 (  "&"     PGNSP PGUID b f      869 869 869 0 0 0 0 0 0 inetand - - ));
-DATA(insert OID = 2636 (  "|"     PGNSP PGUID b f      869 869 869 0 0 0 0 0 0 inetor - - ));
-DATA(insert OID = 2637 (  "+"     PGNSP PGUID b f      869 20 869 2638 0 0 0 0 0 inetpl - - ));
-DATA(insert OID = 2638 (  "+"     PGNSP PGUID b f      20 869 869 2637 0 0 0 0 0 int8pl_inet - - ));
-DATA(insert OID = 2639 (  "-"     PGNSP PGUID b f      869 20 869 0 0 0 0 0 0 inetmi_int8 - - ));
-DATA(insert OID = 2640 (  "-"     PGNSP PGUID b f      869 869 20 0 0 0 0 0 0 inetmi - - ));
+DATA(insert OID = 2634 (  "~"     PGNSP PGUID l f f      0 869 869 0 0 inetnot - - ));
+DATA(insert OID = 2635 (  "&"     PGNSP PGUID b f f    869 869 869 0 0 inetand - - ));
+DATA(insert OID = 2636 (  "|"     PGNSP PGUID b f f    869 869 869 0 0 inetor - - ));
+DATA(insert OID = 2637 (  "+"     PGNSP PGUID b f f    869  20 869 2638 0 inetpl - - ));
+DATA(insert OID = 2638 (  "+"     PGNSP PGUID b f f     20 869 869 2637 0 int8pl_inet - - ));
+DATA(insert OID = 2639 (  "-"     PGNSP PGUID b f f    869  20 869 0 0 inetmi_int8 - - ));
+DATA(insert OID = 2640 (  "-"     PGNSP PGUID b f f    869 869  20 0 0 inetmi - - ));
 
 
 /* case-insensitive LIKE hacks */
-DATA(insert OID = 1625 (  "~~*"   PGNSP PGUID b f  19  25      16 0 1626 0 0 0 0 nameiclike iclikesel iclikejoinsel ));
+DATA(insert OID = 1625 (  "~~*"   PGNSP PGUID b f f  19        25      16 0 1626 nameiclike iclikesel iclikejoinsel ));
 #define OID_NAME_ICLIKE_OP             1625
-DATA(insert OID = 1626 (  "!~~*"  PGNSP PGUID b f  19  25      16 0 1625 0 0 0 0 nameicnlike icnlikesel icnlikejoinsel ));
-DATA(insert OID = 1627 (  "~~*"   PGNSP PGUID b f  25  25      16 0 1628 0 0 0 0 texticlike iclikesel iclikejoinsel ));
+DATA(insert OID = 1626 (  "!~~*"  PGNSP PGUID b f f  19        25      16 0 1625 nameicnlike icnlikesel icnlikejoinsel ));
+DATA(insert OID = 1627 (  "~~*"   PGNSP PGUID b f f  25        25      16 0 1628 texticlike iclikesel iclikejoinsel ));
 #define OID_TEXT_ICLIKE_OP             1627
-DATA(insert OID = 1628 (  "!~~*"  PGNSP PGUID b f  25  25      16 0 1627 0 0 0 0 texticnlike icnlikesel icnlikejoinsel ));
-DATA(insert OID = 1629 (  "~~*"   PGNSP PGUID b f  1042 25     16 0 1630 0 0 0 0 bpchariclike iclikesel iclikejoinsel ));
+DATA(insert OID = 1628 (  "!~~*"  PGNSP PGUID b f f  25        25      16 0 1627 texticnlike icnlikesel icnlikejoinsel ));
+DATA(insert OID = 1629 (  "~~*"   PGNSP PGUID b f f  1042 25   16 0 1630 bpchariclike iclikesel iclikejoinsel ));
 #define OID_BPCHAR_ICLIKE_OP   1629
-DATA(insert OID = 1630 (  "!~~*"  PGNSP PGUID b f  1042 25     16 0 1629 0 0 0 0 bpcharicnlike icnlikesel icnlikejoinsel ));
+DATA(insert OID = 1630 (  "!~~*"  PGNSP PGUID b f f  1042 25   16 0 1629 bpcharicnlike icnlikesel icnlikejoinsel ));
 
 /* NUMERIC type - OID's 1700-1799 */
-DATA(insert OID = 1751 (  "-"     PGNSP PGUID l f      0 1700 1700    0        0 0 0 0 0 numeric_uminus - - ));
-DATA(insert OID = 1752 (  "="     PGNSP PGUID b f 1700 1700     16 1752 1753 1754 1754 1754 1756 numeric_eq eqsel eqjoinsel ));
-DATA(insert OID = 1753 (  "<>"    PGNSP PGUID b f 1700 1700     16 1753 1752 0 0 0 0 numeric_ne neqsel neqjoinsel ));
-DATA(insert OID = 1754 (  "<"     PGNSP PGUID b f 1700 1700     16 1756 1757 0 0 0 0 numeric_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1755 (  "<="    PGNSP PGUID b f 1700 1700     16 1757 1756 0 0 0 0 numeric_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1756 (  ">"     PGNSP PGUID b f 1700 1700     16 1754 1755 0 0 0 0 numeric_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1757 (  ">="    PGNSP PGUID b f 1700 1700     16 1755 1754 0 0 0 0 numeric_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1758 (  "+"     PGNSP PGUID b f 1700 1700 1700 1758  0 0 0 0 0 numeric_add - - ));
-DATA(insert OID = 1759 (  "-"     PGNSP PGUID b f 1700 1700 1700        0      0 0 0 0 0 numeric_sub - - ));
-DATA(insert OID = 1760 (  "*"     PGNSP PGUID b f 1700 1700 1700 1760  0 0 0 0 0 numeric_mul - - ));
-DATA(insert OID = 1761 (  "/"     PGNSP PGUID b f 1700 1700 1700        0      0 0 0 0 0 numeric_div - - ));
-DATA(insert OID = 1762 (  "%"     PGNSP PGUID b f 1700 1700 1700        0      0 0 0 0 0 numeric_mod - - ));
-DATA(insert OID = 1038 (  "^"     PGNSP PGUID b f 1700 1700 1700        0      0 0 0 0 0 numeric_power - - ));
-DATA(insert OID = 1763 (  "@"     PGNSP PGUID l f      0 1700 1700    0        0 0 0 0 0 numeric_abs - - ));
-
-DATA(insert OID = 1784 (  "="    PGNSP PGUID b f 1560 1560 16 1784 1785 1786 1786 1786 1787 biteq eqsel eqjoinsel ));
-DATA(insert OID = 1785 (  "<>"   PGNSP PGUID b f 1560 1560 16 1785 1784        0        0       0       0 bitne neqsel neqjoinsel ));
-DATA(insert OID = 1786 (  "<"    PGNSP PGUID b f 1560 1560 16 1787 1789        0        0       0       0 bitlt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1787 (  ">"    PGNSP PGUID b f 1560 1560 16 1786 1788        0        0       0       0 bitgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1788 (  "<="   PGNSP PGUID b f 1560 1560 16 1789 1787        0        0       0       0 bitle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1789 (  ">="   PGNSP PGUID b f 1560 1560 16 1788 1786        0        0       0       0 bitge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1791 (  "&"    PGNSP PGUID b f 1560 1560 1560 1791    0      0        0       0       0 bitand - - ));
-DATA(insert OID = 1792 (  "|"    PGNSP PGUID b f 1560 1560 1560 1792    0      0        0       0       0 bitor - - ));
-DATA(insert OID = 1793 (  "#"    PGNSP PGUID b f 1560 1560 1560 1793    0      0        0       0       0 bitxor - - ));
-DATA(insert OID = 1794 (  "~"    PGNSP PGUID l f        0 1560 1560      0    0        0        0       0       0 bitnot - - ));
-DATA(insert OID = 1795 (  "<<"   PGNSP PGUID b f 1560   23 1560          0    0        0        0       0       0 bitshiftleft - - ));
-DATA(insert OID = 1796 (  ">>"   PGNSP PGUID b f 1560   23 1560          0    0        0        0       0       0 bitshiftright - - ));
-DATA(insert OID = 1797 (  "||"   PGNSP PGUID b f 1560 1560 1560          0    0        0        0       0       0 bitcat - - ));
-
-DATA(insert OID = 1800 (  "+"     PGNSP PGUID b f 1083 1186 1083        1849 0 0 0 0 0 time_pl_interval - - ));
-DATA(insert OID = 1801 (  "-"     PGNSP PGUID b f 1083 1186 1083        0      0 0 0 0 0 time_mi_interval - - ));
-DATA(insert OID = 1802 (  "+"     PGNSP PGUID b f 1266 1186 1266        2552 0 0 0 0 0 timetz_pl_interval - - ));
-DATA(insert OID = 1803 (  "-"     PGNSP PGUID b f 1266 1186 1266        0      0 0 0 0 0 timetz_mi_interval - - ));
-
-DATA(insert OID = 1804 (  "="    PGNSP PGUID b f 1562 1562 16 1804 1805 1806 1806 1806 1807 varbiteq eqsel eqjoinsel ));
-DATA(insert OID = 1805 (  "<>"   PGNSP PGUID b f 1562 1562 16 1805 1804        0        0       0       0 varbitne neqsel neqjoinsel ));
-DATA(insert OID = 1806 (  "<"    PGNSP PGUID b f 1562 1562 16 1807 1809        0        0       0       0 varbitlt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1807 (  ">"    PGNSP PGUID b f 1562 1562 16 1806 1808        0        0       0       0 varbitgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1808 (  "<="   PGNSP PGUID b f 1562 1562 16 1809 1807        0        0       0       0 varbitle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1809 (  ">="   PGNSP PGUID b f 1562 1562 16 1808 1806        0        0       0       0 varbitge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 1849 (  "+"     PGNSP PGUID b f 1186 1083 1083        1800 0 0 0 0 0 interval_pl_time - - ));
-
-DATA(insert OID = 1862 ( "="      PGNSP PGUID b f      21      20      16 1868  1863  95 412 1864 1865 int28eq eqsel eqjoinsel ));
-DATA(insert OID = 1863 ( "<>"     PGNSP PGUID b f      21      20      16 1869  1862   0       0       0       0 int28ne neqsel neqjoinsel ));
-DATA(insert OID = 1864 ( "<"      PGNSP PGUID b f      21      20      16 1871  1867   0       0       0       0 int28lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1865 ( ">"      PGNSP PGUID b f      21      20      16 1870  1866   0       0       0       0 int28gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1866 ( "<="     PGNSP PGUID b f      21      20      16 1873  1865   0       0       0       0 int28le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1867 ( ">="     PGNSP PGUID b f      21      20      16 1872  1864   0       0       0       0 int28ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 1868 ( "="      PGNSP PGUID b f      20      21      16      1862 1869 412 95 1870 1871 int82eq eqsel eqjoinsel ));
-DATA(insert OID = 1869 ( "<>"     PGNSP PGUID b f      20      21      16      1863 1868       0  0   0   0 int82ne neqsel neqjoinsel ));
-DATA(insert OID = 1870 ( "<"      PGNSP PGUID b f      20      21      16      1865 1873       0  0   0   0 int82lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1871 ( ">"      PGNSP PGUID b f      20      21      16      1864 1872       0  0   0   0 int82gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1872 ( "<="     PGNSP PGUID b f      20      21      16      1867 1871       0  0   0   0 int82le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1873 ( ">="     PGNSP PGUID b f      20      21      16      1866 1870       0  0   0   0 int82ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 1874 ( "&"      PGNSP PGUID b f      21      21      21      1874      0   0  0       0       0 int2and - - ));
-DATA(insert OID = 1875 ( "|"      PGNSP PGUID b f      21      21      21      1875      0   0  0       0       0 int2or - - ));
-DATA(insert OID = 1876 ( "#"      PGNSP PGUID b f      21      21      21      1876      0   0  0       0       0 int2xor - - ));
-DATA(insert OID = 1877 ( "~"      PGNSP PGUID l f       0      21      21       0        0   0  0       0       0 int2not - - ));
-DATA(insert OID = 1878 ( "<<"     PGNSP PGUID b f      21      23      21       0        0   0  0       0       0 int2shl - - ));
-DATA(insert OID = 1879 ( ">>"     PGNSP PGUID b f      21      23      21       0        0   0  0       0       0 int2shr - - ));
-
-DATA(insert OID = 1880 ( "&"      PGNSP PGUID b f      23      23      23      1880      0   0  0       0       0 int4and - - ));
-DATA(insert OID = 1881 ( "|"      PGNSP PGUID b f      23      23      23      1881      0   0  0       0       0 int4or - - ));
-DATA(insert OID = 1882 ( "#"      PGNSP PGUID b f      23      23      23      1882      0   0  0       0       0 int4xor - - ));
-DATA(insert OID = 1883 ( "~"      PGNSP PGUID l f       0      23      23       0        0   0  0       0       0 int4not - - ));
-DATA(insert OID = 1884 ( "<<"     PGNSP PGUID b f      23      23      23       0        0   0  0       0       0 int4shl - - ));
-DATA(insert OID = 1885 ( ">>"     PGNSP PGUID b f      23      23      23       0        0   0  0       0       0 int4shr - - ));
-
-DATA(insert OID = 1886 ( "&"      PGNSP PGUID b f      20      20      20      1886      0   0  0       0       0 int8and - - ));
-DATA(insert OID = 1887 ( "|"      PGNSP PGUID b f      20      20      20      1887      0   0  0       0       0 int8or - - ));
-DATA(insert OID = 1888 ( "#"      PGNSP PGUID b f      20      20      20      1888      0   0  0       0       0 int8xor - - ));
-DATA(insert OID = 1889 ( "~"      PGNSP PGUID l f       0      20      20       0        0   0  0       0       0 int8not - - ));
-DATA(insert OID = 1890 ( "<<"     PGNSP PGUID b f      20      23      20       0        0   0  0       0       0 int8shl - - ));
-DATA(insert OID = 1891 ( ">>"     PGNSP PGUID b f      20      23      20       0        0   0  0       0       0 int8shr - - ));
-
-DATA(insert OID = 1916 (  "+"     PGNSP PGUID l f       0      20      20      0       0       0       0       0       0 int8up - - ));
-DATA(insert OID = 1917 (  "+"     PGNSP PGUID l f       0      21      21      0       0       0       0       0       0 int2up - - ));
-DATA(insert OID = 1918 (  "+"     PGNSP PGUID l f       0      23      23      0       0       0       0       0       0 int4up - - ));
-DATA(insert OID = 1919 (  "+"     PGNSP PGUID l f       0      700 700 0       0       0       0       0       0 float4up - - ));
-DATA(insert OID = 1920 (  "+"     PGNSP PGUID l f       0      701 701 0       0       0       0       0       0 float8up - - ));
-DATA(insert OID = 1921 (  "+"     PGNSP PGUID l f       0 1700 1700    0       0       0       0       0       0 numeric_uplus - - ));
+DATA(insert OID = 1751 (  "-"     PGNSP PGUID l f f    0 1700 1700    0        0 numeric_uminus - - ));
+DATA(insert OID = 1752 (  "="     PGNSP PGUID b t f 1700 1700   16 1752 1753 numeric_eq eqsel eqjoinsel ));
+DATA(insert OID = 1753 (  "<>"    PGNSP PGUID b f f 1700 1700   16 1753 1752 numeric_ne neqsel neqjoinsel ));
+DATA(insert OID = 1754 (  "<"     PGNSP PGUID b f f 1700 1700   16 1756 1757 numeric_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1755 (  "<="    PGNSP PGUID b f f 1700 1700   16 1757 1756 numeric_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1756 (  ">"     PGNSP PGUID b f f 1700 1700   16 1754 1755 numeric_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1757 (  ">="    PGNSP PGUID b f f 1700 1700   16 1755 1754 numeric_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1758 (  "+"     PGNSP PGUID b f f 1700 1700 1700 1758        0 numeric_add - - ));
+DATA(insert OID = 1759 (  "-"     PGNSP PGUID b f f 1700 1700 1700    0        0 numeric_sub - - ));
+DATA(insert OID = 1760 (  "*"     PGNSP PGUID b f f 1700 1700 1700 1760        0 numeric_mul - - ));
+DATA(insert OID = 1761 (  "/"     PGNSP PGUID b f f 1700 1700 1700    0        0 numeric_div - - ));
+DATA(insert OID = 1762 (  "%"     PGNSP PGUID b f f 1700 1700 1700    0        0 numeric_mod - - ));
+DATA(insert OID = 1038 (  "^"     PGNSP PGUID b f f 1700 1700 1700    0        0 numeric_power - - ));
+DATA(insert OID = 1763 (  "@"     PGNSP PGUID l f f    0 1700 1700    0        0 numeric_abs - - ));
+
+DATA(insert OID = 1784 (  "="    PGNSP PGUID b t f 1560 1560 16 1784 1785 biteq eqsel eqjoinsel ));
+DATA(insert OID = 1785 (  "<>"   PGNSP PGUID b f f 1560 1560 16 1785 1784 bitne neqsel neqjoinsel ));
+DATA(insert OID = 1786 (  "<"    PGNSP PGUID b f f 1560 1560 16 1787 1789 bitlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1787 (  ">"    PGNSP PGUID b f f 1560 1560 16 1786 1788 bitgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1788 (  "<="   PGNSP PGUID b f f 1560 1560 16 1789 1787 bitle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1789 (  ">="   PGNSP PGUID b f f 1560 1560 16 1788 1786 bitge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1791 (  "&"    PGNSP PGUID b f f 1560 1560 1560 1791  0 bitand - - ));
+DATA(insert OID = 1792 (  "|"    PGNSP PGUID b f f 1560 1560 1560 1792  0 bitor - - ));
+DATA(insert OID = 1793 (  "#"    PGNSP PGUID b f f 1560 1560 1560 1793  0 bitxor - - ));
+DATA(insert OID = 1794 (  "~"    PGNSP PGUID l f f    0 1560 1560        0  0 bitnot - - ));
+DATA(insert OID = 1795 (  "<<"   PGNSP PGUID b f f 1560   23 1560        0  0 bitshiftleft - - ));
+DATA(insert OID = 1796 (  ">>"   PGNSP PGUID b f f 1560   23 1560        0  0 bitshiftright - - ));
+DATA(insert OID = 1797 (  "||"   PGNSP PGUID b f f 1560 1560 1560        0  0 bitcat - - ));
+
+DATA(insert OID = 1800 (  "+"     PGNSP PGUID b f f 1083 1186 1083      1849 0 time_pl_interval - - ));
+DATA(insert OID = 1801 (  "-"     PGNSP PGUID b f f 1083 1186 1083      0      0 time_mi_interval - - ));
+DATA(insert OID = 1802 (  "+"     PGNSP PGUID b f f 1266 1186 1266      2552 0 timetz_pl_interval - - ));
+DATA(insert OID = 1803 (  "-"     PGNSP PGUID b f f 1266 1186 1266      0      0 timetz_mi_interval - - ));
+
+DATA(insert OID = 1804 (  "="    PGNSP PGUID b t f 1562 1562 16 1804 1805 varbiteq eqsel eqjoinsel ));
+DATA(insert OID = 1805 (  "<>"   PGNSP PGUID b f f 1562 1562 16 1805 1804 varbitne neqsel neqjoinsel ));
+DATA(insert OID = 1806 (  "<"    PGNSP PGUID b f f 1562 1562 16 1807 1809 varbitlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1807 (  ">"    PGNSP PGUID b f f 1562 1562 16 1806 1808 varbitgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1808 (  "<="   PGNSP PGUID b f f 1562 1562 16 1809 1807 varbitle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1809 (  ">="   PGNSP PGUID b f f 1562 1562 16 1808 1806 varbitge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 1849 (  "+"     PGNSP PGUID b f f 1186 1083 1083      1800 0 interval_pl_time - - ));
+
+DATA(insert OID = 1862 ( "="      PGNSP PGUID b t f    21      20      16 1868  1863 int28eq eqsel eqjoinsel ));
+DATA(insert OID = 1863 ( "<>"     PGNSP PGUID b f f    21      20      16 1869  1862 int28ne neqsel neqjoinsel ));
+DATA(insert OID = 1864 ( "<"      PGNSP PGUID b f f    21      20      16 1871  1867 int28lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1865 ( ">"      PGNSP PGUID b f f    21      20      16 1870  1866 int28gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1866 ( "<="     PGNSP PGUID b f f    21      20      16 1873  1865 int28le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1867 ( ">="     PGNSP PGUID b f f    21      20      16 1872  1864 int28ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 1868 ( "="      PGNSP PGUID b t f    20      21      16      1862 1869 int82eq eqsel eqjoinsel ));
+DATA(insert OID = 1869 ( "<>"     PGNSP PGUID b f f    20      21      16      1863 1868 int82ne neqsel neqjoinsel ));
+DATA(insert OID = 1870 ( "<"      PGNSP PGUID b f f    20      21      16      1865 1873 int82lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1871 ( ">"      PGNSP PGUID b f f    20      21      16      1864 1872 int82gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1872 ( "<="     PGNSP PGUID b f f    20      21      16      1867 1871 int82le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1873 ( ">="     PGNSP PGUID b f f    20      21      16      1866 1870 int82ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 1874 ( "&"      PGNSP PGUID b f f    21      21      21      1874  0 int2and - - ));
+DATA(insert OID = 1875 ( "|"      PGNSP PGUID b f f    21      21      21      1875  0 int2or - - ));
+DATA(insert OID = 1876 ( "#"      PGNSP PGUID b f f    21      21      21      1876  0 int2xor - - ));
+DATA(insert OID = 1877 ( "~"      PGNSP PGUID l f f     0      21      21       0        0 int2not - - ));
+DATA(insert OID = 1878 ( "<<"     PGNSP PGUID b f f    21      23      21       0        0 int2shl - - ));
+DATA(insert OID = 1879 ( ">>"     PGNSP PGUID b f f    21      23      21       0        0 int2shr - - ));
+
+DATA(insert OID = 1880 ( "&"      PGNSP PGUID b f f    23      23      23      1880  0 int4and - - ));
+DATA(insert OID = 1881 ( "|"      PGNSP PGUID b f f    23      23      23      1881  0 int4or - - ));
+DATA(insert OID = 1882 ( "#"      PGNSP PGUID b f f    23      23      23      1882  0 int4xor - - ));
+DATA(insert OID = 1883 ( "~"      PGNSP PGUID l f f     0      23      23       0        0 int4not - - ));
+DATA(insert OID = 1884 ( "<<"     PGNSP PGUID b f f    23      23      23       0        0 int4shl - - ));
+DATA(insert OID = 1885 ( ">>"     PGNSP PGUID b f f    23      23      23       0        0 int4shr - - ));
+
+DATA(insert OID = 1886 ( "&"      PGNSP PGUID b f f    20      20      20      1886  0 int8and - - ));
+DATA(insert OID = 1887 ( "|"      PGNSP PGUID b f f    20      20      20      1887  0 int8or - - ));
+DATA(insert OID = 1888 ( "#"      PGNSP PGUID b f f    20      20      20      1888  0 int8xor - - ));
+DATA(insert OID = 1889 ( "~"      PGNSP PGUID l f f     0      20      20       0        0 int8not - - ));
+DATA(insert OID = 1890 ( "<<"     PGNSP PGUID b f f    20      23      20       0        0 int8shl - - ));
+DATA(insert OID = 1891 ( ">>"     PGNSP PGUID b f f    20      23      20       0        0 int8shr - - ));
+
+DATA(insert OID = 1916 (  "+"     PGNSP PGUID l f f     0      20      20      0       0 int8up - - ));
+DATA(insert OID = 1917 (  "+"     PGNSP PGUID l f f     0      21      21      0       0 int2up - - ));
+DATA(insert OID = 1918 (  "+"     PGNSP PGUID l f f     0      23      23      0       0 int4up - - ));
+DATA(insert OID = 1919 (  "+"     PGNSP PGUID l f f     0      700 700 0       0 float4up - - ));
+DATA(insert OID = 1920 (  "+"     PGNSP PGUID l f f     0      701 701 0       0 float8up - - ));
+DATA(insert OID = 1921 (  "+"     PGNSP PGUID l f f     0 1700 1700    0       0 numeric_uplus - - ));
 
 /* bytea operators */
-DATA(insert OID = 1955 ( "="      PGNSP PGUID b t 17 17        16 1955 1956 1957 1957 1957 1959 byteaeq eqsel eqjoinsel ));
-DATA(insert OID = 1956 ( "<>"     PGNSP PGUID b f 17 17        16 1956 1955 0    0   0   0 byteane neqsel neqjoinsel ));
-DATA(insert OID = 1957 ( "<"      PGNSP PGUID b f 17 17        16 1959 1960 0    0   0   0 bytealt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1958 ( "<="     PGNSP PGUID b f 17 17        16 1960 1959 0    0   0   0 byteale scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1959 ( ">"      PGNSP PGUID b f 17 17        16 1957 1958 0    0   0   0 byteagt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1960 ( ">="     PGNSP PGUID b f 17 17        16 1958 1957 0    0   0   0 byteage scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2016 (  "~~"    PGNSP PGUID b f 17 17        16 0    2017 0    0   0   0 bytealike likesel likejoinsel ));
+DATA(insert OID = 1955 ( "="      PGNSP PGUID b t t 17 17      16 1955 1956 byteaeq eqsel eqjoinsel ));
+DATA(insert OID = 1956 ( "<>"     PGNSP PGUID b f f 17 17      16 1956 1955 byteane neqsel neqjoinsel ));
+DATA(insert OID = 1957 ( "<"      PGNSP PGUID b f f 17 17      16 1959 1960 bytealt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1958 ( "<="     PGNSP PGUID b f f 17 17      16 1960 1959 byteale scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1959 ( ">"      PGNSP PGUID b f f 17 17      16 1957 1958 byteagt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1960 ( ">="     PGNSP PGUID b f f 17 17      16 1958 1957 byteage scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2016 (  "~~"    PGNSP PGUID b f f 17 17      16 0    2017 bytealike likesel likejoinsel ));
 #define OID_BYTEA_LIKE_OP              2016
-DATA(insert OID = 2017 (  "!~~"    PGNSP PGUID b f 17 17       16 0    2016 0    0   0   0 byteanlike nlikesel nlikejoinsel ));
-DATA(insert OID = 2018 (  "||"    PGNSP PGUID b f 17 17        17 0    0        0        0   0   0 byteacat - - ));
+DATA(insert OID = 2017 (  "!~~"    PGNSP PGUID b f f 17 17     16 0    2016 byteanlike nlikesel nlikejoinsel ));
+DATA(insert OID = 2018 (  "||"    PGNSP PGUID b f f 17 17      17 0    0    byteacat - - ));
 
 /* timestamp operators */
-DATA(insert OID = 2060 (  "="     PGNSP PGUID b t 1114 1114     16 2060 2061 2062 2062 2062 2064 timestamp_eq eqsel eqjoinsel ));
-DATA(insert OID = 2061 (  "<>"    PGNSP PGUID b f 1114 1114     16 2061 2060 0 0 0 0 timestamp_ne neqsel neqjoinsel ));
-DATA(insert OID = 2062 (  "<"     PGNSP PGUID b f 1114 1114     16 2064 2065 0 0 0 0 timestamp_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2063 (  "<="    PGNSP PGUID b f 1114 1114     16 2065 2064 0 0 0 0 timestamp_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2064 (  ">"     PGNSP PGUID b f 1114 1114     16 2062 2063 0 0 0 0 timestamp_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2065 (  ">="    PGNSP PGUID b f 1114 1114     16 2063 2062 0 0 0 0 timestamp_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2066 (  "+"     PGNSP PGUID b f 1114 1186 1114        2553 0 0 0 0 0 timestamp_pl_interval - - ));
-DATA(insert OID = 2067 (  "-"     PGNSP PGUID b f 1114 1114 1186        0      0 0 0 0 0 timestamp_mi - - ));
-DATA(insert OID = 2068 (  "-"     PGNSP PGUID b f 1114 1186 1114        0      0 0 0 0 0 timestamp_mi_interval - - ));
+DATA(insert OID = 2060 (  "="     PGNSP PGUID b t t 1114 1114   16 2060 2061 timestamp_eq eqsel eqjoinsel ));
+DATA(insert OID = 2061 (  "<>"    PGNSP PGUID b f f 1114 1114   16 2061 2060 timestamp_ne neqsel neqjoinsel ));
+DATA(insert OID = 2062 (  "<"     PGNSP PGUID b f f 1114 1114   16 2064 2065 timestamp_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2063 (  "<="    PGNSP PGUID b f f 1114 1114   16 2065 2064 timestamp_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2064 (  ">"     PGNSP PGUID b f f 1114 1114   16 2062 2063 timestamp_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2065 (  ">="    PGNSP PGUID b f f 1114 1114   16 2063 2062 timestamp_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2066 (  "+"     PGNSP PGUID b f f 1114 1186 1114      2553 0 timestamp_pl_interval - - ));
+DATA(insert OID = 2067 (  "-"     PGNSP PGUID b f f 1114 1114 1186      0      0 timestamp_mi - - ));
+DATA(insert OID = 2068 (  "-"     PGNSP PGUID b f f 1114 1186 1114      0      0 timestamp_mi_interval - - ));
 
 /* character-by-character (not collation order) comparison operators for character types */
 
-DATA(insert OID = 2314 ( "~<~" PGNSP PGUID b f 25 25 16 2318 2317 0 0 0 0 text_pattern_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2315 ( "~<=~" PGNSP PGUID b f 25 25 16 2317 2318 0 0 0 0 text_pattern_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2316 ( "~=~" PGNSP PGUID b t 25 25 16 2316 2319 2314 2314 2314 2318 text_pattern_eq eqsel eqjoinsel ));
-DATA(insert OID = 2317 ( "~>=~" PGNSP PGUID b f 25 25 16 2315 2314 0 0 0 0 text_pattern_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2318 ( "~>~" PGNSP PGUID b f 25 25 16 2314 2315 0 0 0 0 text_pattern_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2319 ( "~<>~" PGNSP PGUID b f 25 25 16 2319 2316 0 0 0 0 text_pattern_ne neqsel neqjoinsel ));
-
-DATA(insert OID = 2326 ( "~<~" PGNSP PGUID b f 1042 1042 16 2330 2329 0 0 0 0 bpchar_pattern_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2327 ( "~<=~" PGNSP PGUID b f 1042 1042 16 2329 2330 0 0 0 0 bpchar_pattern_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2328 ( "~=~" PGNSP PGUID b t 1042 1042 16 2328 2331 2326 2326 2326 2330 bpchar_pattern_eq eqsel eqjoinsel ));
-DATA(insert OID = 2329 ( "~>=~" PGNSP PGUID b f 1042 1042 16 2327 2326 0 0 0 0 bpchar_pattern_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2330 ( "~>~" PGNSP PGUID b f 1042 1042 16 2326 2327 0 0 0 0 bpchar_pattern_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2331 ( "~<>~" PGNSP PGUID b f 1042 1042 16 2331 2328 0 0 0 0 bpchar_pattern_ne neqsel neqjoinsel ));
-
-DATA(insert OID = 2332 ( "~<~" PGNSP PGUID b f 19 19 16 2336 2335 0 0 0 0 name_pattern_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2333 ( "~<=~" PGNSP PGUID b f 19 19 16 2335 2336 0 0 0 0 name_pattern_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2334 ( "~=~" PGNSP PGUID b t 19 19 16 2334 2337 2332 2332 2332 2336 name_pattern_eq eqsel eqjoinsel ));
-DATA(insert OID = 2335 ( "~>=~" PGNSP PGUID b f 19 19 16 2333 2332 0 0 0 0 name_pattern_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2336 ( "~>~" PGNSP PGUID b f 19 19 16 2332 2333 0 0 0 0 name_pattern_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2337 ( "~<>~" PGNSP PGUID b f 19 19 16 2337 2334 0 0 0 0 name_pattern_ne neqsel neqjoinsel ));
+DATA(insert OID = 2314 ( "~<~" PGNSP PGUID b f f 25 25 16 2318 2317 text_pattern_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2315 ( "~<=~" PGNSP PGUID b f f 25 25 16 2317 2318 text_pattern_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2316 ( "~=~" PGNSP PGUID b t t 25 25 16 2316 2319 text_pattern_eq eqsel eqjoinsel ));
+DATA(insert OID = 2317 ( "~>=~" PGNSP PGUID b f f 25 25 16 2315 2314 text_pattern_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2318 ( "~>~" PGNSP PGUID b f f 25 25 16 2314 2315 text_pattern_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2319 ( "~<>~" PGNSP PGUID b f f 25 25 16 2319 2316 text_pattern_ne neqsel neqjoinsel ));
+
+DATA(insert OID = 2326 ( "~<~" PGNSP PGUID b f f 1042 1042 16 2330 2329 bpchar_pattern_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2327 ( "~<=~" PGNSP PGUID b f f 1042 1042 16 2329 2330 bpchar_pattern_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2328 ( "~=~" PGNSP PGUID b t t 1042 1042 16 2328 2331 bpchar_pattern_eq eqsel eqjoinsel ));
+DATA(insert OID = 2329 ( "~>=~" PGNSP PGUID b f f 1042 1042 16 2327 2326 bpchar_pattern_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2330 ( "~>~" PGNSP PGUID b f f 1042 1042 16 2326 2327 bpchar_pattern_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2331 ( "~<>~" PGNSP PGUID b f f 1042 1042 16 2331 2328 bpchar_pattern_ne neqsel neqjoinsel ));
+
+DATA(insert OID = 2332 ( "~<~" PGNSP PGUID b f f 19 19 16 2336 2335 name_pattern_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2333 ( "~<=~" PGNSP PGUID b f f 19 19 16 2335 2336 name_pattern_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2334 ( "~=~" PGNSP PGUID b t t 19 19 16 2334 2337 name_pattern_eq eqsel eqjoinsel ));
+DATA(insert OID = 2335 ( "~>=~" PGNSP PGUID b f f 19 19 16 2333 2332 name_pattern_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2336 ( "~>~" PGNSP PGUID b f f 19 19 16 2332 2333 name_pattern_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2337 ( "~<>~" PGNSP PGUID b f f 19 19 16 2337 2334 name_pattern_ne neqsel neqjoinsel ));
 
 /* crosstype operations for date vs. timestamp and timestamptz */
 
-DATA(insert OID = 2345 ( "<"      PGNSP PGUID b f      1082    1114   16 2375 2348  0 0 0 0 date_lt_timestamp scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2346 ( "<="     PGNSP PGUID b f      1082    1114   16 2374 2349  0 0 0 0 date_le_timestamp scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2347 ( "="      PGNSP PGUID b f      1082    1114   16 2373 2350  1095 2062 2345 2349 date_eq_timestamp eqsel eqjoinsel ));
-DATA(insert OID = 2348 ( ">="     PGNSP PGUID b f      1082    1114   16 2372 2345  0 0 0 0 date_ge_timestamp scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2349 ( ">"      PGNSP PGUID b f      1082    1114   16 2371 2346  0 0 0 0 date_gt_timestamp scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2350 ( "<>"     PGNSP PGUID b f      1082    1114   16 2376 2347  0 0 0 0 date_ne_timestamp neqsel neqjoinsel ));
-
-DATA(insert OID = 2358 ( "<"      PGNSP PGUID b f      1082    1184   16 2388 2361  0 0 0 0 date_lt_timestamptz scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2359 ( "<="     PGNSP PGUID b f      1082    1184   16 2387 2362  0 0 0 0 date_le_timestamptz scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2360 ( "="      PGNSP PGUID b f      1082    1184   16 2386 2363  1095 1322 2358 2362 date_eq_timestamptz eqsel eqjoinsel ));
-DATA(insert OID = 2361 ( ">="     PGNSP PGUID b f      1082    1184   16 2385 2358  0 0 0 0 date_ge_timestamptz scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2362 ( ">"      PGNSP PGUID b f      1082    1184   16 2384 2359  0 0 0 0 date_gt_timestamptz scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2363 ( "<>"     PGNSP PGUID b f      1082    1184   16 2389 2360  0 0 0 0 date_ne_timestamptz neqsel neqjoinsel ));
-
-DATA(insert OID = 2371 ( "<"      PGNSP PGUID b f      1114    1082   16 2349 2374  0 0 0 0 timestamp_lt_date scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2372 ( "<="     PGNSP PGUID b f      1114    1082   16 2348 2375  0 0 0 0 timestamp_le_date scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2373 ( "="      PGNSP PGUID b f      1114    1082   16 2347 2376  2062 1095 2371 2375 timestamp_eq_date eqsel eqjoinsel ));
-DATA(insert OID = 2374 ( ">="     PGNSP PGUID b f      1114    1082   16 2346 2371  0 0 0 0 timestamp_ge_date scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2375 ( ">"      PGNSP PGUID b f      1114    1082   16 2345 2372  0 0 0 0 timestamp_gt_date scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2376 ( "<>"     PGNSP PGUID b f      1114    1082   16 2350 2373  0 0 0 0 timestamp_ne_date neqsel neqjoinsel ));
-
-DATA(insert OID = 2384 ( "<"      PGNSP PGUID b f      1184    1082   16 2362 2387  0 0 0 0 timestamptz_lt_date scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2385 ( "<="     PGNSP PGUID b f      1184    1082   16 2361 2388  0 0 0 0 timestamptz_le_date scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2386 ( "="      PGNSP PGUID b f      1184    1082   16 2360 2389  1322 1095 2384 2388 timestamptz_eq_date eqsel eqjoinsel ));
-DATA(insert OID = 2387 ( ">="     PGNSP PGUID b f      1184    1082   16 2359 2384  0 0 0 0 timestamptz_ge_date scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2388 ( ">"      PGNSP PGUID b f      1184    1082   16 2358 2385  0 0 0 0 timestamptz_gt_date scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2389 ( "<>"     PGNSP PGUID b f      1184    1082   16 2363 2386  0 0 0 0 timestamptz_ne_date neqsel neqjoinsel ));
+DATA(insert OID = 2345 ( "<"      PGNSP PGUID b f f    1082    1114   16 2375 2348 date_lt_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2346 ( "<="     PGNSP PGUID b f f    1082    1114   16 2374 2349 date_le_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2347 ( "="      PGNSP PGUID b t f    1082    1114   16 2373 2350 date_eq_timestamp eqsel eqjoinsel ));
+DATA(insert OID = 2348 ( ">="     PGNSP PGUID b f f    1082    1114   16 2372 2345 date_ge_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2349 ( ">"      PGNSP PGUID b f f    1082    1114   16 2371 2346 date_gt_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2350 ( "<>"     PGNSP PGUID b f f    1082    1114   16 2376 2347 date_ne_timestamp neqsel neqjoinsel ));
+
+DATA(insert OID = 2358 ( "<"      PGNSP PGUID b f f    1082    1184   16 2388 2361 date_lt_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2359 ( "<="     PGNSP PGUID b f f    1082    1184   16 2387 2362 date_le_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2360 ( "="      PGNSP PGUID b t f    1082    1184   16 2386 2363 date_eq_timestamptz eqsel eqjoinsel ));
+DATA(insert OID = 2361 ( ">="     PGNSP PGUID b f f    1082    1184   16 2385 2358 date_ge_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2362 ( ">"      PGNSP PGUID b f f    1082    1184   16 2384 2359 date_gt_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2363 ( "<>"     PGNSP PGUID b f f    1082    1184   16 2389 2360 date_ne_timestamptz neqsel neqjoinsel ));
+
+DATA(insert OID = 2371 ( "<"      PGNSP PGUID b f f    1114    1082   16 2349 2374 timestamp_lt_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2372 ( "<="     PGNSP PGUID b f f    1114    1082   16 2348 2375 timestamp_le_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2373 ( "="      PGNSP PGUID b t f    1114    1082   16 2347 2376 timestamp_eq_date eqsel eqjoinsel ));
+DATA(insert OID = 2374 ( ">="     PGNSP PGUID b f f    1114    1082   16 2346 2371 timestamp_ge_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2375 ( ">"      PGNSP PGUID b f f    1114    1082   16 2345 2372 timestamp_gt_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2376 ( "<>"     PGNSP PGUID b f f    1114    1082   16 2350 2373 timestamp_ne_date neqsel neqjoinsel ));
+
+DATA(insert OID = 2384 ( "<"      PGNSP PGUID b f f    1184    1082   16 2362 2387 timestamptz_lt_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2385 ( "<="     PGNSP PGUID b f f    1184    1082   16 2361 2388 timestamptz_le_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2386 ( "="      PGNSP PGUID b t f    1184    1082   16 2360 2389 timestamptz_eq_date eqsel eqjoinsel ));
+DATA(insert OID = 2387 ( ">="     PGNSP PGUID b f f    1184    1082   16 2359 2384 timestamptz_ge_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2388 ( ">"      PGNSP PGUID b f f    1184    1082   16 2358 2385 timestamptz_gt_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2389 ( "<>"     PGNSP PGUID b f f    1184    1082   16 2363 2386 timestamptz_ne_date neqsel neqjoinsel ));
 
 /* crosstype operations for timestamp vs. timestamptz */
 
-DATA(insert OID = 2534 ( "<"      PGNSP PGUID b f      1114    1184   16 2544 2537  0 0 0 0 timestamp_lt_timestamptz scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2535 ( "<="     PGNSP PGUID b f      1114    1184   16 2543 2538  0 0 0 0 timestamp_le_timestamptz scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2536 ( "="      PGNSP PGUID b f      1114    1184   16 2542 2539  2062 1322 2534 2538 timestamp_eq_timestamptz eqsel eqjoinsel ));
-DATA(insert OID = 2537 ( ">="     PGNSP PGUID b f      1114    1184   16 2541 2534  0 0 0 0 timestamp_ge_timestamptz scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2538 ( ">"      PGNSP PGUID b f      1114    1184   16 2540 2535  0 0 0 0 timestamp_gt_timestamptz scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2539 ( "<>"     PGNSP PGUID b f      1114    1184   16 2545 2536  0 0 0 0 timestamp_ne_timestamptz neqsel neqjoinsel ));
+DATA(insert OID = 2534 ( "<"      PGNSP PGUID b f f    1114    1184   16 2544 2537 timestamp_lt_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2535 ( "<="     PGNSP PGUID b f f    1114    1184   16 2543 2538 timestamp_le_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2536 ( "="      PGNSP PGUID b t f    1114    1184   16 2542 2539 timestamp_eq_timestamptz eqsel eqjoinsel ));
+DATA(insert OID = 2537 ( ">="     PGNSP PGUID b f f    1114    1184   16 2541 2534 timestamp_ge_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2538 ( ">"      PGNSP PGUID b f f    1114    1184   16 2540 2535 timestamp_gt_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2539 ( "<>"     PGNSP PGUID b f f    1114    1184   16 2545 2536 timestamp_ne_timestamptz neqsel neqjoinsel ));
 
-DATA(insert OID = 2540 ( "<"      PGNSP PGUID b f      1184    1114   16 2538 2543  0 0 0 0 timestamptz_lt_timestamp scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2541 ( "<="     PGNSP PGUID b f      1184    1114   16 2537 2544  0 0 0 0 timestamptz_le_timestamp scalarltsel scalarltjoinsel ));
-DATA(insert OID = 2542 ( "="      PGNSP PGUID b f      1184    1114   16 2536 2545  1322 2062 2540 2544 timestamptz_eq_timestamp eqsel eqjoinsel ));
-DATA(insert OID = 2543 ( ">="     PGNSP PGUID b f      1184    1114   16 2535 2540  0 0 0 0 timestamptz_ge_timestamp scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2544 ( ">"      PGNSP PGUID b f      1184    1114   16 2534 2541  0 0 0 0 timestamptz_gt_timestamp scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2545 ( "<>"     PGNSP PGUID b f      1184    1114   16 2539 2542  0 0 0 0 timestamptz_ne_timestamp neqsel neqjoinsel ));
+DATA(insert OID = 2540 ( "<"      PGNSP PGUID b f f    1184    1114   16 2538 2543 timestamptz_lt_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2541 ( "<="     PGNSP PGUID b f f    1184    1114   16 2537 2544 timestamptz_le_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2542 ( "="      PGNSP PGUID b t f    1184    1114   16 2536 2545 timestamptz_eq_timestamp eqsel eqjoinsel ));
+DATA(insert OID = 2543 ( ">="     PGNSP PGUID b f f    1184    1114   16 2535 2540 timestamptz_ge_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2544 ( ">"      PGNSP PGUID b f f    1184    1114   16 2534 2541 timestamptz_gt_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2545 ( "<>"     PGNSP PGUID b f f    1184    1114   16 2539 2542 timestamptz_ne_timestamp neqsel neqjoinsel ));
 
 /* formerly-missing interval + datetime operators */
-DATA(insert OID = 2551 (  "+"     PGNSP PGUID b f      1186 1082 1114 1076 0 0 0 0 0 interval_pl_date - - ));
-DATA(insert OID = 2552 (  "+"     PGNSP PGUID b f      1186 1266 1266 1802 0 0 0 0 0 interval_pl_timetz - - ));
-DATA(insert OID = 2553 (  "+"     PGNSP PGUID b f      1186 1114 1114 2066 0 0 0 0 0 interval_pl_timestamp - - ));
-DATA(insert OID = 2554 (  "+"     PGNSP PGUID b f      1186 1184 1184 1327 0 0 0 0 0 interval_pl_timestamptz - - ));
-DATA(insert OID = 2555 (  "+"     PGNSP PGUID b f      23 1082 1082 1100 0 0 0 0 0 integer_pl_date - - ));
+DATA(insert OID = 2551 (  "+"     PGNSP PGUID b f f    1186 1082 1114 1076 0 interval_pl_date - - ));
+DATA(insert OID = 2552 (  "+"     PGNSP PGUID b f f    1186 1266 1266 1802 0 interval_pl_timetz - - ));
+DATA(insert OID = 2553 (  "+"     PGNSP PGUID b f f    1186 1114 1114 2066 0 interval_pl_timestamp - - ));
+DATA(insert OID = 2554 (  "+"     PGNSP PGUID b f f    1186 1184 1184 1327 0 interval_pl_timestamptz - - ));
+DATA(insert OID = 2555 (  "+"     PGNSP PGUID b f f    23   1082 1082 1100 0 integer_pl_date - - ));
 
 /* new operators for Y-direction rtree opclasses */
-DATA(insert OID = 2570 (  "<<|"    PGNSP PGUID b f 603 603     16       0       0       0       0       0       0 box_below positionsel positionjoinsel ));
-DATA(insert OID = 2571 (  "&<|"    PGNSP PGUID b f 603 603     16       0       0       0       0       0       0 box_overbelow positionsel positionjoinsel ));
-DATA(insert OID = 2572 (  "|&>"    PGNSP PGUID b f 603 603     16       0       0       0       0       0       0 box_overabove positionsel positionjoinsel ));
-DATA(insert OID = 2573 (  "|>>"    PGNSP PGUID b f 603 603     16       0       0       0       0       0       0 box_above positionsel positionjoinsel ));
-DATA(insert OID = 2574 (  "<<|"    PGNSP PGUID b f 604 604     16       0       0       0       0       0       0 poly_below positionsel positionjoinsel ));
-DATA(insert OID = 2575 (  "&<|"    PGNSP PGUID b f 604 604     16       0       0       0       0       0       0 poly_overbelow positionsel positionjoinsel ));
-DATA(insert OID = 2576 (  "|&>"    PGNSP PGUID b f 604 604     16       0       0       0       0       0       0 poly_overabove positionsel positionjoinsel ));
-DATA(insert OID = 2577 (  "|>>"    PGNSP PGUID b f 604 604     16       0       0       0       0       0       0 poly_above positionsel positionjoinsel ));
-DATA(insert OID = 2589 (  "&<|"    PGNSP PGUID b f 718 718     16       0       0       0       0       0       0 circle_overbelow positionsel positionjoinsel ));
-DATA(insert OID = 2590 (  "|&>"    PGNSP PGUID b f 718 718     16       0       0       0       0       0       0 circle_overabove positionsel positionjoinsel ));
+DATA(insert OID = 2570 (  "<<|"    PGNSP PGUID b f f 603 603   16       0       0 box_below positionsel positionjoinsel ));
+DATA(insert OID = 2571 (  "&<|"    PGNSP PGUID b f f 603 603   16       0       0 box_overbelow positionsel positionjoinsel ));
+DATA(insert OID = 2572 (  "|&>"    PGNSP PGUID b f f 603 603   16       0       0 box_overabove positionsel positionjoinsel ));
+DATA(insert OID = 2573 (  "|>>"    PGNSP PGUID b f f 603 603   16       0       0 box_above positionsel positionjoinsel ));
+DATA(insert OID = 2574 (  "<<|"    PGNSP PGUID b f f 604 604   16       0       0 poly_below positionsel positionjoinsel ));
+DATA(insert OID = 2575 (  "&<|"    PGNSP PGUID b f f 604 604   16       0       0 poly_overbelow positionsel positionjoinsel ));
+DATA(insert OID = 2576 (  "|&>"    PGNSP PGUID b f f 604 604   16       0       0 poly_overabove positionsel positionjoinsel ));
+DATA(insert OID = 2577 (  "|>>"    PGNSP PGUID b f f 604 604   16       0       0 poly_above positionsel positionjoinsel ));
+DATA(insert OID = 2589 (  "&<|"    PGNSP PGUID b f f 718 718   16       0       0 circle_overbelow positionsel positionjoinsel ));
+DATA(insert OID = 2590 (  "|&>"    PGNSP PGUID b f f 718 718   16       0       0 circle_overabove positionsel positionjoinsel ));
 
 /* overlap/contains/contained for arrays */
-DATA(insert OID = 2750 (  "&&"    PGNSP PGUID b f 2277 2277    16 2750  0       0       0       0       0 arrayoverlap areasel areajoinsel ));
-DATA(insert OID = 2751 (  "@>"    PGNSP PGUID b f 2277 2277    16 2752  0       0       0       0       0 arraycontains contsel contjoinsel ));
-DATA(insert OID = 2752 (  "<@"    PGNSP PGUID b f 2277 2277    16 2751  0       0       0       0       0 arraycontained contsel contjoinsel ));
+DATA(insert OID = 2750 (  "&&"    PGNSP PGUID b f f 2277 2277  16 2750  0 arrayoverlap areasel areajoinsel ));
+DATA(insert OID = 2751 (  "@>"    PGNSP PGUID b f f 2277 2277  16 2752  0 arraycontains contsel contjoinsel ));
+DATA(insert OID = 2752 (  "<@"    PGNSP PGUID b f f 2277 2277  16 2751  0 arraycontained contsel contjoinsel ));
 
 /* obsolete names for contains/contained-by operators; remove these someday */
-DATA(insert OID = 2860 (  "@"     PGNSP PGUID b f 604 604      16 2861  0       0       0       0       0 poly_contained contsel contjoinsel ));
-DATA(insert OID = 2861 (  "~"     PGNSP PGUID b f 604 604      16 2860  0       0       0       0       0 poly_contain contsel contjoinsel ));
-DATA(insert OID = 2862 (  "@"     PGNSP PGUID b f 603 603      16 2863  0       0       0       0       0 box_contained contsel contjoinsel ));
-DATA(insert OID = 2863 (  "~"     PGNSP PGUID b f 603 603      16 2862  0       0       0       0       0 box_contain contsel contjoinsel ));
-DATA(insert OID = 2864 (  "@"     PGNSP PGUID b f 718 718      16 2865  0       0       0       0       0 circle_contained contsel contjoinsel ));
-DATA(insert OID = 2865 (  "~"     PGNSP PGUID b f 718 718      16 2864  0       0       0       0       0 circle_contain contsel contjoinsel ));
-DATA(insert OID = 2866 (  "@"     PGNSP PGUID b f 600 603      16       0       0       0       0       0       0 on_pb - - ));
-DATA(insert OID = 2867 (  "@"     PGNSP PGUID b f 600 602      16 2868  0       0       0       0       0 on_ppath - - ));
-DATA(insert OID = 2868 (  "~"     PGNSP PGUID b f 602 600       16  2867  0 0 0 0 0 path_contain_pt - - ));
-DATA(insert OID = 2869 (  "@"     PGNSP PGUID b f 600 604       16  2870  0 0 0 0 0 pt_contained_poly - - ));
-DATA(insert OID = 2870 (  "~"     PGNSP PGUID b f 604 600       16  2869  0 0 0 0 0 poly_contain_pt - - ));
-DATA(insert OID = 2871 (  "@"     PGNSP PGUID b f 600 718       16  2872  0 0 0 0 0 pt_contained_circle - - ));
-DATA(insert OID = 2872 (  "~"     PGNSP PGUID b f 718 600       16  2871  0 0 0 0 0 circle_contain_pt - - ));
-DATA(insert OID = 2873 (  "@"     PGNSP PGUID b f 600 628 16     0  0 0 0 0 0 on_pl - - ));
-DATA(insert OID = 2874 (  "@"     PGNSP PGUID b f 600 601 16     0  0 0 0 0 0 on_ps - - ));
-DATA(insert OID = 2875 (  "@"     PGNSP PGUID b f 601 628 16     0  0 0 0 0 0 on_sl - - ));
-DATA(insert OID = 2876 (  "@"     PGNSP PGUID b f 601 603 16     0  0 0 0 0 0 on_sb - - ));
-DATA(insert OID = 2877 (  "~"     PGNSP PGUID b f 1034 1033     16 0 0 0 0 0 0 aclcontains - - ));
+DATA(insert OID = 2860 (  "@"     PGNSP PGUID b f f 604 604    16 2861  0 poly_contained contsel contjoinsel ));
+DATA(insert OID = 2861 (  "~"     PGNSP PGUID b f f 604 604    16 2860  0 poly_contain contsel contjoinsel ));
+DATA(insert OID = 2862 (  "@"     PGNSP PGUID b f f 603 603    16 2863  0 box_contained contsel contjoinsel ));
+DATA(insert OID = 2863 (  "~"     PGNSP PGUID b f f 603 603    16 2862  0 box_contain contsel contjoinsel ));
+DATA(insert OID = 2864 (  "@"     PGNSP PGUID b f f 718 718    16 2865  0 circle_contained contsel contjoinsel ));
+DATA(insert OID = 2865 (  "~"     PGNSP PGUID b f f 718 718    16 2864  0 circle_contain contsel contjoinsel ));
+DATA(insert OID = 2866 (  "@"     PGNSP PGUID b f f 600 603    16       0       0 on_pb - - ));
+DATA(insert OID = 2867 (  "@"     PGNSP PGUID b f f 600 602    16 2868  0 on_ppath - - ));
+DATA(insert OID = 2868 (  "~"     PGNSP PGUID b f f 602 600     16  2867  0 path_contain_pt - - ));
+DATA(insert OID = 2869 (  "@"     PGNSP PGUID b f f 600 604     16  2870  0 pt_contained_poly - - ));
+DATA(insert OID = 2870 (  "~"     PGNSP PGUID b f f 604 600     16  2869  0 poly_contain_pt - - ));
+DATA(insert OID = 2871 (  "@"     PGNSP PGUID b f f 600 718     16  2872  0 pt_contained_circle - - ));
+DATA(insert OID = 2872 (  "~"     PGNSP PGUID b f f 718 600     16  2871  0 circle_contain_pt - - ));
+DATA(insert OID = 2873 (  "@"     PGNSP PGUID b f f 600 628 16   0  0 on_pl - - ));
+DATA(insert OID = 2874 (  "@"     PGNSP PGUID b f f 600 601 16   0  0 on_ps - - ));
+DATA(insert OID = 2875 (  "@"     PGNSP PGUID b f f 601 628 16   0  0 on_sl - - ));
+DATA(insert OID = 2876 (  "@"     PGNSP PGUID b f f 601 603 16   0  0 on_sb - - ));
+DATA(insert OID = 2877 (  "~"     PGNSP PGUID b f f 1034 1033   16 0 0 aclcontains - - ));
 
 
 /*
@@ -916,10 +908,7 @@ extern void OperatorCreate(const char *operatorName,
                           List *negatorName,
                           List *restrictionName,
                           List *joinName,
-                          bool canHash,
-                          List *leftSortName,
-                          List *rightSortName,
-                          List *ltCompareName,
-                          List *gtCompareName);
+                          bool canMerge,
+                          bool canHash);
 
 #endif   /* PG_OPERATOR_H */
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
new file mode 100644 (file)
index 0000000..8e51fb7
--- /dev/null
@@ -0,0 +1,138 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_opfamily.h
+ *       definition of the system "opfamily" relation (pg_opfamily)
+ *       along with the relation's initial contents.
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.1 2006/12/23 00:43:12 tgl Exp $
+ *
+ * NOTES
+ *       the genbki.sh script reads this file and generates .bki
+ *       information from the DATA() statements.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPFAMILY_H
+#define PG_OPFAMILY_H
+
+/* ----------------
+ *             postgres.h contains the system type definitions and the
+ *             CATALOG(), BKI_BOOTSTRAP and DATA() sugar words so this file
+ *             can be read by both genbki.sh and the C compiler.
+ * ----------------
+ */
+
+/* ----------------
+ *             pg_opfamily definition. cpp turns this into
+ *             typedef struct FormData_pg_opfamily
+ * ----------------
+ */
+#define OperatorFamilyRelationId  2753
+
+CATALOG(pg_opfamily,2753)
+{
+       Oid                     opfmethod;              /* index access method opfamily is for */
+       NameData        opfname;                /* name of this opfamily */
+       Oid                     opfnamespace;   /* namespace of this opfamily */
+       Oid                     opfowner;               /* opfamily owner */
+} FormData_pg_opfamily;
+
+/* ----------------
+ *             Form_pg_opfamily corresponds to a pointer to a tuple with
+ *             the format of pg_opfamily relation.
+ * ----------------
+ */
+typedef FormData_pg_opfamily *Form_pg_opfamily;
+
+/* ----------------
+ *             compiler constants for pg_opfamily
+ * ----------------
+ */
+#define Natts_pg_opfamily                              4
+#define Anum_pg_opfamily_opfmethod             1
+#define Anum_pg_opfamily_opfname               2
+#define Anum_pg_opfamily_opfnamespace  3
+#define Anum_pg_opfamily_opfowner              4
+
+/* ----------------
+ *             initial contents of pg_opfamily
+ * ----------------
+ */
+
+DATA(insert OID =  421 (       403             abstime_ops             PGNSP PGUID ));
+DATA(insert OID =  397 (       403             array_ops               PGNSP PGUID ));
+DATA(insert OID =  423 (       403             bit_ops                 PGNSP PGUID ));
+DATA(insert OID =  424 (       403             bool_ops                PGNSP PGUID ));
+#define BOOL_BTREE_FAM_OID 424
+DATA(insert OID =  426 (       403             bpchar_ops              PGNSP PGUID ));
+#define BPCHAR_BTREE_FAM_OID 426
+DATA(insert OID =  427 (       405             bpchar_ops              PGNSP PGUID ));
+DATA(insert OID =  428 (       403             bytea_ops               PGNSP PGUID ));
+#define BYTEA_BTREE_FAM_OID 428
+DATA(insert OID =  429 (       403             char_ops                PGNSP PGUID ));
+DATA(insert OID =  431 (       405             char_ops                PGNSP PGUID ));
+DATA(insert OID =  434 (       403             datetime_ops    PGNSP PGUID ));
+DATA(insert OID =  435 (       405             date_ops                PGNSP PGUID ));
+DATA(insert OID = 1970 (       403             float_ops               PGNSP PGUID ));
+DATA(insert OID = 1971 (       405             float_ops               PGNSP PGUID ));
+DATA(insert OID = 1974 (       403             network_ops             PGNSP PGUID ));
+#define NETWORK_BTREE_FAM_OID 1974
+DATA(insert OID = 1975 (       405             network_ops             PGNSP PGUID ));
+DATA(insert OID = 1976 (       403             integer_ops             PGNSP PGUID ));
+#define INTEGER_BTREE_FAM_OID 1976
+DATA(insert OID = 1977 (       405             integer_ops             PGNSP PGUID ));
+DATA(insert OID = 1982 (       403             interval_ops    PGNSP PGUID ));
+DATA(insert OID = 1983 (       405             interval_ops    PGNSP PGUID ));
+DATA(insert OID = 1984 (       403             macaddr_ops             PGNSP PGUID ));
+DATA(insert OID = 1985 (       405             macaddr_ops             PGNSP PGUID ));
+DATA(insert OID = 1986 (       403             name_ops                PGNSP PGUID ));
+#define NAME_BTREE_FAM_OID 1986
+DATA(insert OID = 1987 (       405             name_ops                PGNSP PGUID ));
+DATA(insert OID = 1988 (       403             numeric_ops             PGNSP PGUID ));
+DATA(insert OID = 1989 (       403             oid_ops                 PGNSP PGUID ));
+#define OID_BTREE_FAM_OID 1989
+DATA(insert OID = 1990 (       405             oid_ops                 PGNSP PGUID ));
+DATA(insert OID = 1991 (       403             oidvector_ops   PGNSP PGUID ));
+DATA(insert OID = 1992 (       405             oidvector_ops   PGNSP PGUID ));
+DATA(insert OID = 1994 (       403             text_ops                PGNSP PGUID ));
+#define TEXT_BTREE_FAM_OID 1994
+DATA(insert OID = 1995 (       405             text_ops                PGNSP PGUID ));
+DATA(insert OID = 1996 (       403             time_ops                PGNSP PGUID ));
+DATA(insert OID = 1997 (       405             time_ops                PGNSP PGUID ));
+DATA(insert OID = 1999 (       405             timestamptz_ops PGNSP PGUID ));
+DATA(insert OID = 2000 (       403             timetz_ops              PGNSP PGUID ));
+DATA(insert OID = 2001 (       405             timetz_ops              PGNSP PGUID ));
+DATA(insert OID = 2002 (       403             varbit_ops              PGNSP PGUID ));
+DATA(insert OID = 2040 (       405             timestamp_ops   PGNSP PGUID ));
+DATA(insert OID = 2095 (       403             text_pattern_ops        PGNSP PGUID ));
+#define TEXT_PATTERN_BTREE_FAM_OID 2095
+DATA(insert OID = 2097 (       403             bpchar_pattern_ops      PGNSP PGUID ));
+#define BPCHAR_PATTERN_BTREE_FAM_OID 2097
+DATA(insert OID = 2098 (       403             name_pattern_ops        PGNSP PGUID ));
+#define NAME_PATTERN_BTREE_FAM_OID 2098
+DATA(insert OID = 2099 (       403             money_ops               PGNSP PGUID ));
+DATA(insert OID = 2222 (       405             bool_ops                PGNSP PGUID ));
+#define BOOL_HASH_FAM_OID 2222
+DATA(insert OID = 2223 (       405             bytea_ops               PGNSP PGUID ));
+DATA(insert OID = 2224 (       405             int2vector_ops  PGNSP PGUID ));
+DATA(insert OID = 2789 (       403             tid_ops                 PGNSP PGUID ));
+DATA(insert OID = 2225 (       405             xid_ops                 PGNSP PGUID ));
+DATA(insert OID = 2226 (       405             cid_ops                 PGNSP PGUID ));
+DATA(insert OID = 2227 (       405             abstime_ops             PGNSP PGUID ));
+DATA(insert OID = 2228 (       405             reltime_ops             PGNSP PGUID ));
+DATA(insert OID = 2229 (       405             text_pattern_ops        PGNSP PGUID ));
+DATA(insert OID = 2231 (       405             bpchar_pattern_ops      PGNSP PGUID ));
+DATA(insert OID = 2232 (       405             name_pattern_ops        PGNSP PGUID ));
+DATA(insert OID = 2233 (       403             reltime_ops             PGNSP PGUID ));
+DATA(insert OID = 2234 (       403             tinterval_ops   PGNSP PGUID ));
+DATA(insert OID = 2235 (       405             aclitem_ops             PGNSP PGUID ));
+DATA(insert OID = 2593 (       783             box_ops                 PGNSP PGUID ));
+DATA(insert OID = 2594 (       783             poly_ops                PGNSP PGUID ));
+DATA(insert OID = 2595 (       783             circle_ops              PGNSP PGUID ));
+DATA(insert OID = 2745 (       2742    array_ops               PGNSP PGUID ));
+
+#endif   /* PG_OPFAMILY_H */
index 7b45ea5..4c8ac8c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.77 2006/10/04 00:30:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.78 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -81,6 +81,9 @@ extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId);
 extern void DefineOpClass(CreateOpClassStmt *stmt);
 extern void RemoveOpClass(RemoveOpClassStmt *stmt);
 extern void RemoveOpClassById(Oid opclassOid);
+extern void RemoveOpFamilyById(Oid opfamilyOid);
+extern void RemoveAmOpEntryById(Oid entryOid);
+extern void RemoveAmProcEntryById(Oid entryOid);
 extern void RenameOpClass(List *name, const char *access_method, const char *newname);
 extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId);
 
index f79bf29..bc62c90 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.334 2006/11/05 22:42:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.335 2006/12/23 00:43:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1318,6 +1318,7 @@ typedef struct CreateOpClassStmt
 {
        NodeTag         type;
        List       *opclassname;        /* qualified name (list of Value strings) */
+       List       *opfamilyname;       /* qualified name (ditto); NIL if omitted */
        char       *amname;                     /* name of index AM opclass is for */
        TypeName   *datatype;           /* datatype of indexed column */
        List       *items;                      /* List of CreateOpClassItem nodes */
index 5c2de28..e825050 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.85 2006/08/02 01:59:47 joe Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.86 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -351,7 +351,9 @@ typedef struct NestLoop
 typedef struct MergeJoin
 {
        Join            join;
-       List       *mergeclauses;
+       List       *mergeclauses;               /* mergeclauses as expression trees */
+       List       *mergefamilies;              /* OID list of btree opfamilies */
+       List       *mergestrategies;    /* integer list of btree strategies */
 } MergeJoin;
 
 /* ----------------
index 9654181..5946300 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.119 2006/12/21 16:05:16 petere Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.120 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -654,7 +654,7 @@ typedef struct RowExpr
  *
  * We support row comparison for any operator that can be determined to
  * act like =, <>, <, <=, >, or >= (we determine this by looking for the
- * operator in btree opclasses).  Note that the same operator name might
+ * operator in btree opfamilies).  Note that the same operator name might
  * map to a different operator for each pair of row elements, since the
  * element datatypes can vary.
  *
@@ -679,7 +679,7 @@ typedef struct RowCompareExpr
        Expr            xpr;
        RowCompareType rctype;          /* LT LE GE or GT, never EQ or NE */
        List       *opnos;                      /* OID list of pairwise comparison ops */
-       List       *opclasses;          /* OID list of containing operator classes */
+       List       *opfamilies;         /* OID list of containing operator families */
        List       *largs;                      /* the left-hand input arguments */
        List       *rargs;                      /* the right-hand input arguments */
 } RowCompareExpr;
index d39e924..955773d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.128 2006/10/04 00:30:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.129 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -300,11 +300,11 @@ typedef struct RelOptInfo
  *             and indexes, but that created confusion without actually doing anything
  *             useful.  So now we have a separate IndexOptInfo struct for indexes.
  *
- *             classlist[], indexkeys[], and ordering[] have ncolumns entries.
+ *             opfamily[], indexkeys[], and ordering[] have ncolumns entries.
  *             Zeroes in the indexkeys[] array indicate index columns that are
  *             expressions; there is one element in indexprs for each such column.
  *
- *             Note: for historical reasons, the classlist and ordering arrays have
+ *             Note: for historical reasons, the opfamily and ordering arrays have
  *             an extra entry that is always zero.  Some code scans until it sees a
  *             zero entry, rather than looking at ncolumns.
  *
@@ -326,7 +326,7 @@ typedef struct IndexOptInfo
 
        /* index descriptor information */
        int                     ncolumns;               /* number of columns in index */
-       Oid                *classlist;          /* OIDs of operator classes for columns */
+       Oid                *opfamily;           /* OIDs of operator families for columns */
        int                *indexkeys;          /* column numbers of index's keys, or 0 */
        Oid                *ordering;           /* OIDs of sort operators for each column */
        Oid                     relam;                  /* OID of the access method (in pg_am) */
@@ -611,7 +611,9 @@ typedef JoinPath NestPath;
  * A mergejoin path has these fields.
  *
  * path_mergeclauses lists the clauses (in the form of RestrictInfos)
- * that will be used in the merge.
+ * that will be used in the merge.  The parallel lists path_mergefamilies
+ * and path_mergestrategies specify the merge semantics for each clause
+ * (in effect, defining the relevant sort ordering for each clause).
  *
  * Note that the mergeclauses are a subset of the parent relation's
  * restriction-clause list.  Any join clauses that are not mergejoinable
@@ -628,6 +630,8 @@ typedef struct MergePath
 {
        JoinPath        jpath;
        List       *path_mergeclauses;          /* join clauses to be used for merge */
+       List       *path_mergefamilies;         /* OID list of btree opfamilies */
+       List       *path_mergestrategies;       /* integer list of btree strategies */
        List       *outersortkeys;      /* keys for explicit sort, if any */
        List       *innersortkeys;      /* keys for explicit sort, if any */
 } MergePath;
@@ -780,6 +784,7 @@ typedef struct RestrictInfo
        Oid                     mergejoinoperator;              /* copy of clause operator */
        Oid                     left_sortop;    /* leftside sortop needed for mergejoin */
        Oid                     right_sortop;   /* rightside sortop needed for mergejoin */
+       Oid                     mergeopfamily;  /* btree opfamily relating these ops */
 
        /* cache space for mergeclause processing; NIL if not yet set */
        List       *left_pathkey;       /* canonical pathkey for left side */
index f8aebd6..59c2a62 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.72 2006/10/04 00:30:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.73 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,6 +71,8 @@ extern MergePath *create_mergejoin_path(PlannerInfo *root,
                                          List *restrict_clauses,
                                          List *pathkeys,
                                          List *mergeclauses,
+                                         List *mergefamilies,
+                                         List *mergestrategies,
                                          List *outersortkeys,
                                          List *innersortkeys);
 
index 69eb31b..272b321 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.107 2006/10/04 00:30:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.108 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,16 +26,22 @@ typedef enum IOFuncSelector
        IOFunc_send
 } IOFuncSelector;
 
-extern bool op_in_opclass(Oid opno, Oid opclass);
-extern int     get_op_opclass_strategy(Oid opno, Oid opclass);
-extern void get_op_opclass_properties(Oid opno, Oid opclass,
-                                                 int *strategy, Oid *subtype,
+extern bool op_in_opfamily(Oid opno, Oid opfamily);
+extern int     get_op_opfamily_strategy(Oid opno, Oid opfamily);
+extern void get_op_opfamily_properties(Oid opno, Oid opfamily,
+                                                 int *strategy,
+                                                 Oid *lefttype,
+                                                 Oid *righttype,
                                                  bool *recheck);
-extern Oid     get_opclass_member(Oid opclass, Oid subtype, int16 strategy);
+extern Oid     get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
+                                                               int16 strategy);
+extern bool get_op_mergejoin_info(Oid eq_op, Oid *left_sortop,
+                                         Oid *right_sortop, Oid *opfamily);
 extern Oid     get_op_hash_function(Oid opno);
 extern void get_op_btree_interpretation(Oid opno,
-                                                       List **opclasses, List **opstrats);
-extern Oid     get_opclass_proc(Oid opclass, Oid subtype, int16 procnum);
+                                                       List **opfamilies, List **opstrats);
+extern Oid     get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
+                                                         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);
@@ -43,16 +49,12 @@ extern Oid  get_atttype(Oid relid, AttrNumber attnum);
 extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
 extern void get_atttypetypmod(Oid relid, AttrNumber attnum,
                                  Oid *typid, int32 *typmod);
-extern bool opclass_is_btree(Oid opclass);
-extern bool opclass_is_hash(Oid opclass);
-extern bool opclass_is_default(Oid opclass);
+extern Oid     get_opclass_family(Oid opclass);
 extern Oid     get_opclass_input_type(Oid opclass);
 extern RegProcedure get_opcode(Oid opno);
 extern char *get_opname(Oid opno);
 extern void op_input_types(Oid opno, Oid *lefttype, Oid *righttype);
-extern bool op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp);
-extern void op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
-                                         RegProcedure *ltproc, RegProcedure *gtproc);
+extern bool op_mergejoinable(Oid opno);
 extern bool op_hashjoinable(Oid opno);
 extern bool op_strict(Oid opno);
 extern char op_volatile(Oid opno);
index 1f7347c..283c04a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.92 2006/10/04 00:30:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.93 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,16 +165,15 @@ typedef struct RelationData
        Form_pg_index rd_index;         /* pg_index tuple describing this index */
        struct HeapTupleData *rd_indextuple;            /* all of pg_index tuple */
        /* "struct HeapTupleData *" avoids need to include htup.h here  */
-       oidvector  *rd_indclass;        /* extracted pointer to rd_index field */
        Form_pg_am      rd_am;                  /* pg_am tuple for index's AM */
 
        /*
         * index access support info (used only for an index relation)
         *
         * 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.
+        * cached, namely those with lefttype and righttype equal to the opclass's
+        * opcintype.  The arrays are indexed by strategy or support number,
+        * which is a sufficient identifier given that restriction.
         *
         * Note: rd_amcache is available for index AMs to cache private data about
         * an index.  This must be just a cache since it may get reset at any time
@@ -185,6 +184,8 @@ typedef struct RelationData
         */
        MemoryContext rd_indexcxt;      /* private memory cxt for this stuff */
        RelationAmInfo *rd_aminfo;      /* lookup info for funcs found in pg_am */
+       Oid                *rd_opfamily;        /* OIDs of op families for each index col */
+       Oid                *rd_opcintype;       /* OIDs of opclass declared input data types */
        Oid                *rd_operator;        /* OIDs of index operators */
        RegProcedure *rd_support;       /* OIDs of support procedures */
        FmgrInfo   *rd_supportinfo; /* lookup info for support procedures */
index 69a22b3..bb6e35b 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.36 2006/10/04 00:30:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.37 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,6 +160,7 @@ extern Selectivity rowcomparesel(PlannerInfo *root,
                          int varRelid, JoinType jointype);
 
 extern void mergejoinscansel(PlannerInfo *root, Node *clause,
+                                Oid opfamily, int strategy,
                                 Selectivity *leftscan,
                                 Selectivity *rightscan);
 
index 5c84c7e..2305ccd 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.65 2006/07/13 18:01:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.66 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define CONOID                 17
 #define DATABASEOID            18
 #define INDEXRELID             19
-#define INHRELID               20
-#define LANGNAME               21
-#define LANGOID                        22
-#define NAMESPACENAME  23
-#define NAMESPACEOID   24
-#define OPERNAMENSP            25
-#define OPEROID                        26
-#define PROCNAMEARGSNSP 27
-#define PROCOID                        28
-#define RELNAMENSP             29
-#define RELOID                 30
-#define RULERELNAME            31
-#define STATRELATT             32
-#define TYPENAMENSP            33
-#define TYPEOID                        34
+#define LANGNAME               20
+#define LANGOID                        21
+#define NAMESPACENAME  22
+#define NAMESPACEOID   23
+#define OPERNAMENSP            24
+#define OPEROID                        25
+#define OPFAMILYAMNAMENSP 26
+#define OPFAMILYOID            27
+#define PROCNAMEARGSNSP 28
+#define PROCOID                        29
+#define RELNAMENSP             30
+#define RELOID                 31
+#define RULERELNAME            32
+#define STATRELATT             33
+#define TYPENAMENSP            34
+#define TYPEOID                        35
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
index 673bf17..5c8b0e8 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/typcache.h,v 1.12 2006/10/04 00:30:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/typcache.h,v 1.13 2006/12/23 00:43:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,17 +33,19 @@ typedef struct TypeCacheEntry
        Oid                     typrelid;
 
        /*
-        * Information obtained from opclass entries
+        * Information obtained from opfamily entries
         *
         * These will be InvalidOid if no match could be found, or if the
         * information hasn't yet been requested.
         */
-       Oid                     btree_opc;              /* OID of the default btree opclass */
-       Oid                     hash_opc;               /* OID of the default hash opclass */
-       Oid                     eq_opr;                 /* OID of the equality operator */
-       Oid                     lt_opr;                 /* OID of the less-than operator */
-       Oid                     gt_opr;                 /* OID of the greater-than operator */
-       Oid                     cmp_proc;               /* OID of the btree comparison function */
+       Oid                     btree_opf;              /* the default btree opclass' family */
+       Oid                     btree_opintype; /* the default btree opclass' opcintype */
+       Oid                     hash_opf;               /* the default hash opclass' family */
+       Oid                     hash_opintype;  /* the default hash opclass' opcintype */
+       Oid                     eq_opr;                 /* the equality operator */
+       Oid                     lt_opr;                 /* the less-than operator */
+       Oid                     gt_opr;                 /* the greater-than operator */
+       Oid                     cmp_proc;               /* the btree comparison function */
 
        /*
         * Pre-set-up fmgr call info for the equality operator and the btree
@@ -71,6 +73,7 @@ typedef struct TypeCacheEntry
 #define TYPECACHE_EQ_OPR_FINFO         0x0010
 #define TYPECACHE_CMP_PROC_FINFO       0x0020
 #define TYPECACHE_TUPDESC                      0x0040
+#define TYPECACHE_BTREE_OPFAMILY       0x0080
 
 extern TypeCacheEntry *lookup_type_cache(Oid type_id, int flags);
 
index 445f41f..cc82b12 100644 (file)
@@ -137,20 +137,36 @@ WHERE     amcostestimate != 0 AND
 ------+----------------
 (0 rows)
 
-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);
- ctid | amopclaid 
+SELECT ctid, amoptions 
+FROM   pg_catalog.pg_am fk 
+WHERE  amoptions != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amoptions);
+ ctid | amoptions 
 ------+-----------
 (0 rows)
 
-SELECT ctid, amopsubtype 
+SELECT ctid, amopfamily 
 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 
-------+-------------
+WHERE  amopfamily != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opfamily pk WHERE pk.oid = fk.amopfamily);
+ ctid | amopfamily 
+------+------------
+(0 rows)
+
+SELECT ctid, amoplefttype 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amoplefttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amoplefttype);
+ ctid | amoplefttype 
+------+--------------
+(0 rows)
+
+SELECT ctid, amoprighttype 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amoprighttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amoprighttype);
+ ctid | amoprighttype 
+------+---------------
 (0 rows)
 
 SELECT ctid, amopopr 
@@ -161,20 +177,36 @@ WHERE     amopopr != 0 AND
 ------+---------
 (0 rows)
 
-SELECT ctid, amopclaid 
+SELECT ctid, amopmethod 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amopmethod != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.amopmethod);
+ ctid | amopmethod 
+------+------------
+(0 rows)
+
+SELECT ctid, amprocfamily 
 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);
- ctid | amopclaid 
-------+-----------
+WHERE  amprocfamily != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opfamily pk WHERE pk.oid = fk.amprocfamily);
+ ctid | amprocfamily 
+------+--------------
 (0 rows)
 
-SELECT ctid, amprocsubtype 
+SELECT ctid, amproclefttype 
 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 
-------+---------------
+WHERE  amproclefttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amproclefttype);
+ ctid | amproclefttype 
+------+----------------
+(0 rows)
+
+SELECT ctid, amprocrighttype 
+FROM   pg_catalog.pg_amproc fk 
+WHERE  amprocrighttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amprocrighttype);
+ ctid | amprocrighttype 
+------+-----------------
 (0 rows)
 
 SELECT ctid, amproc 
@@ -241,6 +273,14 @@ WHERE      reltype != 0 AND
 ------+---------
 (0 rows)
 
+SELECT ctid, relowner 
+FROM   pg_catalog.pg_class fk 
+WHERE  relowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.relowner);
+ ctid | relowner 
+------+----------
+(0 rows)
+
 SELECT ctid, relam 
 FROM   pg_catalog.pg_class fk 
 WHERE  relam != 0 AND 
@@ -297,6 +337,14 @@ WHERE      connamespace != 0 AND
 ------+--------------
 (0 rows)
 
+SELECT ctid, conowner 
+FROM   pg_catalog.pg_conversion fk 
+WHERE  conowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.conowner);
+ ctid | conowner 
+------+----------
+(0 rows)
+
 SELECT ctid, conproc 
 FROM   pg_catalog.pg_conversion fk 
 WHERE  conproc != 0 AND 
@@ -305,6 +353,14 @@ WHERE      conproc != 0 AND
 ------+---------
 (0 rows)
 
+SELECT ctid, datdba 
+FROM   pg_catalog.pg_database fk 
+WHERE  datdba != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.datdba);
+ ctid | datdba 
+------+--------
+(0 rows)
+
 SELECT ctid, dattablespace 
 FROM   pg_catalog.pg_database fk 
 WHERE  dattablespace != 0 AND 
@@ -361,12 +417,20 @@ WHERE     lanvalidator != 0 AND
 ------+--------------
 (0 rows)
 
-SELECT ctid, opcamid 
+SELECT ctid, nspowner 
+FROM   pg_catalog.pg_namespace fk 
+WHERE  nspowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.nspowner);
+ ctid | nspowner 
+------+----------
+(0 rows)
+
+SELECT ctid, opcmethod 
 FROM   pg_catalog.pg_opclass fk 
-WHERE  opcamid != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.opcamid);
- ctid | opcami
-------+---------
+WHERE  opcmethod != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.opcmethod);
+ ctid | opcmetho
+------+-----------
 (0 rows)
 
 SELECT ctid, opcnamespace 
@@ -377,6 +441,22 @@ WHERE      opcnamespace != 0 AND
 ------+--------------
 (0 rows)
 
+SELECT ctid, opcowner 
+FROM   pg_catalog.pg_opclass fk 
+WHERE  opcowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.opcowner);
+ ctid | opcowner 
+------+----------
+(0 rows)
+
+SELECT ctid, opcfamily 
+FROM   pg_catalog.pg_opclass fk 
+WHERE  opcfamily != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opfamily pk WHERE pk.oid = fk.opcfamily);
+ ctid | opcfamily 
+------+-----------
+(0 rows)
+
 SELECT ctid, opcintype 
 FROM   pg_catalog.pg_opclass fk 
 WHERE  opcintype != 0 AND 
@@ -385,6 +465,14 @@ WHERE      opcintype != 0 AND
 ------+-----------
 (0 rows)
 
+SELECT ctid, opckeytype 
+FROM   pg_catalog.pg_opclass fk 
+WHERE  opckeytype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.opckeytype);
+ ctid | opckeytype 
+------+------------
+(0 rows)
+
 SELECT ctid, oprnamespace 
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprnamespace != 0 AND 
@@ -393,6 +481,14 @@ WHERE      oprnamespace != 0 AND
 ------+--------------
 (0 rows)
 
+SELECT ctid, oprowner 
+FROM   pg_catalog.pg_operator fk 
+WHERE  oprowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.oprowner);
+ ctid | oprowner 
+------+----------
+(0 rows)
+
 SELECT ctid, oprleft 
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprleft != 0 AND 
@@ -433,38 +529,6 @@ WHERE      oprnegate != 0 AND
 ------+-----------
 (0 rows)
 
-SELECT ctid, oprlsortop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprlsortop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprlsortop);
- ctid | oprlsortop 
-------+------------
-(0 rows)
-
-SELECT ctid, oprrsortop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprrsortop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprrsortop);
- ctid | oprrsortop 
-------+------------
-(0 rows)
-
-SELECT ctid, oprltcmpop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprltcmpop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprltcmpop);
- ctid | oprltcmpop 
-------+------------
-(0 rows)
-
-SELECT ctid, oprgtcmpop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprgtcmpop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprgtcmpop);
- ctid | oprgtcmpop 
-------+------------
-(0 rows)
-
 SELECT ctid, oprcode 
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprcode != 0 AND 
@@ -489,6 +553,30 @@ WHERE      oprjoin != 0 AND
 ------+---------
 (0 rows)
 
+SELECT ctid, opfmethod 
+FROM   pg_catalog.pg_opfamily fk 
+WHERE  opfmethod != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.opfmethod);
+ ctid | opfmethod 
+------+-----------
+(0 rows)
+
+SELECT ctid, opfnamespace 
+FROM   pg_catalog.pg_opfamily fk 
+WHERE  opfnamespace != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.opfnamespace);
+ ctid | opfnamespace 
+------+--------------
+(0 rows)
+
+SELECT ctid, opfowner 
+FROM   pg_catalog.pg_opfamily fk 
+WHERE  opfowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.opfowner);
+ ctid | opfowner 
+------+----------
+(0 rows)
+
 SELECT ctid, pronamespace 
 FROM   pg_catalog.pg_proc fk 
 WHERE  pronamespace != 0 AND 
@@ -497,6 +585,14 @@ WHERE      pronamespace != 0 AND
 ------+--------------
 (0 rows)
 
+SELECT ctid, proowner 
+FROM   pg_catalog.pg_proc fk 
+WHERE  proowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.proowner);
+ ctid | proowner 
+------+----------
+(0 rows)
+
 SELECT ctid, prolang 
 FROM   pg_catalog.pg_proc fk 
 WHERE  prolang != 0 AND 
@@ -521,6 +617,22 @@ WHERE      ev_class != 0 AND
 ------+----------
 (0 rows)
 
+SELECT ctid, refclassid 
+FROM   pg_catalog.pg_shdepend fk 
+WHERE  refclassid != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.refclassid);
+ ctid | refclassid 
+------+------------
+(0 rows)
+
+SELECT ctid, classoid 
+FROM   pg_catalog.pg_shdescription fk 
+WHERE  classoid != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.classoid);
+ ctid | classoid 
+------+----------
+(0 rows)
+
 SELECT ctid, starelid 
 FROM   pg_catalog.pg_statistic fk 
 WHERE  starelid != 0 AND 
@@ -553,6 +665,14 @@ WHERE      staop3 != 0 AND
 ------+--------
 (0 rows)
 
+SELECT ctid, spcowner 
+FROM   pg_catalog.pg_tablespace fk 
+WHERE  spcowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.spcowner);
+ ctid | spcowner 
+------+----------
+(0 rows)
+
 SELECT ctid, tgrelid 
 FROM   pg_catalog.pg_trigger fk 
 WHERE  tgrelid != 0 AND 
@@ -577,6 +697,14 @@ WHERE      typnamespace != 0 AND
 ------+--------------
 (0 rows)
 
+SELECT ctid, typowner 
+FROM   pg_catalog.pg_type fk 
+WHERE  typowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.typowner);
+ ctid | typowner 
+------+----------
+(0 rows)
+
 SELECT ctid, typrelid 
 FROM   pg_catalog.pg_type fk 
 WHERE  typrelid != 0 AND 
index e455538..a0e9483 100644 (file)
@@ -1,7 +1,8 @@
 --
 -- OPR_SANITY
 -- Sanity checks for common errors in making operator/procedure system tables:
--- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
+-- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am,
+-- pg_amop, pg_amproc, pg_opclass, pg_opfamily.
 --
 -- None of the SELECTs here should ever find any matching entries,
 -- so the expected output is easy to maintain ;-).
@@ -374,158 +375,58 @@ WHERE p1.oprnegate = p2.oid AND
 -----+---------+-----+---------
 (0 rows)
 
--- Look for mergejoin operators that don't match their links.
--- An lsortop/rsortop link leads from an '=' operator to the
--- sort operator ('<' operator) that's appropriate for
--- its left-side or right-side data type.
--- An ltcmpop/gtcmpop link leads from an '=' operator to the
--- '<' or '>' operator of the same input datatypes.
--- (If the '=' operator has identical L and R input datatypes,
--- then lsortop, rsortop, and ltcmpop are all the same operator.)
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprlsortop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprleft != p2.oprleft OR
-     p1.oprleft != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
- oid | oprcode | oid | oprcode 
------+---------+-----+---------
-(0 rows)
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprrsortop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprright != p2.oprleft OR
-     p1.oprright != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
- oid | oprcode | oid | oprcode 
------+---------+-----+---------
-(0 rows)
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprltcmpop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprleft != p2.oprleft OR
-     p1.oprright != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
- oid | oprcode | oid | oprcode 
------+---------+-----+---------
-(0 rows)
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprgtcmpop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('>', '~>~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprleft != p2.oprleft OR
-     p1.oprright != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
- oid | oprcode | oid | oprcode 
------+---------+-----+---------
-(0 rows)
-
--- Make sure all four links are specified if any are.
-SELECT p1.oid, p1.oprcode
-FROM pg_operator AS p1
-WHERE NOT ((oprlsortop = 0 AND oprrsortop = 0 AND
-            oprltcmpop = 0 AND oprgtcmpop = 0) OR
-           (oprlsortop != 0 AND oprrsortop != 0 AND
-            oprltcmpop != 0 AND oprgtcmpop != 0));
- oid | oprcode 
------+---------
-(0 rows)
-
--- A mergejoinable = operator must have a commutator (usually itself).
+-- A mergejoinable or hashjoinable operator must be binary, must return
+-- boolean, and must have a commutator (itself, unless it's a cross-type
+-- operator).
 SELECT p1.oid, p1.oprname FROM pg_operator AS p1
-WHERE p1.oprlsortop != 0 AND
-      p1.oprcom = 0;
+WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
+    (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
  oid | oprname 
 -----+---------
 (0 rows)
 
--- Mergejoinable operators across datatypes must come in closed sets, that
--- is if you provide int2 = int4 and int4 = int8 then you must also provide
--- int2 = int8 (and commutators of all these).  This is necessary because
--- the planner tries to deduce additional qual clauses from transitivity
--- of mergejoinable operators.  If there are clauses int2var = int4var and
--- int4var = int8var, the planner will deduce int2var = int8var ... and it
--- had better have a way to represent it.
-SELECT p1.oid, p2.oid FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprlsortop != p1.oprrsortop AND
-      p1.oprrsortop = p2.oprlsortop AND
-      p2.oprlsortop != p2.oprrsortop AND
-      NOT EXISTS (SELECT 1 FROM pg_operator p3 WHERE
-      p3.oprlsortop = p1.oprlsortop AND p3.oprrsortop = p2.oprrsortop);
- oid | oid 
------+-----
-(0 rows)
-
--- Hashing only works on simple equality operators "type = sametype",
--- since the hash itself depends on the bitwise representation of the type.
--- Check that allegedly hashable operators look like they might be "=".
+-- Mergejoinable operators should appear as equality members of btree index
+-- opfamilies.
 SELECT p1.oid, p1.oprname
 FROM pg_operator AS p1
-WHERE p1.oprcanhash AND NOT
-    (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND
-     p1.oprleft = p1.oprright AND p1.oprname IN ('=', '~=~') AND
-     p1.oprcom = p1.oid);
+WHERE p1.oprcanmerge AND NOT EXISTS
+  (SELECT 1 FROM pg_amop
+   WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+         amopopr = p1.oid AND amopstrategy = 3);
  oid | oprname 
 -----+---------
 (0 rows)
 
--- In 6.5 we accepted hashable array equality operators when the array element
--- type is hashable.  However, what we actually need to make hashjoin work on
--- an array is a hashable element type *and* no padding between elements in
--- the array storage (or, perhaps, guaranteed-zero padding).  Currently,
--- since the padding code in arrayfuncs.c is pretty bogus, it seems safest
--- to just forbid hashjoin on array equality ops.
--- This should be reconsidered someday.
--- -- Look for array equality operators that are hashable when the underlying
--- -- type is not, or vice versa.  This is presumably bogus.
--- 
--- SELECT p1.oid, p1.oprcanhash, p2.oid, p2.oprcanhash, t1.typname, t2.typname
--- FROM pg_operator AS p1, pg_operator AS p2, pg_type AS t1, pg_type AS t2
--- WHERE p1.oprname = '=' AND p1.oprleft = p1.oprright AND 
---     p2.oprname = '=' AND p2.oprleft = p2.oprright AND
---     p1.oprleft = t1.oid AND p2.oprleft = t2.oid AND t1.typelem = t2.oid AND
---     p1.oprcanhash != p2.oprcanhash;
--- Substitute check: forbid hashable array ops, period.
-SELECT p1.oid, p1.oprname
-FROM pg_operator AS p1, pg_proc AS p2
-WHERE p1.oprcanhash AND p1.oprcode = p2.oid AND p2.proname = 'array_eq';
- oid | oprname 
------+---------
+-- And the converse.
+SELECT p1.oid, p1.oprname, p.amopfamily
+FROM pg_operator AS p1, pg_amop p
+WHERE amopopr = p1.oid
+  AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+  AND amopstrategy = 3
+  AND NOT p1.oprcanmerge;
+ oid | oprname | amopfamily 
+-----+---------+------------
 (0 rows)
 
--- Hashable operators should appear as members of hash index opclasses.
+-- Hashable operators should appear as members of hash index opfamilies.
 SELECT p1.oid, p1.oprname
 FROM pg_operator AS p1
 WHERE p1.oprcanhash AND NOT EXISTS
-  (SELECT 1 FROM pg_opclass op JOIN pg_amop p ON op.oid = amopclaid
-   WHERE opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
-         amopopr = p1.oid);
+  (SELECT 1 FROM pg_amop
+   WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
+         amopopr = p1.oid AND amopstrategy = 1);
  oid | oprname 
 -----+---------
 (0 rows)
 
 -- And the converse.
-SELECT p1.oid, p1.oprname, op.opcname
-FROM pg_operator AS p1, pg_opclass op, pg_amop p
-WHERE amopopr = p1.oid AND amopclaid = op.oid
-  AND opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash')
+SELECT p1.oid, p1.oprname, p.amopfamily
+FROM pg_operator AS p1, pg_amop p
+WHERE amopopr = p1.oid
+  AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
   AND NOT p1.oprcanhash;
- oid | oprname | opcname 
------+---------+---------
+ oid | oprname | amopfamily 
+-----+---------+------------
 (0 rows)
 
 -- Check that each operator defined in pg_operator matches its oprcode entry
@@ -571,7 +472,7 @@ WHERE p1.oprcode = p2.oid AND
 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
 FROM pg_operator AS p1, pg_proc AS p2
 WHERE p1.oprcode = p2.oid AND
-    (p1.oprlsortop != 0 OR p1.oprcanhash) AND
+    (p1.oprcanmerge OR p1.oprcanhash) AND
     p2.provolatile = 'v';
  oid | oprname | oid | proname 
 -----+---------+-----+---------
@@ -720,14 +621,15 @@ WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
 ----------+-----
 (0 rows)
 
--- Check operator is a suitable btree opclass member
+-- Check operator is a suitable btree opfamily member
 SELECT a.aggfnoid::oid, o.oid
 FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
 WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
-    NOT EXISTS(SELECT 1 FROM pg_amop ao, pg_opclass oc
-               WHERE amopclaid = oc.oid AND amopsubtype = 0
-                     AND amopopr = o.oid AND opcamid = 403
-                     AND opcintype = o.oprleft AND opcdefault);
+    NOT EXISTS(SELECT 1 FROM pg_amop
+               WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+                     AND amopopr = o.oid
+                     AND amoplefttype = o.oprleft
+                     AND amoprighttype = o.oprright);
  aggfnoid | oid 
 ----------+-----
 (0 rows)
@@ -735,31 +637,50 @@ WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
 -- Check correspondence of btree strategies and names
 SELECT DISTINCT proname, oprname, amopstrategy
 FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p,
-     pg_amop as ao, pg_opclass oc
+     pg_amop as ao
 WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
-    amopclaid = oc.oid AND amopopr = o.oid AND opcamid = 403
-ORDER BY 1;
+    amopopr = o.oid AND
+    amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+ORDER BY 1, 2;
  proname | oprname | amopstrategy 
 ---------+---------+--------------
  max     | >       |            5
  min     | <       |            1
 (2 rows)
 
+-- **************** pg_opfamily ****************
+-- Look for illegal values in pg_opfamily fields
+SELECT p1.oid
+FROM pg_opfamily as p1
+WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
+ oid 
+-----
+(0 rows)
+
 -- **************** pg_opclass ****************
 -- Look for illegal values in pg_opclass fields
 SELECT p1.oid
-FROM pg_opclass as p1
-WHERE p1.opcamid = 0 OR p1.opcintype = 0;
+FROM pg_opclass AS p1
+WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
+    OR p1.opcintype = 0;
  oid 
 -----
 (0 rows)
 
+-- opcmethod must match owning opfamily's opfmethod
+SELECT p1.oid, p2.oid
+FROM pg_opclass AS p1, pg_opfamily AS p2
+WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
+ oid | oid 
+-----+-----
+(0 rows)
+
 -- There should not be multiple entries in pg_opclass with opcdefault true
--- and the same opcamid/opcintype combination.
+-- and the same opcmethod/opcintype combination.
 SELECT p1.oid, p2.oid
 FROM pg_opclass AS p1, pg_opclass AS p2
 WHERE p1.oid != p2.oid AND
-    p1.opcamid = p2.opcamid AND p1.opcintype = p2.opcintype AND
+    p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
     p1.opcdefault AND p2.opcdefault;
  oid | oid 
 -----+-----
@@ -767,181 +688,221 @@ WHERE p1.oid != p2.oid AND
 
 -- **************** pg_amop ****************
 -- Look for illegal values in pg_amop fields
-SELECT p1.amopclaid, p1.amopstrategy
+SELECT p1.amopfamily, p1.amopstrategy
 FROM pg_amop as p1
-WHERE p1.amopclaid = 0 OR p1.amopstrategy <= 0 OR p1.amopopr = 0;
- amopclaid | amopstrategy 
------------+--------------
+WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
+    OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
+ amopfamily | amopstrategy 
+------------+--------------
+(0 rows)
+
+-- amoplefttype/amoprighttype must match the operator
+SELECT p1.oid, p2.oid
+FROM pg_amop AS p1, pg_operator AS p2
+WHERE p1.amopopr = p2.oid AND NOT
+    (p1.amoplefttype = p2.oprleft AND p1.amoprighttype = p2.oprright);
+ oid | oid 
+-----+-----
+(0 rows)
+
+-- amopmethod must match owning opfamily's opfmethod
+SELECT p1.oid, p2.oid
+FROM pg_amop AS p1, pg_opfamily AS p2
+WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
+ oid | oid 
+-----+-----
 (0 rows)
 
 -- Cross-check amopstrategy index against parent AM
-SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.amname
-FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3
-WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.amname
+FROM pg_amop AS p1, pg_am AS p2
+WHERE p1.amopmethod = p2.oid AND
     p1.amopstrategy > p2.amstrategies AND p2.amstrategies <> 0;
- amopclaid | amopopr | oid | amname 
------------+---------+-----+--------
+ amopfamily | amopopr | oid | amname 
+------------+---------+-----+--------
 (0 rows)
 
 -- 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.
+-- as AM expects for each datatype combination supported by the opfamily.
 -- We can't check this for AMs with variable strategy sets.
-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
+SELECT p1.amname, p2.amoplefttype, p2.amoprighttype
+FROM pg_am AS p1, pg_amop AS p2
+WHERE p2.amopmethod = p1.oid AND
     p1.amstrategies <> 0 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 
------+--------+-----+---------+-------------
+    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
+                        WHERE p3.amopfamily = p2.amopfamily AND
+                              p3.amoplefttype = p2.amoplefttype AND
+                              p3.amoprighttype = p2.amoprighttype);
+ amname | amoplefttype | amoprighttype 
+--------+--------------+---------------
 (0 rows)
 
 -- Check that amopopr points at a reasonable-looking operator, ie a binary
 -- operator yielding boolean.
-SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
+SELECT p1.amopfamily, 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);
- amopclaid | amopopr | oid | oprname 
------------+---------+-----+---------
+ amopfamily | 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
+-- swapping two operators within a family.
+SELECT DISTINCT amopmethod, amopstrategy, oprname
+FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.oid
 ORDER BY 1, 2, 3;
opcamid | amopstrategy | oprname 
----------+--------------+---------
-     403 |            1 | <
-     403 |            1 | ~<~
-     403 |            2 | <=
-     403 |            2 | ~<=~
-     403 |            3 | =
-     403 |            3 | ~=~
-     403 |            4 | >=
-     403 |            4 | ~>=~
-     403 |            5 | >
-     403 |            5 | ~>~
-     405 |            1 | =
-     405 |            1 | ~=~
-     783 |            1 | <<
-     783 |            2 | &<
-     783 |            3 | &&
-     783 |            4 | &>
-     783 |            5 | >>
-     783 |            6 | ~=
-     783 |            7 | @>
-     783 |            8 | <@
-     783 |            9 | &<|
-     783 |           10 | <<|
-     783 |           11 | |>>
-     783 |           12 | |&>
-     783 |           13 | ~
-     783 |           14 | @
-    2742 |            1 | &&
-    2742 |            2 | @>
-    2742 |            3 | <@
-    2742 |            4 | =
amopmethod | amopstrategy | oprname 
+------------+--------------+---------
+        403 |            1 | <
+        403 |            1 | ~<~
+        403 |            2 | <=
+        403 |            2 | ~<=~
+        403 |            3 | =
+        403 |            3 | ~=~
+        403 |            4 | >=
+        403 |            4 | ~>=~
+        403 |            5 | >
+        403 |            5 | ~>~
+        405 |            1 | =
+        405 |            1 | ~=~
+        783 |            1 | <<
+        783 |            2 | &<
+        783 |            3 | &&
+        783 |            4 | &>
+        783 |            5 | >>
+        783 |            6 | ~=
+        783 |            7 | @>
+        783 |            8 | <@
+        783 |            9 | &<|
+        783 |           10 | <<|
+        783 |           11 | |>>
+        783 |           12 | |&>
+        783 |           13 | ~
+        783 |           14 | @
+       2742 |            1 | &&
+       2742 |            2 | @>
+       2742 |            3 | <@
+       2742 |            4 | =
 (30 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.
-SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
 FROM pg_amop AS p1, pg_operator AS p2
 WHERE p1.amopopr = p2.oid AND
     (p2.oprrest = 0 OR p2.oprjoin = 0);
- amopclaid | amopopr | oid | oprname 
------------+---------+-----+---------
-(0 rows)
-
--- Check that operator input types match the opclass
--- For 8.0, 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
-    p1.amopsubtype = 0 AND
-    p2.oprleft != p2.oprright;
- amopclaid | amopopr | oid | oprname | opcname 
------------+---------+-----+---------+---------
+ amopfamily | amopopr | oid | oprname 
+------------+---------+-----+---------
 (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 
------------+---------+-----+---------+---------
+-- Check that each opclass in an opfamily has associated operators, that is
+-- ones whose oprleft matches opcintype (possibly by coercion).
+SELECT p1.opcname, p1.opcfamily
+FROM pg_opclass AS p1
+WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
+                 WHERE p2.amopfamily = p1.opcfamily
+                   AND binary_coercible(p1.opcintype, p2.amoplefttype));
+ opcname | opcfamily 
+---------+-----------
 (0 rows)
 
 -- Operators that are primary members of opclasses must be immutable (else
 -- it suggests that the index ordering isn't fixed).  Operators that are
 -- cross-type members need only be stable, since they are just shorthands
 -- for index probe queries.
-SELECT p1.amopclaid, p1.amopopr, p2.oprname, p3.prosrc
+SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
 FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
 WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
-    p1.amopsubtype = 0 AND
+    p1.amoplefttype = p1.amoprighttype AND
     p3.provolatile != 'i';
- amopclaid | amopopr | oprname | prosrc 
------------+---------+---------+--------
+ amopfamily | amopopr | oprname | prosrc 
+------------+---------+---------+--------
 (0 rows)
 
-SELECT p1.amopclaid, p1.amopopr, p2.oprname, p3.prosrc
+SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
 FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
 WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
-    p1.amopsubtype != 0 AND
+    p1.amoplefttype != p1.amoprighttype AND
     p3.provolatile = 'v';
- amopclaid | amopopr | oprname | prosrc 
------------+---------+---------+--------
+ amopfamily | amopopr | oprname | prosrc 
+------------+---------+---------+--------
+(0 rows)
+
+-- Multiple-datatype btree opclasses should provide closed sets of equality
+-- operators; that is if you provide int2 = int4 and int4 = int8 then you
+-- must also provide int2 = int8 (and commutators of all these).  This is
+-- necessary because the planner tries to deduce additional qual clauses from
+-- transitivity of mergejoinable operators.  If there are clauses
+-- int2var = int4var and int4var = int8var, the planner will deduce
+-- int2var = int8var ... and it had better have a way to represent it.
+-- check commutative closure
+SELECT p1.amoplefttype, p1.amoprighttype
+FROM pg_amop AS p1
+WHERE p1.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+    p1.amopstrategy = 3 AND
+    p1.amoplefttype != p1.amoprighttype AND
+    NOT EXISTS(SELECT 1 FROM pg_amop p2 WHERE
+                 p2.amopfamily = p1.amopfamily AND
+                 p2.amoplefttype = p1.amoprighttype AND
+                 p2.amoprighttype = p1.amoplefttype AND
+                 p2.amopstrategy = 3);
+ amoplefttype | amoprighttype 
+--------------+---------------
+(0 rows)
+
+-- check transitive closure
+SELECT p1.amoplefttype, p1.amoprighttype, p2.amoprighttype
+FROM pg_amop AS p1, pg_amop AS p2
+WHERE p1.amopfamily = p2.amopfamily AND
+    p1.amoprighttype = p2.amoplefttype AND
+    p1.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+    p2.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+    p1.amopstrategy = 3 AND p2.amopstrategy = 3 AND
+    p1.amoplefttype != p1.amoprighttype AND
+    p2.amoplefttype != p2.amoprighttype AND
+    NOT EXISTS(SELECT 1 FROM pg_amop p3 WHERE
+                 p3.amopfamily = p1.amopfamily AND
+                 p3.amoplefttype = p1.amoplefttype AND
+                 p3.amoprighttype = p2.amoprighttype AND
+                 p3.amopstrategy = 3);
+ amoplefttype | amoprighttype | amoprighttype 
+--------------+---------------+---------------
 (0 rows)
 
 -- **************** pg_amproc ****************
 -- Look for illegal values in pg_amproc fields
-SELECT p1.amopclaid, p1.amprocnum
+SELECT p1.amprocfamily, p1.amprocnum
 FROM pg_amproc as p1
-WHERE p1.amopclaid = 0 OR p1.amprocnum <= 0 OR p1.amproc = 0;
- amopclaid | amprocnum 
------------+-----------
+WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
+    OR p1.amprocnum < 1 OR p1.amproc = 0;
+ amprocfamily | amprocnum 
+--------------+-----------
 (0 rows)
 
 -- Cross-check amprocnum index against parent AM
-SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
-FROM pg_amproc AS p1, pg_am AS p2, pg_opclass AS p3
-WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
+SELECT p1.amprocfamily, p1.amprocnum, p2.oid, p2.amname
+FROM pg_amproc AS p1, pg_am AS p2, pg_opfamily AS p3
+WHERE p1.amprocfamily = p3.oid AND p3.opfmethod = p2.oid AND
     p1.amprocnum > p2.amsupport;
- amopclaid | amprocnum | oid | amname 
------------+-----------+-----+--------
+ amprocfamily | amprocnum | oid | amname 
+--------------+-----------+-----+--------
 (0 rows)
 
 -- Detect missing pg_amproc entries: should have as many support functions
--- 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
+-- as AM expects for each datatype combination supported by the opfamily.
+SELECT p1.amname, p2.opfname, p3.amproclefttype, p3.amprocrighttype
+FROM pg_am AS p1, pg_opfamily AS p2, pg_amproc AS p3
+WHERE p2.opfmethod = p1.oid AND p3.amprocfamily = 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 
------+--------+-----+---------+---------------
+                     WHERE p4.amprocfamily = p2.oid AND
+                           p4.amproclefttype = p3.amproclefttype AND
+                           p4.amprocrighttype = p3.amprocrighttype);
+ amname | opfname | amproclefttype | amprocrighttype 
+--------+---------+----------------+-----------------
 (0 rows)
 
 -- Unfortunately, we can't check the amproc link very well because the
@@ -950,101 +911,79 @@ WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
 -- We can check that all the referenced instances of the same support
 -- routine number take the same number of parameters, but that's about it
 -- for a general check...
-SELECT p1.amopclaid, p1.amprocnum,
+SELECT p1.amprocfamily, p1.amprocnum,
        p2.oid, p2.proname,
-       p3.opcname,
-       p4.amopclaid, p4.amprocnum,
+       p3.opfname,
+       p4.amprocfamily, p4.amprocnum,
        p5.oid, p5.proname,
-       p6.opcname
-FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3,
-     pg_amproc AS p4, pg_proc AS p5, pg_opclass AS p6
-WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
-    p3.opcamid = p6.opcamid AND p1.amprocnum = p4.amprocnum AND
+       p6.opfname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opfamily AS p3,
+     pg_amproc AS p4, pg_proc AS p5, pg_opfamily AS p6
+WHERE p1.amprocfamily = p3.oid AND p4.amprocfamily = p6.oid AND
+    p3.opfmethod = p6.opfmethod AND p1.amprocnum = p4.amprocnum AND
     p1.amproc = p2.oid AND p4.amproc = p5.oid AND
     (p2.proretset OR p5.proretset OR p2.pronargs != p5.pronargs);
- amopclaid | amprocnum | oid | proname | opcname | amopclaid | amprocnum | oid | proname | opcname 
------------+-----------+-----+---------+---------+-----------+-----------+-----+---------+---------
+ amprocfamily | amprocnum | oid | proname | opfname | amprocfamily | amprocnum | oid | proname | opfname 
+--------------+-----------+-----+---------+---------+--------------+-----------+-----+---------+---------
 (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 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
-     OR prorettype != 23
-     OR pronargs != 2
-     OR NOT binary_coercible(opcintype, proargtypes[0])
-     OR proargtypes[0] != proargtypes[1]);
- amopclaid | amprocnum | oid | proname | opcname 
------------+-----------+-----+---------+---------
-(0 rows)
-
-SELECT p1.amopclaid, p1.amprocnum,
+-- must be of the form cmp(lefttype, righttype) returns int4.
+SELECT p1.amprocfamily, 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
+       p3.opfname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opfamily AS p3
+WHERE p3.opfmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+    AND p1.amprocfamily = p3.oid AND p1.amproc = p2.oid AND
+    (amprocnum != 1
      OR proretset
-     OR prorettype != 23
+     OR prorettype != 'int4'::regtype
      OR pronargs != 2
-     OR NOT binary_coercible(opcintype, proargtypes[0])
-     OR proargtypes[1] != amprocsubtype);
- amopclaid | amprocnum | oid | proname | opcname 
------------+-----------+-----+---------+---------
+     OR proargtypes[0] != amproclefttype
+     OR proargtypes[1] != amprocrighttype);
+ amprocfamily | amprocnum | oid | proname | opfname 
+--------------+-----------+-----+---------+---------
 (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
--- enough cases where that fails that I'll just leave out the check for now.
-SELECT p1.amopclaid, p1.amprocnum,
+-- of the form hash(lefttype) returns int4.  There are several cases where
+-- we cheat and use a hash function that is physically compatible with the
+-- datatype even though there's no cast, so for now we can't check that.
+SELECT p1.amprocfamily, 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 = 'hash')
-    AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
-    (opckeytype != 0
-     OR amprocnum != 1
+       p3.opfname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opfamily AS p3
+WHERE p3.opfmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
+    AND p1.amprocfamily = p3.oid AND p1.amproc = p2.oid AND
+    (amprocnum != 1
      OR proretset
-     OR prorettype != 23
+     OR prorettype != 'int4'::regtype
      OR pronargs != 1
---   OR NOT physically_coercible(opcintype, proargtypes[0])
-);
- amopclaid | amprocnum | oid | proname | opcname 
------------+-----------+-----+---------+---------
+--   OR NOT physically_coercible(amproclefttype, proargtypes[0])
+     OR amproclefttype != amprocrighttype);
+ amprocfamily | amprocnum | oid | proname | opfname 
+--------------+-----------+-----+---------+---------
 (0 rows)
 
--- Support routines that are primary members of opclasses must be immutable
+-- Support routines that are primary members of opfamilies must be immutable
 -- (else it suggests that the index ordering isn't fixed).  But cross-type
 -- members need only be stable, since they are just shorthands
 -- for index probe queries.
-SELECT p1.amopclaid, p1.amproc, p2.prosrc
+SELECT p1.amprocfamily, p1.amproc, p2.prosrc
 FROM pg_amproc AS p1, pg_proc AS p2
 WHERE p1.amproc = p2.oid AND
-    p1.amprocsubtype = 0 AND
+    p1.amproclefttype = p1.amprocrighttype AND
     p2.provolatile != 'i';
- amopclaid | amproc | prosrc 
------------+--------+--------
+ amprocfamily | amproc | prosrc 
+--------------+--------+--------
 (0 rows)
 
-SELECT p1.amopclaid, p1.amproc, p2.prosrc
+SELECT p1.amprocfamily, p1.amproc, p2.prosrc
 FROM pg_amproc AS p1, pg_proc AS p2
 WHERE p1.amproc = p2.oid AND
-    p1.amprocsubtype != 0 AND
+    p1.amproclefttype != p1.amprocrighttype AND
     p2.provolatile = 'v';
- amopclaid | amproc | prosrc 
------------+--------+--------
+ amprocfamily | amproc | prosrc 
+--------------+--------+--------
 (0 rows)
 
index 5b4d955..10687f5 100644 (file)
@@ -203,7 +203,7 @@ select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
 ERROR:  could not determine interpretation of row comparison operator ~~
 LINE 1: select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
                                 ^
-HINT:  Row comparison operators must be associated with btree operator classes.
+HINT:  Row comparison operators must be associated with btree operator families.
 -- Check row comparison with a subselect
 select unique1, unique2 from tenk1
 where (unique1, unique2) < any (select ten, ten from tenk1 where hundred < 3);
index d2c68e8..5e6a570 100644 (file)
@@ -105,6 +105,7 @@ SELECT relname, relhasindex
  pg_namespace            | t
  pg_opclass              | t
  pg_operator             | t
+ pg_opfamily             | t
  pg_pltemplate           | t
  pg_proc                 | t
  pg_rewrite              | t
@@ -140,7 +141,7 @@ SELECT relname, relhasindex
  timetz_tbl              | f
  tinterval_tbl           | f
  varchar_tbl             | f
-(129 rows)
+(130 rows)
 
 --
 -- another sanity check: every system catalog that has OIDs should have
index 910d55f..bf713e9 100644 (file)
@@ -69,26 +69,42 @@ SELECT      ctid, amcostestimate
 FROM   pg_catalog.pg_am fk 
 WHERE  amcostestimate != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amcostestimate);
-SELECT ctid, amopclaid 
+SELECT ctid, amoptions 
+FROM   pg_catalog.pg_am fk 
+WHERE  amoptions != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amoptions);
+SELECT ctid, amopfamily 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amopfamily != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opfamily pk WHERE pk.oid = fk.amopfamily);
+SELECT ctid, amoplefttype 
 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 
+WHERE  amoplefttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amoplefttype);
+SELECT ctid, amoprighttype 
 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);
+WHERE  amoprighttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amoprighttype);
 SELECT ctid, amopopr 
 FROM   pg_catalog.pg_amop fk 
 WHERE  amopopr != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.amopopr);
-SELECT ctid, amopclaid 
+SELECT ctid, amopmethod 
+FROM   pg_catalog.pg_amop fk 
+WHERE  amopmethod != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.amopmethod);
+SELECT ctid, amprocfamily 
 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 
+WHERE  amprocfamily != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opfamily pk WHERE pk.oid = fk.amprocfamily);
+SELECT ctid, amproclefttype 
 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);
+WHERE  amproclefttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amproclefttype);
+SELECT ctid, amprocrighttype 
+FROM   pg_catalog.pg_amproc fk 
+WHERE  amprocrighttype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amprocrighttype);
 SELECT ctid, amproc 
 FROM   pg_catalog.pg_amproc fk 
 WHERE  amproc != 0 AND 
@@ -121,6 +137,10 @@ SELECT     ctid, reltype
 FROM   pg_catalog.pg_class fk 
 WHERE  reltype != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.reltype);
+SELECT ctid, relowner 
+FROM   pg_catalog.pg_class fk 
+WHERE  relowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.relowner);
 SELECT ctid, relam 
 FROM   pg_catalog.pg_class fk 
 WHERE  relam != 0 AND 
@@ -149,10 +169,18 @@ SELECT    ctid, connamespace
 FROM   pg_catalog.pg_conversion fk 
 WHERE  connamespace != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.connamespace);
+SELECT ctid, conowner 
+FROM   pg_catalog.pg_conversion fk 
+WHERE  conowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.conowner);
 SELECT ctid, conproc 
 FROM   pg_catalog.pg_conversion fk 
 WHERE  conproc != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.conproc);
+SELECT ctid, datdba 
+FROM   pg_catalog.pg_database fk 
+WHERE  datdba != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.datdba);
 SELECT ctid, dattablespace 
 FROM   pg_catalog.pg_database fk 
 WHERE  dattablespace != 0 AND 
@@ -181,22 +209,42 @@ SELECT    ctid, lanvalidator
 FROM   pg_catalog.pg_language fk 
 WHERE  lanvalidator != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.lanvalidator);
-SELECT ctid, opcamid 
+SELECT ctid, nspowner 
+FROM   pg_catalog.pg_namespace fk 
+WHERE  nspowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.nspowner);
+SELECT ctid, opcmethod 
 FROM   pg_catalog.pg_opclass fk 
-WHERE  opcamid != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.opcamid);
+WHERE  opcmethod != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.opcmethod);
 SELECT ctid, opcnamespace 
 FROM   pg_catalog.pg_opclass fk 
 WHERE  opcnamespace != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.opcnamespace);
+SELECT ctid, opcowner 
+FROM   pg_catalog.pg_opclass fk 
+WHERE  opcowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.opcowner);
+SELECT ctid, opcfamily 
+FROM   pg_catalog.pg_opclass fk 
+WHERE  opcfamily != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opfamily pk WHERE pk.oid = fk.opcfamily);
 SELECT ctid, opcintype 
 FROM   pg_catalog.pg_opclass fk 
 WHERE  opcintype != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.opcintype);
+SELECT ctid, opckeytype 
+FROM   pg_catalog.pg_opclass fk 
+WHERE  opckeytype != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.opckeytype);
 SELECT ctid, oprnamespace 
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprnamespace != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.oprnamespace);
+SELECT ctid, oprowner 
+FROM   pg_catalog.pg_operator fk 
+WHERE  oprowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.oprowner);
 SELECT ctid, oprleft 
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprleft != 0 AND 
@@ -217,22 +265,6 @@ SELECT     ctid, oprnegate
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprnegate != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprnegate);
-SELECT ctid, oprlsortop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprlsortop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprlsortop);
-SELECT ctid, oprrsortop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprrsortop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprrsortop);
-SELECT ctid, oprltcmpop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprltcmpop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprltcmpop);
-SELECT ctid, oprgtcmpop 
-FROM   pg_catalog.pg_operator fk 
-WHERE  oprgtcmpop != 0 AND 
-       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprgtcmpop);
 SELECT ctid, oprcode 
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprcode != 0 AND 
@@ -245,10 +277,26 @@ SELECT    ctid, oprjoin
 FROM   pg_catalog.pg_operator fk 
 WHERE  oprjoin != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.oprjoin);
+SELECT ctid, opfmethod 
+FROM   pg_catalog.pg_opfamily fk 
+WHERE  opfmethod != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_am pk WHERE pk.oid = fk.opfmethod);
+SELECT ctid, opfnamespace 
+FROM   pg_catalog.pg_opfamily fk 
+WHERE  opfnamespace != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.opfnamespace);
+SELECT ctid, opfowner 
+FROM   pg_catalog.pg_opfamily fk 
+WHERE  opfowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.opfowner);
 SELECT ctid, pronamespace 
 FROM   pg_catalog.pg_proc fk 
 WHERE  pronamespace != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.pronamespace);
+SELECT ctid, proowner 
+FROM   pg_catalog.pg_proc fk 
+WHERE  proowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.proowner);
 SELECT ctid, prolang 
 FROM   pg_catalog.pg_proc fk 
 WHERE  prolang != 0 AND 
@@ -261,6 +309,14 @@ SELECT     ctid, ev_class
 FROM   pg_catalog.pg_rewrite fk 
 WHERE  ev_class != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.ev_class);
+SELECT ctid, refclassid 
+FROM   pg_catalog.pg_shdepend fk 
+WHERE  refclassid != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.refclassid);
+SELECT ctid, classoid 
+FROM   pg_catalog.pg_shdescription fk 
+WHERE  classoid != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.classoid);
 SELECT ctid, starelid 
 FROM   pg_catalog.pg_statistic fk 
 WHERE  starelid != 0 AND 
@@ -277,6 +333,10 @@ SELECT     ctid, staop3
 FROM   pg_catalog.pg_statistic fk 
 WHERE  staop3 != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.staop3);
+SELECT ctid, spcowner 
+FROM   pg_catalog.pg_tablespace fk 
+WHERE  spcowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.spcowner);
 SELECT ctid, tgrelid 
 FROM   pg_catalog.pg_trigger fk 
 WHERE  tgrelid != 0 AND 
@@ -289,6 +349,10 @@ SELECT     ctid, typnamespace
 FROM   pg_catalog.pg_type fk 
 WHERE  typnamespace != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace pk WHERE pk.oid = fk.typnamespace);
+SELECT ctid, typowner 
+FROM   pg_catalog.pg_type fk 
+WHERE  typowner != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.typowner);
 SELECT ctid, typrelid 
 FROM   pg_catalog.pg_type fk 
 WHERE  typrelid != 0 AND 
index 5195a29..4dd39eb 100644 (file)
@@ -1,7 +1,8 @@
 --
 -- OPR_SANITY
 -- Sanity checks for common errors in making operator/procedure system tables:
--- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
+-- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am,
+-- pg_amop, pg_amproc, pg_opclass, pg_opfamily.
 --
 -- None of the SELECTs here should ever find any matching entries,
 -- so the expected output is easy to maintain ;-).
@@ -307,135 +308,48 @@ WHERE p1.oprnegate = p2.oid AND
      p1.oid != p2.oprnegate OR
      p1.oid = p2.oid);
 
--- Look for mergejoin operators that don't match their links.
--- An lsortop/rsortop link leads from an '=' operator to the
--- sort operator ('<' operator) that's appropriate for
--- its left-side or right-side data type.
--- An ltcmpop/gtcmpop link leads from an '=' operator to the
--- '<' or '>' operator of the same input datatypes.
--- (If the '=' operator has identical L and R input datatypes,
--- then lsortop, rsortop, and ltcmpop are all the same operator.)
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprlsortop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprleft != p2.oprleft OR
-     p1.oprleft != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprrsortop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprright != p2.oprleft OR
-     p1.oprright != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprltcmpop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('<', '~<~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprleft != p2.oprleft OR
-     p1.oprright != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
-
-SELECT p1.oid, p1.oprcode, p2.oid, p2.oprcode
-FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprgtcmpop = p2.oid AND
-    (p1.oprname NOT IN ('=', '~=~') OR p2.oprname NOT IN ('>', '~>~') OR
-     p1.oprkind != 'b' OR p2.oprkind != 'b' OR
-     p1.oprleft != p2.oprleft OR
-     p1.oprright != p2.oprright OR
-     p1.oprresult != 'bool'::regtype OR
-     p2.oprresult != 'bool'::regtype);
-
--- Make sure all four links are specified if any are.
-
-SELECT p1.oid, p1.oprcode
-FROM pg_operator AS p1
-WHERE NOT ((oprlsortop = 0 AND oprrsortop = 0 AND
-            oprltcmpop = 0 AND oprgtcmpop = 0) OR
-           (oprlsortop != 0 AND oprrsortop != 0 AND
-            oprltcmpop != 0 AND oprgtcmpop != 0));
-
--- A mergejoinable = operator must have a commutator (usually itself).
+-- A mergejoinable or hashjoinable operator must be binary, must return
+-- boolean, and must have a commutator (itself, unless it's a cross-type
+-- operator).
 
 SELECT p1.oid, p1.oprname FROM pg_operator AS p1
-WHERE p1.oprlsortop != 0 AND
-      p1.oprcom = 0;
-
--- Mergejoinable operators across datatypes must come in closed sets, that
--- is if you provide int2 = int4 and int4 = int8 then you must also provide
--- int2 = int8 (and commutators of all these).  This is necessary because
--- the planner tries to deduce additional qual clauses from transitivity
--- of mergejoinable operators.  If there are clauses int2var = int4var and
--- int4var = int8var, the planner will deduce int2var = int8var ... and it
--- had better have a way to represent it.
+WHERE (p1.oprcanmerge OR p1.oprcanhash) AND NOT
+    (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND p1.oprcom != 0);
 
-SELECT p1.oid, p2.oid FROM pg_operator AS p1, pg_operator AS p2
-WHERE p1.oprlsortop != p1.oprrsortop AND
-      p1.oprrsortop = p2.oprlsortop AND
-      p2.oprlsortop != p2.oprrsortop AND
-      NOT EXISTS (SELECT 1 FROM pg_operator p3 WHERE
-      p3.oprlsortop = p1.oprlsortop AND p3.oprrsortop = p2.oprrsortop);
-
-
--- Hashing only works on simple equality operators "type = sametype",
--- since the hash itself depends on the bitwise representation of the type.
--- Check that allegedly hashable operators look like they might be "=".
+-- Mergejoinable operators should appear as equality members of btree index
+-- opfamilies.
 
 SELECT p1.oid, p1.oprname
 FROM pg_operator AS p1
-WHERE p1.oprcanhash AND NOT
-    (p1.oprkind = 'b' AND p1.oprresult = 'bool'::regtype AND
-     p1.oprleft = p1.oprright AND p1.oprname IN ('=', '~=~') AND
-     p1.oprcom = p1.oid);
-
--- In 6.5 we accepted hashable array equality operators when the array element
--- type is hashable.  However, what we actually need to make hashjoin work on
--- an array is a hashable element type *and* no padding between elements in
--- the array storage (or, perhaps, guaranteed-zero padding).  Currently,
--- since the padding code in arrayfuncs.c is pretty bogus, it seems safest
--- to just forbid hashjoin on array equality ops.
--- This should be reconsidered someday.
-
--- -- Look for array equality operators that are hashable when the underlying
--- -- type is not, or vice versa.  This is presumably bogus.
--- 
--- SELECT p1.oid, p1.oprcanhash, p2.oid, p2.oprcanhash, t1.typname, t2.typname
--- FROM pg_operator AS p1, pg_operator AS p2, pg_type AS t1, pg_type AS t2
--- WHERE p1.oprname = '=' AND p1.oprleft = p1.oprright AND 
---     p2.oprname = '=' AND p2.oprleft = p2.oprright AND
---     p1.oprleft = t1.oid AND p2.oprleft = t2.oid AND t1.typelem = t2.oid AND
---     p1.oprcanhash != p2.oprcanhash;
-
--- Substitute check: forbid hashable array ops, period.
-SELECT p1.oid, p1.oprname
-FROM pg_operator AS p1, pg_proc AS p2
-WHERE p1.oprcanhash AND p1.oprcode = p2.oid AND p2.proname = 'array_eq';
+WHERE p1.oprcanmerge AND NOT EXISTS
+  (SELECT 1 FROM pg_amop
+   WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+         amopopr = p1.oid AND amopstrategy = 3);
 
--- Hashable operators should appear as members of hash index opclasses.
+-- And the converse.
+
+SELECT p1.oid, p1.oprname, p.amopfamily
+FROM pg_operator AS p1, pg_amop p
+WHERE amopopr = p1.oid
+  AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+  AND amopstrategy = 3
+  AND NOT p1.oprcanmerge;
+
+-- Hashable operators should appear as members of hash index opfamilies.
 
 SELECT p1.oid, p1.oprname
 FROM pg_operator AS p1
 WHERE p1.oprcanhash AND NOT EXISTS
-  (SELECT 1 FROM pg_opclass op JOIN pg_amop p ON op.oid = amopclaid
-   WHERE opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
-         amopopr = p1.oid);
+  (SELECT 1 FROM pg_amop
+   WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash') AND
+         amopopr = p1.oid AND amopstrategy = 1);
 
 -- And the converse.
 
-SELECT p1.oid, p1.oprname, op.opcname
-FROM pg_operator AS p1, pg_opclass op, pg_amop p
-WHERE amopopr = p1.oid AND amopclaid = op.oid
-  AND opcamid = (SELECT oid FROM pg_am WHERE amname = 'hash')
+SELECT p1.oid, p1.oprname, p.amopfamily
+FROM pg_operator AS p1, pg_amop p
+WHERE amopopr = p1.oid
+  AND amopmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
   AND NOT p1.oprcanhash;
 
 -- Check that each operator defined in pg_operator matches its oprcode entry
@@ -474,7 +388,7 @@ WHERE p1.oprcode = p2.oid AND
 SELECT p1.oid, p1.oprname, p2.oid, p2.proname
 FROM pg_operator AS p1, pg_proc AS p2
 WHERE p1.oprcode = p2.oid AND
-    (p1.oprlsortop != 0 OR p1.oprcanhash) AND
+    (p1.oprcanmerge OR p1.oprcanhash) AND
     p2.provolatile = 'v';
 
 -- If oprrest is set, the operator must return boolean,
@@ -596,74 +510,105 @@ WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
     (oprkind != 'b' OR oprresult != 'boolean'::regtype
      OR oprleft != p.proargtypes[0] OR oprright != p.proargtypes[0]);
 
--- Check operator is a suitable btree opclass member
+-- Check operator is a suitable btree opfamily member
 
 SELECT a.aggfnoid::oid, o.oid
 FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p
 WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
-    NOT EXISTS(SELECT 1 FROM pg_amop ao, pg_opclass oc
-               WHERE amopclaid = oc.oid AND amopsubtype = 0
-                     AND amopopr = o.oid AND opcamid = 403
-                     AND opcintype = o.oprleft AND opcdefault);
+    NOT EXISTS(SELECT 1 FROM pg_amop
+               WHERE amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+                     AND amopopr = o.oid
+                     AND amoplefttype = o.oprleft
+                     AND amoprighttype = o.oprright);
 
 -- Check correspondence of btree strategies and names
 
 SELECT DISTINCT proname, oprname, amopstrategy
 FROM pg_operator AS o, pg_aggregate AS a, pg_proc AS p,
-     pg_amop as ao, pg_opclass oc
+     pg_amop as ao
 WHERE a.aggfnoid = p.oid AND a.aggsortop = o.oid AND
-    amopclaid = oc.oid AND amopopr = o.oid AND opcamid = 403
-ORDER BY 1;
+    amopopr = o.oid AND
+    amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+ORDER BY 1, 2;
+
+-- **************** pg_opfamily ****************
+
+-- Look for illegal values in pg_opfamily fields
+
+SELECT p1.oid
+FROM pg_opfamily as p1
+WHERE p1.opfmethod = 0 OR p1.opfnamespace = 0;
 
 -- **************** pg_opclass ****************
 
 -- Look for illegal values in pg_opclass fields
 
 SELECT p1.oid
-FROM pg_opclass as p1
-WHERE p1.opcamid = 0 OR p1.opcintype = 0;
+FROM pg_opclass AS p1
+WHERE p1.opcmethod = 0 OR p1.opcnamespace = 0 OR p1.opcfamily = 0
+    OR p1.opcintype = 0;
+
+-- opcmethod must match owning opfamily's opfmethod
+
+SELECT p1.oid, p2.oid
+FROM pg_opclass AS p1, pg_opfamily AS p2
+WHERE p1.opcfamily = p2.oid AND p1.opcmethod != p2.opfmethod;
 
 -- There should not be multiple entries in pg_opclass with opcdefault true
--- and the same opcamid/opcintype combination.
+-- and the same opcmethod/opcintype combination.
 
 SELECT p1.oid, p2.oid
 FROM pg_opclass AS p1, pg_opclass AS p2
 WHERE p1.oid != p2.oid AND
-    p1.opcamid = p2.opcamid AND p1.opcintype = p2.opcintype AND
+    p1.opcmethod = p2.opcmethod AND p1.opcintype = p2.opcintype AND
     p1.opcdefault AND p2.opcdefault;
 
 -- **************** pg_amop ****************
 
 -- Look for illegal values in pg_amop fields
 
-SELECT p1.amopclaid, p1.amopstrategy
+SELECT p1.amopfamily, p1.amopstrategy
 FROM pg_amop as p1
-WHERE p1.amopclaid = 0 OR p1.amopstrategy <= 0 OR p1.amopopr = 0;
+WHERE p1.amopfamily = 0 OR p1.amoplefttype = 0 OR p1.amoprighttype = 0
+    OR p1.amopopr = 0 OR p1.amopmethod = 0 OR p1.amopstrategy < 1;
+
+-- amoplefttype/amoprighttype must match the operator
+
+SELECT p1.oid, p2.oid
+FROM pg_amop AS p1, pg_operator AS p2
+WHERE p1.amopopr = p2.oid AND NOT
+    (p1.amoplefttype = p2.oprleft AND p1.amoprighttype = p2.oprright);
+
+-- amopmethod must match owning opfamily's opfmethod
+
+SELECT p1.oid, p2.oid
+FROM pg_amop AS p1, pg_opfamily AS p2
+WHERE p1.amopfamily = p2.oid AND p1.amopmethod != p2.opfmethod;
 
 -- Cross-check amopstrategy index against parent AM
 
-SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.amname
-FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3
-WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.amname
+FROM pg_amop AS p1, pg_am AS p2
+WHERE p1.amopmethod = p2.oid AND
     p1.amopstrategy > p2.amstrategies AND p2.amstrategies <> 0;
 
 -- 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.
+-- as AM expects for each datatype combination supported by the opfamily.
 -- We can't check this for AMs with variable strategy sets.
 
-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
+SELECT p1.amname, p2.amoplefttype, p2.amoprighttype
+FROM pg_am AS p1, pg_amop AS p2
+WHERE p2.amopmethod = p1.oid AND
     p1.amstrategies <> 0 AND
-    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4
-                        WHERE p4.amopclaid = p2.oid AND
-                              p4.amopsubtype = p3.amopsubtype);
+    p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3
+                        WHERE p3.amopfamily = p2.amopfamily AND
+                              p3.amoplefttype = p2.amoplefttype AND
+                              p3.amoprighttype = p2.amoprighttype);
 
 -- Check that amopopr points at a reasonable-looking operator, ie a binary
 -- operator yielding boolean.
 
-SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
+SELECT p1.amopfamily, 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);
@@ -671,86 +616,109 @@ WHERE p1.amopopr = p2.oid AND
 -- 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.
+-- swapping two operators within a family.
 
-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
+SELECT DISTINCT amopmethod, amopstrategy, oprname
+FROM pg_amop p1 LEFT JOIN pg_operator p2 ON amopopr = p2.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
 -- thing to insist on for all standard datatypes.
 
-SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname
+SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
 FROM pg_amop AS p1, pg_operator AS p2
 WHERE p1.amopopr = p2.oid AND
     (p2.oprrest = 0 OR p2.oprjoin = 0);
 
--- Check that operator input types match the opclass
--- For 8.0, 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.
+-- Check that each opclass in an opfamily has associated operators, that is
+-- ones whose oprleft matches opcintype (possibly by coercion).
 
-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
-    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;
+SELECT p1.opcname, p1.opcfamily
+FROM pg_opclass AS p1
+WHERE NOT EXISTS(SELECT 1 FROM pg_amop AS p2
+                 WHERE p2.amopfamily = p1.opcfamily
+                   AND binary_coercible(p1.opcintype, p2.amoplefttype));
 
 -- Operators that are primary members of opclasses must be immutable (else
 -- it suggests that the index ordering isn't fixed).  Operators that are
 -- cross-type members need only be stable, since they are just shorthands
 -- for index probe queries.
 
-SELECT p1.amopclaid, p1.amopopr, p2.oprname, p3.prosrc
+SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
 FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
 WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
-    p1.amopsubtype = 0 AND
+    p1.amoplefttype = p1.amoprighttype AND
     p3.provolatile != 'i';
 
-SELECT p1.amopclaid, p1.amopopr, p2.oprname, p3.prosrc
+SELECT p1.amopfamily, p1.amopopr, p2.oprname, p3.prosrc
 FROM pg_amop AS p1, pg_operator AS p2, pg_proc AS p3
 WHERE p1.amopopr = p2.oid AND p2.oprcode = p3.oid AND
-    p1.amopsubtype != 0 AND
+    p1.amoplefttype != p1.amoprighttype AND
     p3.provolatile = 'v';
 
+-- Multiple-datatype btree opclasses should provide closed sets of equality
+-- operators; that is if you provide int2 = int4 and int4 = int8 then you
+-- must also provide int2 = int8 (and commutators of all these).  This is
+-- necessary because the planner tries to deduce additional qual clauses from
+-- transitivity of mergejoinable operators.  If there are clauses
+-- int2var = int4var and int4var = int8var, the planner will deduce
+-- int2var = int8var ... and it had better have a way to represent it.
+
+-- check commutative closure
+SELECT p1.amoplefttype, p1.amoprighttype
+FROM pg_amop AS p1
+WHERE p1.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+    p1.amopstrategy = 3 AND
+    p1.amoplefttype != p1.amoprighttype AND
+    NOT EXISTS(SELECT 1 FROM pg_amop p2 WHERE
+                 p2.amopfamily = p1.amopfamily AND
+                 p2.amoplefttype = p1.amoprighttype AND
+                 p2.amoprighttype = p1.amoplefttype AND
+                 p2.amopstrategy = 3);
+
+-- check transitive closure
+SELECT p1.amoplefttype, p1.amoprighttype, p2.amoprighttype
+FROM pg_amop AS p1, pg_amop AS p2
+WHERE p1.amopfamily = p2.amopfamily AND
+    p1.amoprighttype = p2.amoplefttype AND
+    p1.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+    p2.amopmethod = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
+    p1.amopstrategy = 3 AND p2.amopstrategy = 3 AND
+    p1.amoplefttype != p1.amoprighttype AND
+    p2.amoplefttype != p2.amoprighttype AND
+    NOT EXISTS(SELECT 1 FROM pg_amop p3 WHERE
+                 p3.amopfamily = p1.amopfamily AND
+                 p3.amoplefttype = p1.amoplefttype AND
+                 p3.amoprighttype = p2.amoprighttype AND
+                 p3.amopstrategy = 3);
+
 -- **************** pg_amproc ****************
 
 -- Look for illegal values in pg_amproc fields
 
-SELECT p1.amopclaid, p1.amprocnum
+SELECT p1.amprocfamily, p1.amprocnum
 FROM pg_amproc as p1
-WHERE p1.amopclaid = 0 OR p1.amprocnum <= 0 OR p1.amproc = 0;
+WHERE p1.amprocfamily = 0 OR p1.amproclefttype = 0 OR p1.amprocrighttype = 0
+    OR p1.amprocnum < 1 OR p1.amproc = 0;
 
 -- Cross-check amprocnum index against parent AM
 
-SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
-FROM pg_amproc AS p1, pg_am AS p2, pg_opclass AS p3
-WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND
+SELECT p1.amprocfamily, p1.amprocnum, p2.oid, p2.amname
+FROM pg_amproc AS p1, pg_am AS p2, pg_opfamily AS p3
+WHERE p1.amprocfamily = p3.oid AND p3.opfmethod = 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.  When nondefault subtypes are
--- present, enforce condition separately for each subtype.
+-- as AM expects for each datatype combination supported by the opfamily.
 
-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
+SELECT p1.amname, p2.opfname, p3.amproclefttype, p3.amprocrighttype
+FROM pg_am AS p1, pg_opfamily AS p2, pg_amproc AS p3
+WHERE p2.opfmethod = p1.oid AND p3.amprocfamily = p2.oid AND
     p1.amsupport != (SELECT count(*) FROM pg_amproc AS p4
-                     WHERE p4.amopclaid = p2.oid AND
-                           p4.amprocsubtype = p3.amprocsubtype);
+                     WHERE p4.amprocfamily = p2.oid AND
+                           p4.amproclefttype = p3.amproclefttype AND
+                           p4.amprocrighttype = p3.amprocrighttype);
 
 -- Unfortunately, we can't check the amproc link very well because the
 -- signature of the function may be different for different support routines
@@ -759,85 +727,66 @@ WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND
 -- routine number take the same number of parameters, but that's about it
 -- for a general check...
 
-SELECT p1.amopclaid, p1.amprocnum,
+SELECT p1.amprocfamily, p1.amprocnum,
        p2.oid, p2.proname,
-       p3.opcname,
-       p4.amopclaid, p4.amprocnum,
+       p3.opfname,
+       p4.amprocfamily, p4.amprocnum,
        p5.oid, p5.proname,
-       p6.opcname
-FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3,
-     pg_amproc AS p4, pg_proc AS p5, pg_opclass AS p6
-WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND
-    p3.opcamid = p6.opcamid AND p1.amprocnum = p4.amprocnum AND
+       p6.opfname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opfamily AS p3,
+     pg_amproc AS p4, pg_proc AS p5, pg_opfamily AS p6
+WHERE p1.amprocfamily = p3.oid AND p4.amprocfamily = p6.oid AND
+    p3.opfmethod = p6.opfmethod AND p1.amprocnum = p4.amprocnum AND
     p1.amproc = p2.oid AND p4.amproc = p5.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 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
-     OR prorettype != 23
-     OR pronargs != 2
-     OR NOT binary_coercible(opcintype, proargtypes[0])
-     OR proargtypes[0] != proargtypes[1]);
+-- must be of the form cmp(lefttype, righttype) returns int4.
 
-SELECT p1.amopclaid, p1.amprocnum,
+SELECT p1.amprocfamily, 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
+       p3.opfname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opfamily AS p3
+WHERE p3.opfmethod = (SELECT oid FROM pg_am WHERE amname = 'btree')
+    AND p1.amprocfamily = p3.oid AND p1.amproc = p2.oid AND
+    (amprocnum != 1
      OR proretset
-     OR prorettype != 23
+     OR prorettype != 'int4'::regtype
      OR pronargs != 2
-     OR NOT binary_coercible(opcintype, proargtypes[0])
-     OR proargtypes[1] != amprocsubtype);
+     OR proargtypes[0] != amproclefttype
+     OR proargtypes[1] != amprocrighttype);
 
 -- 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
--- enough cases where that fails that I'll just leave out the check for now.
+-- of the form hash(lefttype) returns int4.  There are several cases where
+-- we cheat and use a hash function that is physically compatible with the
+-- datatype even though there's no cast, so for now we can't check that.
 
-SELECT p1.amopclaid, p1.amprocnum,
+SELECT p1.amprocfamily, 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 = 'hash')
-    AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND
-    (opckeytype != 0
-     OR amprocnum != 1
+       p3.opfname
+FROM pg_amproc AS p1, pg_proc AS p2, pg_opfamily AS p3
+WHERE p3.opfmethod = (SELECT oid FROM pg_am WHERE amname = 'hash')
+    AND p1.amprocfamily = p3.oid AND p1.amproc = p2.oid AND
+    (amprocnum != 1
      OR proretset
-     OR prorettype != 23
+     OR prorettype != 'int4'::regtype
      OR pronargs != 1
---   OR NOT physically_coercible(opcintype, proargtypes[0])
-);
+--   OR NOT physically_coercible(amproclefttype, proargtypes[0])
+     OR amproclefttype != amprocrighttype);
 
--- Support routines that are primary members of opclasses must be immutable
+-- Support routines that are primary members of opfamilies must be immutable
 -- (else it suggests that the index ordering isn't fixed).  But cross-type
 -- members need only be stable, since they are just shorthands
 -- for index probe queries.
 
-SELECT p1.amopclaid, p1.amproc, p2.prosrc
+SELECT p1.amprocfamily, p1.amproc, p2.prosrc
 FROM pg_amproc AS p1, pg_proc AS p2
 WHERE p1.amproc = p2.oid AND
-    p1.amprocsubtype = 0 AND
+    p1.amproclefttype = p1.amprocrighttype AND
     p2.provolatile != 'i';
 
-SELECT p1.amopclaid, p1.amproc, p2.prosrc
+SELECT p1.amprocfamily, p1.amproc, p2.prosrc
 FROM pg_amproc AS p1, pg_proc AS p2
 WHERE p1.amproc = p2.oid AND
-    p1.amprocsubtype != 0 AND
+    p1.amproclefttype != p1.amprocrighttype AND
     p2.provolatile = 'v';
index ce31b19..aec8f1b 100644 (file)
@@ -7,13 +7,16 @@ anything but an empty database, such as template1; else it's likely to
 be very slow.
 
 Run on an empty database, it returns the system join relationships (shown
-below for 8.1).  Note that unexpected matches may indicate bogus entries
+below for 8.3).  Note that unexpected matches may indicate bogus entries
 in system tables --- don't accept a peculiar match without question.
 In particular, a field shown as joining to more than one target table is
-probably messed up.  In 8.1, the *only* fields that should join to more
-than one target are pg_description.objoid, pg_depend.objid, and
-pg_depend.refobjid.  (Running make_oidjoins_check is an easy way to spot
-fields joining to more than one table, BTW.)
+probably messed up.  In 8.3, the *only* fields that should join to more
+than one target are pg_description.objoid, pg_depend.objid,
+pg_depend.refobjid, pg_shdescription.objoid, pg_shdepend.objid, and
+pg_shdepend.refobjid.  (Running make_oidjoins_check is an easy way to spot
+fields joining to more than one table, BTW.)  NOTE: in an empty database,
+findoidjoins may not report joins for pg_shdescription and pg_shdepend for
+lack of any entries there.
 
 The shell script make_oidjoins_check converts findoidjoins' output
 into an SQL script that checks for dangling links (entries in an
@@ -26,7 +29,7 @@ revision in the patterns of cross-links between system tables.
 (Ideally we'd just regenerate the script as part of the regression
 tests themselves, but that seems too slow...)
 
-NOTE: in 8.1, make_oidjoins_check produces two bogus join checks:
+NOTE: in 8.3, make_oidjoins_check produces two bogus join checks:
 Join pg_catalog.pg_class.relfilenode => pg_catalog.pg_class.oid
 Join pg_catalog.pg_database.datlastsysoid => pg_catalog.pg_database.oid
 These are artifacts and should not be added to the oidjoins regress test.
@@ -50,11 +53,15 @@ Join pg_catalog.pg_am.ambuild => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_am.ambulkdelete => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_am.amvacuumcleanup => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_am.amcostestimate => pg_catalog.pg_proc.oid
-Join pg_catalog.pg_amop.amopclaid => pg_catalog.pg_opclass.oid
-Join pg_catalog.pg_amop.amopsubtype => pg_catalog.pg_type.oid
+Join pg_catalog.pg_am.amoptions => pg_catalog.pg_proc.oid
+Join pg_catalog.pg_amop.amopfamily => pg_catalog.pg_opfamily.oid
+Join pg_catalog.pg_amop.amoplefttype => pg_catalog.pg_type.oid
+Join pg_catalog.pg_amop.amoprighttype => pg_catalog.pg_type.oid
 Join pg_catalog.pg_amop.amopopr => pg_catalog.pg_operator.oid
-Join pg_catalog.pg_amproc.amopclaid => pg_catalog.pg_opclass.oid
-Join pg_catalog.pg_amproc.amprocsubtype => pg_catalog.pg_type.oid
+Join pg_catalog.pg_amop.amopmethod => pg_catalog.pg_am.oid
+Join pg_catalog.pg_amproc.amprocfamily => pg_catalog.pg_opfamily.oid
+Join pg_catalog.pg_amproc.amproclefttype => pg_catalog.pg_type.oid
+Join pg_catalog.pg_amproc.amprocrighttype => pg_catalog.pg_type.oid
 Join pg_catalog.pg_amproc.amproc => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_attribute.attrelid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_attribute.atttypid => pg_catalog.pg_type.oid
@@ -63,6 +70,7 @@ Join pg_catalog.pg_cast.casttarget => pg_catalog.pg_type.oid
 Join pg_catalog.pg_cast.castfunc => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_class.relnamespace => pg_catalog.pg_namespace.oid
 Join pg_catalog.pg_class.reltype => pg_catalog.pg_type.oid
+Join pg_catalog.pg_class.relowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_class.relam => pg_catalog.pg_am.oid
 Join pg_catalog.pg_class.reltablespace => pg_catalog.pg_tablespace.oid
 Join pg_catalog.pg_class.reltoastrelid => pg_catalog.pg_class.oid
@@ -70,7 +78,9 @@ Join pg_catalog.pg_class.reltoastidxid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_constraint.connamespace => pg_catalog.pg_namespace.oid
 Join pg_catalog.pg_constraint.contypid => pg_catalog.pg_type.oid
 Join pg_catalog.pg_conversion.connamespace => pg_catalog.pg_namespace.oid
+Join pg_catalog.pg_conversion.conowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_conversion.conproc => pg_catalog.pg_proc.oid
+Join pg_catalog.pg_database.datdba => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_database.dattablespace => pg_catalog.pg_tablespace.oid
 Join pg_catalog.pg_depend.classid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_depend.refclassid => pg_catalog.pg_class.oid
@@ -78,33 +88,42 @@ Join pg_catalog.pg_description.classoid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_index.indexrelid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_index.indrelid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_language.lanvalidator => pg_catalog.pg_proc.oid
-Join pg_catalog.pg_opclass.opcamid => pg_catalog.pg_am.oid
+Join pg_catalog.pg_namespace.nspowner => pg_catalog.pg_authid.oid
+Join pg_catalog.pg_opclass.opcmethod => pg_catalog.pg_am.oid
 Join pg_catalog.pg_opclass.opcnamespace => pg_catalog.pg_namespace.oid
+Join pg_catalog.pg_opclass.opcowner => pg_catalog.pg_authid.oid
+Join pg_catalog.pg_opclass.opcfamily => pg_catalog.pg_opfamily.oid
 Join pg_catalog.pg_opclass.opcintype => pg_catalog.pg_type.oid
+Join pg_catalog.pg_opclass.opckeytype => pg_catalog.pg_type.oid
 Join pg_catalog.pg_operator.oprnamespace => pg_catalog.pg_namespace.oid
+Join pg_catalog.pg_operator.oprowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_operator.oprleft => pg_catalog.pg_type.oid
 Join pg_catalog.pg_operator.oprright => pg_catalog.pg_type.oid
 Join pg_catalog.pg_operator.oprresult => pg_catalog.pg_type.oid
 Join pg_catalog.pg_operator.oprcom => pg_catalog.pg_operator.oid
 Join pg_catalog.pg_operator.oprnegate => pg_catalog.pg_operator.oid
-Join pg_catalog.pg_operator.oprlsortop => pg_catalog.pg_operator.oid
-Join pg_catalog.pg_operator.oprrsortop => pg_catalog.pg_operator.oid
-Join pg_catalog.pg_operator.oprltcmpop => pg_catalog.pg_operator.oid
-Join pg_catalog.pg_operator.oprgtcmpop => pg_catalog.pg_operator.oid
 Join pg_catalog.pg_operator.oprcode => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_operator.oprrest => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_operator.oprjoin => pg_catalog.pg_proc.oid
+Join pg_catalog.pg_opfamily.opfmethod => pg_catalog.pg_am.oid
+Join pg_catalog.pg_opfamily.opfnamespace => pg_catalog.pg_namespace.oid
+Join pg_catalog.pg_opfamily.opfowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_proc.pronamespace => pg_catalog.pg_namespace.oid
+Join pg_catalog.pg_proc.proowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_proc.prolang => pg_catalog.pg_language.oid
 Join pg_catalog.pg_proc.prorettype => pg_catalog.pg_type.oid
 Join pg_catalog.pg_rewrite.ev_class => pg_catalog.pg_class.oid
+Join pg_catalog.pg_shdepend.refclassid => pg_catalog.pg_class.oid
+Join pg_catalog.pg_shdescription.classoid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_statistic.starelid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_statistic.staop1 => pg_catalog.pg_operator.oid
 Join pg_catalog.pg_statistic.staop2 => pg_catalog.pg_operator.oid
 Join pg_catalog.pg_statistic.staop3 => pg_catalog.pg_operator.oid
+Join pg_catalog.pg_tablespace.spcowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_trigger.tgrelid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_trigger.tgfoid => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_type.typnamespace => pg_catalog.pg_namespace.oid
+Join pg_catalog.pg_type.typowner => pg_catalog.pg_authid.oid
 Join pg_catalog.pg_type.typrelid => pg_catalog.pg_class.oid
 Join pg_catalog.pg_type.typelem => pg_catalog.pg_type.oid
 Join pg_catalog.pg_type.typinput => pg_catalog.pg_proc.oid
index 50bd2e3..f6460d3 100644 (file)
@@ -7,7 +7,7 @@
 -- Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
 -- Portions Copyright (c) 1994, Regents of the University of California
 --
--- $PostgreSQL: pgsql/src/tutorial/syscat.source,v 1.16 2006/03/05 15:59:11 momjian Exp $
+-- $PostgreSQL: pgsql/src/tutorial/syscat.source,v 1.17 2006/12/23 00:43:13 tgl Exp $
 --
 ---------------------------------------------------------------------------
 
@@ -165,18 +165,18 @@ SELECT n.nspname, p.proname, format_type(t.oid, null) as typname
 
 
 --
--- lists all the operator classes that can be used with each access method
--- as well as the operators that cn be used with the respective operator
--- classes
+-- lists all the operator families that can be used with each access method
+-- as well as the operators that can be used with the respective operator
+-- families
 --
-SELECT n.nspname, am.amname, opc.opcname, opr.oprname
-  FROM pg_namespace n, pg_am am, pg_opclass opc
+SELECT am.amname, n.nspname, opf.opfname, opr.oprname
+  FROM pg_namespace n, pg_am am, pg_opfamily opf
        pg_amop amop, pg_operator opr
-  WHERE opc.opcnamespace = n.oid
-    and opc.opcamid = am.oid
-    and amop.amopclaid = opc.oid
+  WHERE opf.opfnamespace = n.oid
+    and opf.opfmethod = am.oid
+    and amop.amopfamily = opf.oid
     and amop.amopopr = opr.oid
-  ORDER BY nspname, amname, opcname, oprname;
+  ORDER BY nspname, amname, opfname, oprname;
 
 --
 -- Reset the search path