R-tree is dead ... long live GiST.
This commit is contained in:
parent
645adf5de8
commit
2a8d3d83ef
@ -10,7 +10,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
|
@ -5,8 +5,7 @@
|
||||
|
||||
#include "ltree.h"
|
||||
#include "access/gist.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/nbtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "utils/array.h"
|
||||
|
||||
#include "crc32.h"
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#include "ltree.h"
|
||||
#include "access/gist.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/nbtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "utils/array.h"
|
||||
#include "crc32.h"
|
||||
|
||||
|
@ -2,13 +2,10 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "access/tuptoaster.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "access/tuptoaster.h"
|
||||
|
||||
PG_FUNCTION_INFO_V1(gtrgm_in);
|
||||
Datum gtrgm_in(PG_FUNCTION_ARGS);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <float.h>
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
#include "segdata.h"
|
||||
@ -53,7 +53,7 @@ bool *gseg_same(SEG * b1, SEG * b2, bool *result);
|
||||
|
||||
|
||||
/*
|
||||
** R-tree suport functions
|
||||
** R-tree support functions
|
||||
*/
|
||||
bool seg_same(SEG * a, SEG * b);
|
||||
bool seg_contains_int(SEG * a, int *b);
|
||||
|
@ -4,11 +4,10 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/tuptoaster.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "access/tuptoaster.h"
|
||||
|
||||
#include "tsvector.h"
|
||||
#include "query.h"
|
||||
|
@ -15,10 +15,9 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "storage/bufpage.h"
|
||||
|
||||
#include "ts_cfg.h"
|
||||
#include "tsvector.h"
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.75 2005/11/04 23:13:59 petere Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.76 2005/11/07 17:36:44 tgl Exp $
|
||||
-->
|
||||
<chapter id="backup">
|
||||
<title>Backup and Restore</title>
|
||||
@ -1129,8 +1129,8 @@ restore_command = 'copy /mnt/server/archivedir/%f "%p"' # Windows
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Operations on hash and R-tree indexes are
|
||||
not presently WAL-logged, so replay will not update these index types.
|
||||
Operations on hash indexes are
|
||||
not presently WAL-logged, so replay will not update these indexes.
|
||||
The recommended workaround is to manually <command>REINDEX</> each
|
||||
such index after completing a recovery operation.
|
||||
</para>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.33 2005/10/25 13:38:09 momjian Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.34 2005/11/07 17:36:44 tgl Exp $
|
||||
Genetic Optimizer
|
||||
-->
|
||||
|
||||
@ -51,8 +51,8 @@ Genetic Optimizer
|
||||
caused by the support of a variety of <firstterm>join
|
||||
methods</firstterm> (e.g., nested loop, hash join, merge join in
|
||||
<productname>PostgreSQL</productname>) to process individual joins
|
||||
and a diversity of <firstterm>indexes</firstterm> (e.g., R-tree,
|
||||
B-tree, hash in <productname>PostgreSQL</productname>) as access
|
||||
and a diversity of <firstterm>indexes</firstterm> (e.g.,
|
||||
B-tree, hash, GiST in <productname>PostgreSQL</productname>) as access
|
||||
paths for relations.
|
||||
</para>
|
||||
|
||||
|
@ -1,25 +1,22 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.24 2005/11/04 23:14:00 petere Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.25 2005/11/07 17:36:44 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="GiST">
|
||||
<title>GiST Indexes</title>
|
||||
|
||||
<sect1 id="gist-intro">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
<indexterm>
|
||||
<primary>index</primary>
|
||||
<secondary>GiST</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>GiST</primary>
|
||||
<see>index</see>
|
||||
</indexterm>
|
||||
|
||||
<sect1 id="gist-intro">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
<acronym>GiST</acronym> stands for Generalized Search Tree. It is a
|
||||
balanced, tree-structured access method, that acts as a base template in
|
||||
which to implement arbitrary indexing schemes. B+-trees, R-trees and many
|
||||
which to implement arbitrary indexing schemes. B-trees, R-trees and many
|
||||
other indexing schemes can be implemented in <acronym>GiST</acronym>.
|
||||
</para>
|
||||
|
||||
@ -60,17 +57,17 @@ $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.24 2005/11/04 23:14:00 petere Exp
|
||||
<para>
|
||||
This extensibility should not be confused with the extensibility of the
|
||||
other standard search trees in terms of the data they can handle. For
|
||||
example, <productname>PostgreSQL</productname> supports extensible B+-trees
|
||||
and R-trees. That means that you can use
|
||||
<productname>PostgreSQL</productname> to build a B+-tree or R-tree over any
|
||||
data type you want. But B+-trees only support range predicates
|
||||
example, <productname>PostgreSQL</productname> supports extensible B-trees
|
||||
and hash indexes. That means that you can use
|
||||
<productname>PostgreSQL</productname> to build a B-tree or hash over any
|
||||
data type you want. But B-trees only support range predicates
|
||||
(<literal><</literal>, <literal>=</literal>, <literal>></literal>),
|
||||
and R-trees only support n-D range queries (contains, contained, equals).
|
||||
and hash indexes only support equality queries.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So if you index, say, an image collection with a
|
||||
<productname>PostgreSQL</productname> B+-tree, you can only issue queries
|
||||
<productname>PostgreSQL</productname> B-tree, you can only issue queries
|
||||
such as <quote>is imagex equal to imagey</quote>, <quote>is imagex less
|
||||
than imagey</quote> and <quote>is imagex greater than imagey</quote>?
|
||||
Depending on how you define <quote>equals</quote>, <quote>less than</quote>
|
||||
@ -84,7 +81,7 @@ $PostgreSQL: pgsql/doc/src/sgml/gist.sgml,v 1.24 2005/11/04 23:14:00 petere Exp
|
||||
All it takes to get a <acronym>GiST</acronym> access method up and running
|
||||
is to implement seven user-defined methods, which define the behavior of
|
||||
keys in the tree. Of course these methods have to be pretty fancy to
|
||||
support fancy queries, but for all the standard queries (B+-trees,
|
||||
support fancy queries, but for all the standard queries (B-trees,
|
||||
R-trees, etc.) they're relatively straightforward. In short,
|
||||
<acronym>GiST</acronym> combines extensibility along with generality, code
|
||||
reuse, and a clean interface.
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.54 2005/11/04 23:14:00 petere Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indices.sgml,v 1.55 2005/11/07 17:36:44 tgl Exp $ -->
|
||||
|
||||
<chapter id="indexes">
|
||||
<title id="indexes-title">Indexes</title>
|
||||
@ -104,7 +104,7 @@ CREATE INDEX test1_id_index ON test1 (id);
|
||||
|
||||
<para>
|
||||
<productname>PostgreSQL</productname> provides several index types:
|
||||
B-tree, R-tree, Hash, and GiST. Each index type uses a different
|
||||
B-tree, Hash, and GiST. Each index type uses a different
|
||||
algorithm that is best suited to different types of queries.
|
||||
By default, the <command>CREATE INDEX</command> command will create a
|
||||
B-tree index, which fits the most common situations.
|
||||
@ -155,20 +155,51 @@ CREATE INDEX test1_id_index ON test1 (id);
|
||||
<para>
|
||||
<indexterm>
|
||||
<primary>index</primary>
|
||||
<secondary>R-tree</secondary>
|
||||
<secondary>hash</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>R-tree</primary>
|
||||
<primary>hash</primary>
|
||||
<see>index</see>
|
||||
</indexterm>
|
||||
R-tree indexes are suited for queries on two-dimensional spatial data.
|
||||
To create an R-tree index, use a command of the form
|
||||
Hash indexes can only handle simple equality comparisons.
|
||||
The query planner will consider using a hash index whenever an
|
||||
indexed column is involved in a comparison using the
|
||||
<literal>=</literal> operator. The following command is used to
|
||||
create a hash index:
|
||||
<synopsis>
|
||||
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING rtree (<replaceable>column</replaceable>);
|
||||
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING hash (<replaceable>column</replaceable>);
|
||||
</synopsis>
|
||||
The <productname>PostgreSQL</productname> query planner will
|
||||
consider using an R-tree index whenever an indexed column is
|
||||
involved in a comparison using one of these operators:
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Testing has shown <productname>PostgreSQL</productname>'s hash
|
||||
indexes to perform no better than B-tree indexes, and the
|
||||
index size and build time for hash indexes is much worse.
|
||||
Furthermore, hash index operations are not presently WAL-logged,
|
||||
so hash indexes may need to be rebuilt with <command>REINDEX</>
|
||||
after a database crash.
|
||||
For these reasons, hash index use is presently discouraged.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
<indexterm>
|
||||
<primary>index</primary>
|
||||
<secondary>GiST</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>GiST</primary>
|
||||
<see>index</see>
|
||||
</indexterm>
|
||||
GiST indexes are not a single kind of index, but rather an infrastructure
|
||||
within which many different indexing strategies can be implemented.
|
||||
Accordingly, the particular operators with which a GiST index can be
|
||||
used vary depending on the indexing strategy (the <firstterm>operator
|
||||
class</>). As an example, the standard distribution of
|
||||
<productname>PostgreSQL</productname> includes GiST operator classes
|
||||
for several two-dimensional geometric data types, which support indexed
|
||||
queries using these operators:
|
||||
|
||||
<simplelist>
|
||||
<member><literal><<</literal></member>
|
||||
@ -187,64 +218,10 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable>
|
||||
|
||||
(See <xref linkend="functions-geometry"> for the meaning of
|
||||
these operators.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<indexterm>
|
||||
<primary>index</primary>
|
||||
<secondary>hash</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>hash</primary>
|
||||
<see>index</see>
|
||||
</indexterm>
|
||||
Hash indexes can only handle simple equality comparisons.
|
||||
The query planner will consider using a hash index whenever an
|
||||
indexed column is involved in a comparison using the
|
||||
<literal>=</literal> operator. The following command is used to
|
||||
create a hash index:
|
||||
<synopsis>
|
||||
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING hash (<replaceable>column</replaceable>);
|
||||
</synopsis>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
GiST indexes are not a single kind of index, but rather an infrastructure
|
||||
within which many different indexing strategies can be implemented.
|
||||
Accordingly, the particular operators with which a GiST index can be
|
||||
used vary depending on the indexing strategy (the <firstterm>operator
|
||||
class</>). The standard distribution of
|
||||
<productname>PostgreSQL</productname> includes GiST operator classes
|
||||
equivalent to the R-tree operator classes, and many other GiST operator
|
||||
Many other GiST operator
|
||||
classes are available in the <literal>contrib</> collection or as separate
|
||||
projects. For more information see <xref linkend="GiST">.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Testing has shown <productname>PostgreSQL</productname>'s hash
|
||||
indexes to perform no better than B-tree indexes, and the
|
||||
index size and build time for hash indexes is much worse.
|
||||
Furthermore, hash index operations are not presently WAL-logged,
|
||||
so hash indexes may need to be rebuilt with <command>REINDEX</>
|
||||
after a database crash.
|
||||
For these reasons, hash index use is presently discouraged.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Similarly, R-tree indexes do not seem to have any performance
|
||||
advantages compared to the equivalent operations of GiST indexes.
|
||||
Like hash indexes, they are not WAL-logged and may need
|
||||
reindexing after a database crash.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
While the problems with hash indexes may be fixed eventually,
|
||||
it is likely that the R-tree index type will be retired in a future
|
||||
release. Users are encouraged to migrate applications that use R-tree
|
||||
indexes to GiST indexes.
|
||||
</para>
|
||||
</note>
|
||||
</sect1>
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.52 2005/10/21 01:41:28 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/mvcc.sgml,v 2.53 2005/11/07 17:36:44 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="mvcc">
|
||||
@ -991,18 +991,6 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
R-tree indexes
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Share/exclusive index-level locks are used for read/write access.
|
||||
Locks are released after the entire command is done.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
@ -1012,8 +1000,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
|
||||
indexes, they are the recommended index type for concurrent
|
||||
applications that need to index scalar data. When dealing with
|
||||
non-scalar data, B-trees are not useful, and GiST indexes should
|
||||
be used instead. R-tree indexes are deprecated and are likely
|
||||
to disappear entirely in a future release.
|
||||
be used instead.
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.51 2005/01/04 00:39:53 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.52 2005/11/07 17:36:44 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -34,7 +34,7 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">name</replaceable> ON <re
|
||||
<command>CREATE INDEX</command> constructs an index <replaceable
|
||||
class="parameter">index_name</replaceable> on the specified table.
|
||||
Indexes are primarily used to enhance database performance (though
|
||||
inappropriate use will result in slower performance).
|
||||
inappropriate use can result in slower performance).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -55,11 +55,7 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">name</replaceable> ON <re
|
||||
|
||||
<para>
|
||||
<productname>PostgreSQL</productname> provides the index methods
|
||||
B-tree, R-tree, hash, and GiST. The B-tree index method is an
|
||||
implementation of Lehman-Yao high-concurrency B-trees. The R-tree
|
||||
index method implements standard R-trees using Guttman's quadratic
|
||||
split algorithm. The hash index method is an implementation of
|
||||
Litwin's linear hashing. Users can also define their own index
|
||||
B-tree, hash, and GiST. Users can also define their own index
|
||||
methods, but that is fairly complicated.
|
||||
</para>
|
||||
|
||||
@ -137,9 +133,9 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">name</replaceable> ON <re
|
||||
<term><replaceable class="parameter">method</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the method to be used for the index. Choices are
|
||||
The name of the index method to be used. Choices are
|
||||
<literal>btree</literal>, <literal>hash</literal>,
|
||||
<literal>rtree</literal>, and <literal>gist</literal>. The
|
||||
and <literal>gist</literal>. The
|
||||
default method is <literal>btree</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
@ -243,6 +239,15 @@ CREATE [ UNIQUE ] INDEX <replaceable class="parameter">name</replaceable> ON <re
|
||||
The best way to use indexes in such cases is to create a partial index
|
||||
using an <literal>IS NULL</> predicate.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Prior releases of <productname>PostgreSQL</productname> also had an
|
||||
R-tree index method. This method has been removed because
|
||||
it had no significant advantages over the GiST method.
|
||||
If <literal>USING rtree</> is specified, <command>CREATE INDEX</>
|
||||
will interpret it as <literal>USING gist</>, to simplify conversion
|
||||
of old databases to GiST.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -270,13 +275,13 @@ CREATE INDEX code_idx ON films(code) TABLESPACE indexspace;
|
||||
Is this example correct?
|
||||
</comment>
|
||||
<para>
|
||||
To create a R-tree index on a point attribute so that we
|
||||
To create a GiST index on a point attribute so that we
|
||||
can efficiently use box operators on the result of the
|
||||
conversion function:
|
||||
</para>
|
||||
<programlisting>
|
||||
CREATE INDEX pointloc
|
||||
ON points USING RTREE (point2box(location) box_ops);
|
||||
ON points USING GIST (point2box(location) box_ops);
|
||||
SELECT * FROM points
|
||||
WHERE point2box(points.pointloc) = boxes.box;
|
||||
</programlisting>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.41 2005/07/19 01:27:59 neilc Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.42 2005/11/07 17:36:44 tgl Exp $
|
||||
-->
|
||||
|
||||
<sect1 id="xindex">
|
||||
@ -170,8 +170,12 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.41 2005/07/19 01:27:59 neilc Exp
|
||||
</table>
|
||||
|
||||
<para>
|
||||
R-tree indexes express relationships in two-dimensional space.
|
||||
They use twelve strategies, shown in
|
||||
GiST indexes are even more flexible: they do not have a fixed set of
|
||||
strategies at all. Instead, the <quote>consistency</> support routine
|
||||
of each particular GiST operator class interprets the strategy numbers
|
||||
however it likes. As an example, several of the built-in GiST index
|
||||
operator classes index two-dimensional geometric objects, providing
|
||||
the <quote>R-tree</> strategies shown in
|
||||
<xref linkend="xindex-rtree-strat-table">. Four of these are true
|
||||
two-dimensional tests (overlaps, same, contains, contained by);
|
||||
four of them consider only the X direction; and the other four
|
||||
@ -179,7 +183,7 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.41 2005/07/19 01:27:59 neilc Exp
|
||||
</para>
|
||||
|
||||
<table tocentry="1" id="xindex-rtree-strat-table">
|
||||
<title>R-tree Strategies</title>
|
||||
<title>GiST Two-Dimensional <quote>R-tree</> Strategies</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
@ -240,13 +244,6 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.41 2005/07/19 01:27:59 neilc Exp
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
GiST indexes are even more flexible: they do not have a fixed set of
|
||||
strategies at all. Instead, the <quote>consistency</> support routine
|
||||
of each particular GiST operator class interprets the strategy numbers
|
||||
however it likes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note that all strategy operators return Boolean values. In
|
||||
practice, all operators defined as index method strategies must
|
||||
@ -274,9 +271,8 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.41 2005/07/19 01:27:59 neilc Exp
|
||||
additional support routines in order to work. For example, the B-tree
|
||||
index method must be able to compare two keys and determine whether one
|
||||
is greater than, equal to, or less than the other. Similarly, the
|
||||
R-tree index method must be able to compute
|
||||
intersections, unions, and sizes of rectangles. These
|
||||
operations do not correspond to operators used in qualifications in
|
||||
hash index method must be able to compute hash codes for key values.
|
||||
These operations do not correspond to operators used in qualifications in
|
||||
SQL commands; they are administrative routines used by
|
||||
the index methods, internally.
|
||||
</para>
|
||||
@ -339,37 +335,6 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.41 2005/07/19 01:27:59 neilc Exp
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
R-tree indexes require three support functions,
|
||||
shown in <xref linkend="xindex-rtree-support-table">.
|
||||
</para>
|
||||
|
||||
<table tocentry="1" id="xindex-rtree-support-table">
|
||||
<title>R-tree Support Functions</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Function</entry>
|
||||
<entry>Support Number</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>union</entry>
|
||||
<entry>1</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>intersection</entry>
|
||||
<entry>2</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>size</entry>
|
||||
<entry>3</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
GiST indexes require seven support functions,
|
||||
shown in <xref linkend="xindex-gist-support-table">.
|
||||
@ -746,7 +711,7 @@ SELECT * FROM table WHERE integer_column < 4;
|
||||
</programlisting>
|
||||
can be satisfied exactly by a B-tree index on the integer column.
|
||||
But there are cases where an index is useful as an inexact guide to
|
||||
the matching rows. For example, if an R-tree index stores only
|
||||
the matching rows. For example, if a GiST index stores only
|
||||
bounding boxes for objects, then it cannot exactly satisfy a <literal>WHERE</>
|
||||
condition that tests overlap between nonrectangular objects such as
|
||||
polygons. Yet we could use the index to find objects whose bounding
|
||||
|
@ -1,14 +1,14 @@
|
||||
#
|
||||
# Makefile for the access methods module
|
||||
#
|
||||
# $PostgreSQL: pgsql/src/backend/access/Makefile,v 1.9 2003/11/29 19:51:39 pgsql Exp $
|
||||
# $PostgreSQL: pgsql/src/backend/access/Makefile,v 1.10 2005/11/07 17:36:44 tgl Exp $
|
||||
#
|
||||
|
||||
subdir = src/backend/access
|
||||
top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
SUBDIRS := common gist hash heap index nbtree rtree transam
|
||||
SUBDIRS := common gist hash heap index nbtree transam
|
||||
SUBDIROBJS := $(SUBDIRS:%=%/SUBSYS.o)
|
||||
|
||||
all: SUBSYS.o
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.3 2005/10/15 02:49:08 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.4 2005/11/07 17:36:44 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/itup.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/skey.h"
|
||||
#include "utils/geo_decls.h"
|
||||
|
||||
|
||||
@ -40,6 +40,47 @@ static bool rtree_internal_consistent(BOX *key, BOX *query,
|
||||
* Box ops
|
||||
**************************************************/
|
||||
|
||||
static Datum
|
||||
rt_box_union(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Max(a->high.x, b->high.x);
|
||||
n->high.y = Max(a->high.y, b->high.y);
|
||||
n->low.x = Min(a->low.x, b->low.x);
|
||||
n->low.y = Min(a->low.y, b->low.y);
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
static Datum
|
||||
rt_box_inter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Min(a->high.x, b->high.x);
|
||||
n->high.y = Min(a->high.y, b->high.y);
|
||||
n->low.x = Max(a->low.x, b->low.x);
|
||||
n->low.y = Max(a->low.y, b->low.y);
|
||||
|
||||
if (n->high.x < n->low.x || n->high.y < n->low.y)
|
||||
{
|
||||
pfree(n);
|
||||
/* Indicate "no intersection" by returning NULL pointer */
|
||||
n = NULL;
|
||||
}
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* The GiST Consistent method for boxes
|
||||
*
|
||||
@ -493,8 +534,6 @@ size_box(Datum dbox)
|
||||
*
|
||||
* We can use the same function since all types use bounding boxes as the
|
||||
* internal-page representation.
|
||||
*
|
||||
* This implements the same logic as the rtree internal-page strategy map.
|
||||
*/
|
||||
static bool
|
||||
rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
|
||||
|
@ -1,31 +0,0 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile--
|
||||
# Makefile for access/rtree
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $PostgreSQL: pgsql/src/backend/access/rtree/Makefile,v 1.11 2003/11/29 19:51:40 pgsql Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/backend/access/rtree
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = rtget.o rtproc.o rtree.o rtscan.o rtstrat.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
SUBSYS.o: $(OBJS)
|
||||
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
|
||||
|
||||
depend dep:
|
||||
$(CC) -MM $(CFLAGS) *.c >depend
|
||||
|
||||
clean:
|
||||
rm -f SUBSYS.o $(OBJS)
|
||||
|
||||
ifeq (depend,$(wildcard depend))
|
||||
include depend
|
||||
endif
|
||||
|
@ -1,281 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtget.c
|
||||
* fetch tuples from an rtree scan.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtget.c,v 1.37 2005/10/15 02:49:09 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/iqual.h"
|
||||
#include "access/relscan.h"
|
||||
#include "access/rtree.h"
|
||||
#include "pgstat.h"
|
||||
|
||||
|
||||
static OffsetNumber findnext(IndexScanDesc s, OffsetNumber n,
|
||||
ScanDirection dir);
|
||||
static bool rtnext(IndexScanDesc s, ScanDirection dir);
|
||||
|
||||
|
||||
Datum
|
||||
rtgettuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ScanDirection dir = (ScanDirection) PG_GETARG_INT32(1);
|
||||
RTreeScanOpaque so = (RTreeScanOpaque) s->opaque;
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
/*
|
||||
* If we've already produced a tuple and the executor has informed us that
|
||||
* it should be marked "killed", do so now.
|
||||
*/
|
||||
if (s->kill_prior_tuple && ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
|
||||
SetBufferCommitInfoNeedsSave(so->curbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next tuple that matches the search key; if asked to skip killed
|
||||
* tuples, find the first non-killed tuple that matches. Return as soon as
|
||||
* we've run out of matches or we've found an acceptable match.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
bool res = rtnext(s, dir);
|
||||
|
||||
if (res && s->ignore_killed_tuples)
|
||||
{
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
if (ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
continue;
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
}
|
||||
|
||||
Datum
|
||||
rtgetmulti(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1);
|
||||
int32 max_tids = PG_GETARG_INT32(2);
|
||||
int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3);
|
||||
RTreeScanOpaque so = (RTreeScanOpaque) s->opaque;
|
||||
bool res = true;
|
||||
int32 ntids = 0;
|
||||
|
||||
/* XXX generic implementation: loop around guts of rtgettuple */
|
||||
while (ntids < max_tids)
|
||||
{
|
||||
res = rtnext(s, ForwardScanDirection);
|
||||
if (res && s->ignore_killed_tuples)
|
||||
{
|
||||
Page page;
|
||||
OffsetNumber offnum;
|
||||
|
||||
offnum = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
page = BufferGetPage(so->curbuf);
|
||||
if (ItemIdDeleted(PageGetItemId(page, offnum)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
tids[ntids] = s->xs_ctup.t_self;
|
||||
ntids++;
|
||||
}
|
||||
|
||||
*returned_tids = ntids;
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
static bool
|
||||
rtnext(IndexScanDesc s, ScanDirection dir)
|
||||
{
|
||||
Page p;
|
||||
OffsetNumber n;
|
||||
RTreePageOpaque po;
|
||||
RTreeScanOpaque so;
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
if (!ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
/* first call: start at the root */
|
||||
Assert(BufferIsValid(so->curbuf) == false);
|
||||
so->curbuf = ReadBuffer(s->indexRelation, P_ROOT);
|
||||
pgstat_count_index_scan(&s->xs_pgstat_info);
|
||||
}
|
||||
|
||||
p = BufferGetPage(so->curbuf);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
if (!ItemPointerIsValid(&(s->currentItemData)))
|
||||
{
|
||||
/* first call: start at first/last offset */
|
||||
if (ScanDirectionIsForward(dir))
|
||||
n = FirstOffsetNumber;
|
||||
else
|
||||
n = PageGetMaxOffsetNumber(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* go on to the next offset */
|
||||
n = ItemPointerGetOffsetNumber(&(s->currentItemData));
|
||||
if (ScanDirectionIsForward(dir))
|
||||
n = OffsetNumberNext(n);
|
||||
else
|
||||
n = OffsetNumberPrev(n);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
IndexTuple it;
|
||||
RTSTACK *stk;
|
||||
|
||||
n = findnext(s, n, dir);
|
||||
|
||||
/* no match on this page, so read in the next stack entry */
|
||||
if (n == InvalidOffsetNumber)
|
||||
{
|
||||
/* if out of stack entries, we're done */
|
||||
if (so->s_stack == NULL)
|
||||
{
|
||||
ReleaseBuffer(so->curbuf);
|
||||
so->curbuf = InvalidBuffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
stk = so->s_stack;
|
||||
so->curbuf = ReleaseAndReadBuffer(so->curbuf, s->indexRelation,
|
||||
stk->rts_blk);
|
||||
p = BufferGetPage(so->curbuf);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
n = OffsetNumberPrev(stk->rts_child);
|
||||
else
|
||||
n = OffsetNumberNext(stk->rts_child);
|
||||
so->s_stack = stk->rts_parent;
|
||||
pfree(stk);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (po->flags & F_LEAF)
|
||||
{
|
||||
ItemPointerSet(&(s->currentItemData),
|
||||
BufferGetBlockNumber(so->curbuf),
|
||||
n);
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
s->xs_ctup.t_self = it->t_tid;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockNumber blk;
|
||||
|
||||
stk = (RTSTACK *) palloc(sizeof(RTSTACK));
|
||||
stk->rts_child = n;
|
||||
stk->rts_blk = BufferGetBlockNumber(so->curbuf);
|
||||
stk->rts_parent = so->s_stack;
|
||||
so->s_stack = stk;
|
||||
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
blk = ItemPointerGetBlockNumber(&(it->t_tid));
|
||||
|
||||
/*
|
||||
* Note that we release the pin on the page as we descend down the
|
||||
* tree, even though there's a good chance we'll eventually need
|
||||
* to re-read the buffer later in this scan. This may or may not
|
||||
* be optimal, but it doesn't seem likely to make a huge
|
||||
* performance difference either way.
|
||||
*/
|
||||
so->curbuf = ReleaseAndReadBuffer(so->curbuf, s->indexRelation, blk);
|
||||
p = BufferGetPage(so->curbuf);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
n = PageGetMaxOffsetNumber(p);
|
||||
else
|
||||
n = FirstOffsetNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset of the next matching index entry. We begin the
|
||||
* search at offset "n" and search for matches in the direction
|
||||
* "dir". If no more matching entries are found on the page,
|
||||
* InvalidOffsetNumber is returned.
|
||||
*/
|
||||
static OffsetNumber
|
||||
findnext(IndexScanDesc s, OffsetNumber n, ScanDirection dir)
|
||||
{
|
||||
OffsetNumber maxoff;
|
||||
IndexTuple it;
|
||||
RTreePageOpaque po;
|
||||
RTreeScanOpaque so;
|
||||
Page p;
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
p = BufferGetPage(so->curbuf);
|
||||
|
||||
maxoff = PageGetMaxOffsetNumber(p);
|
||||
po = (RTreePageOpaque) PageGetSpecialPointer(p);
|
||||
|
||||
/*
|
||||
* If we modified the index during the scan, we may have a pointer to a
|
||||
* ghost tuple, before the scan. If this is the case, back up one.
|
||||
*/
|
||||
|
||||
if (so->s_flags & RTS_CURBEFORE)
|
||||
{
|
||||
so->s_flags &= ~RTS_CURBEFORE;
|
||||
n = OffsetNumberPrev(n);
|
||||
}
|
||||
|
||||
while (n >= FirstOffsetNumber && n <= maxoff)
|
||||
{
|
||||
it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n));
|
||||
if (po->flags & F_LEAF)
|
||||
{
|
||||
if (index_keytest(it,
|
||||
RelationGetDescr(s->indexRelation),
|
||||
s->numberOfKeys, s->keyData))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index_keytest(it,
|
||||
RelationGetDescr(s->indexRelation),
|
||||
so->s_internalNKey, so->s_internalKey))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ScanDirectionIsBackward(dir))
|
||||
n = OffsetNumberPrev(n);
|
||||
else
|
||||
n = OffsetNumberNext(n);
|
||||
}
|
||||
|
||||
if (n >= FirstOffsetNumber && n <= maxoff)
|
||||
return n; /* found a match on this page */
|
||||
else
|
||||
return InvalidOffsetNumber; /* no match, go to next page */
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtproc.c
|
||||
* pg_amproc entries for rtrees.
|
||||
*
|
||||
* NOTE: for largely-historical reasons, the intersection functions should
|
||||
* return a NULL pointer (*not* an SQL null value) to indicate "no
|
||||
* intersection". The size functions must be prepared to accept such
|
||||
* a pointer and return 0. This convention means that only pass-by-reference
|
||||
* data types can be used as the output of the union and intersection
|
||||
* routines, but that's not a big problem.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtproc.c,v 1.43 2005/10/15 02:49:09 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "utils/geo_decls.h"
|
||||
|
||||
|
||||
Datum
|
||||
rt_box_union(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Max(a->high.x, b->high.x);
|
||||
n->high.y = Max(a->high.y, b->high.y);
|
||||
n->low.x = Min(a->low.x, b->low.x);
|
||||
n->low.y = Min(a->low.y, b->low.y);
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_box_inter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
BOX *b = PG_GETARG_BOX_P(1);
|
||||
BOX *n;
|
||||
|
||||
n = (BOX *) palloc(sizeof(BOX));
|
||||
|
||||
n->high.x = Min(a->high.x, b->high.x);
|
||||
n->high.y = Min(a->high.y, b->high.y);
|
||||
n->low.x = Max(a->low.x, b->low.x);
|
||||
n->low.y = Max(a->low.y, b->low.y);
|
||||
|
||||
if (n->high.x < n->low.x || n->high.y < n->low.y)
|
||||
{
|
||||
pfree(n);
|
||||
/* Indicate "no intersection" by returning NULL pointer */
|
||||
n = NULL;
|
||||
}
|
||||
|
||||
PG_RETURN_BOX_P(n);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_box_size(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BOX *a = PG_GETARG_BOX_P(0);
|
||||
|
||||
/* NB: size is an output argument */
|
||||
float *size = (float *) PG_GETARG_POINTER(1);
|
||||
|
||||
if (a == NULL || a->high.x <= a->low.x || a->high.y <= a->low.y)
|
||||
*size = 0.0;
|
||||
else
|
||||
*size = (float) ((a->high.x - a->low.x) * (a->high.y - a->low.y));
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_poly_union(PG_FUNCTION_ARGS)
|
||||
{
|
||||
POLYGON *a = PG_GETARG_POLYGON_P(0);
|
||||
POLYGON *b = PG_GETARG_POLYGON_P(1);
|
||||
POLYGON *p;
|
||||
|
||||
p = (POLYGON *) palloc0(sizeof(POLYGON)); /* zero any holes */
|
||||
p->size = sizeof(POLYGON);
|
||||
p->npts = 0;
|
||||
p->boundbox.high.x = Max(a->boundbox.high.x, b->boundbox.high.x);
|
||||
p->boundbox.high.y = Max(a->boundbox.high.y, b->boundbox.high.y);
|
||||
p->boundbox.low.x = Min(a->boundbox.low.x, b->boundbox.low.x);
|
||||
p->boundbox.low.y = Min(a->boundbox.low.y, b->boundbox.low.y);
|
||||
|
||||
/* Avoid leaking memory when handed toasted input. */
|
||||
PG_FREE_IF_COPY(a, 0);
|
||||
PG_FREE_IF_COPY(b, 1);
|
||||
|
||||
PG_RETURN_POLYGON_P(p);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_poly_inter(PG_FUNCTION_ARGS)
|
||||
{
|
||||
POLYGON *a = PG_GETARG_POLYGON_P(0);
|
||||
POLYGON *b = PG_GETARG_POLYGON_P(1);
|
||||
POLYGON *p;
|
||||
|
||||
p = (POLYGON *) palloc0(sizeof(POLYGON)); /* zero any holes */
|
||||
p->size = sizeof(POLYGON);
|
||||
p->npts = 0;
|
||||
p->boundbox.high.x = Min(a->boundbox.high.x, b->boundbox.high.x);
|
||||
p->boundbox.high.y = Min(a->boundbox.high.y, b->boundbox.high.y);
|
||||
p->boundbox.low.x = Max(a->boundbox.low.x, b->boundbox.low.x);
|
||||
p->boundbox.low.y = Max(a->boundbox.low.y, b->boundbox.low.y);
|
||||
|
||||
if (p->boundbox.high.x < p->boundbox.low.x ||
|
||||
p->boundbox.high.y < p->boundbox.low.y)
|
||||
{
|
||||
pfree(p);
|
||||
/* Indicate "no intersection" by returning NULL pointer */
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
/* Avoid leaking memory when handed toasted input. */
|
||||
PG_FREE_IF_COPY(a, 0);
|
||||
PG_FREE_IF_COPY(b, 1);
|
||||
|
||||
PG_RETURN_POLYGON_P(p);
|
||||
}
|
||||
|
||||
Datum
|
||||
rt_poly_size(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Pointer aptr = PG_GETARG_POINTER(0);
|
||||
|
||||
/* NB: size is an output argument */
|
||||
float *size = (float *) PG_GETARG_POINTER(1);
|
||||
POLYGON *a;
|
||||
double xdim,
|
||||
ydim;
|
||||
|
||||
/*
|
||||
* Can't just use GETARG because of possibility that input is NULL; since
|
||||
* POLYGON is toastable, GETARG will try to inspect its value
|
||||
*/
|
||||
if (aptr == NULL)
|
||||
{
|
||||
*size = 0.0;
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
/* Now safe to apply GETARG */
|
||||
a = PG_GETARG_POLYGON_P(0);
|
||||
|
||||
if (a->boundbox.high.x <= a->boundbox.low.x ||
|
||||
a->boundbox.high.y <= a->boundbox.low.y)
|
||||
*size = 0.0;
|
||||
else
|
||||
{
|
||||
xdim = (a->boundbox.high.x - a->boundbox.low.x);
|
||||
ydim = (a->boundbox.high.y - a->boundbox.low.y);
|
||||
|
||||
*size = (float) (xdim * ydim);
|
||||
}
|
||||
|
||||
/* Avoid leaking memory when handed toasted input. */
|
||||
PG_FREE_IF_COPY(a, 0);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,493 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtscan.c
|
||||
* routines to manage scans on index relations
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtscan.c,v 1.60 2005/10/15 02:49:09 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/rtree.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/resowner.h"
|
||||
|
||||
|
||||
/* routines defined and used here */
|
||||
static void rtregscan(IndexScanDesc s);
|
||||
static void rtdropscan(IndexScanDesc s);
|
||||
static void rtadjone(IndexScanDesc s, int op, BlockNumber blkno,
|
||||
OffsetNumber offnum);
|
||||
static void adjuststack(RTSTACK *stk, BlockNumber blkno);
|
||||
static void adjustiptr(IndexScanDesc s, ItemPointer iptr,
|
||||
int op, BlockNumber blkno, OffsetNumber offnum);
|
||||
|
||||
/*
|
||||
* Whenever we start an rtree scan in a backend, we register it in private
|
||||
* space. Then if the rtree index gets updated, we check all registered
|
||||
* scans and adjust them if the tuple they point at got moved by the
|
||||
* update. We only need to do this in private space, because when we update
|
||||
* an rtree we have a write lock on the tree, so no other process can have
|
||||
* any locks at all on it. A single transaction can have write and read
|
||||
* locks on the same object, so that's why we need to handle this case.
|
||||
*/
|
||||
|
||||
typedef struct RTScanListData
|
||||
{
|
||||
IndexScanDesc rtsl_scan;
|
||||
ResourceOwner rtsl_owner;
|
||||
struct RTScanListData *rtsl_next;
|
||||
} RTScanListData;
|
||||
|
||||
typedef RTScanListData *RTScanList;
|
||||
|
||||
/* pointer to list of local scans on rtrees */
|
||||
static RTScanList RTScans = NULL;
|
||||
|
||||
Datum
|
||||
rtbeginscan(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation r = (Relation) PG_GETARG_POINTER(0);
|
||||
int nkeys = PG_GETARG_INT32(1);
|
||||
ScanKey key = (ScanKey) PG_GETARG_POINTER(2);
|
||||
IndexScanDesc s;
|
||||
|
||||
s = RelationGetIndexScan(r, nkeys, key);
|
||||
|
||||
rtregscan(s);
|
||||
|
||||
PG_RETURN_POINTER(s);
|
||||
}
|
||||
|
||||
Datum
|
||||
rtrescan(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
ScanKey key = (ScanKey) PG_GETARG_POINTER(1);
|
||||
RTreeScanOpaque p;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Clear all the pointers.
|
||||
*/
|
||||
ItemPointerSetInvalid(&s->currentItemData);
|
||||
ItemPointerSetInvalid(&s->currentMarkData);
|
||||
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
if (p != NULL)
|
||||
{
|
||||
/* rescan an existing indexscan --- reset state */
|
||||
freestack(p->s_stack);
|
||||
freestack(p->s_markstk);
|
||||
p->s_stack = p->s_markstk = NULL;
|
||||
p->s_flags = 0x0;
|
||||
/* drop pins on buffers -- no locks held */
|
||||
if (BufferIsValid(p->curbuf))
|
||||
{
|
||||
ReleaseBuffer(p->curbuf);
|
||||
p->curbuf = InvalidBuffer;
|
||||
}
|
||||
if (BufferIsValid(p->markbuf))
|
||||
{
|
||||
ReleaseBuffer(p->markbuf);
|
||||
p->markbuf = InvalidBuffer;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialize opaque data */
|
||||
p = (RTreeScanOpaque) palloc(sizeof(RTreeScanOpaqueData));
|
||||
p->s_stack = p->s_markstk = NULL;
|
||||
p->curbuf = p->markbuf = InvalidBuffer;
|
||||
p->s_internalNKey = s->numberOfKeys;
|
||||
p->s_flags = 0x0;
|
||||
s->opaque = p;
|
||||
if (s->numberOfKeys > 0)
|
||||
p->s_internalKey = (ScanKey) palloc(sizeof(ScanKeyData) * s->numberOfKeys);
|
||||
}
|
||||
|
||||
/* Update scan key, if a new one is given */
|
||||
if (key && s->numberOfKeys > 0)
|
||||
{
|
||||
memmove(s->keyData,
|
||||
key,
|
||||
s->numberOfKeys * sizeof(ScanKeyData));
|
||||
|
||||
/*
|
||||
* Scans on internal pages use different operators than they do on
|
||||
* leaf pages. For example, if the user wants all boxes that exactly
|
||||
* match (x1,y1,x2,y2), then on internal pages we need to find all
|
||||
* boxes that contain (x1,y1,x2,y2). rtstrat.c knows how to pick the
|
||||
* opclass member to use for internal pages. In some cases we need to
|
||||
* negate the result of the opclass member.
|
||||
*/
|
||||
for (i = 0; i < s->numberOfKeys; i++)
|
||||
{
|
||||
AttrNumber attno = s->keyData[i].sk_attno;
|
||||
Oid opclass;
|
||||
Oid subtype;
|
||||
StrategyNumber orig_strategy;
|
||||
StrategyNumber int_strategy;
|
||||
Oid int_oper;
|
||||
RegProcedure int_proc;
|
||||
int int_flags;
|
||||
|
||||
opclass = s->indexRelation->rd_indclass->values[attno - 1];
|
||||
subtype = s->keyData[i].sk_subtype;
|
||||
orig_strategy = s->keyData[i].sk_strategy;
|
||||
int_strategy = RTMapToInternalOperator(orig_strategy);
|
||||
int_oper = get_opclass_member(opclass, subtype, int_strategy);
|
||||
Assert(OidIsValid(int_oper));
|
||||
int_proc = get_opcode(int_oper);
|
||||
int_flags = s->keyData[i].sk_flags;
|
||||
if (RTMapToInternalNegate(orig_strategy))
|
||||
int_flags |= SK_NEGATE;
|
||||
ScanKeyEntryInitialize(&(p->s_internalKey[i]),
|
||||
int_flags,
|
||||
attno,
|
||||
int_strategy,
|
||||
subtype,
|
||||
int_proc,
|
||||
s->keyData[i].sk_argument);
|
||||
}
|
||||
}
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtmarkpos(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
RTreeScanOpaque p;
|
||||
RTSTACK *o,
|
||||
*n,
|
||||
*tmp;
|
||||
|
||||
s->currentMarkData = s->currentItemData;
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
if (p->s_flags & RTS_CURBEFORE)
|
||||
p->s_flags |= RTS_MRKBEFORE;
|
||||
else
|
||||
p->s_flags &= ~RTS_MRKBEFORE;
|
||||
|
||||
o = NULL;
|
||||
n = p->s_stack;
|
||||
|
||||
/* copy the parent stack from the current item data */
|
||||
while (n != NULL)
|
||||
{
|
||||
tmp = (RTSTACK *) palloc(sizeof(RTSTACK));
|
||||
tmp->rts_child = n->rts_child;
|
||||
tmp->rts_blk = n->rts_blk;
|
||||
tmp->rts_parent = o;
|
||||
o = tmp;
|
||||
n = n->rts_parent;
|
||||
}
|
||||
|
||||
freestack(p->s_markstk);
|
||||
p->s_markstk = o;
|
||||
|
||||
/* Update markbuf: make sure to bump ref count on curbuf */
|
||||
if (BufferIsValid(p->markbuf))
|
||||
{
|
||||
ReleaseBuffer(p->markbuf);
|
||||
p->markbuf = InvalidBuffer;
|
||||
}
|
||||
if (BufferIsValid(p->curbuf))
|
||||
{
|
||||
IncrBufferRefCount(p->curbuf);
|
||||
p->markbuf = p->curbuf;
|
||||
}
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtrestrpos(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
RTreeScanOpaque p;
|
||||
RTSTACK *o,
|
||||
*n,
|
||||
*tmp;
|
||||
|
||||
s->currentItemData = s->currentMarkData;
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
if (p->s_flags & RTS_MRKBEFORE)
|
||||
p->s_flags |= RTS_CURBEFORE;
|
||||
else
|
||||
p->s_flags &= ~RTS_CURBEFORE;
|
||||
|
||||
o = NULL;
|
||||
n = p->s_markstk;
|
||||
|
||||
/* copy the parent stack from the current item data */
|
||||
while (n != NULL)
|
||||
{
|
||||
tmp = (RTSTACK *) palloc(sizeof(RTSTACK));
|
||||
tmp->rts_child = n->rts_child;
|
||||
tmp->rts_blk = n->rts_blk;
|
||||
tmp->rts_parent = o;
|
||||
o = tmp;
|
||||
n = n->rts_parent;
|
||||
}
|
||||
|
||||
freestack(p->s_stack);
|
||||
p->s_stack = o;
|
||||
|
||||
/* Update curbuf; be sure to bump ref count on markbuf */
|
||||
if (BufferIsValid(p->curbuf))
|
||||
{
|
||||
ReleaseBuffer(p->curbuf);
|
||||
p->curbuf = InvalidBuffer;
|
||||
}
|
||||
if (BufferIsValid(p->markbuf))
|
||||
{
|
||||
IncrBufferRefCount(p->markbuf);
|
||||
p->curbuf = p->markbuf;
|
||||
}
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtendscan(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0);
|
||||
RTreeScanOpaque p;
|
||||
|
||||
p = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
freestack(p->s_stack);
|
||||
freestack(p->s_markstk);
|
||||
if (BufferIsValid(p->curbuf))
|
||||
ReleaseBuffer(p->curbuf);
|
||||
if (BufferIsValid(p->markbuf))
|
||||
ReleaseBuffer(p->markbuf);
|
||||
pfree(s->opaque);
|
||||
}
|
||||
|
||||
rtdropscan(s);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
static void
|
||||
rtregscan(IndexScanDesc s)
|
||||
{
|
||||
RTScanList l;
|
||||
|
||||
l = (RTScanList) palloc(sizeof(RTScanListData));
|
||||
l->rtsl_scan = s;
|
||||
l->rtsl_owner = CurrentResourceOwner;
|
||||
l->rtsl_next = RTScans;
|
||||
RTScans = l;
|
||||
}
|
||||
|
||||
static void
|
||||
rtdropscan(IndexScanDesc s)
|
||||
{
|
||||
RTScanList l;
|
||||
RTScanList prev;
|
||||
|
||||
prev = NULL;
|
||||
|
||||
for (l = RTScans;
|
||||
l != NULL && l->rtsl_scan != s;
|
||||
l = l->rtsl_next)
|
||||
prev = l;
|
||||
|
||||
if (l == NULL)
|
||||
elog(ERROR, "rtree scan list corrupted -- could not find 0x%p",
|
||||
(void *) s);
|
||||
|
||||
if (prev == NULL)
|
||||
RTScans = l->rtsl_next;
|
||||
else
|
||||
prev->rtsl_next = l->rtsl_next;
|
||||
|
||||
pfree(l);
|
||||
}
|
||||
|
||||
/*
|
||||
* ReleaseResources_rtree() --- clean up rtree subsystem resources.
|
||||
*
|
||||
* This is here because it needs to touch this module's static var RTScans.
|
||||
*/
|
||||
void
|
||||
ReleaseResources_rtree(void)
|
||||
{
|
||||
RTScanList l;
|
||||
RTScanList prev;
|
||||
RTScanList next;
|
||||
|
||||
/*
|
||||
* Note: this should be a no-op during normal query shutdown. However, in
|
||||
* an abort situation ExecutorEnd is not called and so there may be open
|
||||
* index scans to clean up.
|
||||
*/
|
||||
prev = NULL;
|
||||
|
||||
for (l = RTScans; l != NULL; l = next)
|
||||
{
|
||||
next = l->rtsl_next;
|
||||
if (l->rtsl_owner == CurrentResourceOwner)
|
||||
{
|
||||
if (prev == NULL)
|
||||
RTScans = next;
|
||||
else
|
||||
prev->rtsl_next = next;
|
||||
|
||||
pfree(l);
|
||||
/* prev does not change */
|
||||
}
|
||||
else
|
||||
prev = l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum)
|
||||
{
|
||||
RTScanList l;
|
||||
Oid relid;
|
||||
|
||||
relid = RelationGetRelid(r);
|
||||
for (l = RTScans; l != NULL; l = l->rtsl_next)
|
||||
{
|
||||
if (RelationGetRelid(l->rtsl_scan->indexRelation) == relid)
|
||||
rtadjone(l->rtsl_scan, op, blkno, offnum);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rtadjone() -- adjust one scan for update.
|
||||
*
|
||||
* By here, the scan passed in is on a modified relation. Op tells
|
||||
* us what the modification is, and blkno and offind tell us what
|
||||
* block and offset index were affected. This routine checks the
|
||||
* current and marked positions, and the current and marked stacks,
|
||||
* to see if any stored location needs to be changed because of the
|
||||
* update. If so, we make the change here.
|
||||
*/
|
||||
static void
|
||||
rtadjone(IndexScanDesc s,
|
||||
int op,
|
||||
BlockNumber blkno,
|
||||
OffsetNumber offnum)
|
||||
{
|
||||
RTreeScanOpaque so;
|
||||
|
||||
adjustiptr(s, &(s->currentItemData), op, blkno, offnum);
|
||||
adjustiptr(s, &(s->currentMarkData), op, blkno, offnum);
|
||||
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
if (op == RTOP_SPLIT)
|
||||
{
|
||||
adjuststack(so->s_stack, blkno);
|
||||
adjuststack(so->s_markstk, blkno);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* adjustiptr() -- adjust current and marked item pointers in the scan
|
||||
*
|
||||
* Depending on the type of update and the place it happened, we
|
||||
* need to do nothing, to back up one record, or to start over on
|
||||
* the same page.
|
||||
*/
|
||||
static void
|
||||
adjustiptr(IndexScanDesc s,
|
||||
ItemPointer iptr,
|
||||
int op,
|
||||
BlockNumber blkno,
|
||||
OffsetNumber offnum)
|
||||
{
|
||||
OffsetNumber curoff;
|
||||
RTreeScanOpaque so;
|
||||
|
||||
if (ItemPointerIsValid(iptr))
|
||||
{
|
||||
if (ItemPointerGetBlockNumber(iptr) == blkno)
|
||||
{
|
||||
curoff = ItemPointerGetOffsetNumber(iptr);
|
||||
so = (RTreeScanOpaque) s->opaque;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case RTOP_DEL:
|
||||
/* back up one if we need to */
|
||||
if (curoff >= offnum)
|
||||
{
|
||||
|
||||
if (curoff > FirstOffsetNumber)
|
||||
{
|
||||
/* just adjust the item pointer */
|
||||
ItemPointerSet(iptr, blkno, OffsetNumberPrev(curoff));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* remember that we're before the current tuple
|
||||
*/
|
||||
ItemPointerSet(iptr, blkno, FirstOffsetNumber);
|
||||
if (iptr == &(s->currentItemData))
|
||||
so->s_flags |= RTS_CURBEFORE;
|
||||
else
|
||||
so->s_flags |= RTS_MRKBEFORE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RTOP_SPLIT:
|
||||
/* back to start of page on split */
|
||||
ItemPointerSet(iptr, blkno, FirstOffsetNumber);
|
||||
if (iptr == &(s->currentItemData))
|
||||
so->s_flags &= ~RTS_CURBEFORE;
|
||||
else
|
||||
so->s_flags &= ~RTS_MRKBEFORE;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unrecognized operation in rtree scan adjust: %d", op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* adjuststack() -- adjust the supplied stack for a split on a page in
|
||||
* the index we're scanning.
|
||||
*
|
||||
* If a page on our parent stack has split, we need to back up to the
|
||||
* beginning of the page and rescan it. The reason for this is that
|
||||
* the split algorithm for rtrees doesn't order tuples in any useful
|
||||
* way on a single page. This means on that a split, we may wind up
|
||||
* looking at some heap tuples more than once. This is handled in the
|
||||
* access method update code for heaps; if we've modified the tuple we
|
||||
* are looking at already in this transaction, we ignore the update
|
||||
* request.
|
||||
*/
|
||||
static void
|
||||
adjuststack(RTSTACK *stk, BlockNumber blkno)
|
||||
{
|
||||
while (stk != NULL)
|
||||
{
|
||||
if (stk->rts_blk == blkno)
|
||||
stk->rts_child = FirstOffsetNumber;
|
||||
|
||||
stk = stk->rts_parent;
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtstrat.c
|
||||
* strategy map data for rtrees.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/rtree/rtstrat.c,v 1.27 2005/06/24 20:53:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/rtree.h"
|
||||
|
||||
|
||||
/*
|
||||
* Here's something peculiar to rtrees that doesn't apply to most other
|
||||
* indexing structures: When we're searching a tree for a given value, we
|
||||
* can't do the same sorts of comparisons on internal node entries as we
|
||||
* do at leaves. The reason is that if we're looking for (say) all boxes
|
||||
* that are the same as (0,0,10,10), then we need to find all leaf pages
|
||||
* that overlap that region. So internally we search for overlap, and at
|
||||
* the leaf we search for equality.
|
||||
*
|
||||
* This array maps leaf search operators to the internal search operators.
|
||||
*/
|
||||
static const StrategyNumber RTOperMap[RTNStrategies] = {
|
||||
RTOverRightStrategyNumber, /* left */
|
||||
RTRightStrategyNumber, /* overleft */
|
||||
RTOverlapStrategyNumber, /* overlap */
|
||||
RTLeftStrategyNumber, /* overright */
|
||||
RTOverLeftStrategyNumber, /* right */
|
||||
RTContainsStrategyNumber, /* same */
|
||||
RTContainsStrategyNumber, /* contains */
|
||||
RTOverlapStrategyNumber, /* contained-by */
|
||||
RTAboveStrategyNumber, /* overbelow */
|
||||
RTOverAboveStrategyNumber, /* below */
|
||||
RTOverBelowStrategyNumber, /* above */
|
||||
RTBelowStrategyNumber /* overabove */
|
||||
};
|
||||
|
||||
/*
|
||||
* We may need to negate the result of the selected operator. (This could
|
||||
* be avoided by expanding the set of operators required for an opclass.)
|
||||
*/
|
||||
static const bool RTNegateMap[RTNStrategies] = {
|
||||
true, /* left */
|
||||
true, /* overleft */
|
||||
false, /* overlap */
|
||||
true, /* overright */
|
||||
true, /* right */
|
||||
false, /* same */
|
||||
false, /* contains */
|
||||
false, /* contained-by */
|
||||
true, /* overbelow */
|
||||
true, /* below */
|
||||
true, /* above */
|
||||
true /* overabove */
|
||||
};
|
||||
|
||||
|
||||
StrategyNumber
|
||||
RTMapToInternalOperator(StrategyNumber strat)
|
||||
{
|
||||
Assert(strat > 0 && strat <= RTNStrategies);
|
||||
return RTOperMap[strat - 1];
|
||||
}
|
||||
|
||||
bool
|
||||
RTMapToInternalNegate(StrategyNumber strat)
|
||||
{
|
||||
Assert(strat > 0 && strat <= RTNStrategies);
|
||||
return RTNegateMap[strat - 1];
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Resource managers definition
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.20 2005/06/14 11:45:14 teodor Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.21 2005/11/07 17:36:45 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "access/heapam.h"
|
||||
#include "access/multixact.h"
|
||||
#include "access/nbtree.h"
|
||||
#include "access/rtree.h"
|
||||
#include "access/xact.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "commands/dbcommands.h"
|
||||
@ -36,7 +35,7 @@ const RmgrData RmgrTable[RM_MAX_ID + 1] = {
|
||||
{"Heap", heap_redo, heap_desc, NULL, NULL},
|
||||
{"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup},
|
||||
{"Hash", hash_redo, hash_desc, NULL, NULL},
|
||||
{"Rtree", rtree_redo, rtree_desc, NULL, NULL},
|
||||
{"Reserved 13", NULL, NULL, NULL, NULL},
|
||||
{"Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup},
|
||||
{"Sequence", seq_redo, seq_desc, NULL, NULL}
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.134 2005/10/15 02:49:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.135 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -226,10 +226,27 @@ DefineIndex(RangeVar *heapRelation,
|
||||
PointerGetDatum(accessMethodName),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
accessMethodName)));
|
||||
{
|
||||
/*
|
||||
* Hack to provide more-or-less-transparent updating of old RTREE
|
||||
* indexes to GIST: if RTREE is requested and not found, use GIST.
|
||||
*/
|
||||
if (strcmp(accessMethodName, "rtree") == 0)
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("substituting access method \"gist\" for obsolete method \"rtree\"")));
|
||||
accessMethodName = "gist";
|
||||
tuple = SearchSysCache(AMNAME,
|
||||
PointerGetDatum(accessMethodName),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
accessMethodName)));
|
||||
}
|
||||
accessMethodId = HeapTupleGetOid(tuple);
|
||||
accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/geo_selfuncs.c,v 1.24 2004/12/31 22:01:22 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/geo_selfuncs.c,v 1.25 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
* XXX These are totally bogus. Perhaps someone will make them do
|
||||
* something reasonable, someday.
|
||||
@ -22,19 +22,19 @@
|
||||
|
||||
|
||||
/*
|
||||
* Selectivity functions for rtrees. These are bogus -- unless we know
|
||||
* the actual key distribution in the index, we can't make a good prediction
|
||||
* of the selectivity of these operators.
|
||||
* Selectivity functions for geometric operators. These are bogus -- unless
|
||||
* we know the actual key distribution in the index, we can't make a good
|
||||
* prediction of the selectivity of these operators.
|
||||
*
|
||||
* Note: the values used here may look unreasonably small. Perhaps they
|
||||
* are. For now, we want to make sure that the optimizer will make use
|
||||
* of an r-tree index if one is available, so the selectivity had better
|
||||
* of a geometric index if one is available, so the selectivity had better
|
||||
* be fairly small.
|
||||
*
|
||||
* In general, rtrees need to search multiple subtrees in order to guarantee
|
||||
* In general, GiST needs to search multiple subtrees in order to guarantee
|
||||
* that all occurrences of the same key have been found. Because of this,
|
||||
* the estimated cost for scanning the index ought to be higher than the
|
||||
* output selectivity would indicate. rtcostestimate(), over in selfuncs.c,
|
||||
* output selectivity would indicate. gistcostestimate(), over in selfuncs.c,
|
||||
* ought to be adjusted accordingly --- but until we can generate somewhat
|
||||
* realistic numbers here, it hardly matters...
|
||||
*/
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.191 2005/10/15 02:49:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.192 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -4470,24 +4470,6 @@ btcostestimate(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
rtcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
|
||||
List *indexQuals = (List *) PG_GETARG_POINTER(2);
|
||||
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
|
||||
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
|
||||
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
|
||||
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
|
||||
|
||||
genericcostestimate(root, index, indexQuals, 0.0,
|
||||
indexStartupCost, indexTotalCost,
|
||||
indexSelectivity, indexCorrelation);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
Datum
|
||||
hashcostestimate(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.14 2005/10/15 02:49:36 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.15 2005/11/07 17:36:45 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -23,7 +23,6 @@
|
||||
#include "utils/resowner.h"
|
||||
#include "access/gistscan.h"
|
||||
#include "access/hash.h"
|
||||
#include "access/rtree.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/memutils.h"
|
||||
@ -280,7 +279,6 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
|
||||
/* Clean up index scans too */
|
||||
ReleaseResources_gist();
|
||||
ReleaseResources_hash();
|
||||
ReleaseResources_rtree();
|
||||
}
|
||||
|
||||
/* Let add-on modules get a chance too */
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.138 2005/10/15 02:49:40 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.139 2005/11/07 17:36:45 tgl Exp $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -1025,7 +1025,7 @@ psql_completion(char *text, int start, int end)
|
||||
else if (pg_strcasecmp(prev_wd, "USING") == 0)
|
||||
{
|
||||
static const char *const index_mth[] =
|
||||
{"BTREE", "RTREE", "HASH", "GIST", NULL};
|
||||
{"BTREE", "HASH", "GIST", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(index_mth);
|
||||
}
|
||||
|
@ -9,18 +9,18 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.50 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/gist.h,v 1.51 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef GIST_H
|
||||
#define GIST_H
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlogdefs.h"
|
||||
#include "storage/bufpage.h"
|
||||
#include "storage/off.h"
|
||||
#include "utils/rel.h"
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlogdefs.h"
|
||||
|
||||
/*
|
||||
* amproc indexes for GiST indexes.
|
||||
@ -34,6 +34,23 @@
|
||||
#define GIST_EQUAL_PROC 7
|
||||
#define GISTNProcs 7
|
||||
|
||||
/*
|
||||
* strategy numbers for GiST opclasses that want to implement the old
|
||||
* RTREE behavior.
|
||||
*/
|
||||
#define RTLeftStrategyNumber 1
|
||||
#define RTOverLeftStrategyNumber 2
|
||||
#define RTOverlapStrategyNumber 3
|
||||
#define RTOverRightStrategyNumber 4
|
||||
#define RTRightStrategyNumber 5
|
||||
#define RTSameStrategyNumber 6
|
||||
#define RTContainsStrategyNumber 7
|
||||
#define RTContainedByStrategyNumber 8
|
||||
#define RTOverBelowStrategyNumber 9
|
||||
#define RTBelowStrategyNumber 10
|
||||
#define RTAboveStrategyNumber 11
|
||||
#define RTOverAboveStrategyNumber 12
|
||||
|
||||
/*
|
||||
* Page opaque data in a GiST index page.
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Resource managers definition
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.14 2005/06/06 17:01:24 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.15 2005/11/07 17:36:46 tgl Exp $
|
||||
*/
|
||||
#ifndef RMGR_H
|
||||
#define RMGR_H
|
||||
@ -23,7 +23,6 @@ typedef uint8 RmgrId;
|
||||
#define RM_HEAP_ID 10
|
||||
#define RM_BTREE_ID 11
|
||||
#define RM_HASH_ID 12
|
||||
#define RM_RTREE_ID 13
|
||||
#define RM_GIST_ID 14
|
||||
#define RM_SEQ_ID 15
|
||||
#define RM_MAX_ID RM_SEQ_ID
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtree.h
|
||||
* common declarations for the rtree access method code.
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.41 2005/06/24 20:53:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef RTREE_H
|
||||
#define RTREE_H
|
||||
|
||||
#include "access/itup.h"
|
||||
#include "access/sdir.h"
|
||||
#include "access/skey.h"
|
||||
#include "access/xlog.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
/* see rtstrat.c for what all this is about */
|
||||
#define RTNStrategies 12
|
||||
#define RTLeftStrategyNumber 1
|
||||
#define RTOverLeftStrategyNumber 2
|
||||
#define RTOverlapStrategyNumber 3
|
||||
#define RTOverRightStrategyNumber 4
|
||||
#define RTRightStrategyNumber 5
|
||||
#define RTSameStrategyNumber 6
|
||||
#define RTContainsStrategyNumber 7
|
||||
#define RTContainedByStrategyNumber 8
|
||||
#define RTOverBelowStrategyNumber 9
|
||||
#define RTBelowStrategyNumber 10
|
||||
#define RTAboveStrategyNumber 11
|
||||
#define RTOverAboveStrategyNumber 12
|
||||
|
||||
#define RTNProcs 3
|
||||
#define RT_UNION_PROC 1
|
||||
#define RT_INTER_PROC 2
|
||||
#define RT_SIZE_PROC 3
|
||||
|
||||
#define F_LEAF (1 << 0)
|
||||
|
||||
typedef struct RTreePageOpaqueData
|
||||
{
|
||||
uint32 flags;
|
||||
} RTreePageOpaqueData;
|
||||
|
||||
typedef RTreePageOpaqueData *RTreePageOpaque;
|
||||
|
||||
/*
|
||||
* When we descend a tree, we keep a stack of parent pointers.
|
||||
*/
|
||||
|
||||
typedef struct RTSTACK
|
||||
{
|
||||
struct RTSTACK *rts_parent;
|
||||
OffsetNumber rts_child;
|
||||
BlockNumber rts_blk;
|
||||
} RTSTACK;
|
||||
|
||||
/*
|
||||
* When we're doing a scan, we need to keep track of the parent stack
|
||||
* for the marked and current items. Also, rtrees have the following
|
||||
* property: if you're looking for the box (1,1,2,2), on the internal
|
||||
* nodes you have to search for all boxes that *contain* (1,1,2,2),
|
||||
* and not the ones that match it. We have a private scan key for
|
||||
* internal nodes in the opaque structure for rtrees for this reason.
|
||||
* See access/index-rtree/rtscan.c and rtstrat.c for how it gets
|
||||
* initialized. We also keep pins on the scan's current buffer and
|
||||
* marked buffer, if any: this avoids the need to invoke ReadBuffer()
|
||||
* for each tuple produced by the index scan.
|
||||
*/
|
||||
|
||||
typedef struct RTreeScanOpaqueData
|
||||
{
|
||||
struct RTSTACK *s_stack;
|
||||
struct RTSTACK *s_markstk;
|
||||
uint16 s_flags;
|
||||
int s_internalNKey;
|
||||
ScanKey s_internalKey;
|
||||
Buffer curbuf;
|
||||
Buffer markbuf;
|
||||
} RTreeScanOpaqueData;
|
||||
|
||||
typedef RTreeScanOpaqueData *RTreeScanOpaque;
|
||||
|
||||
/*
|
||||
* When we're doing a scan and updating a tree at the same time, the
|
||||
* updates may affect the scan. We use the flags entry of the scan's
|
||||
* opaque space to record our actual position in response to updates
|
||||
* that we can't handle simply by adjusting pointers.
|
||||
*/
|
||||
|
||||
#define RTS_CURBEFORE ((uint16) (1 << 0))
|
||||
#define RTS_MRKBEFORE ((uint16) (1 << 1))
|
||||
|
||||
/* root page of an rtree */
|
||||
#define P_ROOT 0
|
||||
|
||||
/*
|
||||
* When we update a relation on which we're doing a scan, we need to
|
||||
* check the scan and fix it if the update affected any of the pages it
|
||||
* touches. Otherwise, we can miss records that we should see. The only
|
||||
* times we need to do this are for deletions and splits. See the code in
|
||||
* rtscan.c for how the scan is fixed. These two contants tell us what sort
|
||||
* of operation changed the index.
|
||||
*/
|
||||
|
||||
#define RTOP_DEL 0
|
||||
#define RTOP_SPLIT 1
|
||||
|
||||
/* defined in rtree.c */
|
||||
extern void freestack(RTSTACK *s);
|
||||
|
||||
/*
|
||||
* RTree code.
|
||||
* Defined in access/rtree/
|
||||
*/
|
||||
extern Datum rtinsert(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbulkdelete(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbeginscan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtgettuple(PG_FUNCTION_ARGS);
|
||||
extern Datum rtgetmulti(PG_FUNCTION_ARGS);
|
||||
extern Datum rtendscan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtmarkpos(PG_FUNCTION_ARGS);
|
||||
extern Datum rtrestrpos(PG_FUNCTION_ARGS);
|
||||
extern Datum rtrescan(PG_FUNCTION_ARGS);
|
||||
extern Datum rtbuild(PG_FUNCTION_ARGS);
|
||||
extern void _rtdump(Relation r);
|
||||
|
||||
extern void rtree_redo(XLogRecPtr lsn, XLogRecord *record);
|
||||
extern void rtree_desc(char *buf, uint8 xl_info, char *rec);
|
||||
|
||||
/* rtscan.c */
|
||||
extern void rtadjscans(Relation r, int op, BlockNumber blkno,
|
||||
OffsetNumber offnum);
|
||||
extern void ReleaseResources_rtree(void);
|
||||
|
||||
/* rtstrat.c */
|
||||
extern StrategyNumber RTMapToInternalOperator(StrategyNumber strat);
|
||||
extern bool RTMapToInternalNegate(StrategyNumber strat);
|
||||
|
||||
#endif /* RTREE_H */
|
@ -1,23 +0,0 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* rtscan.h
|
||||
* routines defined in access/rtree/rtscan.c
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/rtscan.h,v 1.18 2004/12/31 22:03:21 pgsql Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef RTSCAN_H
|
||||
#define RTSCAN_H
|
||||
|
||||
#include "storage/block.h"
|
||||
#include "storage/off.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
void rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum);
|
||||
|
||||
#endif /* RTSCAN_H */
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.305 2005/10/21 15:45:06 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.306 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200510211
|
||||
#define CATALOG_VERSION_NO 200511071
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.38 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.39 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -104,8 +104,6 @@ typedef FormData_pg_am *Form_pg_am;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
DATA(insert OID = 402 ( rtree 12 3 0 f f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate ));
|
||||
DESCR("r-tree index access method");
|
||||
DATA(insert OID = 403 ( btree 5 1 1 t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
|
||||
DESCR("b-tree index access method");
|
||||
#define BTREE_AM_OID 403
|
||||
|
@ -23,7 +23,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.66 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.67 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -80,40 +80,6 @@ typedef FormData_pg_amop *Form_pg_amop;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* rtree box_ops
|
||||
*/
|
||||
|
||||
DATA(insert ( 425 0 1 f 493 ));
|
||||
DATA(insert ( 425 0 2 f 494 ));
|
||||
DATA(insert ( 425 0 3 f 500 ));
|
||||
DATA(insert ( 425 0 4 f 495 ));
|
||||
DATA(insert ( 425 0 5 f 496 ));
|
||||
DATA(insert ( 425 0 6 f 499 ));
|
||||
DATA(insert ( 425 0 7 f 498 ));
|
||||
DATA(insert ( 425 0 8 f 497 ));
|
||||
DATA(insert ( 425 0 9 f 2571 ));
|
||||
DATA(insert ( 425 0 10 f 2570 ));
|
||||
DATA(insert ( 425 0 11 f 2573 ));
|
||||
DATA(insert ( 425 0 12 f 2572 ));
|
||||
|
||||
/*
|
||||
* rtree poly_ops (supports polygons)
|
||||
*/
|
||||
|
||||
DATA(insert ( 1993 0 1 f 485 ));
|
||||
DATA(insert ( 1993 0 2 f 486 ));
|
||||
DATA(insert ( 1993 0 3 f 492 ));
|
||||
DATA(insert ( 1993 0 4 f 487 ));
|
||||
DATA(insert ( 1993 0 5 f 488 ));
|
||||
DATA(insert ( 1993 0 6 f 491 ));
|
||||
DATA(insert ( 1993 0 7 f 490 ));
|
||||
DATA(insert ( 1993 0 8 f 489 ));
|
||||
DATA(insert ( 1993 0 9 f 2575 ));
|
||||
DATA(insert ( 1993 0 10 f 2574 ));
|
||||
DATA(insert ( 1993 0 11 f 2577 ));
|
||||
DATA(insert ( 1993 0 12 f 2576 ));
|
||||
|
||||
/*
|
||||
* btree int2_ops
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.54 2005/07/01 19:19:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.55 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -74,15 +74,6 @@ typedef FormData_pg_amproc *Form_pg_amproc;
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/* rtree */
|
||||
DATA(insert ( 425 0 1 193 ));
|
||||
DATA(insert ( 425 0 2 194 ));
|
||||
DATA(insert ( 425 0 3 195 ));
|
||||
DATA(insert ( 1993 0 1 197 ));
|
||||
DATA(insert ( 1993 0 2 198 ));
|
||||
DATA(insert ( 1993 0 3 199 ));
|
||||
|
||||
|
||||
/* btree */
|
||||
DATA(insert ( 397 0 1 382 ));
|
||||
DATA(insert ( 421 0 1 357 ));
|
||||
|
@ -27,7 +27,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.66 2005/07/01 19:19:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.67 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -94,7 +94,6 @@ DATA(insert OID = 397 ( 403 array_ops PGNSP PGUID 2277 t 0 ));
|
||||
DATA(insert OID = 423 ( 403 bit_ops PGNSP PGUID 1560 t 0 ));
|
||||
DATA(insert OID = 424 ( 403 bool_ops PGNSP PGUID 16 t 0 ));
|
||||
#define BOOL_BTREE_OPS_OID 424
|
||||
DATA(insert OID = 425 ( 402 box_ops PGNSP PGUID 603 t 0 ));
|
||||
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 ));
|
||||
@ -135,7 +134,6 @@ DATA(insert OID = 1989 ( 403 oid_ops PGNSP PGUID 26 t 0 ));
|
||||
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 = 1993 ( 402 poly_ops PGNSP PGUID 604 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 ));
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.387 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.388 2005/11/07 17:36:46 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The script catalog/genbki.sh reads this file and generates .bki
|
||||
@ -394,18 +394,6 @@ DATA(insert OID = 191 ( box_right PGNSP PGUID 12 f f t f i 2 16 "603 603" _
|
||||
DESCR("is right of");
|
||||
DATA(insert OID = 192 ( box_contained PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_contained - _null_ ));
|
||||
DESCR("contained in?");
|
||||
DATA(insert OID = 193 ( rt_box_union PGNSP PGUID 12 f f t f i 2 603 "603 603" _null_ _null_ _null_ rt_box_union - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 194 ( rt_box_inter PGNSP PGUID 12 f f t f i 2 2278 "603 603" _null_ _null_ _null_ rt_box_inter - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 195 ( rt_box_size PGNSP PGUID 12 f f t f i 2 2278 "603 2281" _null_ _null_ _null_ rt_box_size - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 197 ( rt_poly_union PGNSP PGUID 12 f f t f i 2 604 "604 604" _null_ _null_ _null_ rt_poly_union - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 198 ( rt_poly_inter PGNSP PGUID 12 f f t f i 2 2278 "604 604" _null_ _null_ _null_ rt_poly_inter - _null_ ));
|
||||
DESCR("r-tree");
|
||||
DATA(insert OID = 199 ( rt_poly_size PGNSP PGUID 12 f f t f i 2 2278 "604 2281" _null_ _null_ _null_ rt_poly_size - _null_ ));
|
||||
DESCR("r-tree");
|
||||
|
||||
/* OIDS 200 - 299 */
|
||||
|
||||
@ -668,29 +656,6 @@ DESCR("convert int4 to float4");
|
||||
DATA(insert OID = 319 ( int4 PGNSP PGUID 12 f f t f i 1 23 "700" _null_ _null_ _null_ ftoi4 - _null_ ));
|
||||
DESCR("convert float4 to int4");
|
||||
|
||||
DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ rtinsert - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ rtgettuple - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 635 ( rtgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ rtgetmulti - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 323 ( rtbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ rtbuild - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 324 ( rtbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ rtbeginscan - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 325 ( rtendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ rtendscan - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 326 ( rtmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ rtmarkpos - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 327 ( rtrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _null_ _null_ _null_ rtrestrpos - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 328 ( rtrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" _null_ _null_ _null_ rtrescan - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 321 ( rtbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ rtbulkdelete - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
DATA(insert OID = 1265 ( rtcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ rtcostestimate - _null_ ));
|
||||
DESCR("r-tree(internal)");
|
||||
|
||||
DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ btgettuple - _null_ ));
|
||||
DESCR("btree(internal)");
|
||||
DATA(insert OID = 636 ( btgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ btgetmulti - _null_ ));
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.48 2005/07/01 19:19:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.49 2005/11/07 17:36:47 tgl Exp $
|
||||
*
|
||||
* NOTE
|
||||
* These routines do *not* use the float types from adt/.
|
||||
@ -406,14 +406,6 @@ extern Datum poly_circle(PG_FUNCTION_ARGS);
|
||||
extern Datum circle_poly(PG_FUNCTION_ARGS);
|
||||
extern Datum circle_area(PG_FUNCTION_ARGS);
|
||||
|
||||
/* support routines for the rtree access method (access/rtree/rtproc.c) */
|
||||
extern Datum rt_box_union(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_box_inter(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_box_size(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_poly_size(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_poly_union(PG_FUNCTION_ARGS);
|
||||
extern Datum rt_poly_inter(PG_FUNCTION_ARGS);
|
||||
|
||||
/* support routines for the GiST access method (access/gist/gistproc.c) */
|
||||
extern Datum gist_box_compress(PG_FUNCTION_ARGS);
|
||||
extern Datum gist_box_decompress(PG_FUNCTION_ARGS);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.24 2005/10/15 02:49:46 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.25 2005/11/07 17:36:47 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -124,7 +124,6 @@ extern Selectivity estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey,
|
||||
double nbuckets);
|
||||
|
||||
extern Datum btcostestimate(PG_FUNCTION_ARGS);
|
||||
extern Datum rtcostestimate(PG_FUNCTION_ARGS);
|
||||
extern Datum hashcostestimate(PG_FUNCTION_ARGS);
|
||||
extern Datum gistcostestimate(PG_FUNCTION_ARGS);
|
||||
|
||||
|
@ -46,55 +46,6 @@ CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
||||
CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
|
||||
where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K';
|
||||
--
|
||||
-- RTREE
|
||||
--
|
||||
-- rtrees use a quadratic page-splitting algorithm that takes a
|
||||
-- really, really long time. we don't test all rtree opclasses
|
||||
-- in the regression test (we check them using the sequoia 2000
|
||||
-- benchmark).
|
||||
--
|
||||
CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base);
|
||||
SET enable_seqscan = ON;
|
||||
SET enable_indexscan = OFF;
|
||||
SET enable_bitmapscan = OFF;
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
home_base
|
||||
-----------------------
|
||||
(1444,403),(1346,344)
|
||||
(337,455),(240,359)
|
||||
(2 rows)
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
count
|
||||
-------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
SET enable_seqscan = OFF;
|
||||
SET enable_indexscan = ON;
|
||||
SET enable_bitmapscan = ON;
|
||||
-- there's no easy way to check that these commands actually use
|
||||
-- the index, unfortunately. (EXPLAIN would work, but its output
|
||||
-- changes too often for me to want to put an EXPLAIN in the test...)
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
home_base
|
||||
-----------------------
|
||||
(1444,403),(1346,344)
|
||||
(337,455),(240,359)
|
||||
(2 rows)
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
count
|
||||
-------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
DROP INDEX rect2ind;
|
||||
--
|
||||
-- GiST (rtree-equivalent opclasses only)
|
||||
--
|
||||
CREATE INDEX grect2ind ON fast_emp4000 USING gist (home_base);
|
||||
|
@ -798,18 +798,6 @@ FROM pg_amop p1 LEFT JOIN pg_opclass p2 ON amopclaid = p2.oid
|
||||
ORDER BY 1, 2, 3;
|
||||
opcamid | amopstrategy | oprname
|
||||
---------+--------------+---------
|
||||
402 | 1 | <<
|
||||
402 | 2 | &<
|
||||
402 | 3 | &&
|
||||
402 | 4 | &>
|
||||
402 | 5 | >>
|
||||
402 | 6 | ~=
|
||||
402 | 7 | ~
|
||||
402 | 8 | @
|
||||
402 | 9 | &<|
|
||||
402 | 10 | <<|
|
||||
402 | 11 | |>>
|
||||
402 | 12 | |&>
|
||||
403 | 1 | <
|
||||
403 | 1 | ~<~
|
||||
403 | 2 | <=
|
||||
@ -834,7 +822,7 @@ ORDER BY 1, 2, 3;
|
||||
783 | 10 | <<|
|
||||
783 | 11 | |>>
|
||||
783 | 12 | |&>
|
||||
(36 rows)
|
||||
(24 rows)
|
||||
|
||||
-- Check that all operators linked to by opclass entries have selectivity
|
||||
-- estimators. This is not absolutely required, but it seems a reasonable
|
||||
|
@ -67,42 +67,6 @@ CREATE INDEX onek2_u2_prtl ON onek2 USING btree(unique2 int4_ops)
|
||||
CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
|
||||
where onek2.stringu1 >= 'J' and onek2.stringu1 < 'K';
|
||||
|
||||
--
|
||||
-- RTREE
|
||||
--
|
||||
-- rtrees use a quadratic page-splitting algorithm that takes a
|
||||
-- really, really long time. we don't test all rtree opclasses
|
||||
-- in the regression test (we check them using the sequoia 2000
|
||||
-- benchmark).
|
||||
--
|
||||
CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base);
|
||||
|
||||
SET enable_seqscan = ON;
|
||||
SET enable_indexscan = OFF;
|
||||
SET enable_bitmapscan = OFF;
|
||||
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
|
||||
SET enable_seqscan = OFF;
|
||||
SET enable_indexscan = ON;
|
||||
SET enable_bitmapscan = ON;
|
||||
|
||||
-- there's no easy way to check that these commands actually use
|
||||
-- the index, unfortunately. (EXPLAIN would work, but its output
|
||||
-- changes too often for me to want to put an EXPLAIN in the test...)
|
||||
SELECT * FROM fast_emp4000
|
||||
WHERE home_base @ '(200,200),(2000,1000)'::box
|
||||
ORDER BY home_base USING <;
|
||||
|
||||
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
|
||||
|
||||
DROP INDEX rect2ind;
|
||||
|
||||
|
||||
--
|
||||
-- GiST (rtree-equivalent opclasses only)
|
||||
--
|
||||
|
@ -212,9 +212,6 @@ index types<br />
|
||||
<a id="access_nbtree" name="access_nbtree"></a> <a
|
||||
href="../../backend/access/nbtree">access/nbtree</a> - Lehman and
|
||||
Yao's btree management algorithm<br />
|
||||
<a id="access_rtree" name="access_rtree"></a> <a
|
||||
href="../../backend/access/rtree">access/rtree</a> - used for
|
||||
indexing of 2-dimensional data<br />
|
||||
<a id="access_transam" name="access_transam"></a> <a
|
||||
href="../../backend/access/transam">access/transam</a> -
|
||||
transaction manager (BEGIN/ABORT/COMMIT)<br />
|
||||
|
Loading…
Reference in New Issue
Block a user