[postgis-tickets] r15028 - Add support for BRIN indexes (2nd Quadrant, Giuseppe Broccolo, Julien Rouhaud)
Regina Obe
lr at pcorp.us
Sat Jul 30 20:46:40 PDT 2016
Author: robe
Date: 2016-07-30 20:46:40 -0700 (Sat, 30 Jul 2016)
New Revision: 15028
Modified:
trunk/NEWS
trunk/configure.ac
trunk/doc/reference_operator.xml
trunk/doc/using_postgis_dataman.xml
trunk/libpgcommon/gserialized_gist.c
trunk/libpgcommon/gserialized_gist.h
trunk/postgis/Makefile.in
trunk/postgis/geography.sql.in
trunk/postgis/gserialized_gist_2d.c
trunk/postgis/gserialized_gist_nd.c
trunk/postgis/postgis.sql.in
trunk/regress/Makefile.in
trunk/utils/postgis_proc_upgrade.pl
Log:
Add support for BRIN indexes (2nd Quadrant, Giuseppe Broccolo, Julien Rouhaud)
Closes #3591
Closes https://github.com/postgis/postgis/pull/106
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/NEWS 2016-07-31 03:46:40 UTC (rev 15028)
@@ -4,7 +4,7 @@
* 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 @@
- #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 *
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/configure.ac 2016-07-31 03:46:40 UTC (rev 15028)
@@ -444,6 +444,11 @@
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 @@
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
Modified: trunk/doc/reference_operator.xml
===================================================================
--- trunk/doc/reference_operator.xml 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/doc/reference_operator.xml 2016-07-31 03:46:40 UTC (rev 15028)
@@ -91,6 +91,204 @@
</refsection>
</refentry>
+ <refentry id="overlaps_geometry_box2df">
+ <refnamediv>
+ <refname>&&(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>&&</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 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) && 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>&&(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>&&</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 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)) && 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>&&(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>&&</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 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)) && 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>&&&</refname>
@@ -177,6 +375,192 @@
</refsection>
</refentry>
+ <refentry id="overlaps_nd_geometry_gidx">
+ <refnamediv>
+ <refname>&&&(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>&&&</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>&&&</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) &&& 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>&&&(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>&&&</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>&&&</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)) &&& 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>&&&(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>&&&</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>&&&</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)) &&& 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>&<</refname>
@@ -786,6 +1170,204 @@
</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>
+ </refsection>
+
+ <refsection>
+ <title>Examples</title>
+
+ <programlisting>SELECT ST_Buffer(ST_GeomFromText('POINT(2 2)'), 1) @ ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(5,5)) AS is_contained;
+
+ is_contained
+--------------
+ 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="contains_box2df_box2df" />,
+ <xref linkend="is_contained_box2df_geometry" />,
+ <xref linkend="is_contained_box2df_box2df" /></para>
+ </refsection>
+ </refentry>
+
+ <refentry id="is_contained_box2df_geometry">
+ <refnamediv>
+ <refname>@(box2df,geometry)</refname>
+
+ <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>
+ <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 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 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(2,2), ST_MakePoint(3,3)) @ ST_Buffer(ST_GeomFromText('POINT(1 1)'), 10) AS is_contained;
+
+ is_contained
+--------------
+ 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="contains_box2df_box2df" />,
+ <xref linkend="is_contained_geometry_box2df" />,
+ <xref linkend="is_contained_box2df_box2df" /></para>
+ </refsection>
+ </refentry>
+
+ <refentry id="is_contained_box2df_box2df">
+ <refnamediv>
+ <refname>@(box2df,box2df)</refname>
+
+ <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>
+ <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 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 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(2,2), ST_MakePoint(3,3)) @ ST_MakeBox2D(ST_MakePoint(0,0), ST_MakePoint(5,5)) AS is_contained;
+
+ is_contained
+--------------
+ 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="contains_box2df_box2df" />,
+ <xref linkend="is_contained_geometry_box2df" />,
+ <xref linkend="is_contained_box2df_geometry" /></para>
+ </refsection>
+ </refentry>
+
<refentry id="ST_Geometry_Overabove">
<refnamediv>
<refname>|&></refname>
@@ -992,6 +1574,204 @@
</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>
Modified: trunk/doc/using_postgis_dataman.xml
===================================================================
--- trunk/doc/using_postgis_dataman.xml 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/doc/using_postgis_dataman.xml 2016-07-31 03:46:40 UTC (rev 15028)
@@ -2178,6 +2178,72 @@
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>&&</varname>, <varname>~</varname> and
+ <varname>@</varname> operators can be used for the 2D cases (both for
+ "geometry" and for "geography"), and just the <varname>&&&</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>
Modified: trunk/libpgcommon/gserialized_gist.c
===================================================================
--- trunk/libpgcommon/gserialized_gist.c 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/libpgcommon/gserialized_gist.c 2016-07-31 03:46:40 UTC (rev 15028)
@@ -374,6 +374,7 @@
{
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;
Modified: trunk/libpgcommon/gserialized_gist.h
===================================================================
--- trunk/libpgcommon/gserialized_gist.h 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/libpgcommon/gserialized_gist.h 2016-07-31 03:46:40 UTC (rev 15028)
@@ -24,6 +24,7 @@
** 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 @@
/* Remove the box from a disk serialization */
GSERIALIZED* gserialized_drop_gidx(GSERIALIZED *g);
+int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df);
Modified: trunk/postgis/Makefile.in
===================================================================
--- trunk/postgis/Makefile.in 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/postgis/Makefile.in 2016-07-31 03:46:40 UTC (rev 15028)
@@ -46,6 +46,9 @@
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 @@
gserialized_typmod.o \
gserialized_gist_2d.o \
gserialized_gist_nd.o \
+ $(BRIN_OBJ) \
gserialized_estimate.o \
geography_inout.o \
geography_btree.o \
Modified: trunk/postgis/geography.sql.in
===================================================================
--- trunk/postgis/geography.sql.in 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/postgis/geography.sql.in 2016-07-31 03:46:40 UTC (rev 15028)
@@ -286,7 +286,94 @@
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
-- For sorting and grouping
Modified: trunk/postgis/gserialized_gist_2d.c
===================================================================
--- trunk/postgis/gserialized_gist_2d.c 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/postgis/gserialized_gist_2d.c 2016-07-31 03:46:40 UTC (rev 15028)
@@ -116,6 +116,15 @@
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 @@
* 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,10 +630,86 @@
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
*/
Modified: trunk/postgis/gserialized_gist_nd.c
===================================================================
--- trunk/postgis/gserialized_gist_nd.c 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/postgis/gserialized_gist_nd.c 2016-07-31 03:46:40 UTC (rev 15028)
@@ -100,8 +100,20 @@
*/
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 @@
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,7 +861,37 @@
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,7 +906,57 @@
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 @@
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
*/
Modified: trunk/postgis/postgis.sql.in
===================================================================
--- trunk/postgis/postgis.sql.in 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/postgis/postgis.sql.in 2016-07-31 03:46:40 UTC (rev 15028)
@@ -746,7 +746,6 @@
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,11 +5545,301 @@
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
---------------------------------------------------------------
Modified: trunk/regress/Makefile.in
===================================================================
--- trunk/regress/Makefile.in 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/regress/Makefile.in 2016-07-31 03:46:40 UTC (rev 15028)
@@ -23,6 +23,7 @@
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 @@
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 += \
Modified: trunk/utils/postgis_proc_upgrade.pl
===================================================================
--- trunk/utils/postgis_proc_upgrade.pl 2016-07-30 17:39:39 UTC (rev 15027)
+++ trunk/utils/postgis_proc_upgrade.pl 2016-07-31 03:46:40 UTC (rev 15028)
@@ -390,6 +390,37 @@
}
}
+ # 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 )
{
More information about the postgis-tickets
mailing list