mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Restructure operator classes to allow improved handling of cross-data-type
cases. Operator classes now exist within "operator families". While most families are equivalent to a single class, related classes can be grouped into one family to represent the fact that they are semantically compatible. Cross-type operators are now naturally adjunct parts of a family, without having to wedge them into a particular opclass as we had done originally. This commit restructures the catalogs and cleans up enough of the fallout so that everything still works at least as well as before, but most of the work needed to actually improve the planner's behavior will come later. Also, there are not yet CREATE/DROP/ALTER OPERATOR FAMILY commands; the only way to create a new family right now is to allow CREATE OPERATOR CLASS to make one by default. I owe some more documentation work, too. But that can all be done in smaller pieces once this infrastructure is in place.
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.138 2006/12/18 18:56:28 tgl Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.139 2006/12/23 00:43:08 tgl Exp $ -->
|
||||
<!--
|
||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||
-->
|
||||
@ -160,7 +160,7 @@
|
||||
|
||||
<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>
|
||||
@ -168,6 +168,11 @@
|
||||
<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>
|
||||
@ -516,9 +521,11 @@
|
||||
</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>
|
||||
@ -536,18 +543,24 @@
|
||||
<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>
|
||||
@ -571,10 +584,27 @@
|
||||
<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>
|
||||
|
||||
|
||||
@ -586,10 +616,9 @@
|
||||
</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>
|
||||
@ -607,17 +636,24 @@
|
||||
<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>amprocsubtype</structfield></entry>
|
||||
<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>Subtype, if cross-type routine, else zero</entry>
|
||||
<entry>Left-hand input data type of associated operator</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<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>Right-hand input data type of associated operator</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -638,6 +674,18 @@
|
||||
</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>
|
||||
|
||||
|
||||
@ -2843,9 +2891,11 @@
|
||||
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>
|
||||
@ -2867,7 +2917,7 @@
|
||||
<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>
|
||||
@ -2894,6 +2944,13 @@
|
||||
<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>
|
||||
@ -2920,14 +2977,11 @@
|
||||
</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>
|
||||
@ -2993,6 +3047,13 @@
|
||||
</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>
|
||||
@ -3035,46 +3096,6 @@
|
||||
<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>
|
||||
@ -3107,6 +3128,86 @@
|
||||
</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>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.18 2006/09/16 00:30:14 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.19 2006/12/23 00:43:08 tgl Exp $ -->
|
||||
|
||||
<chapter id="indexam">
|
||||
<title>Index Access Method Interface Definition</title>
|
||||
@ -63,13 +63,15 @@
|
||||
|
||||
<para>
|
||||
To be useful, an index access method must also have one or more
|
||||
<firstterm>operator families</> and
|
||||
<firstterm>operator classes</> defined in
|
||||
<link linkend="catalog-pg-opfamily"><structname>pg_opfamily</structname></link>,
|
||||
<link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>,
|
||||
<link linkend="catalog-pg-amop"><structname>pg_amop</structname></link>, and
|
||||
<link linkend="catalog-pg-amproc"><structname>pg_amproc</structname></link>.
|
||||
These entries allow the planner
|
||||
to determine what kinds of query qualifications can be used with
|
||||
indexes of this access method. Operator classes are described
|
||||
indexes of this access method. Operator families and classes are described
|
||||
in <xref linkend="xindex">, which is prerequisite material for reading
|
||||
this chapter.
|
||||
</para>
|
||||
@ -409,14 +411,14 @@ amrestrpos (IndexScanDesc scan);
|
||||
A scan key is the internal representation of a <literal>WHERE</> clause of
|
||||
the form <replaceable>index_key</> <replaceable>operator</>
|
||||
<replaceable>constant</>, where the index key is one of the columns of the
|
||||
index and the operator is one of the members of the operator class
|
||||
index and the operator is one of the members of the operator family
|
||||
associated with that index column. An index scan has zero or more scan
|
||||
keys, which are implicitly ANDed — the returned tuples are expected
|
||||
to satisfy all the indicated conditions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The operator class may indicate that the index is <firstterm>lossy</> for a
|
||||
The operator family may indicate that the index is <firstterm>lossy</> for a
|
||||
particular operator; this implies that the index scan will return all the
|
||||
entries that pass the scan key, plus possibly additional entries that do
|
||||
not. The core system's index-scan machinery will then apply that operator
|
||||
@ -429,7 +431,7 @@ amrestrpos (IndexScanDesc scan);
|
||||
Note that it is entirely up to the access method to ensure that it
|
||||
correctly finds all and only the entries passing all the given scan keys.
|
||||
Also, the core system will simply hand off all the <literal>WHERE</>
|
||||
clauses that match the index keys and operator classes, without any
|
||||
clauses that match the index keys and operator families, without any
|
||||
semantic analysis to determine whether they are redundant or
|
||||
contradictory. As an example, given
|
||||
<literal>WHERE x > 4 AND x > 14</> where <literal>x</> is a b-tree
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.66 2006/12/01 23:46:46 tgl Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.67 2006/12/23 00:43:08 tgl Exp $ -->
|
||||
|
||||
<chapter id="indexes">
|
||||
<title id="indexes-title">Indexes</title>
|
||||
@ -784,12 +784,16 @@ CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
|
||||
|
||||
|
||||
<sect1 id="indexes-opclass">
|
||||
<title>Operator Classes</title>
|
||||
<title>Operator Classes and Operator Families</title>
|
||||
|
||||
<indexterm zone="indexes-opclass">
|
||||
<primary>operator class</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm zone="indexes-opclass">
|
||||
<primary>operator family</primary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
An index definition may specify an <firstterm>operator
|
||||
class</firstterm> for each column of an index.
|
||||
@ -854,20 +858,32 @@ CREATE INDEX test_index ON test_table (col varchar_pattern_ops);
|
||||
SELECT am.amname AS index_method,
|
||||
opc.opcname AS opclass_name
|
||||
FROM pg_am am, pg_opclass opc
|
||||
WHERE opc.opcamid = am.oid
|
||||
WHERE opc.opcmethod = am.oid
|
||||
ORDER BY index_method, opclass_name;
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
It can be extended to show all the operators included in each class:
|
||||
<para>
|
||||
An operator class is actually just a subset of a larger structure called an
|
||||
<firstterm>operator family</>. In cases where several data types have
|
||||
similar behaviors, it is frequently useful to define cross-data-type
|
||||
operators and allow these to work with indexes. To do this, the operator
|
||||
classes for each of the types must be grouped into the same operator
|
||||
family. The cross-type operators are members of the family, but are not
|
||||
associated with any single class within the family.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This query shows all defined operator families and all
|
||||
the operators included in each family:
|
||||
<programlisting>
|
||||
SELECT am.amname AS index_method,
|
||||
opc.opcname AS opclass_name,
|
||||
opr.oid::regoperator AS opclass_operator
|
||||
FROM pg_am am, pg_opclass opc, pg_amop amop, pg_operator opr
|
||||
WHERE opc.opcamid = am.oid AND
|
||||
amop.amopclaid = opc.oid AND
|
||||
amop.amopopr = opr.oid
|
||||
ORDER BY index_method, opclass_name, opclass_operator;
|
||||
opf.opfname AS opfamily_name,
|
||||
amop.amopopr::regoperator AS opfamily_operator
|
||||
FROM pg_am am, pg_opfamily opf, pg_amop amop
|
||||
WHERE opf.opfmethod = am.oid AND
|
||||
amop.amopfamily = opf.oid
|
||||
ORDER BY index_method, opfamily_name, opfamily_operator;
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect1>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.45 2006/09/16 00:30:17 momjian Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.46 2006/12/23 00:43:08 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -26,8 +26,6 @@ CREATE OPERATOR <replaceable>name</replaceable> (
|
||||
[, COMMUTATOR = <replaceable class="parameter">com_op</replaceable> ] [, NEGATOR = <replaceable class="parameter">neg_op</replaceable> ]
|
||||
[, RESTRICT = <replaceable class="parameter">res_proc</replaceable> ] [, JOIN = <replaceable class="parameter">join_proc</replaceable> ]
|
||||
[, HASHES ] [, MERGES ]
|
||||
[, SORT1 = <replaceable class="parameter">left_sort_op</replaceable> ] [, SORT2 = <replaceable class="parameter">right_sort_op</replaceable> ]
|
||||
[, LTCMP = <replaceable class="parameter">less_than_op</replaceable> ] [, GTCMP = <replaceable class="parameter">greater_than_op</replaceable> ]
|
||||
)
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
@ -202,46 +200,6 @@ CREATE OPERATOR <replaceable>name</replaceable> (
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">left_sort_op</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If this operator can support a merge join, the less-than
|
||||
operator that sorts the left-hand data type of this operator.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">right_sort_op</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If this operator can support a merge join, the less-than
|
||||
operator that sorts the right-hand data type of this operator.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">less_than_op</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If this operator can support a merge join, the less-than
|
||||
operator that compares the input data types of this operator.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">greater_than_op</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If this operator can support a merge join, the greater-than
|
||||
operator that compares the input data types of this operator.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
||||
@ -261,6 +219,16 @@ COMMUTATOR = OPERATOR(myschema.===) ,
|
||||
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
|
||||
@ -285,11 +253,7 @@ CREATE OPERATOR === (
|
||||
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>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/xoper.sgml,v 1.36 2006/09/16 00:30:16 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/xoper.sgml,v 1.37 2006/12/23 00:43:08 tgl Exp $ -->
|
||||
|
||||
<sect1 id="xoper">
|
||||
<title>User-Defined Operators</title>
|
||||
@ -342,13 +342,13 @@ table1.column1 OP table2.column2
|
||||
|
||||
<para>
|
||||
To be marked <literal>HASHES</literal>, the join operator must appear
|
||||
in a hash index operator class. This is not enforced when you create
|
||||
the operator, since of course the referencing operator class couldn't
|
||||
in a hash index operator family. This is not enforced when you create
|
||||
the operator, since of course the referencing operator family couldn't
|
||||
exist yet. But attempts to use the operator in hash joins will fail
|
||||
at run time if no such operator class exists. The system needs the
|
||||
operator class to find the data-type-specific hash function for the
|
||||
at run time if no such operator family exists. The system needs the
|
||||
operator family to find the data-type-specific hash function for the
|
||||
operator's input data type. Of course, you must also supply a suitable
|
||||
hash function before you can create the operator class.
|
||||
hash function before you can create the operator family.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -390,7 +390,7 @@ table1.column1 OP table2.column2
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title><literal>MERGES</> (<literal>SORT1</>, <literal>SORT2</>, <literal>LTCMP</>, <literal>GTCMP</>)</title>
|
||||
<title><literal>MERGES</></title>
|
||||
|
||||
<para>
|
||||
The <literal>MERGES</literal> clause, if present, tells the system that
|
||||
@ -418,36 +418,13 @@ table1.column1 OP table2.column2
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Execution of a merge join requires that the system be able to identify
|
||||
four operators related to the merge-join equality operator: less-than
|
||||
comparison for the left operand data type, less-than comparison for the
|
||||
right operand data type, less-than comparison between the two data types, and
|
||||
greater-than comparison between the two data types. (These are actually
|
||||
four distinct operators if the merge-joinable operator has two different
|
||||
operand data types; but when the operand types are the same the three
|
||||
less-than operators are all the same operator.)
|
||||
It is possible to
|
||||
specify these operators individually by name, as the <literal>SORT1</>,
|
||||
<literal>SORT2</>, <literal>LTCMP</>, and <literal>GTCMP</> options
|
||||
respectively. The system will fill in the default names
|
||||
<literal><</>, <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>
|
||||
@ -474,13 +451,6 @@ table1.column1 OP table2.column2
|
||||
be transitive.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Bizarre results will ensue at run time if the four comparison
|
||||
operators you name do not sort the data values compatibly.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
@ -491,17 +461,5 @@ table1.column1 OP table2.column2
|
||||
attempt to use the operator for a merge join.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
In <productname>PostgreSQL</productname> versions before 7.3,
|
||||
the <literal>MERGES</> shorthand was not available: to make a
|
||||
merge-joinable operator one had to write both <literal>SORT1</> and
|
||||
<literal>SORT2</> explicitly. Also, the <literal>LTCMP</> and
|
||||
<literal>GTCMP</>
|
||||
options did not exist; the names of those operators were hardwired as
|
||||
<literal><</> and <literal>></> respectively.
|
||||
</para>
|
||||
</note>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
Reference in New Issue
Block a user