--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
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';
-<!-- $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>
<entry>operators</entry>
</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>
</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>
<entry>Owner of the operator class</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>
</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 — 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>
</entry>
</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>Negator of this operator, if any</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<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<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<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>R</>)
- </entry>
- </row>
-
<row>
<entry><structfield>oprcode</structfield></entry>
<entry><type>regproc</type></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>
-<!-- $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>
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 — 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
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 > 4 AND x > 14</> where <literal>x</> is a b-tree
-<!-- $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>
<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.
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>
<!--
-$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
-->
[, 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>
</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>
Refer to <xref linkend="xoper"> for further information.
</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
NEGATOR = !==,
RESTRICT = area_restriction_procedure,
JOIN = area_join_procedure,
- HASHES,
- SORT1 = <<<,
- SORT2 = <<<
- -- Since sort operators were given, MERGES is implied.
- -- LTCMP and GTCMP are assumed to be < and > respectively
+ HASHES, MERGES
);
</programlisting>
</para>
-<!-- $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>
<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>
</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
</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><</>, <literal><</>, <literal><</>, <literal>></>
- 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>
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>
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><</> and <literal>></> respectively.
- </para>
- </note>
</sect2>
</sect1>
*
*
* 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
{
/*
* 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);
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
/*
* 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);
*
*
* 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
/* ----------------
* 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
* 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,
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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;
cur->sk_flags,
cur->sk_attno,
InvalidStrategy,
- InvalidOid,
+ cur->sk_subtype,
procinfo,
cur->sk_argument);
}
{
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,
#
# 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 $
#
#-------------------------------------------------------------------------
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 \
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
#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"
* 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 */
};
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);
/*
* 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
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;
RemoveSchemaById(object->objectId);
break;
+ /* OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE not handled */
+
default:
elog(ERROR, "unrecognized object class: %u",
object->classId);
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 */
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;
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 */
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;
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);
+}
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
*/
char *opcname = NameStr(opcform->opcname);
- visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
+ visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
}
ReleaseSysCache(opctup);
return visible;
}
+/*
+ * 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.
*
*
* 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.
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 */
* 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
* 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
* (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
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;
Oid operResultType;
Oid commutatorId,
negatorId,
- leftSortId,
- rightSortId,
- ltCompareId,
- gtCompareId,
restOid,
joinOid;
bool selfCommutator = false;
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,
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 */
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 */
/*
* 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 */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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));
{
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);
}
}
}
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;
}
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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.
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;
char nulls[Natts_pg_opclass];
AclResult aclresult;
NameData opcName;
- int i;
ObjectAddress myself,
referenced;
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;
CreateOpClassItem *item = lfirst(l);
Oid operOid;
Oid funcOid;
- OpClassMember *member;
+ OpFamilyMember *member;
Assert(IsA(item, CreateOpClassItem));
switch (item->itemtype)
#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)
#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))
SysScanDesc scan;
ScanKeyInit(&skey[0],
- Anum_pg_opclass_opcamid,
+ Anum_pg_opclass_opcmethod,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(amoid));
/*
* 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);
/*
* 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;
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;
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());
}
/*
- * 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);
/*
* 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);
/*
* 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);
{
Oid amID,
opcID;
- char *schemaname;
- char *opcname;
HeapTuple tuple;
ObjectAddress object;
/*
* 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),
}
/*
- * 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,
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);
/*
* 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)
*
*
* 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
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 */
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 */
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),
if (typeName2)
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..
*/
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 */
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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",
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
/*
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
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++;
*
*
* 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 */
bool lisnull; /* and their isnull flags */
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;
* 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");
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,
- <op,
- >op,
- <proc,
- >proc);
-
- 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++;
}
* 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.
clause->ldatum = ExecEvalExpr(clause->lexpr, econtext,
&clause->lisnull, NULL);
- if (clause->lisnull && clause->mergestrict)
+ if (clause->lisnull)
canmatch = false;
}
clause->rdatum = ExecEvalExpr(clause->rexpr, econtext,
&clause->risnull, NULL);
- if (clause->risnull && clause->mergestrict)
+ if (clause->risnull)
canmatch = false;
}
/*
* 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;
}
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;
}
}
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;
*/
mergestate->mj_NumClauses = list_length(node->mergeclauses);
mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
+ node->mergefamilies,
+ node->mergestrategies,
(PlanState *) mergestate);
/*
* 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 $
*
*-------------------------------------------------------------------------
*/
* copy remainder of node
*/
COPY_NODE_FIELD(mergeclauses);
+ COPY_NODE_FIELD(mergefamilies);
+ COPY_NODE_FIELD(mergestrategies);
return newnode;
}
COPY_SCALAR_FIELD(rctype);
COPY_NODE_FIELD(opnos);
- COPY_NODE_FIELD(opclasses);
+ COPY_NODE_FIELD(opfamilies);
COPY_NODE_FIELD(largs);
COPY_NODE_FIELD(rargs);
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
CreateOpClassStmt *newnode = makeNode(CreateOpClassStmt);
COPY_NODE_FIELD(opclassname);
+ COPY_NODE_FIELD(opfamilyname);
COPY_STRING_FIELD(amname);
COPY_NODE_FIELD(datatype);
COPY_NODE_FIELD(items);
* 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 $
*
*-------------------------------------------------------------------------
*/
{
COMPARE_SCALAR_FIELD(rctype);
COMPARE_NODE_FIELD(opnos);
- COMPARE_NODE_FIELD(opclasses);
+ COMPARE_NODE_FIELD(opfamilies);
COMPARE_NODE_FIELD(largs);
COMPARE_NODE_FIELD(rargs);
_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);
*
*
* 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*
_outJoinPlanInfo(str, (Join *) node);
WRITE_NODE_FIELD(mergeclauses);
+ WRITE_NODE_FIELD(mergefamilies);
+ WRITE_NODE_FIELD(mergestrategies);
}
static void
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);
}
_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);
}
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);
*
*
* 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
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
*
* 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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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,
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);
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);
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 */
do
{
- Oid curClass = classes[0];
+ Oid curFamily = families[0];
List *clausegroup = NIL;
ListCell *l;
Assert(IsA(rinfo, RestrictInfo));
if (match_clause_to_indexcol(index,
indexcol,
- curClass,
+ curFamily,
rinfo,
outer_relids,
saop_control))
Assert(IsA(rinfo, RestrictInfo));
if (match_clause_to_indexcol(index,
indexcol,
- curClass,
+ curFamily,
rinfo,
outer_relids,
saop_control))
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 */
*
* (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().
*
*
* '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.
*
static bool
match_clause_to_indexcol(IndexOptInfo *index,
int indexcol,
- Oid opclass,
+ Oid opfamily,
RestrictInfo *rinfo,
Relids outer_relids,
SaOpControl saop_control)
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;
}
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);
}
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;
}
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;
}
/*
* 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)
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);
}
/*
static bool
match_rowcompare_to_indexcol(IndexOptInfo *index,
int indexcol,
- Oid opclass,
+ Oid opfamily,
RowCompareExpr *clause,
Relids outer_relids)
{
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);
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:
{
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;
* 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.
*
/*
* 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.)
foreach(l, restrictclauses)
{
List *sublist = (List *) lfirst(l);
- Oid opclass = index->classlist[indexcol];
+ Oid opfamily = index->opfamily[indexcol];
ListCell *l2;
foreach(l2, sublist)
bool ispc;
/* First check for boolean-index cases. */
- if (IsBooleanOpclass(opclass))
+ if (IsBooleanOpfamily(opfamily))
{
if (match_boolean_index_clause((Node *) clause, indexcol,
index))
{
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.
*/
*
* 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.
*
* 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.
* 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
*
* 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;
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)
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:
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:
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;
}
* 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.
List *resultquals = NIL;
ListCell *clausegroup_item;
int indexcol = 0;
- Oid *classes = index->classlist;
+ Oid *families = index->opfamily;
if (clausegroups == NIL)
return NIL;
clausegroup_item = list_head(clausegroups);
do
{
- Oid curClass = classes[0];
+ Oid curFamily = families[0];
ListCell *l;
foreach(l, (List *) lfirst(clausegroup_item))
Expr *clause = rinfo->clause;
/* First check for boolean cases */
- if (IsBooleanOpclass(curClass))
+ if (IsBooleanOpfamily(curFamily))
{
Expr *boolqual;
{
resultquals = list_concat(resultquals,
expand_indexqual_opclause(rinfo,
- curClass));
+ curFamily));
}
else if (IsA(clause, ScalarArrayOpExpr))
{
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 */
* 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;
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().
*/
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:
/* 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:
/* 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:
/* 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;
* 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
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;
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
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++;
}
else
{
- ListCell *opclasses_cell;
- ListCell *subtypes_cell;
+ ListCell *opfamilies_cell;
+ ListCell *lefttypes_cell;
+ ListCell *righttypes_cell;
if (op_strategy == BTLessStrategyNumber)
op_strategy = BTLessEqualStrategyNumber;
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 */
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),
/*
* 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;
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;
}
*/
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));
*
* 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));
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,
}
/*
- * 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;
*/
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);
/* 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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include <math.h>
+#include "access/skey.h"
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
RelOptInfo *innerrel,
List *restrictlist,
JoinType jointype);
+static void build_mergejoin_strat_lists(List *mergeclauses,
+ List **mergefamilies, List **mergestrategies);
/*
List *front_pathkey = (List *) lfirst(l);
List *cur_pathkeys;
List *cur_mergeclauses;
+ List *mergefamilies;
+ List *mergestrategies;
List *outerkeys;
List *innerkeys;
List *merge_pathkeys;
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.
*/
restrictlist,
merge_pathkeys,
cur_mergeclauses,
+ mergefamilies,
+ mergestrategies,
outerkeys,
innerkeys));
}
Path *outerpath = (Path *) lfirst(l);
List *merge_pathkeys;
List *mergeclauses;
+ List *mergefamilies;
+ List *mergestrategies;
List *innersortkeys;
List *trialsortkeys;
Path *cheapest_startup_inner;
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
restrictlist,
merge_pathkeys,
mergeclauses,
+ mergefamilies,
+ mergestrategies,
NIL,
innersortkeys));
}
else
newclauses = mergeclauses;
+
+ /* Build opfamily info for execution */
+ build_mergejoin_strat_lists(newclauses,
+ &mergefamilies, &mergestrategies);
+
add_path(joinrel, (Path *)
create_mergejoin_path(root,
joinrel,
restrictlist,
merge_pathkeys,
newclauses,
+ mergefamilies,
+ mergestrategies,
NIL,
NIL));
cheapest_total_inner = innerpath;
else
newclauses = mergeclauses;
}
+
+ /* Build opfamily info for execution */
+ build_mergejoin_strat_lists(newclauses,
+ &mergefamilies, &mergestrategies);
+
add_path(joinrel, (Path *)
create_mergejoin_path(root,
joinrel,
restrictlist,
merge_pathkeys,
newclauses,
+ mergefamilies,
+ mergestrategies,
NIL,
NIL));
}
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);
+ }
+}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
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,
joinclauses,
otherclauses,
mergeclauses,
+ best_path->path_mergefamilies,
+ best_path->path_mergestrategies,
outer_plan,
inner_plan,
best_path->jpath.jointype);
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));
/*
* 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))
* 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);
}
/*
* 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
*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)
}
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
{
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;
}
}
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);
/* Ooops... */
elog(ERROR, "node is not an index attribute");
- *opclass = InvalidOid; /* keep compiler quiet */
+ *opfamily = InvalidOid; /* keep compiler quiet */
return NULL;
}
List *joinclauses,
List *otherclauses,
List *mergeclauses,
+ List *mergefamilies,
+ List *mergestrategies,
Plan *lefttree,
Plan *righttree,
JoinType jointype)
plan->lefttree = lefttree;
plan->righttree = righttree;
node->mergeclauses = mergeclauses;
+ node->mergefamilies = mergefamilies;
+ node->mergestrategies = mergestrategies;
node->join.jointype = jointype;
node->join.joinqual = joinclauses;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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",
Oid opno,
leftOp,
rightOp;
+ Oid opfamily;
if (restrictinfo->pseudoconstant)
return;
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;
+ }
}
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
}
* 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
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)
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
}
*
*
* 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
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* '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
*/
List *restrict_clauses,
List *pathkeys,
List *mergeclauses,
+ List *mergefamilies,
+ List *mergestrategies,
List *outersortkeys,
List *innersortkeys)
{
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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];
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
* 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
* 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:
*
* 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.)
*----------
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;
}
/*
- * 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)
/* 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);
}
/*
- * 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 = */
}
/*
- * 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))
{
* 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)
if (!found)
{
- /* couldn't find a btree opclass to interpret the operators */
+ /* couldn't find a btree opfamily to interpret the operators */
return false;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
+ restrictinfo->mergeopfamily = InvalidOid;
restrictinfo->left_pathkey = NIL;
restrictinfo->right_pathkey = NIL;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
/*
* 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,
/*
* 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
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
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",
rcexpr = makeNode(RowCompareExpr);
rcexpr->rctype = rctype;
rcexpr->opnos = opnos;
- rcexpr->opclasses = opclasses;
+ rcexpr->opfamilies = opfamilies;
rcexpr->largs = largs;
rcexpr->rargs = rargs;
* 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"
#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"
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),
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
{
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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);
Datum constval;
Oid consttype;
Oid vartype;
- Oid opclass;
+ Oid opfamily;
Pattern_Prefix_Status pstatus;
Const *patt = NULL;
Const *prefix = NULL;
* 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.
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);
/*
* 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),
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);
* 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
*/
void
mergejoinscansel(PlannerInfo *root, Node *clause,
+ Oid opfamily, int strategy,
Selectivity *leftscan,
Selectivity *rightscan)
{
*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;
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))
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, <op, >op, 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;
* 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;
* 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.
*
* 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,
{
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,
}
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
}
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
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 */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
*/
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;
* 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;
tp = SearchSysCache(AMOPOPID,
ObjectIdGetDatum(opno),
- ObjectIdGetDatum(opclass),
+ ObjectIdGetDatum(opfamily),
0, 0);
if (!HeapTupleIsValid(tp))
return 0;
}
/*
- * 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);
return result;
}
+/*
+ * 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.)
*/
{
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,
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.
*/
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)
}
}
- /* 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);
op_strategy = ROWCOMPARE_NE;
}
- *opclasses = lappend_oid(*opclasses, opclass_id);
+ *opfamilies = lappend_oid(*opfamilies, opfamily_id);
*opstrats = lappend_int(*opstrats, op_strategy);
}
/* ---------- 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);
/* ---------- 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),
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;
}
/*
* 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;
{
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)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
#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
/*
* 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
{
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;
static void IndexSupportInitialize(oidvector *indclass,
Oid *indexOperator,
RegProcedure *indexSupport,
+ Oid *opFamily,
+ Oid *opcInType,
StrategyNumber maxStrategyNumber,
StrategyNumber maxSupportNumber,
AttrNumber maxAttributeNumber);
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;
MemoryContextSwitchTo(oldcontext);
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
*/
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);
/*
* 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
IndexSupportInitialize(oidvector *indclass,
Oid *indexOperator,
RegProcedure *indexSupport,
+ Oid *opFamily,
+ Oid *opcInType,
StrategyNumber maxStrategyNumber,
StrategyNumber maxSupportNumber,
AttrNumber maxAttributeNumber)
maxSupportNumber);
/* copy cached data into relcache entry */
+ opFamily[attIndex] = opcentry->opcfamily;
+ opcInType[attIndex] = opcentry->opcintype;
if (maxStrategyNumber > 0)
memcpy(&indexOperator[attIndex * maxStrategyNumber],
opcentry->operatorOids,
bool found;
Relation rel;
SysScanDesc scan;
- ScanKeyData skey[2];
+ ScanKeyData skey[3];
HeapTuple htup;
bool indexOK;
(operatorClassOid != OID_BTREE_OPS_OID &&
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)))
{
/*
* 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)))
{
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))
{
Form_pg_am am;
MemoryContext indexcxt;
+ Oid *opfamily;
+ Oid *opcintype;
Oid *operator;
RegProcedure *support;
int nsupport;
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;
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;
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);
/* 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)),
*
*
* 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"
2,
{
Anum_pg_amop_amopopr,
- Anum_pg_amop_amopclaid,
+ Anum_pg_amop_amopfamily,
0,
0
},
{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
},
0,
3,
{
- Anum_pg_opclass_opcamid,
+ Anum_pg_opclass_opcmethod,
Anum_pg_opclass_opcname,
Anum_pg_opclass_opcnamespace,
0
},
1024
},
- {InheritsRelationId, /* INHRELID */
- InheritsRelidSeqnoIndexId,
- Anum_pg_inherits_inhrelid,
- 2,
- {
- Anum_pg_inherits_inhrelid,
- Anum_pg_inherits_inhseqno,
- 0,
- 0
- },
- 256
- },
{LanguageRelationId, /* LANGNAME */
LanguageNameIndexId,
0,
},
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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
{
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);
}
/*
* 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 $
*
*-------------------------------------------------------------------------
*/
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),
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 */
}
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;
}
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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.
"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",
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
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)
/* 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, "
"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);
"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);
"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);
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);
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));
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");
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
*/
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);
*/
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);
*/
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200612201
+#define CATALOG_VERSION_NO 200612221
#endif
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
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
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
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
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
* 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;
/* ----------------
* 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
*/
/*
- * 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 */
* 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;
/* ----------------
* 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
*/
/* 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 */
* 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
* 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 */
* 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 */
* 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
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 */
* ----------------
*/
-#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&