]> granicus.if.org Git - postgis/commitdiff
preliminary work on x3d export. Still a lot to go. point, multipoint, tin, linestri...
authorRegina Obe <lr@pcorp.us>
Fri, 11 Mar 2011 21:12:35 +0000 (21:12 +0000)
committerRegina Obe <lr@pcorp.us>
Fri, 11 Mar 2011 21:12:35 +0000 (21:12 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@6897 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/Makefile.in
liblwgeom/lwout_x3d.c [new file with mode: 0644]
postgis/lwgeom_export.c
postgis/postgis.sql.in.c

index b3a39d5d87ed114bc3d213199cc724abc49dde88..bb10d47de74ca45f4b6a853634b4974a5b66ab07 100644 (file)
@@ -66,7 +66,8 @@ SA_OBJS = \
        lwout_gml.o \
        lwout_kml.o \
        lwout_geojson.o \
-       lwout_svg.o 
+       lwout_svg.o \
+       lwout_x3d.o
 
 NM_OBJS = \
        lwspheroid.o 
diff --git a/liblwgeom/lwout_x3d.c b/liblwgeom/lwout_x3d.c
new file mode 100644 (file)
index 0000000..c495a1f
--- /dev/null
@@ -0,0 +1,804 @@
+/**********************************************************************\r
+ * $Id: lwout_x3d.c 6850 2011-02-22 14:25:15Z strk $\r
+ *\r
+ * PostGIS - Spatial Types for PostgreSQL\r
+ * http://www.postgis.org\r
+ * adapted from lwout_asgml.c\r
+ * Copyright 2011 Arrival 3D \r
+ *                             Regina Obe with input from Dave Arendash\r
+ *\r
+ * This is free software; you can redistribute and/or modify it under\r
+ * the terms of the GNU General Public Licence. See the COPYING file.\r
+ *\r
+ **********************************************************************/\r
+\r
+/**\r
+* @file X3D output routines.\r
+*\r
+**********************************************************************/\r
+\r
+\r
+#include <string.h>\r
+#include <math.h> /* fabs */\r
+#include "liblwgeom_internal.h"\r
+/** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/\r
+static size_t asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);\r
+static size_t asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid);\r
+static size_t asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_poly(const LWPOLY *poly, char *srs, int precision, int opts, int is_patch, const char *defid);\r
+static size_t asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);\r
+static size_t asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid);\r
+static size_t asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);\r
+static char *asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);\r
+static size_t pointArray_toX3D3(POINTARRAY *pa, char *buf, int precision, int opts);\r
+\r
+static size_t pointArray_X3Dsize(POINTARRAY *pa, int precision);\r
+\r
+\r
+/*\r
+ * VERSION X3D 3.0.2 http://www.web3d.org/specifications/x3d-3.0.dtd\r
+ */\r
+\r
+\r
+/* takes a GEOMETRY and returns an X3D representation */\r
+extern char *\r
+lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int type = geom->type;\r
+\r
+       switch (type)\r
+       {\r
+       case POINTTYPE:\r
+               return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid);\r
+\r
+       case LINETYPE:\r
+               return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid);\r
+\r
+       case POLYGONTYPE:\r
+               return asx3d3_poly((LWPOLY*)geom, srs, precision, opts, 0, defid);\r
+\r
+       case TRIANGLETYPE:\r
+               return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid);\r
+\r
+       case MULTIPOINTTYPE:\r
+       case MULTILINETYPE:\r
+       case MULTIPOLYGONTYPE:\r
+               return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid);\r
+\r
+       case POLYHEDRALSURFACETYPE:\r
+               return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid);\r
+\r
+       case TINTYPE:\r
+               return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid);\r
+\r
+       case COLLECTIONTYPE:\r
+               return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid);\r
+\r
+       default:\r
+               lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type));\r
+               return NULL;\r
+       }\r
+}\r
+\r
+static size_t\r
+asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int size;\r
+       //size_t defidlen = strlen(defid);\r
+\r
+       size = pointArray_X3Dsize(point->point, precision);\r
+       //size += ( sizeof("<point><pos>/") + (defidlen*2) ) * 2;\r
+       //if (srs)     size += strlen(srs) + sizeof(" srsName=..");\r
+       return size;\r
+}\r
+\r
+static size_t\r
+asx3d3_point_buf(const LWPOINT *point, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       char *ptr = output;\r
+       //int dimension=2;\r
+\r
+       //if (FLAGS_GET_Z(point->flags)) dimension = 3;\r
+/*     if ( srs )\r
+       {\r
+               ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", defid, srs);\r
+       }\r
+       else*/\r
+       //ptr += sprintf(ptr, "%s", defid);\r
+       \r
+       //ptr += sprintf(ptr, "<%spos>", defid);\r
+       ptr += pointArray_toX3D3(point->point, ptr, precision, opts);\r
+       //ptr += sprintf(ptr, "</%spos></%sPoint>", defid, defid);\r
+\r
+       return (ptr-output);\r
+}\r
+\r
+static char *\r
+asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *output;\r
+       int size;\r
+\r
+       size = asx3d3_point_size(point, srs, precision, opts, defid);\r
+       output = lwalloc(size);\r
+       asx3d3_point_buf(point, srs, output, precision, opts, defid);\r
+       return output;\r
+}\r
+\r
+\r
+static size_t\r
+asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int size;\r
+       size_t defidlen = strlen(defid);\r
+\r
+       size = pointArray_X3Dsize(line->points, precision)*2;\r
+\r
+       size += (\r
+               sizeof("<LineSet vertexCount=''><Coordinate point='' /></LineSet>")  + defidlen  \r
+       ) * 2;\r
+       \r
+       //if (srs)     size += strlen(srs) + sizeof(" srsName=..");\r
+       return size;\r
+}\r
+\r
+static size_t\r
+asx3d3_line_buf(const LWLINE *line, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       char *ptr=output;\r
+       //int dimension=2;\r
+       POINTARRAY *pa;\r
+\r
+\r
+       //if (FLAGS_GET_Z(line->flags)) dimension = 3;\r
+\r
+       pa = line->points;\r
+       ptr += sprintf(ptr, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);\r
+\r
+\r
+       ptr += sprintf(ptr, "<Coordinate point='");\r
+       ptr += pointArray_toX3D3(line->points, ptr, precision, opts);\r
+\r
+       ptr += sprintf(ptr, "' />");\r
+\r
+       ptr += sprintf(ptr, "</LineSet>");\r
+       return (ptr-output);\r
+}\r
+\r
+static size_t\r
+asx3d3_line_coords(const LWLINE *line, char *output, int precision, int opts)\r
+{\r
+       char *ptr=output;\r
+       //int dimension=2;\r
+       POINTARRAY *pa;\r
+       pa = line->points;\r
+       ptr += pointArray_toX3D3(line->points, ptr, precision, opts);\r
+       return (ptr-output);\r
+}\r
+\r
+static char *\r
+asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *output;\r
+       int size;\r
+\r
+       size = asx3d3_line_size(line, srs, precision, opts, defid);\r
+       output = lwalloc(size);\r
+       asx3d3_line_buf(line, srs, output, precision, opts, defid);\r
+       return output;\r
+}\r
+\r
+\r
+static size_t\r
+asx3d3_poly_size(const LWPOLY *poly,  char *srs, int precision, int opts, const char *defid)\r
+{\r
+       size_t size;\r
+       size_t defidlen = strlen(defid);\r
+       int i;\r
+\r
+       size = ( sizeof("<PolygonPatch><exterior><LinearRing>///") + (defidlen*3) ) * 2;\r
+       size += ( sizeof("<interior><LinearRing>//") + (defidlen*2) ) * 2 * (poly->nrings - 1);\r
+       size += ( sizeof("<posList></posList>") + (defidlen*2) ) * poly->nrings;\r
+       //if (srs)     size += strlen(srs) + sizeof(" srsName=..");\r
+       //if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'") * poly->nrings;\r
+\r
+       for (i=0; i<poly->nrings; i++)\r
+               size += pointArray_X3Dsize(poly->rings[i], precision);\r
+\r
+       return size;\r
+}\r
+\r
+static size_t\r
+asx3d3_poly_buf(const LWPOLY *poly, char *srs, char *output, int precision, int opts, int is_patch, const char *defid)\r
+{\r
+       int i;\r
+       char *ptr=output;\r
+       int dimension=2;\r
+\r
+       if (FLAGS_GET_Z(poly->flags)) dimension = 3;\r
+       if (is_patch)\r
+       {\r
+               if (srs) ptr += sprintf(ptr, "<%sPolygonPatch srsName=\"%s\">", defid, srs);\r
+               else     ptr += sprintf(ptr, "<%sPolygonPatch>", defid);\r
+       }\r
+       else\r
+       {\r
+               if (srs) ptr += sprintf(ptr, "<%sPolygon srsName=\"%s\">", defid, srs);\r
+               else     ptr += sprintf(ptr, "<%sPolygon>", defid);\r
+       }\r
+\r
+       ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", defid, defid);\r
+       if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", defid, dimension);\r
+       else         ptr += sprintf(ptr, "<%sposList>", defid);\r
+\r
+       ptr += pointArray_toX3D3(poly->rings[0], ptr, precision, opts);\r
+       ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sexterior>",\r
+                      defid, defid, defid);\r
+       for (i=1; i<poly->nrings; i++)\r
+       {\r
+               ptr += sprintf(ptr, "<%sinterior><%sLinearRing>", defid, defid);\r
+               if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", defid, dimension);\r
+               else         ptr += sprintf(ptr, "<%sposList>", defid);\r
+               ptr += pointArray_toX3D3(poly->rings[i], ptr, precision, opts);\r
+               ptr += sprintf(ptr, "</%sposList></%sLinearRing></%sinterior>",\r
+                              defid, defid, defid);\r
+       }\r
+       if (is_patch) ptr += sprintf(ptr, "</%sPolygonPatch>", defid);\r
+       else ptr += sprintf(ptr, "</%sPolygon>", defid);\r
+\r
+       return (ptr-output);\r
+}\r
+\r
+static char *\r
+asx3d3_poly(const LWPOLY *poly, char *srs, int precision, int opts, int is_patch, const char *defid)\r
+{\r
+       char *output;\r
+       int size;\r
+\r
+       size = asx3d3_poly_size(poly, srs, precision, opts, defid);\r
+       output = lwalloc(size);\r
+       asx3d3_poly_buf(poly, srs, output, precision, opts, is_patch, defid);\r
+       return output;\r
+}\r
+\r
+\r
+static size_t\r
+asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       size_t size;\r
+       size_t defidlen = strlen(defid);\r
+\r
+       /** 6 for the 3 sides and space to separate each side **/ \r
+       size = sizeof("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + 6; \r
+       //size +=   sizeof("<posList></posList>") + (defidlen*2);\r
+       //if (srs)     size += strlen(srs) + sizeof(" srsName=..");\r
+       //if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'");\r
+\r
+       size += pointArray_X3Dsize(triangle->points, precision);\r
+\r
+       return size;\r
+}\r
+\r
+static size_t\r
+asx3d3_triangle_buf(const LWTRIANGLE *triangle, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       char *ptr=output;\r
+\r
+       ptr += pointArray_toX3D3(triangle->points, ptr, precision, opts);\r
+\r
+       return (ptr-output);\r
+}\r
+\r
+static char *\r
+asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *output;\r
+       int size;\r
+\r
+       size = asx3d3_triangle_size(triangle, srs, precision, opts, defid);\r
+       output = lwalloc(size);\r
+       asx3d3_triangle_buf(triangle, srs, output, precision, opts, defid);\r
+       return output;\r
+}\r
+\r
+\r
+/*\r
+ * Compute max size required for X3D version of this\r
+ * inspected geometry. Will recurse when needed.\r
+ * Don't call this with single-geoms inspected.\r
+ */\r
+static size_t\r
+asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int i;\r
+       size_t size;\r
+       size_t defidlen = strlen(defid);\r
+       LWGEOM *subgeom;\r
+\r
+       /* the longest possible multi version needs to hold DEF=defid and coordinate breakout */\r
+       size = sizeof("<PointSet><Coordinate point='' /></PointSet>") + defidlen;\r
+\r
+       //if ( srs ) size += strlen(srs) + sizeof(" srsName=..");\r
+\r
+       for (i=0; i<col->ngeoms; i++)\r
+       {\r
+               subgeom = col->geoms[i];\r
+               if (subgeom->type == POINTTYPE)\r
+               {\r
+                       //size += ( sizeof("point=''") + defidlen ) * 2;\r
+                       size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);\r
+               }\r
+               else if (subgeom->type == LINETYPE)\r
+               {\r
+                       size += ( sizeof("<curveMember>/") + defidlen ) * 2;\r
+                       size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);\r
+               }\r
+               else if (subgeom->type == POLYGONTYPE)\r
+               {\r
+                       size += ( sizeof("<surfaceMember>/") + defidlen ) * 2;\r
+                       size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);\r
+               }\r
+       }\r
+\r
+       return size;\r
+}\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static size_t\r
+asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       int type = col->type;\r
+       char *ptr, *x3dtype, *coordIndex;\r
+       int i, size;\r
+       //int numvertices;\r
+       LWGEOM *subgeom;\r
+       POINTARRAY *pa;\r
+\r
+       ptr = output;\r
+       x3dtype="";\r
+       //numvertices = lwcollection_count_vertices(col)*col->ngeoms*20;\r
+       size = 1000;\r
+       coordIndex = lwalloc(size);\r
+\r
+       for (i=0; i<col->ngeoms; i++){\r
+                       coordIndex += sprintf(coordIndex, "-1 ");\r
+       }\r
+                       \r
+       if      (type == MULTIPOINTTYPE) {\r
+               x3dtype = "PointSet";\r
+               ptr += sprintf(ptr, "<%s %s>", x3dtype, defid);\r
+       }\r
+       else if (type == MULTILINETYPE) {\r
+               x3dtype = "IndexedLineSet";\r
+               ptr += sprintf(ptr, "<%s %s coordIndex='%s'", x3dtype, defid, coordIndex);\r
+       }\r
+       else if (type == MULTIPOLYGONTYPE) {\r
+               x3dtype = "IndexedFaceSet";\r
+               ptr += sprintf(ptr, "<%s %s coordIndex='%s'", x3dtype, defid, coordIndex);\r
+       }\r
+\r
+       \r
+       /* Open outmost tag */\r
+/*     if ( srs )\r
+       {\r
+               ptr += sprintf(ptr, "<%s%s srsName=\"%s\">", defid, x3dtype, srs);\r
+       }\r
+       else*/\r
+\r
+       ptr += sprintf(ptr, "<%s>%s <Coordinate point='", x3dtype, defid);\r
+\r
+       for (i=0; i<col->ngeoms; i++)\r
+       {\r
+               subgeom = col->geoms[i];\r
+               if (subgeom->type == POINTTYPE)\r
+               {\r
+                       //ptr += sprintf(ptr, " ");\r
+                       ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);\r
+                       ptr += sprintf(ptr, " ");\r
+               }\r
+               else if (subgeom->type == LINETYPE)\r
+               {\r
+                       for (i=0; i<col->ngeoms; i++)\r
+                       ptr += asx3d3_line_coords((LWLINE*)subgeom, ptr, precision, opts);\r
+                       ptr += sprintf(ptr, " ");\r
+               }\r
+               else if (subgeom->type == POLYGONTYPE)\r
+               {\r
+                       ptr += sprintf(ptr, "<%ssurfaceMember>", defid);\r
+                       ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);\r
+                       ptr += sprintf(ptr, "</%ssurfaceMember>", defid);\r
+               }\r
+       }\r
+\r
+       /* Close outmost tag */\r
+       ptr += sprintf(ptr, "' /></%s>", x3dtype);\r
+\r
+       return (ptr-output);\r
+}\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static char *\r
+asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *x3d;\r
+       size_t size;\r
+\r
+       size = asx3d3_multi_size(col, srs, precision, opts, defid);\r
+       x3d = lwalloc(size);\r
+       asx3d3_multi_buf(col, srs, x3d, precision, opts, defid);\r
+       return x3d;\r
+}\r
+\r
+\r
+static size_t\r
+asx3d3_psurface_size(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int i;\r
+       size_t size;\r
+       size_t defidlen = strlen(defid);\r
+\r
+       size = sizeof("<IndexedFaceSet coordIndex=''><Coordinate point='' />") + defidlen;\r
+       //if ( srs ) size += strlen(srs) + sizeof(" srsName=..");\r
+\r
+       for (i=0; i<psur->ngeoms; i++)\r
+       {\r
+               size += asx3d3_poly_size(psur->geoms[i], 0, precision, opts, defid)*5; /** need to make spacked for coordIndex values too including -1 separating each poly**/\r
+       }\r
+\r
+       return size;\r
+}\r
+\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static size_t\r
+asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       char *ptr;\r
+       int i;\r
+       int j;\r
+       int k;\r
+       int np;\r
+       LWPOLY *patch;\r
+\r
+       ptr = output;\r
+\r
+       /* Open outmost tag */\r
+       ptr += sprintf(ptr, "<IndexedFaceSet %s coordIndex='",defid);\r
+       \r
+       j = 0;\r
+       for (i=0; i<psur->ngeoms; i++)\r
+       {\r
+               patch = (LWPOLY *) psur->geoms[i];\r
+               np = patch->rings[0]->npoints - 1;\r
+           for(k=0; k < np ; k++){\r
+               if (k) {\r
+                   ptr += sprintf(ptr, " ");    \r
+               }\r
+               ptr += sprintf(ptr, "%d", (j + k));\r
+           }\r
+           if (i < (psur->ngeoms - 1) ){\r
+               ptr += sprintf(ptr, "-1 "); //separator for each subgeom\r
+           }\r
+           j += k;\r
+       }\r
+       \r
+       ptr += sprintf(ptr, "'><Coordinate point='");\r
+\r
+       for (i=0; i<psur->ngeoms; i++)\r
+       {\r
+               ptr += asx3d3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, defid);\r
+       }\r
+\r
+       /* Close outmost tag */\r
+       ptr += sprintf(ptr, "' /></IndexedFaceSet>");\r
+\r
+       return (ptr-output);\r
+}\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static char *\r
+asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *x3d;\r
+       size_t size;\r
+\r
+       size = asx3d3_psurface_size(psur, srs, precision, opts, defid);\r
+       x3d = lwalloc(size);\r
+       asx3d3_psurface_buf(psur, srs, x3d, precision, opts, defid);\r
+       return x3d;\r
+}\r
+\r
+\r
+static size_t\r
+asx3d3_tin_size(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int i;\r
+       size_t size;\r
+       size_t defidlen = strlen(defid);\r
+       //int dimension=2;\r
+\r
+       //if (FLAGS_GET_Z(tin->flags)) dimension = 3;\r
+       /** Need to make space for size of additional attributes, \r
+       ** the coordIndex has a value for each edge for each triangle plus apace to separate so we need at least that much extra room ***/\r
+       size = sizeof("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + tin->ngeoms*12;\r
+\r
+       //if ( srs ) size += strlen(srs) + sizeof(" srsName=..");\r
+\r
+       for (i=0; i<tin->ngeoms; i++)\r
+       {\r
+               size += (asx3d3_triangle_size(tin->geoms[i], 0, precision, opts, defid) * 20); /** 3 is to make space for coordIndex **/\r
+       }\r
+\r
+       return size;\r
+}\r
+\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static size_t\r
+asx3d3_tin_buf(const LWTIN *tin, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       char *ptr;\r
+       int i;\r
+       int k;\r
+       //int dimension=2;\r
+\r
+       ptr = output;\r
+\r
+       /* Open outmost tag */\r
+       //if (srs) ptr += sprintf(ptr, "<%sTin srsName=\"%s\"><%strianglePatches>",\r
+       //                              defid, srs, defid);\r
+       \r
+       //if (FLAGS_GET_Z(tin->flags)) dimension = 3;\r
+\r
+       ptr += sprintf(ptr, "<IndexedTriangleSet %s coordIndex='",defid);\r
+       k = 0;\r
+       /** Fill in coordIndex **/\r
+       for (i=0; i<tin->ngeoms; i++)\r
+       {\r
+               ptr += sprintf(ptr, "%d %d %d", k, (k+1), (k+2));\r
+               if (i < (tin->ngeoms - 1) ){\r
+                   ptr += sprintf(ptr, " ");\r
+               }\r
+               k += 3;\r
+       }\r
+       \r
+       ptr += sprintf(ptr, "'><Coordinate point='");\r
+       /** TODO: I think we need to exclude the closing point **/\r
+       for (i=0; i<tin->ngeoms; i++)\r
+       {\r
+               ptr += asx3d3_triangle_buf(tin->geoms[i], 0, ptr, precision,\r
+                                          opts, defid);\r
+       }\r
+\r
+       /* Close outmost tag */\r
+\r
+       ptr += sprintf(ptr, "'/></IndexedTriangleSet>");\r
+       \r
+       return (ptr-output);\r
+}\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static char *\r
+asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *x3d;\r
+       size_t size;\r
+\r
+       size = asx3d3_tin_size(tin, srs, precision, opts, defid);\r
+       x3d = lwalloc(size);\r
+       asx3d3_tin_buf(tin, srs, x3d, precision, opts, defid);\r
+       return x3d;\r
+}\r
+\r
+static size_t\r
+asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       int i;\r
+       size_t size;\r
+       size_t defidlen = strlen(defid);\r
+       LWGEOM *subgeom;\r
+\r
+       size = sizeof("<MultiGeometry></MultiGeometry>") + defidlen*2;\r
+\r
+       if ( srs ) size += strlen(srs) + sizeof(" srsName=..");\r
+\r
+       for (i=0; i<col->ngeoms; i++)\r
+       {\r
+               subgeom = col->geoms[i];\r
+               size += ( sizeof("<geometryMember>/") + defidlen ) * 2;\r
+               if ( subgeom->type == POINTTYPE )\r
+               {\r
+                       size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);\r
+               }\r
+               else if ( subgeom->type == LINETYPE )\r
+               {\r
+                       size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);\r
+               }\r
+               else if ( subgeom->type == POLYGONTYPE )\r
+               {\r
+                       size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);\r
+               }\r
+               else if ( lwgeom_is_collection(subgeom) )\r
+               {\r
+                       size += asx3d3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, defid);\r
+               }\r
+               else\r
+                       lwerror("asx3d3_collection_size: unknown geometry type");\r
+       }\r
+\r
+       return size;\r
+}\r
+\r
+static size_t\r
+asx3d3_collection_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)\r
+{\r
+       char *ptr;\r
+       int i;\r
+       LWGEOM *subgeom;\r
+\r
+       ptr = output;\r
+\r
+       /* Open outmost tag */\r
+       if ( srs )\r
+       {\r
+               ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", defid, srs);\r
+       }\r
+       else\r
+       {\r
+               ptr += sprintf(ptr, "<%sMultiGeometry>", defid);\r
+       }\r
+\r
+       for (i=0; i<col->ngeoms; i++)\r
+       {\r
+               subgeom = col->geoms[i];\r
+               ptr += sprintf(ptr, "<%sgeometryMember>", defid);\r
+               if ( subgeom->type == POINTTYPE )\r
+               {\r
+                       ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);\r
+               }\r
+               else if ( subgeom->type == LINETYPE )\r
+               {\r
+                       ptr += asx3d3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, defid);\r
+               }\r
+               else if ( subgeom->type == POLYGONTYPE )\r
+               {\r
+                       ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);\r
+               }\r
+               else if ( lwgeom_is_collection(subgeom) )\r
+               {\r
+                       if ( subgeom->type == COLLECTIONTYPE )\r
+                               ptr += asx3d3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);\r
+                       else\r
+                               ptr += asx3d3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);\r
+               }\r
+               else \r
+                       lwerror("asx3d3_collection_buf: unknown geometry type");\r
+                       \r
+               ptr += sprintf(ptr, "</%sgeometryMember>", defid);\r
+       }\r
+\r
+       /* Close outmost tag */\r
+       ptr += sprintf(ptr, "</%sMultiGeometry>", defid);\r
+\r
+       return (ptr-output);\r
+}\r
+\r
+/*\r
+ * Don't call this with single-geoms inspected!\r
+ */\r
+static char *\r
+asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)\r
+{\r
+       char *x3d;\r
+       size_t size;\r
+\r
+       size = asx3d3_collection_size(col, srs, precision, opts, defid);\r
+       x3d = lwalloc(size);\r
+       asx3d3_collection_buf(col, srs, x3d, precision, opts, defid);\r
+       return x3d;\r
+}\r
+\r
+\r
+/* In X3D3, inside <posList> or <pos>, coordinates are separated by a space separator\r
+ * In X3D3 also, lat/lon are reversed for geocentric data\r
+ */\r
+static size_t\r
+pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts)\r
+{\r
+       int i;\r
+       char *ptr;\r
+       char x[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];\r
+       char y[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];\r
+       char z[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];\r
+\r
+       ptr = output;\r
+\r
+       if ( ! FLAGS_GET_Z(pa->flags) )\r
+       {\r
+               for (i=0; i<pa->npoints; i++)\r
+               {\r
+                       POINT2D pt;\r
+                       getPoint2d_p(pa, i, &pt);\r
+\r
+                       if (fabs(pt.x) < OUT_MAX_DOUBLE)\r
+                               sprintf(x, "%.*f", precision, pt.x);\r
+                       else\r
+                               sprintf(x, "%g", pt.x);\r
+                       trim_trailing_zeros(x);\r
+\r
+                       if (fabs(pt.y) < OUT_MAX_DOUBLE)\r
+                               sprintf(y, "%.*f", precision, pt.y);\r
+                       else\r
+                               sprintf(y, "%g", pt.y);\r
+                       trim_trailing_zeros(y);\r
+\r
+                       if ( i ) ptr += sprintf(ptr, " ");\r
+                       ptr += sprintf(ptr, "%s %s", x, y);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               for (i=0; i<pa->npoints; i++)\r
+               {\r
+                       POINT4D pt;\r
+                       getPoint4d_p(pa, i, &pt);\r
+\r
+                       if (fabs(pt.x) < OUT_MAX_DOUBLE)\r
+                               sprintf(x, "%.*f", precision, pt.x);\r
+                       else\r
+                               sprintf(x, "%g", pt.x);\r
+                       trim_trailing_zeros(x);\r
+\r
+                       if (fabs(pt.y) < OUT_MAX_DOUBLE)\r
+                               sprintf(y, "%.*f", precision, pt.y);\r
+                       else\r
+                               sprintf(y, "%g", pt.y);\r
+                       trim_trailing_zeros(y);\r
+\r
+                       if (fabs(pt.z) < OUT_MAX_DOUBLE)\r
+                               sprintf(z, "%.*f", precision, pt.z);\r
+                       else\r
+                               sprintf(z, "%g", pt.z);\r
+                       trim_trailing_zeros(z);\r
+\r
+                       if ( i ) ptr += sprintf(ptr, " ");\r
+                       \r
+                       ptr += sprintf(ptr, "%s %s %s", x, y, z);\r
+               }\r
+       }\r
+\r
+       return ptr-output;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * Returns maximum size of rendered pointarray in bytes.\r
+ */\r
+static size_t\r
+pointArray_X3Dsize(POINTARRAY *pa, int precision)\r
+{\r
+       if (FLAGS_NDIMS(pa->flags) == 2)\r
+               return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" "))\r
+                      * 2 * pa->npoints;\r
+\r
+       return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" ")) * 3 * pa->npoints;\r
+}\r
index 8e63b6896d136c76456820665b90bdcb7d5ca25a..baf948589ed267a774112ab8f10a891b2cb9b1c5 100644 (file)
-/**********************************************************************
- * $Id:$
- *
- * PostGIS - Export functions for PostgreSQL/PostGIS
- * Copyright 2009-2010 Olivier Courtin <olivier.courtin@oslandia.com>
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of the GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************/
-
-
-/** @file
- *  Commons functions for all export functions
- */
-
-#include "postgres.h"
-#include "executor/spi.h"
-
-#include "lwgeom_pg.h"
-#include "liblwgeom.h"
-#include "lwgeom_export.h"
-
-Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
-Datum LWGEOM_asKML(PG_FUNCTION_ARGS);
-Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS);
-Datum LWGEOM_asSVG(PG_FUNCTION_ARGS);
-
-
-/*
- * Retrieve an SRS from a given SRID
- * Require valid spatial_ref_sys table entry
- *
- * Could return SRS as short one (i.e EPSG:4326)
- * or as long one: (i.e urn:ogc:def:crs:EPSG::4326)
- */
-char * getSRSbySRID(int srid, bool short_crs)
-{
-       char query[256];
-       char *srs, *srscopy;
-       int size, err;
-
-       if (SPI_OK_CONNECT != SPI_connect ())
-       {
-               elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");
-               SPI_finish();
-               return NULL;
-       }
-
-       if (short_crs)
-               sprintf(query, "SELECT auth_name||':'||auth_srid \
-                       FROM spatial_ref_sys WHERE srid='%d'", srid);
-       else
-               sprintf(query, "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \
-                       FROM spatial_ref_sys WHERE srid='%d'", srid);
-
-       err = SPI_exec(query, 1);
-       if ( err < 0 )
-       {
-               elog(NOTICE, "getSRSbySRID: error executing query %d", err);
-               SPI_finish();
-               return NULL;
-       }
-
-       /* no entry in spatial_ref_sys */
-       if (SPI_processed <= 0)
-       {
-               SPI_finish();
-               return NULL;
-       }
-
-       /* get result  */
-       srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
-
-       /* NULL result */
-       if ( ! srs )
-       {
-               SPI_finish();
-               return NULL;
-       }
-
-       /* copy result to upper executor context */
-       size = strlen(srs)+1;
-       srscopy = SPI_palloc(size);
-       memcpy(srscopy, srs, size);
-
-       /* disconnect from SPI */
-       SPI_finish();
-
-       return srscopy;
-}
-
-
-/**
- * Encode feature in GML
- */
-PG_FUNCTION_INFO_V1(LWGEOM_asGML);
-Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
-{
-       PG_LWGEOM *geom;
-       LWGEOM *lwgeom;
-       char *gml;
-       text *result;
-       int version;
-       char *srs;
-       int srid;
-       int option = 0;
-       int lwopts = LW_GML_IS_DIMS;
-       int precision = OUT_MAX_DOUBLE_PRECISION;
-       static const char* default_prefix = "gml:"; /* default prefix */
-       char *prefixbuf;
-       const char* prefix = default_prefix;
-       text *prefix_text;
-
-       /* Get the version */
-       version = PG_GETARG_INT32(0);
-       if ( version != 2 && version != 3 )
-       {
-               elog(ERROR, "Only GML 2 and GML 3 are supported");
-               PG_RETURN_NULL();
-       }
-
-       /* Get the geometry */
-       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       /* Retrieve precision if any (default is max) */
-       if (PG_NARGS() >2 && !PG_ARGISNULL(2))
-       {
-               precision = PG_GETARG_INT32(2);
-               if ( precision > OUT_MAX_DOUBLE_PRECISION )
-                       precision = OUT_MAX_DOUBLE_PRECISION;
-               else if ( precision < 0 ) precision = 0;
-       }
-
-       /* retrieve option */
-       if (PG_NARGS() >3 && !PG_ARGISNULL(3))
-               option = PG_GETARG_INT32(3);
-
-       /* retrieve prefix */
-       if (PG_NARGS() >4 && !PG_ARGISNULL(4))
-       {
-               prefix_text = PG_GETARG_TEXT_P(4);
-               if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
-               {
-                       prefix = "";
-               }
-               else
-               {
-                       /* +2 is one for the ':' and one for term null */
-                       prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
-                       memcpy(prefixbuf, VARDATA(prefix_text),
-                              VARSIZE(prefix_text)-VARHDRSZ);
-                       /* add colon and null terminate */
-                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
-                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
-                       prefix = prefixbuf;
-               }
-       }
-
-       srid = pglwgeom_get_srid(geom);
-       if (srid == SRID_UNKNOWN)      srs = NULL;
-       else if (option & 1) srs = getSRSbySRID(srid, false);
-       else                 srs = getSRSbySRID(srid, true);
-
-       if (option & 2)  lwopts &= ~LW_GML_IS_DIMS; 
-       if (option & 4)  lwopts |= LW_GML_SHORTLINE;
-       if (option & 16) lwopts |= LW_GML_IS_DEGREE;
-
-       lwgeom = pglwgeom_deserialize(geom);
-
-       if (version == 2)
-               gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
-       else
-               gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix);
-
-       lwgeom_free(lwgeom);
-       PG_FREE_IF_COPY(geom, 1);
-
-       result = cstring2text(gml);
-       lwfree(gml);
-
-       PG_RETURN_TEXT_P(result);
-}
-
-
-/**
- * Encode feature in KML
- */
-PG_FUNCTION_INFO_V1(LWGEOM_asKML);
-Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
-{
-       PG_LWGEOM *geom;
-       LWGEOM *lwgeom;
-       char *kml;
-       text *result;
-       int version;
-       int precision = OUT_MAX_DOUBLE_PRECISION;
-       static const char* default_prefix = ""; /* default prefix */
-       char *prefixbuf;
-       const char* prefix = default_prefix;
-       text *prefix_text;
-
-
-       /* Get the version */
-       version = PG_GETARG_INT32(0);
-       if ( version != 2)
-       {
-               elog(ERROR, "Only KML 2 is supported");
-               PG_RETURN_NULL();
-       }
-
-       /* Get the geometry */
-       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       /* Retrieve precision if any (default is max) */
-       if (PG_NARGS() >2 && !PG_ARGISNULL(2))
-       {
-               precision = PG_GETARG_INT32(2);
-               if ( precision > OUT_MAX_DOUBLE_PRECISION )
-                       precision = OUT_MAX_DOUBLE_PRECISION;
-               else if ( precision < 0 ) precision = 0;
-       }
-
-       /* retrieve prefix */
-       if (PG_NARGS() >3 && !PG_ARGISNULL(3))
-       {
-               prefix_text = PG_GETARG_TEXT_P(3);
-               if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )
-               {
-                       prefix = "";
-               }
-               else
-               {
-                       /* +2 is one for the ':' and one for term null */
-                       prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);
-                       memcpy(prefixbuf, VARDATA(prefix_text),
-                              VARSIZE(prefix_text)-VARHDRSZ);
-                       /* add colon and null terminate */
-                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';
-                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';
-                       prefix = prefixbuf;
-               }
-       }
-
-       lwgeom = pglwgeom_deserialize(geom);
-       kml = lwgeom_to_kml2(lwgeom, precision, prefix);
-       lwgeom_free(lwgeom);
-       PG_FREE_IF_COPY(geom, 1);
-       
-       if( ! kml ) 
-               PG_RETURN_NULL();       
-
-       result = cstring2text(kml);
-       lwfree(kml);
-
-       PG_RETURN_POINTER(result);
-}
-
-
-/**
- * Encode Feature in GeoJson
- */
-PG_FUNCTION_INFO_V1(LWGEOM_asGeoJson);
-Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
-{
-       PG_LWGEOM *geom;
-       LWGEOM *lwgeom;
-       char *geojson;
-       text *result;
-       int srid;
-       int version;
-       int option = 0;
-       int has_bbox = 0;
-       int precision = OUT_MAX_DOUBLE_PRECISION;
-       char * srs = NULL;
-
-       /* Get the version */
-       version = PG_GETARG_INT32(0);
-       if ( version != 1)
-       {
-               elog(ERROR, "Only GeoJSON 1 is supported");
-               PG_RETURN_NULL();
-       }
-
-       /* Get the geometry */
-       if (PG_ARGISNULL(1) ) PG_RETURN_NULL();
-       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-       /* Retrieve precision if any (default is max) */
-       if (PG_NARGS() >2 && !PG_ARGISNULL(2))
-       {
-               precision = PG_GETARG_INT32(2);
-               if ( precision > OUT_MAX_DOUBLE_PRECISION )
-                       precision = OUT_MAX_DOUBLE_PRECISION;
-               else if ( precision < 0 ) precision = 0;
-       }
-
-       /* Retrieve output option
-        * 0 = without option (default)
-        * 1 = bbox
-        * 2 = short crs
-        * 4 = long crs
-        */
-       if (PG_NARGS() >3 && !PG_ARGISNULL(3))
-               option = PG_GETARG_INT32(3);
-
-       if (option & 2 || option & 4)
-       {
-               srid = pglwgeom_get_srid(geom);
-               if ( srid != SRID_UNKNOWN )
-               {
-                       if (option & 2) srs = getSRSbySRID(srid, true);
-                       if (option & 4) srs = getSRSbySRID(srid, false);
-                       if (!srs)
-                       {
-                               elog(   ERROR,
-                                     "SRID %i unknown in spatial_ref_sys table",
-                                     srid);
-                               PG_RETURN_NULL();
-                       }
-               }
-       }
-
-       if (option & 1) has_bbox = 1;
-
-       lwgeom = pglwgeom_deserialize(geom);
-       geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);
-       lwgeom_free(lwgeom);
-
-       PG_FREE_IF_COPY(geom, 1);
-       if (srs) pfree(srs);
-
-       result = cstring2text(geojson);
-
-       lwfree(geojson);
-
-       PG_RETURN_TEXT_P(result);
-}
-
-
-/**
- * SVG features
- */
-PG_FUNCTION_INFO_V1(LWGEOM_asSVG);
-Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)
-{
-       PG_LWGEOM *geom;
-       LWGEOM *lwgeom;
-       char *svg;
-       text *result;
-       int relative = 0;
-       int precision=OUT_MAX_DOUBLE_PRECISION;
-
-       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
-
-       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-
-       /* check for relative path notation */
-       if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
-               relative = PG_GETARG_INT32(1) ? 1:0;
-
-       if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
-       {
-               precision = PG_GETARG_INT32(2);
-               if ( precision > OUT_MAX_DOUBLE_PRECISION )
-                       precision = OUT_MAX_DOUBLE_PRECISION;
-               else if ( precision < 0 ) precision = 0;
-       }
-
-       lwgeom = pglwgeom_deserialize(geom);
-       svg = lwgeom_to_svg(lwgeom, precision, relative);
-       result = cstring2text(svg);
-       lwgeom_free(lwgeom);
-       pfree(svg);
-       PG_FREE_IF_COPY(geom, 0);
-
-       PG_RETURN_TEXT_P(result);
-}
+/**********************************************************************\r
+ * $Id:$\r
+ *\r
+ * PostGIS - Export functions for PostgreSQL/PostGIS\r
+ * Copyright 2009-2010 Olivier Courtin <olivier.courtin@oslandia.com>\r
+ *\r
+ * This is free software; you can redistribute and/or modify it under\r
+ * the terms of the GNU General Public Licence. See the COPYING file.\r
+ *\r
+ **********************************************************************/\r
+\r
+\r
+/** @file\r
+ *  Commons functions for all export functions\r
+ */\r
+\r
+#include "postgres.h"\r
+#include "executor/spi.h"\r
+\r
+#include "lwgeom_pg.h"\r
+#include "liblwgeom.h"\r
+#include "lwgeom_export.h"\r
+\r
+Datum LWGEOM_asGML(PG_FUNCTION_ARGS);\r
+Datum LWGEOM_asKML(PG_FUNCTION_ARGS);\r
+Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS);\r
+Datum LWGEOM_asSVG(PG_FUNCTION_ARGS);\r
+Datum LWGEOM_asX3D(PG_FUNCTION_ARGS);\r
+\r
+/*\r
+ * Retrieve an SRS from a given SRID\r
+ * Require valid spatial_ref_sys table entry\r
+ *\r
+ * Could return SRS as short one (i.e EPSG:4326)\r
+ * or as long one: (i.e urn:ogc:def:crs:EPSG::4326)\r
+ */\r
+char * getSRSbySRID(int srid, bool short_crs)\r
+{\r
+       char query[256];\r
+       char *srs, *srscopy;\r
+       int size, err;\r
+\r
+       if (SPI_OK_CONNECT != SPI_connect ())\r
+       {\r
+               elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");\r
+               SPI_finish();\r
+               return NULL;\r
+       }\r
+\r
+       if (short_crs)\r
+               sprintf(query, "SELECT auth_name||':'||auth_srid \\r
+                       FROM spatial_ref_sys WHERE srid='%d'", srid);\r
+       else\r
+               sprintf(query, "SELECT 'urn:ogc:def:crs:'||auth_name||'::'||auth_srid \\r
+                       FROM spatial_ref_sys WHERE srid='%d'", srid);\r
+\r
+       err = SPI_exec(query, 1);\r
+       if ( err < 0 )\r
+       {\r
+               elog(NOTICE, "getSRSbySRID: error executing query %d", err);\r
+               SPI_finish();\r
+               return NULL;\r
+       }\r
+\r
+       /* no entry in spatial_ref_sys */\r
+       if (SPI_processed <= 0)\r
+       {\r
+               SPI_finish();\r
+               return NULL;\r
+       }\r
+\r
+       /* get result  */\r
+       srs = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);\r
+\r
+       /* NULL result */\r
+       if ( ! srs )\r
+       {\r
+               SPI_finish();\r
+               return NULL;\r
+       }\r
+\r
+       /* copy result to upper executor context */\r
+       size = strlen(srs)+1;\r
+       srscopy = SPI_palloc(size);\r
+       memcpy(srscopy, srs, size);\r
+\r
+       /* disconnect from SPI */\r
+       SPI_finish();\r
+\r
+       return srscopy;\r
+}\r
+\r
+\r
+/**\r
+ * Encode feature in GML\r
+ */\r
+PG_FUNCTION_INFO_V1(LWGEOM_asGML);\r
+Datum LWGEOM_asGML(PG_FUNCTION_ARGS)\r
+{\r
+       PG_LWGEOM *geom;\r
+       LWGEOM *lwgeom;\r
+       char *gml;\r
+       text *result;\r
+       int version;\r
+       char *srs;\r
+       int srid;\r
+       int option = 0;\r
+       int lwopts = LW_GML_IS_DIMS;\r
+       int precision = OUT_MAX_DOUBLE_PRECISION;\r
+       static const char* default_prefix = "gml:"; /* default prefix */\r
+       char *prefixbuf;\r
+       const char* prefix = default_prefix;\r
+       text *prefix_text;\r
+\r
+       /* Get the version */\r
+       version = PG_GETARG_INT32(0);\r
+       if ( version != 2 && version != 3 )\r
+       {\r
+               elog(ERROR, "Only GML 2 and GML 3 are supported");\r
+               PG_RETURN_NULL();\r
+       }\r
+\r
+       /* Get the geometry */\r
+       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();\r
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));\r
+\r
+       /* Retrieve precision if any (default is max) */\r
+       if (PG_NARGS() >2 && !PG_ARGISNULL(2))\r
+       {\r
+               precision = PG_GETARG_INT32(2);\r
+               if ( precision > OUT_MAX_DOUBLE_PRECISION )\r
+                       precision = OUT_MAX_DOUBLE_PRECISION;\r
+               else if ( precision < 0 ) precision = 0;\r
+       }\r
+\r
+       /* retrieve option */\r
+       if (PG_NARGS() >3 && !PG_ARGISNULL(3))\r
+               option = PG_GETARG_INT32(3);\r
+\r
+       /* retrieve prefix */\r
+       if (PG_NARGS() >4 && !PG_ARGISNULL(4))\r
+       {\r
+               prefix_text = PG_GETARG_TEXT_P(4);\r
+               if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )\r
+               {\r
+                       prefix = "";\r
+               }\r
+               else\r
+               {\r
+                       /* +2 is one for the ':' and one for term null */\r
+                       prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);\r
+                       memcpy(prefixbuf, VARDATA(prefix_text),\r
+                              VARSIZE(prefix_text)-VARHDRSZ);\r
+                       /* add colon and null terminate */\r
+                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';\r
+                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';\r
+                       prefix = prefixbuf;\r
+               }\r
+       }\r
+\r
+       srid = pglwgeom_get_srid(geom);\r
+       if (srid == SRID_UNKNOWN)      srs = NULL;\r
+       else if (option & 1) srs = getSRSbySRID(srid, false);\r
+       else                 srs = getSRSbySRID(srid, true);\r
+\r
+       if (option & 2)  lwopts &= ~LW_GML_IS_DIMS; \r
+       if (option & 4)  lwopts |= LW_GML_SHORTLINE;\r
+       if (option & 16) lwopts |= LW_GML_IS_DEGREE;\r
+\r
+       lwgeom = pglwgeom_deserialize(geom);\r
+\r
+       if (version == 2)\r
+               gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);\r
+       else\r
+               gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix);\r
+\r
+       lwgeom_free(lwgeom);\r
+       PG_FREE_IF_COPY(geom, 1);\r
+\r
+       result = cstring2text(gml);\r
+       lwfree(gml);\r
+\r
+       PG_RETURN_TEXT_P(result);\r
+}\r
+\r
+\r
+/**\r
+ * Encode feature in KML\r
+ */\r
+PG_FUNCTION_INFO_V1(LWGEOM_asKML);\r
+Datum LWGEOM_asKML(PG_FUNCTION_ARGS)\r
+{\r
+       PG_LWGEOM *geom;\r
+       LWGEOM *lwgeom;\r
+       char *kml;\r
+       text *result;\r
+       int version;\r
+       int precision = OUT_MAX_DOUBLE_PRECISION;\r
+       static const char* default_prefix = ""; /* default prefix */\r
+       char *prefixbuf;\r
+       const char* prefix = default_prefix;\r
+       text *prefix_text;\r
+\r
+\r
+       /* Get the version */\r
+       version = PG_GETARG_INT32(0);\r
+       if ( version != 2)\r
+       {\r
+               elog(ERROR, "Only KML 2 is supported");\r
+               PG_RETURN_NULL();\r
+       }\r
+\r
+       /* Get the geometry */\r
+       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();\r
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));\r
+\r
+       /* Retrieve precision if any (default is max) */\r
+       if (PG_NARGS() >2 && !PG_ARGISNULL(2))\r
+       {\r
+               precision = PG_GETARG_INT32(2);\r
+               if ( precision > OUT_MAX_DOUBLE_PRECISION )\r
+                       precision = OUT_MAX_DOUBLE_PRECISION;\r
+               else if ( precision < 0 ) precision = 0;\r
+       }\r
+\r
+       /* retrieve prefix */\r
+       if (PG_NARGS() >3 && !PG_ARGISNULL(3))\r
+       {\r
+               prefix_text = PG_GETARG_TEXT_P(3);\r
+               if ( VARSIZE(prefix_text)-VARHDRSZ == 0 )\r
+               {\r
+                       prefix = "";\r
+               }\r
+               else\r
+               {\r
+                       /* +2 is one for the ':' and one for term null */\r
+                       prefixbuf = palloc(VARSIZE(prefix_text)-VARHDRSZ+2);\r
+                       memcpy(prefixbuf, VARDATA(prefix_text),\r
+                              VARSIZE(prefix_text)-VARHDRSZ);\r
+                       /* add colon and null terminate */\r
+                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ] = ':';\r
+                       prefixbuf[VARSIZE(prefix_text)-VARHDRSZ+1] = '\0';\r
+                       prefix = prefixbuf;\r
+               }\r
+       }\r
+\r
+       lwgeom = pglwgeom_deserialize(geom);\r
+       kml = lwgeom_to_kml2(lwgeom, precision, prefix);\r
+       lwgeom_free(lwgeom);\r
+       PG_FREE_IF_COPY(geom, 1);\r
+       \r
+       if( ! kml ) \r
+               PG_RETURN_NULL();       \r
+\r
+       result = cstring2text(kml);\r
+       lwfree(kml);\r
+\r
+       PG_RETURN_POINTER(result);\r
+}\r
+\r
+\r
+/**\r
+ * Encode Feature in GeoJson\r
+ */\r
+PG_FUNCTION_INFO_V1(LWGEOM_asGeoJson);\r
+Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)\r
+{\r
+       PG_LWGEOM *geom;\r
+       LWGEOM *lwgeom;\r
+       char *geojson;\r
+       text *result;\r
+       int srid;\r
+       int version;\r
+       int option = 0;\r
+       int has_bbox = 0;\r
+       int precision = OUT_MAX_DOUBLE_PRECISION;\r
+       char * srs = NULL;\r
+\r
+       /* Get the version */\r
+       version = PG_GETARG_INT32(0);\r
+       if ( version != 1)\r
+       {\r
+               elog(ERROR, "Only GeoJSON 1 is supported");\r
+               PG_RETURN_NULL();\r
+       }\r
+\r
+       /* Get the geometry */\r
+       if (PG_ARGISNULL(1) ) PG_RETURN_NULL();\r
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));\r
+\r
+       /* Retrieve precision if any (default is max) */\r
+       if (PG_NARGS() >2 && !PG_ARGISNULL(2))\r
+       {\r
+               precision = PG_GETARG_INT32(2);\r
+               if ( precision > OUT_MAX_DOUBLE_PRECISION )\r
+                       precision = OUT_MAX_DOUBLE_PRECISION;\r
+               else if ( precision < 0 ) precision = 0;\r
+       }\r
+\r
+       /* Retrieve output option\r
+        * 0 = without option (default)\r
+        * 1 = bbox\r
+        * 2 = short crs\r
+        * 4 = long crs\r
+        */\r
+       if (PG_NARGS() >3 && !PG_ARGISNULL(3))\r
+               option = PG_GETARG_INT32(3);\r
+\r
+       if (option & 2 || option & 4)\r
+       {\r
+               srid = pglwgeom_get_srid(geom);\r
+               if ( srid != SRID_UNKNOWN )\r
+               {\r
+                       if (option & 2) srs = getSRSbySRID(srid, true);\r
+                       if (option & 4) srs = getSRSbySRID(srid, false);\r
+                       if (!srs)\r
+                       {\r
+                               elog(   ERROR,\r
+                                     "SRID %i unknown in spatial_ref_sys table",\r
+                                     srid);\r
+                               PG_RETURN_NULL();\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (option & 1) has_bbox = 1;\r
+\r
+       lwgeom = pglwgeom_deserialize(geom);\r
+       geojson = lwgeom_to_geojson(lwgeom, srs, precision, has_bbox);\r
+       lwgeom_free(lwgeom);\r
+\r
+       PG_FREE_IF_COPY(geom, 1);\r
+       if (srs) pfree(srs);\r
+\r
+       result = cstring2text(geojson);\r
+\r
+       lwfree(geojson);\r
+\r
+       PG_RETURN_TEXT_P(result);\r
+}\r
+\r
+\r
+/**\r
+ * SVG features\r
+ */\r
+PG_FUNCTION_INFO_V1(LWGEOM_asSVG);\r
+Datum LWGEOM_asSVG(PG_FUNCTION_ARGS)\r
+{\r
+       PG_LWGEOM *geom;\r
+       LWGEOM *lwgeom;\r
+       char *svg;\r
+       text *result;\r
+       int relative = 0;\r
+       int precision=OUT_MAX_DOUBLE_PRECISION;\r
+\r
+       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();\r
+\r
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));\r
+\r
+       /* check for relative path notation */\r
+       if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )\r
+               relative = PG_GETARG_INT32(1) ? 1:0;\r
+\r
+       if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )\r
+       {\r
+               precision = PG_GETARG_INT32(2);\r
+               if ( precision > OUT_MAX_DOUBLE_PRECISION )\r
+                       precision = OUT_MAX_DOUBLE_PRECISION;\r
+               else if ( precision < 0 ) precision = 0;\r
+       }\r
+\r
+       lwgeom = pglwgeom_deserialize(geom);\r
+       svg = lwgeom_to_svg(lwgeom, precision, relative);\r
+       result = cstring2text(svg);\r
+       lwgeom_free(lwgeom);\r
+       pfree(svg);\r
+       PG_FREE_IF_COPY(geom, 0);\r
+\r
+       PG_RETURN_TEXT_P(result);\r
+}\r
+\r
+/**\r
+ * Encode feature as X3D\r
+ */\r
+PG_FUNCTION_INFO_V1(LWGEOM_asX3D);\r
+Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)\r
+{\r
+       PG_LWGEOM *geom;\r
+       LWGEOM *lwgeom;\r
+       char *x3d;\r
+       text *result;\r
+       int version;\r
+       char *srs;\r
+       int srid;\r
+       int option = 0;\r
+       int is_deegree = 0;\r
+       int is_dims = 1;\r
+       int precision = OUT_MAX_DOUBLE_PRECISION;\r
+       static const char* default_defid = "x3d:"; /* default defid */\r
+       char *defidbuf;\r
+       const char* defid = default_defid;\r
+       text *defid_text;\r
+\r
+       /* Get the version */\r
+       version = PG_GETARG_INT32(0);\r
+       if (  version != 3 )\r
+       {\r
+               elog(ERROR, "Only X3D version 3 are supported");\r
+               PG_RETURN_NULL();\r
+       }\r
+\r
+       /* Get the geometry */\r
+       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();\r
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));\r
+\r
+       /* Retrieve precision if any (default is max) */\r
+       if (PG_NARGS() >2 && !PG_ARGISNULL(2))\r
+       {\r
+               precision = PG_GETARG_INT32(2);\r
+               if ( precision > OUT_MAX_DOUBLE_PRECISION )\r
+                       precision = OUT_MAX_DOUBLE_PRECISION;\r
+               else if ( precision < 0 ) precision = 0;\r
+       }\r
+\r
+       /* retrieve option */\r
+       if (PG_NARGS() >3 && !PG_ARGISNULL(3))\r
+               option = PG_GETARG_INT32(3);\r
+\r
+       /* retrieve defid */\r
+       if (PG_NARGS() >4 && !PG_ARGISNULL(4))\r
+       {\r
+               defid_text = PG_GETARG_TEXT_P(4);\r
+               if ( VARSIZE(defid_text)-VARHDRSZ == 0 )\r
+               {\r
+                       defid = "";\r
+               }\r
+               else\r
+               {\r
+                       /* +2 is one for the ':' and one for term null */\r
+                       defidbuf = palloc(VARSIZE(defid_text)-VARHDRSZ+2);\r
+                       memcpy(defidbuf, VARDATA(defid_text),\r
+                              VARSIZE(defid_text)-VARHDRSZ);\r
+                       /* add colon and null terminate */\r
+                       defidbuf[VARSIZE(defid_text)-VARHDRSZ] = ':';\r
+                       defidbuf[VARSIZE(defid_text)-VARHDRSZ+1] = '\0';\r
+                       defid = defidbuf;\r
+               }\r
+       }\r
+\r
+       srid = pglwgeom_get_srid(geom);\r
+       if (srid == SRID_UNKNOWN)      srs = NULL;\r
+       else if (option & 1) srs = getSRSbySRID(srid, false);\r
+       else                 srs = getSRSbySRID(srid, true);\r
+\r
+       if (option & 2)  is_dims = 0;\r
+       if (option & 16) is_deegree = 1;\r
+\r
+       lwgeom = pglwgeom_deserialize(geom);\r
+\r
+\r
+       x3d = lwgeom_to_x3d3(lwgeom, srs, precision,option, defid);\r
+\r
+       lwgeom_free(lwgeom);\r
+       PG_FREE_IF_COPY(geom, 1);\r
+\r
+       result = cstring2text(x3d);\r
+       lwfree(x3d);\r
+\r
+       PG_RETURN_TEXT_P(result);\r
+}\r
index 476d1a10fa0d3026d1037b245efc5f7c1568af25..a21bb3aa0859b55a40788fc741128ee46221fd65 100644 (file)
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
---
--- $Id$
---
--- PostGIS - Spatial Types for PostgreSQL
--- http://postgis.refractions.net
--- Copyright 2001-2003 Refractions Research Inc.
---
--- This is free software; you can redistribute and/or modify it under
--- the terms of the GNU General Public Licence. See the COPYING file.
---
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
---
--- WARNING: Any change in this file must be evaluated for compatibility.
---          Changes cleanly handled by postgis_upgrade.sql are fine,
---         other changes will require a bump in Major version.
---         Currently only function replaceble by CREATE OR REPLACE
---         are cleanly handled.
---
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-#include "sqldefines.h"
-
-SET client_min_messages TO warning;
-
-
--- INSTALL VERSION: POSTGIS_LIB_VERSION
-
-BEGIN;
-
--------------------------------------------------------------------
---  SPHEROID TYPE
--------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION spheroid_in(cstring)
-       RETURNS spheroid
-       AS 'MODULE_PATHNAME','ellipsoid_in'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION spheroid_out(spheroid)
-       RETURNS cstring
-       AS 'MODULE_PATHNAME','ellipsoid_out'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE TYPE spheroid (
-       alignment = double,
-       internallength = 65,
-       input = spheroid_in,
-       output = spheroid_out
-);
-
--------------------------------------------------------------------
---  GEOMETRY TYPE (lwgeom)
--------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION geometry_in(cstring)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_in'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_out(geometry)
-       RETURNS cstring
-       AS 'MODULE_PATHNAME','LWGEOM_out'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_analyze(internal)
-       RETURNS bool
-#ifdef GSERIALIZED_ON
-       AS 'MODULE_PATHNAME', 'geometry_analyze'
-#else
-       AS 'MODULE_PATHNAME', 'LWGEOM_analyze'
-#endif
-       LANGUAGE 'C' VOLATILE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_recv(internal)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_recv'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_send(geometry)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','LWGEOM_send'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE TYPE geometry (
-       internallength = variable,
-       input = geometry_in,
-       output = geometry_out,
-       send = geometry_send,
-       receive = geometry_recv,
-       delimiter = ':',
-       analyze = geometry_analyze,
-       storage = main
-);
-
--------------------------------------------
--- Affine transforms
--------------------------------------------
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Affine(geometry,float8,float8,float8,float8,float8,float8,float8,float8,float8,float8,float8,float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_affine'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Affine(geometry,float8,float8,float8,float8,float8,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1,  $2, $3, 0,  $4, $5, 0,  0, 0, 1,  $6, $7, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_RotateZ(geometry,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1,  cos($2), -sin($2), 0,  sin($2), cos($2), 0,  0, 0, 1,  0, 0, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8)
-       RETURNS geometry
-       AS 'SELECT ST_RotateZ($1, $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_RotateX(geometry,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1, 1, 0, 0, 0, cos($2), -sin($2), 0, sin($2), cos($2), 0, 0, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_RotateY(geometry,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1,  cos($2), 0, sin($2),  0, 1, 0,  -sin($2), 0, cos($2), 0,  0, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Translate(geometry,float8,float8,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1, 1, 0, 0, 0, 1, 0, 0, 0, 1, $2, $3, $4)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Translate(geometry,float8,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Translate($1, $2, $3, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Scale(geometry,float8,float8,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1,  $2, 0, 0,  0, $3, 0,  0, 0, $4,  0, 0, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Scale(geometry,float8,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Scale($1, $2, $3, 1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Transscale(geometry,float8,float8,float8,float8)
-       RETURNS geometry
-       AS 'SELECT ST_Affine($1,  $4, 0, 0,  0, $5, 0,
-               0, 0, 1,  $2 * $4, $3 * $5, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Shift_Longitude(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_longitude_shift'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--------------------------------------------------------------------
---  BOX3D TYPE
--------------------------------------------------------------------
-
-CREATE OR REPLACE FUNCTION box3d_in(cstring)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME', 'BOX3D_in'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box3d_out(box3d)
-       RETURNS cstring
-       AS 'MODULE_PATHNAME', 'BOX3D_out'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE TYPE box3d (
-       alignment = double,
-       internallength = 48,
-       input = box3d_in,
-       output = box3d_out
-);
-
--- Temporary box3d aggregate type to retain full double precision
--- for ST_Extent(). Should be removed when we change the output
--- type of ST_Extent() to return something other than BOX2DFLOAT4.
-CREATE OR REPLACE FUNCTION box3d_extent_in(cstring)
-       RETURNS box3d_extent
-       AS 'MODULE_PATHNAME', 'BOX3D_in'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box3d_extent_out(box3d_extent)
-       RETURNS cstring
-       AS 'MODULE_PATHNAME', 'BOX3D_extent_out'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE TYPE box3d_extent (
-       alignment = double,
-       internallength = 48,
-       input = box3d_extent_in,
-       output = box3d_extent_out
-);
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION box3d_extent(box3d_extent)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME', 'BOX3D_extent_to_BOX3D'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry(box3d_extent)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','BOX3D_to_LWGEOM'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- End of temporary hack
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_XMin(box3d)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','BOX3D_xmin'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_YMin(box3d)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','BOX3D_ymin'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_ZMin(box3d)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','BOX3D_zmin'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_XMax(box3d)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','BOX3D_xmax'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_YMax(box3d)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','BOX3D_ymax'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_ZMax(box3d)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','BOX3D_zmax'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
------------------------------------------------------------------------
--- BOX2D
------------------------------------------------------------------------
-
-CREATE OR REPLACE FUNCTION box2d_in(cstring)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME','BOX2DFLOAT4_in'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box2d_out(box2d)
-       RETURNS cstring
-       AS 'MODULE_PATHNAME','BOX2DFLOAT4_out'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE TYPE box2d (
-#ifdef GSERIALIZED_ON
-       internallength = 65,
-#else
-       internallength = 16,
-#endif
-       input = box2d_in,
-       output = box2d_out,
-       storage = plain
-);
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_expand(box2d,float8)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_expand'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION postgis_getbbox(geometry)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME','LWGEOM_to_BOX2DFLOAT4'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box2d(box3d_extent)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME', 'BOX3D_to_BOX2DFLOAT4'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION MakeBox2d(geometry, geometry)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_construct'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakeBox2d(geometry, geometry)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_construct'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Combine_BBox(box2d,geometry)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_combine'
-       LANGUAGE 'C' IMMUTABLE;
-
------------------------------------------------------------------------
--- ESTIMATED_EXTENT( <schema name>, <table name>, <column name> )
------------------------------------------------------------------------
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION estimated_extent(text,text,text) RETURNS box2d AS
-#ifdef GSERIALIZED_ON
-       'MODULE_PATHNAME', 'geometry_estimated_extent'
-#else
-       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'
-#endif
-       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text,text) RETURNS box2d AS
-#ifdef GSERIALIZED_ON
-       'MODULE_PATHNAME', 'geometry_estimated_extent'
-#else
-       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'
-#endif
-       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;
-
------------------------------------------------------------------------
--- ESTIMATED_EXTENT( <table name>, <column name> )
------------------------------------------------------------------------
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION estimated_extent(text,text) RETURNS box2d AS
-#ifdef GSERIALIZED_ON
-       'MODULE_PATHNAME', 'geometry_estimated_extent'
-#else
-       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'
-#endif
-       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text) RETURNS box2d AS
-#ifdef GSERIALIZED_ON
-       'MODULE_PATHNAME', 'geometry_estimated_extent'
-#else
-       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'
-#endif
-       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;
-
------------------------------------------------------------------------
--- FIND_EXTENT( <schema name>, <table name>, <column name> )
------------------------------------------------------------------------
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION find_extent(text,text,text) RETURNS box2d AS
-$$
-DECLARE
-       schemaname alias for $1;
-       tablename alias for $2;
-       columnname alias for $3;
-       myrec RECORD;
-
-BEGIN
-       FOR myrec IN EXECUTE 'SELECT ST_Extent("' || columnname || '") FROM "' || schemaname || '"."' || tablename || '"' LOOP
-               return myrec.extent;
-       END LOOP;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_find_extent(text,text,text) RETURNS box2d AS
-$$
-DECLARE
-       schemaname alias for $1;
-       tablename alias for $2;
-       columnname alias for $3;
-       myrec RECORD;
-
-BEGIN
-       FOR myrec IN EXECUTE 'SELECT ST_Extent("' || columnname || '") FROM "' || schemaname || '"."' || tablename || '"' LOOP
-               return myrec.extent;
-       END LOOP;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
-
------------------------------------------------------------------------
--- FIND_EXTENT( <table name>, <column name> )
------------------------------------------------------------------------
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION find_extent(text,text) RETURNS box2d AS
-$$
-DECLARE
-       tablename alias for $1;
-       columnname alias for $2;
-       myrec RECORD;
-
-BEGIN
-       FOR myrec IN EXECUTE 'SELECT extent("' || columnname || '") FROM "' || tablename || '"' LOOP
-               return myrec.extent;
-       END LOOP;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_find_extent(text,text) RETURNS box2d AS
-$$
-DECLARE
-       tablename alias for $1;
-       columnname alias for $2;
-       myrec RECORD;
-
-BEGIN
-       FOR myrec IN EXECUTE 'SELECT extent("' || columnname || '") FROM "' || tablename || '"' LOOP
-               return myrec.extent;
-       END LOOP;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
--------------------------------------------------------------------
--- BTREE indexes
--------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION geometry_lt(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'lwgeom_lt'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_le(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'lwgeom_le'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_gt(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'lwgeom_gt'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_ge(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'lwgeom_ge'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_eq(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'lwgeom_eq'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_cmp(geometry, geometry)
-       RETURNS integer
-       AS 'MODULE_PATHNAME', 'lwgeom_cmp'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
---
--- Sorting operators for Btree
---
-
-CREATE OPERATOR < (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_lt,
-       COMMUTATOR = '>', NEGATOR = '>=',
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR <= (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_le,
-       COMMUTATOR = '>=', NEGATOR = '>',
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR = (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_eq,
-       COMMUTATOR = '=', -- we might implement a faster negator here
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR >= (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_ge,
-       COMMUTATOR = '<=', NEGATOR = '<',
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-CREATE OPERATOR > (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_gt,
-       COMMUTATOR = '<', NEGATOR = '<=',
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-
-
-CREATE OPERATOR CLASS btree_geometry_ops
-       DEFAULT FOR TYPE geometry USING btree AS
-       OPERATOR        1       < ,
-       OPERATOR        2       <= ,
-       OPERATOR        3       = ,
-       OPERATOR        4       >= ,
-       OPERATOR        5       > ,
-       FUNCTION        1       geometry_cmp (geometry, geometry);
-
-#ifndef GSERIALIZED_ON
--------------------------------------------------------------------
--- GiST indexes
--------------------------------------------------------------------
--- Deprecation in 1.5.0 -- is this deprecated? 2011-01-05 robe
-CREATE OR REPLACE FUNCTION geometry_same(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_samebox'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_gist_sel (internal, oid, internal, int4)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_gist_sel'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION geometry_gist_joinsel(internal, oid, internal, smallint)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_gist_joinsel'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION geometry_overleft(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_overleft'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_overright(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_overright'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_overabove(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_overabove'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_overbelow(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_overbelow'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_left(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_left'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_right(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_right'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_above(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_above'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_below(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_below'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_contain(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_contain'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_contained(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_contained'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_overlap(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_overlap'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry_samebox(geometry, geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_samebox'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OPERATOR << (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_left,
-       COMMUTATOR = '>>',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR &< (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overleft,
-       COMMUTATOR = '&>',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR <<| (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_below,
-       COMMUTATOR = '|>>',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR &<| (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overbelow,
-       COMMUTATOR = '|&>',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR && (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overlap,
-       COMMUTATOR = '&&',
-       RESTRICT = geometry_gist_sel, JOIN = geometry_gist_joinsel
-);
-
-CREATE OPERATOR &> (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overright,
-       COMMUTATOR = '&<',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR >> (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_right,
-       COMMUTATOR = '<<',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR |&> (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overabove,
-       COMMUTATOR = '&<|',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR |>> (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_above,
-       COMMUTATOR = '<<|',
-       RESTRICT = positionsel, JOIN = positionjoinsel
-);
-
-CREATE OPERATOR ~= (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_samebox,
-       COMMUTATOR = '~=',
-       RESTRICT = eqsel, JOIN = eqjoinsel
-);
-
-CREATE OPERATOR @ (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_contained,
-       COMMUTATOR = '~',
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-
-CREATE OPERATOR ~ (
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_contain,
-       COMMUTATOR = '@',
-       RESTRICT = contsel, JOIN = contjoinsel
-);
-
--- gist support functions
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_consistent(internal,geometry,int4)
-       RETURNS bool
-       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_consistent'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_compress(internal)
-       RETURNS internal
-       AS 'MODULE_PATHNAME','LWGEOM_gist_compress'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_penalty(internal,internal,internal)
-       RETURNS internal
-       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_penalty'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_picksplit(internal, internal)
-       RETURNS internal
-       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_picksplit'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_union(bytea, internal)
-       RETURNS internal
-       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_union'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_same(box2d, box2d, internal)
-       RETURNS internal
-       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_same'
-       LANGUAGE 'C';
-
-CREATE OR REPLACE FUNCTION LWGEOM_gist_decompress(internal)
-       RETURNS internal
-       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_decompress'
-       LANGUAGE 'C';
-
--------------------------------------------
--- GIST opclass index binding entries.
--------------------------------------------
---
--- Create opclass index bindings for PG>=73
---
-
-CREATE OPERATOR CLASS gist_geometry_ops
-       DEFAULT FOR TYPE geometry USING gist AS
-       STORAGE         box2d,
-       OPERATOR        1        << ,
-       OPERATOR        2        &<     ,
-       OPERATOR        3        &&     ,
-       OPERATOR        4        &>     ,
-       OPERATOR        5        >>     ,
-       OPERATOR        6        ~=     ,
-       OPERATOR        7        ~      ,
-       OPERATOR        8        @      ,
-       OPERATOR        9        &<|    ,
-       OPERATOR        10       <<|    ,
-       OPERATOR        11       |>>    ,
-       OPERATOR        12       |&>    ,
-       FUNCTION        1        LWGEOM_gist_consistent (internal, geometry, int4),
-       FUNCTION        2        LWGEOM_gist_union (bytea, internal),
-       FUNCTION        3        LWGEOM_gist_compress (internal),
-       FUNCTION        4        LWGEOM_gist_decompress (internal),
-       FUNCTION        5        LWGEOM_gist_penalty (internal, internal, internal),
-       FUNCTION        6        LWGEOM_gist_picksplit (internal, internal),
-       FUNCTION        7        LWGEOM_gist_same (box2d, box2d, internal);
-
-#endif
-
--------------------------------------------
--- other lwgeom functions
--------------------------------------------
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION postgis_addbbox(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_addBBOX'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION postgis_dropbbox(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_dropBBOX'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION getsrid(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME','LWGEOM_get_srid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION postgis_hasbbox(geometry)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_hasBBOX'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
-------------------------------------------------------------------------
--- DEBUG
-------------------------------------------------------------------------
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_mem_size(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME', 'LWGEOM_mem_size'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_summary(geometry)
-       RETURNS text
-       AS 'MODULE_PATHNAME', 'LWGEOM_summary'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Npoints(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME', 'LWGEOM_npoints'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_nrings(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME', 'LWGEOM_nrings'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-------------------------------------------------------------------------
--- Misures
-------------------------------------------------------------------------
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Length3d(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_length_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Length2d(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_length2d_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: length2d(geometry)
-CREATE OR REPLACE FUNCTION ST_Length(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_length2d_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- this is a fake (for back-compatibility)
--- uses 3d if 3d is available, 2d otherwise
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_length3d_spheroid(geometry, spheroid)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','LWGEOM_length_ellipsoid_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_length_spheroid(geometry, spheroid)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','LWGEOM_length_ellipsoid_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_length2d_spheroid(geometry, spheroid)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','LWGEOM_length2d_ellipsoid'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_perimeter3d(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_perimeter_poly'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_perimeter2d(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_perimeter2d_poly'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: perimeter2d(geometry)
-CREATE OR REPLACE FUNCTION ST_Perimeter(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_perimeter2d_poly'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
--- Deprecation in 1.3.4
-CREATE OR REPLACE FUNCTION ST_area2d(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'LWGEOM_area_polygon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: area(geometry)
-CREATE OR REPLACE FUNCTION ST_Area(geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','LWGEOM_area_polygon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_distance_spheroid(geometry,geometry,spheroid)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','LWGEOM_distance_ellipsoid'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_distance_sphere(geometry,geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME','LWGEOM_distance_sphere'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Minimum distance. 2d only.
-
--- PostGIS equivalent function: distance(geometry,geometry)
-CREATE OR REPLACE FUNCTION ST_Distance(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_mindistance2d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_point_inside_circle(geometry,float8,float8,float8)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'LWGEOM_inside_circle_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_azimuth(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_azimuth'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-------------------------------------------------------------------------
--- MISC
-------------------------------------------------------------------------
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_force_2d(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_2d'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_force_3dz(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_3dz'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_force_3d(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_3dz'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_force_3dm(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_3dm'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_force_4d(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_4d'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_force_collection(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_collection'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_CollectionExtract(geometry, integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_CollectionExtract'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Multi(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_multi'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Expand(box3d,float8)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME', 'BOX3D_expand'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Expand(geometry,float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_expand'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: envelope(geometry)
-CREATE OR REPLACE FUNCTION ST_Envelope(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_envelope'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Reverse(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_reverse'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_ForceRHR(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_force_clockwise_poly'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION postgis_noop(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_noop'
-       LANGUAGE 'C' VOLATILE STRICT;
-       
--- Deprecation in 1.5.0
-CREATE OR REPLACE FUNCTION ST_zmflag(geometry)
-       RETURNS smallint
-       AS 'MODULE_PATHNAME', 'LWGEOM_zmflag'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_NDims(geometry)
-       RETURNS smallint
-       AS 'MODULE_PATHNAME', 'LWGEOM_ndims'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsEWKT(geometry)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asEWKT'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsEWKB(geometry)
-       RETURNS BYTEA
-       AS 'MODULE_PATHNAME','WKBFromLWGEOM'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsHEXEWKB(geometry)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asHEXEWKB'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsHEXEWKB(geometry, text)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asHEXEWKB'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsEWKB(geometry,text)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','WKBFromLWGEOM'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_AsLatLonText(geometry, text)
-       RETURNS text
-       AS 'MODULE_PATHNAME','LWGEOM_to_latlon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_AsLatLonText(geometry)
-       RETURNS text
-       AS $$ SELECT ST_AsLatLonText($1, '') $$
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeomFromEWKB(bytea)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOMFromWKB'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomFromEWKB(bytea)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOMFromWKB'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeomFromEWKT(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','parse_WKT_lwgeom'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomFromEWKT(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','parse_WKT_lwgeom'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION postgis_cache_bbox()
-       RETURNS trigger
-       AS 'MODULE_PATHNAME', 'cache_bbox'
-       LANGUAGE 'C';
-
-------------------------------------------------------------------------
--- CONSTRUCTORS
-------------------------------------------------------------------------
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakePoint(float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakePoint(float8, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakePoint(float8, float8, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.3.4
-CREATE OR REPLACE FUNCTION ST_MakePointM(float8, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint3dm'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakeBox3d(geometry, geometry)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME', 'BOX3D_construct'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_MakeLine (geometry[])
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makeline_garray'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_LineFromMultiPoint(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_line_from_mpoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-       
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakeLine(geometry, geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makeline'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AddPoint(geometry, geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_addpoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AddPoint(geometry, geometry, integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_addpoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_RemovePoint(geometry, integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_removepoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_SetPoint(geometry, integer, geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_setpoint_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_MakeEnvelope(float8, float8, float8, float8, integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_MakeEnvelope'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakePolygon(geometry, geometry[])
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoly'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MakePolygon(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoly'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_BuildArea(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_buildarea'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_Polygonize (geometry[])
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'polygonize_garray'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_LineMerge(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'linemerge'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
-
-CREATE TYPE geometry_dump AS (path integer[], geom geometry);
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION Dump(geometry)
-       RETURNS SETOF geometry_dump
-       AS 'MODULE_PATHNAME', 'LWGEOM_dump'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Dump(geometry)
-       RETURNS SETOF geometry_dump
-       AS 'MODULE_PATHNAME', 'LWGEOM_dump'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_DumpRings(geometry)
-       RETURNS SETOF geometry_dump
-       AS 'MODULE_PATHNAME', 'LWGEOM_dump_rings'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
------------------------------------------------------------------------
--- _ST_DumpPoints()
------------------------------------------------------------------------
--- A helper function for ST_DumpPoints(geom)
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION _ST_DumpPoints(the_geom geometry, cur_path integer[]) RETURNS SETOF geometry_dump AS $$
-DECLARE
-  tmp geometry_dump;
-  tmp2 geometry_dump;
-  nb_points integer;
-  nb_geom integer;
-  i integer;
-  j integer;
-  g geometry;
-  
-BEGIN
-  
-  RAISE DEBUG '%,%', cur_path, ST_GeometryType(the_geom);
-
-  -- Special case collections : iterate and return the DumpPoints of the geometries
-
-  IF (ST_IsCollection(the_geom)) THEN
-    i = 1;
-    FOR tmp2 IN SELECT (ST_Dump(the_geom)).* LOOP
-
-      FOR tmp IN SELECT * FROM _ST_DumpPoints(tmp2.geom, cur_path || tmp2.path) LOOP
-           RETURN NEXT tmp;
-      END LOOP;
-      i = i + 1;
-      
-    END LOOP;
-
-    RETURN;
-  END IF;
-  
-
-  -- Special case (POLYGON) : return the points of the rings of a polygon
-  IF (ST_GeometryType(the_geom) = 'ST_Polygon') THEN
-
-    FOR tmp IN SELECT * FROM _ST_DumpPoints(ST_ExteriorRing(the_geom), cur_path || ARRAY[1]) LOOP
-      RETURN NEXT tmp;
-    END LOOP;
-    
-    j := ST_NumInteriorRings(the_geom);
-    FOR i IN 1..j LOOP
-        FOR tmp IN SELECT * FROM _ST_DumpPoints(ST_InteriorRingN(the_geom, i), cur_path || ARRAY[i+1]) LOOP
-          RETURN NEXT tmp;
-        END LOOP;
-    END LOOP;
-    
-    RETURN;
-  END IF;
-
-  -- Special case (TRIANGLE) : return the points of the external rings of a TRIANGLE
-  IF (ST_GeometryType(the_geom) = 'ST_Triangle') THEN
-
-    FOR tmp IN SELECT * FROM _ST_DumpPoints(ST_ExteriorRing(the_geom), cur_path || ARRAY[1]) LOOP
-      RETURN NEXT tmp;
-    END LOOP;
-    
-    RETURN;
-  END IF;
-
-    
-  -- Special case (POINT) : return the point
-  IF (ST_GeometryType(the_geom) = 'ST_Point') THEN
-
-    tmp.path = cur_path || ARRAY[1];
-    tmp.geom = the_geom;
-
-    RETURN NEXT tmp;
-    RETURN;
-
-  END IF;
-
-
-  -- Use ST_NumPoints rather than ST_NPoints to have a NULL value if the_geom isn't
-  -- a LINESTRING, CIRCULARSTRING.
-  SELECT ST_NumPoints(the_geom) INTO nb_points;
-
-  -- This should never happen
-  IF (nb_points IS NULL) THEN
-    RAISE EXCEPTION 'Unexpected error while dumping geometry %', ST_AsText(the_geom);
-  END IF;
-
-  FOR i IN 1..nb_points LOOP
-    tmp.path = cur_path || ARRAY[i];
-    tmp.geom := ST_PointN(the_geom, i);
-    RETURN NEXT tmp;
-  END LOOP;
-   
-END
-$$ LANGUAGE plpgsql;
-
------------------------------------------------------------------------
--- ST_DumpPoints()
------------------------------------------------------------------------
--- This function mimicks that of ST_Dump for collections, but this function 
--- that returns a path and all the points that make up a particular geometry.
--- This current implementation in plpgsql does not scale very well at all.
--- and should be ported to C at some point.
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_DumpPoints(geometry) RETURNS SETOF geometry_dump AS $$
-  SELECT * FROM _ST_DumpPoints($1, NULL);
-$$ LANGUAGE SQL;
-
-
-------------------------------------------------------------------------
-
---
--- Aggregate functions
---
-
-
--- Temporary hack function
-CREATE OR REPLACE FUNCTION combine_bbox(box3d_extent,geometry)
-       RETURNS box3d_extent
-       AS 'MODULE_PATHNAME', 'BOX3D_combine'
-       LANGUAGE 'C' IMMUTABLE;
-
--- Temporary hack function
-CREATE OR REPLACE FUNCTION ST_Combine_BBox(box3d_extent,geometry)
-       RETURNS box3d_extent
-       AS 'MODULE_PATHNAME', 'BOX3D_combine'
-       LANGUAGE 'C' IMMUTABLE;
-
--- Deprecation in 1.2.3
-CREATE AGGREGATE Extent(
-       sfunc = ST_combine_bbox,
-       basetype = geometry,
-       stype = box3d_extent
-       );
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_Extent(
-       sfunc = ST_combine_bbox,
-       basetype = geometry,
-       stype = box3d_extent
-       );
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Combine_BBox(box3d,geometry)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME', 'BOX3D_combine'
-       LANGUAGE 'C' IMMUTABLE;
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_Extent3d(
-       sfunc = ST_combine_bbox,
-       basetype = geometry,
-       stype = box3d
-       );
-
-
-
--------------------------------------------------------------------
--- SPATIAL_REF_SYS
--------------------------------------------------------------------
-CREATE TABLE spatial_ref_sys (
-        srid integer not null primary key,
-        auth_name varchar(256),
-        auth_srid integer,
-        srtext varchar(2048),
-        proj4text varchar(2048)
-);
-
--------------------------------------------------------------------
--- GEOMETRY_COLUMNS
--------------------------------------------------------------------
-CREATE TABLE geometry_columns (
-       f_table_catalog varchar(256) not null,
-       f_table_schema varchar(256) not null,
-       f_table_name varchar(256) not null,
-       f_geometry_column varchar(256) not null,
-       coord_dimension integer not null,
-       srid integer not null,
-       type varchar(30) not null,
-       CONSTRAINT geometry_columns_pk primary key (
-               f_table_catalog,
-               f_table_schema,
-               f_table_name,
-               f_geometry_column )
-) WITH OIDS;
-
------------------------------------------------------------------------
--- RENAME_GEOMETRY_TABLE_CONSTRAINTS()
------------------------------------------------------------------------
--- This function has been obsoleted for the difficulty in
--- finding attribute on which the constraint is applied.
--- AddGeometryColumn will name the constraints in a meaningful
--- way, but nobody can rely on it since old postgis versions did
--- not do that.
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION rename_geometry_table_constraints() RETURNS text
-AS
-$$
-SELECT 'rename_geometry_table_constraint() is obsoleted'::text
-$$
-LANGUAGE 'SQL' IMMUTABLE;
-
------------------------------------------------------------------------
--- FIX_GEOMETRY_COLUMNS()
------------------------------------------------------------------------
--- This function will:
---
---     o try to fix the schema of records with an integer one
---             (for PG>=73)
---
---     o link records to system tables through attrelid and varattnum
---             (for PG<75)
---
---     o delete all records for which no linking was possible
---             (for PG<75)
---
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION fix_geometry_columns() RETURNS text
-AS
-$$
-DECLARE
-       mislinked record;
-       result text;
-       linked integer;
-       deleted integer;
-       foundschema integer;
-BEGIN
-
-       -- Since 7.3 schema support has been added.
-       -- Previous postgis versions used to put the database name in
-       -- the schema column. This needs to be fixed, so we try to
-       -- set the correct schema for each geometry_colums record
-       -- looking at table, column, type and srid.
-       UPDATE geometry_columns SET f_table_schema = n.nspname
-               FROM pg_namespace n, pg_class c, pg_attribute a,
-                       pg_constraint sridcheck, pg_constraint typecheck
-                       WHERE ( f_table_schema is NULL
-               OR f_table_schema = ''
-                       OR f_table_schema NOT IN (
-                                       SELECT nspname::varchar
-                                       FROM pg_namespace nn, pg_class cc, pg_attribute aa
-                                       WHERE cc.relnamespace = nn.oid
-                                       AND cc.relname = f_table_name::name
-                                       AND aa.attrelid = cc.oid
-                                       AND aa.attname = f_geometry_column::name))
-                       AND f_table_name::name = c.relname
-                       AND c.oid = a.attrelid
-                       AND c.relnamespace = n.oid
-                       AND f_geometry_column::name = a.attname
-
-                       AND sridcheck.conrelid = c.oid
-               AND sridcheck.consrc LIKE '(%srid(% = %)'
-                       AND sridcheck.consrc ~ textcat(' = ', srid::text)
-
-                       AND typecheck.conrelid = c.oid
-               AND typecheck.consrc LIKE
-               '((geometrytype(%) = ''%''::text) OR (% IS NULL))'
-                       AND typecheck.consrc ~ textcat(' = ''', type::text)
-
-                       AND NOT EXISTS (
-                                       SELECT oid FROM geometry_columns gc
-                                       WHERE c.relname::varchar = gc.f_table_name
-                                       AND n.nspname::varchar = gc.f_table_schema
-                                       AND a.attname::varchar = gc.f_geometry_column
-                       );
-
-       GET DIAGNOSTICS foundschema = ROW_COUNT;
-
-       -- no linkage to system table needed
-       return 'fixed:'||foundschema::text;
-
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE;
-
------------------------------------------------------------------------
--- POPULATE_GEOMETRY_COLUMNS()
------------------------------------------------------------------------
--- Truncates and refills the geometry_columns table from all tables and
--- views in the database that contain geometry columns. This function
--- is a simple wrapper for populate_geometry_columns(oid).  In essence,
--- this function ensures every geometry column in the database has the
--- appropriate spatial contraints (for tables) and exists in the
--- geometry_columns table.
--- Availability: 1.4.0
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION populate_geometry_columns()
-       RETURNS text AS
-$$
-DECLARE
-       inserted    integer;
-       oldcount    integer;
-       probed      integer;
-       stale       integer;
-       gcs         RECORD;
-       gc          RECORD;
-       gsrid       integer;
-       gndims      integer;
-       gtype       text;
-       query       text;
-       gc_is_valid boolean;
-
-BEGIN
-       SELECT count(*) INTO oldcount FROM geometry_columns;
-       inserted := 0;
-
-       EXECUTE 'TRUNCATE geometry_columns';
-
-       -- Count the number of geometry columns in all tables and views
-       SELECT count(DISTINCT c.oid) INTO probed
-       FROM pg_class c,
-                pg_attribute a,
-                pg_type t,
-                pg_namespace n
-       WHERE (c.relkind = 'r' OR c.relkind = 'v')
-       AND t.typname = 'geometry'
-       AND a.attisdropped = false
-       AND a.atttypid = t.oid
-       AND a.attrelid = c.oid
-       AND c.relnamespace = n.oid
-       AND n.nspname NOT ILIKE 'pg_temp%';
-
-       -- Iterate through all non-dropped geometry columns
-       RAISE DEBUG 'Processing Tables.....';
-
-       FOR gcs IN
-       SELECT DISTINCT ON (c.oid) c.oid, n.nspname, c.relname
-               FROM pg_class c,
-                        pg_attribute a,
-                        pg_type t,
-                        pg_namespace n
-               WHERE c.relkind = 'r'
-               AND t.typname = 'geometry'
-               AND a.attisdropped = false
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-               AND c.relnamespace = n.oid
-               AND n.nspname NOT ILIKE 'pg_temp%'
-       LOOP
-
-       inserted := inserted + populate_geometry_columns(gcs.oid);
-       END LOOP;
-
-       -- Add views to geometry columns table
-       RAISE DEBUG 'Processing Views.....';
-       FOR gcs IN
-       SELECT DISTINCT ON (c.oid) c.oid, n.nspname, c.relname
-               FROM pg_class c,
-                        pg_attribute a,
-                        pg_type t,
-                        pg_namespace n
-               WHERE c.relkind = 'v'
-               AND t.typname = 'geometry'
-               AND a.attisdropped = false
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-               AND c.relnamespace = n.oid
-       LOOP
-
-       inserted := inserted + populate_geometry_columns(gcs.oid);
-       END LOOP;
-
-       IF oldcount > inserted THEN
-       stale = oldcount-inserted;
-       ELSE
-       stale = 0;
-       END IF;
-
-       RETURN 'probed:' ||probed|| ' inserted:'||inserted|| ' conflicts:'||probed-inserted|| ' deleted:'||stale;
-END
-
-$$
-LANGUAGE 'plpgsql' VOLATILE;
-
------------------------------------------------------------------------
--- POPULATE_GEOMETRY_COLUMNS(tbl_oid oid)
------------------------------------------------------------------------
--- DELETEs from and reINSERTs into the geometry_columns table all entries
--- associated with the oid of a particular table or view.
---
--- If the provided oid is for a table, this function tries to determine
--- the srid, dimension, and geometry type of the all geometries
--- in the table, adding contraints as necessary to the table.  If
--- successful, an appropriate row is inserted into the geometry_columns
--- table, otherwise, the exception is caught and an error notice is
--- raised describing the problem. (This is so the wrapper function
--- populate_geometry_columns() can apply spatial constraints to all
--- geometry columns across an entire database at once without erroring
--- out)
---
--- If the provided oid is for a view, as with a table oid, this function
--- tries to determine the srid, dimension, and type of all the geometries
--- in the view, inserting appropriate entries into the geometry_columns
--- table.
--- Availability: 1.4.0
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION populate_geometry_columns(tbl_oid oid)
-       RETURNS integer AS
-$$
-DECLARE
-       gcs         RECORD;
-       gc          RECORD;
-       gsrid       integer;
-       gndims      integer;
-       gtype       text;
-       query       text;
-       gc_is_valid boolean;
-       inserted    integer;
-
-BEGIN
-       inserted := 0;
-
-       -- Iterate through all geometry columns in this table
-       FOR gcs IN
-       SELECT n.nspname, c.relname, a.attname
-               FROM pg_class c,
-                        pg_attribute a,
-                        pg_type t,
-                        pg_namespace n
-               WHERE c.relkind = 'r'
-               AND t.typname = 'geometry'
-               AND a.attisdropped = false
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-               AND c.relnamespace = n.oid
-               AND n.nspname NOT ILIKE 'pg_temp%'
-               AND c.oid = tbl_oid
-       LOOP
-
-       RAISE DEBUG 'Processing table %.%.%', gcs.nspname, gcs.relname, gcs.attname;
-
-       DELETE FROM geometry_columns
-         WHERE f_table_schema = quote_ident(gcs.nspname)
-         AND f_table_name = quote_ident(gcs.relname)
-         AND f_geometry_column = quote_ident(gcs.attname);
-
-       gc_is_valid := true;
-
-       -- Try to find srid check from system tables (pg_constraint)
-       gsrid :=
-               (SELECT replace(replace(split_part(s.consrc, ' = ', 2), ')', ''), '(', '')
-                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s
-                WHERE n.nspname = gcs.nspname
-                AND c.relname = gcs.relname
-                AND a.attname = gcs.attname
-                AND a.attrelid = c.oid
-                AND s.connamespace = n.oid
-                AND s.conrelid = c.oid
-                AND a.attnum = ANY (s.conkey)
-                AND s.consrc LIKE '%srid(% = %');
-       IF (gsrid IS NULL) THEN
-               -- Try to find srid from the geometry itself
-               EXECUTE 'SELECT st_srid(' || quote_ident(gcs.attname) || ') As srid
-                                FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'
-                       INTO gc;
-               gsrid := gc.srid;
-
-               -- Try to apply srid check to column
-               IF (gsrid IS NOT NULL) THEN
-                       BEGIN
-                               EXECUTE 'ALTER TABLE ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                                ADD CONSTRAINT ' || quote_ident('enforce_srid_' || gcs.attname) || '
-                                                CHECK (st_srid(' || quote_ident(gcs.attname) || ') = ' || gsrid || ')';
-                       EXCEPTION
-                               WHEN check_violation THEN
-                                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not apply constraint CHECK (st_srid(%) = %)', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname), quote_ident(gcs.attname), gsrid;
-                                       gc_is_valid := false;
-                       END;
-               END IF;
-       END IF;
-
-       -- Try to find ndims check from system tables (pg_constraint)
-       gndims :=
-               (SELECT replace(split_part(s.consrc, ' = ', 2), ')', '')
-                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s
-                WHERE n.nspname = gcs.nspname
-                AND c.relname = gcs.relname
-                AND a.attname = gcs.attname
-                AND a.attrelid = c.oid
-                AND s.connamespace = n.oid
-                AND s.conrelid = c.oid
-                AND a.attnum = ANY (s.conkey)
-                AND s.consrc LIKE '%ndims(% = %');
-       IF (gndims IS NULL) THEN
-               -- Try to find ndims from the geometry itself
-               EXECUTE 'SELECT st_ndims(' || quote_ident(gcs.attname) || ') As ndims
-                                FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'
-                       INTO gc;
-               gndims := gc.ndims;
-
-               -- Try to apply ndims check to column
-               IF (gndims IS NOT NULL) THEN
-                       BEGIN
-                               EXECUTE 'ALTER TABLE ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                                ADD CONSTRAINT ' || quote_ident('enforce_dims_' || gcs.attname) || '
-                                                CHECK (st_ndims(' || quote_ident(gcs.attname) || ') = '||gndims||')';
-                       EXCEPTION
-                               WHEN check_violation THEN
-                                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not apply constraint CHECK (st_ndims(%) = %)', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname), quote_ident(gcs.attname), gndims;
-                                       gc_is_valid := false;
-                       END;
-               END IF;
-       END IF;
-
-       -- Try to find geotype check from system tables (pg_constraint)
-       gtype :=
-               (SELECT replace(split_part(s.consrc, '''', 2), ')', '')
-                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s
-                WHERE n.nspname = gcs.nspname
-                AND c.relname = gcs.relname
-                AND a.attname = gcs.attname
-                AND a.attrelid = c.oid
-                AND s.connamespace = n.oid
-                AND s.conrelid = c.oid
-                AND a.attnum = ANY (s.conkey)
-                AND s.consrc LIKE '%geometrytype(% = %');
-       IF (gtype IS NULL) THEN
-               -- Try to find geotype from the geometry itself
-               EXECUTE 'SELECT geometrytype(' || quote_ident(gcs.attname) || ')
-                                FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'
-                       INTO gc;
-               gtype := gc.geometrytype;
-               --IF (gtype IS NULL) THEN
-               --    gtype := 'GEOMETRY';
-               --END IF;
-
-               -- Try to apply geometrytype check to column
-               IF (gtype IS NOT NULL) THEN
-                       BEGIN
-                               EXECUTE 'ALTER TABLE ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                               ADD CONSTRAINT ' || quote_ident('enforce_geotype_' || gcs.attname) || '
-                               CHECK ((geometrytype(' || quote_ident(gcs.attname) || ') = ' || quote_literal(gtype) || ') OR (' || quote_ident(gcs.attname) || ' IS NULL))';
-                       EXCEPTION
-                               WHEN check_violation THEN
-                                       -- No geometry check can be applied. This column contains a number of geometry types.
-                                       RAISE WARNING 'Could not add geometry type check (%) to table column: %.%.%', gtype, quote_ident(gcs.nspname),quote_ident(gcs.relname),quote_ident(gcs.attname);
-                       END;
-               END IF;
-       END IF;
-
-       IF (gsrid IS NULL) THEN
-               RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine the srid', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);
-       ELSIF (gndims IS NULL) THEN
-               RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine the number of dimensions', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);
-       ELSIF (gtype IS NULL) THEN
-               RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine the geometry type', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);
-       ELSE
-               -- Only insert into geometry_columns if table constraints could be applied.
-               IF (gc_is_valid) THEN
-                       INSERT INTO geometry_columns (f_table_catalog,f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, type)
-                       VALUES ('', gcs.nspname, gcs.relname, gcs.attname, gndims, gsrid, gtype);
-                       inserted := inserted + 1;
-               END IF;
-       END IF;
-       END LOOP;
-
-       -- Add views to geometry columns table
-       FOR gcs IN
-       SELECT n.nspname, c.relname, a.attname
-               FROM pg_class c,
-                        pg_attribute a,
-                        pg_type t,
-                        pg_namespace n
-               WHERE c.relkind = 'v'
-               AND t.typname = 'geometry'
-               AND a.attisdropped = false
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-               AND c.relnamespace = n.oid
-               AND n.nspname NOT ILIKE 'pg_temp%'
-               AND c.oid = tbl_oid
-       LOOP
-               RAISE DEBUG 'Processing view %.%.%', gcs.nspname, gcs.relname, gcs.attname;
-
-               EXECUTE 'SELECT st_ndims(' || quote_ident(gcs.attname) || ') As ndims
-                                FROM ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'
-                       INTO gc;
-               gndims := gc.ndims;
-
-               EXECUTE 'SELECT st_srid(' || quote_ident(gcs.attname) || ') As srid
-                                FROM ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'
-                       INTO gc;
-               gsrid := gc.srid;
-
-               EXECUTE 'SELECT geometrytype(' || quote_ident(gcs.attname) || ')
-                                FROM ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '
-                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'
-                       INTO gc;
-               gtype := gc.geometrytype;
-
-               IF (gndims IS NULL) THEN
-                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine ndims', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);
-               ELSIF (gsrid IS NULL) THEN
-                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine srid', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);
-               ELSIF (gtype IS NULL) THEN
-                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine gtype', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);
-               ELSE
-                       query := 'INSERT INTO geometry_columns (f_table_catalog,f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, type) ' ||
-                                        'VALUES ('''', ' || quote_literal(gcs.nspname) || ',' || quote_literal(gcs.relname) || ',' || quote_literal(gcs.attname) || ',' || gndims || ',' || gsrid || ',' || quote_literal(gtype) || ')';
-                       EXECUTE query;
-                       inserted := inserted + 1;
-               END IF;
-       END LOOP;
-
-       RETURN inserted;
-END
-
-$$
-LANGUAGE 'plpgsql' VOLATILE;
-
-
------------------------------------------------------------------------
--- PROBE_GEOMETRY_COLUMNS()
------------------------------------------------------------------------
--- Fill the geometry_columns table with values probed from the system
--- catalogues. This is done by simply looking up constraints previously
--- added to a geometry column. If geometry constraints are missing, no
--- attempt is made to add the necessary constraints to the geometry
--- column, nor is it recorded in the geometry_columns table.
--- 3d flag cannot be probed, it defaults to 2
---
--- Note that bogus records already in geometry_columns are not
--- overridden (a check for schema.table.column is performed), so
--- to have a fresh probe backup your geometry_columns, delete from
--- it and probe.
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION probe_geometry_columns() RETURNS text AS
-$$
-DECLARE
-       inserted integer;
-       oldcount integer;
-       probed integer;
-       stale integer;
-BEGIN
-
-       SELECT count(*) INTO oldcount FROM geometry_columns;
-
-       SELECT count(*) INTO probed
-               FROM pg_class c, pg_attribute a, pg_type t,
-                       pg_namespace n,
-                       pg_constraint sridcheck, pg_constraint typecheck
-
-               WHERE t.typname = 'geometry'
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-               AND c.relnamespace = n.oid
-               AND sridcheck.connamespace = n.oid
-               AND typecheck.connamespace = n.oid
-               AND sridcheck.conrelid = c.oid
-               AND sridcheck.consrc LIKE '(%srid('||a.attname||') = %)'
-               AND typecheck.conrelid = c.oid
-               AND typecheck.consrc LIKE
-               '((geometrytype('||a.attname||') = ''%''::text) OR (% IS NULL))'
-               ;
-
-       INSERT INTO geometry_columns SELECT
-               ''::varchar as f_table_catalogue,
-               n.nspname::varchar as f_table_schema,
-               c.relname::varchar as f_table_name,
-               a.attname::varchar as f_geometry_column,
-               2 as coord_dimension,
-               trim(both  ' =)' from
-                       replace(replace(split_part(
-                               sridcheck.consrc, ' = ', 2), ')', ''), '(', ''))::integer AS srid,
-               trim(both ' =)''' from substr(typecheck.consrc,
-                       strpos(typecheck.consrc, '='),
-                       strpos(typecheck.consrc, '::')-
-                       strpos(typecheck.consrc, '=')
-                       ))::varchar as type
-               FROM pg_class c, pg_attribute a, pg_type t,
-                       pg_namespace n,
-                       pg_constraint sridcheck, pg_constraint typecheck
-               WHERE t.typname = 'geometry'
-               AND a.atttypid = t.oid
-               AND a.attrelid = c.oid
-               AND c.relnamespace = n.oid
-               AND sridcheck.connamespace = n.oid
-               AND typecheck.connamespace = n.oid
-               AND sridcheck.conrelid = c.oid
-               AND sridcheck.consrc LIKE '(%srid('||a.attname||') = %)'
-               AND typecheck.conrelid = c.oid
-               AND typecheck.consrc LIKE
-               '((geometrytype('||a.attname||') = ''%''::text) OR (% IS NULL))'
-
-                       AND NOT EXISTS (
-                                       SELECT oid FROM geometry_columns gc
-                                       WHERE c.relname::varchar = gc.f_table_name
-                                       AND n.nspname::varchar = gc.f_table_schema
-                                       AND a.attname::varchar = gc.f_geometry_column
-                       );
-
-       GET DIAGNOSTICS inserted = ROW_COUNT;
-
-       IF oldcount > probed THEN
-               stale = oldcount-probed;
-       ELSE
-               stale = 0;
-       END IF;
-
-       RETURN 'probed:'||probed::text||
-               ' inserted:'||inserted::text||
-               ' conflicts:'||(probed-inserted)::text||
-               ' stale:'||stale::text;
-END
-
-$$
-LANGUAGE 'plpgsql' VOLATILE;
-
------------------------------------------------------------------------
--- ADDGEOMETRYCOLUMN
---   <catalogue>, <schema>, <table>, <column>, <srid>, <type>, <dim>
------------------------------------------------------------------------
---
--- Type can be one of GEOMETRY, GEOMETRYCOLLECTION, POINT, MULTIPOINT, POLYGON,
--- MULTIPOLYGON, LINESTRING, or MULTILINESTRING.
---
--- Geometry types (except GEOMETRY) are checked for consistency using a CHECK constraint.
--- Uses an ALTER TABLE command to add the geometry column to the table.
--- Addes a row to geometry_columns.
--- Addes a constraint on the table that all the geometries MUST have the same
--- SRID. Checks the coord_dimension to make sure its between 0 and 3.
--- Should also check the precision grid (future expansion).
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION AddGeometryColumn(varchar,varchar,varchar,varchar,integer,varchar,integer)
-       RETURNS text
-       AS
-$$
-DECLARE
-       catalog_name alias for $1;
-       schema_name alias for $2;
-       table_name alias for $3;
-       column_name alias for $4;
-       new_srid alias for $5;
-       new_type alias for $6;
-       new_dim alias for $7;
-       rec RECORD;
-       sr varchar;
-       real_schema name;
-       sql text;
-
-BEGIN
-
-       -- Verify geometry type
-       IF ( NOT ( (new_type = 'GEOMETRY') OR
-                          (new_type = 'GEOMETRYCOLLECTION') OR
-                          (new_type = 'POINT') OR
-                          (new_type = 'MULTIPOINT') OR
-                          (new_type = 'POLYGON') OR
-                          (new_type = 'MULTIPOLYGON') OR
-                          (new_type = 'LINESTRING') OR
-                          (new_type = 'MULTILINESTRING') OR
-                          (new_type = 'GEOMETRYCOLLECTIONM') OR
-                          (new_type = 'POINTM') OR
-                          (new_type = 'MULTIPOINTM') OR
-                          (new_type = 'POLYGONM') OR
-                          (new_type = 'MULTIPOLYGONM') OR
-                          (new_type = 'LINESTRINGM') OR
-                          (new_type = 'MULTILINESTRINGM') OR
-                          (new_type = 'CIRCULARSTRING') OR
-                          (new_type = 'CIRCULARSTRINGM') OR
-                          (new_type = 'COMPOUNDCURVE') OR
-                          (new_type = 'COMPOUNDCURVEM') OR
-                          (new_type = 'CURVEPOLYGON') OR
-                          (new_type = 'CURVEPOLYGONM') OR
-                          (new_type = 'MULTICURVE') OR
-                          (new_type = 'MULTICURVEM') OR
-                          (new_type = 'MULTISURFACE') OR
-                          (new_type = 'MULTISURFACEM') OR
-                          (new_type = 'TRIANGLE') OR
-                          (new_type = 'TRIANGLEM') OR
-                          (new_type = 'POLYHEDRALSURFACE') OR
-                          (new_type = 'POLYHEDRALSURFACEM') OR
-                          (new_type = 'TIN') OR
-                          (new_type = 'TINM')) )
-       THEN
-               RAISE EXCEPTION 'Invalid type name - valid ones are:
-       POINT, MULTIPOINT,
-       LINESTRING, MULTILINESTRING,
-       POLYGON, MULTIPOLYGON,
-       CIRCULARSTRING, COMPOUNDCURVE, MULTICURVE,
-       CURVEPOLYGON, MULTISURFACE,
-       GEOMETRY, GEOMETRYCOLLECTION,
-       POINTM, MULTIPOINTM,
-       LINESTRINGM, MULTILINESTRINGM,
-       POLYGONM, MULTIPOLYGONM,
-       CIRCULARSTRINGM, COMPOUNDCURVEM, MULTICURVEM
-       CURVEPOLYGONM, MULTISURFACEM, TRIANGLE, TRIANGLEM,
-       POLYHEDRALSURFACE, POLYHEDRALSURFACEM, TIN, TINM
-       or GEOMETRYCOLLECTIONM';
-               RETURN 'fail';
-       END IF;
-
-
-       -- Verify dimension
-       IF ( (new_dim >4) OR (new_dim <0) ) THEN
-               RAISE EXCEPTION 'invalid dimension';
-               RETURN 'fail';
-       END IF;
-
-       IF ( (new_type LIKE '%M') AND (new_dim!=3) ) THEN
-               RAISE EXCEPTION 'TypeM needs 3 dimensions';
-               RETURN 'fail';
-       END IF;
-
-
-       -- Verify SRID
-       IF ( new_srid != -1 ) THEN
-               SELECT SRID INTO sr FROM spatial_ref_sys WHERE SRID = new_srid;
-               IF NOT FOUND THEN
-                       RAISE EXCEPTION 'AddGeometryColumns() - invalid SRID';
-                       RETURN 'fail';
-               END IF;
-       END IF;
-
-
-       -- Verify schema
-       IF ( schema_name IS NOT NULL AND schema_name != '' ) THEN
-               sql := 'SELECT nspname FROM pg_namespace ' ||
-                       'WHERE text(nspname) = ' || quote_literal(schema_name) ||
-                       'LIMIT 1';
-               RAISE DEBUG '%', sql;
-               EXECUTE sql INTO real_schema;
-
-               IF ( real_schema IS NULL ) THEN
-                       RAISE EXCEPTION 'Schema % is not a valid schemaname', quote_literal(schema_name);
-                       RETURN 'fail';
-               END IF;
-       END IF;
-
-       IF ( real_schema IS NULL ) THEN
-               RAISE DEBUG 'Detecting schema';
-               sql := 'SELECT n.nspname AS schemaname ' ||
-                       'FROM pg_catalog.pg_class c ' ||
-                         'JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace ' ||
-                       'WHERE c.relkind = ' || quote_literal('r') ||
-                       ' AND n.nspname NOT IN (' || quote_literal('pg_catalog') || ', ' || quote_literal('pg_toast') || ')' ||
-                       ' AND pg_catalog.pg_table_is_visible(c.oid)' ||
-                       ' AND c.relname = ' || quote_literal(table_name);
-               RAISE DEBUG '%', sql;
-               EXECUTE sql INTO real_schema;
-
-               IF ( real_schema IS NULL ) THEN
-                       RAISE EXCEPTION 'Table % does not occur in the search_path', quote_literal(table_name);
-                       RETURN 'fail';
-               END IF;
-       END IF;
-
-
-       -- Add geometry column to table
-       sql := 'ALTER TABLE ' ||
-               quote_ident(real_schema) || '.' || quote_ident(table_name)
-               || ' ADD COLUMN ' || quote_ident(column_name) ||
-               ' geometry ';
-       RAISE DEBUG '%', sql;
-       EXECUTE sql;
-
-
-       -- Delete stale record in geometry_columns (if any)
-       sql := 'DELETE FROM geometry_columns WHERE
-               f_table_catalog = ' || quote_literal('') ||
-               ' AND f_table_schema = ' ||
-               quote_literal(real_schema) ||
-               ' AND f_table_name = ' || quote_literal(table_name) ||
-               ' AND f_geometry_column = ' || quote_literal(column_name);
-       RAISE DEBUG '%', sql;
-       EXECUTE sql;
-
-
-       -- Add record in geometry_columns
-       sql := 'INSERT INTO geometry_columns (f_table_catalog,f_table_schema,f_table_name,' ||
-                                                                                 'f_geometry_column,coord_dimension,srid,type)' ||
-               ' VALUES (' ||
-               quote_literal('') || ',' ||
-               quote_literal(real_schema) || ',' ||
-               quote_literal(table_name) || ',' ||
-               quote_literal(column_name) || ',' ||
-               new_dim::text || ',' ||
-               new_srid::text || ',' ||
-               quote_literal(new_type) || ')';
-       RAISE DEBUG '%', sql;
-       EXECUTE sql;
-
-
-       -- Add table CHECKs
-       sql := 'ALTER TABLE ' ||
-               quote_ident(real_schema) || '.' || quote_ident(table_name)
-               || ' ADD CONSTRAINT '
-               || quote_ident('enforce_srid_' || column_name)
-               || ' CHECK (st_srid(' || quote_ident(column_name) ||
-               ') = ' || new_srid::text || ')' ;
-       RAISE DEBUG '%', sql;
-       EXECUTE sql;
-
-       sql := 'ALTER TABLE ' ||
-               quote_ident(real_schema) || '.' || quote_ident(table_name)
-               || ' ADD CONSTRAINT '
-               || quote_ident('enforce_dims_' || column_name)
-               || ' CHECK (st_ndims(' || quote_ident(column_name) ||
-               ') = ' || new_dim::text || ')' ;
-       RAISE DEBUG '%', sql;
-       EXECUTE sql;
-
-       IF ( NOT (new_type = 'GEOMETRY')) THEN
-               sql := 'ALTER TABLE ' ||
-                       quote_ident(real_schema) || '.' || quote_ident(table_name) || ' ADD CONSTRAINT ' ||
-                       quote_ident('enforce_geotype_' || column_name) ||
-                       ' CHECK (GeometryType(' ||
-                       quote_ident(column_name) || ')=' ||
-                       quote_literal(new_type) || ' OR (' ||
-                       quote_ident(column_name) || ') is null)';
-               RAISE DEBUG '%', sql;
-               EXECUTE sql;
-       END IF;
-
-       RETURN
-               real_schema || '.' ||
-               table_name || '.' || column_name ||
-               ' SRID:' || new_srid::text ||
-               ' TYPE:' || new_type ||
-               ' DIMS:' || new_dim::text || ' ';
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
-----------------------------------------------------------------------------
--- ADDGEOMETRYCOLUMN ( <schema>, <table>, <column>, <srid>, <type>, <dim> )
-----------------------------------------------------------------------------
---
--- This is a wrapper to the real AddGeometryColumn, for use
--- when catalogue is undefined
---
-----------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION AddGeometryColumn(varchar,varchar,varchar,integer,varchar,integer) RETURNS text AS $$
-DECLARE
-       ret  text;
-BEGIN
-       SELECT AddGeometryColumn('',$1,$2,$3,$4,$5,$6) into ret;
-       RETURN ret;
-END;
-$$
-LANGUAGE 'plpgsql' STABLE STRICT;
-
-----------------------------------------------------------------------------
--- ADDGEOMETRYCOLUMN ( <table>, <column>, <srid>, <type>, <dim> )
-----------------------------------------------------------------------------
---
--- This is a wrapper to the real AddGeometryColumn, for use
--- when catalogue and schema are undefined
---
-----------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION AddGeometryColumn(varchar,varchar,integer,varchar,integer) RETURNS text AS $$
-DECLARE
-       ret  text;
-BEGIN
-       SELECT AddGeometryColumn('','',$1,$2,$3,$4,$5) into ret;
-       RETURN ret;
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- DROPGEOMETRYCOLUMN
---   <catalogue>, <schema>, <table>, <column>
------------------------------------------------------------------------
---
--- Removes geometry column reference from geometry_columns table.
--- Drops the column with pgsql >= 73.
--- Make some silly enforcements on it for pgsql < 73
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION DropGeometryColumn(varchar, varchar,varchar,varchar)
-       RETURNS text
-       AS
-$$
-DECLARE
-       catalog_name alias for $1;
-       schema_name alias for $2;
-       table_name alias for $3;
-       column_name alias for $4;
-       myrec RECORD;
-       okay boolean;
-       real_schema name;
-
-BEGIN
-
-
-       -- Find, check or fix schema_name
-       IF ( schema_name != '' ) THEN
-               okay = 'f';
-
-               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP
-                       okay := 't';
-               END LOOP;
-
-               IF ( okay <> 't' ) THEN
-                       RAISE NOTICE 'Invalid schema name - using current_schema()';
-                       SELECT current_schema() into real_schema;
-               ELSE
-                       real_schema = schema_name;
-               END IF;
-       ELSE
-               SELECT current_schema() into real_schema;
-       END IF;
-
-       -- Find out if the column is in the geometry_columns table
-       okay = 'f';
-       FOR myrec IN SELECT * from geometry_columns where f_table_schema = text(real_schema) and f_table_name = table_name and f_geometry_column = column_name LOOP
-               okay := 't';
-       END LOOP;
-       IF (okay <> 't') THEN
-               RAISE EXCEPTION 'column not found in geometry_columns table';
-               RETURN 'f';
-       END IF;
-
-       -- Remove ref from geometry_columns table
-       EXECUTE 'delete from geometry_columns where f_table_schema = ' ||
-               quote_literal(real_schema) || ' and f_table_name = ' ||
-               quote_literal(table_name)  || ' and f_geometry_column = ' ||
-               quote_literal(column_name);
-
-       -- Remove table column
-       EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) || '.' ||
-               quote_ident(table_name) || ' DROP COLUMN ' ||
-               quote_ident(column_name);
-
-       RETURN real_schema || '.' || table_name || '.' || column_name ||' effectively removed.';
-
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- DROPGEOMETRYCOLUMN
---   <schema>, <table>, <column>
------------------------------------------------------------------------
---
--- This is a wrapper to the real DropGeometryColumn, for use
--- when catalogue is undefined
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION DropGeometryColumn(varchar,varchar,varchar)
-       RETURNS text
-       AS
-$$
-DECLARE
-       ret text;
-BEGIN
-       SELECT DropGeometryColumn('',$1,$2,$3) into ret;
-       RETURN ret;
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- DROPGEOMETRYCOLUMN
---   <table>, <column>
------------------------------------------------------------------------
---
--- This is a wrapper to the real DropGeometryColumn, for use
--- when catalogue and schema is undefined.
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION DropGeometryColumn(varchar,varchar)
-       RETURNS text
-       AS
-$$
-DECLARE
-       ret text;
-BEGIN
-       SELECT DropGeometryColumn('','',$1,$2) into ret;
-       RETURN ret;
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- DROPGEOMETRYTABLE
---   <catalogue>, <schema>, <table>
------------------------------------------------------------------------
---
--- Drop a table and all its references in geometry_columns
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION DropGeometryTable(varchar, varchar,varchar)
-       RETURNS text
-       AS
-$$
-DECLARE
-       catalog_name alias for $1;
-       schema_name alias for $2;
-       table_name alias for $3;
-       real_schema name;
-
-BEGIN
-
-       IF ( schema_name = '' ) THEN
-               SELECT current_schema() into real_schema;
-       ELSE
-               real_schema = schema_name;
-       END IF;
-
-       -- Remove refs from geometry_columns table
-       EXECUTE 'DELETE FROM geometry_columns WHERE ' ||
-               'f_table_schema = ' || quote_literal(real_schema) ||
-               ' AND ' ||
-               ' f_table_name = ' || quote_literal(table_name);
-
-       -- Remove table
-       EXECUTE 'DROP TABLE '
-               || quote_ident(real_schema) || '.' ||
-               quote_ident(table_name);
-
-       RETURN
-               real_schema || '.' ||
-               table_name ||' dropped.';
-
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- DROPGEOMETRYTABLE
---   <schema>, <table>
------------------------------------------------------------------------
---
--- Drop a table and all its references in geometry_columns
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION DropGeometryTable(varchar,varchar) RETURNS text AS
-$$ SELECT DropGeometryTable('',$1,$2) $$
-LANGUAGE 'sql' WITH (isstrict);
-
------------------------------------------------------------------------
--- DROPGEOMETRYTABLE
---   <table>
------------------------------------------------------------------------
---
--- Drop a table and all its references in geometry_columns
--- For PG>=73 use current_schema()
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION DropGeometryTable(varchar) RETURNS text AS
-$$ SELECT DropGeometryTable('','',$1) $$
-LANGUAGE 'sql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- UPDATEGEOMETRYSRID
---   <catalogue>, <schema>, <table>, <column>, <srid>
------------------------------------------------------------------------
---
--- Change SRID of all features in a spatially-enabled table
---
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION UpdateGeometrySRID(varchar,varchar,varchar,varchar,integer)
-       RETURNS text
-       AS
-$$
-DECLARE
-       catalog_name alias for $1;
-       schema_name alias for $2;
-       table_name alias for $3;
-       column_name alias for $4;
-       new_srid alias for $5;
-       myrec RECORD;
-       okay boolean;
-       cname varchar;
-       real_schema name;
-
-BEGIN
-
-
-       -- Find, check or fix schema_name
-       IF ( schema_name != '' ) THEN
-               okay = 'f';
-
-               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP
-                       okay := 't';
-               END LOOP;
-
-               IF ( okay <> 't' ) THEN
-                       RAISE EXCEPTION 'Invalid schema name';
-               ELSE
-                       real_schema = schema_name;
-               END IF;
-       ELSE
-               SELECT INTO real_schema current_schema()::text;
-       END IF;
-
-       -- Find out if the column is in the geometry_columns table
-       okay = 'f';
-       FOR myrec IN SELECT * from geometry_columns where f_table_schema = text(real_schema) and f_table_name = table_name and f_geometry_column = column_name LOOP
-               okay := 't';
-       END LOOP;
-       IF (okay <> 't') THEN
-               RAISE EXCEPTION 'column not found in geometry_columns table';
-               RETURN 'f';
-       END IF;
-
-       -- Update ref from geometry_columns table
-       EXECUTE 'UPDATE geometry_columns SET SRID = ' || new_srid::text ||
-               ' where f_table_schema = ' ||
-               quote_literal(real_schema) || ' and f_table_name = ' ||
-               quote_literal(table_name)  || ' and f_geometry_column = ' ||
-               quote_literal(column_name);
-
-       -- Make up constraint name
-       cname = 'enforce_srid_'  || column_name;
-
-       -- Drop enforce_srid constraint
-       EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) ||
-               '.' || quote_ident(table_name) ||
-               ' DROP constraint ' || quote_ident(cname);
-
-       -- Update geometries SRID
-       EXECUTE 'UPDATE ' || quote_ident(real_schema) ||
-               '.' || quote_ident(table_name) ||
-               ' SET ' || quote_ident(column_name) ||
-               ' = ST_SetSRID(' || quote_ident(column_name) ||
-               ', ' || new_srid::text || ')';
-
-       -- Reset enforce_srid constraint
-       EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) ||
-               '.' || quote_ident(table_name) ||
-               ' ADD constraint ' || quote_ident(cname) ||
-               ' CHECK (st_srid(' || quote_ident(column_name) ||
-               ') = ' || new_srid::text || ')';
-
-       RETURN real_schema || '.' || table_name || '.' || column_name ||' SRID changed to ' || new_srid::text;
-
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- UPDATEGEOMETRYSRID
---   <schema>, <table>, <column>, <srid>
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION UpdateGeometrySRID(varchar,varchar,varchar,integer)
-       RETURNS text
-       AS $$
-DECLARE
-       ret  text;
-BEGIN
-       SELECT UpdateGeometrySRID('',$1,$2,$3,$4) into ret;
-       RETURN ret;
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- UPDATEGEOMETRYSRID
---   <table>, <column>, <srid>
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION UpdateGeometrySRID(varchar,varchar,integer)
-       RETURNS text
-       AS $$
-DECLARE
-       ret  text;
-BEGIN
-       SELECT UpdateGeometrySRID('','',$1,$2,$3) into ret;
-       RETURN ret;
-END;
-$$
-LANGUAGE 'plpgsql' VOLATILE STRICT;
-
------------------------------------------------------------------------
--- FIND_SRID( <schema>, <table>, <geom col> )
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION find_srid(varchar,varchar,varchar) RETURNS int4 AS
-$$
-DECLARE
-       schem text;
-       tabl text;
-       sr int4;
-BEGIN
-       IF $1 IS NULL THEN
-         RAISE EXCEPTION 'find_srid() - schema is NULL!';
-       END IF;
-       IF $2 IS NULL THEN
-         RAISE EXCEPTION 'find_srid() - table name is NULL!';
-       END IF;
-       IF $3 IS NULL THEN
-         RAISE EXCEPTION 'find_srid() - column name is NULL!';
-       END IF;
-       schem = $1;
-       tabl = $2;
--- if the table contains a . and the schema is empty
--- split the table into a schema and a table
--- otherwise drop through to default behavior
-       IF ( schem = '' and tabl LIKE '%.%' ) THEN
-        schem = substr(tabl,1,strpos(tabl,'.')-1);
-        tabl = substr(tabl,length(schem)+2);
-       ELSE
-        schem = schem || '%';
-       END IF;
-
-       select SRID into sr from geometry_columns where f_table_schema like schem and f_table_name = tabl and f_geometry_column = $3;
-       IF NOT FOUND THEN
-          RAISE EXCEPTION 'find_srid() - couldnt find the corresponding SRID - is the geometry registered in the GEOMETRY_COLUMNS table?  Is there an uppercase/lowercase missmatch?';
-       END IF;
-       return sr;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
-
----------------------------------------------------------------
--- PROJ support
----------------------------------------------------------------
-
-CREATE OR REPLACE FUNCTION get_proj4_from_srid(integer) RETURNS text AS
-$$
-BEGIN
-       RETURN proj4text::text FROM spatial_ref_sys WHERE srid= $1;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION postgis_transform_geometry(geometry,text,text,int)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','transform_geom'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION transform(geometry,integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','transform'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: transform(geometry,integer)
-CREATE OR REPLACE FUNCTION ST_Transform(geometry,integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','transform'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
------------------------------------------------------------------------
--- POSTGIS_VERSION()
------------------------------------------------------------------------
-
-CREATE OR REPLACE FUNCTION postgis_version() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_proj_version() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
---
--- IMPORTANT:
--- Starting at 1.1.0 this function is used by postgis_proc_upgrade.pl
--- to extract version of postgis being installed.
--- Do not modify this w/out also changing postgis_proc_upgrade.pl
---
-CREATE OR REPLACE FUNCTION postgis_scripts_installed() RETURNS text
-       AS _POSTGIS_SQL_SELECT_POSTGIS_SCRIPTS_VERSION
-       LANGUAGE 'sql' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_lib_version() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE; -- a new lib will require a new session
-
--- NOTE: starting at 1.1.0 this is the same of postgis_lib_version()
-CREATE OR REPLACE FUNCTION postgis_scripts_released() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_uses_stats() RETURNS bool
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_geos_version() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_libxml_version() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_scripts_build_date() RETURNS text
-       AS _POSTGIS_SQL_SELECT_POSTGIS_BUILD_DATE
-       LANGUAGE 'sql' IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION postgis_lib_build_date() RETURNS text
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE;
-
-
-
-CREATE OR REPLACE FUNCTION postgis_full_version() RETURNS text
-AS $$
-DECLARE
-       libver text;
-       projver text;
-       geosver text;
-       libxmlver text;
-       usestats bool;
-       dbproc text;
-       relproc text;
-       fullver text;
-BEGIN
-       SELECT postgis_lib_version() INTO libver;
-       SELECT postgis_proj_version() INTO projver;
-       SELECT postgis_geos_version() INTO geosver;
-       SELECT postgis_libxml_version() INTO libxmlver;
-       SELECT postgis_uses_stats() INTO usestats;
-       SELECT postgis_scripts_installed() INTO dbproc;
-       SELECT postgis_scripts_released() INTO relproc;
-
-       fullver = 'POSTGIS="' || libver || '"';
-
-       IF  geosver IS NOT NULL THEN
-               fullver = fullver || ' GEOS="' || geosver || '"';
-       END IF;
-
-       IF  projver IS NOT NULL THEN
-               fullver = fullver || ' PROJ="' || projver || '"';
-       END IF;
-
-       IF  libxmlver IS NOT NULL THEN
-               fullver = fullver || ' LIBXML="' || libxmlver || '"';
-       END IF;
-
-       IF usestats THEN
-               fullver = fullver || ' USE_STATS';
-       END IF;
-
-       -- fullver = fullver || ' DBPROC="' || dbproc || '"';
-       -- fullver = fullver || ' RELPROC="' || relproc || '"';
-
-       IF dbproc != relproc THEN
-               fullver = fullver || ' (procs from ' || dbproc || ' need upgrade)';
-       END IF;
-
-       RETURN fullver;
-END
-$$
-LANGUAGE 'plpgsql' IMMUTABLE;
-
----------------------------------------------------------------
--- CASTS
----------------------------------------------------------------
-               
-CREATE OR REPLACE FUNCTION box2d(geometry)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME','LWGEOM_to_BOX2DFLOAT4'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box3d(geometry)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME','LWGEOM_to_BOX3D'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box(geometry)
-       RETURNS box
-       AS 'MODULE_PATHNAME','LWGEOM_to_BOX'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box2d(box3d)
-       RETURNS box2d
-       AS 'MODULE_PATHNAME','BOX3D_to_BOX2DFLOAT4'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box3d(box2d)
-       RETURNS box3d
-       AS 'MODULE_PATHNAME','BOX2DFLOAT4_to_BOX3D'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION box(box3d)
-       RETURNS box
-       AS 'MODULE_PATHNAME','BOX3D_to_BOX'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION text(geometry)
-       RETURNS text
-       AS 'MODULE_PATHNAME','LWGEOM_to_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- this is kept for backward-compatibility
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION box3dtobox(box3d)
-       RETURNS box
-       AS 'SELECT box($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry(box2d)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','BOX2DFLOAT4_to_LWGEOM'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry(box3d)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','BOX3D_to_LWGEOM'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','parse_WKT_lwgeom'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION geometry(bytea)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_bytea'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION bytea(geometry)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','LWGEOM_to_bytea'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- 7.3+ explicit casting definitions
-CREATE CAST (geometry AS box2d) WITH FUNCTION box2d(geometry) AS IMPLICIT;
-CREATE CAST (geometry AS box3d) WITH FUNCTION box3d(geometry) AS IMPLICIT;
-CREATE CAST (geometry AS box) WITH FUNCTION box(geometry) AS IMPLICIT;
-CREATE CAST (box3d AS box2d) WITH FUNCTION box2d(box3d) AS IMPLICIT;
-CREATE CAST (box2d AS box3d) WITH FUNCTION box3d(box2d) AS IMPLICIT;
-CREATE CAST (box2d AS geometry) WITH FUNCTION geometry(box2d) AS IMPLICIT;
-CREATE CAST (box3d AS box) WITH FUNCTION box(box3d) AS IMPLICIT;
-CREATE CAST (box3d AS geometry) WITH FUNCTION geometry(box3d) AS IMPLICIT;
-CREATE CAST (text AS geometry) WITH FUNCTION geometry(text) AS IMPLICIT;
-CREATE CAST (geometry AS text) WITH FUNCTION text(geometry) AS IMPLICIT;
-CREATE CAST (bytea AS geometry) WITH FUNCTION geometry(bytea) AS IMPLICIT;
-CREATE CAST (geometry AS bytea) WITH FUNCTION bytea(geometry) AS IMPLICIT;
-
--- Casts to allow the box3d_extent type to automatically cast to box3d/box2d in queries
-CREATE CAST (box3d_extent AS box3d) WITH FUNCTION box3d_extent(box3d_extent) AS IMPLICIT;
-CREATE CAST (box3d_extent AS box2d) WITH FUNCTION box2d(box3d_extent) AS IMPLICIT;
-CREATE CAST (box3d_extent AS geometry) WITH FUNCTION geometry(box3d_extent) AS IMPLICIT;
-
----------------------------------------------------------------
--- Algorithms
----------------------------------------------------------------
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Simplify(geometry, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_simplify2d'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- SnapToGrid(input, xoff, yoff, xsize, ysize)
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION SnapToGrid(geometry, float8, float8, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_snaptogrid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, float8, float8, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_snaptogrid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- SnapToGrid(input, xsize, ysize) # offsets=0
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION SnapToGrid(geometry, float8, float8)
-       RETURNS geometry
-       AS 'SELECT ST_SnapToGrid($1, 0, 0, $2, $3)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, float8, float8)
-       RETURNS geometry
-       AS 'SELECT ST_SnapToGrid($1, 0, 0, $2, $3)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_SnapToGrid(input, size) # xsize=ysize=size, offsets=0
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, float8)
-       RETURNS geometry
-       AS 'SELECT ST_SnapToGrid($1, 0, 0, $2, $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_SnapToGrid(input, point_offsets, xsize, ysize, zsize, msize)
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, geometry, float8, float8, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_snaptogrid_pointoff'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Segmentize(geometry, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_segmentize2d'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
----------------------------------------------------------------
--- LRS
----------------------------------------------------------------
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_line_interpolate_point(geometry, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_line_interpolate_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_line_substring(geometry, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_line_substring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_line_locate_point(geometry, geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_line_locate_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_locate_between_measures(geometry, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_locate_between_m'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_locate_along_measure(geometry, float8)
-       RETURNS geometry
-       AS $$ SELECT ST_locate_between_measures($1, $2, $2) $$
-       LANGUAGE 'sql' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_AddMeasure(geometry, float8, float8) 
-       RETURNS geometry 
-       AS 'MODULE_PATHNAME', 'ST_AddMeasure' 
-       LANGUAGE 'C' IMMUTABLE STRICT;
-    
----------------------------------------------------------------
--- GEOS
----------------------------------------------------------------
-
--- PostGIS equivalent function: intersection(geometry,geometry)
-CREATE OR REPLACE FUNCTION ST_Intersection(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','intersection'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- PostGIS equivalent function: buffer(geometry,float8)
-CREATE OR REPLACE FUNCTION ST_Buffer(geometry,float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','buffer'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.5.0 - requires GEOS-3.2 or higher
-CREATE OR REPLACE FUNCTION _ST_Buffer(geometry,float8,cstring)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','buffer'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Buffer(geometry,float8,integer)
-       RETURNS geometry
-       AS $$ SELECT _ST_Buffer($1, $2,
-               CAST('quad_segs='||CAST($3 AS text) as cstring))
-          $$
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_Buffer(geometry,float8,text)
-       RETURNS geometry
-       AS $$ SELECT _ST_Buffer($1, $2,
-               CAST( regexp_replace($3, '^[0123456789]+$',
-                       'quad_segs='||$3) AS cstring)
-               )
-          $$
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: convexhull(geometry)
-CREATE OR REPLACE FUNCTION ST_ConvexHull(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','convexhull'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Only accepts LINESTRING as parameters.
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION _ST_LineCrossingDirection(geometry, geometry)
-       RETURNS integer
-       AS 'MODULE_PATHNAME', 'ST_LineCrossingDirection'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_LineCrossingDirection(geometry, geometry)
-       RETURNS integer AS
-       $$ SELECT CASE WHEN NOT $1 && $2 THEN 0 ELSE _ST_LineCrossingDirection($1,$2) END $$
-       LANGUAGE 'sql' IMMUTABLE;
-
-
--- Only accepts LINESTRING as parameters.
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(geometry, float8, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Requires GEOS >= 3.0.0
--- Availability: 1.3.3
-CREATE OR REPLACE FUNCTION ST_SimplifyPreserveTopology(geometry, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','topologypreservesimplify'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Requires GEOS >= 3.1.0
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_IsValidReason(geometry)
-       RETURNS text
-       AS 'MODULE_PATHNAME', 'isvalidreason'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 2.0.0
-CREATE TYPE valid_detail AS (valid bool, reason varchar, location geometry);
-
--- Requires GEOS >= 3.3.0
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_IsValidDetail(geometry)
-       RETURNS valid_detail
-       AS 'MODULE_PATHNAME', 'isvaliddetail'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Requires GEOS >= 3.3.0
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_IsValidDetail(geometry, int4)
-       RETURNS valid_detail
-       AS 'MODULE_PATHNAME', 'isvaliddetail'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
-#if POSTGIS_GEOS_VERSION >= 33
--- Requires GEOS >= 3.3.0
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_IsValidReason(geometry, int4)
-       RETURNS text
-       AS $$
-SELECT CASE WHEN valid THEN 'Valid Geometry' ELSE reason END FROM (
-       SELECT (ST_isValidDetail($1, $2)).*
-) foo
-       $$
-       LANGUAGE 'sql' IMMUTABLE STRICT
-       COST 100;
-#endif
-
-#if POSTGIS_GEOS_VERSION >= 33
--- Requires GEOS >= 3.3.0
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_IsValid(geometry, int4)
-       RETURNS boolean
-       AS 'SELECT (ST_isValidDetail($1, $2)).valid'
-       LANGUAGE 'sql' IMMUTABLE STRICT
-       COST 100;
-#endif
-
-
-#if POSTGIS_GEOS_VERSION >= 32
--- Requires GEOS >= 3.2.0
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geometry, geometry)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'hausdorffdistance'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-#endif
-
-#if POSTGIS_GEOS_VERSION >= 32
--- Requires GEOS >= 3.2.0
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geometry, geometry, float8)
-       RETURNS FLOAT8
-       AS 'MODULE_PATHNAME', 'hausdorffdistancedensify'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-#endif
-
--- PostGIS equivalent function: difference(geometry,geometry)
-CREATE OR REPLACE FUNCTION ST_Difference(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','difference'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: boundary(geometry)
-CREATE OR REPLACE FUNCTION ST_Boundary(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','boundary'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: symdifference(geometry,geometry)
-CREATE OR REPLACE FUNCTION ST_SymDifference(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','symdifference'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_symmetricdifference(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','symdifference'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: GeomUnion(geometry,geometry)
-CREATE OR REPLACE FUNCTION ST_Union(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','geomunion'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
--- Requires: GEOS-3.3.0
-CREATE OR REPLACE FUNCTION ST_UnaryUnion(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','ST_UnaryUnion'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- ST_RemoveRepeatedPoints(in geometry)
---
--- Removes duplicate vertices in input.
--- Only checks consecutive points for lineal and polygonal geoms.
--- Checks all points for multipoint geoms.
---
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_RemoveRepeatedPoints(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_RemoveRepeatedPoints'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
---------------------------------------------------------------------------------
--- ST_CleanGeometry / ST_MakeValid
---------------------------------------------------------------------------------
-
--- ST_MakeValid(in geometry)
---
--- Try to make the input valid maintaining the boundary profile.
--- May return a collection.
--- May return a geometry with inferior dimensions (dimensional collapses).
--- May return NULL if can't handle input.
---
--- Requires: GEOS-3.3.0
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_MakeValid(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_MakeValid'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- ST_CleanGeometry(in geometry)
---
--- Make input:
---     - Simple (lineal components)
---     - Valid (polygonal components)
---     - Obeying the RHR (if polygonal)
---     - Simplified of consecutive duplicated points 
--- Ensuring:
---     - No input vertexes are discarded (except consecutive repeated ones)
---     - Output geometry type matches input
---
--- Returns NULL on failure.
--- 
--- Requires: GEOS-3.3.0
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_CleanGeometry(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_CleanGeometry'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
---------------------------------------------------------------------------------
--- ST_Split
---------------------------------------------------------------------------------
-
--- ST_Split(in geometry, blade geometry)
---
--- Split a geometry in parts after cutting it with given blade.
--- Returns a collection containing all parts.
---
--- Note that multi-part geometries will be returned exploded,
--- no matter relation to blade.
--- 
--- Availability: 2.0.0
---
-CREATE OR REPLACE FUNCTION ST_Split(geometry, geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_Split'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
---------------------------------------------------------------------------------
--- ST_SharedPaths
---------------------------------------------------------------------------------
-
--- ST_SharedPaths(lineal1 geometry, lineal1 geometry)
---
--- Returns a collection containing paths shared by the two
--- input geometries. Those going in the same direction are
--- in the first element of the collection, those going in the
--- opposite direction are in the second element.
---
--- The paths themselves are given in the direction of the
--- first geometry.
--- 
--- Availability: 2.0.0
--- Requires GEOS >= 3.3.0
---
-CREATE OR REPLACE FUNCTION ST_SharedPaths(geometry, geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_SharedPaths'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
---------------------------------------------------------------------------------
--- ST_Snap
---------------------------------------------------------------------------------
-
--- ST_Snap(g1 geometry, g2 geometry, tolerance float8)
---
--- Snap first geometry against second.
---
--- Availability: 2.0.0
--- Requires GEOS >= 3.3.0
---
-CREATE OR REPLACE FUNCTION ST_Snap(geometry, geometry, float8)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_Snap'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
---------------------------------------------------------------------------------
--- ST_RelateMatch
---------------------------------------------------------------------------------
-
--- ST_RelateMatch(matrix text, pattern text)
---
--- Returns true if pattern 'pattern' matches DE9 intersection matrix 'matrix'
---
--- Availability: 2.0.0
--- Requires GEOS >= 3.3.0
---
-CREATE OR REPLACE FUNCTION ST_RelateMatch(text, text)
-       RETURNS bool
-       AS 'MODULE_PATHNAME', 'ST_RelateMatch'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
-
---------------------------------------------------------------------------------
--- Aggregates and their supporting functions
---------------------------------------------------------------------------------
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Collect(geometry, geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_collect'
-       LANGUAGE 'C' IMMUTABLE;
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_MemCollect(
-       sfunc = ST_collect,
-       basetype = geometry,
-       stype = geometry
-       );
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Collect(geometry[])
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_collect_garray'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_MemUnion (
-       basetype = geometry,
-       sfunc = ST_Union,
-       stype = geometry
-       );
-
---
--- pgis_abs
--- Container type to hold the ArrayBuildState pointer as it passes through
--- the geometry array accumulation aggregate.
---
-CREATE OR REPLACE FUNCTION pgis_abs_in(cstring)
-       RETURNS pgis_abs
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION pgis_abs_out(pgis_abs)
-       RETURNS cstring
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE TYPE pgis_abs (
-       internallength = 8,
-       input = pgis_abs_in,
-       output = pgis_abs_out,
-       alignment = double
-);
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION pgis_geometry_accum_transfn(pgis_abs, geometry)
-       RETURNS pgis_abs
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C';
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION pgis_geometry_accum_finalfn(pgis_abs)
-       RETURNS geometry[]
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C';
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION pgis_geometry_union_finalfn(pgis_abs)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C';
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION pgis_geometry_collect_finalfn(pgis_abs)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C';
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION pgis_geometry_polygonize_finalfn(pgis_abs)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C';
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION pgis_geometry_makeline_finalfn(pgis_abs)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C';
-
--- Deprecation in: 1.2.3
-CREATE AGGREGATE accum (
-       sfunc = pgis_geometry_accum_transfn,
-       basetype = geometry,
-       stype = pgis_abs,
-       finalfunc = pgis_geometry_accum_finalfn
-       );
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_Accum (
-       sfunc = pgis_geometry_accum_transfn,
-       basetype = geometry,
-       stype = pgis_abs,
-       finalfunc = pgis_geometry_accum_finalfn
-       );
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_Union (geometry[])
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','pgis_union_geometry_array'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_Union (
-       basetype = geometry,
-       sfunc = pgis_geometry_accum_transfn,
-       stype = pgis_abs,
-       finalfunc = pgis_geometry_union_finalfn
-       );
-
--- Deprecation in 1.2.3
-CREATE AGGREGATE collect (
-       basetype = geometry,
-       sfunc = pgis_geometry_accum_transfn,
-       stype = pgis_abs,
-       finalfunc = pgis_geometry_collect_finalfn
-);
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_Collect (
-       BASETYPE = geometry,
-       SFUNC = pgis_geometry_accum_transfn,
-       STYPE = pgis_abs,
-       FINALFUNC = pgis_geometry_collect_finalfn
-       );
-
--- Deprecation in 1.2.3
-CREATE AGGREGATE Polygonize (
-       BASETYPE = geometry,
-       SFUNC = pgis_geometry_accum_transfn,
-       STYPE = pgis_abs,
-       FINALFUNC = pgis_geometry_polygonize_finalfn
-       );
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_Polygonize (
-       BASETYPE = geometry,
-       SFUNC = pgis_geometry_accum_transfn,
-       STYPE = pgis_abs,
-       FINALFUNC = pgis_geometry_polygonize_finalfn
-       );
-
--- Availability: 1.2.2
-CREATE AGGREGATE ST_MakeLine (
-       BASETYPE = geometry,
-       SFUNC = pgis_geometry_accum_transfn,
-       STYPE = pgis_abs,
-       FINALFUNC = pgis_geometry_makeline_finalfn
-       );
-
-
-
---------------------------------------------------------------------------------
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Relate(geometry,geometry)
-       RETURNS text
-       AS 'MODULE_PATHNAME','relate_full'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
--- Requires GEOS >= 3.3.0
-CREATE OR REPLACE FUNCTION ST_Relate(geometry, geometry, int4)
-       RETURNS text
-       AS 'MODULE_PATHNAME','relate_full'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: relate(geometry,geometry,text)
-CREATE OR REPLACE FUNCTION ST_Relate(geometry,geometry,text)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','relate_pattern'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: disjoint(geometry,geometry)
-CREATE OR REPLACE FUNCTION ST_Disjoint(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','disjoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: touches(geometry,geometry)
-CREATE OR REPLACE FUNCTION _ST_Touches(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','touches'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Touches(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Touches($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- Availability: 1.3.4
-CREATE OR REPLACE FUNCTION _ST_DWithin(geometry,geometry,float8)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_dwithin'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_DWithin(geometry, geometry, float8)
-       RETURNS boolean
-       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_DWithin($1, $2, $3)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- PostGIS equivalent function: intersects(geometry,geometry)
-CREATE OR REPLACE FUNCTION _ST_Intersects(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','intersects'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Intersects(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Intersects($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-       
--- PostGIS equivalent function: crosses(geometry,geometry)
-CREATE OR REPLACE FUNCTION _ST_Crosses(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','crosses'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Crosses(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Crosses($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- PostGIS equivalent function: within(geometry,geometry)
-CREATE OR REPLACE FUNCTION _ST_Within(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','within'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Within(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Within($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- PostGIS equivalent function: contains(geometry,geometry)
-CREATE OR REPLACE FUNCTION _ST_Contains(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','contains'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Contains(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Contains($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION _ST_CoveredBy(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'coveredby'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_CoveredBy(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_CoveredBy($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION _ST_Covers(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'covers'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Covers(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Covers($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION _ST_ContainsProperly(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','containsproperly'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.4.0
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_ContainsProperly(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_ContainsProperly($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- PostGIS equivalent function: overlaps(geometry,geometry)
-CREATE OR REPLACE FUNCTION _ST_Overlaps(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','overlaps'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.2
--- Inlines index magic
-CREATE OR REPLACE FUNCTION ST_Overlaps(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Overlaps($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
--- PostGIS equivalent function: IsValid(geometry)
--- TODO: change null returns to true
-CREATE OR REPLACE FUNCTION ST_IsValid(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'isvalid'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- This is also available w/out GEOS
-CREATE OR REPLACE FUNCTION Centroid(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-       
--- PostGIS equivalent function: Centroid(geometry)
-CREATE OR REPLACE FUNCTION ST_Centroid(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'centroid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-       
--- PostGIS equivalent function: IsRing(geometry)
-CREATE OR REPLACE FUNCTION ST_IsRing(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'isring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: PointOnSurface(geometry)
-CREATE OR REPLACE FUNCTION ST_PointOnSurface(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'pointonsurface'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- PostGIS equivalent function: IsSimple(geometry)
-CREATE OR REPLACE FUNCTION ST_IsSimple(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'issimple'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_IsCollection(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'ST_IsCollection'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION Equals(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','geomequals'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION _ST_Equals(geometry,geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME','geomequals'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
--- Availability: 1.2.1
-CREATE OR REPLACE FUNCTION ST_Equals(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_Equals($1,$2)'
-       LANGUAGE 'SQL' IMMUTABLE;
-
-
------------------------------------------------------------------------
--- GML & KML INPUT
--- Availability: 1.5.0
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION ST_GeomFromGML(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','geom_from_gml'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_GMLToSQL(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','geom_from_gml'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_GeomFromKML(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','geom_from_kml'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
------------------------------------------------------------------------
--- SVG OUTPUT
------------------------------------------------------------------------
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsSVG(geometry,int4,int4)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asSVG'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsSVG(geometry,int4)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asSVG'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsSVG(geometry)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asSVG'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
------------------------------------------------------------------------
--- GML OUTPUT
------------------------------------------------------------------------
--- _ST_AsGML(version, geom, precision, option, prefix)
-CREATE OR REPLACE FUNCTION _ST_AsGML(int4, geometry, int4, int4, text)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asGML'
-       LANGUAGE 'C' IMMUTABLE;
-
--- ST_AsGML(geom, precision) / version=2
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsGML(geometry, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML(2, $1, $2, 0, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGML(geom) / precision=15 version=2
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsGML(geometry)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML(2, $1, 15, 0, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGML(version, geom) / precision=15 
--- Availability: 1.3.2
-CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML($1, $2, 15, 0, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGML(version, geom, precision)
--- Availability: 1.3.2
-CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML($1, $2, $3, 0, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGML (geom, precision, option) / version=2
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_AsGML(geometry, int4, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML(2, $1, $2, $3, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGML(version, geom, precision, option)
--- Availability: 1.4.0
-CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry, int4, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML($1, $2, $3, $4, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
--- ST_AsGML(version, geom, precision, option, prefix)
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry, int4, int4, text)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGML($1, $2, $3, $4, $5)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
------------------------------------------------------------------------
--- KML OUTPUT
------------------------------------------------------------------------
--- _ST_AsKML(version, geom, precision)
-CREATE OR REPLACE FUNCTION _ST_AsKML(int4, geometry, int4, text)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asKML'
-       LANGUAGE 'C' IMMUTABLE;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsKML(geometry, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsKML(2, ST_Transform($1,4326), $2, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsKML(geometry)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsKML(2, ST_Transform($1,4326), 15, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsKML(version, geom) / precision=15 version=2
--- Availability: 1.3.2
-CREATE OR REPLACE FUNCTION ST_AsKML(int4, geometry)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsKML($1, ST_Transform($2,4326), 15, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsKML(version, geom, precision)
--- Availability: 1.3.2
-CREATE OR REPLACE FUNCTION ST_AsKML(int4, geometry, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsKML($1, ST_Transform($2,4326), $3, null)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsKML(version, geom, precision, text)
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_AsKML(int4, geometry, int4, text)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsKML($1, ST_Transform($2,4326), $3, $4)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
------------------------------------------------------------------------
--- GEOJSON OUTPUT
--- Availability: 1.3.4
------------------------------------------------------------------------
--- _ST_AsGeoJson(version, geom, precision, options)
-CREATE OR REPLACE FUNCTION _ST_AsGeoJson(int4, geometry, int4, int4)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asGeoJson'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- ST_AsGeoJson(geom, precision) / version=1 options=0
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(geometry, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGeoJson(1, $1, $2, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGeoJson(geom) / precision=15 version=1 options=0
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(geometry)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGeoJson(1, $1, 15, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGeoJson(version, geom) / precision=15 options=0
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(int4, geometry)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGeoJson($1, $2, 15, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGeoJson(version, geom, precision) / options=0
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(int4, geometry, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGeoJson($1, $2, $3, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGeoJson(geom, precision, options) / version=1
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(geometry, int4, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGeoJson(1, $1, $2, $3)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- ST_AsGeoJson(version, geom, precision,options)
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(int4, geometry, int4, int4)
-       RETURNS TEXT
-       AS 'SELECT _ST_AsGeoJson($1, $2, $3, $4)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-------------------------------------------------------------------------
--- GeoHash (geohash.org)
-------------------------------------------------------------------------
-
--- Availability 1.4.0
-CREATE OR REPLACE FUNCTION ST_GeoHash(geometry, int4)
-       RETURNS TEXT
-               AS 'MODULE_PATHNAME', 'ST_GeoHash'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability 1.4.0
-CREATE OR REPLACE FUNCTION ST_GeoHash(geometry)
-       RETURNS TEXT
-       AS 'SELECT ST_GeoHash($1, 0)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-------------------------------------------------------------------------
--- OGC defined
-------------------------------------------------------------------------
--- PostGIS equivalent function: NumPoints(geometry)
-CREATE OR REPLACE FUNCTION ST_NumPoints(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME', 'LWGEOM_numpoints_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: NumGeometries(geometry)
-CREATE OR REPLACE FUNCTION ST_NumGeometries(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME', 'LWGEOM_numgeometries_collection'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: GeometryN(geometry)
-CREATE OR REPLACE FUNCTION ST_GeometryN(geometry,integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_geometryn_collection'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: Dimension(geometry)
-CREATE OR REPLACE FUNCTION ST_Dimension(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME', 'LWGEOM_dimension'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: ExteriorRing(geometry)
-CREATE OR REPLACE FUNCTION ST_ExteriorRing(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_exteriorring_polygon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: NumInteriorRings(geometry)
-CREATE OR REPLACE FUNCTION ST_NumInteriorRings(geometry)
-       RETURNS integer
-       AS 'MODULE_PATHNAME','LWGEOM_numinteriorrings_polygon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_NumInteriorRing(geometry)
-       RETURNS integer
-       AS 'MODULE_PATHNAME','LWGEOM_numinteriorrings_polygon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: InteriorRingN(geometry)
-CREATE OR REPLACE FUNCTION ST_InteriorRingN(geometry,integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_interiorringn_polygon'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3 -- this should not be deprecated (2011-01-04 robe)
-CREATE OR REPLACE FUNCTION GeometryType(geometry)
-       RETURNS text
-       AS 'MODULE_PATHNAME', 'LWGEOM_getTYPE'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Not quite equivalent to GeometryType
-CREATE OR REPLACE FUNCTION ST_GeometryType(geometry)
-       RETURNS text
-       AS 'MODULE_PATHNAME', 'geometry_geometrytype'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: PointN(geometry,integer)
-CREATE OR REPLACE FUNCTION ST_PointN(geometry,integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_pointn_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_NumPatches(geometry)
-       RETURNS int4
-       AS '
-       SELECT CASE WHEN ST_GeometryType($1) = ''ST_PolyhedralSurface''
-       THEN ST_NumGeometries($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 2.0.0
-CREATE OR REPLACE FUNCTION ST_PatchN(geometry, integer)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN ST_GeometryType($1) = ''ST_PolyhedralSurface''
-       THEN ST_GeometryN($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: X(geometry)
-CREATE OR REPLACE FUNCTION ST_X(geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME','LWGEOM_x_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: Y(geometry)
-CREATE OR REPLACE FUNCTION ST_Y(geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME','LWGEOM_y_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_Z(geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME','LWGEOM_z_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_M(geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME','LWGEOM_m_point'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION StartPoint(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_startpoint_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: StartPoint(geometry))
-CREATE OR REPLACE FUNCTION ST_StartPoint(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_startpoint_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION EndPoint(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_endpoint_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: EndPoint(geometry)
-CREATE OR REPLACE FUNCTION ST_EndPoint(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_endpoint_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: IsClosed(geometry)
-CREATE OR REPLACE FUNCTION ST_IsClosed(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_isclosed'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: IsEmpty(geometry)
-CREATE OR REPLACE FUNCTION ST_IsEmpty(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_isempty'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION SRID(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME','LWGEOM_get_srid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: getSRID(geometry)
-CREATE OR REPLACE FUNCTION ST_SRID(geometry)
-       RETURNS int4
-       AS 'MODULE_PATHNAME','LWGEOM_get_srid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION SetSRID(geometry,int4)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_set_srid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_SetSRID(geometry,int4)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_set_srid'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION AsBinary(geometry)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','LWGEOM_asBinary'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: AsBinary(geometry)
-CREATE OR REPLACE FUNCTION ST_AsBinary(geometry)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','LWGEOM_asBinary'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION AsBinary(geometry,text)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','LWGEOM_asBinary'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_AsBinary(geometry,text)
-       RETURNS bytea
-       AS 'MODULE_PATHNAME','LWGEOM_asBinary'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION AsText(geometry)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asText'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: AsText(geometry)
-CREATE OR REPLACE FUNCTION ST_AsText(geometry)
-       RETURNS TEXT
-       AS 'MODULE_PATHNAME','LWGEOM_asText'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeometryFromText(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeometryFromText(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeometryFromText(text, int4)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeometryFromText(text, int4)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeomFromText(text)
-       RETURNS geometry AS 'SELECT geometryfromtext($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomFromText(text)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeomFromText(text, int4)
-       RETURNS geometry AS 'SELECT geometryfromtext($1, $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: ST_GeometryFromText(text, int4)
-CREATE OR REPLACE FUNCTION ST_GeomFromText(text, int4)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_text'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PointFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''POINT''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
--- PostGIS equivalent function: PointFromText(text, int4)
--- TODO: improve this ... by not duplicating constructor time.
-CREATE OR REPLACE FUNCTION ST_PointFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''POINT''
-       THEN ST_GeomFromText($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_LineFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''LINESTRING''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: LineFromText(text, int4)
-CREATE OR REPLACE FUNCTION ST_LineFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(GeomFromText($1, $2)) = ''LINESTRING''
-       THEN GeomFromText($1,$2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PolyFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''POLYGON''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: ST_PolygonFromText(text, int4)
-CREATE OR REPLACE FUNCTION ST_PolyFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''POLYGON''
-       THEN ST_GeomFromText($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PolygonFromText(text, int4)
-       RETURNS geometry
-       AS 'SELECT ST_PolyFromText($1, $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PolygonFromText(text)
-       RETURNS geometry
-       AS 'SELECT ST_PolyFromText($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: MLineFromText(text, int4)
-CREATE OR REPLACE FUNCTION ST_MLineFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE
-       WHEN geometrytype(ST_GeomFromText($1, $2)) = ''MULTILINESTRING''
-       THEN GeomFromText($1,$2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MLineFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''MULTILINESTRING''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiLineStringFromText(text)
-       RETURNS geometry
-       AS 'SELECT ST_MLineFromText($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiLineStringFromText(text, int4)
-       RETURNS geometry
-       AS 'SELECT ST_MLineFromText($1, $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: MPointFromText(text, int4)
-CREATE OR REPLACE FUNCTION ST_MPointFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''MULTIPOINT''
-       THEN GeomFromText($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MPointFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''MULTIPOINT''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPointFromText(text)
-       RETURNS geometry
-       AS 'SELECT ST_MPointFromText($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPointFromText(text)
-       RETURNS geometry
-       AS 'SELECT ST_MPointFromText($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: MPolyFromText(text, int4)
-CREATE OR REPLACE FUNCTION ST_MPolyFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''MULTIPOLYGON''
-       THEN ST_GeomFromText($1,$2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
---Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MPolyFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''MULTIPOLYGON''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPolygonFromText(text, int4)
-       RETURNS geometry
-       AS 'SELECT ST_MPolyFromText($1, $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPolygonFromText(text)
-       RETURNS geometry
-       AS 'SELECT ST_MPolyFromText($1)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomCollFromText(text, int4)
-       RETURNS geometry
-       AS '
-       SELECT CASE
-       WHEN geometrytype(ST_GeomFromText($1, $2)) = ''GEOMETRYCOLLECTION''
-       THEN ST_GeomFromText($1,$2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomCollFromText(text)
-       RETURNS geometry
-       AS '
-       SELECT CASE
-       WHEN geometrytype(ST_GeomFromText($1)) = ''GEOMETRYCOLLECTION''
-       THEN ST_GeomFromText($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeomFromWKB(bytea)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomFromWKB(bytea)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
--- Deprecation in 1.2.3
-CREATE OR REPLACE FUNCTION GeomFromWKB(bytea, int)
-       RETURNS geometry
-       AS 'SELECT ST_SetSRID(GeomFromWKB($1), $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: GeomFromWKB(bytea, int)
-CREATE OR REPLACE FUNCTION ST_GeomFromWKB(bytea, int)
-       RETURNS geometry
-       AS 'SELECT ST_SetSRID(ST_GeomFromWKB($1), $2)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: PointFromWKB(bytea, int)
-CREATE OR REPLACE FUNCTION ST_PointFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''POINT''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PointFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''POINT''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: LineFromWKB(bytea, int)
-CREATE OR REPLACE FUNCTION ST_LineFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''LINESTRING''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_LineFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''LINESTRING''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_LinestringFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''LINESTRING''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_LinestringFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(GeomFromWKB($1)) = ''LINESTRING''
-       THEN GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: PolyFromWKB(text, int)
-CREATE OR REPLACE FUNCTION ST_PolyFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''POLYGON''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PolyFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''POLYGON''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PolygonFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1,$2)) = ''POLYGON''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_PolygonFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''POLYGON''
-       THEN GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: MPointFromWKB(text, int)
-CREATE OR REPLACE FUNCTION ST_MPointFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTIPOINT''
-       THEN GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MPointFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOINT''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPointFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1,$2)) = ''MULTIPOINT''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPointFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOINT''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiLineFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTILINESTRING''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- PostGIS equivalent function: MLineFromWKB(text, int)
-CREATE OR REPLACE FUNCTION ST_MLineFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTILINESTRING''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MLineFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTILINESTRING''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
--- PostGIS equivalent function: MPolyFromWKB(bytea, int)
-CREATE OR REPLACE FUNCTION ST_MPolyFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTIPOLYGON''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MPolyFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOLYGON''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPolyFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTIPOLYGON''
-       THEN ST_GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_MultiPolyFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOLYGON''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomCollFromWKB(bytea, int)
-       RETURNS geometry
-       AS '
-       SELECT CASE
-       WHEN geometrytype(GeomFromWKB($1, $2)) = ''GEOMETRYCOLLECTION''
-       THEN GeomFromWKB($1, $2)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_GeomCollFromWKB(bytea)
-       RETURNS geometry
-       AS '
-       SELECT CASE
-       WHEN geometrytype(ST_GeomFromWKB($1)) = ''GEOMETRYCOLLECTION''
-       THEN ST_GeomFromWKB($1)
-       ELSE NULL END
-       '
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
---New functions
-
--- Maximum distance between linestrings.
-
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION _ST_MaxDistance(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'
-       LANGUAGE 'C' IMMUTABLE STRICT; 
-       
--- Availability: 1.5.0
-CREATE OR REPLACE FUNCTION ST_MaxDistance(geometry,geometry)
-       RETURNS float8
-       AS 'SELECT _ST_MaxDistance(ST_ConvexHull($1), ST_ConvexHull($2))'
-       LANGUAGE 'SQL' IMMUTABLE STRICT; 
-
-CREATE OR REPLACE FUNCTION ST_ClosestPoint(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_ShortestLine(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline2d'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION _ST_LongestLine(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_longestline2d'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_LongestLine(geometry,geometry)
-       RETURNS geometry
-       AS 'SELECT _ST_LongestLine(ST_ConvexHull($1), ST_ConvexHull($2))'
-       LANGUAGE 'SQL' IMMUTABLE STRICT; 
-
-CREATE OR REPLACE FUNCTION _ST_DFullyWithin(geometry,geometry,float8)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin'
-       LANGUAGE 'C' IMMUTABLE STRICT; 
-
-CREATE OR REPLACE FUNCTION ST_DFullyWithin(geometry, geometry, float8)
-       RETURNS boolean
-       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_DFullyWithin(ST_ConvexHull($1), ST_ConvexHull($2), $3)'
-       LANGUAGE 'SQL' IMMUTABLE; 
-       
-CREATE OR REPLACE FUNCTION ST_FlipCoordinates(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'ST_FlipCoordinates'
-       LANGUAGE 'C' IMMUTABLE STRICT; 
-
---
--- SFSQL 1.1
---
--- BdPolyFromText(multiLineStringTaggedText String, SRID Integer): Polygon
---
---  Construct a Polygon given an arbitrary
---  collection of closed linestrings as a
---  MultiLineString text representation.
---
--- This is a PLPGSQL function rather then an SQL function
--- To avoid double call of BuildArea (one to get GeometryType
--- and another to actual return, in a CASE WHEN construct).
--- Also, we profit from plpgsql to RAISE exceptions.
---
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_BdPolyFromText(text, integer)
-RETURNS geometry
-AS $$
-DECLARE
-       geomtext alias for $1;
-       srid alias for $2;
-       mline geometry;
-       geom geometry;
-BEGIN
-       mline := ST_MultiLineStringFromText(geomtext, srid);
-
-       IF mline IS NULL
-       THEN
-               RAISE EXCEPTION 'Input is not a MultiLinestring';
-       END IF;
-
-       geom := ST_BuildArea(mline);
-
-       IF GeometryType(geom) != 'POLYGON'
-       THEN
-               RAISE EXCEPTION 'Input returns more then a single polygon, try using BdMPolyFromText instead';
-       END IF;
-
-       RETURN geom;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
---
--- SFSQL 1.1
---
--- BdMPolyFromText(multiLineStringTaggedText String, SRID Integer): MultiPolygon
---
---  Construct a MultiPolygon given an arbitrary
---  collection of closed linestrings as a
---  MultiLineString text representation.
---
--- This is a PLPGSQL function rather then an SQL function
--- To raise an exception in case of invalid input.
---
-
--- Availability: 1.2.2
-CREATE OR REPLACE FUNCTION ST_BdMPolyFromText(text, integer)
-RETURNS geometry
-AS $$
-DECLARE
-       geomtext alias for $1;
-       srid alias for $2;
-       mline geometry;
-       geom geometry;
-BEGIN
-       mline := ST_MultiLineStringFromText(geomtext, srid);
-
-       IF mline IS NULL
-       THEN
-               RAISE EXCEPTION 'Input is not a MultiLinestring';
-       END IF;
-
-       geom := ST_Multi(ST_BuildArea(mline));
-
-       RETURN geom;
-END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
-#include "long_xact.sql.in.c"
-#include "sqlmm.sql.in.c"
-#include "geography.sql.in.c"
-
-
----------------------------------------------------------------
--- 3D-functions
----------------------------------------------------------------
-
-CREATE OR REPLACE FUNCTION ST_3DDistance(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_mindistance3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-       
-CREATE OR REPLACE FUNCTION ST_3DMaxDistance(geometry,geometry)
-       RETURNS float8
-       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;       
-
-CREATE OR REPLACE FUNCTION ST_3DClosestPoint(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
-CREATE OR REPLACE FUNCTION ST_3DShortestLine(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-
-CREATE OR REPLACE FUNCTION ST_3DLongestLine(geometry,geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_longestline3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-       
-CREATE OR REPLACE FUNCTION _ST_3DDWithin(geometry,geometry,float8)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_dwithin3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-       
-CREATE OR REPLACE FUNCTION ST_3DDWithin(geometry,geometry,float8)
-       RETURNS boolean
-       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_3DDWithin($1, $2, $3)'
-       LANGUAGE 'SQL' IMMUTABLE
-       COST 100;
-       
-CREATE OR REPLACE FUNCTION _ST_3DDFullyWithin(geometry,geometry,float8)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin3d'
-       LANGUAGE 'C' IMMUTABLE STRICT
-       COST 100;
-       
-CREATE OR REPLACE FUNCTION ST_3DDFullyWithin(geometry,geometry,float8)
-       RETURNS boolean
-       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_3DDFullyWithin($1, $2, $3)'
-       LANGUAGE 'SQL' IMMUTABLE
-       COST 100;
-       
-CREATE OR REPLACE FUNCTION ST_3DIntersects(geometry,geometry)
-       RETURNS boolean
-       AS 'SELECT $1 && $2 AND _ST_3DDWithin($1, $2, 0.0)'
-       LANGUAGE 'SQL' IMMUTABLE
-       COST 100;
-       
-       
----------------------------------------------------------------
--- SQL-MM
----------------------------------------------------------------
-
---
--- SQL-MM
---
--- ST_CurveToLine(Geometry geometry, SegmentsPerQuarter integer)
---
--- Converts a given geometry to a linear geometry.  Each curveed
--- geometry or segment is converted into a linear approximation using
--- the given number of segments per quarter circle.
-CREATE OR REPLACE FUNCTION ST_CurveToLine(geometry, integer)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_curve_segmentize'
-       LANGUAGE 'C' IMMUTABLE STRICT;
---
--- SQL-MM
---
--- ST_CurveToLine(Geometry geometry, SegmentsPerQuarter integer)
---
--- Converts a given geometry to a linear geometry.  Each curveed
--- geometry or segment is converted into a linear approximation using
--- the default value of 32 segments per quarter circle
-CREATE OR REPLACE FUNCTION ST_CurveToLine(geometry)
-       RETURNS geometry AS 'SELECT ST_CurveToLine($1, 32)'
-       LANGUAGE 'SQL' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_HasArc(geometry)
-       RETURNS boolean
-       AS 'MODULE_PATHNAME', 'LWGEOM_has_arc'
-       LANGUAGE 'C' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_LineToCurve(geometry)
-       RETURNS geometry
-       AS 'MODULE_PATHNAME', 'LWGEOM_line_desegmentize'
-       LANGUAGE 'C' IMMUTABLE STRICT;
----------------------------------------------------------------
--- END
----------------------------------------------------------------
-
-
----------------------------------------------------------------
--- USER CONTRIBUTED
----------------------------------------------------------------
-
------------------------------------------------------------------------
--- ST_MinimumBoundingCircle(inputgeom geometry, segs_per_quarter integer)
------------------------------------------------------------------------
--- Returns the smallest circle polygon that can fully contain a geometry
--- Defaults to 48 segs per quarter to approximate a circle
--- Contributed by Bruce Rindahl
--- Availability: 1.4.0
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION ST_MinimumBoundingCircle(inputgeom geometry, segs_per_quarter integer)
-       RETURNS geometry AS
-$BODY$
-       DECLARE
-       hull GEOMETRY;
-       ring GEOMETRY;
-       center GEOMETRY;
-       radius DOUBLE PRECISION;
-       dist DOUBLE PRECISION;
-       d DOUBLE PRECISION;
-       idx1 integer;
-       idx2 integer;
-       l1 GEOMETRY;
-       l2 GEOMETRY;
-       p1 GEOMETRY;
-       p2 GEOMETRY;
-       a1 DOUBLE PRECISION;
-       a2 DOUBLE PRECISION;
-
-
-       BEGIN
-
-       -- First compute the ConvexHull of the geometry
-       hull = ST_ConvexHull(inputgeom);
-       --A point really has no MBC
-       IF ST_GeometryType(hull) = 'ST_Point' THEN
-               RETURN hull;
-       END IF;
-       -- convert the hull perimeter to a linestring so we can manipulate individual points
-       --If its already a linestring force it to a closed linestring
-       ring = CASE WHEN ST_GeometryType(hull) = 'ST_LineString' THEN ST_AddPoint(hull, ST_StartPoint(hull)) ELSE ST_ExteriorRing(hull) END;
-
-       dist = 0;
-       -- Brute Force - check every pair
-       FOR i in 1 .. (ST_NumPoints(ring)-2)
-               LOOP
-                       FOR j in i .. (ST_NumPoints(ring)-1)
-                               LOOP
-                               d = ST_Distance(ST_PointN(ring,i),ST_PointN(ring,j));
-                               -- Check the distance and update if larger
-                               IF (d > dist) THEN
-                                       dist = d;
-                                       idx1 = i;
-                                       idx2 = j;
-                               END IF;
-                       END LOOP;
-               END LOOP;
-
-       -- We now have the diameter of the convex hull.  The following line returns it if desired.
-       -- RETURN MakeLine(PointN(ring,idx1),PointN(ring,idx2));
-
-       -- Now for the Minimum Bounding Circle.  Since we know the two points furthest from each
-       -- other, the MBC must go through those two points. Start with those points as a diameter of a circle.
-
-       -- The radius is half the distance between them and the center is midway between them
-       radius = ST_Distance(ST_PointN(ring,idx1),ST_PointN(ring,idx2)) / 2.0;
-       center = ST_Line_interpolate_point(ST_MakeLine(ST_PointN(ring,idx1),ST_PointN(ring,idx2)),0.5);
-
-       -- Loop through each vertex and check if the distance from the center to the point
-       -- is greater than the current radius.
-       FOR k in 1 .. (ST_NumPoints(ring)-1)
-               LOOP
-               IF(k <> idx1 and k <> idx2) THEN
-                       dist = ST_Distance(center,ST_PointN(ring,k));
-                       IF (dist > radius) THEN
-                               -- We have to expand the circle.  The new circle must pass trhough
-                               -- three points - the two original diameters and this point.
-
-                               -- Draw a line from the first diameter to this point
-                               l1 = ST_Makeline(ST_PointN(ring,idx1),ST_PointN(ring,k));
-                               -- Compute the midpoint
-                               p1 = ST_line_interpolate_point(l1,0.5);
-                               -- Rotate the line 90 degrees around the midpoint (perpendicular bisector)
-                               l1 = ST_Translate(ST_Rotate(ST_Translate(l1,-X(p1),-Y(p1)),pi()/2),X(p1),Y(p1));
-                               --  Compute the azimuth of the bisector
-                               a1 = ST_Azimuth(ST_PointN(l1,1),ST_PointN(l1,2));
-                               --  Extend the line in each direction the new computed distance to insure they will intersect
-                               l1 = ST_AddPoint(l1,ST_Makepoint(X(ST_PointN(l1,2))+sin(a1)*dist,Y(ST_PointN(l1,2))+cos(a1)*dist),-1);
-                               l1 = ST_AddPoint(l1,ST_Makepoint(X(ST_PointN(l1,1))-sin(a1)*dist,Y(ST_PointN(l1,1))-cos(a1)*dist),0);
-
-                               -- Repeat for the line from the point to the other diameter point
-                               l2 = ST_Makeline(ST_PointN(ring,idx2),ST_PointN(ring,k));
-                               p2 = ST_Line_interpolate_point(l2,0.5);
-                               l2 = ST_Translate(ST_Rotate(ST_Translate(l2,-X(p2),-Y(p2)),pi()/2),X(p2),Y(p2));
-                               a2 = ST_Azimuth(ST_PointN(l2,1),ST_PointN(l2,2));
-                               l2 = ST_AddPoint(l2,ST_Makepoint(X(ST_PointN(l2,2))+sin(a2)*dist,Y(ST_PointN(l2,2))+cos(a2)*dist),-1);
-                               l2 = ST_AddPoint(l2,ST_Makepoint(X(ST_PointN(l2,1))-sin(a2)*dist,Y(ST_PointN(l2,1))-cos(a2)*dist),0);
-
-                               -- The new center is the intersection of the two bisectors
-                               center = ST_Intersection(l1,l2);
-                               -- The new radius is the distance to any of the three points
-                               radius = ST_Distance(center,ST_PointN(ring,idx1));
-                       END IF;
-               END IF;
-               END LOOP;
-       --DONE!!  Return the MBC via the buffer command
-       RETURN ST_Buffer(center,radius,segs_per_quarter);
-
-       END;
-$BODY$
-       LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_MinimumBoundingCircle(geometry)
- RETURNS geometry AS
-'SELECT ST_MinimumBoundingCircle($1, 48)'
- LANGUAGE 'sql' IMMUTABLE STRICT;
--- ST_ConcaveHull and Helper functions starts here --
------------------------------------------------------------------------
--- Contributed by Regina Obe and Leo Hsu
--- Availability: 2.0.0
------------------------------------------------------------------------
-CREATE OR REPLACE FUNCTION _ST_ConcaveHull(param_inputgeom geometry)
-  RETURNS geometry AS
-$$
-       DECLARE     
-       vexhull GEOMETRY;
-       var_resultgeom geometry;
-       vexring GEOMETRY;
-       cavering GEOMETRY;
-       cavept geometry[];
-       seglength double precision;
-       var_tempgeom geometry;
-       i integer;
-       
-       BEGIN
-
-               -- First compute the ConvexHull of the geometry
-               vexhull := ST_ConvexHull(param_inputgeom);
-               --A point really has no concave hull
-               IF ST_GeometryType(vexhull) = 'ST_Point' OR ST_GeometryType(vexHull) = 'ST_LineString' THEN
-                       RETURN vexhull;
-               END IF;
-
-               -- convert the hull perimeter to a linestring so we can manipulate individual points
-               vexring := CASE WHEN ST_GeometryType(vexhull) = 'ST_LineString' THEN vexhull ELSE ST_ExteriorRing(vexhull) END;
-               seglength := ST_Length(vexring)/least(ST_NPoints(vexring)*2,1000) ;
-
-               vexring := ST_Segmentize(vexring, seglength);
-               -- find the point on the original geom that is closest to each point of the convex hull and make a new linestring out of it.
-               cavering := ST_Collect(
-                       ARRAY(
-
-                               SELECT 
-                                       ST_ClosestPoint(param_inputgeom, pt ) As the_geom
-                                       FROM (
-                                               SELECT  ST_PointN(vexring, n ) As pt, n
-                                                       FROM 
-                                                       generate_series(1, ST_NPoints(vexring) ) As n
-                                               ) As pt
-                               
-                               )
-                       )
-               ; 
-
-               var_resultgeom := ST_MakePolygon(ST_MakeLine(geom)) 
-                       FROM ST_Dump(cavering) As foo;
-               
-               IF NOT ST_IsValid(var_resultgeom) THEN
-                   --RAISE NOTICE '_ST_Concavehull invalid %', ST_AsText(var_resultgeom);
-                   var_tempgeom := ST_BuildArea(var_resultgeom); -- try to make valid
-                   IF NOT ST_IsValid(var_tempgeom) THEN
-                               var_resultgeom := ST_Buffer(var_resultgeom,ST_Length(cavering)/1000, 'quad_segs=3'); -- try to make valid
-                   END IF;
-                    --if still invalid or doens't  contain the geometry just return convex hull
-                   IF NOT ST_IsValid(var_resultgeom) or ST_GeometryType(var_resultgeom) <> 'ST_Polygon' THEN
-                               var_resultgeom := ST_ConvexHull(param_inputgeom);
-                   ELSIF ST_GeometryType(param_inputgeom) ILIKE '%Geometry%' THEN
-                               IF EXISTS(SELECT geom FROM ST_Dump(param_inputgeom) WHERE NOT ST_Covers(var_resultgeom,geom) ) THEN 
-                               --we have to explode inputgeom since geos doesn't support geometrycollections for containment check
-                                  var_resultgeom := ST_ConvexHull(param_inputgeom);
-                               END IF;
-                       ELSIF NOT ST_Contains(var_resultgeom, param_inputgeom) THEN
-                               var_resultgeom := ST_ConvexHull(param_inputgeom);
-                       END IF;
-               END IF;
-               RETURN var_resultgeom;
-       
-       END;
-$$
-  LANGUAGE 'plpgsql' IMMUTABLE STRICT
-  COST 100;
-  
-CREATE OR REPLACE FUNCTION ST_ConcaveHull(param_geom geometry, param_pctconvex float, param_allow_holes boolean) RETURNS geometry AS
-$$
-       DECLARE
-               var_convhull geometry := ST_ConvexHull(param_geom);
-               var_param_geom geometry := param_geom;
-               var_initarea float := ST_Area(var_convhull);
-               var_newarea float := var_initarea;
-               var_div integer := 6; /** this is the 1/var_div is the percent increase we will allow per triangle to keep speed decent **/
-               var_tempgeom geometry;
-               var_tempgeom2 geometry;
-               var_cent geometry;
-               var_geoms geometry[4]; /** We will cut the current geometry into 4 triangular quadrants along the centroid/extent **/
-               var_enline geometry;
-               var_resultgeom geometry;
-               var_atempgeoms geometry[];
-               var_buf float := 1; /**tolerance so that geometries that are right on the extent don't get accidentally clipped off **/
-       BEGIN
-               -- We start with convex hull as our base
-               var_resultgeom := var_convhull;
-               
-               IF param_pctconvex = 1 THEN
-                       return var_resultgeom;
-               ELSIF ST_GeometryType(var_param_geom) = 'ST_Polygon' THEN -- it is as concave as it is going to get
-                       IF param_allow_holes THEN -- leave the holes
-                               RETURN var_param_geom;
-                       ELSE -- remove the holes
-                               var_resultgeom := ST_MakePolygon(ST_ExteriorRing(var_param_geom));
-                               RETURN var_resultgeom;
-                       END IF;
-               END IF;
-               IF ST_Dimension(var_resultgeom) > 1 AND param_pctconvex BETWEEN 0 and 0.98 THEN
-               -- get linestring that forms envelope of geometry
-                       var_enline := ST_Boundary(ST_Envelope(var_param_geom));
-                       var_buf := ST_Length(var_enline)/1000.0;
-                       IF ST_GeometryType(var_param_geom) = 'ST_MultiPoint' AND ST_NumGeometries(var_param_geom) BETWEEN 4 and 200 THEN
-                       -- we make polygons out of points since they are easier to cave in. 
-                       -- Note we limit to between 4 and 200 points because this process is slow and gets quadratically slow
-                               var_buf := sqrt(ST_Area(var_convhull)*0.8/(ST_NumGeometries(var_param_geom)*ST_NumGeometries(var_param_geom)));
-                               var_atempgeoms := ARRAY(SELECT geom FROM ST_DumpPoints(var_param_geom));
-                               -- 5 and 10 and just fudge factors
-                               var_tempgeom := ST_Union(ARRAY(SELECT geom
-                                               FROM (
-                                               -- fuse near neighbors together
-                                               SELECT DISTINCT ON (i) i,  ST_Distance(var_atempgeoms[i],var_atempgeoms[j]), ST_Buffer(ST_MakeLine(var_atempgeoms[i], var_atempgeoms[j]) , var_buf*5, 'quad_segs=3') As geom
-                                                               FROM generate_series(1,array_upper(var_atempgeoms, 1)) As i
-                                                                       INNER JOIN generate_series(1,array_upper(var_atempgeoms, 1)) As j 
-                                                                               ON (
-                                                                NOT ST_Intersects(var_atempgeoms[i],var_atempgeoms[j])
-                                                                       AND ST_DWithin(var_atempgeoms[i],var_atempgeoms[j], var_buf*10)
-                                                                       )
-                                                               UNION ALL
-                                               -- catch the ones with no near neighbors
-                                                               SELECT i, 0, ST_Buffer(var_atempgeoms[i] , var_buf*10, 'quad_segs=3') As geom
-                                                               FROM generate_series(1,array_upper(var_atempgeoms, 1)) As i
-                                                                       LEFT JOIN generate_series(ceiling(array_upper(var_atempgeoms,1)/2)::integer,array_upper(var_atempgeoms, 1)) As j 
-                                                                               ON (
-                                                                NOT ST_Intersects(var_atempgeoms[i],var_atempgeoms[j])
-                                                                       AND ST_DWithin(var_atempgeoms[i],var_atempgeoms[j], var_buf*10) 
-                                                                       )
-                                                                       WHERE j IS NULL
-                                                               ORDER BY 1, 2
-                                                       ) As foo        ) );
-                               IF ST_IsValid(var_tempgeom) AND ST_GeometryType(var_tempgeom) = 'ST_Polygon' THEN
-                                       var_tempgeom := ST_Intersection(var_tempgeom, var_convhull);
-                                       IF param_allow_holes THEN
-                                               var_param_geom := var_tempgeom;
-                                       ELSE
-                                               var_param_geom := ST_MakePolygon(ST_ExteriorRing(var_tempgeom));
-                                       END IF;
-                                       return var_param_geom;
-                               ELSIF ST_IsValid(var_tempgeom) THEN
-                                       var_param_geom := ST_Intersection(var_tempgeom, var_convhull);  
-                               END IF;
-                       END IF;
-
-                       IF ST_GeometryType(var_param_geom) = 'ST_Polygon' THEN
-                               IF NOT param_allow_holes THEN
-                                       var_param_geom := ST_MakePolygon(ST_ExteriorRing(var_param_geom));
-                               END IF;
-                               return var_param_geom;
-                       END IF;
-            var_cent := ST_Centroid(var_param_geom);
-            IF (ST_XMax(var_enline) - ST_XMin(var_enline) ) > var_buf AND (ST_YMax(var_enline) - ST_YMin(var_enline) ) > var_buf THEN
-                    IF ST_Dwithin(ST_Centroid(var_convhull) , ST_Centroid(ST_Envelope(var_param_geom)), var_buf/2) THEN
-                -- If the geometric dimension is > 1 and the object is symettric (cutting at centroid will not work -- offset a bit)
-                        var_cent := ST_Translate(var_cent, (ST_XMax(var_enline) - ST_XMin(var_enline))/1000,  (ST_YMAX(var_enline) - ST_YMin(var_enline))/1000);
-                    ELSE
-                        -- uses closest point on geometry to centroid. I can't explain why we are doing this
-                        var_cent := ST_ClosestPoint(var_param_geom,var_cent);
-                    END IF;
-                    IF ST_DWithin(var_cent, var_enline,var_buf) THEN
-                        var_cent := ST_centroid(ST_Envelope(var_param_geom));
-                    END IF;
-                    -- break envelope into 4 triangles about the centroid of the geometry and returned the clipped geometry in each quadrant
-                    FOR i in 1 .. 4 LOOP
-                       var_geoms[i] := ST_MakePolygon(ST_MakeLine(ARRAY[ST_PointN(var_enline,i), ST_PointN(var_enline,i+1), var_cent, ST_PointN(var_enline,i)]));
-                       var_geoms[i] := ST_Intersection(var_param_geom, ST_Buffer(var_geoms[i],var_buf));
-                       IF ST_IsValid(var_geoms[i]) THEN 
-                            
-                       ELSE
-                            var_geoms[i] := ST_BuildArea(ST_MakeLine(ARRAY[ST_PointN(var_enline,i), ST_PointN(var_enline,i+1), var_cent, ST_PointN(var_enline,i)]));
-                       END IF; 
-                    END LOOP;
-                    var_tempgeom := ST_Union(ARRAY[ST_ConvexHull(var_geoms[1]), ST_ConvexHull(var_geoms[2]) , ST_ConvexHull(var_geoms[3]), ST_ConvexHull(var_geoms[4])]); 
-                    --RAISE NOTICE 'Curr vex % ', ST_AsText(var_tempgeom);
-                    IF ST_Area(var_tempgeom) <= var_newarea AND ST_IsValid(var_tempgeom)  THEN --AND ST_GeometryType(var_tempgeom) ILIKE '%Polygon'
-                        
-                        var_tempgeom := ST_Buffer(ST_ConcaveHull(var_geoms[1],least(param_pctconvex + param_pctconvex/var_div),true),var_buf, 'quad_segs=2');
-                        FOR i IN 1 .. 4 LOOP
-                            var_geoms[i] := ST_Buffer(ST_ConcaveHull(var_geoms[i],least(param_pctconvex + param_pctconvex/var_div),true), var_buf, 'quad_segs=2');
-                            IF ST_IsValid(var_geoms[i]) Then
-                                var_tempgeom := ST_Union(var_tempgeom, var_geoms[i]);
-                            ELSE
-                                RAISE NOTICE 'Not valid % %', i, ST_AsText(var_tempgeom);
-                                var_tempgeom := ST_Union(var_tempgeom, ST_ConvexHull(var_geoms[i]));
-                            END IF; 
-                        END LOOP;
-
-                        --RAISE NOTICE 'Curr concave % ', ST_AsText(var_tempgeom);
-                        IF ST_IsValid(var_tempgeom) THEN
-                            var_resultgeom := var_tempgeom;
-                        END IF;
-                        var_newarea := ST_Area(var_resultgeom);
-                    ELSIF ST_IsValid(var_tempgeom) THEN
-                        var_resultgeom := var_tempgeom;
-                    END IF;
-
-                    IF ST_NumGeometries(var_resultgeom) > 1  THEN
-                        var_tempgeom := _ST_ConcaveHull(var_resultgeom);
-                        IF ST_IsValid(var_tempgeom) AND ST_GeometryType(var_tempgeom) ILIKE 'ST_Polygon' THEN
-                            var_resultgeom := var_tempgeom;
-                        ELSE
-                            var_resultgeom := ST_Buffer(var_tempgeom,var_buf, 'quad_segs=2');
-                        END IF;
-                    END IF;
-                    IF param_allow_holes = false THEN 
-                    -- only keep exterior ring since we do not want holes
-                        var_resultgeom := ST_MakePolygon(ST_ExteriorRing(var_resultgeom));
-                    END IF;
-                ELSE
-                    var_resultgeom := ST_Buffer(var_resultgeom,var_buf);
-                END IF;
-                var_resultgeom := ST_Intersection(var_resultgeom, ST_ConvexHull(var_param_geom));
-            ELSE
-                -- dimensions are too small to cut
-                var_resultgeom := _ST_ConcaveHull(var_param_geom);
-            END IF;
-            RETURN var_resultgeom;
-       END;
-$$
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;
-
-CREATE OR REPLACE FUNCTION ST_ConcaveHull(param_geom geometry, param_pctconvex float)
-       RETURNS geometry AS
-$$
-       SELECT ST_ConcaveHull($1, $2, false);
-$$
-LANGUAGE 'sql' IMMUTABLE STRICT;
--- ST_ConcaveHull and Helper functions end here --
-COMMIT;
-
-#include "postgis_drop.sql.in.c"
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r
+--\r
+-- $Id$\r
+--\r
+-- PostGIS - Spatial Types for PostgreSQL\r
+-- http://postgis.refractions.net\r
+-- Copyright 2001-2003 Refractions Research Inc.\r
+--\r
+-- This is free software; you can redistribute and/or modify it under\r
+-- the terms of the GNU General Public Licence. See the COPYING file.\r
+--\r
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r
+--\r
+-- WARNING: Any change in this file must be evaluated for compatibility.\r
+--          Changes cleanly handled by postgis_upgrade.sql are fine,\r
+--         other changes will require a bump in Major version.\r
+--         Currently only function replaceble by CREATE OR REPLACE\r
+--         are cleanly handled.\r
+--\r
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+#include "sqldefines.h"\r
+\r
+SET client_min_messages TO warning;\r
+\r
+\r
+-- INSTALL VERSION: POSTGIS_LIB_VERSION\r
+\r
+BEGIN;\r
+\r
+-------------------------------------------------------------------\r
+--  SPHEROID TYPE\r
+-------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION spheroid_in(cstring)\r
+       RETURNS spheroid\r
+       AS 'MODULE_PATHNAME','ellipsoid_in'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION spheroid_out(spheroid)\r
+       RETURNS cstring\r
+       AS 'MODULE_PATHNAME','ellipsoid_out'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE TYPE spheroid (\r
+       alignment = double,\r
+       internallength = 65,\r
+       input = spheroid_in,\r
+       output = spheroid_out\r
+);\r
+\r
+-------------------------------------------------------------------\r
+--  GEOMETRY TYPE (lwgeom)\r
+-------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION geometry_in(cstring)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_in'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_out(geometry)\r
+       RETURNS cstring\r
+       AS 'MODULE_PATHNAME','LWGEOM_out'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_analyze(internal)\r
+       RETURNS bool\r
+#ifdef GSERIALIZED_ON\r
+       AS 'MODULE_PATHNAME', 'geometry_analyze'\r
+#else\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_analyze'\r
+#endif\r
+       LANGUAGE 'C' VOLATILE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_recv(internal)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_recv'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_send(geometry)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','LWGEOM_send'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE TYPE geometry (\r
+       internallength = variable,\r
+       input = geometry_in,\r
+       output = geometry_out,\r
+       send = geometry_send,\r
+       receive = geometry_recv,\r
+       delimiter = ':',\r
+       analyze = geometry_analyze,\r
+       storage = main\r
+);\r
+\r
+-------------------------------------------\r
+-- Affine transforms\r
+-------------------------------------------\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Affine(geometry,float8,float8,float8,float8,float8,float8,float8,float8,float8,float8,float8,float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_affine'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Affine(geometry,float8,float8,float8,float8,float8,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1,  $2, $3, 0,  $4, $5, 0,  0, 0, 1,  $6, $7, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_RotateZ(geometry,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1,  cos($2), -sin($2), 0,  sin($2), cos($2), 0,  0, 0, 1,  0, 0, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_RotateZ($1, $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_RotateX(geometry,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1, 1, 0, 0, 0, cos($2), -sin($2), 0, sin($2), cos($2), 0, 0, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_RotateY(geometry,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1,  cos($2), 0, sin($2),  0, 1, 0,  -sin($2), 0, cos($2), 0,  0, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Translate(geometry,float8,float8,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1, 1, 0, 0, 0, 1, 0, 0, 0, 1, $2, $3, $4)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Translate(geometry,float8,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Translate($1, $2, $3, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Scale(geometry,float8,float8,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1,  $2, 0, 0,  0, $3, 0,  0, 0, $4,  0, 0, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Scale(geometry,float8,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Scale($1, $2, $3, 1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Transscale(geometry,float8,float8,float8,float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_Affine($1,  $4, 0, 0,  0, $5, 0,\r
+               0, 0, 1,  $2 * $4, $3 * $5, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Shift_Longitude(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_longitude_shift'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-------------------------------------------------------------------\r
+--  BOX3D TYPE\r
+-------------------------------------------------------------------\r
+\r
+CREATE OR REPLACE FUNCTION box3d_in(cstring)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME', 'BOX3D_in'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box3d_out(box3d)\r
+       RETURNS cstring\r
+       AS 'MODULE_PATHNAME', 'BOX3D_out'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE TYPE box3d (\r
+       alignment = double,\r
+       internallength = 48,\r
+       input = box3d_in,\r
+       output = box3d_out\r
+);\r
+\r
+-- Temporary box3d aggregate type to retain full double precision\r
+-- for ST_Extent(). Should be removed when we change the output\r
+-- type of ST_Extent() to return something other than BOX2DFLOAT4.\r
+CREATE OR REPLACE FUNCTION box3d_extent_in(cstring)\r
+       RETURNS box3d_extent\r
+       AS 'MODULE_PATHNAME', 'BOX3D_in'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box3d_extent_out(box3d_extent)\r
+       RETURNS cstring\r
+       AS 'MODULE_PATHNAME', 'BOX3D_extent_out'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE TYPE box3d_extent (\r
+       alignment = double,\r
+       internallength = 48,\r
+       input = box3d_extent_in,\r
+       output = box3d_extent_out\r
+);\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION box3d_extent(box3d_extent)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME', 'BOX3D_extent_to_BOX3D'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry(box3d_extent)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','BOX3D_to_LWGEOM'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- End of temporary hack\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_XMin(box3d)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','BOX3D_xmin'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_YMin(box3d)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','BOX3D_ymin'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_ZMin(box3d)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','BOX3D_zmin'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_XMax(box3d)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','BOX3D_xmax'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_YMax(box3d)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','BOX3D_ymax'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_ZMax(box3d)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','BOX3D_zmax'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- BOX2D\r
+-----------------------------------------------------------------------\r
+\r
+CREATE OR REPLACE FUNCTION box2d_in(cstring)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME','BOX2DFLOAT4_in'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box2d_out(box2d)\r
+       RETURNS cstring\r
+       AS 'MODULE_PATHNAME','BOX2DFLOAT4_out'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE TYPE box2d (\r
+#ifdef GSERIALIZED_ON\r
+       internallength = 65,\r
+#else\r
+       internallength = 16,\r
+#endif\r
+       input = box2d_in,\r
+       output = box2d_out,\r
+       storage = plain\r
+);\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_expand(box2d,float8)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_expand'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION postgis_getbbox(geometry)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_BOX2DFLOAT4'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box2d(box3d_extent)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME', 'BOX3D_to_BOX2DFLOAT4'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION MakeBox2d(geometry, geometry)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_construct'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakeBox2d(geometry, geometry)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_construct'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Combine_BBox(box2d,geometry)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME', 'BOX2DFLOAT4_combine'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-----------------------------------------------------------------------\r
+-- ESTIMATED_EXTENT( <schema name>, <table name>, <column name> )\r
+-----------------------------------------------------------------------\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION estimated_extent(text,text,text) RETURNS box2d AS\r
+#ifdef GSERIALIZED_ON\r
+       'MODULE_PATHNAME', 'geometry_estimated_extent'\r
+#else\r
+       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'\r
+#endif\r
+       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text,text) RETURNS box2d AS\r
+#ifdef GSERIALIZED_ON\r
+       'MODULE_PATHNAME', 'geometry_estimated_extent'\r
+#else\r
+       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'\r
+#endif\r
+       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;\r
+\r
+-----------------------------------------------------------------------\r
+-- ESTIMATED_EXTENT( <table name>, <column name> )\r
+-----------------------------------------------------------------------\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION estimated_extent(text,text) RETURNS box2d AS\r
+#ifdef GSERIALIZED_ON\r
+       'MODULE_PATHNAME', 'geometry_estimated_extent'\r
+#else\r
+       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'\r
+#endif\r
+       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text) RETURNS box2d AS\r
+#ifdef GSERIALIZED_ON\r
+       'MODULE_PATHNAME', 'geometry_estimated_extent'\r
+#else\r
+       'MODULE_PATHNAME', 'LWGEOM_estimated_extent'\r
+#endif\r
+       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;\r
+\r
+-----------------------------------------------------------------------\r
+-- FIND_EXTENT( <schema name>, <table name>, <column name> )\r
+-----------------------------------------------------------------------\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION find_extent(text,text,text) RETURNS box2d AS\r
+$$\r
+DECLARE\r
+       schemaname alias for $1;\r
+       tablename alias for $2;\r
+       columnname alias for $3;\r
+       myrec RECORD;\r
+\r
+BEGIN\r
+       FOR myrec IN EXECUTE 'SELECT ST_Extent("' || columnname || '") FROM "' || schemaname || '"."' || tablename || '"' LOOP\r
+               return myrec.extent;\r
+       END LOOP;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_find_extent(text,text,text) RETURNS box2d AS\r
+$$\r
+DECLARE\r
+       schemaname alias for $1;\r
+       tablename alias for $2;\r
+       columnname alias for $3;\r
+       myrec RECORD;\r
+\r
+BEGIN\r
+       FOR myrec IN EXECUTE 'SELECT ST_Extent("' || columnname || '") FROM "' || schemaname || '"."' || tablename || '"' LOOP\r
+               return myrec.extent;\r
+       END LOOP;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+\r
+-----------------------------------------------------------------------\r
+-- FIND_EXTENT( <table name>, <column name> )\r
+-----------------------------------------------------------------------\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION find_extent(text,text) RETURNS box2d AS\r
+$$\r
+DECLARE\r
+       tablename alias for $1;\r
+       columnname alias for $2;\r
+       myrec RECORD;\r
+\r
+BEGIN\r
+       FOR myrec IN EXECUTE 'SELECT extent("' || columnname || '") FROM "' || tablename || '"' LOOP\r
+               return myrec.extent;\r
+       END LOOP;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_find_extent(text,text) RETURNS box2d AS\r
+$$\r
+DECLARE\r
+       tablename alias for $1;\r
+       columnname alias for $2;\r
+       myrec RECORD;\r
+\r
+BEGIN\r
+       FOR myrec IN EXECUTE 'SELECT extent("' || columnname || '") FROM "' || tablename || '"' LOOP\r
+               return myrec.extent;\r
+       END LOOP;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+-------------------------------------------------------------------\r
+-- BTREE indexes\r
+-------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION geometry_lt(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'lwgeom_lt'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_le(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'lwgeom_le'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_gt(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'lwgeom_gt'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_ge(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'lwgeom_ge'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_eq(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'lwgeom_eq'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_cmp(geometry, geometry)\r
+       RETURNS integer\r
+       AS 'MODULE_PATHNAME', 'lwgeom_cmp'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+--\r
+-- Sorting operators for Btree\r
+--\r
+\r
+CREATE OPERATOR < (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_lt,\r
+       COMMUTATOR = '>', NEGATOR = '>=',\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+\r
+CREATE OPERATOR <= (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_le,\r
+       COMMUTATOR = '>=', NEGATOR = '>',\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+\r
+CREATE OPERATOR = (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_eq,\r
+       COMMUTATOR = '=', -- we might implement a faster negator here\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+\r
+CREATE OPERATOR >= (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_ge,\r
+       COMMUTATOR = '<=', NEGATOR = '<',\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+CREATE OPERATOR > (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_gt,\r
+       COMMUTATOR = '<', NEGATOR = '<=',\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+\r
+\r
+CREATE OPERATOR CLASS btree_geometry_ops\r
+       DEFAULT FOR TYPE geometry USING btree AS\r
+       OPERATOR        1       < ,\r
+       OPERATOR        2       <= ,\r
+       OPERATOR        3       = ,\r
+       OPERATOR        4       >= ,\r
+       OPERATOR        5       > ,\r
+       FUNCTION        1       geometry_cmp (geometry, geometry);\r
+\r
+#ifndef GSERIALIZED_ON\r
+-------------------------------------------------------------------\r
+-- GiST indexes\r
+-------------------------------------------------------------------\r
+-- Deprecation in 1.5.0 -- is this deprecated? 2011-01-05 robe\r
+CREATE OR REPLACE FUNCTION geometry_same(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_samebox'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_gist_sel (internal, oid, internal, int4)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_gist_sel'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION geometry_gist_joinsel(internal, oid, internal, smallint)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_gist_joinsel'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION geometry_overleft(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_overleft'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_overright(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_overright'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_overabove(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_overabove'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_overbelow(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_overbelow'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_left(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_left'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_right(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_right'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_above(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_above'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_below(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_below'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_contain(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_contain'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_contained(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_contained'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_overlap(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_overlap'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry_samebox(geometry, geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_samebox'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OPERATOR << (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_left,\r
+       COMMUTATOR = '>>',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR &< (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overleft,\r
+       COMMUTATOR = '&>',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR <<| (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_below,\r
+       COMMUTATOR = '|>>',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR &<| (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overbelow,\r
+       COMMUTATOR = '|&>',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR && (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overlap,\r
+       COMMUTATOR = '&&',\r
+       RESTRICT = geometry_gist_sel, JOIN = geometry_gist_joinsel\r
+);\r
+\r
+CREATE OPERATOR &> (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overright,\r
+       COMMUTATOR = '&<',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR >> (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_right,\r
+       COMMUTATOR = '<<',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR |&> (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overabove,\r
+       COMMUTATOR = '&<|',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR |>> (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_above,\r
+       COMMUTATOR = '<<|',\r
+       RESTRICT = positionsel, JOIN = positionjoinsel\r
+);\r
+\r
+CREATE OPERATOR ~= (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_samebox,\r
+       COMMUTATOR = '~=',\r
+       RESTRICT = eqsel, JOIN = eqjoinsel\r
+);\r
+\r
+CREATE OPERATOR @ (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_contained,\r
+       COMMUTATOR = '~',\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+\r
+CREATE OPERATOR ~ (\r
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_contain,\r
+       COMMUTATOR = '@',\r
+       RESTRICT = contsel, JOIN = contjoinsel\r
+);\r
+\r
+-- gist support functions\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_consistent(internal,geometry,int4)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_consistent'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_compress(internal)\r
+       RETURNS internal\r
+       AS 'MODULE_PATHNAME','LWGEOM_gist_compress'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_penalty(internal,internal,internal)\r
+       RETURNS internal\r
+       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_penalty'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_picksplit(internal, internal)\r
+       RETURNS internal\r
+       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_picksplit'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_union(bytea, internal)\r
+       RETURNS internal\r
+       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_union'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_same(box2d, box2d, internal)\r
+       RETURNS internal\r
+       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_same'\r
+       LANGUAGE 'C';\r
+\r
+CREATE OR REPLACE FUNCTION LWGEOM_gist_decompress(internal)\r
+       RETURNS internal\r
+       AS 'MODULE_PATHNAME' ,'LWGEOM_gist_decompress'\r
+       LANGUAGE 'C';\r
+\r
+-------------------------------------------\r
+-- GIST opclass index binding entries.\r
+-------------------------------------------\r
+--\r
+-- Create opclass index bindings for PG>=73\r
+--\r
+\r
+CREATE OPERATOR CLASS gist_geometry_ops\r
+       DEFAULT FOR TYPE geometry USING gist AS\r
+       STORAGE         box2d,\r
+       OPERATOR        1        << ,\r
+       OPERATOR        2        &<     ,\r
+       OPERATOR        3        &&     ,\r
+       OPERATOR        4        &>     ,\r
+       OPERATOR        5        >>     ,\r
+       OPERATOR        6        ~=     ,\r
+       OPERATOR        7        ~      ,\r
+       OPERATOR        8        @      ,\r
+       OPERATOR        9        &<|    ,\r
+       OPERATOR        10       <<|    ,\r
+       OPERATOR        11       |>>    ,\r
+       OPERATOR        12       |&>    ,\r
+       FUNCTION        1        LWGEOM_gist_consistent (internal, geometry, int4),\r
+       FUNCTION        2        LWGEOM_gist_union (bytea, internal),\r
+       FUNCTION        3        LWGEOM_gist_compress (internal),\r
+       FUNCTION        4        LWGEOM_gist_decompress (internal),\r
+       FUNCTION        5        LWGEOM_gist_penalty (internal, internal, internal),\r
+       FUNCTION        6        LWGEOM_gist_picksplit (internal, internal),\r
+       FUNCTION        7        LWGEOM_gist_same (box2d, box2d, internal);\r
+\r
+#endif\r
+\r
+-------------------------------------------\r
+-- other lwgeom functions\r
+-------------------------------------------\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION postgis_addbbox(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_addBBOX'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION postgis_dropbbox(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_dropBBOX'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION getsrid(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME','LWGEOM_get_srid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION postgis_hasbbox(geometry)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_hasBBOX'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+------------------------------------------------------------------------\r
+-- DEBUG\r
+------------------------------------------------------------------------\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_mem_size(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_mem_size'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_summary(geometry)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_summary'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Npoints(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_npoints'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_nrings(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_nrings'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+------------------------------------------------------------------------\r
+-- Misures\r
+------------------------------------------------------------------------\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Length3d(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_length_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Length2d(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_length2d_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: length2d(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Length(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_length2d_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- this is a fake (for back-compatibility)\r
+-- uses 3d if 3d is available, 2d otherwise\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_length3d_spheroid(geometry, spheroid)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','LWGEOM_length_ellipsoid_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_length_spheroid(geometry, spheroid)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','LWGEOM_length_ellipsoid_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_length2d_spheroid(geometry, spheroid)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','LWGEOM_length2d_ellipsoid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_perimeter3d(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_perimeter_poly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_perimeter2d(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_perimeter2d_poly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: perimeter2d(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Perimeter(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_perimeter2d_poly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+-- Deprecation in 1.3.4\r
+CREATE OR REPLACE FUNCTION ST_area2d(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_area_polygon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: area(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Area(geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','LWGEOM_area_polygon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_distance_spheroid(geometry,geometry,spheroid)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','LWGEOM_distance_ellipsoid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_distance_sphere(geometry,geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME','LWGEOM_distance_sphere'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Minimum distance. 2d only.\r
+\r
+-- PostGIS equivalent function: distance(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION ST_Distance(geometry,geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_mindistance2d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_point_inside_circle(geometry,float8,float8,float8)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_inside_circle_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_azimuth(geometry,geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_azimuth'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+------------------------------------------------------------------------\r
+-- MISC\r
+------------------------------------------------------------------------\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_force_2d(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_2d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_force_3dz(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_3dz'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_force_3d(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_3dz'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_force_3dm(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_3dm'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_force_4d(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_4d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_force_collection(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_collection'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_CollectionExtract(geometry, integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_CollectionExtract'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Multi(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_multi'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Expand(box3d,float8)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME', 'BOX3D_expand'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Expand(geometry,float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_expand'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: envelope(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Envelope(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_envelope'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Reverse(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_reverse'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_ForceRHR(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_force_clockwise_poly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION postgis_noop(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_noop'\r
+       LANGUAGE 'C' VOLATILE STRICT;\r
+       \r
+-- Deprecation in 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_zmflag(geometry)\r
+       RETURNS smallint\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_zmflag'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_NDims(geometry)\r
+       RETURNS smallint\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_ndims'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsEWKT(geometry)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asEWKT'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsEWKB(geometry)\r
+       RETURNS BYTEA\r
+       AS 'MODULE_PATHNAME','WKBFromLWGEOM'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsHEXEWKB(geometry)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asHEXEWKB'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsHEXEWKB(geometry, text)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asHEXEWKB'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsEWKB(geometry,text)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','WKBFromLWGEOM'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_AsLatLonText(geometry, text)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_latlon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_AsLatLonText(geometry)\r
+       RETURNS text\r
+       AS $$ SELECT ST_AsLatLonText($1, '') $$\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeomFromEWKB(bytea)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOMFromWKB'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomFromEWKB(bytea)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOMFromWKB'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeomFromEWKT(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','parse_WKT_lwgeom'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomFromEWKT(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','parse_WKT_lwgeom'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION postgis_cache_bbox()\r
+       RETURNS trigger\r
+       AS 'MODULE_PATHNAME', 'cache_bbox'\r
+       LANGUAGE 'C';\r
+\r
+------------------------------------------------------------------------\r
+-- CONSTRUCTORS\r
+------------------------------------------------------------------------\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakePoint(float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakePoint(float8, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakePoint(float8, float8, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.3.4\r
+CREATE OR REPLACE FUNCTION ST_MakePointM(float8, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint3dm'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakeBox3d(geometry, geometry)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME', 'BOX3D_construct'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_MakeLine (geometry[])\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makeline_garray'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_LineFromMultiPoint(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_line_from_mpoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+       \r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakeLine(geometry, geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makeline'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AddPoint(geometry, geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_addpoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AddPoint(geometry, geometry, integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_addpoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_RemovePoint(geometry, integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_removepoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_SetPoint(geometry, integer, geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_setpoint_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_MakeEnvelope(float8, float8, float8, float8, integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_MakeEnvelope'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakePolygon(geometry, geometry[])\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MakePolygon(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_BuildArea(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_buildarea'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_Polygonize (geometry[])\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'polygonize_garray'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_LineMerge(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'linemerge'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+\r
+CREATE TYPE geometry_dump AS (path integer[], geom geometry);\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION Dump(geometry)\r
+       RETURNS SETOF geometry_dump\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dump'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Dump(geometry)\r
+       RETURNS SETOF geometry_dump\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dump'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_DumpRings(geometry)\r
+       RETURNS SETOF geometry_dump\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dump_rings'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- _ST_DumpPoints()\r
+-----------------------------------------------------------------------\r
+-- A helper function for ST_DumpPoints(geom)\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION _ST_DumpPoints(the_geom geometry, cur_path integer[]) RETURNS SETOF geometry_dump AS $$\r
+DECLARE\r
+  tmp geometry_dump;\r
+  tmp2 geometry_dump;\r
+  nb_points integer;\r
+  nb_geom integer;\r
+  i integer;\r
+  j integer;\r
+  g geometry;\r
+  \r
+BEGIN\r
+  \r
+  RAISE DEBUG '%,%', cur_path, ST_GeometryType(the_geom);\r
+\r
+  -- Special case collections : iterate and return the DumpPoints of the geometries\r
+\r
+  IF (ST_IsCollection(the_geom)) THEN\r
\r
+    i = 1;\r
+    FOR tmp2 IN SELECT (ST_Dump(the_geom)).* LOOP\r
+\r
+      FOR tmp IN SELECT * FROM _ST_DumpPoints(tmp2.geom, cur_path || tmp2.path) LOOP\r
+           RETURN NEXT tmp;\r
+      END LOOP;\r
+      i = i + 1;\r
+      \r
+    END LOOP;\r
+\r
+    RETURN;\r
+  END IF;\r
+  \r
+\r
+  -- Special case (POLYGON) : return the points of the rings of a polygon\r
+  IF (ST_GeometryType(the_geom) = 'ST_Polygon') THEN\r
+\r
+    FOR tmp IN SELECT * FROM _ST_DumpPoints(ST_ExteriorRing(the_geom), cur_path || ARRAY[1]) LOOP\r
+      RETURN NEXT tmp;\r
+    END LOOP;\r
+    \r
+    j := ST_NumInteriorRings(the_geom);\r
+    FOR i IN 1..j LOOP\r
+        FOR tmp IN SELECT * FROM _ST_DumpPoints(ST_InteriorRingN(the_geom, i), cur_path || ARRAY[i+1]) LOOP\r
+          RETURN NEXT tmp;\r
+        END LOOP;\r
+    END LOOP;\r
+    \r
+    RETURN;\r
+  END IF;\r
+\r
+  -- Special case (TRIANGLE) : return the points of the external rings of a TRIANGLE\r
+  IF (ST_GeometryType(the_geom) = 'ST_Triangle') THEN\r
+\r
+    FOR tmp IN SELECT * FROM _ST_DumpPoints(ST_ExteriorRing(the_geom), cur_path || ARRAY[1]) LOOP\r
+      RETURN NEXT tmp;\r
+    END LOOP;\r
+    \r
+    RETURN;\r
+  END IF;\r
+\r
+    \r
+  -- Special case (POINT) : return the point\r
+  IF (ST_GeometryType(the_geom) = 'ST_Point') THEN\r
+\r
+    tmp.path = cur_path || ARRAY[1];\r
+    tmp.geom = the_geom;\r
+\r
+    RETURN NEXT tmp;\r
+    RETURN;\r
+\r
+  END IF;\r
+\r
+\r
+  -- Use ST_NumPoints rather than ST_NPoints to have a NULL value if the_geom isn't\r
+  -- a LINESTRING, CIRCULARSTRING.\r
+  SELECT ST_NumPoints(the_geom) INTO nb_points;\r
+\r
+  -- This should never happen\r
+  IF (nb_points IS NULL) THEN\r
+    RAISE EXCEPTION 'Unexpected error while dumping geometry %', ST_AsText(the_geom);\r
+  END IF;\r
+\r
+  FOR i IN 1..nb_points LOOP\r
+    tmp.path = cur_path || ARRAY[i];\r
+    tmp.geom := ST_PointN(the_geom, i);\r
+    RETURN NEXT tmp;\r
+  END LOOP;\r
+   \r
+END\r
+$$ LANGUAGE plpgsql;\r
+\r
+-----------------------------------------------------------------------\r
+-- ST_DumpPoints()\r
+-----------------------------------------------------------------------\r
+-- This function mimicks that of ST_Dump for collections, but this function \r
+-- that returns a path and all the points that make up a particular geometry.\r
+-- This current implementation in plpgsql does not scale very well at all.\r
+-- and should be ported to C at some point.\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_DumpPoints(geometry) RETURNS SETOF geometry_dump AS $$\r
+  SELECT * FROM _ST_DumpPoints($1, NULL);\r
+$$ LANGUAGE SQL;\r
+\r
+\r
+------------------------------------------------------------------------\r
+\r
+--\r
+-- Aggregate functions\r
+--\r
+\r
+\r
+-- Temporary hack function\r
+CREATE OR REPLACE FUNCTION combine_bbox(box3d_extent,geometry)\r
+       RETURNS box3d_extent\r
+       AS 'MODULE_PATHNAME', 'BOX3D_combine'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-- Temporary hack function\r
+CREATE OR REPLACE FUNCTION ST_Combine_BBox(box3d_extent,geometry)\r
+       RETURNS box3d_extent\r
+       AS 'MODULE_PATHNAME', 'BOX3D_combine'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE AGGREGATE Extent(\r
+       sfunc = ST_combine_bbox,\r
+       basetype = geometry,\r
+       stype = box3d_extent\r
+       );\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_Extent(\r
+       sfunc = ST_combine_bbox,\r
+       basetype = geometry,\r
+       stype = box3d_extent\r
+       );\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Combine_BBox(box3d,geometry)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME', 'BOX3D_combine'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_Extent3d(\r
+       sfunc = ST_combine_bbox,\r
+       basetype = geometry,\r
+       stype = box3d\r
+       );\r
+\r
+\r
+\r
+-------------------------------------------------------------------\r
+-- SPATIAL_REF_SYS\r
+-------------------------------------------------------------------\r
+CREATE TABLE spatial_ref_sys (\r
+        srid integer not null primary key,\r
+        auth_name varchar(256),\r
+        auth_srid integer,\r
+        srtext varchar(2048),\r
+        proj4text varchar(2048)\r
+);\r
+\r
+-------------------------------------------------------------------\r
+-- GEOMETRY_COLUMNS\r
+-------------------------------------------------------------------\r
+CREATE TABLE geometry_columns (\r
+       f_table_catalog varchar(256) not null,\r
+       f_table_schema varchar(256) not null,\r
+       f_table_name varchar(256) not null,\r
+       f_geometry_column varchar(256) not null,\r
+       coord_dimension integer not null,\r
+       srid integer not null,\r
+       type varchar(30) not null,\r
+       CONSTRAINT geometry_columns_pk primary key (\r
+               f_table_catalog,\r
+               f_table_schema,\r
+               f_table_name,\r
+               f_geometry_column )\r
+) WITH OIDS;\r
+\r
+-----------------------------------------------------------------------\r
+-- RENAME_GEOMETRY_TABLE_CONSTRAINTS()\r
+-----------------------------------------------------------------------\r
+-- This function has been obsoleted for the difficulty in\r
+-- finding attribute on which the constraint is applied.\r
+-- AddGeometryColumn will name the constraints in a meaningful\r
+-- way, but nobody can rely on it since old postgis versions did\r
+-- not do that.\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION rename_geometry_table_constraints() RETURNS text\r
+AS\r
+$$\r
+SELECT 'rename_geometry_table_constraint() is obsoleted'::text\r
+$$\r
+LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-----------------------------------------------------------------------\r
+-- FIX_GEOMETRY_COLUMNS()\r
+-----------------------------------------------------------------------\r
+-- This function will:\r
+--\r
+--     o try to fix the schema of records with an integer one\r
+--             (for PG>=73)\r
+--\r
+--     o link records to system tables through attrelid and varattnum\r
+--             (for PG<75)\r
+--\r
+--     o delete all records for which no linking was possible\r
+--             (for PG<75)\r
+--\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION fix_geometry_columns() RETURNS text\r
+AS\r
+$$\r
+DECLARE\r
+       mislinked record;\r
+       result text;\r
+       linked integer;\r
+       deleted integer;\r
+       foundschema integer;\r
+BEGIN\r
+\r
+       -- Since 7.3 schema support has been added.\r
+       -- Previous postgis versions used to put the database name in\r
+       -- the schema column. This needs to be fixed, so we try to\r
+       -- set the correct schema for each geometry_colums record\r
+       -- looking at table, column, type and srid.\r
+       UPDATE geometry_columns SET f_table_schema = n.nspname\r
+               FROM pg_namespace n, pg_class c, pg_attribute a,\r
+                       pg_constraint sridcheck, pg_constraint typecheck\r
+                       WHERE ( f_table_schema is NULL\r
+               OR f_table_schema = ''\r
+                       OR f_table_schema NOT IN (\r
+                                       SELECT nspname::varchar\r
+                                       FROM pg_namespace nn, pg_class cc, pg_attribute aa\r
+                                       WHERE cc.relnamespace = nn.oid\r
+                                       AND cc.relname = f_table_name::name\r
+                                       AND aa.attrelid = cc.oid\r
+                                       AND aa.attname = f_geometry_column::name))\r
+                       AND f_table_name::name = c.relname\r
+                       AND c.oid = a.attrelid\r
+                       AND c.relnamespace = n.oid\r
+                       AND f_geometry_column::name = a.attname\r
+\r
+                       AND sridcheck.conrelid = c.oid\r
+               AND sridcheck.consrc LIKE '(%srid(% = %)'\r
+                       AND sridcheck.consrc ~ textcat(' = ', srid::text)\r
+\r
+                       AND typecheck.conrelid = c.oid\r
+               AND typecheck.consrc LIKE\r
+               '((geometrytype(%) = ''%''::text) OR (% IS NULL))'\r
+                       AND typecheck.consrc ~ textcat(' = ''', type::text)\r
+\r
+                       AND NOT EXISTS (\r
+                                       SELECT oid FROM geometry_columns gc\r
+                                       WHERE c.relname::varchar = gc.f_table_name\r
+                                       AND n.nspname::varchar = gc.f_table_schema\r
+                                       AND a.attname::varchar = gc.f_geometry_column\r
+                       );\r
+\r
+       GET DIAGNOSTICS foundschema = ROW_COUNT;\r
+\r
+       -- no linkage to system table needed\r
+       return 'fixed:'||foundschema::text;\r
+\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE;\r
+\r
+-----------------------------------------------------------------------\r
+-- POPULATE_GEOMETRY_COLUMNS()\r
+-----------------------------------------------------------------------\r
+-- Truncates and refills the geometry_columns table from all tables and\r
+-- views in the database that contain geometry columns. This function\r
+-- is a simple wrapper for populate_geometry_columns(oid).  In essence,\r
+-- this function ensures every geometry column in the database has the\r
+-- appropriate spatial contraints (for tables) and exists in the\r
+-- geometry_columns table.\r
+-- Availability: 1.4.0\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION populate_geometry_columns()\r
+       RETURNS text AS\r
+$$\r
+DECLARE\r
+       inserted    integer;\r
+       oldcount    integer;\r
+       probed      integer;\r
+       stale       integer;\r
+       gcs         RECORD;\r
+       gc          RECORD;\r
+       gsrid       integer;\r
+       gndims      integer;\r
+       gtype       text;\r
+       query       text;\r
+       gc_is_valid boolean;\r
+\r
+BEGIN\r
+       SELECT count(*) INTO oldcount FROM geometry_columns;\r
+       inserted := 0;\r
+\r
+       EXECUTE 'TRUNCATE geometry_columns';\r
+\r
+       -- Count the number of geometry columns in all tables and views\r
+       SELECT count(DISTINCT c.oid) INTO probed\r
+       FROM pg_class c,\r
+                pg_attribute a,\r
+                pg_type t,\r
+                pg_namespace n\r
+       WHERE (c.relkind = 'r' OR c.relkind = 'v')\r
+       AND t.typname = 'geometry'\r
+       AND a.attisdropped = false\r
+       AND a.atttypid = t.oid\r
+       AND a.attrelid = c.oid\r
+       AND c.relnamespace = n.oid\r
+       AND n.nspname NOT ILIKE 'pg_temp%';\r
+\r
+       -- Iterate through all non-dropped geometry columns\r
+       RAISE DEBUG 'Processing Tables.....';\r
+\r
+       FOR gcs IN\r
+       SELECT DISTINCT ON (c.oid) c.oid, n.nspname, c.relname\r
+               FROM pg_class c,\r
+                        pg_attribute a,\r
+                        pg_type t,\r
+                        pg_namespace n\r
+               WHERE c.relkind = 'r'\r
+               AND t.typname = 'geometry'\r
+               AND a.attisdropped = false\r
+               AND a.atttypid = t.oid\r
+               AND a.attrelid = c.oid\r
+               AND c.relnamespace = n.oid\r
+               AND n.nspname NOT ILIKE 'pg_temp%'\r
+       LOOP\r
+\r
+       inserted := inserted + populate_geometry_columns(gcs.oid);\r
+       END LOOP;\r
+\r
+       -- Add views to geometry columns table\r
+       RAISE DEBUG 'Processing Views.....';\r
+       FOR gcs IN\r
+       SELECT DISTINCT ON (c.oid) c.oid, n.nspname, c.relname\r
+               FROM pg_class c,\r
+                        pg_attribute a,\r
+                        pg_type t,\r
+                        pg_namespace n\r
+               WHERE c.relkind = 'v'\r
+               AND t.typname = 'geometry'\r
+               AND a.attisdropped = false\r
+               AND a.atttypid = t.oid\r
+               AND a.attrelid = c.oid\r
+               AND c.relnamespace = n.oid\r
+       LOOP\r
+\r
+       inserted := inserted + populate_geometry_columns(gcs.oid);\r
+       END LOOP;\r
+\r
+       IF oldcount > inserted THEN\r
+       stale = oldcount-inserted;\r
+       ELSE\r
+       stale = 0;\r
+       END IF;\r
+\r
+       RETURN 'probed:' ||probed|| ' inserted:'||inserted|| ' conflicts:'||probed-inserted|| ' deleted:'||stale;\r
+END\r
+\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE;\r
+\r
+-----------------------------------------------------------------------\r
+-- POPULATE_GEOMETRY_COLUMNS(tbl_oid oid)\r
+-----------------------------------------------------------------------\r
+-- DELETEs from and reINSERTs into the geometry_columns table all entries\r
+-- associated with the oid of a particular table or view.\r
+--\r
+-- If the provided oid is for a table, this function tries to determine\r
+-- the srid, dimension, and geometry type of the all geometries\r
+-- in the table, adding contraints as necessary to the table.  If\r
+-- successful, an appropriate row is inserted into the geometry_columns\r
+-- table, otherwise, the exception is caught and an error notice is\r
+-- raised describing the problem. (This is so the wrapper function\r
+-- populate_geometry_columns() can apply spatial constraints to all\r
+-- geometry columns across an entire database at once without erroring\r
+-- out)\r
+--\r
+-- If the provided oid is for a view, as with a table oid, this function\r
+-- tries to determine the srid, dimension, and type of all the geometries\r
+-- in the view, inserting appropriate entries into the geometry_columns\r
+-- table.\r
+-- Availability: 1.4.0\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION populate_geometry_columns(tbl_oid oid)\r
+       RETURNS integer AS\r
+$$\r
+DECLARE\r
+       gcs         RECORD;\r
+       gc          RECORD;\r
+       gsrid       integer;\r
+       gndims      integer;\r
+       gtype       text;\r
+       query       text;\r
+       gc_is_valid boolean;\r
+       inserted    integer;\r
+\r
+BEGIN\r
+       inserted := 0;\r
+\r
+       -- Iterate through all geometry columns in this table\r
+       FOR gcs IN\r
+       SELECT n.nspname, c.relname, a.attname\r
+               FROM pg_class c,\r
+                        pg_attribute a,\r
+                        pg_type t,\r
+                        pg_namespace n\r
+               WHERE c.relkind = 'r'\r
+               AND t.typname = 'geometry'\r
+               AND a.attisdropped = false\r
+               AND a.atttypid = t.oid\r
+               AND a.attrelid = c.oid\r
+               AND c.relnamespace = n.oid\r
+               AND n.nspname NOT ILIKE 'pg_temp%'\r
+               AND c.oid = tbl_oid\r
+       LOOP\r
+\r
+       RAISE DEBUG 'Processing table %.%.%', gcs.nspname, gcs.relname, gcs.attname;\r
+\r
+       DELETE FROM geometry_columns\r
+         WHERE f_table_schema = quote_ident(gcs.nspname)\r
+         AND f_table_name = quote_ident(gcs.relname)\r
+         AND f_geometry_column = quote_ident(gcs.attname);\r
+\r
+       gc_is_valid := true;\r
+\r
+       -- Try to find srid check from system tables (pg_constraint)\r
+       gsrid :=\r
+               (SELECT replace(replace(split_part(s.consrc, ' = ', 2), ')', ''), '(', '')\r
+                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s\r
+                WHERE n.nspname = gcs.nspname\r
+                AND c.relname = gcs.relname\r
+                AND a.attname = gcs.attname\r
+                AND a.attrelid = c.oid\r
+                AND s.connamespace = n.oid\r
+                AND s.conrelid = c.oid\r
+                AND a.attnum = ANY (s.conkey)\r
+                AND s.consrc LIKE '%srid(% = %');\r
+       IF (gsrid IS NULL) THEN\r
+               -- Try to find srid from the geometry itself\r
+               EXECUTE 'SELECT st_srid(' || quote_ident(gcs.attname) || ') As srid\r
+                                FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'\r
+                       INTO gc;\r
+               gsrid := gc.srid;\r
+\r
+               -- Try to apply srid check to column\r
+               IF (gsrid IS NOT NULL) THEN\r
+                       BEGIN\r
+                               EXECUTE 'ALTER TABLE ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                                ADD CONSTRAINT ' || quote_ident('enforce_srid_' || gcs.attname) || '\r
+                                                CHECK (st_srid(' || quote_ident(gcs.attname) || ') = ' || gsrid || ')';\r
+                       EXCEPTION\r
+                               WHEN check_violation THEN\r
+                                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not apply constraint CHECK (st_srid(%) = %)', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname), quote_ident(gcs.attname), gsrid;\r
+                                       gc_is_valid := false;\r
+                       END;\r
+               END IF;\r
+       END IF;\r
+\r
+       -- Try to find ndims check from system tables (pg_constraint)\r
+       gndims :=\r
+               (SELECT replace(split_part(s.consrc, ' = ', 2), ')', '')\r
+                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s\r
+                WHERE n.nspname = gcs.nspname\r
+                AND c.relname = gcs.relname\r
+                AND a.attname = gcs.attname\r
+                AND a.attrelid = c.oid\r
+                AND s.connamespace = n.oid\r
+                AND s.conrelid = c.oid\r
+                AND a.attnum = ANY (s.conkey)\r
+                AND s.consrc LIKE '%ndims(% = %');\r
+       IF (gndims IS NULL) THEN\r
+               -- Try to find ndims from the geometry itself\r
+               EXECUTE 'SELECT st_ndims(' || quote_ident(gcs.attname) || ') As ndims\r
+                                FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'\r
+                       INTO gc;\r
+               gndims := gc.ndims;\r
+\r
+               -- Try to apply ndims check to column\r
+               IF (gndims IS NOT NULL) THEN\r
+                       BEGIN\r
+                               EXECUTE 'ALTER TABLE ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                                ADD CONSTRAINT ' || quote_ident('enforce_dims_' || gcs.attname) || '\r
+                                                CHECK (st_ndims(' || quote_ident(gcs.attname) || ') = '||gndims||')';\r
+                       EXCEPTION\r
+                               WHEN check_violation THEN\r
+                                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not apply constraint CHECK (st_ndims(%) = %)', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname), quote_ident(gcs.attname), gndims;\r
+                                       gc_is_valid := false;\r
+                       END;\r
+               END IF;\r
+       END IF;\r
+\r
+       -- Try to find geotype check from system tables (pg_constraint)\r
+       gtype :=\r
+               (SELECT replace(split_part(s.consrc, '''', 2), ')', '')\r
+                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s\r
+                WHERE n.nspname = gcs.nspname\r
+                AND c.relname = gcs.relname\r
+                AND a.attname = gcs.attname\r
+                AND a.attrelid = c.oid\r
+                AND s.connamespace = n.oid\r
+                AND s.conrelid = c.oid\r
+                AND a.attnum = ANY (s.conkey)\r
+                AND s.consrc LIKE '%geometrytype(% = %');\r
+       IF (gtype IS NULL) THEN\r
+               -- Try to find geotype from the geometry itself\r
+               EXECUTE 'SELECT geometrytype(' || quote_ident(gcs.attname) || ')\r
+                                FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'\r
+                       INTO gc;\r
+               gtype := gc.geometrytype;\r
+               --IF (gtype IS NULL) THEN\r
+               --    gtype := 'GEOMETRY';\r
+               --END IF;\r
+\r
+               -- Try to apply geometrytype check to column\r
+               IF (gtype IS NOT NULL) THEN\r
+                       BEGIN\r
+                               EXECUTE 'ALTER TABLE ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                               ADD CONSTRAINT ' || quote_ident('enforce_geotype_' || gcs.attname) || '\r
+                               CHECK ((geometrytype(' || quote_ident(gcs.attname) || ') = ' || quote_literal(gtype) || ') OR (' || quote_ident(gcs.attname) || ' IS NULL))';\r
+                       EXCEPTION\r
+                               WHEN check_violation THEN\r
+                                       -- No geometry check can be applied. This column contains a number of geometry types.\r
+                                       RAISE WARNING 'Could not add geometry type check (%) to table column: %.%.%', gtype, quote_ident(gcs.nspname),quote_ident(gcs.relname),quote_ident(gcs.attname);\r
+                       END;\r
+               END IF;\r
+       END IF;\r
+\r
+       IF (gsrid IS NULL) THEN\r
+               RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine the srid', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);\r
+       ELSIF (gndims IS NULL) THEN\r
+               RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine the number of dimensions', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);\r
+       ELSIF (gtype IS NULL) THEN\r
+               RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine the geometry type', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);\r
+       ELSE\r
+               -- Only insert into geometry_columns if table constraints could be applied.\r
+               IF (gc_is_valid) THEN\r
+                       INSERT INTO geometry_columns (f_table_catalog,f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, type)\r
+                       VALUES ('', gcs.nspname, gcs.relname, gcs.attname, gndims, gsrid, gtype);\r
+                       inserted := inserted + 1;\r
+               END IF;\r
+       END IF;\r
+       END LOOP;\r
+\r
+       -- Add views to geometry columns table\r
+       FOR gcs IN\r
+       SELECT n.nspname, c.relname, a.attname\r
+               FROM pg_class c,\r
+                        pg_attribute a,\r
+                        pg_type t,\r
+                        pg_namespace n\r
+               WHERE c.relkind = 'v'\r
+               AND t.typname = 'geometry'\r
+               AND a.attisdropped = false\r
+               AND a.atttypid = t.oid\r
+               AND a.attrelid = c.oid\r
+               AND c.relnamespace = n.oid\r
+               AND n.nspname NOT ILIKE 'pg_temp%'\r
+               AND c.oid = tbl_oid\r
+       LOOP\r
+               RAISE DEBUG 'Processing view %.%.%', gcs.nspname, gcs.relname, gcs.attname;\r
+\r
+               EXECUTE 'SELECT st_ndims(' || quote_ident(gcs.attname) || ') As ndims\r
+                                FROM ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'\r
+                       INTO gc;\r
+               gndims := gc.ndims;\r
+\r
+               EXECUTE 'SELECT st_srid(' || quote_ident(gcs.attname) || ') As srid\r
+                                FROM ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'\r
+                       INTO gc;\r
+               gsrid := gc.srid;\r
+\r
+               EXECUTE 'SELECT geometrytype(' || quote_ident(gcs.attname) || ')\r
+                                FROM ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || '\r
+                                WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1'\r
+                       INTO gc;\r
+               gtype := gc.geometrytype;\r
+\r
+               IF (gndims IS NULL) THEN\r
+                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine ndims', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);\r
+               ELSIF (gsrid IS NULL) THEN\r
+                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine srid', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);\r
+               ELSIF (gtype IS NULL) THEN\r
+                       RAISE WARNING 'Not inserting ''%'' in ''%.%'' into geometry_columns: could not determine gtype', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname);\r
+               ELSE\r
+                       query := 'INSERT INTO geometry_columns (f_table_catalog,f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, type) ' ||\r
+                                        'VALUES ('''', ' || quote_literal(gcs.nspname) || ',' || quote_literal(gcs.relname) || ',' || quote_literal(gcs.attname) || ',' || gndims || ',' || gsrid || ',' || quote_literal(gtype) || ')';\r
+                       EXECUTE query;\r
+                       inserted := inserted + 1;\r
+               END IF;\r
+       END LOOP;\r
+\r
+       RETURN inserted;\r
+END\r
+\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE;\r
+\r
+\r
+-----------------------------------------------------------------------\r
+-- PROBE_GEOMETRY_COLUMNS()\r
+-----------------------------------------------------------------------\r
+-- Fill the geometry_columns table with values probed from the system\r
+-- catalogues. This is done by simply looking up constraints previously\r
+-- added to a geometry column. If geometry constraints are missing, no\r
+-- attempt is made to add the necessary constraints to the geometry\r
+-- column, nor is it recorded in the geometry_columns table.\r
+-- 3d flag cannot be probed, it defaults to 2\r
+--\r
+-- Note that bogus records already in geometry_columns are not\r
+-- overridden (a check for schema.table.column is performed), so\r
+-- to have a fresh probe backup your geometry_columns, delete from\r
+-- it and probe.\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION probe_geometry_columns() RETURNS text AS\r
+$$\r
+DECLARE\r
+       inserted integer;\r
+       oldcount integer;\r
+       probed integer;\r
+       stale integer;\r
+BEGIN\r
+\r
+       SELECT count(*) INTO oldcount FROM geometry_columns;\r
+\r
+       SELECT count(*) INTO probed\r
+               FROM pg_class c, pg_attribute a, pg_type t,\r
+                       pg_namespace n,\r
+                       pg_constraint sridcheck, pg_constraint typecheck\r
+\r
+               WHERE t.typname = 'geometry'\r
+               AND a.atttypid = t.oid\r
+               AND a.attrelid = c.oid\r
+               AND c.relnamespace = n.oid\r
+               AND sridcheck.connamespace = n.oid\r
+               AND typecheck.connamespace = n.oid\r
+               AND sridcheck.conrelid = c.oid\r
+               AND sridcheck.consrc LIKE '(%srid('||a.attname||') = %)'\r
+               AND typecheck.conrelid = c.oid\r
+               AND typecheck.consrc LIKE\r
+               '((geometrytype('||a.attname||') = ''%''::text) OR (% IS NULL))'\r
+               ;\r
+\r
+       INSERT INTO geometry_columns SELECT\r
+               ''::varchar as f_table_catalogue,\r
+               n.nspname::varchar as f_table_schema,\r
+               c.relname::varchar as f_table_name,\r
+               a.attname::varchar as f_geometry_column,\r
+               2 as coord_dimension,\r
+               trim(both  ' =)' from\r
+                       replace(replace(split_part(\r
+                               sridcheck.consrc, ' = ', 2), ')', ''), '(', ''))::integer AS srid,\r
+               trim(both ' =)''' from substr(typecheck.consrc,\r
+                       strpos(typecheck.consrc, '='),\r
+                       strpos(typecheck.consrc, '::')-\r
+                       strpos(typecheck.consrc, '=')\r
+                       ))::varchar as type\r
+               FROM pg_class c, pg_attribute a, pg_type t,\r
+                       pg_namespace n,\r
+                       pg_constraint sridcheck, pg_constraint typecheck\r
+               WHERE t.typname = 'geometry'\r
+               AND a.atttypid = t.oid\r
+               AND a.attrelid = c.oid\r
+               AND c.relnamespace = n.oid\r
+               AND sridcheck.connamespace = n.oid\r
+               AND typecheck.connamespace = n.oid\r
+               AND sridcheck.conrelid = c.oid\r
+               AND sridcheck.consrc LIKE '(%srid('||a.attname||') = %)'\r
+               AND typecheck.conrelid = c.oid\r
+               AND typecheck.consrc LIKE\r
+               '((geometrytype('||a.attname||') = ''%''::text) OR (% IS NULL))'\r
+\r
+                       AND NOT EXISTS (\r
+                                       SELECT oid FROM geometry_columns gc\r
+                                       WHERE c.relname::varchar = gc.f_table_name\r
+                                       AND n.nspname::varchar = gc.f_table_schema\r
+                                       AND a.attname::varchar = gc.f_geometry_column\r
+                       );\r
+\r
+       GET DIAGNOSTICS inserted = ROW_COUNT;\r
+\r
+       IF oldcount > probed THEN\r
+               stale = oldcount-probed;\r
+       ELSE\r
+               stale = 0;\r
+       END IF;\r
+\r
+       RETURN 'probed:'||probed::text||\r
+               ' inserted:'||inserted::text||\r
+               ' conflicts:'||(probed-inserted)::text||\r
+               ' stale:'||stale::text;\r
+END\r
+\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE;\r
+\r
+-----------------------------------------------------------------------\r
+-- ADDGEOMETRYCOLUMN\r
+--   <catalogue>, <schema>, <table>, <column>, <srid>, <type>, <dim>\r
+-----------------------------------------------------------------------\r
+--\r
+-- Type can be one of GEOMETRY, GEOMETRYCOLLECTION, POINT, MULTIPOINT, POLYGON,\r
+-- MULTIPOLYGON, LINESTRING, or MULTILINESTRING.\r
+--\r
+-- Geometry types (except GEOMETRY) are checked for consistency using a CHECK constraint.\r
+-- Uses an ALTER TABLE command to add the geometry column to the table.\r
+-- Addes a row to geometry_columns.\r
+-- Addes a constraint on the table that all the geometries MUST have the same\r
+-- SRID. Checks the coord_dimension to make sure its between 0 and 3.\r
+-- Should also check the precision grid (future expansion).\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION AddGeometryColumn(varchar,varchar,varchar,varchar,integer,varchar,integer)\r
+       RETURNS text\r
+       AS\r
+$$\r
+DECLARE\r
+       catalog_name alias for $1;\r
+       schema_name alias for $2;\r
+       table_name alias for $3;\r
+       column_name alias for $4;\r
+       new_srid alias for $5;\r
+       new_type alias for $6;\r
+       new_dim alias for $7;\r
+       rec RECORD;\r
+       sr varchar;\r
+       real_schema name;\r
+       sql text;\r
+\r
+BEGIN\r
+\r
+       -- Verify geometry type\r
+       IF ( NOT ( (new_type = 'GEOMETRY') OR\r
+                          (new_type = 'GEOMETRYCOLLECTION') OR\r
+                          (new_type = 'POINT') OR\r
+                          (new_type = 'MULTIPOINT') OR\r
+                          (new_type = 'POLYGON') OR\r
+                          (new_type = 'MULTIPOLYGON') OR\r
+                          (new_type = 'LINESTRING') OR\r
+                          (new_type = 'MULTILINESTRING') OR\r
+                          (new_type = 'GEOMETRYCOLLECTIONM') OR\r
+                          (new_type = 'POINTM') OR\r
+                          (new_type = 'MULTIPOINTM') OR\r
+                          (new_type = 'POLYGONM') OR\r
+                          (new_type = 'MULTIPOLYGONM') OR\r
+                          (new_type = 'LINESTRINGM') OR\r
+                          (new_type = 'MULTILINESTRINGM') OR\r
+                          (new_type = 'CIRCULARSTRING') OR\r
+                          (new_type = 'CIRCULARSTRINGM') OR\r
+                          (new_type = 'COMPOUNDCURVE') OR\r
+                          (new_type = 'COMPOUNDCURVEM') OR\r
+                          (new_type = 'CURVEPOLYGON') OR\r
+                          (new_type = 'CURVEPOLYGONM') OR\r
+                          (new_type = 'MULTICURVE') OR\r
+                          (new_type = 'MULTICURVEM') OR\r
+                          (new_type = 'MULTISURFACE') OR\r
+                          (new_type = 'MULTISURFACEM') OR\r
+                          (new_type = 'TRIANGLE') OR\r
+                          (new_type = 'TRIANGLEM') OR\r
+                          (new_type = 'POLYHEDRALSURFACE') OR\r
+                          (new_type = 'POLYHEDRALSURFACEM') OR\r
+                          (new_type = 'TIN') OR\r
+                          (new_type = 'TINM')) )\r
+       THEN\r
+               RAISE EXCEPTION 'Invalid type name - valid ones are:\r
+       POINT, MULTIPOINT,\r
+       LINESTRING, MULTILINESTRING,\r
+       POLYGON, MULTIPOLYGON,\r
+       CIRCULARSTRING, COMPOUNDCURVE, MULTICURVE,\r
+       CURVEPOLYGON, MULTISURFACE,\r
+       GEOMETRY, GEOMETRYCOLLECTION,\r
+       POINTM, MULTIPOINTM,\r
+       LINESTRINGM, MULTILINESTRINGM,\r
+       POLYGONM, MULTIPOLYGONM,\r
+       CIRCULARSTRINGM, COMPOUNDCURVEM, MULTICURVEM\r
+       CURVEPOLYGONM, MULTISURFACEM, TRIANGLE, TRIANGLEM,\r
+       POLYHEDRALSURFACE, POLYHEDRALSURFACEM, TIN, TINM\r
+       or GEOMETRYCOLLECTIONM';\r
+               RETURN 'fail';\r
+       END IF;\r
+\r
+\r
+       -- Verify dimension\r
+       IF ( (new_dim >4) OR (new_dim <0) ) THEN\r
+               RAISE EXCEPTION 'invalid dimension';\r
+               RETURN 'fail';\r
+       END IF;\r
+\r
+       IF ( (new_type LIKE '%M') AND (new_dim!=3) ) THEN\r
+               RAISE EXCEPTION 'TypeM needs 3 dimensions';\r
+               RETURN 'fail';\r
+       END IF;\r
+\r
+\r
+       -- Verify SRID\r
+       IF ( new_srid != -1 ) THEN\r
+               SELECT SRID INTO sr FROM spatial_ref_sys WHERE SRID = new_srid;\r
+               IF NOT FOUND THEN\r
+                       RAISE EXCEPTION 'AddGeometryColumns() - invalid SRID';\r
+                       RETURN 'fail';\r
+               END IF;\r
+       END IF;\r
+\r
+\r
+       -- Verify schema\r
+       IF ( schema_name IS NOT NULL AND schema_name != '' ) THEN\r
+               sql := 'SELECT nspname FROM pg_namespace ' ||\r
+                       'WHERE text(nspname) = ' || quote_literal(schema_name) ||\r
+                       'LIMIT 1';\r
+               RAISE DEBUG '%', sql;\r
+               EXECUTE sql INTO real_schema;\r
+\r
+               IF ( real_schema IS NULL ) THEN\r
+                       RAISE EXCEPTION 'Schema % is not a valid schemaname', quote_literal(schema_name);\r
+                       RETURN 'fail';\r
+               END IF;\r
+       END IF;\r
+\r
+       IF ( real_schema IS NULL ) THEN\r
+               RAISE DEBUG 'Detecting schema';\r
+               sql := 'SELECT n.nspname AS schemaname ' ||\r
+                       'FROM pg_catalog.pg_class c ' ||\r
+                         'JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace ' ||\r
+                       'WHERE c.relkind = ' || quote_literal('r') ||\r
+                       ' AND n.nspname NOT IN (' || quote_literal('pg_catalog') || ', ' || quote_literal('pg_toast') || ')' ||\r
+                       ' AND pg_catalog.pg_table_is_visible(c.oid)' ||\r
+                       ' AND c.relname = ' || quote_literal(table_name);\r
+               RAISE DEBUG '%', sql;\r
+               EXECUTE sql INTO real_schema;\r
+\r
+               IF ( real_schema IS NULL ) THEN\r
+                       RAISE EXCEPTION 'Table % does not occur in the search_path', quote_literal(table_name);\r
+                       RETURN 'fail';\r
+               END IF;\r
+       END IF;\r
+\r
+\r
+       -- Add geometry column to table\r
+       sql := 'ALTER TABLE ' ||\r
+               quote_ident(real_schema) || '.' || quote_ident(table_name)\r
+               || ' ADD COLUMN ' || quote_ident(column_name) ||\r
+               ' geometry ';\r
+       RAISE DEBUG '%', sql;\r
+       EXECUTE sql;\r
+\r
+\r
+       -- Delete stale record in geometry_columns (if any)\r
+       sql := 'DELETE FROM geometry_columns WHERE\r
+               f_table_catalog = ' || quote_literal('') ||\r
+               ' AND f_table_schema = ' ||\r
+               quote_literal(real_schema) ||\r
+               ' AND f_table_name = ' || quote_literal(table_name) ||\r
+               ' AND f_geometry_column = ' || quote_literal(column_name);\r
+       RAISE DEBUG '%', sql;\r
+       EXECUTE sql;\r
+\r
+\r
+       -- Add record in geometry_columns\r
+       sql := 'INSERT INTO geometry_columns (f_table_catalog,f_table_schema,f_table_name,' ||\r
+                                                                                 'f_geometry_column,coord_dimension,srid,type)' ||\r
+               ' VALUES (' ||\r
+               quote_literal('') || ',' ||\r
+               quote_literal(real_schema) || ',' ||\r
+               quote_literal(table_name) || ',' ||\r
+               quote_literal(column_name) || ',' ||\r
+               new_dim::text || ',' ||\r
+               new_srid::text || ',' ||\r
+               quote_literal(new_type) || ')';\r
+       RAISE DEBUG '%', sql;\r
+       EXECUTE sql;\r
+\r
+\r
+       -- Add table CHECKs\r
+       sql := 'ALTER TABLE ' ||\r
+               quote_ident(real_schema) || '.' || quote_ident(table_name)\r
+               || ' ADD CONSTRAINT '\r
+               || quote_ident('enforce_srid_' || column_name)\r
+               || ' CHECK (st_srid(' || quote_ident(column_name) ||\r
+               ') = ' || new_srid::text || ')' ;\r
+       RAISE DEBUG '%', sql;\r
+       EXECUTE sql;\r
+\r
+       sql := 'ALTER TABLE ' ||\r
+               quote_ident(real_schema) || '.' || quote_ident(table_name)\r
+               || ' ADD CONSTRAINT '\r
+               || quote_ident('enforce_dims_' || column_name)\r
+               || ' CHECK (st_ndims(' || quote_ident(column_name) ||\r
+               ') = ' || new_dim::text || ')' ;\r
+       RAISE DEBUG '%', sql;\r
+       EXECUTE sql;\r
+\r
+       IF ( NOT (new_type = 'GEOMETRY')) THEN\r
+               sql := 'ALTER TABLE ' ||\r
+                       quote_ident(real_schema) || '.' || quote_ident(table_name) || ' ADD CONSTRAINT ' ||\r
+                       quote_ident('enforce_geotype_' || column_name) ||\r
+                       ' CHECK (GeometryType(' ||\r
+                       quote_ident(column_name) || ')=' ||\r
+                       quote_literal(new_type) || ' OR (' ||\r
+                       quote_ident(column_name) || ') is null)';\r
+               RAISE DEBUG '%', sql;\r
+               EXECUTE sql;\r
+       END IF;\r
+\r
+       RETURN\r
+               real_schema || '.' ||\r
+               table_name || '.' || column_name ||\r
+               ' SRID:' || new_srid::text ||\r
+               ' TYPE:' || new_type ||\r
+               ' DIMS:' || new_dim::text || ' ';\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+----------------------------------------------------------------------------\r
+-- ADDGEOMETRYCOLUMN ( <schema>, <table>, <column>, <srid>, <type>, <dim> )\r
+----------------------------------------------------------------------------\r
+--\r
+-- This is a wrapper to the real AddGeometryColumn, for use\r
+-- when catalogue is undefined\r
+--\r
+----------------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION AddGeometryColumn(varchar,varchar,varchar,integer,varchar,integer) RETURNS text AS $$\r
+DECLARE\r
+       ret  text;\r
+BEGIN\r
+       SELECT AddGeometryColumn('',$1,$2,$3,$4,$5,$6) into ret;\r
+       RETURN ret;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' STABLE STRICT;\r
+\r
+----------------------------------------------------------------------------\r
+-- ADDGEOMETRYCOLUMN ( <table>, <column>, <srid>, <type>, <dim> )\r
+----------------------------------------------------------------------------\r
+--\r
+-- This is a wrapper to the real AddGeometryColumn, for use\r
+-- when catalogue and schema are undefined\r
+--\r
+----------------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION AddGeometryColumn(varchar,varchar,integer,varchar,integer) RETURNS text AS $$\r
+DECLARE\r
+       ret  text;\r
+BEGIN\r
+       SELECT AddGeometryColumn('','',$1,$2,$3,$4,$5) into ret;\r
+       RETURN ret;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- DROPGEOMETRYCOLUMN\r
+--   <catalogue>, <schema>, <table>, <column>\r
+-----------------------------------------------------------------------\r
+--\r
+-- Removes geometry column reference from geometry_columns table.\r
+-- Drops the column with pgsql >= 73.\r
+-- Make some silly enforcements on it for pgsql < 73\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION DropGeometryColumn(varchar, varchar,varchar,varchar)\r
+       RETURNS text\r
+       AS\r
+$$\r
+DECLARE\r
+       catalog_name alias for $1;\r
+       schema_name alias for $2;\r
+       table_name alias for $3;\r
+       column_name alias for $4;\r
+       myrec RECORD;\r
+       okay boolean;\r
+       real_schema name;\r
+\r
+BEGIN\r
+\r
+\r
+       -- Find, check or fix schema_name\r
+       IF ( schema_name != '' ) THEN\r
+               okay = 'f';\r
+\r
+               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP\r
+                       okay := 't';\r
+               END LOOP;\r
+\r
+               IF ( okay <> 't' ) THEN\r
+                       RAISE NOTICE 'Invalid schema name - using current_schema()';\r
+                       SELECT current_schema() into real_schema;\r
+               ELSE\r
+                       real_schema = schema_name;\r
+               END IF;\r
+       ELSE\r
+               SELECT current_schema() into real_schema;\r
+       END IF;\r
+\r
+       -- Find out if the column is in the geometry_columns table\r
+       okay = 'f';\r
+       FOR myrec IN SELECT * from geometry_columns where f_table_schema = text(real_schema) and f_table_name = table_name and f_geometry_column = column_name LOOP\r
+               okay := 't';\r
+       END LOOP;\r
+       IF (okay <> 't') THEN\r
+               RAISE EXCEPTION 'column not found in geometry_columns table';\r
+               RETURN 'f';\r
+       END IF;\r
+\r
+       -- Remove ref from geometry_columns table\r
+       EXECUTE 'delete from geometry_columns where f_table_schema = ' ||\r
+               quote_literal(real_schema) || ' and f_table_name = ' ||\r
+               quote_literal(table_name)  || ' and f_geometry_column = ' ||\r
+               quote_literal(column_name);\r
+\r
+       -- Remove table column\r
+       EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) || '.' ||\r
+               quote_ident(table_name) || ' DROP COLUMN ' ||\r
+               quote_ident(column_name);\r
+\r
+       RETURN real_schema || '.' || table_name || '.' || column_name ||' effectively removed.';\r
+\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- DROPGEOMETRYCOLUMN\r
+--   <schema>, <table>, <column>\r
+-----------------------------------------------------------------------\r
+--\r
+-- This is a wrapper to the real DropGeometryColumn, for use\r
+-- when catalogue is undefined\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION DropGeometryColumn(varchar,varchar,varchar)\r
+       RETURNS text\r
+       AS\r
+$$\r
+DECLARE\r
+       ret text;\r
+BEGIN\r
+       SELECT DropGeometryColumn('',$1,$2,$3) into ret;\r
+       RETURN ret;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- DROPGEOMETRYCOLUMN\r
+--   <table>, <column>\r
+-----------------------------------------------------------------------\r
+--\r
+-- This is a wrapper to the real DropGeometryColumn, for use\r
+-- when catalogue and schema is undefined.\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION DropGeometryColumn(varchar,varchar)\r
+       RETURNS text\r
+       AS\r
+$$\r
+DECLARE\r
+       ret text;\r
+BEGIN\r
+       SELECT DropGeometryColumn('','',$1,$2) into ret;\r
+       RETURN ret;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- DROPGEOMETRYTABLE\r
+--   <catalogue>, <schema>, <table>\r
+-----------------------------------------------------------------------\r
+--\r
+-- Drop a table and all its references in geometry_columns\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION DropGeometryTable(varchar, varchar,varchar)\r
+       RETURNS text\r
+       AS\r
+$$\r
+DECLARE\r
+       catalog_name alias for $1;\r
+       schema_name alias for $2;\r
+       table_name alias for $3;\r
+       real_schema name;\r
+\r
+BEGIN\r
+\r
+       IF ( schema_name = '' ) THEN\r
+               SELECT current_schema() into real_schema;\r
+       ELSE\r
+               real_schema = schema_name;\r
+       END IF;\r
+\r
+       -- Remove refs from geometry_columns table\r
+       EXECUTE 'DELETE FROM geometry_columns WHERE ' ||\r
+               'f_table_schema = ' || quote_literal(real_schema) ||\r
+               ' AND ' ||\r
+               ' f_table_name = ' || quote_literal(table_name);\r
+\r
+       -- Remove table\r
+       EXECUTE 'DROP TABLE '\r
+               || quote_ident(real_schema) || '.' ||\r
+               quote_ident(table_name);\r
+\r
+       RETURN\r
+               real_schema || '.' ||\r
+               table_name ||' dropped.';\r
+\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- DROPGEOMETRYTABLE\r
+--   <schema>, <table>\r
+-----------------------------------------------------------------------\r
+--\r
+-- Drop a table and all its references in geometry_columns\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION DropGeometryTable(varchar,varchar) RETURNS text AS\r
+$$ SELECT DropGeometryTable('',$1,$2) $$\r
+LANGUAGE 'sql' WITH (isstrict);\r
+\r
+-----------------------------------------------------------------------\r
+-- DROPGEOMETRYTABLE\r
+--   <table>\r
+-----------------------------------------------------------------------\r
+--\r
+-- Drop a table and all its references in geometry_columns\r
+-- For PG>=73 use current_schema()\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION DropGeometryTable(varchar) RETURNS text AS\r
+$$ SELECT DropGeometryTable('','',$1) $$\r
+LANGUAGE 'sql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- UPDATEGEOMETRYSRID\r
+--   <catalogue>, <schema>, <table>, <column>, <srid>\r
+-----------------------------------------------------------------------\r
+--\r
+-- Change SRID of all features in a spatially-enabled table\r
+--\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION UpdateGeometrySRID(varchar,varchar,varchar,varchar,integer)\r
+       RETURNS text\r
+       AS\r
+$$\r
+DECLARE\r
+       catalog_name alias for $1;\r
+       schema_name alias for $2;\r
+       table_name alias for $3;\r
+       column_name alias for $4;\r
+       new_srid alias for $5;\r
+       myrec RECORD;\r
+       okay boolean;\r
+       cname varchar;\r
+       real_schema name;\r
+\r
+BEGIN\r
+\r
+\r
+       -- Find, check or fix schema_name\r
+       IF ( schema_name != '' ) THEN\r
+               okay = 'f';\r
+\r
+               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP\r
+                       okay := 't';\r
+               END LOOP;\r
+\r
+               IF ( okay <> 't' ) THEN\r
+                       RAISE EXCEPTION 'Invalid schema name';\r
+               ELSE\r
+                       real_schema = schema_name;\r
+               END IF;\r
+       ELSE\r
+               SELECT INTO real_schema current_schema()::text;\r
+       END IF;\r
+\r
+       -- Find out if the column is in the geometry_columns table\r
+       okay = 'f';\r
+       FOR myrec IN SELECT * from geometry_columns where f_table_schema = text(real_schema) and f_table_name = table_name and f_geometry_column = column_name LOOP\r
+               okay := 't';\r
+       END LOOP;\r
+       IF (okay <> 't') THEN\r
+               RAISE EXCEPTION 'column not found in geometry_columns table';\r
+               RETURN 'f';\r
+       END IF;\r
+\r
+       -- Update ref from geometry_columns table\r
+       EXECUTE 'UPDATE geometry_columns SET SRID = ' || new_srid::text ||\r
+               ' where f_table_schema = ' ||\r
+               quote_literal(real_schema) || ' and f_table_name = ' ||\r
+               quote_literal(table_name)  || ' and f_geometry_column = ' ||\r
+               quote_literal(column_name);\r
+\r
+       -- Make up constraint name\r
+       cname = 'enforce_srid_'  || column_name;\r
+\r
+       -- Drop enforce_srid constraint\r
+       EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) ||\r
+               '.' || quote_ident(table_name) ||\r
+               ' DROP constraint ' || quote_ident(cname);\r
+\r
+       -- Update geometries SRID\r
+       EXECUTE 'UPDATE ' || quote_ident(real_schema) ||\r
+               '.' || quote_ident(table_name) ||\r
+               ' SET ' || quote_ident(column_name) ||\r
+               ' = ST_SetSRID(' || quote_ident(column_name) ||\r
+               ', ' || new_srid::text || ')';\r
+\r
+       -- Reset enforce_srid constraint\r
+       EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) ||\r
+               '.' || quote_ident(table_name) ||\r
+               ' ADD constraint ' || quote_ident(cname) ||\r
+               ' CHECK (st_srid(' || quote_ident(column_name) ||\r
+               ') = ' || new_srid::text || ')';\r
+\r
+       RETURN real_schema || '.' || table_name || '.' || column_name ||' SRID changed to ' || new_srid::text;\r
+\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- UPDATEGEOMETRYSRID\r
+--   <schema>, <table>, <column>, <srid>\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION UpdateGeometrySRID(varchar,varchar,varchar,integer)\r
+       RETURNS text\r
+       AS $$\r
+DECLARE\r
+       ret  text;\r
+BEGIN\r
+       SELECT UpdateGeometrySRID('',$1,$2,$3,$4) into ret;\r
+       RETURN ret;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- UPDATEGEOMETRYSRID\r
+--   <table>, <column>, <srid>\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION UpdateGeometrySRID(varchar,varchar,integer)\r
+       RETURNS text\r
+       AS $$\r
+DECLARE\r
+       ret  text;\r
+BEGIN\r
+       SELECT UpdateGeometrySRID('','',$1,$2,$3) into ret;\r
+       RETURN ret;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' VOLATILE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- FIND_SRID( <schema>, <table>, <geom col> )\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION find_srid(varchar,varchar,varchar) RETURNS int4 AS\r
+$$\r
+DECLARE\r
+       schem text;\r
+       tabl text;\r
+       sr int4;\r
+BEGIN\r
+       IF $1 IS NULL THEN\r
+         RAISE EXCEPTION 'find_srid() - schema is NULL!';\r
+       END IF;\r
+       IF $2 IS NULL THEN\r
+         RAISE EXCEPTION 'find_srid() - table name is NULL!';\r
+       END IF;\r
+       IF $3 IS NULL THEN\r
+         RAISE EXCEPTION 'find_srid() - column name is NULL!';\r
+       END IF;\r
+       schem = $1;\r
+       tabl = $2;\r
+-- if the table contains a . and the schema is empty\r
+-- split the table into a schema and a table\r
+-- otherwise drop through to default behavior\r
+       IF ( schem = '' and tabl LIKE '%.%' ) THEN\r
+        schem = substr(tabl,1,strpos(tabl,'.')-1);\r
+        tabl = substr(tabl,length(schem)+2);\r
+       ELSE\r
+        schem = schem || '%';\r
+       END IF;\r
+\r
+       select SRID into sr from geometry_columns where f_table_schema like schem and f_table_name = tabl and f_geometry_column = $3;\r
+       IF NOT FOUND THEN\r
+          RAISE EXCEPTION 'find_srid() - couldnt find the corresponding SRID - is the geometry registered in the GEOMETRY_COLUMNS table?  Is there an uppercase/lowercase missmatch?';\r
+       END IF;\r
+       return sr;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+\r
+---------------------------------------------------------------\r
+-- PROJ support\r
+---------------------------------------------------------------\r
+\r
+CREATE OR REPLACE FUNCTION get_proj4_from_srid(integer) RETURNS text AS\r
+$$\r
+BEGIN\r
+       RETURN proj4text::text FROM spatial_ref_sys WHERE srid= $1;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_transform_geometry(geometry,text,text,int)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','transform_geom'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION transform(geometry,integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','transform'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: transform(geometry,integer)\r
+CREATE OR REPLACE FUNCTION ST_Transform(geometry,integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','transform'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-----------------------------------------------------------------------\r
+-- POSTGIS_VERSION()\r
+-----------------------------------------------------------------------\r
+\r
+CREATE OR REPLACE FUNCTION postgis_version() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_proj_version() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+--\r
+-- IMPORTANT:\r
+-- Starting at 1.1.0 this function is used by postgis_proc_upgrade.pl\r
+-- to extract version of postgis being installed.\r
+-- Do not modify this w/out also changing postgis_proc_upgrade.pl\r
+--\r
+CREATE OR REPLACE FUNCTION postgis_scripts_installed() RETURNS text\r
+       AS _POSTGIS_SQL_SELECT_POSTGIS_SCRIPTS_VERSION\r
+       LANGUAGE 'sql' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_lib_version() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE; -- a new lib will require a new session\r
+\r
+-- NOTE: starting at 1.1.0 this is the same of postgis_lib_version()\r
+CREATE OR REPLACE FUNCTION postgis_scripts_released() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_uses_stats() RETURNS bool\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_geos_version() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_libxml_version() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_scripts_build_date() RETURNS text\r
+       AS _POSTGIS_SQL_SELECT_POSTGIS_BUILD_DATE\r
+       LANGUAGE 'sql' IMMUTABLE;\r
+\r
+CREATE OR REPLACE FUNCTION postgis_lib_build_date() RETURNS text\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+\r
+\r
+CREATE OR REPLACE FUNCTION postgis_full_version() RETURNS text\r
+AS $$\r
+DECLARE\r
+       libver text;\r
+       projver text;\r
+       geosver text;\r
+       libxmlver text;\r
+       usestats bool;\r
+       dbproc text;\r
+       relproc text;\r
+       fullver text;\r
+BEGIN\r
+       SELECT postgis_lib_version() INTO libver;\r
+       SELECT postgis_proj_version() INTO projver;\r
+       SELECT postgis_geos_version() INTO geosver;\r
+       SELECT postgis_libxml_version() INTO libxmlver;\r
+       SELECT postgis_uses_stats() INTO usestats;\r
+       SELECT postgis_scripts_installed() INTO dbproc;\r
+       SELECT postgis_scripts_released() INTO relproc;\r
+\r
+       fullver = 'POSTGIS="' || libver || '"';\r
+\r
+       IF  geosver IS NOT NULL THEN\r
+               fullver = fullver || ' GEOS="' || geosver || '"';\r
+       END IF;\r
+\r
+       IF  projver IS NOT NULL THEN\r
+               fullver = fullver || ' PROJ="' || projver || '"';\r
+       END IF;\r
+\r
+       IF  libxmlver IS NOT NULL THEN\r
+               fullver = fullver || ' LIBXML="' || libxmlver || '"';\r
+       END IF;\r
+\r
+       IF usestats THEN\r
+               fullver = fullver || ' USE_STATS';\r
+       END IF;\r
+\r
+       -- fullver = fullver || ' DBPROC="' || dbproc || '"';\r
+       -- fullver = fullver || ' RELPROC="' || relproc || '"';\r
+\r
+       IF dbproc != relproc THEN\r
+               fullver = fullver || ' (procs from ' || dbproc || ' need upgrade)';\r
+       END IF;\r
+\r
+       RETURN fullver;\r
+END\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE;\r
+\r
+---------------------------------------------------------------\r
+-- CASTS\r
+---------------------------------------------------------------\r
+               \r
+CREATE OR REPLACE FUNCTION box2d(geometry)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_BOX2DFLOAT4'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box3d(geometry)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_BOX3D'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box(geometry)\r
+       RETURNS box\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_BOX'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box2d(box3d)\r
+       RETURNS box2d\r
+       AS 'MODULE_PATHNAME','BOX3D_to_BOX2DFLOAT4'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box3d(box2d)\r
+       RETURNS box3d\r
+       AS 'MODULE_PATHNAME','BOX2DFLOAT4_to_BOX3D'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION box(box3d)\r
+       RETURNS box\r
+       AS 'MODULE_PATHNAME','BOX3D_to_BOX'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION text(geometry)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- this is kept for backward-compatibility\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION box3dtobox(box3d)\r
+       RETURNS box\r
+       AS 'SELECT box($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry(box2d)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','BOX2DFLOAT4_to_LWGEOM'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry(box3d)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','BOX3D_to_LWGEOM'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','parse_WKT_lwgeom'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION geometry(bytea)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_bytea'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION bytea(geometry)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','LWGEOM_to_bytea'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- 7.3+ explicit casting definitions\r
+CREATE CAST (geometry AS box2d) WITH FUNCTION box2d(geometry) AS IMPLICIT;\r
+CREATE CAST (geometry AS box3d) WITH FUNCTION box3d(geometry) AS IMPLICIT;\r
+CREATE CAST (geometry AS box) WITH FUNCTION box(geometry) AS IMPLICIT;\r
+CREATE CAST (box3d AS box2d) WITH FUNCTION box2d(box3d) AS IMPLICIT;\r
+CREATE CAST (box2d AS box3d) WITH FUNCTION box3d(box2d) AS IMPLICIT;\r
+CREATE CAST (box2d AS geometry) WITH FUNCTION geometry(box2d) AS IMPLICIT;\r
+CREATE CAST (box3d AS box) WITH FUNCTION box(box3d) AS IMPLICIT;\r
+CREATE CAST (box3d AS geometry) WITH FUNCTION geometry(box3d) AS IMPLICIT;\r
+CREATE CAST (text AS geometry) WITH FUNCTION geometry(text) AS IMPLICIT;\r
+CREATE CAST (geometry AS text) WITH FUNCTION text(geometry) AS IMPLICIT;\r
+CREATE CAST (bytea AS geometry) WITH FUNCTION geometry(bytea) AS IMPLICIT;\r
+CREATE CAST (geometry AS bytea) WITH FUNCTION bytea(geometry) AS IMPLICIT;\r
+\r
+-- Casts to allow the box3d_extent type to automatically cast to box3d/box2d in queries\r
+CREATE CAST (box3d_extent AS box3d) WITH FUNCTION box3d_extent(box3d_extent) AS IMPLICIT;\r
+CREATE CAST (box3d_extent AS box2d) WITH FUNCTION box2d(box3d_extent) AS IMPLICIT;\r
+CREATE CAST (box3d_extent AS geometry) WITH FUNCTION geometry(box3d_extent) AS IMPLICIT;\r
+\r
+---------------------------------------------------------------\r
+-- Algorithms\r
+---------------------------------------------------------------\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Simplify(geometry, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_simplify2d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- SnapToGrid(input, xoff, yoff, xsize, ysize)\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION SnapToGrid(geometry, float8, float8, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_snaptogrid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, float8, float8, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_snaptogrid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- SnapToGrid(input, xsize, ysize) # offsets=0\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION SnapToGrid(geometry, float8, float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_SnapToGrid($1, 0, 0, $2, $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, float8, float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_SnapToGrid($1, 0, 0, $2, $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_SnapToGrid(input, size) # xsize=ysize=size, offsets=0\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, float8)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_SnapToGrid($1, 0, 0, $2, $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_SnapToGrid(input, point_offsets, xsize, ysize, zsize, msize)\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_SnapToGrid(geometry, geometry, float8, float8, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_snaptogrid_pointoff'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Segmentize(geometry, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_segmentize2d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+---------------------------------------------------------------\r
+-- LRS\r
+---------------------------------------------------------------\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_line_interpolate_point(geometry, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_line_interpolate_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_line_substring(geometry, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_line_substring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_line_locate_point(geometry, geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_line_locate_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_locate_between_measures(geometry, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_locate_between_m'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_locate_along_measure(geometry, float8)\r
+       RETURNS geometry\r
+       AS $$ SELECT ST_locate_between_measures($1, $2, $2) $$\r
+       LANGUAGE 'sql' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_AddMeasure(geometry, float8, float8) \r
+       RETURNS geometry \r
+       AS 'MODULE_PATHNAME', 'ST_AddMeasure' \r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+    \r
+---------------------------------------------------------------\r
+-- GEOS\r
+---------------------------------------------------------------\r
+\r
+-- PostGIS equivalent function: intersection(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION ST_Intersection(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','intersection'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- PostGIS equivalent function: buffer(geometry,float8)\r
+CREATE OR REPLACE FUNCTION ST_Buffer(geometry,float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','buffer'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.5.0 - requires GEOS-3.2 or higher\r
+CREATE OR REPLACE FUNCTION _ST_Buffer(geometry,float8,cstring)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','buffer'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Buffer(geometry,float8,integer)\r
+       RETURNS geometry\r
+       AS $$ SELECT _ST_Buffer($1, $2,\r
+               CAST('quad_segs='||CAST($3 AS text) as cstring))\r
+          $$\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_Buffer(geometry,float8,text)\r
+       RETURNS geometry\r
+       AS $$ SELECT _ST_Buffer($1, $2,\r
+               CAST( regexp_replace($3, '^[0123456789]+$',\r
+                       'quad_segs='||$3) AS cstring)\r
+               )\r
+          $$\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: convexhull(geometry)\r
+CREATE OR REPLACE FUNCTION ST_ConvexHull(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','convexhull'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Only accepts LINESTRING as parameters.\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION _ST_LineCrossingDirection(geometry, geometry)\r
+       RETURNS integer\r
+       AS 'MODULE_PATHNAME', 'ST_LineCrossingDirection'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_LineCrossingDirection(geometry, geometry)\r
+       RETURNS integer AS\r
+       $$ SELECT CASE WHEN NOT $1 && $2 THEN 0 ELSE _ST_LineCrossingDirection($1,$2) END $$\r
+       LANGUAGE 'sql' IMMUTABLE;\r
+\r
+\r
+-- Only accepts LINESTRING as parameters.\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(geometry, float8, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Requires GEOS >= 3.0.0\r
+-- Availability: 1.3.3\r
+CREATE OR REPLACE FUNCTION ST_SimplifyPreserveTopology(geometry, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','topologypreservesimplify'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Requires GEOS >= 3.1.0\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_IsValidReason(geometry)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME', 'isvalidreason'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 2.0.0\r
+CREATE TYPE valid_detail AS (valid bool, reason varchar, location geometry);\r
+\r
+-- Requires GEOS >= 3.3.0\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_IsValidDetail(geometry)\r
+       RETURNS valid_detail\r
+       AS 'MODULE_PATHNAME', 'isvaliddetail'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Requires GEOS >= 3.3.0\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_IsValidDetail(geometry, int4)\r
+       RETURNS valid_detail\r
+       AS 'MODULE_PATHNAME', 'isvaliddetail'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+#if POSTGIS_GEOS_VERSION >= 33\r
+-- Requires GEOS >= 3.3.0\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_IsValidReason(geometry, int4)\r
+       RETURNS text\r
+       AS $$\r
+SELECT CASE WHEN valid THEN 'Valid Geometry' ELSE reason END FROM (\r
+       SELECT (ST_isValidDetail($1, $2)).*\r
+) foo\r
+       $$\r
+       LANGUAGE 'sql' IMMUTABLE STRICT\r
+       COST 100;\r
+#endif\r
+\r
+#if POSTGIS_GEOS_VERSION >= 33\r
+-- Requires GEOS >= 3.3.0\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_IsValid(geometry, int4)\r
+       RETURNS boolean\r
+       AS 'SELECT (ST_isValidDetail($1, $2)).valid'\r
+       LANGUAGE 'sql' IMMUTABLE STRICT\r
+       COST 100;\r
+#endif\r
+\r
+\r
+#if POSTGIS_GEOS_VERSION >= 32\r
+-- Requires GEOS >= 3.2.0\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geometry, geometry)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'hausdorffdistance'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+#endif\r
+\r
+#if POSTGIS_GEOS_VERSION >= 32\r
+-- Requires GEOS >= 3.2.0\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geometry, geometry, float8)\r
+       RETURNS FLOAT8\r
+       AS 'MODULE_PATHNAME', 'hausdorffdistancedensify'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+#endif\r
+\r
+-- PostGIS equivalent function: difference(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION ST_Difference(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','difference'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: boundary(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Boundary(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','boundary'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: symdifference(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION ST_SymDifference(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','symdifference'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_symmetricdifference(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','symdifference'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: GeomUnion(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION ST_Union(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','geomunion'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+-- Requires: GEOS-3.3.0\r
+CREATE OR REPLACE FUNCTION ST_UnaryUnion(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','ST_UnaryUnion'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- ST_RemoveRepeatedPoints(in geometry)\r
+--\r
+-- Removes duplicate vertices in input.\r
+-- Only checks consecutive points for lineal and polygonal geoms.\r
+-- Checks all points for multipoint geoms.\r
+--\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_RemoveRepeatedPoints(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_RemoveRepeatedPoints'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+--------------------------------------------------------------------------------\r
+-- ST_CleanGeometry / ST_MakeValid\r
+--------------------------------------------------------------------------------\r
+\r
+-- ST_MakeValid(in geometry)\r
+--\r
+-- Try to make the input valid maintaining the boundary profile.\r
+-- May return a collection.\r
+-- May return a geometry with inferior dimensions (dimensional collapses).\r
+-- May return NULL if can't handle input.\r
+--\r
+-- Requires: GEOS-3.3.0\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_MakeValid(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_MakeValid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- ST_CleanGeometry(in geometry)\r
+--\r
+-- Make input:\r
+--     - Simple (lineal components)\r
+--     - Valid (polygonal components)\r
+--     - Obeying the RHR (if polygonal)\r
+--     - Simplified of consecutive duplicated points \r
+-- Ensuring:\r
+--     - No input vertexes are discarded (except consecutive repeated ones)\r
+--     - Output geometry type matches input\r
+--\r
+-- Returns NULL on failure.\r
+-- \r
+-- Requires: GEOS-3.3.0\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_CleanGeometry(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_CleanGeometry'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+--------------------------------------------------------------------------------\r
+-- ST_Split\r
+--------------------------------------------------------------------------------\r
+\r
+-- ST_Split(in geometry, blade geometry)\r
+--\r
+-- Split a geometry in parts after cutting it with given blade.\r
+-- Returns a collection containing all parts.\r
+--\r
+-- Note that multi-part geometries will be returned exploded,\r
+-- no matter relation to blade.\r
+-- \r
+-- Availability: 2.0.0\r
+--\r
+CREATE OR REPLACE FUNCTION ST_Split(geometry, geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_Split'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+--------------------------------------------------------------------------------\r
+-- ST_SharedPaths\r
+--------------------------------------------------------------------------------\r
+\r
+-- ST_SharedPaths(lineal1 geometry, lineal1 geometry)\r
+--\r
+-- Returns a collection containing paths shared by the two\r
+-- input geometries. Those going in the same direction are\r
+-- in the first element of the collection, those going in the\r
+-- opposite direction are in the second element.\r
+--\r
+-- The paths themselves are given in the direction of the\r
+-- first geometry.\r
+-- \r
+-- Availability: 2.0.0\r
+-- Requires GEOS >= 3.3.0\r
+--\r
+CREATE OR REPLACE FUNCTION ST_SharedPaths(geometry, geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_SharedPaths'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+--------------------------------------------------------------------------------\r
+-- ST_Snap\r
+--------------------------------------------------------------------------------\r
+\r
+-- ST_Snap(g1 geometry, g2 geometry, tolerance float8)\r
+--\r
+-- Snap first geometry against second.\r
+--\r
+-- Availability: 2.0.0\r
+-- Requires GEOS >= 3.3.0\r
+--\r
+CREATE OR REPLACE FUNCTION ST_Snap(geometry, geometry, float8)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_Snap'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+--------------------------------------------------------------------------------\r
+-- ST_RelateMatch\r
+--------------------------------------------------------------------------------\r
+\r
+-- ST_RelateMatch(matrix text, pattern text)\r
+--\r
+-- Returns true if pattern 'pattern' matches DE9 intersection matrix 'matrix'\r
+--\r
+-- Availability: 2.0.0\r
+-- Requires GEOS >= 3.3.0\r
+--\r
+CREATE OR REPLACE FUNCTION ST_RelateMatch(text, text)\r
+       RETURNS bool\r
+       AS 'MODULE_PATHNAME', 'ST_RelateMatch'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+\r
+--------------------------------------------------------------------------------\r
+-- Aggregates and their supporting functions\r
+--------------------------------------------------------------------------------\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Collect(geometry, geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_collect'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_MemCollect(\r
+       sfunc = ST_collect,\r
+       basetype = geometry,\r
+       stype = geometry\r
+       );\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Collect(geometry[])\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_collect_garray'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_MemUnion (\r
+       basetype = geometry,\r
+       sfunc = ST_Union,\r
+       stype = geometry\r
+       );\r
+\r
+--\r
+-- pgis_abs\r
+-- Container type to hold the ArrayBuildState pointer as it passes through\r
+-- the geometry array accumulation aggregate.\r
+--\r
+CREATE OR REPLACE FUNCTION pgis_abs_in(cstring)\r
+       RETURNS pgis_abs\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION pgis_abs_out(pgis_abs)\r
+       RETURNS cstring\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE TYPE pgis_abs (\r
+       internallength = 8,\r
+       input = pgis_abs_in,\r
+       output = pgis_abs_out,\r
+       alignment = double\r
+);\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION pgis_geometry_accum_transfn(pgis_abs, geometry)\r
+       RETURNS pgis_abs\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C';\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION pgis_geometry_accum_finalfn(pgis_abs)\r
+       RETURNS geometry[]\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C';\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION pgis_geometry_union_finalfn(pgis_abs)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C';\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION pgis_geometry_collect_finalfn(pgis_abs)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C';\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION pgis_geometry_polygonize_finalfn(pgis_abs)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C';\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION pgis_geometry_makeline_finalfn(pgis_abs)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C';\r
+\r
+-- Deprecation in: 1.2.3\r
+CREATE AGGREGATE accum (\r
+       sfunc = pgis_geometry_accum_transfn,\r
+       basetype = geometry,\r
+       stype = pgis_abs,\r
+       finalfunc = pgis_geometry_accum_finalfn\r
+       );\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_Accum (\r
+       sfunc = pgis_geometry_accum_transfn,\r
+       basetype = geometry,\r
+       stype = pgis_abs,\r
+       finalfunc = pgis_geometry_accum_finalfn\r
+       );\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_Union (geometry[])\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','pgis_union_geometry_array'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_Union (\r
+       basetype = geometry,\r
+       sfunc = pgis_geometry_accum_transfn,\r
+       stype = pgis_abs,\r
+       finalfunc = pgis_geometry_union_finalfn\r
+       );\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE AGGREGATE collect (\r
+       basetype = geometry,\r
+       sfunc = pgis_geometry_accum_transfn,\r
+       stype = pgis_abs,\r
+       finalfunc = pgis_geometry_collect_finalfn\r
+);\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_Collect (\r
+       BASETYPE = geometry,\r
+       SFUNC = pgis_geometry_accum_transfn,\r
+       STYPE = pgis_abs,\r
+       FINALFUNC = pgis_geometry_collect_finalfn\r
+       );\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE AGGREGATE Polygonize (\r
+       BASETYPE = geometry,\r
+       SFUNC = pgis_geometry_accum_transfn,\r
+       STYPE = pgis_abs,\r
+       FINALFUNC = pgis_geometry_polygonize_finalfn\r
+       );\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_Polygonize (\r
+       BASETYPE = geometry,\r
+       SFUNC = pgis_geometry_accum_transfn,\r
+       STYPE = pgis_abs,\r
+       FINALFUNC = pgis_geometry_polygonize_finalfn\r
+       );\r
+\r
+-- Availability: 1.2.2\r
+CREATE AGGREGATE ST_MakeLine (\r
+       BASETYPE = geometry,\r
+       SFUNC = pgis_geometry_accum_transfn,\r
+       STYPE = pgis_abs,\r
+       FINALFUNC = pgis_geometry_makeline_finalfn\r
+       );\r
+\r
+\r
+\r
+--------------------------------------------------------------------------------\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Relate(geometry,geometry)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME','relate_full'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+-- Requires GEOS >= 3.3.0\r
+CREATE OR REPLACE FUNCTION ST_Relate(geometry, geometry, int4)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME','relate_full'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: relate(geometry,geometry,text)\r
+CREATE OR REPLACE FUNCTION ST_Relate(geometry,geometry,text)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','relate_pattern'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: disjoint(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION ST_Disjoint(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','disjoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: touches(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION _ST_Touches(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','touches'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Touches(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Touches($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- Availability: 1.3.4\r
+CREATE OR REPLACE FUNCTION _ST_DWithin(geometry,geometry,float8)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dwithin'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_DWithin(geometry, geometry, float8)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_DWithin($1, $2, $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- PostGIS equivalent function: intersects(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION _ST_Intersects(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','intersects'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Intersects(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Intersects($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+       \r
+-- PostGIS equivalent function: crosses(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION _ST_Crosses(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','crosses'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Crosses(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Crosses($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- PostGIS equivalent function: within(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION _ST_Within(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','within'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Within(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Within($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- PostGIS equivalent function: contains(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION _ST_Contains(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','contains'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Contains(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Contains($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION _ST_CoveredBy(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'coveredby'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_CoveredBy(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_CoveredBy($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION _ST_Covers(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'covers'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Covers(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Covers($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION _ST_ContainsProperly(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','containsproperly'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.4.0\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_ContainsProperly(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_ContainsProperly($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- PostGIS equivalent function: overlaps(geometry,geometry)\r
+CREATE OR REPLACE FUNCTION _ST_Overlaps(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','overlaps'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.2\r
+-- Inlines index magic\r
+CREATE OR REPLACE FUNCTION ST_Overlaps(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Overlaps($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+-- PostGIS equivalent function: IsValid(geometry)\r
+-- TODO: change null returns to true\r
+CREATE OR REPLACE FUNCTION ST_IsValid(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'isvalid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- This is also available w/out GEOS\r
+CREATE OR REPLACE FUNCTION Centroid(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+       \r
+-- PostGIS equivalent function: Centroid(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Centroid(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'centroid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+       \r
+-- PostGIS equivalent function: IsRing(geometry)\r
+CREATE OR REPLACE FUNCTION ST_IsRing(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'isring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: PointOnSurface(geometry)\r
+CREATE OR REPLACE FUNCTION ST_PointOnSurface(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'pointonsurface'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- PostGIS equivalent function: IsSimple(geometry)\r
+CREATE OR REPLACE FUNCTION ST_IsSimple(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'issimple'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_IsCollection(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'ST_IsCollection'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION Equals(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','geomequals'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION _ST_Equals(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME','geomequals'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+-- Availability: 1.2.1\r
+CREATE OR REPLACE FUNCTION ST_Equals(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_Equals($1,$2)'\r
+       LANGUAGE 'SQL' IMMUTABLE;\r
+\r
+\r
+-----------------------------------------------------------------------\r
+-- GML & KML INPUT\r
+-- Availability: 1.5.0\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION ST_GeomFromGML(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','geom_from_gml'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_GMLToSQL(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','geom_from_gml'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_GeomFromKML(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','geom_from_kml'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- SVG OUTPUT\r
+-----------------------------------------------------------------------\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsSVG(geometry,int4,int4)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asSVG'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsSVG(geometry,int4)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asSVG'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsSVG(geometry)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asSVG'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- GML OUTPUT\r
+-----------------------------------------------------------------------\r
+-- _ST_AsGML(version, geom, precision, option, prefix)\r
+CREATE OR REPLACE FUNCTION _ST_AsGML(int4, geometry, int4, int4, text)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asGML'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-- ST_AsGML(geom, precision) / version=2\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsGML(geometry, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML(2, $1, $2, 0, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGML(geom) / precision=15 version=2\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsGML(geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML(2, $1, 15, 0, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGML(version, geom) / precision=15 \r
+-- Availability: 1.3.2\r
+CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML($1, $2, 15, 0, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGML(version, geom, precision)\r
+-- Availability: 1.3.2\r
+CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML($1, $2, $3, 0, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGML (geom, precision, option) / version=2\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_AsGML(geometry, int4, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML(2, $1, $2, $3, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGML(version, geom, precision, option)\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry, int4, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML($1, $2, $3, $4, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-- ST_AsGML(version, geom, precision, option, prefix)\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_AsGML(int4, geometry, int4, int4, text)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGML($1, $2, $3, $4, $5)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-----------------------------------------------------------------------\r
+-- KML OUTPUT\r
+-----------------------------------------------------------------------\r
+-- _ST_AsKML(version, geom, precision)\r
+CREATE OR REPLACE FUNCTION _ST_AsKML(int4, geometry, int4, text)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asKML'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsKML(geometry, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsKML(2, ST_Transform($1,4326), $2, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsKML(geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsKML(2, ST_Transform($1,4326), 15, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsKML(version, geom) / precision=15 version=2\r
+-- Availability: 1.3.2\r
+CREATE OR REPLACE FUNCTION ST_AsKML(int4, geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsKML($1, ST_Transform($2,4326), 15, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsKML(version, geom, precision)\r
+-- Availability: 1.3.2\r
+CREATE OR REPLACE FUNCTION ST_AsKML(int4, geometry, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsKML($1, ST_Transform($2,4326), $3, null)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsKML(version, geom, precision, text)\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_AsKML(int4, geometry, int4, text)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsKML($1, ST_Transform($2,4326), $3, $4)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-----------------------------------------------------------------------\r
+-- GEOJSON OUTPUT\r
+-- Availability: 1.3.4\r
+-----------------------------------------------------------------------\r
+-- _ST_AsGeoJson(version, geom, precision, options)\r
+CREATE OR REPLACE FUNCTION _ST_AsGeoJson(int4, geometry, int4, int4)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asGeoJson'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGeoJson(geom, precision) / version=1 options=0\r
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(geometry, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGeoJson(1, $1, $2, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGeoJson(geom) / precision=15 version=1 options=0\r
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGeoJson(1, $1, 15, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGeoJson(version, geom) / precision=15 options=0\r
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(int4, geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGeoJson($1, $2, 15, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGeoJson(version, geom, precision) / options=0\r
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(int4, geometry, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGeoJson($1, $2, $3, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGeoJson(geom, precision, options) / version=1\r
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(geometry, int4, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGeoJson(1, $1, $2, $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- ST_AsGeoJson(version, geom, precision,options)\r
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(int4, geometry, int4, int4)\r
+       RETURNS TEXT\r
+       AS 'SELECT _ST_AsGeoJson($1, $2, $3, $4)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+------------------------------------------------------------------------\r
+-- GeoHash (geohash.org)\r
+------------------------------------------------------------------------\r
+\r
+-- Availability 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_GeoHash(geometry, int4)\r
+       RETURNS TEXT\r
+               AS 'MODULE_PATHNAME', 'ST_GeoHash'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_GeoHash(geometry)\r
+       RETURNS TEXT\r
+       AS 'SELECT ST_GeoHash($1, 0)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+------------------------------------------------------------------------\r
+-- OGC defined\r
+------------------------------------------------------------------------\r
+-- PostGIS equivalent function: NumPoints(geometry)\r
+CREATE OR REPLACE FUNCTION ST_NumPoints(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_numpoints_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: NumGeometries(geometry)\r
+CREATE OR REPLACE FUNCTION ST_NumGeometries(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_numgeometries_collection'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: GeometryN(geometry)\r
+CREATE OR REPLACE FUNCTION ST_GeometryN(geometry,integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_geometryn_collection'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: Dimension(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Dimension(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dimension'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: ExteriorRing(geometry)\r
+CREATE OR REPLACE FUNCTION ST_ExteriorRing(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_exteriorring_polygon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: NumInteriorRings(geometry)\r
+CREATE OR REPLACE FUNCTION ST_NumInteriorRings(geometry)\r
+       RETURNS integer\r
+       AS 'MODULE_PATHNAME','LWGEOM_numinteriorrings_polygon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_NumInteriorRing(geometry)\r
+       RETURNS integer\r
+       AS 'MODULE_PATHNAME','LWGEOM_numinteriorrings_polygon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: InteriorRingN(geometry)\r
+CREATE OR REPLACE FUNCTION ST_InteriorRingN(geometry,integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_interiorringn_polygon'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3 -- this should not be deprecated (2011-01-04 robe)\r
+CREATE OR REPLACE FUNCTION GeometryType(geometry)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_getTYPE'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Not quite equivalent to GeometryType\r
+CREATE OR REPLACE FUNCTION ST_GeometryType(geometry)\r
+       RETURNS text\r
+       AS 'MODULE_PATHNAME', 'geometry_geometrytype'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: PointN(geometry,integer)\r
+CREATE OR REPLACE FUNCTION ST_PointN(geometry,integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_pointn_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_NumPatches(geometry)\r
+       RETURNS int4\r
+       AS '\r
+       SELECT CASE WHEN ST_GeometryType($1) = ''ST_PolyhedralSurface''\r
+       THEN ST_NumGeometries($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_PatchN(geometry, integer)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN ST_GeometryType($1) = ''ST_PolyhedralSurface''\r
+       THEN ST_GeometryN($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: X(geometry)\r
+CREATE OR REPLACE FUNCTION ST_X(geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME','LWGEOM_x_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: Y(geometry)\r
+CREATE OR REPLACE FUNCTION ST_Y(geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME','LWGEOM_y_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_Z(geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME','LWGEOM_z_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_M(geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME','LWGEOM_m_point'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION StartPoint(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_startpoint_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: StartPoint(geometry))\r
+CREATE OR REPLACE FUNCTION ST_StartPoint(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_startpoint_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION EndPoint(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_endpoint_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: EndPoint(geometry)\r
+CREATE OR REPLACE FUNCTION ST_EndPoint(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_endpoint_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: IsClosed(geometry)\r
+CREATE OR REPLACE FUNCTION ST_IsClosed(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_isclosed'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: IsEmpty(geometry)\r
+CREATE OR REPLACE FUNCTION ST_IsEmpty(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_isempty'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION SRID(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME','LWGEOM_get_srid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: getSRID(geometry)\r
+CREATE OR REPLACE FUNCTION ST_SRID(geometry)\r
+       RETURNS int4\r
+       AS 'MODULE_PATHNAME','LWGEOM_get_srid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION SetSRID(geometry,int4)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_set_srid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_SetSRID(geometry,int4)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_set_srid'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION AsBinary(geometry)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','LWGEOM_asBinary'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: AsBinary(geometry)\r
+CREATE OR REPLACE FUNCTION ST_AsBinary(geometry)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','LWGEOM_asBinary'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION AsBinary(geometry,text)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','LWGEOM_asBinary'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_AsBinary(geometry,text)\r
+       RETURNS bytea\r
+       AS 'MODULE_PATHNAME','LWGEOM_asBinary'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION AsText(geometry)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asText'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: AsText(geometry)\r
+CREATE OR REPLACE FUNCTION ST_AsText(geometry)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asText'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeometryFromText(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeometryFromText(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeometryFromText(text, int4)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeometryFromText(text, int4)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeomFromText(text)\r
+       RETURNS geometry AS 'SELECT geometryfromtext($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomFromText(text)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeomFromText(text, int4)\r
+       RETURNS geometry AS 'SELECT geometryfromtext($1, $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: ST_GeometryFromText(text, int4)\r
+CREATE OR REPLACE FUNCTION ST_GeomFromText(text, int4)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PointFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''POINT''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-- PostGIS equivalent function: PointFromText(text, int4)\r
+-- TODO: improve this ... by not duplicating constructor time.\r
+CREATE OR REPLACE FUNCTION ST_PointFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''POINT''\r
+       THEN ST_GeomFromText($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_LineFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''LINESTRING''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: LineFromText(text, int4)\r
+CREATE OR REPLACE FUNCTION ST_LineFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(GeomFromText($1, $2)) = ''LINESTRING''\r
+       THEN GeomFromText($1,$2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PolyFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''POLYGON''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: ST_PolygonFromText(text, int4)\r
+CREATE OR REPLACE FUNCTION ST_PolyFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''POLYGON''\r
+       THEN ST_GeomFromText($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PolygonFromText(text, int4)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_PolyFromText($1, $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PolygonFromText(text)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_PolyFromText($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: MLineFromText(text, int4)\r
+CREATE OR REPLACE FUNCTION ST_MLineFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE\r
+       WHEN geometrytype(ST_GeomFromText($1, $2)) = ''MULTILINESTRING''\r
+       THEN GeomFromText($1,$2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MLineFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''MULTILINESTRING''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiLineStringFromText(text)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_MLineFromText($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiLineStringFromText(text, int4)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_MLineFromText($1, $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: MPointFromText(text, int4)\r
+CREATE OR REPLACE FUNCTION ST_MPointFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''MULTIPOINT''\r
+       THEN GeomFromText($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MPointFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''MULTIPOINT''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPointFromText(text)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_MPointFromText($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPointFromText(text)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_MPointFromText($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: MPolyFromText(text, int4)\r
+CREATE OR REPLACE FUNCTION ST_MPolyFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1, $2)) = ''MULTIPOLYGON''\r
+       THEN ST_GeomFromText($1,$2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+--Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MPolyFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromText($1)) = ''MULTIPOLYGON''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPolygonFromText(text, int4)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_MPolyFromText($1, $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPolygonFromText(text)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_MPolyFromText($1)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomCollFromText(text, int4)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE\r
+       WHEN geometrytype(ST_GeomFromText($1, $2)) = ''GEOMETRYCOLLECTION''\r
+       THEN ST_GeomFromText($1,$2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomCollFromText(text)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE\r
+       WHEN geometrytype(ST_GeomFromText($1)) = ''GEOMETRYCOLLECTION''\r
+       THEN ST_GeomFromText($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeomFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+-- Deprecation in 1.2.3\r
+CREATE OR REPLACE FUNCTION GeomFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_SetSRID(GeomFromWKB($1), $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: GeomFromWKB(bytea, int)\r
+CREATE OR REPLACE FUNCTION ST_GeomFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS 'SELECT ST_SetSRID(ST_GeomFromWKB($1), $2)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: PointFromWKB(bytea, int)\r
+CREATE OR REPLACE FUNCTION ST_PointFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''POINT''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PointFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''POINT''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: LineFromWKB(bytea, int)\r
+CREATE OR REPLACE FUNCTION ST_LineFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''LINESTRING''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_LineFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''LINESTRING''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_LinestringFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''LINESTRING''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_LinestringFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(GeomFromWKB($1)) = ''LINESTRING''\r
+       THEN GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: PolyFromWKB(text, int)\r
+CREATE OR REPLACE FUNCTION ST_PolyFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''POLYGON''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PolyFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''POLYGON''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PolygonFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1,$2)) = ''POLYGON''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_PolygonFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''POLYGON''\r
+       THEN GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: MPointFromWKB(text, int)\r
+CREATE OR REPLACE FUNCTION ST_MPointFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTIPOINT''\r
+       THEN GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MPointFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOINT''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPointFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1,$2)) = ''MULTIPOINT''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPointFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOINT''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiLineFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTILINESTRING''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- PostGIS equivalent function: MLineFromWKB(text, int)\r
+CREATE OR REPLACE FUNCTION ST_MLineFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTILINESTRING''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MLineFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTILINESTRING''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+-- PostGIS equivalent function: MPolyFromWKB(bytea, int)\r
+CREATE OR REPLACE FUNCTION ST_MPolyFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTIPOLYGON''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MPolyFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOLYGON''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPolyFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1, $2)) = ''MULTIPOLYGON''\r
+       THEN ST_GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_MultiPolyFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE WHEN geometrytype(ST_GeomFromWKB($1)) = ''MULTIPOLYGON''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomCollFromWKB(bytea, int)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE\r
+       WHEN geometrytype(GeomFromWKB($1, $2)) = ''GEOMETRYCOLLECTION''\r
+       THEN GeomFromWKB($1, $2)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_GeomCollFromWKB(bytea)\r
+       RETURNS geometry\r
+       AS '\r
+       SELECT CASE\r
+       WHEN geometrytype(ST_GeomFromWKB($1)) = ''GEOMETRYCOLLECTION''\r
+       THEN ST_GeomFromWKB($1)\r
+       ELSE NULL END\r
+       '\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+--New functions\r
+\r
+-- Maximum distance between linestrings.\r
+\r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION _ST_MaxDistance(geometry,geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'\r
+       LANGUAGE 'C' IMMUTABLE STRICT; \r
+       \r
+-- Availability: 1.5.0\r
+CREATE OR REPLACE FUNCTION ST_MaxDistance(geometry,geometry)\r
+       RETURNS float8\r
+       AS 'SELECT _ST_MaxDistance(ST_ConvexHull($1), ST_ConvexHull($2))'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT; \r
+\r
+CREATE OR REPLACE FUNCTION ST_ClosestPoint(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_ShortestLine(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline2d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION _ST_LongestLine(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_longestline2d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_LongestLine(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'SELECT _ST_LongestLine(ST_ConvexHull($1), ST_ConvexHull($2))'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT; \r
+\r
+CREATE OR REPLACE FUNCTION _ST_DFullyWithin(geometry,geometry,float8)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin'\r
+       LANGUAGE 'C' IMMUTABLE STRICT; \r
+\r
+CREATE OR REPLACE FUNCTION ST_DFullyWithin(geometry, geometry, float8)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_DFullyWithin(ST_ConvexHull($1), ST_ConvexHull($2), $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE; \r
+       \r
+CREATE OR REPLACE FUNCTION ST_FlipCoordinates(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'ST_FlipCoordinates'\r
+       LANGUAGE 'C' IMMUTABLE STRICT; \r
+\r
+--\r
+-- SFSQL 1.1\r
+--\r
+-- BdPolyFromText(multiLineStringTaggedText String, SRID Integer): Polygon\r
+--\r
+--  Construct a Polygon given an arbitrary\r
+--  collection of closed linestrings as a\r
+--  MultiLineString text representation.\r
+--\r
+-- This is a PLPGSQL function rather then an SQL function\r
+-- To avoid double call of BuildArea (one to get GeometryType\r
+-- and another to actual return, in a CASE WHEN construct).\r
+-- Also, we profit from plpgsql to RAISE exceptions.\r
+--\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_BdPolyFromText(text, integer)\r
+RETURNS geometry\r
+AS $$\r
+DECLARE\r
+       geomtext alias for $1;\r
+       srid alias for $2;\r
+       mline geometry;\r
+       geom geometry;\r
+BEGIN\r
+       mline := ST_MultiLineStringFromText(geomtext, srid);\r
+\r
+       IF mline IS NULL\r
+       THEN\r
+               RAISE EXCEPTION 'Input is not a MultiLinestring';\r
+       END IF;\r
+\r
+       geom := ST_BuildArea(mline);\r
+\r
+       IF GeometryType(geom) != 'POLYGON'\r
+       THEN\r
+               RAISE EXCEPTION 'Input returns more then a single polygon, try using BdMPolyFromText instead';\r
+       END IF;\r
+\r
+       RETURN geom;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+--\r
+-- SFSQL 1.1\r
+--\r
+-- BdMPolyFromText(multiLineStringTaggedText String, SRID Integer): MultiPolygon\r
+--\r
+--  Construct a MultiPolygon given an arbitrary\r
+--  collection of closed linestrings as a\r
+--  MultiLineString text representation.\r
+--\r
+-- This is a PLPGSQL function rather then an SQL function\r
+-- To raise an exception in case of invalid input.\r
+--\r
+\r
+-- Availability: 1.2.2\r
+CREATE OR REPLACE FUNCTION ST_BdMPolyFromText(text, integer)\r
+RETURNS geometry\r
+AS $$\r
+DECLARE\r
+       geomtext alias for $1;\r
+       srid alias for $2;\r
+       mline geometry;\r
+       geom geometry;\r
+BEGIN\r
+       mline := ST_MultiLineStringFromText(geomtext, srid);\r
+\r
+       IF mline IS NULL\r
+       THEN\r
+               RAISE EXCEPTION 'Input is not a MultiLinestring';\r
+       END IF;\r
+\r
+       geom := ST_Multi(ST_BuildArea(mline));\r
+\r
+       RETURN geom;\r
+END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+#include "long_xact.sql.in.c"\r
+#include "sqlmm.sql.in.c"\r
+#include "geography.sql.in.c"\r
+\r
+\r
+---------------------------------------------------------------\r
+-- 3D-functions\r
+---------------------------------------------------------------\r
+\r
+CREATE OR REPLACE FUNCTION ST_3DDistance(geometry,geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_mindistance3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+       \r
+CREATE OR REPLACE FUNCTION ST_3DMaxDistance(geometry,geometry)\r
+       RETURNS float8\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;       \r
+\r
+CREATE OR REPLACE FUNCTION ST_3DClosestPoint(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+CREATE OR REPLACE FUNCTION ST_3DShortestLine(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+\r
+CREATE OR REPLACE FUNCTION ST_3DLongestLine(geometry,geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_longestline3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+       \r
+CREATE OR REPLACE FUNCTION _ST_3DDWithin(geometry,geometry,float8)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dwithin3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+       \r
+CREATE OR REPLACE FUNCTION ST_3DDWithin(geometry,geometry,float8)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_3DDWithin($1, $2, $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE\r
+       COST 100;\r
+       \r
+CREATE OR REPLACE FUNCTION _ST_3DDFullyWithin(geometry,geometry,float8)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin3d'\r
+       LANGUAGE 'C' IMMUTABLE STRICT\r
+       COST 100;\r
+       \r
+CREATE OR REPLACE FUNCTION ST_3DDFullyWithin(geometry,geometry,float8)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && ST_Expand($2,$3) AND $2 && ST_Expand($1,$3) AND _ST_3DDFullyWithin($1, $2, $3)'\r
+       LANGUAGE 'SQL' IMMUTABLE\r
+       COST 100;\r
+       \r
+CREATE OR REPLACE FUNCTION ST_3DIntersects(geometry,geometry)\r
+       RETURNS boolean\r
+       AS 'SELECT $1 && $2 AND _ST_3DDWithin($1, $2, 0.0)'\r
+       LANGUAGE 'SQL' IMMUTABLE\r
+       COST 100;\r
+       \r
+       \r
+---------------------------------------------------------------\r
+-- SQL-MM\r
+---------------------------------------------------------------\r
+\r
+--\r
+-- SQL-MM\r
+--\r
+-- ST_CurveToLine(Geometry geometry, SegmentsPerQuarter integer)\r
+--\r
+-- Converts a given geometry to a linear geometry.  Each curveed\r
+-- geometry or segment is converted into a linear approximation using\r
+-- the given number of segments per quarter circle.\r
+CREATE OR REPLACE FUNCTION ST_CurveToLine(geometry, integer)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_curve_segmentize'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+--\r
+-- SQL-MM\r
+--\r
+-- ST_CurveToLine(Geometry geometry, SegmentsPerQuarter integer)\r
+--\r
+-- Converts a given geometry to a linear geometry.  Each curveed\r
+-- geometry or segment is converted into a linear approximation using\r
+-- the default value of 32 segments per quarter circle\r
+CREATE OR REPLACE FUNCTION ST_CurveToLine(geometry)\r
+       RETURNS geometry AS 'SELECT ST_CurveToLine($1, 32)'\r
+       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_HasArc(geometry)\r
+       RETURNS boolean\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_has_arc'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_LineToCurve(geometry)\r
+       RETURNS geometry\r
+       AS 'MODULE_PATHNAME', 'LWGEOM_line_desegmentize'\r
+       LANGUAGE 'C' IMMUTABLE STRICT;\r
+---------------------------------------------------------------\r
+-- END\r
+---------------------------------------------------------------\r
+\r
+\r
+---------------------------------------------------------------\r
+-- USER CONTRIBUTED\r
+---------------------------------------------------------------\r
+\r
+-----------------------------------------------------------------------\r
+-- ST_MinimumBoundingCircle(inputgeom geometry, segs_per_quarter integer)\r
+-----------------------------------------------------------------------\r
+-- Returns the smallest circle polygon that can fully contain a geometry\r
+-- Defaults to 48 segs per quarter to approximate a circle\r
+-- Contributed by Bruce Rindahl\r
+-- Availability: 1.4.0\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION ST_MinimumBoundingCircle(inputgeom geometry, segs_per_quarter integer)\r
+       RETURNS geometry AS\r
+$BODY$\r
+       DECLARE\r
+       hull GEOMETRY;\r
+       ring GEOMETRY;\r
+       center GEOMETRY;\r
+       radius DOUBLE PRECISION;\r
+       dist DOUBLE PRECISION;\r
+       d DOUBLE PRECISION;\r
+       idx1 integer;\r
+       idx2 integer;\r
+       l1 GEOMETRY;\r
+       l2 GEOMETRY;\r
+       p1 GEOMETRY;\r
+       p2 GEOMETRY;\r
+       a1 DOUBLE PRECISION;\r
+       a2 DOUBLE PRECISION;\r
+\r
+\r
+       BEGIN\r
+\r
+       -- First compute the ConvexHull of the geometry\r
+       hull = ST_ConvexHull(inputgeom);\r
+       --A point really has no MBC\r
+       IF ST_GeometryType(hull) = 'ST_Point' THEN\r
+               RETURN hull;\r
+       END IF;\r
+       -- convert the hull perimeter to a linestring so we can manipulate individual points\r
+       --If its already a linestring force it to a closed linestring\r
+       ring = CASE WHEN ST_GeometryType(hull) = 'ST_LineString' THEN ST_AddPoint(hull, ST_StartPoint(hull)) ELSE ST_ExteriorRing(hull) END;\r
+\r
+       dist = 0;\r
+       -- Brute Force - check every pair\r
+       FOR i in 1 .. (ST_NumPoints(ring)-2)\r
+               LOOP\r
+                       FOR j in i .. (ST_NumPoints(ring)-1)\r
+                               LOOP\r
+                               d = ST_Distance(ST_PointN(ring,i),ST_PointN(ring,j));\r
+                               -- Check the distance and update if larger\r
+                               IF (d > dist) THEN\r
+                                       dist = d;\r
+                                       idx1 = i;\r
+                                       idx2 = j;\r
+                               END IF;\r
+                       END LOOP;\r
+               END LOOP;\r
+\r
+       -- We now have the diameter of the convex hull.  The following line returns it if desired.\r
+       -- RETURN MakeLine(PointN(ring,idx1),PointN(ring,idx2));\r
+\r
+       -- Now for the Minimum Bounding Circle.  Since we know the two points furthest from each\r
+       -- other, the MBC must go through those two points. Start with those points as a diameter of a circle.\r
+\r
+       -- The radius is half the distance between them and the center is midway between them\r
+       radius = ST_Distance(ST_PointN(ring,idx1),ST_PointN(ring,idx2)) / 2.0;\r
+       center = ST_Line_interpolate_point(ST_MakeLine(ST_PointN(ring,idx1),ST_PointN(ring,idx2)),0.5);\r
+\r
+       -- Loop through each vertex and check if the distance from the center to the point\r
+       -- is greater than the current radius.\r
+       FOR k in 1 .. (ST_NumPoints(ring)-1)\r
+               LOOP\r
+               IF(k <> idx1 and k <> idx2) THEN\r
+                       dist = ST_Distance(center,ST_PointN(ring,k));\r
+                       IF (dist > radius) THEN\r
+                               -- We have to expand the circle.  The new circle must pass trhough\r
+                               -- three points - the two original diameters and this point.\r
+\r
+                               -- Draw a line from the first diameter to this point\r
+                               l1 = ST_Makeline(ST_PointN(ring,idx1),ST_PointN(ring,k));\r
+                               -- Compute the midpoint\r
+                               p1 = ST_line_interpolate_point(l1,0.5);\r
+                               -- Rotate the line 90 degrees around the midpoint (perpendicular bisector)\r
+                               l1 = ST_Translate(ST_Rotate(ST_Translate(l1,-X(p1),-Y(p1)),pi()/2),X(p1),Y(p1));\r
+                               --  Compute the azimuth of the bisector\r
+                               a1 = ST_Azimuth(ST_PointN(l1,1),ST_PointN(l1,2));\r
+                               --  Extend the line in each direction the new computed distance to insure they will intersect\r
+                               l1 = ST_AddPoint(l1,ST_Makepoint(X(ST_PointN(l1,2))+sin(a1)*dist,Y(ST_PointN(l1,2))+cos(a1)*dist),-1);\r
+                               l1 = ST_AddPoint(l1,ST_Makepoint(X(ST_PointN(l1,1))-sin(a1)*dist,Y(ST_PointN(l1,1))-cos(a1)*dist),0);\r
+\r
+                               -- Repeat for the line from the point to the other diameter point\r
+                               l2 = ST_Makeline(ST_PointN(ring,idx2),ST_PointN(ring,k));\r
+                               p2 = ST_Line_interpolate_point(l2,0.5);\r
+                               l2 = ST_Translate(ST_Rotate(ST_Translate(l2,-X(p2),-Y(p2)),pi()/2),X(p2),Y(p2));\r
+                               a2 = ST_Azimuth(ST_PointN(l2,1),ST_PointN(l2,2));\r
+                               l2 = ST_AddPoint(l2,ST_Makepoint(X(ST_PointN(l2,2))+sin(a2)*dist,Y(ST_PointN(l2,2))+cos(a2)*dist),-1);\r
+                               l2 = ST_AddPoint(l2,ST_Makepoint(X(ST_PointN(l2,1))-sin(a2)*dist,Y(ST_PointN(l2,1))-cos(a2)*dist),0);\r
+\r
+                               -- The new center is the intersection of the two bisectors\r
+                               center = ST_Intersection(l1,l2);\r
+                               -- The new radius is the distance to any of the three points\r
+                               radius = ST_Distance(center,ST_PointN(ring,idx1));\r
+                       END IF;\r
+               END IF;\r
+               END LOOP;\r
+       --DONE!!  Return the MBC via the buffer command\r
+       RETURN ST_Buffer(center,radius,segs_per_quarter);\r
+\r
+       END;\r
+$BODY$\r
+       LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_MinimumBoundingCircle(geometry)\r
+ RETURNS geometry AS\r
+'SELECT ST_MinimumBoundingCircle($1, 48)'\r
+ LANGUAGE 'sql' IMMUTABLE STRICT;\r
\r
+-- ST_ConcaveHull and Helper functions starts here --\r
+-----------------------------------------------------------------------\r
+-- Contributed by Regina Obe and Leo Hsu\r
+-- Availability: 2.0.0\r
+-----------------------------------------------------------------------\r
+CREATE OR REPLACE FUNCTION _ST_ConcaveHull(param_inputgeom geometry)\r
+  RETURNS geometry AS\r
+$$\r
+       DECLARE     \r
+       vexhull GEOMETRY;\r
+       var_resultgeom geometry;\r
+       vexring GEOMETRY;\r
+       cavering GEOMETRY;\r
+       cavept geometry[];\r
+       seglength double precision;\r
+       var_tempgeom geometry;\r
+       i integer;\r
+       \r
+       BEGIN\r
+\r
+               -- First compute the ConvexHull of the geometry\r
+               vexhull := ST_ConvexHull(param_inputgeom);\r
+               --A point really has no concave hull\r
+               IF ST_GeometryType(vexhull) = 'ST_Point' OR ST_GeometryType(vexHull) = 'ST_LineString' THEN\r
+                       RETURN vexhull;\r
+               END IF;\r
+\r
+               -- convert the hull perimeter to a linestring so we can manipulate individual points\r
+               vexring := CASE WHEN ST_GeometryType(vexhull) = 'ST_LineString' THEN vexhull ELSE ST_ExteriorRing(vexhull) END;\r
+               seglength := ST_Length(vexring)/least(ST_NPoints(vexring)*2,1000) ;\r
+\r
+               vexring := ST_Segmentize(vexring, seglength);\r
+               -- find the point on the original geom that is closest to each point of the convex hull and make a new linestring out of it.\r
+               cavering := ST_Collect(\r
+                       ARRAY(\r
+\r
+                               SELECT \r
+                                       ST_ClosestPoint(param_inputgeom, pt ) As the_geom\r
+                                       FROM (\r
+                                               SELECT  ST_PointN(vexring, n ) As pt, n\r
+                                                       FROM \r
+                                                       generate_series(1, ST_NPoints(vexring) ) As n\r
+                                               ) As pt\r
+                               \r
+                               )\r
+                       )\r
+               ; \r
+\r
+               var_resultgeom := ST_MakePolygon(ST_MakeLine(geom)) \r
+                       FROM ST_Dump(cavering) As foo;\r
+               \r
+               IF NOT ST_IsValid(var_resultgeom) THEN\r
+                   --RAISE NOTICE '_ST_Concavehull invalid %', ST_AsText(var_resultgeom);\r
+                   var_tempgeom := ST_BuildArea(var_resultgeom); -- try to make valid\r
+                   IF NOT ST_IsValid(var_tempgeom) THEN\r
+                               var_resultgeom := ST_Buffer(var_resultgeom,ST_Length(cavering)/1000, 'quad_segs=3'); -- try to make valid\r
+                   END IF;\r
+                    --if still invalid or doens't  contain the geometry just return convex hull\r
+                   IF NOT ST_IsValid(var_resultgeom) or ST_GeometryType(var_resultgeom) <> 'ST_Polygon' THEN\r
+                               var_resultgeom := ST_ConvexHull(param_inputgeom);\r
+                   ELSIF ST_GeometryType(param_inputgeom) ILIKE '%Geometry%' THEN\r
+                               IF EXISTS(SELECT geom FROM ST_Dump(param_inputgeom) WHERE NOT ST_Covers(var_resultgeom,geom) ) THEN \r
+                               --we have to explode inputgeom since geos doesn't support geometrycollections for containment check\r
+                                  var_resultgeom := ST_ConvexHull(param_inputgeom);\r
+                               END IF;\r
+                       ELSIF NOT ST_Contains(var_resultgeom, param_inputgeom) THEN\r
+                               var_resultgeom := ST_ConvexHull(param_inputgeom);\r
+                       END IF;\r
+               END IF;\r
+               RETURN var_resultgeom;\r
+       \r
+       END;\r
+$$\r
+  LANGUAGE 'plpgsql' IMMUTABLE STRICT\r
+  COST 100;\r
+  \r
+CREATE OR REPLACE FUNCTION ST_ConcaveHull(param_geom geometry, param_pctconvex float, param_allow_holes boolean) RETURNS geometry AS\r
+$$\r
+       DECLARE\r
+               var_convhull geometry := ST_ConvexHull(param_geom);\r
+               var_param_geom geometry := param_geom;\r
+               var_initarea float := ST_Area(var_convhull);\r
+               var_newarea float := var_initarea;\r
+               var_div integer := 6; /** this is the 1/var_div is the percent increase we will allow per triangle to keep speed decent **/\r
+               var_tempgeom geometry;\r
+               var_tempgeom2 geometry;\r
+               var_cent geometry;\r
+               var_geoms geometry[4]; /** We will cut the current geometry into 4 triangular quadrants along the centroid/extent **/\r
+               var_enline geometry;\r
+               var_resultgeom geometry;\r
+               var_atempgeoms geometry[];\r
+               var_buf float := 1; /**tolerance so that geometries that are right on the extent don't get accidentally clipped off **/\r
+       BEGIN\r
+               -- We start with convex hull as our base\r
+               var_resultgeom := var_convhull;\r
+               \r
+               IF param_pctconvex = 1 THEN\r
+                       return var_resultgeom;\r
+               ELSIF ST_GeometryType(var_param_geom) = 'ST_Polygon' THEN -- it is as concave as it is going to get\r
+                       IF param_allow_holes THEN -- leave the holes\r
+                               RETURN var_param_geom;\r
+                       ELSE -- remove the holes\r
+                               var_resultgeom := ST_MakePolygon(ST_ExteriorRing(var_param_geom));\r
+                               RETURN var_resultgeom;\r
+                       END IF;\r
+               END IF;\r
+               IF ST_Dimension(var_resultgeom) > 1 AND param_pctconvex BETWEEN 0 and 0.98 THEN\r
+               -- get linestring that forms envelope of geometry\r
+                       var_enline := ST_Boundary(ST_Envelope(var_param_geom));\r
+                       var_buf := ST_Length(var_enline)/1000.0;\r
+                       IF ST_GeometryType(var_param_geom) = 'ST_MultiPoint' AND ST_NumGeometries(var_param_geom) BETWEEN 4 and 200 THEN\r
+                       -- we make polygons out of points since they are easier to cave in. \r
+                       -- Note we limit to between 4 and 200 points because this process is slow and gets quadratically slow\r
+                               var_buf := sqrt(ST_Area(var_convhull)*0.8/(ST_NumGeometries(var_param_geom)*ST_NumGeometries(var_param_geom)));\r
+                               var_atempgeoms := ARRAY(SELECT geom FROM ST_DumpPoints(var_param_geom));\r
+                               -- 5 and 10 and just fudge factors\r
+                               var_tempgeom := ST_Union(ARRAY(SELECT geom\r
+                                               FROM (\r
+                                               -- fuse near neighbors together\r
+                                               SELECT DISTINCT ON (i) i,  ST_Distance(var_atempgeoms[i],var_atempgeoms[j]), ST_Buffer(ST_MakeLine(var_atempgeoms[i], var_atempgeoms[j]) , var_buf*5, 'quad_segs=3') As geom\r
+                                                               FROM generate_series(1,array_upper(var_atempgeoms, 1)) As i\r
+                                                                       INNER JOIN generate_series(1,array_upper(var_atempgeoms, 1)) As j \r
+                                                                               ON (\r
+                                                                NOT ST_Intersects(var_atempgeoms[i],var_atempgeoms[j])\r
+                                                                       AND ST_DWithin(var_atempgeoms[i],var_atempgeoms[j], var_buf*10)\r
+                                                                       )\r
+                                                               UNION ALL\r
+                                               -- catch the ones with no near neighbors\r
+                                                               SELECT i, 0, ST_Buffer(var_atempgeoms[i] , var_buf*10, 'quad_segs=3') As geom\r
+                                                               FROM generate_series(1,array_upper(var_atempgeoms, 1)) As i\r
+                                                                       LEFT JOIN generate_series(ceiling(array_upper(var_atempgeoms,1)/2)::integer,array_upper(var_atempgeoms, 1)) As j \r
+                                                                               ON (\r
+                                                                NOT ST_Intersects(var_atempgeoms[i],var_atempgeoms[j])\r
+                                                                       AND ST_DWithin(var_atempgeoms[i],var_atempgeoms[j], var_buf*10) \r
+                                                                       )\r
+                                                                       WHERE j IS NULL\r
+                                                               ORDER BY 1, 2\r
+                                                       ) As foo        ) );\r
+                               IF ST_IsValid(var_tempgeom) AND ST_GeometryType(var_tempgeom) = 'ST_Polygon' THEN\r
+                                       var_tempgeom := ST_Intersection(var_tempgeom, var_convhull);\r
+                                       IF param_allow_holes THEN\r
+                                               var_param_geom := var_tempgeom;\r
+                                       ELSE\r
+                                               var_param_geom := ST_MakePolygon(ST_ExteriorRing(var_tempgeom));\r
+                                       END IF;\r
+                                       return var_param_geom;\r
+                               ELSIF ST_IsValid(var_tempgeom) THEN\r
+                                       var_param_geom := ST_Intersection(var_tempgeom, var_convhull);  \r
+                               END IF;\r
+                       END IF;\r
+\r
+                       IF ST_GeometryType(var_param_geom) = 'ST_Polygon' THEN\r
+                               IF NOT param_allow_holes THEN\r
+                                       var_param_geom := ST_MakePolygon(ST_ExteriorRing(var_param_geom));\r
+                               END IF;\r
+                               return var_param_geom;\r
+                       END IF;\r
+            var_cent := ST_Centroid(var_param_geom);\r
+            IF (ST_XMax(var_enline) - ST_XMin(var_enline) ) > var_buf AND (ST_YMax(var_enline) - ST_YMin(var_enline) ) > var_buf THEN\r
+                    IF ST_Dwithin(ST_Centroid(var_convhull) , ST_Centroid(ST_Envelope(var_param_geom)), var_buf/2) THEN\r
+                -- If the geometric dimension is > 1 and the object is symettric (cutting at centroid will not work -- offset a bit)\r
+                        var_cent := ST_Translate(var_cent, (ST_XMax(var_enline) - ST_XMin(var_enline))/1000,  (ST_YMAX(var_enline) - ST_YMin(var_enline))/1000);\r
+                    ELSE\r
+                        -- uses closest point on geometry to centroid. I can't explain why we are doing this\r
+                        var_cent := ST_ClosestPoint(var_param_geom,var_cent);\r
+                    END IF;\r
+                    IF ST_DWithin(var_cent, var_enline,var_buf) THEN\r
+                        var_cent := ST_centroid(ST_Envelope(var_param_geom));\r
+                    END IF;\r
+                    -- break envelope into 4 triangles about the centroid of the geometry and returned the clipped geometry in each quadrant\r
+                    FOR i in 1 .. 4 LOOP\r
+                       var_geoms[i] := ST_MakePolygon(ST_MakeLine(ARRAY[ST_PointN(var_enline,i), ST_PointN(var_enline,i+1), var_cent, ST_PointN(var_enline,i)]));\r
+                       var_geoms[i] := ST_Intersection(var_param_geom, ST_Buffer(var_geoms[i],var_buf));\r
+                       IF ST_IsValid(var_geoms[i]) THEN \r
+                            \r
+                       ELSE\r
+                            var_geoms[i] := ST_BuildArea(ST_MakeLine(ARRAY[ST_PointN(var_enline,i), ST_PointN(var_enline,i+1), var_cent, ST_PointN(var_enline,i)]));\r
+                       END IF; \r
+                    END LOOP;\r
+                    var_tempgeom := ST_Union(ARRAY[ST_ConvexHull(var_geoms[1]), ST_ConvexHull(var_geoms[2]) , ST_ConvexHull(var_geoms[3]), ST_ConvexHull(var_geoms[4])]); \r
+                    --RAISE NOTICE 'Curr vex % ', ST_AsText(var_tempgeom);\r
+                    IF ST_Area(var_tempgeom) <= var_newarea AND ST_IsValid(var_tempgeom)  THEN --AND ST_GeometryType(var_tempgeom) ILIKE '%Polygon'\r
+                        \r
+                        var_tempgeom := ST_Buffer(ST_ConcaveHull(var_geoms[1],least(param_pctconvex + param_pctconvex/var_div),true),var_buf, 'quad_segs=2');\r
+                        FOR i IN 1 .. 4 LOOP\r
+                            var_geoms[i] := ST_Buffer(ST_ConcaveHull(var_geoms[i],least(param_pctconvex + param_pctconvex/var_div),true), var_buf, 'quad_segs=2');\r
+                            IF ST_IsValid(var_geoms[i]) Then\r
+                                var_tempgeom := ST_Union(var_tempgeom, var_geoms[i]);\r
+                            ELSE\r
+                                RAISE NOTICE 'Not valid % %', i, ST_AsText(var_tempgeom);\r
+                                var_tempgeom := ST_Union(var_tempgeom, ST_ConvexHull(var_geoms[i]));\r
+                            END IF; \r
+                        END LOOP;\r
+\r
+                        --RAISE NOTICE 'Curr concave % ', ST_AsText(var_tempgeom);\r
+                        IF ST_IsValid(var_tempgeom) THEN\r
+                            var_resultgeom := var_tempgeom;\r
+                        END IF;\r
+                        var_newarea := ST_Area(var_resultgeom);\r
+                    ELSIF ST_IsValid(var_tempgeom) THEN\r
+                        var_resultgeom := var_tempgeom;\r
+                    END IF;\r
+\r
+                    IF ST_NumGeometries(var_resultgeom) > 1  THEN\r
+                        var_tempgeom := _ST_ConcaveHull(var_resultgeom);\r
+                        IF ST_IsValid(var_tempgeom) AND ST_GeometryType(var_tempgeom) ILIKE 'ST_Polygon' THEN\r
+                            var_resultgeom := var_tempgeom;\r
+                        ELSE\r
+                            var_resultgeom := ST_Buffer(var_tempgeom,var_buf, 'quad_segs=2');\r
+                        END IF;\r
+                    END IF;\r
+                    IF param_allow_holes = false THEN \r
+                    -- only keep exterior ring since we do not want holes\r
+                        var_resultgeom := ST_MakePolygon(ST_ExteriorRing(var_resultgeom));\r
+                    END IF;\r
+                ELSE\r
+                    var_resultgeom := ST_Buffer(var_resultgeom,var_buf);\r
+                END IF;\r
+                var_resultgeom := ST_Intersection(var_resultgeom, ST_ConvexHull(var_param_geom));\r
+            ELSE\r
+                -- dimensions are too small to cut\r
+                var_resultgeom := _ST_ConcaveHull(var_param_geom);\r
+            END IF;\r
+            RETURN var_resultgeom;\r
+       END;\r
+$$\r
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
+\r
+CREATE OR REPLACE FUNCTION ST_ConcaveHull(param_geom geometry, param_pctconvex float)\r
+       RETURNS geometry AS\r
+$$\r
+       SELECT ST_ConcaveHull($1, $2, false);\r
+$$\r
+LANGUAGE 'sql' IMMUTABLE STRICT;\r
+-- ST_ConcaveHull and Helper functions end here --\r
+\r
+-----------------------------------------------------------------------\r
+-- X3D OUTPUT\r
+-----------------------------------------------------------------------\r
+-- _ST_AsX3D(version, geom, precision, option, attribs)\r
+CREATE OR REPLACE FUNCTION _ST_AsX3D(int4, geometry, int4, int4, text)\r
+       RETURNS TEXT\r
+       AS 'MODULE_PATHNAME','LWGEOM_asX3D'\r
+       LANGUAGE 'C' IMMUTABLE;\r
+       \r
+-- ST_AsX3D(geom, precision)\r
+CREATE OR REPLACE FUNCTION ST_AsX3D(geom geometry, prec int4)\r
+       RETURNS TEXT\r
+       AS $$SELECT _ST_AsX3D(3,$1,$2,1,'');$$\r
+       LANGUAGE 'sql' IMMUTABLE;\r
+COMMIT;\r
+\r
+#include "postgis_drop.sql.in.c"\r