]> granicus.if.org Git - postgis/commitdiff
Add support for BRIN indexes (2nd Quadrant, Giuseppe Broccolo, Julien Rouhaud)
authorRegina Obe <lr@pcorp.us>
Sun, 31 Jul 2016 03:46:40 +0000 (03:46 +0000)
committerRegina Obe <lr@pcorp.us>
Sun, 31 Jul 2016 03:46:40 +0000 (03:46 +0000)
Closes #3591
Closes https://github.com/postgis/postgis/pull/106

git-svn-id: http://svn.osgeo.org/postgis/trunk@15028 b70326c6-7e19-0410-871a-916f4a2858ee

13 files changed:
NEWS
configure.ac
doc/reference_operator.xml
doc/using_postgis_dataman.xml
libpgcommon/gserialized_gist.c
libpgcommon/gserialized_gist.h
postgis/Makefile.in
postgis/geography.sql.in
postgis/gserialized_gist_2d.c
postgis/gserialized_gist_nd.c
postgis/postgis.sql.in
regress/Makefile.in
utils/postgis_proc_upgrade.pl

diff --git a/NEWS b/NEWS
index 89334b685d9495aa4c354a16891242c84da2684b..c988a6491c3995b5c3c8bbd9c9c9a18f0668ff8e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,7 @@ PostGIS 2.3.0
  * Important / Breaking Changes *
 
   - #3466, Casting from box3d to geometry now returns a 3D
-           geometry (Julien Rouhaud)
+           geometry (2nd Quadrant, Julien Rouhaud)
 
  * Deprecated signatures *
 
@@ -33,8 +33,9 @@ PostGIS 2.3.0
   - #3465, ST_ClusterKMeans (Paul Ramsey)
   - #3469, ST_MakeLine with MULTIPOINTs (Paul Norman)
   - #3549, Support PgSQL 9.6 parallel query mode, as far as possible
-    (Paul Ramsey)
+    (Paul Ramsey, Regina Obe)
   - #3557, Geometry function costs based on query stats (Paul Norman)
+  - #3591, Add support for BRIN indexes (2nd Quadrant, Giuseppe Broccolo, Julien Rouhaud)
 
  * Performance Enhancements *
 
index 370fd1ea056d92230acae4385a902d204636ed47..ff00df60788aef6730eb480bff023a3866f40480 100644 (file)
@@ -444,6 +444,11 @@ if test "x$LIBLWGEOM_ONLY" = "xno"; then
     AC_MSG_ERROR([PostGIS requires PostgreSQL >= 9.1])
   fi
 
+  HAVE_BRIN=no
+  if test $POSTGIS_PGSQL_VERSION -gt 94; then
+    HAVE_BRIN=yes
+  fi
+
   dnl Note: We don't need the server-side LDFLAGS or CPPFLAGS because we get these from PGXS 
 
   dnl Extract the linker and include flags for the frontend (for programs that use libpq)
@@ -503,6 +508,7 @@ if test "x$LIBLWGEOM_ONLY" = "xno"; then
 
   AC_DEFINE_UNQUOTED([POSTGIS_PGSQL_VERSION], [$POSTGIS_PGSQL_VERSION], [PostgreSQL server version])   
   AC_SUBST([POSTGIS_PGSQL_VERSION])
+  AC_SUBST([HAVE_BRIN])
 
 fi dnl LIBLWGEOM_ONLY != no
 
index daf42d26d1903fc5ac125e963bb87225e3bc395a..7937549bbad6f0ae554aa9b5aa704a89fb0481a0 100644 (file)
@@ -91,6 +91,204 @@ FROM ( VALUES
                  </refsection>
                </refentry>
 
+               <refentry id="overlaps_geometry_box2df">
+                 <refnamediv>
+                       <refname>&amp;&amp;(geometry,box2df)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a geometry's (cached) 2D bounding box intersects a 2D float precision bounding box (BOX2DF).</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>&amp;&amp;</function></funcdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>box2df</type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&amp;&amp;</varname> operator returns <varname>TRUE</varname> if the cached 2D bounding box of geometry A intersects the 2D bounding box B, using float precision. This means that if B is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
+
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_MakePoint(1,1) &amp;&amp; ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(2,2)) AS overlaps;
+
+ overlaps
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="overlaps_box2df_geometry">
+                 <refnamediv>
+                       <refname>&amp;&amp;(box2df,geometry)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a 2D float precision bounding box (BOX2DF) intersects a geometry's (cached) 2D bounding box.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>&amp;&amp;</function></funcdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&amp;&amp;</varname> operator returns <varname>TRUE</varname> if the 2D bounding box A intersects the cached 2D bounding box of geometry B, using float precision. This means that if A is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
+
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(2,2)) &amp;&amp; ST_MakePoint(1,1) AS overlaps;
+
+ overlaps
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="overlaps_box2df_box2df">
+                 <refnamediv>
+                       <refname>&amp;&amp;(box2df,box2df)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if two 2D float precision bounding boxes (BOX2DF) intersect each other.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>&amp;&amp;</function></funcdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&amp;&amp;</varname> operator returns <varname>TRUE</varname> if two 2D bounding boxes A and B intersect each other, using float precision. This means that if A (or B) is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
+
+                       <note><para>This operator is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(2,2)) &amp;&amp; ST_MakeBox2D(ST_MakePoint(1,1), ST_MakePoint(3,3)) AS overlaps;
+
+ overlaps
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
+                 </refsection>
+               </refentry>
+
                <refentry id="geometry_overlaps_nd">
                  <refnamediv>
                        <refname>&amp;&amp;&amp;</refname>
@@ -177,6 +375,192 @@ FROM ( VALUES
                  </refsection>
                </refentry>
 
+               <refentry id="overlaps_nd_geometry_gidx">
+                 <refnamediv>
+                       <refname>&amp;&amp;&amp;(geometry,gidx)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a geometry's (cached) n-D bounding box intersects a n-D float precision bounding box (GIDX).</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>&amp;&amp;&amp;</function></funcdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>gidx </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&amp;&amp;&amp;</varname> operator returns <varname>TRUE</varname> if the cached n-D bounding box of geometry A intersects the n-D bounding box B, using float precision. This means that if B is a (double precision) box3d, it will be internally converted to a float precision 3D bounding box (GIDX)</para>
+
+                       <note><para>This operator is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                       <para>&T_support;</para>
+                       <para>&Z_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_MakePoint(1,1,1) &amp;&amp;&amp; ST_3DMakeBox(ST_MakePoint(0,0,0), ST_MakePoint(2,2,2)) AS overlaps;
+
+ overlaps
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_nd_gidx_geometry" />,
+                               <xref linkend="overlaps_nd_gidx_gidx" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="overlaps_nd_gidx_geometry">
+                 <refnamediv>
+                       <refname>&amp;&amp;&amp;(gidx,geometry)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a n-D float precision bounding box (GIDX) intersects a geometry's (cached) n-D bounding box.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>&amp;&amp;&amp;</function></funcdef>
+
+                               <paramdef>
+                                 <type>gidx </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&amp;&amp;&amp;</varname> operator returns <varname>TRUE</varname> if the n-D bounding box A intersects the cached n-D bounding box of geometry B, using float precision. This means that if A is a (double precision) box3d, it will be internally converted to a float precision 3D bounding box (GIDX)</para>
+
+                       <note><para>This operator is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                       <para>&T_support;</para>
+                       <para>&Z_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_3DMakeBox(ST_MakePoint(0,0,0), ST_MakePoint(2,2,2)) &amp;&amp;&amp; ST_MakePoint(1,1,1) AS overlaps;
+
+ overlaps
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_nd_geometry_gidx" />,
+                               <xref linkend="overlaps_nd_gidx_gidx" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="overlaps_nd_gidx_gidx">
+                 <refnamediv>
+                       <refname>&amp;&amp;&amp;(gidx,gidx)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if two n-D float precision bounding boxes (GIDX) intersect each other.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>&amp;&amp;&amp;</function></funcdef>
+
+                               <paramdef>
+                                 <type>gidx </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>gidx </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&amp;&amp;&amp;</varname> operator returns <varname>TRUE</varname> if two n-D bounding boxes A and B intersect each other, using float precision. This means that if A (or B) is a (double precision) box3d, it will be internally converted to a float precision 3D bounding box (GIDX)</para>
+
+                       <note><para>This operator is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                       <para>&T_support;</para>
+                       <para>&Z_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_3DMakeBox(ST_MakePoint(0,0,0), ST_MakePoint(2,2,2)) &amp;&amp;&amp; ST_3DMakeBox(ST_MakePoint(1,1,1), ST_MakePoint(3,3,3)) AS overlaps;
+
+ overlaps
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                                <xref linkend="overlaps_nd_geometry_gidx" />,
+                                <xref linkend="overlaps_nd_gidx_geometry" /></para>
+                 </refsection>
+               </refentry>
+
                <refentry id="ST_Geometry_Overleft">
                  <refnamediv>
                        <refname>&amp;&lt;</refname>
@@ -591,82 +975,281 @@ FROM
                          linkend="ST_Equals" /></para>
                        </warning>
 
-                       <caution><para>This operand will NOT make use of any indexes that may be available on the
-                               geometries.</para></caution>
+                       <caution><para>This operand will NOT make use of any indexes that may be available on the
+                               geometries.</para></caution>
+
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                       <para>Changed:  2.0.0 , the bounding box of geometries was changed to use double precision instead of float4 precision of
+                       prior. The side effect of this is that in particular points in prior versions that were a little different may have returned
+                               true in prior versions and false in 2.0+ since their float4 boxes would be the same but there float8 (double precision), would be
+                               different.</para>
+
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT 'LINESTRING(0 0, 0 1, 1 0)'::geometry = 'LINESTRING(1 1, 0 0)'::geometry;
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ST_AsText(column1)
+FROM ( VALUES
+       ('LINESTRING(0 0, 1 1)'::geometry),
+       ('LINESTRING(1 1, 0 0)'::geometry)) AS foo;
+         st_astext
+---------------------
+ LINESTRING(0 0,1 1)
+ LINESTRING(1 1,0 0)
+(2 rows)
+
+-- Note: the GROUP BY uses the "=" to compare for geometry equivalency.
+SELECT ST_AsText(column1)
+FROM ( VALUES
+       ('LINESTRING(0 0, 1 1)'::geometry),
+       ('LINESTRING(1 1, 0 0)'::geometry)) AS foo
+GROUP BY column1;
+         st_astext
+---------------------
+ LINESTRING(0 0,1 1)
+(1 row)
+
+-- In versions prior to 2.0, this used to return true --
+ SELECT ST_GeomFromText('POINT(1707296.37 4820536.77)') =
+       ST_GeomFromText('POINT(1707296.27 4820536.87)') As pt_intersect;
+
+--pt_intersect --
+f
+</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para><xref linkend="ST_Equals" />, <xref linkend="ST_OrderingEquals" />
+                       <!--, <xref linkend="ST_Geometry_LT" />, <xref linkend="ST_Geometry_GT" /> --></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="ST_Geometry_Right">
+                 <refnamediv>
+                       <refname>&gt;&gt;</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if A's bounding box is strictly to the right of B's.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <!-- TODO: Ideally, it would be nice if this could be reordered to
+                               "boolean (geometry A >> geometry B)" instead of
+                               "boolean >>( geometry A, geometry B)" -->
+                               <funcdef>boolean <function>&gt;&gt;</function></funcdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>&gt;&gt;</varname> operator returns <varname>TRUE</varname> if the bounding box of geometry A
+                       is strictly to the right of the bounding box of geometry B.</para>
+
+                       <note><para>This operand will make use of any indexes that may be available on the
+                               geometries.</para></note>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT tbl1.column1, tbl2.column1, tbl1.column2 &gt;&gt; tbl2.column2 AS right
+FROM
+  ( VALUES
+       (1, 'LINESTRING (2 3, 5 6)'::geometry)) AS tbl1,
+  ( VALUES
+       (2, 'LINESTRING (1 4, 1 7)'::geometry),
+       (3, 'LINESTRING (6 1, 6 5)'::geometry),
+       (4, 'LINESTRING (0 0, 4 3)'::geometry)) AS tbl2;
+
+ column1 | column1 | right
+---------+---------+-------
+          1 |       2 | t
+          1 |       3 | f
+          1 |       4 | f
+(3 rows)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para><xref linkend="ST_Geometry_Left" />, <xref linkend="ST_Geometry_Above" />, <xref linkend="ST_Geometry_Below" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="ST_Geometry_Contained">
+                 <refnamediv>
+                       <refname>@</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if A's bounding box is contained by B's.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <!-- TODO: Ideally, it would be nice if this could be reordered to
+                               "boolean (geometry A @ geometry B)" instead of
+                               "boolean @( geometry A, geometry B)" -->
+                               <funcdef>boolean <function>@</function></funcdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>@</varname> operator returns <varname>TRUE</varname> if the bounding box of geometry A is completely
+                       contained by the bounding box of geometry B.</para>
+
+                       <note>
+                         <para>This operand will make use of any indexes that may be available on the
+                         geometries.</para>
+                       </note>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT tbl1.column1, tbl2.column1, tbl1.column2 @ tbl2.column2 AS contained
+FROM
+  ( VALUES
+       (1, 'LINESTRING (1 1, 3 3)'::geometry)) AS tbl1,
+  ( VALUES
+       (2, 'LINESTRING (0 0, 4 4)'::geometry),
+       (3, 'LINESTRING (2 2, 4 4)'::geometry),
+       (4, 'LINESTRING (1 1, 3 3)'::geometry)) AS tbl2;
+
+ column1 | column1 | contained
+---------+---------+-----------
+          1 |       2 | t
+          1 |       3 | f
+          1 |       4 | t
+(3 rows)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para><xref linkend="ST_Geometry_Contain" />, <xref linkend="geometry_overlaps" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="is_contained_geometry_box2df">
+                 <refnamediv>
+                       <refname>@(geometry,box2df)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a geometry's 2D bounding box is contained into a 2D float precision bounding box (BOX2DF).</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>@</function></funcdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>@</varname> operator returns <varname>TRUE</varname> if the A geometry's 2D bounding box is contained the 2D bounding box B, using float precision. This means that if B is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
 
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
                        <para>&curve_support;</para>
                        <para>&P_support;</para>
-                       <para>Changed:  2.0.0 , the bounding box of geometries was changed to use double precision instead of float4 precision of
-                       prior. The side effect of this is that in particular points in prior versions that were a little different may have returned
-                               true in prior versions and false in 2.0+ since their float4 boxes would be the same but there float8 (double precision), would be
-                               different.</para>
-
                  </refsection>
 
                  <refsection>
                        <title>Examples</title>
 
-                       <programlisting>SELECT 'LINESTRING(0 0, 0 1, 1 0)'::geometry = 'LINESTRING(1 1, 0 0)'::geometry;
- ?column?
-----------
- t
-(1 row)
-
-SELECT ST_AsText(column1)
-FROM ( VALUES
-       ('LINESTRING(0 0, 1 1)'::geometry),
-       ('LINESTRING(1 1, 0 0)'::geometry)) AS foo;
-         st_astext
----------------------
- LINESTRING(0 0,1 1)
- LINESTRING(1 1,0 0)
-(2 rows)
-
--- Note: the GROUP BY uses the "=" to compare for geometry equivalency.
-SELECT ST_AsText(column1)
-FROM ( VALUES
-       ('LINESTRING(0 0, 1 1)'::geometry),
-       ('LINESTRING(1 1, 0 0)'::geometry)) AS foo
-GROUP BY column1;
-         st_astext
----------------------
- LINESTRING(0 0,1 1)
-(1 row)
-
--- In versions prior to 2.0, this used to return true --
- SELECT ST_GeomFromText('POINT(1707296.37 4820536.77)') =
-       ST_GeomFromText('POINT(1707296.27 4820536.87)') As pt_intersect;
+                       <programlisting>SELECT ST_Buffer(ST_GeomFromText('POINT(2 2)'), 1) @ ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(5,5)) AS is_contained;
 
---pt_intersect --
-f
-</programlisting>
+ is_contained
+--------------
+ t
+(1 row)</programlisting>
                  </refsection>
 
                  <refsection>
                        <title>See Also</title>
 
-                       <para><xref linkend="ST_Equals" />, <xref linkend="ST_OrderingEquals" />
-                       <!--, <xref linkend="ST_Geometry_LT" />, <xref linkend="ST_Geometry_GT" /> --></para>
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
                  </refsection>
                </refentry>
 
-               <refentry id="ST_Geometry_Right">
+               <refentry id="is_contained_box2df_geometry">
                  <refnamediv>
-                       <refname>&gt;&gt;</refname>
+                       <refname>@(box2df,geometry)</refname>
 
-                       <refpurpose>Returns <varname>TRUE</varname> if A's bounding box is strictly to the right of B's.</refpurpose>
+                       <refpurpose>Returns <varname>TRUE</varname> if a 2D float precision bounding box (BOX2DF) is contained into a geometry's 2D bounding box.</refpurpose>
                  </refnamediv>
 
                  <refsynopsisdiv>
                        <funcsynopsis>
                          <funcprototype>
-                               <!-- TODO: Ideally, it would be nice if this could be reordered to
-                               "boolean (geometry A >> geometry B)" instead of
-                               "boolean >>( geometry A, geometry B)" -->
-                               <funcdef>boolean <function>&gt;&gt;</function></funcdef>
+                               <funcdef>boolean <function>@</function></funcdef>
 
                                <paramdef>
-                                 <type>geometry </type>
+                                 <type>box2df </type>
 
                                  <parameter>A</parameter>
                                </paramdef>
@@ -683,63 +1266,62 @@ f
                  <refsection>
                        <title>Description</title>
 
-                       <para>The <varname>&gt;&gt;</varname> operator returns <varname>TRUE</varname> if the bounding box of geometry A
-                       is strictly to the right of the bounding box of geometry B.</para>
+                       <para>The <varname>@</varname> operator returns <varname>TRUE</varname> if the 2D bounding box A is contained into the B geometry's 2D bounding box, using float precision. This means that if B is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
 
-                       <note><para>This operand will make use of any indexes that may be available on the
-                               geometries.</para></note>
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
                  </refsection>
 
                  <refsection>
                        <title>Examples</title>
 
-                       <programlisting>SELECT tbl1.column1, tbl2.column1, tbl1.column2 &gt;&gt; tbl2.column2 AS right
-FROM
-  ( VALUES
-       (1, 'LINESTRING (2 3, 5 6)'::geometry)) AS tbl1,
-  ( VALUES
-       (2, 'LINESTRING (1 4, 1 7)'::geometry),
-       (3, 'LINESTRING (6 1, 6 5)'::geometry),
-       (4, 'LINESTRING (0 0, 4 3)'::geometry)) AS tbl2;
+                       <programlisting>SELECT ST_MakeBox2D(ST_MakePoint(2,2), ST_MakePoint(3,3)) @ ST_Buffer(ST_GeomFromText('POINT(1 1)'), 10) AS is_contained;
 
- column1 | column1 | right
----------+---------+-------
-          1 |       2 | t
-          1 |       3 | f
-          1 |       4 | f
-(3 rows)</programlisting>
+ is_contained
+--------------
+ t
+(1 row)</programlisting>
                  </refsection>
 
                  <refsection>
                        <title>See Also</title>
 
-                       <para><xref linkend="ST_Geometry_Left" />, <xref linkend="ST_Geometry_Above" />, <xref linkend="ST_Geometry_Below" /></para>
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
                  </refsection>
                </refentry>
 
-               <refentry id="ST_Geometry_Contained">
+               <refentry id="is_contained_box2df_box2df">
                  <refnamediv>
-                       <refname>@</refname>
+                       <refname>@(box2df,box2df)</refname>
 
-                       <refpurpose>Returns <varname>TRUE</varname> if A's bounding box is contained by B's.</refpurpose>
+                       <refpurpose>Returns <varname>TRUE</varname> if a 2D float precision bounding box (BOX2DF) is contained into another 2D float precision bounding box.</refpurpose>
                  </refnamediv>
 
                  <refsynopsisdiv>
                        <funcsynopsis>
                          <funcprototype>
-                               <!-- TODO: Ideally, it would be nice if this could be reordered to
-                               "boolean (geometry A @ geometry B)" instead of
-                               "boolean @( geometry A, geometry B)" -->
                                <funcdef>boolean <function>@</function></funcdef>
 
                                <paramdef>
-                                 <type>geometry </type>
+                                 <type>box2df </type>
 
                                  <parameter>A</parameter>
                                </paramdef>
 
                                <paramdef>
-                                 <type>geometry </type>
+                                 <type>box2df </type>
 
                                  <parameter>B</parameter>
                                </paramdef>
@@ -750,39 +1332,39 @@ FROM
                  <refsection>
                        <title>Description</title>
 
-                       <para>The <varname>@</varname> operator returns <varname>TRUE</varname> if the bounding box of geometry A is completely
-                       contained by the bounding box of geometry B.</para>
+                       <para>The <varname>@</varname> operator returns <varname>TRUE</varname> if the 2D bounding box A is contained into the 2D bounding box B, using float precision. This means that if A (or B) is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
 
-                       <note>
-                         <para>This operand will make use of any indexes that may be available on the
-                         geometries.</para>
-                       </note>
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
                  </refsection>
 
                  <refsection>
                        <title>Examples</title>
 
-                       <programlisting>SELECT tbl1.column1, tbl2.column1, tbl1.column2 @ tbl2.column2 AS contained
-FROM
-  ( VALUES
-       (1, 'LINESTRING (1 1, 3 3)'::geometry)) AS tbl1,
-  ( VALUES
-       (2, 'LINESTRING (0 0, 4 4)'::geometry),
-       (3, 'LINESTRING (2 2, 4 4)'::geometry),
-       (4, 'LINESTRING (1 1, 3 3)'::geometry)) AS tbl2;
+                       <programlisting>SELECT ST_MakeBox2D(ST_MakePoint(2,2), ST_MakePoint(3,3)) @ ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(5,5)) AS is_contained;
 
- column1 | column1 | contained
----------+---------+-----------
-          1 |       2 | t
-          1 |       3 | f
-          1 |       4 | t
-(3 rows)</programlisting>
+ is_contained
+--------------
+ t
+(1 row)</programlisting>
                  </refsection>
 
                  <refsection>
                        <title>See Also</title>
 
-                       <para><xref linkend="ST_Geometry_Contain" />, <xref linkend="geometry_overlaps" /></para>
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" /></para>
                  </refsection>
                </refentry>
 
@@ -992,6 +1574,204 @@ FROM
                  </refsection>
                </refentry>
 
+               <refentry id="contains_geometry_box2df">
+                 <refnamediv>
+                       <refname>~(geometry,box2df)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a geometry's 2D bonding box contains a 2D float precision bounding box (GIDX).</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>~</function></funcdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>~</varname> operator returns <varname>TRUE</varname> if the 2D bounding box of a geometry A contains the 2D bounding box B, using float precision. This means that if B is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
+
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_Buffer(ST_GeomFromText('POINT(1 1)'), 10) ~ ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(2,2)) AS contains;
+
+ contains
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="contains_box2df_geometry">
+                 <refnamediv>
+                       <refname>~(box2df,geometry)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a 2D float precision bounding box (BOX2DF) contains a geometry's 2D bonding box.</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>~</function></funcdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>geometry </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>~</varname> operator returns <varname>TRUE</varname> if the 2D bounding box A contains the B geometry's bounding box, using float precision. This means that if A is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
+
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(5,5)) ~ ST_Buffer(ST_GeomFromText('POINT(2 2)'), 1) AS contains;
+
+ contains
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_box2df" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
+                 </refsection>
+               </refentry>
+
+               <refentry id="contains_box2df_box2df">
+                 <refnamediv>
+                       <refname>~(box2df,box2df)</refname>
+
+                       <refpurpose>Returns <varname>TRUE</varname> if a 2D float precision bounding box (BOX2DF) contains another 2D float precision bounding box (BOX2DF).</refpurpose>
+                 </refnamediv>
+
+                 <refsynopsisdiv>
+                       <funcsynopsis>
+                         <funcprototype>
+                               <funcdef>boolean <function>~</function></funcdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>A</parameter>
+                               </paramdef>
+
+                               <paramdef>
+                                 <type>box2df </type>
+
+                                 <parameter>B</parameter>
+                               </paramdef>
+                         </funcprototype>
+                       </funcsynopsis>
+                 </refsynopsisdiv>
+
+                 <refsection>
+                       <title>Description</title>
+
+                       <para>The <varname>~</varname> operator returns <varname>TRUE</varname> if the 2D bounding box A contains the 2D bounding box B, using float precision. This means that if A is a (double precision) box2d, it will be internally converted to a float precision 2D bounding box (BOX2DF)</para>
+
+                       <note><para>This operand is intended to be used internally by BRIN indexes, more
+                               than by users.</para></note>
+
+                       <para>Availability: 2.3.0 support for Block Range INdexes (BRIN) was introduced.</para>
+                       <para>&curve_support;</para>
+                       <para>&P_support;</para>
+                 </refsection>
+
+                 <refsection>
+                       <title>Examples</title>
+
+                       <programlisting>SELECT ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(5,5)) ~ ST_MakeBox2D(ST_MakePoint(2,2), ST_MakePoint(3,3)) AS contains;
+
+ contains
+----------
+ t
+(1 row)</programlisting>
+                 </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+
+                       <para>
+                               <xref linkend="overlaps_geometry_box2df" />,
+                               <xref linkend="overlaps_box2df_geometry" />,
+                               <xref linkend="overlaps_box2df_box2df" />,
+                               <xref linkend="contains_geometry_box2df" />,
+                               <xref linkend="contains_box2df_geometry" />,
+                               <xref linkend="is_contained_geometry_box2df" />,
+                               <xref linkend="is_contained_box2df_geometry" />,
+                               <xref linkend="is_contained_box2df_box2df" /></para>
+                 </refsection>
+               </refentry>
+
                <refentry id="ST_Geometry_Same">
                  <refnamediv>
                        <refname>~=</refname>
index f92b11934615d7cb62cf9b6560c4cfec03785488..ee91e6740d23d9bc4b70466fe3798f21e2b9a7f9 100644 (file)
@@ -2178,6 +2178,72 @@ SELECT UPDATE_GEOMETRY_STATS([table_name], [column_name]);</programlisting></par
          built.</para>
        </sect2>
 
+       <sect2 id="brin_indexes">
+         <title>BRIN Indexes</title>
+
+         <para>BRIN stands for "Block Range Index" and is a generic form of
+         indexing that has been introduced in PostgreSQL 9.5. BRIN is a lossy kind
+         of index, and its main usage is to provide a compromise for both read and
+         write performance. It's primary goal is to handle very large tables for
+         which some of the columns have some natural correlation with their
+         physical location within the table.  In addition to GIS indexing, BRIN is
+         used to speed up searches on various kinds of regular or irregular data
+         structures (integer, arrays etc).</para>
+
+         <para>Once a GIS data table exceeds a few thousand rows, you will want
+         to build an index to speed up spatial searches of the data (unless all
+         your searches are based on attributes, in which case you'll want to
+      build a normal index on the attribute fields). GiST indexes are really
+      performant as long as their size doesn't exceed the amount of RAM
+      available for the database, and as long as you can afford the storage
+      size, and the penalty in write workload. Otherwise, BRIN index can be
+      considered as an alternative. </para>
+
+      <para>The idea of a BRIN index is to store only the bouding box englobing
+      all the geometries contained in all the rows in a set of table blocks,
+      called a range.  Obviously, this indexing method will only be efficient
+      if the data is physically ordered in a way where the resulting bouding
+      boxes for block ranges will be mutually exclusive. The resulting index
+      will be really small, but will be less efficient than a GiST index in
+      many cases.</para>
+
+         <para>Building a BRIN index is way less intensive than building a GiST
+         index. It's quite common to build a BRIN index in more than ten time less
+         than a GiST index would have required. As a BRIN index only store one
+         bouding box for one to many table blocks, it's pretty common to consume
+         up to a thousand time less disk space for this kind of indexes.</para>
+
+      <para>You can choose the number of blocks to summarize in a range. If you
+      decrease this number, the index will be bigger but will probably help to
+      get better performance.</para>
+
+         <para>The syntax for building a BRIN index on a "geometry" column is as
+         follows:</para>
+
+         <para><programlisting>CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geometryfield] ); </programlisting></para>
+         <para>The above syntax will always build a 2D-index.  To get the 3d-dimensional index supported in PostGIS 2.0+ for the geometry type, you can create one using this syntax</para>
+         <programlisting>CREATE INDEX [indexname] ON [tablename] USING BRIN ([geometryfield] brin_geometry_inclusion_ops_3d);</programlisting>
+         <para>These above syntaxes will use the default number or block in a range, which is 128. To specify the number of blocks you want to summarise in a range, you can create one using this syntax</para>
+         <para><programlisting>CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geometryfield] ) WITH (pages_per_range = [number]); </programlisting></para>
+
+          <para>Also the "geography" datatype is supported for BRIN indexing. The
+          syntax for building a BRIN index on a "geometry" column is as follows:</para>
+
+          <para><programlisting>CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geographyfield] ); </programlisting></para>
+          <para>The above syntax will always build a 2D-index for geospatial objetcs on the spheroid. </para>
+
+          <para>Currently, just the "inclusion support" is considered here, meaning
+          that just <varname>&amp;&amp;</varname>, <varname>~</varname> and
+          <varname>@</varname> operators can be used for the 2D cases (both for
+          "geometry" and for "geography"), and just the <varname>&amp;&amp;&amp;</varname>
+          operator can be used for the 3D geometries. There is no support
+          for kNN searches at the moment.</para>
+
+         <para><programlisting>VACUUM ANALYZE [table_name] [(column_name)];
+-- This is only needed for PostgreSQL 7.4 installations and below
+SELECT UPDATE_GEOMETRY_STATS([table_name], [column_name]);</programlisting></para>
+       </sect2>
+
        <sect2>
          <title>Using Indexes</title>
 
index 9a277d933bdf4b1ce7bda3f73151998bc195e373..4a8d8c977871c1a9694a9e81d6be01bc46e8f25f 100644 (file)
@@ -374,6 +374,7 @@ GIDX* gidx_new(int ndims)
 {
        size_t size = GIDX_SIZE(ndims);
        GIDX *g = (GIDX*)palloc(size);
+       Assert( (ndims <= GIDX_MAX_DIM) && (size <= GIDX_MAX_SIZE) );
        POSTGIS_DEBUGF(5,"created new gidx of %d dimensions, size %d", ndims, (int)size);
        SET_VARSIZE(g, size);
        return g;
index 57177c7d7be5e7dc61a1e1f012bf3bd2495e63d2..b6a3c49ab918a790011984ed2a2abb3a0a7163e8 100644 (file)
@@ -24,6 +24,7 @@ typedef struct
 ** 4 bytes varsize + 4 dimensions * 2 ordinates * 4 bytes float size = 36 bytes
 */
 #define GIDX_MAX_SIZE 36
+#define GIDX_MAX_DIM 4
 
 
 /**********************************************************************
@@ -94,5 +95,6 @@ GSERIALIZED* gserialized_set_gidx(GSERIALIZED *g, GIDX *gidx);
 /* Remove the box from a disk serialization */
 GSERIALIZED* gserialized_drop_gidx(GSERIALIZED *g);
 
+int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df);
 
 
index 6a176a1e7d80a12d66a9cf491db076d0bc865a2a..26dfe3289f4ced5e57a288859cde7959bde9ab31 100644 (file)
@@ -46,6 +46,9 @@ DATA_built=$(SQL_built)
 SQL_OBJS=$(SQL_objs)
 endif
 
+ifeq (@HAVE_BRIN@,yes)
+BRIN_OBJ= brin_2d.o brin_nd.o brin_common.o
+endif
 
 
 # SQL preprocessor
@@ -87,6 +90,7 @@ PG_OBJS= \
        gserialized_typmod.o \
        gserialized_gist_2d.o \
        gserialized_gist_nd.o \
+       $(BRIN_OBJ) \
        gserialized_estimate.o \
        geography_inout.o \
        geography_btree.o \
index 69ac907b3e0afda3e329714e720dadd23059961b..f16e74c1aae287ab00956f39b55913c6e179eae0 100644 (file)
@@ -286,6 +286,93 @@ CREATE OPERATOR CLASS gist_geography_ops
        FUNCTION        6        geography_gist_picksplit (internal, internal),
        FUNCTION        7        geography_gist_same (box2d, box2d, internal);
 
+#if POSTGIS_PGSQL_VERSION > 94
+--------------------------------------------------------------------
+-- BRIN support for geographies                                   --
+--------------------------------------------------------------------
+
+--------------------------------
+-- the needed cross-operators --
+--------------------------------
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_geog(gidx, geography)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_gidx_geog_overlaps'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_geog(gidx, gidx)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_gidx_gidx_overlaps'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OPERATOR && (
+  LEFTARG    = gidx,
+  RIGHTARG   = geography,
+  PROCEDURE  = overlaps_geog,
+  COMMUTATOR = &&
+);
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_geog(geography, gidx)
+RETURNS boolean
+AS $$
+  SELECT $2 && $1;
+$$ LANGUAGE SQL IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OPERATOR && (
+  LEFTARG    = geography,
+  RIGHTARG   = gidx,
+  PROCEDURE  = overlaps_geog,
+  COMMUTATOR = &&
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR && (
+  LEFTARG   = gidx,
+  RIGHTARG  = gidx,
+  PROCEDURE = overlaps_geog,
+  COMMUTATOR = &&
+);
+
+--------------------------------
+-- the OpFamily               --
+--------------------------------
+
+-- Availability: 2.3.0
+CREATE OPERATOR FAMILY brin_geography_inclusion_ops USING brin;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION geog_brin_inclusion_add_value(internal, internal, internal, internal) RETURNS boolean
+        AS 'MODULE_PATHNAME','geog_brin_inclusion_add_value'
+        LANGUAGE 'c';
+
+-- Availability: 2.3.0
+CREATE OPERATOR CLASS brin_geography_inclusion_ops
+  DEFAULT FOR TYPE geography
+  USING brin
+  FAMILY brin_geography_inclusion_ops AS
+    OPERATOR      3        &&(geography, geography),
+    FUNCTION      1        brin_inclusion_opcinfo(internal) ,
+    FUNCTION      2        geog_brin_inclusion_add_value(internal, internal, internal, internal) ,
+    FUNCTION      3        brin_inclusion_consistent(internal, internal, internal) ,
+    FUNCTION      4        brin_inclusion_union(internal, internal, internal) ,
+  STORAGE gidx;
+
+ALTER OPERATOR FAMILY brin_geography_inclusion_ops USING brin ADD
+    OPERATOR      3         &&(gidx, geography),
+
+    OPERATOR      3         &&(geography, gidx),
+
+    OPERATOR      3         &&(gidx, gidx);
+
+---------------------------------------------------------------
+-- END
+---------------------------------------------------------------
+#endif
 
 -- ---------- ---------- ---------- ---------- ---------- ---------- ----------
 -- B-Tree Functions
index 06eaaeca205fe41a0a7da3ac8a9eb4ff77ac8352..dfd5b42c8ade3de8d794ed741b1b7e3a00a2327e 100644 (file)
@@ -116,6 +116,15 @@ Datum gserialized_overbelow_2d(PG_FUNCTION_ARGS);
 Datum gserialized_distance_box_2d(PG_FUNCTION_ARGS);
 Datum gserialized_distance_centroid_2d(PG_FUNCTION_ARGS);
 
+#if POSTGIS_PGSQL_VERSION > 94
+Datum gserialized_contains_box2df_geom_2d(PG_FUNCTION_ARGS);
+Datum gserialized_contains_box2df_box2df_2d(PG_FUNCTION_ARGS);
+Datum gserialized_within_box2df_geom_2d(PG_FUNCTION_ARGS);
+Datum gserialized_within_box2df_box2df_2d(PG_FUNCTION_ARGS);
+Datum gserialized_overlaps_box2df_geom_2d(PG_FUNCTION_ARGS);
+Datum gserialized_overlaps_box2df_box2df_2d(PG_FUNCTION_ARGS);
+#endif
+
 /*
 ** true/false test function type
 */
@@ -541,7 +550,7 @@ static double box2df_distance(const BOX2DF *a, const BOX2DF *b)
 * full object and return the box based on that. If no box is available,
 * return #LW_FAILURE, otherwise #LW_SUCCESS.
 */
-static int
+int
 gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
 {
        GSERIALIZED *gpart;
@@ -621,8 +630,84 @@ gserialized_datum_predicate_2d(Datum gs1, Datum gs2, box2df_predicate predicate)
        return LW_FALSE;
 }
 
+#if POSTGIS_PGSQL_VERSION > 94
+static int
+gserialized_datum_predicate_box2df_geom_2d(const BOX2DF *br1, Datum gs2, box2df_predicate predicate)
+{
+       BOX2DF b2, *br2=NULL;
+       POSTGIS_DEBUG(3, "entered function");
+
+       if (gserialized_datum_get_box2df_p(gs2, &b2) == LW_SUCCESS) br2 = &b2;
+
+       if ( predicate(br1, br2) )
+       {
+               POSTGIS_DEBUGF(3, "got boxes %s and %s", br1 ? box2df_to_string(&b1) : "(null)", br2 ? box2df_to_string(&b2) : "(null)");
+               return LW_TRUE;
+       }
+       return LW_FALSE;
+}
+
+/***********************************************************************
+* BRIN 2-D Index Operator Functions
+*/
+
+PG_FUNCTION_INFO_V1(gserialized_contains_box2df_geom_2d);
+Datum gserialized_contains_box2df_geom_2d(PG_FUNCTION_ARGS)
+{
+       POSTGIS_DEBUG(3, "entered function");
+        if ( gserialized_datum_predicate_box2df_geom_2d((BOX2DF*)PG_GETARG_POINTER(0), PG_GETARG_DATUM(1), box2df_contains) == LW_TRUE )
+                PG_RETURN_BOOL(TRUE);
+
+        PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_contains_box2df_box2df_2d);
+Datum gserialized_contains_box2df_box2df_2d(PG_FUNCTION_ARGS)
+{
+       if ( box2df_contains((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
+               PG_RETURN_BOOL(TRUE);
+
+       PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_within_box2df_geom_2d);
+Datum gserialized_within_box2df_geom_2d(PG_FUNCTION_ARGS)
+{
+       POSTGIS_DEBUG(3, "entered function");
+        if ( gserialized_datum_predicate_box2df_geom_2d((BOX2DF*)PG_GETARG_POINTER(0), PG_GETARG_DATUM(1), box2df_within) == LW_TRUE )
+                PG_RETURN_BOOL(TRUE);
 
+        PG_RETURN_BOOL(FALSE);
+}
 
+PG_FUNCTION_INFO_V1(gserialized_within_box2df_box2df_2d);
+Datum gserialized_within_box2df_box2df_2d(PG_FUNCTION_ARGS)
+{
+        if ( box2df_within((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
+                PG_RETURN_BOOL(TRUE);
+
+        PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_overlaps_box2df_geom_2d);
+Datum gserialized_overlaps_box2df_geom_2d(PG_FUNCTION_ARGS)
+{
+        POSTGIS_DEBUG(3, "entered function");
+        if ( gserialized_datum_predicate_box2df_geom_2d((BOX2DF*)PG_GETARG_POINTER(0), PG_GETARG_DATUM(1), box2df_overlaps) == LW_TRUE )
+                PG_RETURN_BOOL(TRUE);
+
+        PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_overlaps_box2df_box2df_2d);
+Datum gserialized_overlaps_box2df_box2df_2d(PG_FUNCTION_ARGS)
+{
+        if ( box2df_overlaps((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
+                PG_RETURN_BOOL(TRUE);
+
+        PG_RETURN_BOOL(FALSE);
+}
+#endif
 
 /***********************************************************************
 * GiST 2-D Index Operator Functions
index fb281afd1112a091d5c9bc02a95921e61a2cd11a..9be47be17d6d1ec6832122f3230bf0eb204afceb 100644 (file)
@@ -100,8 +100,20 @@ Datum gserialized_gist_geog_distance(PG_FUNCTION_ARGS);
 */
 Datum gserialized_overlaps(PG_FUNCTION_ARGS);
 Datum gserialized_contains(PG_FUNCTION_ARGS);
+#if POSTGIS_PGSQL_VERSION > 94
+Datum gserialized_gidx_geom_contains(PG_FUNCTION_ARGS);
+Datum gserialized_gidx_gidx_contains(PG_FUNCTION_ARGS);
+#endif
 Datum gserialized_within(PG_FUNCTION_ARGS);
+#if POSTGIS_PGSQL_VERSION > 94
+Datum gserialized_gidx_geom_within(PG_FUNCTION_ARGS);
+Datum gserialized_gidx_gidx_within(PG_FUNCTION_ARGS);
+#endif
 Datum gserialized_distance_nd(PG_FUNCTION_ARGS);
+#if POSTGIS_PGSQL_VERSION > 94
+Datum gserialized_gidx_geom_same(PG_FUNCTION_ARGS);
+Datum gserialized_gidx_gidx_same(PG_FUNCTION_ARGS);
+#endif
 
 /*
 ** GIDX true/false test function type
@@ -476,6 +488,49 @@ gserialized_datum_predicate(Datum gs1, Datum gs2, gidx_predicate predicate)
        return LW_FALSE;
 }
 
+#if POSTGIS_PGSQL_VERSION > 94
+static int
+gserialized_datum_predicate_gidx_geom(GIDX *gidx1, Datum gs2, gidx_predicate predicate)
+{
+   /* Put aside some stack memory and use it for GIDX pointers. */
+   char boxmem2[GIDX_MAX_SIZE];
+   GIDX *gidx2 = (GIDX*)boxmem2;
+
+   POSTGIS_DEBUG(3, "entered function");
+
+   /* Must be able to build box for gs2 arguement (ie, not empty geometry)
+      and predicate function to return true. */
+   if ( (gserialized_datum_get_gidx_p(gs2, gidx2) == LW_SUCCESS) &&
+         predicate(gidx1, gidx2) )
+   {
+       POSTGIS_DEBUGF(3, "got boxes %s and %s", gidx_to_string(gidx1), gidx_to_string(gidx2));
+       return LW_TRUE;
+   }
+   return LW_FALSE;
+}
+
+static int
+gserialized_datum_predicate_geom_gidx(Datum gs1, GIDX *gidx2, gidx_predicate predicate)
+{
+   /* Put aside some stack memory and use it for GIDX pointers. */
+   char boxmem2[GIDX_MAX_SIZE];
+   GIDX *gidx1 = (GIDX*)boxmem2;
+
+   POSTGIS_DEBUG(3, "entered function");
+
+   /* Must be able to build box for gs2 arguement (ie, not empty geometry)
+      and predicate function to return true. */
+   if ( (gserialized_datum_get_gidx_p(gs1, gidx1) == LW_SUCCESS) &&
+         predicate(gidx1, gidx2) )
+   {
+       POSTGIS_DEBUGF(3, "got boxes %s and %s", gidx_to_string(gidx1), gidx_to_string(gidx2));
+       return LW_TRUE;
+   }
+   return LW_FALSE;
+}
+#endif
+
+
 /**
 * Calculate the centroid->centroid distance between the boxes.
 */
@@ -806,6 +861,36 @@ Datum gserialized_within(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(FALSE);
 }
 
+#if POSTGIS_PGSQL_VERSION > 94
+/*
+** '~' and operator function. Based on a GIDX and a serialized return true if
+** the first is contained by the second.
+*/
+PG_FUNCTION_INFO_V1(gserialized_gidx_geom_within);
+Datum gserialized_gidx_geom_within(PG_FUNCTION_ARGS)
+{
+   GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
+
+   if ( gserialized_datum_predicate_geom_gidx(PG_GETARG_DATUM(1), gidx, gidx_contains) == LW_TRUE )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+
+/*
+** '~' and operator function. Based on two GIDX return true if
+** the first is contained by the second.
+*/
+PG_FUNCTION_INFO_V1(gserialized_gidx_gidx_within);
+Datum gserialized_gidx_gidx_within(PG_FUNCTION_ARGS)
+{
+   if ( gidx_contains((GIDX *)PG_GETARG_POINTER(1), (GIDX *)PG_GETARG_POINTER(0)))
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+#endif
+
 /*
 ** '@' and operator function. Based on two serialized return true if
 ** the first contains the second.
@@ -821,6 +906,56 @@ Datum gserialized_contains(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(FALSE);
 }
 
+#if POSTGIS_PGSQL_VERSION > 94
+/*
+** '@' and operator function. Based on a GIDX and a serialized return true if
+** the first contains the second.
+*/
+PG_FUNCTION_INFO_V1(gserialized_gidx_geom_contains);
+Datum gserialized_gidx_geom_contains(PG_FUNCTION_ARGS)
+{
+   GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
+
+   if ( gserialized_datum_predicate_gidx_geom(gidx, PG_GETARG_DATUM(1), gidx_contains) == LW_TRUE )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+
+/*
+** '@' and operator function. Based on two GIDX return true if
+** the first contains the second.
+*/
+PG_FUNCTION_INFO_V1(gserialized_gidx_gidx_contains);
+Datum gserialized_gidx_gidx_contains(PG_FUNCTION_ARGS)
+{
+   if ( gidx_contains((GIDX *)PG_GETARG_POINTER(0), (GIDX *)PG_GETARG_POINTER(1)))
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_gidx_geom_same);
+Datum gserialized_gidx_geom_same(PG_FUNCTION_ARGS)
+{
+   GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
+
+   if ( gserialized_datum_predicate_gidx_geom(gidx, PG_GETARG_DATUM(1), gidx_equals) == LW_TRUE )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_gidx_gidx_same);
+Datum gserialized_gidx_gidx_same(PG_FUNCTION_ARGS)
+{
+   if ( gidx_equals((GIDX *)PG_GETARG_POINTER(0), (GIDX *)PG_GETARG_POINTER(1)) )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+#endif
+
 /*
 ** '&&' operator function. Based on two serialized return true if
 ** they overlap and false otherwise.
@@ -836,6 +971,42 @@ Datum gserialized_overlaps(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(FALSE);
 }
 
+#if POSTGIS_PGSQL_VERSION > 94
+/*
+ * This is the cross-operator for the geographies
+ */
+PG_FUNCTION_INFO_V1(gserialized_gidx_geog_overlaps);
+Datum gserialized_gidx_geog_overlaps(PG_FUNCTION_ARGS)
+{
+   GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
+
+   if ( gserialized_datum_predicate_gidx_geom(gidx, PG_GETARG_DATUM(1), gidx_overlaps) == LW_TRUE )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_gidx_geom_overlaps);
+Datum gserialized_gidx_geom_overlaps(PG_FUNCTION_ARGS)
+{
+   GIDX *gidx = (GIDX *)PG_GETARG_POINTER(0);
+
+   if ( gserialized_datum_predicate_gidx_geom(gidx, PG_GETARG_DATUM(1), gidx_overlaps) == LW_TRUE )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+
+PG_FUNCTION_INFO_V1(gserialized_gidx_gidx_overlaps);
+Datum gserialized_gidx_gidx_overlaps(PG_FUNCTION_ARGS)
+{
+   if ( gidx_overlaps((GIDX *)PG_GETARG_POINTER(0), (GIDX *)PG_GETARG_POINTER(1)) )
+       PG_RETURN_BOOL(TRUE);
+
+   PG_RETURN_BOOL(FALSE);
+}
+#endif
+
 /***********************************************************************
 * GiST Index  Support Functions
 */
index 59b3d177cd9bede011b69aff3838ed7f50dd9396..235d688bc6b68f3005a138697b51b2bd0fb26120 100644 (file)
@@ -746,7 +746,6 @@ CREATE OPERATOR CLASS gist_geometry_ops_2d
        FUNCTION        6        geometry_gist_picksplit_2d (internal, internal),
        FUNCTION        7        geometry_gist_same_2d (geom1 geometry, geom2 geometry, internal);
 
-
 -----------------------------------------------------------------------------
 -- GiST ND GEOMETRY-over-GSERIALIZED
 -----------------------------------------------------------------------------
@@ -5546,10 +5545,300 @@ CREATE OR REPLACE FUNCTION ST_InterpolatePoint(Line geometry, Point geometry)
        AS 'MODULE_PATHNAME', 'ST_InterpolatePoint'
        LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL;
 
+#if POSTGIS_PGSQL_VERSION > 94
+--------------------------------------------------------------------
+-- BRIN support                                                   --
+--------------------------------------------------------------------
+
+---------------------------------
+-- 2d operators                --
+---------------------------------
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION contains_2d(box2df, geometry)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_contains_box2df_geom_2d'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION is_contained_2d(box2df, geometry)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_within_box2df_geom_2d'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_2d(box2df, geometry)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_overlaps_box2df_geom_2d'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_2d(box2df, box2df)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_contains_box2df_box2df_2d'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION contains_2d(box2df, box2df)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_contains_box2df_box2df_2d'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION is_contained_2d(box2df, box2df)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_contains_box2df_box2df_2d'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OPERATOR ~ (
+  LEFTARG    = box2df,
+  RIGHTARG   = geometry,
+  PROCEDURE  = contains_2d,
+  COMMUTATOR = @
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR @ (
+  LEFTARG    = box2df,
+  RIGHTARG   = geometry,
+  PROCEDURE  = is_contained_2d,
+  COMMUTATOR = ~
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR && (
+  LEFTARG    = box2df,
+  RIGHTARG   = geometry,
+  PROCEDURE  = overlaps_2d,
+  COMMUTATOR = &&
+);
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION contains_2d(geometry, box2df)
+RETURNS boolean
+AS $$
+  SELECT $2 @ $1;
+$$ LANGUAGE SQL IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION is_contained_2d(geometry, box2df)
+RETURNS boolean
+AS $$
+  SELECT $2 ~ $1;
+$$ LANGUAGE SQL IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_2d(geometry, box2df)
+RETURNS boolean
+AS $$
+  SELECT $2 && $1;
+$$ LANGUAGE SQL IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OPERATOR ~ (
+  LEFTARG = geometry,
+  RIGHTARG = box2df,
+  COMMUTATOR = @,
+  PROCEDURE  = contains_2d
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR @ (
+  LEFTARG = geometry,
+  RIGHTARG = box2df,
+  COMMUTATOR = ~,
+  PROCEDURE = is_contained_2d
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR && (
+  LEFTARG    = geometry,
+  RIGHTARG   = box2df,
+  PROCEDURE  = overlaps_2d,
+  COMMUTATOR = &&
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR && (
+  LEFTARG   = box2df,
+  RIGHTARG  = box2df,
+  PROCEDURE = overlaps_2d,
+  COMMUTATOR = &&
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR @ (
+  LEFTARG   = box2df,
+  RIGHTARG  = box2df,
+  PROCEDURE = is_contained_2d,
+  COMMUTATOR = ~
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR ~ (
+  LEFTARG   = box2df,
+  RIGHTARG  = box2df,
+  PROCEDURE = contains_2d,
+  COMMUTATOR = @
+);
+
+----------------------------
+-- nd operators           --
+----------------------------
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_nd(gidx, geometry)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_gidx_geom_overlaps'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_nd(gidx, gidx)
+RETURNS boolean
+AS 'MODULE_PATHNAME','gserialized_gidx_gidx_overlaps'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OPERATOR &&& (
+  LEFTARG    = gidx,
+  RIGHTARG   = geometry,
+  PROCEDURE  = overlaps_nd,
+  COMMUTATOR = &&&
+);
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION overlaps_nd(geometry, gidx)
+RETURNS boolean
+AS $$
+  SELECT $2 &&& $1;
+$$ LANGUAGE SQL IMMUTABLE STRICT;
+
+-- Availability: 2.3.0
+CREATE OPERATOR &&& (
+  LEFTARG    = geometry,
+  RIGHTARG   = gidx,
+  PROCEDURE  = overlaps_nd,
+  COMMUTATOR = &&&
+);
+
+-- Availability: 2.3.0
+CREATE OPERATOR &&& (
+  LEFTARG   = gidx,
+  RIGHTARG  = gidx,
+  PROCEDURE = overlaps_nd,
+  COMMUTATOR = &&&
+);
+
+------------------------------
+-- Create operator families --
+------------------------------
+
+-------------
+-- 2D case --
+-------------
+
+-- Availability: 2.3.0
+CREATE OPERATOR FAMILY brin_geometry_inclusion_ops_2d USING brin;
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION geom2d_brin_inclusion_add_value(internal, internal, internal, internal) RETURNS boolean
+       AS 'MODULE_PATHNAME','geom2d_brin_inclusion_add_value'
+       LANGUAGE 'c';
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION geom3d_brin_inclusion_add_value(internal, internal, internal, internal) RETURNS boolean
+       AS 'MODULE_PATHNAME','geom3d_brin_inclusion_add_value'
+       LANGUAGE 'c';
+
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION geom4d_brin_inclusion_add_value(internal, internal, internal, internal) RETURNS boolean
+       AS 'MODULE_PATHNAME','geom4d_brin_inclusion_add_value'
+       LANGUAGE 'c';
+
+-- Availability: 2.3.0
+CREATE OPERATOR CLASS brin_geometry_inclusion_ops_2d
+  DEFAULT FOR TYPE geometry
+  USING brin
+  FAMILY brin_geometry_inclusion_ops_2d AS
+    OPERATOR      3        &&(geometry, geometry),
+    OPERATOR      7        ~(geometry, geometry),
+    OPERATOR      8        @(geometry, geometry),
+    FUNCTION      1        brin_inclusion_opcinfo(internal) ,
+    FUNCTION      2        geom2d_brin_inclusion_add_value(internal, internal, internal, internal) ,
+    FUNCTION      3        brin_inclusion_consistent(internal, internal, internal) ,
+    FUNCTION      4        brin_inclusion_union(internal, internal, internal) ,
+  STORAGE box2df;
+
+ALTER OPERATOR FAMILY brin_geometry_inclusion_ops_2d USING brin ADD
+    OPERATOR      3         &&(box2df, geometry),
+    OPERATOR      7         ~(box2df, geometry),
+    OPERATOR      8         @(box2df, geometry),
+
+    OPERATOR      3         &&(geometry, box2df),
+    OPERATOR      7         ~(geometry, box2df),
+    OPERATOR      8         @(geometry, box2df),
+
+    OPERATOR      3         &&(box2df, box2df),
+    OPERATOR      7         ~(box2df, box2df),
+    OPERATOR      8         @(box2df, box2df);
+
+-------------
+-- 3D case --
+-------------
+
+-- Availability: 2.3.0
+CREATE OPERATOR FAMILY brin_geometry_inclusion_ops_3d USING brin;
+
+-- Availability: 2.3.0
+CREATE OPERATOR CLASS brin_geometry_inclusion_ops_3d
+  FOR TYPE geometry
+  USING brin
+  FAMILY brin_geometry_inclusion_ops_3d AS
+    OPERATOR      3        &&&(geometry, geometry),
+    FUNCTION      1        brin_inclusion_opcinfo(internal) ,
+    FUNCTION      2        geom3d_brin_inclusion_add_value(internal, internal, internal, internal) ,
+    FUNCTION      3        brin_inclusion_consistent(internal, internal, internal) ,
+    FUNCTION      4        brin_inclusion_union(internal, internal, internal) ,
+  STORAGE gidx;
+
+ALTER OPERATOR FAMILY brin_geometry_inclusion_ops_3d USING brin ADD
+    OPERATOR      3         &&&(gidx, geometry),
+
+    OPERATOR      3         &&&(geometry, gidx),
+
+    OPERATOR      3         &&&(gidx, gidx);
+
+-------------
+-- 4D case --
+-------------
+
+-- Availability: 2.3.0
+CREATE OPERATOR FAMILY brin_geometry_inclusion_ops_4d USING brin;
+
+-- Availability: 2.3.0
+CREATE OPERATOR CLASS brin_geometry_inclusion_ops_4d
+  FOR TYPE geometry
+  USING brin
+  FAMILY brin_geometry_inclusion_ops_4d AS
+    OPERATOR      3        &&&(geometry, geometry),
+    FUNCTION      1        brin_inclusion_opcinfo(internal) ,
+    FUNCTION      2        geom4d_brin_inclusion_add_value(internal, internal, internal, internal) ,
+    FUNCTION      3        brin_inclusion_consistent(internal, internal, internal) ,
+    FUNCTION      4        brin_inclusion_union(internal, internal, internal) ,
+  STORAGE gidx;
+
+ALTER OPERATOR FAMILY brin_geometry_inclusion_ops_4d USING brin ADD
+    OPERATOR      3         &&&(gidx, geometry),
+
+    OPERATOR      3         &&&(geometry, gidx),
+
+    OPERATOR      3         &&&(gidx, gidx);
+
 ---------------------------------------------------------------
 -- END
 ---------------------------------------------------------------
-
+#endif
 
 ---------------------------------------------------------------
 -- USER CONTRIBUTED
index d8a2ad6ae5e1e9271e6e08eb3ae55316d99c4a1b..5b7946aa7769feafb903f96b172883a6a6b1f16c 100644 (file)
@@ -23,6 +23,7 @@ POSTGIS_MAJOR_VERSION=@POSTGIS_MAJOR_VERSION@
 POSTGIS_MINOR_VERSION=@POSTGIS_MINOR_VERSION@
 HAVE_JSON=@HAVE_JSON@
 HAVE_SFCGAL=@HAVE_SFCGAL@
+HAVE_BRIN=@HAVE_BRIN@
 MINGWBUILD=@MINGWBUILD@
 INTERRUPTTESTS=@INTERRUPTTESTS@
 
@@ -231,6 +232,13 @@ ifeq ($(HAVE_JSON),yes)
                in_geojson
 endif
 
+ifeq ($(HAVE_BRIN),yes)
+       TESTS += \
+               regress_brin_index \
+               regress_brin_index_3d \
+               regress_brin_index_geography
+endif
+
 ifeq ($(HAVE_SFCGAL),yes)
        # SFCGAL additionnal backend
        TESTS += \
index 9298b652a4658ba4dfc9f67ee37085c0bb2955b4..0425b016855b2e53913dac5ed2c671618bb78cb7 100755 (executable)
@@ -390,6 +390,37 @@ EOF
                }
        }
 
+       # This code handles operator family by creating them if we are doing a major upgrade
+       if ( /^create operator family\s+(\w+)\s+USING\s+(\w+)\s*/i )
+       {
+               my $opfname = $1;
+               my $amname = $2;
+               my $def = $_;
+               my $opfsig = $opfname . " " . $amname;
+               while(<INPUT>)
+               {
+                       $def .= $_;
+                       last if /\);/;
+               }
+
+       my $last_updated = parse_last_updated($comment);
+       if ( ! $last_updated ) {
+               print STDERR "WARNING: no last updated info for operator family '${opfname}'\n";
+               $last_updated = find_last_updated("opfamilies", $opfsig);
+       }
+       print "-- Operator family ${opfsig} -- LastUpdated: ${last_updated}\n";
+       print <<"EOF";
+DO LANGUAGE 'plpgsql'
+\$postgis_proc_upgrade\$
+BEGIN
+  IF $last_updated > version_from_num FROM _postgis_upgrade_info THEN
+    EXECUTE \$postgis_proc_upgrade_parsed_def\$ $def \$postgis_proc_upgrade_parsed_def\$;
+  END IF;
+END
+\$postgis_proc_upgrade\$;
+EOF
+       }
+
        # This code handles operator classes by creating them if we are doing a major upgrade
        if ( /^create operator class\s+(\w+)\s*/i )
        {