]> granicus.if.org Git - postgis/commitdiff
Really remove the dos linefeeds this time (#1598)
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 22 Feb 2012 19:18:21 +0000 (19:18 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 22 Feb 2012 19:18:21 +0000 (19:18 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@9263 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/lwout_x3d.c
postgis/lwgeom_export.c
postgis/lwgeom_rtree.h
postgis/postgis.sql.in.c

index 80d0625811511a319bd30f06fe8dbf66cbab1299..e3ff033d2425b065353b3f4709d41b3fe0b1fd86 100644 (file)
-/**********************************************************************\r
- * $Id$\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
-* @file X3D output routines.\r
-*\r
-**********************************************************************/\r
-\r
-\r
-#include <string.h>\r
-#include "liblwgeom_internal.h"\r
-\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 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, int is_closed);\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
-       {\r
-               /** We might change this later, but putting a polygon in an indexed face set\r
-               * seems like the simplest way to go so treat just like a mulitpolygon\r
-               */\r
-               LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom);\r
-               char *ret = asx3d3_multi(tmp, srs, precision, opts, defid);\r
-               lwcollection_free(tmp);\r
-               return ret;\r
-       }\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, 0);\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, lwline_is_closed((LWLINE *) line));\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
-       //ptr += sprintf(ptr, "");\r
-       ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed(line));\r
-       return (ptr-output);\r
-}\r
-\r
-/* Calculate the coordIndex property of the IndexedLineSet for the multilinestring */\r
-static size_t\r
-asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output)\r
-{\r
-       char *ptr=output;\r
-       LWLINE *geom;\r
-       int i, j, k, si;\r
-       POINTARRAY *pa;\r
-       int np;\r
-\r
-       j = 0;\r
-       for (i=0; i < mgeom->ngeoms; i++)\r
-       {\r
-               geom = (LWLINE *) mgeom->geoms[i];\r
-               pa = geom->points;\r
-               np = pa->npoints;\r
-               si = j; //start index of first point of linestring\r
-               for (k=0; k < np ; k++)\r
-               {\r
-                       if (k)\r
-                       {\r
-                               ptr += sprintf(ptr, " ");\r
-                       }\r
-                       /** if the linestring is closed, we put the start point index\r
-                       *   for the last vertex to denote use first point\r
-                       *    and don't increment the index **/\r
-                       if (!lwline_is_closed(geom) || k < (np -1) )\r
-                       {\r
-                               ptr += sprintf(ptr, "%d", j);\r
-                               j += 1;\r
-                       }\r
-                       else\r
-                       {\r
-                               ptr += sprintf(ptr,"%d", si);\r
-                       }\r
-               }\r
-               if (i < (mgeom->ngeoms - 1) )\r
-               {\r
-                       ptr += sprintf(ptr, " -1 "); //separator for each linestring\r
-               }\r
-       }\r
-       return (ptr-output);\r
-}\r
-\r
-/* Calculate the coordIndex property of the IndexedLineSet for a multipolygon\r
-    This is not ideal -- would be really nice to just share this function with psurf,\r
-    but I'm not smart enough to do that yet*/\r
-static size_t\r
-asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output)\r
-{\r
-       char *ptr=output;\r
-       LWPOLY *patch;\r
-       int i, j, k, l;\r
-       int np;\r
-       j = 0;\r
-       for (i=0; i<psur->ngeoms; i++)\r
-       {\r
-               patch = (LWPOLY *) psur->geoms[i];\r
-               for (l=0; l < patch->nrings; l++)\r
-               {\r
-                       np = patch->rings[l]->npoints - 1;\r
-                       for (k=0; k < np ; k++)\r
-                       {\r
-                               if (k)\r
-                               {\r
-                                       ptr += sprintf(ptr, " ");\r
-                               }\r
-                               ptr += sprintf(ptr, "%d", (j + k));\r
-                       }\r
-                       j += k;\r
-                       if (l < (patch->nrings - 1) )\r
-                       {\r
-                               /** @todo TODO: Decide the best way to render holes\r
-                               *  Evidentally according to my X3D expert the X3D consortium doesn't really\r
-                               *  support holes and it's an issue of argument among many that feel it should. He thinks CAD x3d extensions to spec might.\r
-                               *  What he has done and others developing X3D exports to simulate a hole is to cut around it.\r
-                               *  So if you have a donut, you would cut it into half and have 2 solid polygons.  Not really sure the best way to handle this.\r
-                               *  For now will leave it as polygons stacked on top of each other -- which is what we are doing here and perhaps an option\r
-                               *  to color differently.  It's not ideal but the alternative sounds complicated.\r
-                               **/\r
-                               ptr += sprintf(ptr, " -1 "); //separator for each inner ring. Ideally we should probably triangulate and cut around as others do\r
-                       }\r
-               }\r
-               if (i < (psur->ngeoms - 1) )\r
-               {\r
-                       ptr += sprintf(ptr, " -1 "); //separator for each subgeom\r
-               }\r
-       }\r
-       return (ptr-output);\r
-}\r
-\r
-/** Return the linestring as an X3D LineSet */\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 = sizeof("<LineSet><CoordIndex ='' /></LineSet>") + 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
-/** Compute the string space needed for the IndexedFaceSet representation of the polygon **/\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("<IndexedFaceSet></IndexedFaceSet>") + (defidlen*3) ) * 2 + 6 * (poly->nrings - 1);\r
-\r
-       for (i=0; i<poly->nrings; i++)\r
-               size += pointArray_X3Dsize(poly->rings[i], precision);\r
-\r
-       return size;\r
-}\r
-\r
-/** Compute the X3D coordinates of the polygon **/\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))\r
-               dimension = 3;\r
-       ptr += pointArray_toX3D3(poly->rings[0], ptr, precision, opts, 1);\r
-       for (i=1; i<poly->nrings; i++)\r
-       {\r
-               ptr += sprintf(ptr, " "); //inner ring points start\r
-               ptr += pointArray_toX3D3(poly->rings[i], ptr, precision, opts,1);\r
-       }\r
-       return (ptr-output);\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 index=''></IndexedTriangleSet>") + defidlen + 6;\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
-       ptr += pointArray_toX3D3(triangle->points, ptr, precision, opts, 1);\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
-       char *ptr, *x3dtype;\r
-       int i;\r
-       int dimension=2;\r
-\r
-       if (FLAGS_GET_Z(col->flags)) dimension = 3;\r
-       LWGEOM *subgeom;\r
-       ptr = output;\r
-       x3dtype="";\r
-\r
-\r
-       switch (col->type)\r
-       {\r
-        case MULTIPOINTTYPE:\r
-            x3dtype = "PointSet";\r
-            if ( dimension == 2 ){ /** Use Polypoint2D instead **/\r
-                x3dtype = "Polypoint2D";   \r
-                ptr += sprintf(ptr, "<%s %s point='", x3dtype, defid);\r
-            }\r
-            else {\r
-                ptr += sprintf(ptr, "<%s %s>", x3dtype, defid);\r
-            }\r
-            break;\r
-        case MULTILINETYPE:\r
-            x3dtype = "IndexedLineSet";\r
-            ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid);\r
-            ptr += asx3d3_mline_coordindex((const LWMLINE *)col, ptr);\r
-            ptr += sprintf(ptr, "'>");\r
-            break;\r
-        case MULTIPOLYGONTYPE:\r
-            x3dtype = "IndexedFaceSet";\r
-            ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid);\r
-            ptr += asx3d3_mpoly_coordindex((const LWMPOLY *)col, ptr);\r
-            ptr += sprintf(ptr, "'>");\r
-            break;\r
-        default:\r
-            lwerror("asx3d3_multi_buf: '%s' geometry type not supported", lwtype_name(col->type));\r
-            return 0;\r
-    }\r
-    if (dimension == 3){\r
-        ptr += sprintf(ptr, "<Coordinate point='");\r
-    }\r
-\r
-       for (i=0; i<col->ngeoms; i++)\r
-       {\r
-               subgeom = col->geoms[i];\r
-               if (subgeom->type == POINTTYPE)\r
-               {\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
-                       ptr += asx3d3_line_coords((LWLINE*)subgeom, ptr, precision, opts);\r
-                       ptr += sprintf(ptr, " ");\r
-               }\r
-               else if (subgeom->type == POLYGONTYPE)\r
-               {\r
-                       ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);\r
-                       ptr += sprintf(ptr, " ");\r
-               }\r
-       }\r
-\r
-       /* Close outmost tag */\r
-       if (dimension == 3){\r
-           ptr += sprintf(ptr, "' /></%s>", x3dtype);\r
-       }\r
-       else { ptr += sprintf(ptr, "' />"); }    \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
-\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 space 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
-               {\r
-                       if (k)\r
-                       {\r
-                               ptr += sprintf(ptr, " ");\r
-                       }\r
-                       ptr += sprintf(ptr, "%d", (j + k));\r
-               }\r
-               if (i < (psur->ngeoms - 1) )\r
-               {\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
-               if (i < (psur->ngeoms - 1) )\r
-               {\r
-                       ptr += sprintf(ptr, " "); //only add a trailing space if its not the last polygon in the set\r
-               }\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
-       /** Need to make space for size of additional attributes,\r
-       ** the coordIndex has a value for each edge for each triangle plus a space to separate so we need at least that much extra room ***/\r
-       size = sizeof("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + tin->ngeoms*12;\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
-       ptr += sprintf(ptr, "<IndexedTriangleSet %s index='",defid);\r
-       k = 0;\r
-       /** Fill in triangle index **/\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
-               {\r
-                       ptr += sprintf(ptr, " ");\r
-               }\r
-               k += 3;\r
-       }\r
-\r
-       ptr += sprintf(ptr, "'><Coordinate 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
-               if (i < (tin->ngeoms - 1) )\r
-               {\r
-                       ptr += sprintf(ptr, " ");\r
-               }\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 )\r
-               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, coordinates are separated by a space separator\r
- */\r
-static size_t\r
-pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_closed)\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
-                       /** Only output the point if it is not the last point of a closed object or it is a non-closed type **/\r
-                       if ( !is_closed || i < (pa->npoints - 1) )\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 )\r
-                                       ptr += sprintf(ptr, " ");\r
-                               ptr += sprintf(ptr, "%s %s", x, y);\r
-                       }\r
-               }\r
-       }\r
-       else\r
-       {\r
-               for (i=0; i<pa->npoints; i++)\r
-               {\r
-                       /** Only output the point if it is not the last point of a closed object or it is a non-closed type **/\r
-                       if ( !is_closed || i < (pa->npoints - 1) )\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 )\r
-                                       ptr += sprintf(ptr, " ");\r
-\r
-                               ptr += sprintf(ptr, "%s %s %s", x, y, z);\r
-                       }\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
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://www.postgis.org
+ * adapted from lwout_asgml.c
+ * Copyright 2011 Arrival 3D
+ *                             Regina Obe with input from Dave Arendash
+ *
+ * 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 X3D output routines.
+*
+**********************************************************************/
+
+
+#include <string.h>
+#include "liblwgeom_internal.h"
+
+/** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/
+static size_t asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);
+static size_t asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid);
+static size_t asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid);
+static size_t asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);
+static size_t asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid);
+static size_t asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
+static char *asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
+static size_t pointArray_toX3D3(POINTARRAY *pa, char *buf, int precision, int opts, int is_closed);
+
+static size_t pointArray_X3Dsize(POINTARRAY *pa, int precision);
+
+
+/*
+ * VERSION X3D 3.0.2 http://www.web3d.org/specifications/x3d-3.0.dtd
+ */
+
+
+/* takes a GEOMETRY and returns an X3D representation */
+extern char *
+lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
+{
+       int type = geom->type;
+
+       switch (type)
+       {
+       case POINTTYPE:
+               return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid);
+
+       case LINETYPE:
+               return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid);
+
+       case POLYGONTYPE:
+       {
+               /** We might change this later, but putting a polygon in an indexed face set
+               * seems like the simplest way to go so treat just like a mulitpolygon
+               */
+               LWCOLLECTION *tmp = (LWCOLLECTION*)lwgeom_as_multi(geom);
+               char *ret = asx3d3_multi(tmp, srs, precision, opts, defid);
+               lwcollection_free(tmp);
+               return ret;
+       }
+
+       case TRIANGLETYPE:
+               return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid);
+
+       case MULTIPOINTTYPE:
+       case MULTILINETYPE:
+       case MULTIPOLYGONTYPE:
+               return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid);
+
+       case POLYHEDRALSURFACETYPE:
+               return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid);
+
+       case TINTYPE:
+               return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid);
+
+       case COLLECTIONTYPE:
+               return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid);
+
+       default:
+               lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type));
+               return NULL;
+       }
+}
+
+static size_t
+asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
+{
+       int size;
+       //size_t defidlen = strlen(defid);
+
+       size = pointArray_X3Dsize(point->point, precision);
+       //size += ( sizeof("<point><pos>/") + (defidlen*2) ) * 2;
+       //if (srs)     size += strlen(srs) + sizeof(" srsName=..");
+       return size;
+}
+
+static size_t
+asx3d3_point_buf(const LWPOINT *point, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr = output;
+       //int dimension=2;
+
+       //if (FLAGS_GET_Z(point->flags)) dimension = 3;
+       /*      if ( srs )
+               {
+                       ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", defid, srs);
+               }
+               else*/
+       //ptr += sprintf(ptr, "%s", defid);
+
+       //ptr += sprintf(ptr, "<%spos>", defid);
+       ptr += pointArray_toX3D3(point->point, ptr, precision, opts, 0);
+       //ptr += sprintf(ptr, "</%spos></%sPoint>", defid, defid);
+
+       return (ptr-output);
+}
+
+static char *
+asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
+{
+       char *output;
+       int size;
+
+       size = asx3d3_point_size(point, srs, precision, opts, defid);
+       output = lwalloc(size);
+       asx3d3_point_buf(point, srs, output, precision, opts, defid);
+       return output;
+}
+
+
+static size_t
+asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
+{
+       int size;
+       size_t defidlen = strlen(defid);
+
+       size = pointArray_X3Dsize(line->points, precision)*2;
+
+       size += (
+                   sizeof("<LineSet vertexCount=''><Coordinate point='' /></LineSet>")  + defidlen
+               ) * 2;
+
+       //if (srs)     size += strlen(srs) + sizeof(" srsName=..");
+       return size;
+}
+
+static size_t
+asx3d3_line_buf(const LWLINE *line, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr=output;
+       //int dimension=2;
+       POINTARRAY *pa;
+
+
+       //if (FLAGS_GET_Z(line->flags)) dimension = 3;
+
+       pa = line->points;
+       ptr += sprintf(ptr, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
+
+
+       ptr += sprintf(ptr, "<Coordinate point='");
+       ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed((LWLINE *) line));
+
+       ptr += sprintf(ptr, "' />");
+
+       ptr += sprintf(ptr, "</LineSet>");
+       return (ptr-output);
+}
+
+static size_t
+asx3d3_line_coords(const LWLINE *line, char *output, int precision, int opts)
+{
+       char *ptr=output;
+       //ptr += sprintf(ptr, "");
+       ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed(line));
+       return (ptr-output);
+}
+
+/* Calculate the coordIndex property of the IndexedLineSet for the multilinestring */
+static size_t
+asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output)
+{
+       char *ptr=output;
+       LWLINE *geom;
+       int i, j, k, si;
+       POINTARRAY *pa;
+       int np;
+
+       j = 0;
+       for (i=0; i < mgeom->ngeoms; i++)
+       {
+               geom = (LWLINE *) mgeom->geoms[i];
+               pa = geom->points;
+               np = pa->npoints;
+               si = j; //start index of first point of linestring
+               for (k=0; k < np ; k++)
+               {
+                       if (k)
+                       {
+                               ptr += sprintf(ptr, " ");
+                       }
+                       /** if the linestring is closed, we put the start point index
+                       *   for the last vertex to denote use first point
+                       *    and don't increment the index **/
+                       if (!lwline_is_closed(geom) || k < (np -1) )
+                       {
+                               ptr += sprintf(ptr, "%d", j);
+                               j += 1;
+                       }
+                       else
+                       {
+                               ptr += sprintf(ptr,"%d", si);
+                       }
+               }
+               if (i < (mgeom->ngeoms - 1) )
+               {
+                       ptr += sprintf(ptr, " -1 "); //separator for each linestring
+               }
+       }
+       return (ptr-output);
+}
+
+/* Calculate the coordIndex property of the IndexedLineSet for a multipolygon
+    This is not ideal -- would be really nice to just share this function with psurf,
+    but I'm not smart enough to do that yet*/
+static size_t
+asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output)
+{
+       char *ptr=output;
+       LWPOLY *patch;
+       int i, j, k, l;
+       int np;
+       j = 0;
+       for (i=0; i<psur->ngeoms; i++)
+       {
+               patch = (LWPOLY *) psur->geoms[i];
+               for (l=0; l < patch->nrings; l++)
+               {
+                       np = patch->rings[l]->npoints - 1;
+                       for (k=0; k < np ; k++)
+                       {
+                               if (k)
+                               {
+                                       ptr += sprintf(ptr, " ");
+                               }
+                               ptr += sprintf(ptr, "%d", (j + k));
+                       }
+                       j += k;
+                       if (l < (patch->nrings - 1) )
+                       {
+                               /** @todo TODO: Decide the best way to render holes
+                               *  Evidentally according to my X3D expert the X3D consortium doesn't really
+                               *  support holes and it's an issue of argument among many that feel it should. He thinks CAD x3d extensions to spec might.
+                               *  What he has done and others developing X3D exports to simulate a hole is to cut around it.
+                               *  So if you have a donut, you would cut it into half and have 2 solid polygons.  Not really sure the best way to handle this.
+                               *  For now will leave it as polygons stacked on top of each other -- which is what we are doing here and perhaps an option
+                               *  to color differently.  It's not ideal but the alternative sounds complicated.
+                               **/
+                               ptr += sprintf(ptr, " -1 "); //separator for each inner ring. Ideally we should probably triangulate and cut around as others do
+                       }
+               }
+               if (i < (psur->ngeoms - 1) )
+               {
+                       ptr += sprintf(ptr, " -1 "); //separator for each subgeom
+               }
+       }
+       return (ptr-output);
+}
+
+/** Return the linestring as an X3D LineSet */
+static char *
+asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
+{
+       char *output;
+       int size;
+
+       size = sizeof("<LineSet><CoordIndex ='' /></LineSet>") + asx3d3_line_size(line, srs, precision, opts, defid);
+       output = lwalloc(size);
+       asx3d3_line_buf(line, srs, output, precision, opts, defid);
+       return output;
+}
+
+/** Compute the string space needed for the IndexedFaceSet representation of the polygon **/
+static size_t
+asx3d3_poly_size(const LWPOLY *poly,  char *srs, int precision, int opts, const char *defid)
+{
+       size_t size;
+       size_t defidlen = strlen(defid);
+       int i;
+
+       size = ( sizeof("<IndexedFaceSet></IndexedFaceSet>") + (defidlen*3) ) * 2 + 6 * (poly->nrings - 1);
+
+       for (i=0; i<poly->nrings; i++)
+               size += pointArray_X3Dsize(poly->rings[i], precision);
+
+       return size;
+}
+
+/** Compute the X3D coordinates of the polygon **/
+static size_t
+asx3d3_poly_buf(const LWPOLY *poly, char *srs, char *output, int precision, int opts, int is_patch, const char *defid)
+{
+       int i;
+       char *ptr=output;
+       int dimension=2;
+
+       if (FLAGS_GET_Z(poly->flags))
+               dimension = 3;
+       ptr += pointArray_toX3D3(poly->rings[0], ptr, precision, opts, 1);
+       for (i=1; i<poly->nrings; i++)
+       {
+               ptr += sprintf(ptr, " "); //inner ring points start
+               ptr += pointArray_toX3D3(poly->rings[i], ptr, precision, opts,1);
+       }
+       return (ptr-output);
+}
+
+static size_t
+asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
+{
+       size_t size;
+       size_t defidlen = strlen(defid);
+
+       /** 6 for the 3 sides and space to separate each side **/
+       size = sizeof("<IndexedTriangleSet index=''></IndexedTriangleSet>") + defidlen + 6;
+       size += pointArray_X3Dsize(triangle->points, precision);
+
+       return size;
+}
+
+static size_t
+asx3d3_triangle_buf(const LWTRIANGLE *triangle, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr=output;
+       ptr += pointArray_toX3D3(triangle->points, ptr, precision, opts, 1);
+
+       return (ptr-output);
+}
+
+static char *
+asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
+{
+       char *output;
+       int size;
+
+       size = asx3d3_triangle_size(triangle, srs, precision, opts, defid);
+       output = lwalloc(size);
+       asx3d3_triangle_buf(triangle, srs, output, precision, opts, defid);
+       return output;
+}
+
+
+/**
+ * Compute max size required for X3D version of this
+ * inspected geometry. Will recurse when needed.
+ * Don't call this with single-geoms inspected.
+ */
+static size_t
+asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
+{
+       int i;
+       size_t size;
+       size_t defidlen = strlen(defid);
+       LWGEOM *subgeom;
+
+       /* the longest possible multi version needs to hold DEF=defid and coordinate breakout */
+       size = sizeof("<PointSet><Coordinate point='' /></PointSet>") + defidlen;
+
+       //if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
+
+       for (i=0; i<col->ngeoms; i++)
+       {
+               subgeom = col->geoms[i];
+               if (subgeom->type == POINTTYPE)
+               {
+                       //size += ( sizeof("point=''") + defidlen ) * 2;
+                       size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);
+               }
+               else if (subgeom->type == LINETYPE)
+               {
+                       //size += ( sizeof("<curveMember>/") + defidlen ) * 2;
+                       size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
+               }
+               else if (subgeom->type == POLYGONTYPE)
+               {
+                       //size += ( sizeof("<surfaceMember>/") + defidlen ) * 2;
+                       size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);
+               }
+       }
+
+       return size;
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static size_t
+asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr, *x3dtype;
+       int i;
+       int dimension=2;
+
+       if (FLAGS_GET_Z(col->flags)) dimension = 3;
+       LWGEOM *subgeom;
+       ptr = output;
+       x3dtype="";
+
+
+       switch (col->type)
+       {
+        case MULTIPOINTTYPE:
+            x3dtype = "PointSet";
+            if ( dimension == 2 ){ /** Use Polypoint2D instead **/
+                x3dtype = "Polypoint2D";   
+                ptr += sprintf(ptr, "<%s %s point='", x3dtype, defid);
+            }
+            else {
+                ptr += sprintf(ptr, "<%s %s>", x3dtype, defid);
+            }
+            break;
+        case MULTILINETYPE:
+            x3dtype = "IndexedLineSet";
+            ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid);
+            ptr += asx3d3_mline_coordindex((const LWMLINE *)col, ptr);
+            ptr += sprintf(ptr, "'>");
+            break;
+        case MULTIPOLYGONTYPE:
+            x3dtype = "IndexedFaceSet";
+            ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid);
+            ptr += asx3d3_mpoly_coordindex((const LWMPOLY *)col, ptr);
+            ptr += sprintf(ptr, "'>");
+            break;
+        default:
+            lwerror("asx3d3_multi_buf: '%s' geometry type not supported", lwtype_name(col->type));
+            return 0;
+    }
+    if (dimension == 3){
+        ptr += sprintf(ptr, "<Coordinate point='");
+    }
+
+       for (i=0; i<col->ngeoms; i++)
+       {
+               subgeom = col->geoms[i];
+               if (subgeom->type == POINTTYPE)
+               {
+                       ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
+                       ptr += sprintf(ptr, " ");
+               }
+               else if (subgeom->type == LINETYPE)
+               {
+                       ptr += asx3d3_line_coords((LWLINE*)subgeom, ptr, precision, opts);
+                       ptr += sprintf(ptr, " ");
+               }
+               else if (subgeom->type == POLYGONTYPE)
+               {
+                       ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
+                       ptr += sprintf(ptr, " ");
+               }
+       }
+
+       /* Close outmost tag */
+       if (dimension == 3){
+           ptr += sprintf(ptr, "' /></%s>", x3dtype);
+       }
+       else { ptr += sprintf(ptr, "' />"); }    
+       return (ptr-output);
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static char *
+asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
+{
+       char *x3d;
+       size_t size;
+
+       size = asx3d3_multi_size(col, srs, precision, opts, defid);
+       x3d = lwalloc(size);
+       asx3d3_multi_buf(col, srs, x3d, precision, opts, defid);
+       return x3d;
+}
+
+
+static size_t
+asx3d3_psurface_size(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
+{
+       int i;
+       size_t size;
+       size_t defidlen = strlen(defid);
+
+       size = sizeof("<IndexedFaceSet coordIndex=''><Coordinate point='' />") + defidlen;
+
+       for (i=0; i<psur->ngeoms; i++)
+       {
+               size += asx3d3_poly_size(psur->geoms[i], 0, precision, opts, defid)*5; /** need to make space for coordIndex values too including -1 separating each poly**/
+       }
+
+       return size;
+}
+
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static size_t
+asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr;
+       int i;
+       int j;
+       int k;
+       int np;
+       LWPOLY *patch;
+
+       ptr = output;
+
+       /* Open outmost tag */
+       ptr += sprintf(ptr, "<IndexedFaceSet %s coordIndex='",defid);
+
+       j = 0;
+       for (i=0; i<psur->ngeoms; i++)
+       {
+               patch = (LWPOLY *) psur->geoms[i];
+               np = patch->rings[0]->npoints - 1;
+               for (k=0; k < np ; k++)
+               {
+                       if (k)
+                       {
+                               ptr += sprintf(ptr, " ");
+                       }
+                       ptr += sprintf(ptr, "%d", (j + k));
+               }
+               if (i < (psur->ngeoms - 1) )
+               {
+                       ptr += sprintf(ptr, " -1 "); //separator for each subgeom
+               }
+               j += k;
+       }
+
+       ptr += sprintf(ptr, "'><Coordinate point='");
+
+       for (i=0; i<psur->ngeoms; i++)
+       {
+               ptr += asx3d3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, defid);
+               if (i < (psur->ngeoms - 1) )
+               {
+                       ptr += sprintf(ptr, " "); //only add a trailing space if its not the last polygon in the set
+               }
+       }
+
+       /* Close outmost tag */
+       ptr += sprintf(ptr, "' /></IndexedFaceSet>");
+
+       return (ptr-output);
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static char *
+asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
+{
+       char *x3d;
+       size_t size;
+
+       size = asx3d3_psurface_size(psur, srs, precision, opts, defid);
+       x3d = lwalloc(size);
+       asx3d3_psurface_buf(psur, srs, x3d, precision, opts, defid);
+       return x3d;
+}
+
+
+static size_t
+asx3d3_tin_size(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
+{
+       int i;
+       size_t size;
+       size_t defidlen = strlen(defid);
+       //int dimension=2;
+
+       /** Need to make space for size of additional attributes,
+       ** the coordIndex has a value for each edge for each triangle plus a space to separate so we need at least that much extra room ***/
+       size = sizeof("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + tin->ngeoms*12;
+
+       for (i=0; i<tin->ngeoms; i++)
+       {
+               size += (asx3d3_triangle_size(tin->geoms[i], 0, precision, opts, defid) * 20); /** 3 is to make space for coordIndex **/
+       }
+
+       return size;
+}
+
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static size_t
+asx3d3_tin_buf(const LWTIN *tin, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr;
+       int i;
+       int k;
+       //int dimension=2;
+
+       ptr = output;
+
+       ptr += sprintf(ptr, "<IndexedTriangleSet %s index='",defid);
+       k = 0;
+       /** Fill in triangle index **/
+       for (i=0; i<tin->ngeoms; i++)
+       {
+               ptr += sprintf(ptr, "%d %d %d", k, (k+1), (k+2));
+               if (i < (tin->ngeoms - 1) )
+               {
+                       ptr += sprintf(ptr, " ");
+               }
+               k += 3;
+       }
+
+       ptr += sprintf(ptr, "'><Coordinate point='");
+       for (i=0; i<tin->ngeoms; i++)
+       {
+               ptr += asx3d3_triangle_buf(tin->geoms[i], 0, ptr, precision,
+                                          opts, defid);
+               if (i < (tin->ngeoms - 1) )
+               {
+                       ptr += sprintf(ptr, " ");
+               }
+       }
+
+       /* Close outmost tag */
+
+       ptr += sprintf(ptr, "'/></IndexedTriangleSet>");
+
+       return (ptr-output);
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static char *
+asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
+{
+       char *x3d;
+       size_t size;
+
+       size = asx3d3_tin_size(tin, srs, precision, opts, defid);
+       x3d = lwalloc(size);
+       asx3d3_tin_buf(tin, srs, x3d, precision, opts, defid);
+       return x3d;
+}
+
+static size_t
+asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
+{
+       int i;
+       size_t size;
+       size_t defidlen = strlen(defid);
+       LWGEOM *subgeom;
+
+       size = sizeof("<MultiGeometry></MultiGeometry>") + defidlen*2;
+
+       if ( srs )
+               size += strlen(srs) + sizeof(" srsName=..");
+
+       for (i=0; i<col->ngeoms; i++)
+       {
+               subgeom = col->geoms[i];
+               size += ( sizeof("<geometryMember>/") + defidlen ) * 2;
+               if ( subgeom->type == POINTTYPE )
+               {
+                       size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);
+               }
+               else if ( subgeom->type == LINETYPE )
+               {
+                       size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
+               }
+               else if ( subgeom->type == POLYGONTYPE )
+               {
+                       size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);
+               }
+               else if ( lwgeom_is_collection(subgeom) )
+               {
+                       size += asx3d3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, defid);
+               }
+               else
+                       lwerror("asx3d3_collection_size: unknown geometry type");
+       }
+
+       return size;
+}
+
+static size_t
+asx3d3_collection_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
+{
+       char *ptr;
+       int i;
+       LWGEOM *subgeom;
+
+       ptr = output;
+
+       /* Open outmost tag */
+       if ( srs )
+       {
+               ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", defid, srs);
+       }
+       else
+       {
+               ptr += sprintf(ptr, "<%sMultiGeometry>", defid);
+       }
+
+       for (i=0; i<col->ngeoms; i++)
+       {
+               subgeom = col->geoms[i];
+               ptr += sprintf(ptr, "<%sgeometryMember>", defid);
+               if ( subgeom->type == POINTTYPE )
+               {
+                       ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
+               }
+               else if ( subgeom->type == LINETYPE )
+               {
+                       ptr += asx3d3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, defid);
+               }
+               else if ( subgeom->type == POLYGONTYPE )
+               {
+                       ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
+               }
+               else if ( lwgeom_is_collection(subgeom) )
+               {
+                       if ( subgeom->type == COLLECTIONTYPE )
+                               ptr += asx3d3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);
+                       else
+                               ptr += asx3d3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);
+               }
+               else
+                       lwerror("asx3d3_collection_buf: unknown geometry type");
+
+               ptr += sprintf(ptr, "</%sgeometryMember>", defid);
+       }
+
+       /* Close outmost tag */
+       ptr += sprintf(ptr, "</%sMultiGeometry>", defid);
+
+       return (ptr-output);
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static char *
+asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
+{
+       char *x3d;
+       size_t size;
+
+       size = asx3d3_collection_size(col, srs, precision, opts, defid);
+       x3d = lwalloc(size);
+       asx3d3_collection_buf(col, srs, x3d, precision, opts, defid);
+       return x3d;
+}
+
+
+/** In X3D3, coordinates are separated by a space separator
+ */
+static size_t
+pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_closed)
+{
+       int i;
+       char *ptr;
+       char x[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
+       char y[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
+       char z[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
+
+       ptr = output;
+
+       if ( ! FLAGS_GET_Z(pa->flags) )
+       {
+               for (i=0; i<pa->npoints; i++)
+               {
+                       /** Only output the point if it is not the last point of a closed object or it is a non-closed type **/
+                       if ( !is_closed || i < (pa->npoints - 1) )
+                       {
+                               POINT2D pt;
+                               getPoint2d_p(pa, i, &pt);
+
+                               if (fabs(pt.x) < OUT_MAX_DOUBLE)
+                                       sprintf(x, "%.*f", precision, pt.x);
+                               else
+                                       sprintf(x, "%g", pt.x);
+                               trim_trailing_zeros(x);
+
+                               if (fabs(pt.y) < OUT_MAX_DOUBLE)
+                                       sprintf(y, "%.*f", precision, pt.y);
+                               else
+                                       sprintf(y, "%g", pt.y);
+                               trim_trailing_zeros(y);
+
+                               if ( i )
+                                       ptr += sprintf(ptr, " ");
+                               ptr += sprintf(ptr, "%s %s", x, y);
+                       }
+               }
+       }
+       else
+       {
+               for (i=0; i<pa->npoints; i++)
+               {
+                       /** Only output the point if it is not the last point of a closed object or it is a non-closed type **/
+                       if ( !is_closed || i < (pa->npoints - 1) )
+                       {
+                               POINT4D pt;
+                               getPoint4d_p(pa, i, &pt);
+
+                               if (fabs(pt.x) < OUT_MAX_DOUBLE)
+                                       sprintf(x, "%.*f", precision, pt.x);
+                               else
+                                       sprintf(x, "%g", pt.x);
+                               trim_trailing_zeros(x);
+
+                               if (fabs(pt.y) < OUT_MAX_DOUBLE)
+                                       sprintf(y, "%.*f", precision, pt.y);
+                               else
+                                       sprintf(y, "%g", pt.y);
+                               trim_trailing_zeros(y);
+
+                               if (fabs(pt.z) < OUT_MAX_DOUBLE)
+                                       sprintf(z, "%.*f", precision, pt.z);
+                               else
+                                       sprintf(z, "%g", pt.z);
+                               trim_trailing_zeros(z);
+
+                               if ( i )
+                                       ptr += sprintf(ptr, " ");
+
+                               ptr += sprintf(ptr, "%s %s %s", x, y, z);
+                       }
+               }
+       }
+
+       return ptr-output;
+}
+
+
+
+/**
+ * Returns maximum size of rendered pointarray in bytes.
+ */
+static size_t
+pointArray_X3Dsize(POINTARRAY *pa, int precision)
+{
+       if (FLAGS_NDIMS(pa->flags) == 2)
+               return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" "))
+                      * 2 * pa->npoints;
+
+       return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" ")) * 3 * pa->npoints;
+}
index c95c0feb3f316d4569b9eb94dda8167c837202e2..f8dcae18960ed3f5b9272ea0e66c7cced4e14ff6 100644 (file)
-/**********************************************************************\r
- * $Id:$\r
- *\r
- * PostGIS - Export functions for PostgreSQL/PostGIS\r
- * Copyright 2009-2011 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 "../postgis_config.h"\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
-* Retrieve an SRID from a given SRS\r
-* Require valid spatial_ref_sys table entry\r
-*\r
-*/\r
-int getSRIDbySRS(const char* srs)\r
-{\r
-       char query[256];\r
-       int srid, err;\r
-\r
-       if (srs == NULL)\r
-               return 0;\r
-\r
-       if (SPI_OK_CONNECT != SPI_connect ())\r
-       {\r
-               elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");\r
-               SPI_finish();\r
-               return 0;\r
-       }\r
-       sprintf(query, "SELECT srid \\r
-               FROM spatial_ref_sys WHERE auth_name||':'||auth_srid = '%s'", srs);\r
-\r
-       err = SPI_exec(query, 1);\r
-       if ( err < 0 )\r
-       {\r
-               elog(NOTICE, "getSRIDbySRS: error executing query %d", err);\r
-               SPI_finish();\r
-               return 0;\r
-       }\r
-\r
-       /* no entry in spatial_ref_sys */\r
-       if (SPI_processed <= 0)\r
-       {\r
-               sprintf(query, "SELECT srid \\r
-                       FROM spatial_ref_sys WHERE \\r
-                       'urn:ogc:def:crs:'||auth_name||'::'||auth_srid = '%s'", srs);\r
-\r
-               err = SPI_exec(query, 1);\r
-               if ( err < 0 )\r
-               {\r
-                       elog(NOTICE, "getSRIDbySRS: error executing query %d", err);\r
-                       SPI_finish();\r
-                       return 0;\r
-               }\r
-\r
-               if (SPI_processed <= 0) {\r
-                       SPI_finish();\r
-                       return 0;\r
-               }\r
-       }\r
-\r
-       srid = atoi(SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1));\r
-       if ( ! srs )\r
-       {\r
-               SPI_finish();\r
-               return 0;\r
-       }\r
-\r
-       SPI_finish();\r
-\r
-       return srid;\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
-       GSERIALIZED *geom;\r
-       LWGEOM *lwgeom;\r
-       char *gml = NULL;\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 = (GSERIALIZED *)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 = gserialized_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
-        if (option & 32) lwopts |= LW_GML_EXTENT;\r
-\r
-       lwgeom = lwgeom_from_gserialized(geom);\r
-\r
-       if (version == 2 && lwopts & LW_GML_EXTENT)\r
-               gml = lwgeom_extent_to_gml2(lwgeom, srs, precision, prefix);\r
-       else if (version == 2)\r
-               gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);\r
-       else if (version == 3 && lwopts & LW_GML_EXTENT)\r
-               gml = lwgeom_extent_to_gml3(lwgeom, srs, precision, lwopts, prefix);\r
-       else if (version == 3) \r
-               gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix);\r
-\r
-       lwgeom_free(lwgeom);\r
-       PG_FREE_IF_COPY(geom, 1);\r
-\r
-       /* Return null on null */\r
-       if ( ! gml )\r
-               PG_RETURN_NULL();\r
-\r
-       result = cstring2text(gml);\r
-       lwfree(gml);\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
-       GSERIALIZED *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 = (GSERIALIZED *)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 = lwgeom_from_gserialized(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
-       GSERIALIZED *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 = (GSERIALIZED *)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 = gserialized_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 = lwgeom_from_gserialized(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
-       GSERIALIZED *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 = (GSERIALIZED *)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 = lwgeom_from_gserialized(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
-       GSERIALIZED *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 = (GSERIALIZED *)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 = gserialized_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 = lwgeom_from_gserialized(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
+/**********************************************************************
+ * $Id:$
+ *
+ * PostGIS - Export functions for PostgreSQL/PostGIS
+ * Copyright 2009-2011 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 "../postgis_config.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);
+Datum LWGEOM_asX3D(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;
+}
+
+
+/*
+* Retrieve an SRID from a given SRS
+* Require valid spatial_ref_sys table entry
+*
+*/
+int getSRIDbySRS(const char* srs)
+{
+       char query[256];
+       int srid, err;
+
+       if (srs == NULL)
+               return 0;
+
+       if (SPI_OK_CONNECT != SPI_connect ())
+       {
+               elog(NOTICE, "getSRIDbySRS: could not connect to SPI manager");
+               SPI_finish();
+               return 0;
+       }
+       sprintf(query, "SELECT srid \
+               FROM spatial_ref_sys WHERE auth_name||':'||auth_srid = '%s'", srs);
+
+       err = SPI_exec(query, 1);
+       if ( err < 0 )
+       {
+               elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
+               SPI_finish();
+               return 0;
+       }
+
+       /* no entry in spatial_ref_sys */
+       if (SPI_processed <= 0)
+       {
+               sprintf(query, "SELECT srid \
+                       FROM spatial_ref_sys WHERE \
+                       'urn:ogc:def:crs:'||auth_name||'::'||auth_srid = '%s'", srs);
+
+               err = SPI_exec(query, 1);
+               if ( err < 0 )
+               {
+                       elog(NOTICE, "getSRIDbySRS: error executing query %d", err);
+                       SPI_finish();
+                       return 0;
+               }
+
+               if (SPI_processed <= 0) {
+                       SPI_finish();
+                       return 0;
+               }
+       }
+
+       srid = atoi(SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1));
+       if ( ! srs )
+       {
+               SPI_finish();
+               return 0;
+       }
+
+       SPI_finish();
+
+       return srid;
+}
+
+
+/**
+ * Encode feature in GML
+ */
+PG_FUNCTION_INFO_V1(LWGEOM_asGML);
+Datum LWGEOM_asGML(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *geom;
+       LWGEOM *lwgeom;
+       char *gml = NULL;
+       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 = (GSERIALIZED *)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 = gserialized_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;
+        if (option & 32) lwopts |= LW_GML_EXTENT;
+
+       lwgeom = lwgeom_from_gserialized(geom);
+
+       if (version == 2 && lwopts & LW_GML_EXTENT)
+               gml = lwgeom_extent_to_gml2(lwgeom, srs, precision, prefix);
+       else if (version == 2)
+               gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix);
+       else if (version == 3 && lwopts & LW_GML_EXTENT)
+               gml = lwgeom_extent_to_gml3(lwgeom, srs, precision, lwopts, prefix);
+       else if (version == 3) 
+               gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix);
+
+       lwgeom_free(lwgeom);
+       PG_FREE_IF_COPY(geom, 1);
+
+       /* Return null on null */
+       if ( ! gml )
+               PG_RETURN_NULL();
+
+       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)
+{
+       GSERIALIZED *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 = (GSERIALIZED *)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 = lwgeom_from_gserialized(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)
+{
+       GSERIALIZED *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 = (GSERIALIZED *)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 = gserialized_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 = lwgeom_from_gserialized(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)
+{
+       GSERIALIZED *geom;
+       LWGEOM *lwgeom;
+       char *svg;
+       text *result;
+       int relative = 0;
+       int precision=OUT_MAX_DOUBLE_PRECISION;
+
+       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
+
+       geom = (GSERIALIZED *)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 = lwgeom_from_gserialized(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);
+}
+
+/**
+ * Encode feature as X3D
+ */
+PG_FUNCTION_INFO_V1(LWGEOM_asX3D);
+Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
+{
+       GSERIALIZED *geom;
+       LWGEOM *lwgeom;
+       char *x3d;
+       text *result;
+       int version;
+       char *srs;
+       int srid;
+       int option = 0;
+       int is_deegree = 0;
+       int is_dims = 1;
+       int precision = OUT_MAX_DOUBLE_PRECISION;
+       static const char* default_defid = "x3d:"; /* default defid */
+       char *defidbuf;
+       const char* defid = default_defid;
+       text *defid_text;
+
+       /* Get the version */
+       version = PG_GETARG_INT32(0);
+       if (  version != 3 )
+       {
+               elog(ERROR, "Only X3D version 3 are supported");
+               PG_RETURN_NULL();
+       }
+
+       /* Get the geometry */
+       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
+       geom = (GSERIALIZED *)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 defid */
+       if (PG_NARGS() >4 && !PG_ARGISNULL(4))
+       {
+               defid_text = PG_GETARG_TEXT_P(4);
+               if ( VARSIZE(defid_text)-VARHDRSZ == 0 )
+               {
+                       defid = "";
+               }
+               else
+               {
+                       /* +2 is one for the ':' and one for term null */
+                       defidbuf = palloc(VARSIZE(defid_text)-VARHDRSZ+2);
+                       memcpy(defidbuf, VARDATA(defid_text),
+                              VARSIZE(defid_text)-VARHDRSZ);
+                       /* add colon and null terminate */
+                       defidbuf[VARSIZE(defid_text)-VARHDRSZ] = ':';
+                       defidbuf[VARSIZE(defid_text)-VARHDRSZ+1] = '\0';
+                       defid = defidbuf;
+               }
+       }
+
+       srid = gserialized_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)  is_dims = 0;
+       if (option & 16) is_deegree = 1;
+
+       lwgeom = lwgeom_from_gserialized(geom);
+
+
+       x3d = lwgeom_to_x3d3(lwgeom, srs, precision,option, defid);
+
+       lwgeom_free(lwgeom);
+       PG_FREE_IF_COPY(geom, 1);
+
+       result = cstring2text(x3d);
+       lwfree(x3d);
+
+       PG_RETURN_TEXT_P(result);
+}
index d2e33da905a8962a38d69d6228bf5321f75195f1..42100775480d65be6de278697669da9ae65743da 100644 (file)
@@ -1,72 +1,72 @@
-#ifndef _LWGEOM_RTREE_H\r
-#define _LWGEOM_RTREE_H\r
-\r
-#include "liblwgeom.h"\r
-\r
-typedef struct\r
-{\r
-       double min;\r
-       double max;\r
-}\r
-INTERVAL;\r
-\r
-/* Returns 1 if min < value <= max, 0 otherwise */\r
-uint32 isContained(INTERVAL *interval, double value);\r
-/* Creates an interval given the min and max values, in whatever order. */\r
-INTERVAL *createInterval(double value1, double value2);\r
-/* Creates an interval with the total extents of the two given intervals. */\r
-INTERVAL *mergeIntervals(INTERVAL *inter1, INTERVAL *inter2);\r
-\r
-/*\r
- * The following struct and methods are used for a 1D RTree implementation,\r
- * described at:\r
- *  http://lin-ear-th-inking.blogspot.com/2007/06/packed-1-dimensional-r-tree.html\r
- */\r
-typedef struct rtree_node\r
-{\r
-       INTERVAL *interval;\r
-       struct rtree_node *leftNode;\r
-       struct rtree_node *rightNode;\r
-       LWLINE *segment;\r
-}\r
-RTREE_NODE;\r
-\r
-/* Creates an interior node given the children. */\r
-RTREE_NODE *createInteriorNode(RTREE_NODE *left, RTREE_NODE *right);\r
-/* Creates a leaf node given the pointer to the start point of the segment. */\r
-RTREE_NODE *createLeafNode(POINTARRAY *pa, int startPoint);\r
-/*\r
- * Creates an rtree given a pointer to the point array.\r
- * Must copy the point array.\r
- */\r
-RTREE_NODE *createTree(POINTARRAY *pointArray);\r
-/* Frees the tree. */\r
-void freeTree(RTREE_NODE *root);\r
-/* Retrieves a collection of line segments given the root and crossing value. */\r
-LWMLINE *findLineSegments(RTREE_NODE *root, double value);\r
-/* Merges two multilinestrings into a single multilinestring. */\r
-LWMLINE *mergeMultiLines(LWMLINE *line1, LWMLINE *line2);\r
-\r
-typedef struct\r
-{\r
-       char type;\r
-       RTREE_NODE **ringIndices;\r
-       int* ringCounts;\r
-       int polyCount;\r
-       GSERIALIZED *poly;\r
-}\r
-RTREE_POLY_CACHE;\r
-\r
-/*\r
- * Creates a new cachable index if needed, or returns the current cache if\r
- * it is applicable to the current polygon.\r
- */\r
-RTREE_POLY_CACHE *retrieveCache(LWGEOM *lwgeom, GSERIALIZED *serializedPoly, RTREE_POLY_CACHE *currentCache);\r
-RTREE_POLY_CACHE *createCache(void);\r
-/* Frees the cache. */\r
-void populateCache(RTREE_POLY_CACHE *cache, LWGEOM *lwgeom, GSERIALIZED *serializedPoly);\r
-void clearCache(RTREE_POLY_CACHE *cache);\r
-\r
-\r
-\r
-#endif /* !defined _LIBLWGEOM_H */\r
+#ifndef _LWGEOM_RTREE_H
+#define _LWGEOM_RTREE_H
+
+#include "liblwgeom.h"
+
+typedef struct
+{
+       double min;
+       double max;
+}
+INTERVAL;
+
+/* Returns 1 if min < value <= max, 0 otherwise */
+uint32 isContained(INTERVAL *interval, double value);
+/* Creates an interval given the min and max values, in whatever order. */
+INTERVAL *createInterval(double value1, double value2);
+/* Creates an interval with the total extents of the two given intervals. */
+INTERVAL *mergeIntervals(INTERVAL *inter1, INTERVAL *inter2);
+
+/*
+ * The following struct and methods are used for a 1D RTree implementation,
+ * described at:
+ *  http://lin-ear-th-inking.blogspot.com/2007/06/packed-1-dimensional-r-tree.html
+ */
+typedef struct rtree_node
+{
+       INTERVAL *interval;
+       struct rtree_node *leftNode;
+       struct rtree_node *rightNode;
+       LWLINE *segment;
+}
+RTREE_NODE;
+
+/* Creates an interior node given the children. */
+RTREE_NODE *createInteriorNode(RTREE_NODE *left, RTREE_NODE *right);
+/* Creates a leaf node given the pointer to the start point of the segment. */
+RTREE_NODE *createLeafNode(POINTARRAY *pa, int startPoint);
+/*
+ * Creates an rtree given a pointer to the point array.
+ * Must copy the point array.
+ */
+RTREE_NODE *createTree(POINTARRAY *pointArray);
+/* Frees the tree. */
+void freeTree(RTREE_NODE *root);
+/* Retrieves a collection of line segments given the root and crossing value. */
+LWMLINE *findLineSegments(RTREE_NODE *root, double value);
+/* Merges two multilinestrings into a single multilinestring. */
+LWMLINE *mergeMultiLines(LWMLINE *line1, LWMLINE *line2);
+
+typedef struct
+{
+       char type;
+       RTREE_NODE **ringIndices;
+       int* ringCounts;
+       int polyCount;
+       GSERIALIZED *poly;
+}
+RTREE_POLY_CACHE;
+
+/*
+ * Creates a new cachable index if needed, or returns the current cache if
+ * it is applicable to the current polygon.
+ */
+RTREE_POLY_CACHE *retrieveCache(LWGEOM *lwgeom, GSERIALIZED *serializedPoly, RTREE_POLY_CACHE *currentCache);
+RTREE_POLY_CACHE *createCache(void);
+/* Frees the cache. */
+void populateCache(RTREE_POLY_CACHE *cache, LWGEOM *lwgeom, GSERIALIZED *serializedPoly);
+void clearCache(RTREE_POLY_CACHE *cache);
+
+
+
+#endif /* !defined _LIBLWGEOM_H */
index ec53da5d37c267fc1090acb49895408d3926e71f..d48dbf8a9c6341c858942ed3304d9e3a787a763a 100644 (file)
--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\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
--- 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
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_typmod_in(cstring[])\r
-       RETURNS integer\r
-       AS 'MODULE_PATHNAME','geometry_typmod_in'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_typmod_out(integer)\r
-       RETURNS cstring\r
-       AS 'MODULE_PATHNAME','postgis_typmod_out'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
-CREATE OR REPLACE FUNCTION geometry_analyze(internal)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'geometry_analyze_2d'\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
-       typmod_in = geometry_typmod_in,\r
-       typmod_out = geometry_typmod_out,\r
-       delimiter = ':',\r
-    alignment = double,\r
-       analyze = geometry_analyze,\r
-       storage = main\r
-);\r
-\r
-\r
--- Availability: 2.0.0\r
--- Special cast for enforcing the typmod restrictions\r
-CREATE OR REPLACE FUNCTION geometry(geometry, integer, boolean)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME','geometry_enforce_typmod'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
--- Availability: 2.0.0\r
-CREATE CAST (geometry AS geometry) WITH FUNCTION geometry(geometry, integer, boolean) AS IMPLICIT;\r
-\r
-\r
--------------------------------------------------------------------\r
---  BOX3D TYPE\r
--- Point coordinate data access\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
--------------------------------------------\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
------------------------------------------------------------------------\r
--- BOX2D\r
------------------------------------------------------------------------\r
-\r
-CREATE OR REPLACE FUNCTION box2d_in(cstring)\r
-       RETURNS box2d\r
-       AS 'MODULE_PATHNAME','BOX2D_in'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION box2d_out(box2d)\r
-       RETURNS cstring\r
-       AS 'MODULE_PATHNAME','BOX2D_out'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE TYPE box2d (\r
-       internallength = 65,\r
-       input = box2d_in,\r
-       output = box2d_out,\r
-       storage = plain\r
-);\r
-\r
--------------------------------------------------------------------\r
---  BOX2DF TYPE (INTERNAL ONLY)\r
--------------------------------------------------------------------\r
---\r
--- Box2Df type is used by the GiST index bindings. \r
--- In/out functions are stubs, as all access should be internal.\r
----\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION box2df_in(cstring)\r
-       RETURNS box2df\r
-       AS 'MODULE_PATHNAME','box2df_in'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION box2df_out(box2df)\r
-       RETURNS cstring\r
-       AS 'MODULE_PATHNAME','box2df_out'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
--- Availability: 2.0.0\r
-CREATE TYPE box2df (\r
-       internallength = 16,\r
-       input = box2df_in,\r
-       output = box2df_out,\r
-       storage = plain,\r
-       alignment = double\r
-);\r
-\r
-\r
--------------------------------------------------------------------\r
---  GIDX TYPE (INTERNAL ONLY)\r
--------------------------------------------------------------------\r
---\r
--- GIDX type is used by the N-D and GEOGRAPHY GiST index bindings. \r
--- In/out functions are stubs, as all access should be internal.\r
----\r
-\r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION gidx_in(cstring)\r
-       RETURNS gidx\r
-       AS 'MODULE_PATHNAME','gidx_in'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION gidx_out(gidx)\r
-       RETURNS cstring\r
-       AS 'MODULE_PATHNAME','gidx_out'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
--- Availability: 1.5.0\r
-CREATE TYPE gidx (\r
-       internallength = variable,\r
-       input = gidx_in,\r
-       output = gidx_out,\r
-       storage = plain,\r
-       alignment = double\r
-);\r
-\r
--------------------------------------------------------------------\r
--- BTREE indexes\r
--------------------------------------------------------------------\r
-CREATE OR REPLACE FUNCTION geometry_lt(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'lwgeom_lt'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION geometry_le(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'lwgeom_le'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION geometry_gt(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'lwgeom_gt'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION geometry_ge(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'lwgeom_ge'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION geometry_eq(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'lwgeom_eq'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION geometry_cmp(geom1 geometry, geom2 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 (geom1 geometry, geom2 geometry);\r
-\r
-\r
------------------------------------------------------------------------------\r
--- GiST 2D GEOMETRY-over-GSERIALIZED INDEX\r
------------------------------------------------------------------------------\r
-\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
--- GiST Support Functions\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_distance_2d(internal,geometry,int4) \r
-       RETURNS float8 \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_distance_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_consistent_2d(internal,geometry,int4) \r
-       RETURNS bool \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_consistent_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_compress_2d(internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME','gserialized_gist_compress_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_penalty_2d(internal,internal,internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_penalty_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_picksplit_2d(internal, internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_picksplit_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_union_2d(bytea, internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_union_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_same_2d(geom1 geometry, geom2 geometry, internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_same_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_decompress_2d(internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_decompress_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_sel_2d (internal, oid, internal, int4)\r
-       RETURNS float8\r
-       AS 'MODULE_PATHNAME', 'geometry_gist_sel_2d'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_joinsel_2d(internal, oid, internal, smallint)\r
-       RETURNS float8\r
-       AS 'MODULE_PATHNAME', 'geometry_gist_joinsel_2d'\r
-       LANGUAGE 'C';\r
-\r
------------------------------------------------------------------------------\r
--- GEOMETRY Operators\r
------------------------------------------------------------------------------\r
-\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
--- 2D GEOMETRY Operators\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_overlaps(geom1 geometry, geom2 geometry) \r
-       RETURNS boolean \r
-       AS 'MODULE_PATHNAME' ,'gserialized_overlaps_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR && (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overlaps,\r
-       COMMUTATOR = '&&'\r
---     ,RESTRICT = contsel, JOIN = contjoinsel\r
-       ,RESTRICT = geometry_gist_sel_2d, JOIN = geometry_gist_joinsel_2d       \r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_same(geom1 geometry, geom2 geometry) \r
-       RETURNS boolean \r
-       AS 'MODULE_PATHNAME' ,'gserialized_same_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR ~= (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_same,\r
-       RESTRICT = contsel, JOIN = contjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_distance_centroid(geom1 geometry, geom2 geometry) \r
-       RETURNS float8 \r
-       AS 'MODULE_PATHNAME' ,'gserialized_distance_centroid_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_distance_box(geom1 geometry, geom2 geometry) \r
-       RETURNS float8 \r
-       AS 'MODULE_PATHNAME' ,'gserialized_distance_box_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-#if POSTGIS_PGSQL_VERSION >= 91\r
-CREATE OPERATOR <-> (\r
-    LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_distance_centroid,\r
-    COMMUTATOR = '<->'\r
-);\r
-\r
-CREATE OPERATOR <#> (\r
-    LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_distance_box,\r
-    COMMUTATOR = '<#>'\r
-);\r
-#endif\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_contains(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_contains_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_within(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_within_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR @ (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_within,\r
-       COMMUTATOR = '~',\r
-       RESTRICT = contsel, JOIN = contjoinsel\r
-);\r
-\r
-CREATE OPERATOR ~ (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_contains,\r
-       COMMUTATOR = '@',\r
-       RESTRICT = contsel, JOIN = contjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_left(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_left_2d'\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
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_overleft(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_overleft_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR &< (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overleft,\r
-       COMMUTATOR = '&>',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_below(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_below_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR <<| (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_below,\r
-       COMMUTATOR = '|>>',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_overbelow(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_overbelow_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR &<| (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overbelow,\r
-       COMMUTATOR = '|&>',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_overright(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_overright_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR &> (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overright,\r
-       COMMUTATOR = '&<',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_right(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_right_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR >> (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_right,\r
-       COMMUTATOR = '<<',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_overabove(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_overabove_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR |&> (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overabove,\r
-       COMMUTATOR = '&<|',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_above(geom1 geometry, geom2 geometry)\r
-       RETURNS bool\r
-       AS 'MODULE_PATHNAME', 'gserialized_above_2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OPERATOR |>> (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_above,\r
-       COMMUTATOR = '<<|',\r
-       RESTRICT = positionsel, JOIN = positionjoinsel\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OPERATOR CLASS gist_geometry_ops_2d\r
-       DEFAULT FOR TYPE geometry USING GIST AS\r
-       STORAGE box2df,\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
-#if POSTGIS_PGSQL_VERSION >= 91\r
-       OPERATOR        13       <-> FOR ORDER BY pg_catalog.float_ops,\r
-       OPERATOR        14       <#> FOR ORDER BY pg_catalog.float_ops,\r
-       FUNCTION        8        geometry_gist_distance_2d (internal, geometry, int4),\r
-#endif\r
-       FUNCTION        1        geometry_gist_consistent_2d (internal, geometry, int4),\r
-       FUNCTION        2        geometry_gist_union_2d (bytea, internal),\r
-       FUNCTION        3        geometry_gist_compress_2d (internal),\r
-       FUNCTION        4        geometry_gist_decompress_2d (internal),\r
-       FUNCTION        5        geometry_gist_penalty_2d (internal, internal, internal),\r
-       FUNCTION        6        geometry_gist_picksplit_2d (internal, internal),\r
-       FUNCTION        7        geometry_gist_same_2d (geom1 geometry, geom2 geometry, internal);\r
-\r
-\r
------------------------------------------------------------------------------\r
--- GiST ND GEOMETRY-over-GSERIALIZED\r
------------------------------------------------------------------------------\r
-\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
--- GiST Support Functions\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_consistent_nd(internal,geometry,int4) \r
-       RETURNS bool \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_consistent'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_compress_nd(internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME','gserialized_gist_compress'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_penalty_nd(internal,internal,internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_penalty'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_picksplit_nd(internal, internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_picksplit'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_union_nd(bytea, internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_union'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_same_nd(geometry, geometry, internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_same'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_gist_decompress_nd(internal) \r
-       RETURNS internal \r
-       AS 'MODULE_PATHNAME' ,'gserialized_gist_decompress'\r
-       LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
---CREATE OR REPLACE FUNCTION geometry_gist_selectivity_nd (internal, oid, internal, int4)\r
---     RETURNS float8\r
---     AS 'MODULE_PATHNAME', 'geometry_gist_selectivity_nd'\r
---     LANGUAGE 'C';\r
-\r
--- Availability: 2.0.0\r
---CREATE OR REPLACE FUNCTION geography_gist_join_selectivity_nd(internal, oid, internal, smallint)\r
---     RETURNS float8\r
---     AS 'MODULE_PATHNAME', 'geometry_gist_join_selectivity_nd'\r
---     LANGUAGE 'C';\r
-\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
--- N-D GEOMETRY Operators\r
--- ---------- ---------- ---------- ---------- ---------- ---------- ----------\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION geometry_overlaps_nd(geometry, geometry) \r
-       RETURNS boolean \r
-       AS 'MODULE_PATHNAME' ,'gserialized_overlaps'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 2.0.0\r
-CREATE OPERATOR &&& (\r
-       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overlaps_nd,\r
-       COMMUTATOR = '&&&'\r
-       ,RESTRICT = contsel, JOIN = contjoinsel\r
---     ,RESTRICT = geometry_gist_selectivity_nd \r
---     ,JOIN = geometry_gist_join_selectivity_nd\r
-);\r
-\r
--- Availability: 2.0.0\r
-CREATE OPERATOR CLASS gist_geometry_ops_nd\r
-       FOR TYPE geometry USING GIST AS\r
-       STORAGE         gidx,\r
-       OPERATOR        3        &&&    ,\r
---     OPERATOR        6        ~=     ,\r
---     OPERATOR        7        ~      ,\r
---     OPERATOR        8        @      ,\r
-       FUNCTION        1        geometry_gist_consistent_nd (internal, geometry, int4),\r
-       FUNCTION        2        geometry_gist_union_nd (bytea, internal),\r
-       FUNCTION        3        geometry_gist_compress_nd (internal),\r
-       FUNCTION        4        geometry_gist_decompress_nd (internal),\r
-       FUNCTION        5        geometry_gist_penalty_nd (internal, internal, internal),\r
-       FUNCTION        6        geometry_gist_picksplit_nd (internal, internal),\r
-       FUNCTION        7        geometry_gist_same_nd (geometry, geometry, internal);\r
-\r
-\r
------------------------------------------------------------------------------\r
--- Affine transforms\r
------------------------------------------------------------------------------\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_Rotate(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: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8,float8,float8)\r
-       RETURNS geometry\r
-       AS 'SELECT ST_Affine($1,  cos($2), -sin($2), 0,  sin($2),  cos($2), 0, 0, 0, 1, $3 - cos($2) * $3 + sin($2) * $4, $4 - sin($2) * $3 - cos($2) * $4, 0)'\r
-       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8,geometry)\r
-       RETURNS geometry\r
-       AS 'SELECT ST_Affine($1,  cos($2), -sin($2), 0,  sin($2),  cos($2), 0, 0, 0, 1, ST_X($3) - cos($2) * ST_X($3) + sin($2) * ST_Y($3), ST_Y($3) - sin($2) * ST_X($3) - cos($2) * ST_Y($3), 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_Rotate($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 FUNCTIONS\r
------------------------------------------------------------------------------\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 FUNCTIONS\r
------------------------------------------------------------------------------\r
-\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_expand(box2d,float8)\r
-       RETURNS box2d\r
-       AS 'MODULE_PATHNAME', 'BOX2D_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_BOX2D'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_MakeBox2d(geom1 geometry, geom2 geometry)\r
-       RETURNS box2d\r
-       AS 'MODULE_PATHNAME', 'BOX2D_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', 'BOX2D_combine'\r
-       LANGUAGE 'C' IMMUTABLE;\r
-\r
------------------------------------------------------------------------\r
--- ESTIMATED_EXTENT( <schema name>, <table name>, <column name> )\r
------------------------------------------------------------------------\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text,text) RETURNS box2d AS\r
-       'MODULE_PATHNAME', 'geometry_estimated_extent'\r
-       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;\r
-\r
------------------------------------------------------------------------\r
--- ESTIMATED_EXTENT( <table name>, <column name> )\r
------------------------------------------------------------------------\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text) RETURNS box2d AS\r
-       'MODULE_PATHNAME', 'geometry_estimated_extent'\r
-       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;\r
-\r
------------------------------------------------------------------------\r
--- FIND_EXTENT( <schema name>, <table name>, <column name> )\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 || '") As extent 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
--- 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 ST_Extent("' || columnname || '") As extent FROM "' || tablename || '"' LOOP\r
-               return myrec.extent;\r
-       END LOOP;\r
-END;\r
-$$\r
-LANGUAGE 'plpgsql' IMMUTABLE STRICT;\r
-\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.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
--- Measures\r
-------------------------------------------------------------------------\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_3DLength(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: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_3DLength_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: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_3DPerimeter(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
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_distance_spheroid(geom1 geometry, geom2 geometry,spheroid)\r
-       RETURNS FLOAT8\r
-       AS 'MODULE_PATHNAME','LWGEOM_distance_ellipsoid'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
--- Minimum distance. 2d only.\r
-\r
--- PostGIS equivalent function: distance(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION ST_Distance(geom1 geometry, geom2 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(geom1 geometry, geom2 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: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_CollectionHomogenize(geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'ST_CollectionHomogenize'\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
--- 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: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_3DMakeBox(geom1 geometry, geom2 geometry)\r
-       RETURNS box3d\r
-       AS 'MODULE_PATHNAME', 'BOX3D_construct'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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
--- Availability: 2.0.0 - made srid optional\r
-CREATE OR REPLACE FUNCTION ST_MakeEnvelope(float8, float8, float8, float8, integer DEFAULT 0)\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', 'ST_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
--- 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  STRICT;\r
-\r
-\r
-\r
--------------------------------------------------------------------\r
--- SPATIAL_REF_SYS\r
--------------------------------------------------------------------\r
-CREATE TABLE spatial_ref_sys (\r
-        srid integer not null primary key\r
-               check (srid > 0 and srid <= SRID_USR_MAX),\r
-        auth_name varchar(256),\r
-        auth_srid integer,\r
-        srtext varchar(2048),\r
-        proj4text varchar(2048)\r
-);\r
-\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
--- Revised: 2.0.0 -- no longer deletes from geometry_columns\r
--- Has new use_typmod option that defaults to true.  \r
--- If use typmod is  set to false will use old constraint behavior.\r
--- Will only touch table missing typmod or geometry constraints\r
------------------------------------------------------------------------\r
-CREATE OR REPLACE FUNCTION populate_geometry_columns(use_typmod boolean DEFAULT true)\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
-       -- 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%' AND c.relname != 'raster_columns' ;\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%' AND c.relname != 'raster_columns' \r
-       LOOP\r
-\r
-               inserted := inserted + populate_geometry_columns(gcs.oid, use_typmod);\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;\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, use_typmod boolean DEFAULT true)\r
-       RETURNS integer AS\r
-$$\r
-DECLARE\r
-       gcs         RECORD;\r
-       gc          RECORD;\r
-       gc_old      RECORD;\r
-       gsrid       integer;\r
-       gndims      integer;\r
-       gtype       text;\r
-       query       text;\r
-       gc_is_valid boolean;\r
-       inserted    integer;\r
-       constraint_successful boolean := false;\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
-        gc_is_valid := true;\r
-        -- Find the srid, coord_dimension, and type of current geometry\r
-        -- in geometry_columns -- which is now a view\r
-        \r
-        SELECT type, srid, coord_dimension INTO gc_old \r
-            FROM geometry_columns \r
-            WHERE f_table_schema = gcs.nspname AND f_table_name = gcs.relname AND f_geometry_column = gcs.attname; \r
-            \r
-        IF upper(gc_old.type) = 'GEOMETRY' THEN\r
-        -- This is an unconstrained geometry we need to do something\r
-        -- We need to figure out what to set the type by inspecting the data\r
-            EXECUTE 'SELECT st_srid(' || quote_ident(gcs.attname) || ') As srid, GeometryType(' || quote_ident(gcs.attname) || ') As type, ST_NDims(' || quote_ident(gcs.attname) || ') As dims ' ||\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
-            IF gc IS NULL THEN -- there is no data so we can not determine geometry type\r
-               RAISE WARNING 'No data in table %.%, so no information to determine geometry type and srid', gcs.nspname, gcs.relname;\r
-               RETURN 0;\r
-            END IF;\r
-            gsrid := gc.srid; gtype := gc.type; gndims := gc.dims;\r
-               \r
-            IF use_typmod THEN\r
-                BEGIN\r
-                    EXECUTE 'ALTER TABLE ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || ' ALTER COLUMN ' || quote_ident(gcs.attname) || \r
-                        ' TYPE geometry(' || postgis_type_name(gtype, gndims, true) || ', ' || gsrid::text  || ') ';\r
-                    inserted := inserted + 1;\r
-                EXCEPTION\r
-                        WHEN invalid_parameter_value THEN\r
-                        RAISE WARNING 'Could not convert ''%'' in ''%.%'' to use typmod with srid %, type: % ', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname), gsrid, postgis_type_name(gtype, gndims, true);\r
-                            gc_is_valid := false;\r
-                END;\r
-                \r
-            ELSE\r
-                -- Try to apply srid check to column\r
-               constraint_successful = false;\r
-                IF (gsrid > 0 AND postgis_constraint_srid(gcs.nspname, gcs.relname,gcs.attname) IS 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
-                        constraint_successful := true;\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
-                \r
-                -- Try to apply ndims check to column\r
-                IF (gndims IS NOT NULL AND postgis_constraint_dims(gcs.nspname, gcs.relname,gcs.attname) IS 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
-                        constraint_successful := true;\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
-    \r
-                -- Try to apply geometrytype check to column\r
-                IF (gtype IS NOT NULL AND postgis_constraint_type(gcs.nspname, gcs.relname,gcs.attname) IS 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
-                        constraint_successful := true;\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
-                 --only count if we were successful in applying at least one constraint\r
-                IF constraint_successful THEN\r
-                       inserted := inserted + 1;\r
-                END IF;\r
-            END IF;            \r
-           END IF;\r
-\r
-       END LOOP;\r
-\r
-       RETURN inserted;\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(catalog_name varchar,schema_name varchar,table_name varchar,column_name varchar,new_srid_in integer,new_type varchar,new_dim integer, use_typmod boolean DEFAULT true)\r
-       RETURNS text\r
-       AS\r
-$$\r
-DECLARE\r
-       rec RECORD;\r
-       sr varchar;\r
-       real_schema name;\r
-       sql text;\r
-       new_srid integer;\r
-\r
-BEGIN\r
-\r
-       -- Verify geometry type\r
-       IF (postgis_type_name(new_type,new_dim) IS NULL )\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', new_type, new_dim;\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_in > 0 ) THEN\r
-               IF new_srid_in > SRID_USR_MAX THEN\r
-                       RAISE EXCEPTION 'AddGeometryColumn() - SRID must be <= %', SRID_USR_MAX;\r
-               END IF;\r
-               new_srid := new_srid_in;\r
-               SELECT SRID INTO sr FROM spatial_ref_sys WHERE SRID = new_srid;\r
-               IF NOT FOUND THEN\r
-                       RAISE EXCEPTION 'AddGeometryColumn() - invalid SRID';\r
-                       RETURN 'fail';\r
-               END IF;\r
-       ELSE\r
-               new_srid := ST_SRID('POINT EMPTY'::geometry);\r
-               IF ( new_srid_in != new_srid ) THEN\r
-                       RAISE NOTICE 'SRID value % converted to the officially unknown SRID value %', new_srid_in, new_srid;\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
-       IF use_typmod THEN\r
-            sql := 'ALTER TABLE ' ||\r
-            quote_ident(real_schema) || '.' || quote_ident(table_name)\r
-            || ' ADD COLUMN ' || quote_ident(column_name) ||\r
-            ' geometry(' || postgis_type_name(new_type, new_dim) || ', ' || new_srid::text || ')';\r
-        RAISE DEBUG '%', sql;\r
-       ELSE\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
-    END IF;\r
-       EXECUTE sql;\r
-\r
-       IF NOT use_typmod THEN\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
-    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(schema_name varchar,table_name varchar,column_name varchar,new_srid integer,new_type varchar,new_dim integer, use_typmod boolean DEFAULT true) RETURNS text AS $$\r
-DECLARE\r
-       ret  text;\r
-BEGIN\r
-       SELECT AddGeometryColumn('',$1,$2,$3,$4,$5,$6,$7) 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(table_name varchar,column_name varchar,new_srid integer,new_type varchar,new_dim integer, use_typmod boolean DEFAULT true) 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' 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(catalog_name varchar, schema_name varchar,table_name varchar,column_name varchar)\r
-       RETURNS text\r
-       AS\r
-$$\r
-DECLARE\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 = false;\r
-\r
-               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP\r
-                       okay := true;\r
-               END LOOP;\r
-\r
-               IF ( okay <>  true ) 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 = false;\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 := true;\r
-       END LOOP;\r
-       IF (okay <> true) THEN\r
-               RAISE EXCEPTION 'column not found in geometry_columns table';\r
-               RETURN false;\r
-       END IF;\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(schema_name varchar, table_name varchar,column_name 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(table_name varchar, column_name 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(catalog_name varchar, schema_name varchar, table_name varchar)\r
-       RETURNS text\r
-       AS\r
-$$\r
-DECLARE\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
-       -- TODO: Should we warn if table doesn't exist probably instead just saying dropped\r
-       -- Remove table\r
-       EXECUTE 'DROP TABLE IF EXISTS '\r
-               || quote_ident(real_schema) || '.' ||\r
-               quote_ident(table_name) || ' RESTRICT';\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(schema_name varchar, table_name varchar) RETURNS text AS\r
-$$ SELECT DropGeometryTable('',$1,$2) $$\r
-LANGUAGE 'sql' VOLATILE STRICT;\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(table_name 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(catalogn_name varchar,schema_name varchar,table_name varchar,column_name varchar,new_srid_in integer)\r
-       RETURNS text\r
-       AS\r
-$$\r
-DECLARE\r
-       myrec RECORD;\r
-       okay boolean;\r
-       cname varchar;\r
-       real_schema name;\r
-       unknown_srid integer;\r
-       new_srid integer := new_srid_in;\r
-\r
-BEGIN\r
-\r
-\r
-       -- Find, check or fix schema_name\r
-       IF ( schema_name != '' ) THEN\r
-               okay = false;\r
-\r
-               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP\r
-                       okay := true;\r
-               END LOOP;\r
-\r
-               IF ( okay <> true ) 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
-       -- Ensure that column_name is in geometry_columns\r
-       okay = false;\r
-       FOR myrec IN SELECT type, coord_dimension 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 := true;\r
-       END LOOP;\r
-       IF (NOT okay) THEN\r
-               RAISE EXCEPTION 'column not found in geometry_columns table';\r
-               RETURN false;\r
-       END IF;\r
-\r
-       -- Ensure that new_srid is valid\r
-       IF ( new_srid > 0 ) THEN\r
-               IF ( SELECT count(*) = 0 from spatial_ref_sys where srid = new_srid ) THEN\r
-                       RAISE EXCEPTION 'invalid SRID: % not found in spatial_ref_sys', new_srid;\r
-                       RETURN false;\r
-               END IF;\r
-       ELSE\r
-               unknown_srid := ST_SRID('POINT EMPTY'::geometry);\r
-               IF ( new_srid != unknown_srid ) THEN\r
-                       new_srid := unknown_srid;\r
-                       RAISE NOTICE 'SRID value % converted to the officially unknown SRID value %', new_srid_in, new_srid;\r
-               END IF;\r
-       END IF;\r
-\r
-       IF postgis_constraint_srid(schema_name, table_name, column_name) IS NOT NULL THEN \r
-       -- srid was enforced with constraints before, keep it that way.\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
-    ELSE \r
-        -- We will use typmod to enforce if no srid constraints\r
-        -- We are using postgis_type_name to lookup the new name \r
-        -- (in case Paul changes his mind and flips geometry_columns to return old upper case name) \r
-        EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) || '.' || quote_ident(table_name) || \r
-        ' ALTER COLUMN ' || quote_ident(column_name) || ' TYPE  geometry(' || postgis_type_name(myrec.type, myrec.coord_dimension, true) || ', ' || new_srid::text || ') USING ST_SetSRID(' || quote_ident(column_name) || ',' || new_srid::text || ');' ;\r
-    END IF;\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
--- PostGIS equivalent of old 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_svn_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
-CREATE OR REPLACE FUNCTION postgis_full_version() RETURNS text\r
-AS $$\r
-DECLARE\r
-       libver text;\r
-       svnver text;\r
-       projver text;\r
-       geosver text;\r
-       gdalver 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
-       BEGIN\r
-               SELECT postgis_gdal_version() INTO gdalver;\r
-       EXCEPTION\r
-               WHEN undefined_function THEN\r
-                       gdalver := NULL;\r
-                       RAISE NOTICE 'Function postgis_gdal_version() not found.  Is raster support enabled and rtpostgis.sql installed?';\r
-       END;\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
-       select postgis_svn_version() INTO svnver;\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  gdalver IS NOT NULL THEN\r
-               fullver = fullver || ' GDAL="' || gdalver || '"';\r
-       END IF;\r
-\r
-       IF  libxmlver IS NOT NULL THEN\r
-               fullver = fullver || ' LIBXML="' || libxmlver || '"';\r
-       END IF;\r
-\r
-       IF  svnver IS NOT NULL THEN\r
-               fullver = fullver || ' SVN_REVISION=' || svnver;\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_BOX2D'\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_BOX2D'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION box3d(box2d)\r
-       RETURNS box3d\r
-       AS 'MODULE_PATHNAME','BOX2D_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','BOX2D_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
-\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
--- ST_SnapToGrid(input, xoff, yoff, xsize, ysize)\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
--- ST_SnapToGrid(input, xsize, ysize) # offsets=0\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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION ST_Intersection(geom1 geometry, geom2 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
--- Availability: 2.0.0 - requires GEOS-3.2 or higher\r
-CREATE OR REPLACE FUNCTION ST_OffsetCurve(line geometry, distance float8, params text DEFAULT '')\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME','ST_OffsetCurve'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\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(geom1 geometry, geom2 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(geom1 geometry, geom2 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
--- 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
--- 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
-\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
-\r
-\r
--- Requires GEOS >= 3.2.0\r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geom1 geometry, geom2 geometry)\r
-       RETURNS FLOAT8\r
-       AS 'MODULE_PATHNAME', 'hausdorffdistance'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
--- Requires GEOS >= 3.2.0\r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geom1 geometry, geom2 geometry, float8)\r
-       RETURNS FLOAT8\r
-       AS 'MODULE_PATHNAME', 'hausdorffdistancedensify'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
--- PostGIS equivalent function: difference(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION ST_Difference(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION ST_SymDifference(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME','symdifference'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- PostGIS equivalent function: GeomUnion(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION ST_Union(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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
--- ST_Node\r
---------------------------------------------------------------------------------\r
-\r
--- ST_Node(in geometry)\r
---\r
--- Fully node lines in input using the least set of nodes while\r
--- preserving each of the input ones.\r
--- Returns a linestring or a multilinestring containing all parts.\r
---\r
--- Availability: 2.0.0\r
--- Requires GEOS >= 3.3.0\r
---\r
-CREATE OR REPLACE FUNCTION ST_Node(g geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'ST_Node'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
-\r
---------------------------------------------------------------------------------\r
--- Aggregates and their supporting functions\r
---------------------------------------------------------------------------------\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_Extent(\r
-       sfunc = ST_combine_bbox,\r
-       finalfunc = box2d,\r
-       basetype = geometry,\r
-       stype = box3d\r
-       );\r
-\r
--- Availability: 2.0.0\r
-CREATE AGGREGATE ST_3DExtent(\r
-       sfunc = ST_combine_bbox,\r
-       basetype = geometry,\r
-       stype = box3d\r
-       );\r
-\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_Collect(geom1 geometry, geom2 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
--- 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
--- 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
--- 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry, int4)\r
-       RETURNS text\r
-       AS 'MODULE_PATHNAME','relate_full'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- PostGIS equivalent function: relate(geom1 geometry, geom2 geometry,text)\r
-CREATE OR REPLACE FUNCTION ST_Relate(geom1 geometry, geom2 geometry,text)\r
-       RETURNS boolean\r
-       AS 'MODULE_PATHNAME','relate_pattern'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- PostGIS equivalent function: disjoint(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION ST_Disjoint(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'MODULE_PATHNAME','disjoint'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- PostGIS equivalent function: touches(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION _ST_Touches(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION _ST_Intersects(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'SELECT $1 && $2 AND _ST_Intersects($1,$2)'\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-       \r
--- PostGIS equivalent function: crosses(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION _ST_Crosses(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'SELECT $1 && $2 AND _ST_Crosses($1,$2)'\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-\r
--- PostGIS equivalent function: contains(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION _ST_Contains(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'SELECT $1 && $2 AND _ST_ContainsProperly($1,$2)'\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-\r
--- PostGIS equivalent function: overlaps(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION _ST_Overlaps(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'MODULE_PATHNAME','overlaps'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
--- PostGIS equivalent function: within(geom1 geometry, geom2 geometry)\r
-CREATE OR REPLACE FUNCTION _ST_Within(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'SELECT _ST_Contains($2,$1)'\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-\r
--- Availability: 1.2.2\r
--- Inlines index magic\r
-CREATE OR REPLACE FUNCTION ST_Within(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'SELECT $1 && $2 AND _ST_Contains($2,$1)'\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-\r
--- Availability: 1.2.2\r
--- Inlines index magic\r
-CREATE OR REPLACE FUNCTION ST_Overlaps(geom1 geometry, geom2 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
--- 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
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION _ST_Equals(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'MODULE_PATHNAME','ST_Equals'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
--- Availability: 1.2.1\r
-CREATE OR REPLACE FUNCTION ST_Equals(geom1 geometry, geom2 geometry)\r
-       RETURNS boolean\r
-       AS 'SELECT $1 ~= $2 AND _ST_Equals($1,$2)'\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-\r
--- Deprecation in 1.2.3 \r
--- TODO: drop in 2.0.0 ! \r
-CREATE OR REPLACE FUNCTION Equals(geom1 geometry, geom2 geometry) \r
-       RETURNS boolean \r
-       AS 'MODULE_PATHNAME','ST_Equals' \r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
------------------------------------------------------------------------\r
--- GML & KML INPUT\r
------------------------------------------------------------------------\r
-CREATE OR REPLACE FUNCTION _ST_GeomFromGML(text, int4)\r
-        RETURNS geometry\r
-        AS 'MODULE_PATHNAME','geom_from_gml'\r
-        LANGUAGE 'C' IMMUTABLE;\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_GeomFromGML(text, int4)\r
-        RETURNS geometry\r
-        AS 'MODULE_PATHNAME','geom_from_gml'\r
-        LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION ST_GeomFromGML(text)\r
-        RETURNS geometry\r
-        AS 'SELECT _ST_GeomFromGML($1, 0)'\r
-        LANGUAGE 'SQL' IMMUTABLE STRICT;\r
-\r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION ST_GMLToSQL(text)\r
-        RETURNS geometry\r
-        AS 'SELECT _ST_GeomFromGML($1, 0)'\r
-        LANGUAGE 'SQL' IMMUTABLE STRICT;\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_GMLToSQL(text, int4)\r
-        RETURNS geometry\r
-        AS 'MODULE_PATHNAME','geom_from_gml'\r
-        LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 1.5.0\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
--- GEOJSON INPUT\r
------------------------------------------------------------------------\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_GeomFromGeoJson(text)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME','geom_from_geojson'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
------------------------------------------------------------------------\r
--- SVG OUTPUT\r
------------------------------------------------------------------------\r
--- Availability: 1.2.2\r
--- Changed: 2.0.0 changed to use default args and allow calling by named args\r
-CREATE OR REPLACE FUNCTION ST_AsSVG(geom geometry,rel int4 DEFAULT 0,maxdecimaldigits int4 DEFAULT 15)\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(version, geom) / precision=15 \r
--- Availability: 1.3.2\r
--- ST_AsGML(version, geom, precision)\r
--- Availability: 1.3.2\r
-\r
--- ST_AsGML (geom, precision, option) / version=2\r
--- Availability: 1.4.0\r
--- Changed: 2.0.0 to have default args\r
-CREATE OR REPLACE FUNCTION ST_AsGML(geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0)\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
--- ST_AsGML(version, geom, precision, option, prefix)\r
--- Availability: 2.0.0\r
--- Changed: 2.0.0 to use default and named args\r
-CREATE OR REPLACE FUNCTION ST_AsGML(version int4, geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0, nprefix text DEFAULT null)\r
-       RETURNS TEXT\r
-       AS $$ SELECT _ST_AsGML($1, $2, $3, $4,$5); $$\r
-       LANGUAGE 'SQL' IMMUTABLE;\r
-\r
------------------------------------------------------------------------\r
--- KML OUTPUT\r
------------------------------------------------------------------------\r
--- _ST_AsKML(version, geom, precision, nprefix)\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
--- Changed: 2.0.0 to use default args and allow named args\r
-CREATE OR REPLACE FUNCTION ST_AsKML(geom geometry, maxdecimaldigits int4 DEFAULT 15)\r
-       RETURNS TEXT\r
-       AS $$ SELECT _ST_AsKML(2, ST_Transform($1,4326), $2, null); $$\r
-       LANGUAGE 'SQL' IMMUTABLE STRICT;\r
-\r
--- ST_AsKML(version, geom, precision, text)\r
--- Availability: 2.0.0\r
--- Changed: 2.0.0 allows default args and got rid of other permutations\r
-CREATE OR REPLACE FUNCTION ST_AsKML(version int4, geom geometry, maxdecimaldigits int4 DEFAULT 15, nprefix text DEFAULT null)\r
-       RETURNS TEXT\r
-       AS $$ SELECT _ST_AsKML($1, ST_Transform($2,4326), $3, $4); $$\r
-       LANGUAGE 'SQL' IMMUTABLE;\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, options) / version=1\r
--- Changed 2.0.0 to use default args and named args\r
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0)\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
--- Changed 2.0.0 to use default args and named args\r
-CREATE OR REPLACE FUNCTION ST_AsGeoJson(gj_version int4, geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0)\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
--- Changed 2.0.0 to use default args and named args\r
-CREATE OR REPLACE FUNCTION ST_GeoHash(geom geometry, maxchars int4 DEFAULT 0)\r
-       RETURNS TEXT\r
-               AS 'MODULE_PATHNAME', 'ST_GeoHash'\r
-       LANGUAGE 'C' 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 of old 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
--- PostGIS equivalent function of old 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
-CREATE OR REPLACE FUNCTION ST_SRID(geometry)\r
-       RETURNS int4\r
-       AS 'MODULE_PATHNAME','LWGEOM_get_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
--- 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
--- PostGIS equivalent of old 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
--- 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
--- 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
--- 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
--- 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
--- 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
--- PostGIS equivalent function: ST_GeometryFromText(text)\r
--- SQL/MM alias for ST_GeomFromText\r
-CREATE OR REPLACE FUNCTION ST_WKTToSQL(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_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(ST_GeomFromText($1, $2)) = ''LINESTRING''\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_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 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_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 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_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
--- 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
--- 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(ST_GeomFromWKB($1)) = ''LINESTRING''\r
-       THEN ST_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 ST_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 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_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(ST_GeomFromWKB($1, $2)) = ''GEOMETRYCOLLECTION''\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_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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION ST_ShortestLine(geom1 geometry, geom2 geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION _ST_LongestLine(geom1 geometry, geom2 geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_longestline2d'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION ST_LongestLine(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry,float8)\r
-       RETURNS boolean\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-\r
-CREATE OR REPLACE FUNCTION ST_DFullyWithin(geom1 geometry, geom2 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 "geography.sql.in.c"\r
-\r
-\r
-\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_distance_sphere(geom1 geometry, geom2 geometry)\r
-       RETURNS FLOAT8\r
-       AS $$\r
-       select st_distance(geography($1),geography($2),false)\r
-       $$\r
-       LANGUAGE 'SQL' IMMUTABLE STRICT\r
-       COST 300;\r
-\r
--- Availability: 1.2.2\r
-CREATE OR REPLACE FUNCTION ST_distance_sphere(geom1 geometry, geom2 geometry)\r
-       RETURNS FLOAT8\r
-       AS $$\r
-       select st_distance(geography($1),geography($2),false)\r
-       $$\r
-       LANGUAGE 'SQL' IMMUTABLE STRICT\r
-       COST 300;\r
-\r
-\r
----------------------------------------------------------------\r
--- GEOMETRY_COLUMNS view support functions\r
----------------------------------------------------------------\r
--- New helper function so we can keep list of valid geometry types in one place --\r
--- Maps old names to pramsey beautiful names but can take old name or new name as input\r
--- By default returns new name but can be overridden to return old name for old constraint like support\r
-CREATE OR REPLACE FUNCTION postgis_type_name(geomname varchar, coord_dimension integer, use_new_name boolean DEFAULT true) \r
-       RETURNS varchar\r
-AS\r
-$$\r
- SELECT CASE WHEN $3 THEN new_name ELSE old_name END As geomname\r
-       FROM \r
-       ( VALUES\r
-                ('GEOMETRY', 'Geometry', 2) ,\r
-                       ('GEOMETRY', 'GeometryZ', 3) ,\r
-                       ('GEOMETRY', 'GeometryZM', 4) ,\r
-                       ('GEOMETRYCOLLECTION', 'GeometryCollection', 2) ,\r
-                       ('GEOMETRYCOLLECTION', 'GeometryCollectionZ', 3) ,\r
-                       ('GEOMETRYCOLLECTIONM', 'GeometryCollectionM', 3) ,\r
-                       ('GEOMETRYCOLLECTION', 'GeometryCollectionZM', 4) ,\r
-                       \r
-                       ('POINT', 'Point',2) ,\r
-                       ('POINTM','PointM',3) ,\r
-                       ('POINT', 'PointZ',3) ,\r
-                       ('POINT', 'PointZM',4) ,\r
-                       \r
-                       ('MULTIPOINT','MultiPoint',2) ,\r
-                       ('MULTIPOINT','MultiPointZ',3) ,\r
-                       ('MULTIPOINTM','MultiPointM',3) ,\r
-                       ('MULTIPOINT','MultiPointZM',4) ,\r
-                       \r
-                       ('POLYGON', 'Polygon',2) ,\r
-                       ('POLYGON', 'PolygonZ',3) ,\r
-                       ('POLYGONM', 'PolygonM',3) ,\r
-                       ('POLYGON', 'PolygonZM',4) ,\r
-                       \r
-                       ('MULTIPOLYGON', 'MultiPolygon',2) ,\r
-                       ('MULTIPOLYGON', 'MultiPolygonZ',3) ,\r
-                       ('MULTIPOLYGONM', 'MultiPolygonM',3) ,\r
-                       ('MULTIPOLYGON', 'MultiPolygonZM',4) ,\r
-                       \r
-                       ('MULTILINESTRING', 'MultiLineString',2) ,\r
-                       ('MULTILINESTRING', 'MultiLineStringZ',3) ,\r
-                       ('MULTILINESTRINGM', 'MultiLineStringM',3) ,\r
-                       ('MULTILINESTRING', 'MultiLineStringZM',4) ,\r
-                       \r
-                       ('LINESTRING', 'LineString',2) ,\r
-                       ('LINESTRING', 'LineStringZ',3) ,\r
-                       ('LINESTRINGM', 'LineStringM',3) ,\r
-                       ('LINESTRING', 'LineStringZM',4) ,\r
-                       \r
-                       ('CIRCULARSTRING', 'CircularString',2) ,\r
-                       ('CIRCULARSTRING', 'CircularStringZ',3) ,\r
-                       ('CIRCULARSTRINGM', 'CircularStringM',3) ,\r
-                       ('CIRCULARSTRING', 'CircularStringZM',4) ,\r
-                       \r
-                       ('COMPOUNDCURVE', 'CompoundCurve',2) ,\r
-                       ('COMPOUNDCURVE', 'CompoundCurveZ',3) ,\r
-                       ('COMPOUNDCURVEM', 'CompoundCurveM',3) ,\r
-                       ('COMPOUNDCURVE', 'CompoundCurveZM',4) ,\r
-                       \r
-                       ('CURVEPOLYGON', 'CurvePolygon',2) ,\r
-                       ('CURVEPOLYGON', 'CurvePolygonZ',3) ,\r
-                       ('CURVEPOLYGONM', 'CurvePolygonM',3) ,\r
-                       ('CURVEPOLYGON', 'CurvePolygonZM',4) ,\r
-                       \r
-                       ('MULTICURVE', 'MultiCurve',2 ) ,\r
-                       ('MULTICURVE', 'MultiCurveZ',3 ) ,\r
-                       ('MULTICURVEM', 'MultiCurveM',3 ) ,\r
-                       ('MULTICURVE', 'MultiCurveZM',4 ) ,\r
-                       \r
-                       ('MULTISURFACE', 'MultiSurface', 2) ,\r
-                       ('MULTISURFACE', 'MultiSurfaceZ', 3) ,\r
-                       ('MULTISURFACEM', 'MultiSurfaceM', 3) ,\r
-                       ('MULTISURFACE', 'MultiSurfaceZM', 4) ,\r
-                       \r
-                       ('POLYHEDRALSURFACE', 'PolyhedralSurface',2) ,\r
-                       ('POLYHEDRALSURFACE', 'PolyhedralSurfaceZ',3) ,\r
-                       ('POLYHEDRALSURFACEM', 'PolyhedralSurfaceM',3) ,\r
-                       ('POLYHEDRALSURFACE', 'PolyhedralSurfaceZM',4) ,\r
-                       \r
-                       ('TRIANGLE', 'Triangle',2) ,\r
-                       ('TRIANGLE', 'TriangleZ',3) ,\r
-                       ('TRIANGLEM', 'TriangleM',3) ,\r
-                       ('TRIANGLE', 'TriangleZM',4) ,\r
-\r
-                       ('TIN', 'Tin', 2),\r
-                       ('TIN', 'TinZ', 3),\r
-                       ('TIN', 'TinM', 3),\r
-                       ('TIN', 'TinZM', 4) )\r
-                        As g(old_name, new_name, coord_dimension)\r
-               WHERE (upper(old_name) = upper($1) OR upper(new_name) = upper($1))\r
-                       AND coord_dimension = $2;\r
-$$\r
-language 'sql' IMMUTABLE STRICT COST 200;\r
-\r
-CREATE OR REPLACE FUNCTION postgis_constraint_srid(geomschema text, geomtable text, geomcolumn text) RETURNS integer AS\r
-$$\r
-SELECT replace(replace(split_part(s.consrc, ' = ', 2), ')', ''), '(', '')::integer\r
-                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s\r
-                WHERE n.nspname = $1\r
-                AND c.relname = $2\r
-                AND a.attname = $3\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
-$$\r
-LANGUAGE 'sql' STABLE STRICT;\r
-\r
-CREATE OR REPLACE FUNCTION postgis_constraint_dims(geomschema text, geomtable text, geomcolumn text) RETURNS integer AS\r
-$$\r
-SELECT  replace(split_part(s.consrc, ' = ', 2), ')', '')::integer\r
-                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s\r
-                WHERE n.nspname = $1\r
-                AND c.relname = $2\r
-                AND a.attname = $3\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
-$$\r
-LANGUAGE 'sql' STABLE STRICT;\r
-\r
--- support function to pull out geometry type from constraint check\r
--- will return pretty name instead of ugly name\r
-CREATE OR REPLACE FUNCTION postgis_constraint_type(geomschema text, geomtable text, geomcolumn text) RETURNS varchar AS\r
-$$\r
-SELECT  replace(split_part(s.consrc, '''', 2), ')', '')::varchar               \r
-                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s\r
-                WHERE n.nspname = $1\r
-                AND c.relname = $2\r
-                AND a.attname = $3\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
-$$\r
-LANGUAGE 'sql' STABLE STRICT;\r
-\r
-CREATE OR REPLACE VIEW geometry_columns AS \r
-  SELECT current_database()::varchar(256) AS f_table_catalog, \r
-    n.nspname::varchar(256) AS f_table_schema, \r
-    c.relname::varchar(256) AS f_table_name, \r
-    a.attname::varchar(256) AS f_geometry_column, \r
-    COALESCE(NULLIF(postgis_typmod_dims(a.atttypmod),2),\r
-             postgis_constraint_dims(n.nspname, c.relname, a.attname),\r
-             2) AS coord_dimension, \r
-    COALESCE(NULLIF(postgis_typmod_srid(a.atttypmod),0),\r
-             postgis_constraint_srid(n.nspname, c.relname, a.attname),\r
-             0) AS srid, \r
-    -- force to be uppercase with no ZM so is backwards compatible\r
-    -- with old geometry_columns\r
-    replace(\r
-      replace(\r
-        COALESCE(\r
-          NULLIF(upper(postgis_typmod_type(a.atttypmod)::text), 'GEOMETRY'),\r
-          postgis_constraint_type(n.nspname, c.relname, a.attname),\r
-          'GEOMETRY'\r
-        ), 'ZM', ''\r
-      ), 'Z', ''\r
-    )::varchar(30) AS type\r
-  FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n\r
-  WHERE t.typname = 'geometry'::name \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 (c.relkind = 'r'::"char" OR c.relkind = 'v'::"char")\r
-    AND NOT pg_is_other_temp_schema(c.relnamespace)\r
-    AND NOT ( n.nspname = 'public' AND c.relname = 'raster_columns' );\r
-\r
--- TODO: support RETURNING and raise a WARNING\r
-CREATE OR REPLACE RULE geometry_columns_insert AS\r
-        ON INSERT TO geometry_columns\r
-        DO INSTEAD NOTHING;\r
-\r
--- TODO: raise a WARNING\r
-CREATE OR REPLACE RULE geometry_columns_update AS\r
-        ON UPDATE TO geometry_columns\r
-        DO INSTEAD NOTHING;\r
-\r
--- TODO: raise a WARNING\r
-CREATE OR REPLACE RULE geometry_columns_delete AS\r
-        ON DELETE TO geometry_columns\r
-        DO INSTEAD NOTHING;\r
-\r
-\r
----------------------------------------------------------------\r
--- 3D-functions\r
----------------------------------------------------------------\r
-\r
-CREATE OR REPLACE FUNCTION ST_3DDistance(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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
--- PostGIS equivalent function: ST_ndims(geometry)\r
-CREATE OR REPLACE FUNCTION ST_CoordDim(Geometry geometry)\r
-       RETURNS smallint\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_ndims'\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 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 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 geometry)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_line_desegmentize'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-       \r
--- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION _ST_OrderingEquals(GeometryA geometry, GeometryB geometry)\r
-       RETURNS boolean\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_same'\r
-       LANGUAGE 'C' IMMUTABLE STRICT\r
-       COST 100;\r
-\r
--- Availability: 1.3.0\r
-CREATE OR REPLACE FUNCTION ST_OrderingEquals(GeometryA geometry, GeometryB geometry)\r
-       RETURNS boolean\r
-       AS $$ \r
-       SELECT $1 ~= $2 AND _ST_OrderingEquals($1, $2)\r
-       $$      \r
-       LANGUAGE 'SQL' IMMUTABLE STRICT; \r
-       \r
--------------------------------------------------------------------------------\r
--- SQL/MM - SQL Functions on type ST_Point\r
--------------------------------------------------------------------------------\r
-\r
--- PostGIS equivalent function: ST_MakePoint(XCoordinate float8,YCoordinate float8)\r
-CREATE OR REPLACE FUNCTION ST_Point(float8, float8)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-       \r
--- PostGIS equivalent function: ST_MakePolygon(Geometry geometry)\r
-CREATE OR REPLACE FUNCTION ST_Polygon(geometry, int)\r
-       RETURNS geometry\r
-       AS $$ \r
-       SELECT ST_SetSRID(ST_MakePolygon($1), $2)\r
-       $$      \r
-       LANGUAGE 'SQL' IMMUTABLE STRICT; \r
-       \r
--- PostGIS equivalent function: GeomFromWKB(WKB bytea))\r
--- Note: Defaults to an SRID=-1, not 0 as per SQL/MM specs.\r
-CREATE OR REPLACE FUNCTION ST_WKBToSQL(WKB bytea)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'\r
-       LANGUAGE 'C' IMMUTABLE STRICT; \r
-       \r
----\r
--- Linear referencing functions\r
----\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, FromMeasure float8, ToMeasure float8, LeftRightOffset float8 default 0.0)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'ST_LocateBetween'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-       \r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, LeftRightOffset float8 default 0.0)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'ST_LocateAlong'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Only accepts LINESTRING as parameters.\r
--- Availability: 1.4.0\r
-CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(Geometry geometry, FromElevation float8, ToElevation float8)\r
-       RETURNS geometry\r
-       AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
--- Availability: 2.0.0\r
-CREATE OR REPLACE FUNCTION ST_InterpolatePoint(Line geometry, Point geometry)\r
-       RETURNS float8\r
-       AS 'MODULE_PATHNAME', 'ST_InterpolatePoint'\r
-       LANGUAGE 'C' IMMUTABLE STRICT;\r
-\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 DEFAULT 48)\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 ST_MakeLine(ST_PointN(ring,idx1),ST_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_Rotate(l1,pi()/2,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(ST_X(ST_PointN(l1,2))+sin(a1)*dist,ST_Y(ST_PointN(l1,2))+cos(a1)*dist),-1);\r
-                               l1 = ST_AddPoint(l1,ST_Makepoint(ST_X(ST_PointN(l1,1))-sin(a1)*dist,ST_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_Rotate(l2,pi()/2,p2);\r
-                               a2 = ST_Azimuth(ST_PointN(l2,1),ST_PointN(l2,2));\r
-                               l2 = ST_AddPoint(l2,ST_Makepoint(ST_X(ST_PointN(l2,2))+sin(a2)*dist,ST_Y(ST_PointN(l2,2))+cos(a2)*dist),-1);\r
-                               l2 = ST_AddPoint(l2,ST_Makepoint(ST_X(ST_PointN(l2,1))-sin(a2)*dist,ST_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
\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
-       var_inputgeom geometry;\r
-       vexring GEOMETRY;\r
-       cavering GEOMETRY;\r
-       cavept geometry[];\r
-       seglength double precision;\r
-       var_tempgeom geometry;\r
-       scale_factor integer := 1;\r
-       i integer;\r
-       \r
-       BEGIN\r
-\r
-               -- First compute the ConvexHull of the geometry\r
-               vexhull := ST_ConvexHull(param_inputgeom);\r
-               var_inputgeom := 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
-               IF abs(ST_X(ST_PointN(vexring,1))) < 1 THEN --scale the geometry to prevent stupid precision errors - not sure it works so make low for now\r
-                       scale_factor := 100;\r
-                       vexring := ST_Scale(vexring, scale_factor,scale_factor);\r
-                       var_inputgeom := ST_Scale(var_inputgeom, scale_factor, scale_factor);\r
-                       --RAISE NOTICE 'Scaling';\r
-               END IF;\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(var_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
-\r
-               var_resultgeom := ST_MakeLine(geom) \r
-                       FROM ST_Dump(cavering) As foo;\r
-\r
-               IF ST_IsSimple(var_resultgeom) THEN\r
-                       var_resultgeom := ST_MakePolygon(var_resultgeom);\r
-                       --RAISE NOTICE 'is Simple: %', var_resultgeom;\r
-               ELSE /** will not result in a valid polygon -- just return convex hull **/\r
-                       --RAISE NOTICE 'is not Simple: %', var_resultgeom;\r
-                       var_resultgeom := ST_ConvexHull(var_resultgeom);\r
-               END IF;\r
-               \r
-               IF scale_factor > 1 THEN -- scale the result back\r
-                       var_resultgeom := ST_Scale(var_resultgeom, 1/scale_factor, 1/scale_factor);\r
-               END IF;\r
-               RETURN var_resultgeom;\r
-       \r
-       END;\r
-$$\r
-  LANGUAGE plpgsql IMMUTABLE STRICT;\r
-  \r
-CREATE OR REPLACE FUNCTION ST_ConcaveHull(param_geom geometry, param_pctconvex float, param_allow_holes boolean DEFAULT false) 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
--- 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, options)\r
-CREATE OR REPLACE FUNCTION ST_AsX3D(geom geometry, maxdecimaldigits integer DEFAULT 15, options integer DEFAULT 0)\r
-       RETURNS TEXT\r
-       AS $$SELECT _ST_AsX3D(3,$1,$2,$3,'');$$\r
-       LANGUAGE 'sql' IMMUTABLE;\r
-\r
-COMMIT;\r
-\r
-#include "postgis_drop.sql.in.c"\r
+-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+--
+-- $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;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_typmod_in(cstring[])
+       RETURNS integer
+       AS 'MODULE_PATHNAME','geometry_typmod_in'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_typmod_out(integer)
+       RETURNS cstring
+       AS 'MODULE_PATHNAME','postgis_typmod_out'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION geometry_analyze(internal)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'geometry_analyze_2d'
+       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,
+       typmod_in = geometry_typmod_in,
+       typmod_out = geometry_typmod_out,
+       delimiter = ':',
+    alignment = double,
+       analyze = geometry_analyze,
+       storage = main
+);
+
+
+-- Availability: 2.0.0
+-- Special cast for enforcing the typmod restrictions
+CREATE OR REPLACE FUNCTION geometry(geometry, integer, boolean)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','geometry_enforce_typmod'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 2.0.0
+CREATE CAST (geometry AS geometry) WITH FUNCTION geometry(geometry, integer, boolean) AS IMPLICIT;
+
+
+-------------------------------------------------------------------
+--  BOX3D TYPE
+-- Point coordinate data access
+-------------------------------------------
+-- 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;
+
+-------------------------------------------
+-------------------------------------------------------------------
+
+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
+);
+
+-----------------------------------------------------------------------
+-- BOX2D
+-----------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION box2d_in(cstring)
+       RETURNS box2d
+       AS 'MODULE_PATHNAME','BOX2D_in'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION box2d_out(box2d)
+       RETURNS cstring
+       AS 'MODULE_PATHNAME','BOX2D_out'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE TYPE box2d (
+       internallength = 65,
+       input = box2d_in,
+       output = box2d_out,
+       storage = plain
+);
+
+-------------------------------------------------------------------
+--  BOX2DF TYPE (INTERNAL ONLY)
+-------------------------------------------------------------------
+--
+-- Box2Df type is used by the GiST index bindings. 
+-- In/out functions are stubs, as all access should be internal.
+---
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION box2df_in(cstring)
+       RETURNS box2df
+       AS 'MODULE_PATHNAME','box2df_in'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION box2df_out(box2df)
+       RETURNS cstring
+       AS 'MODULE_PATHNAME','box2df_out'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 2.0.0
+CREATE TYPE box2df (
+       internallength = 16,
+       input = box2df_in,
+       output = box2df_out,
+       storage = plain,
+       alignment = double
+);
+
+
+-------------------------------------------------------------------
+--  GIDX TYPE (INTERNAL ONLY)
+-------------------------------------------------------------------
+--
+-- GIDX type is used by the N-D and GEOGRAPHY GiST index bindings. 
+-- In/out functions are stubs, as all access should be internal.
+---
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION gidx_in(cstring)
+       RETURNS gidx
+       AS 'MODULE_PATHNAME','gidx_in'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION gidx_out(gidx)
+       RETURNS cstring
+       AS 'MODULE_PATHNAME','gidx_out'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+-- Availability: 1.5.0
+CREATE TYPE gidx (
+       internallength = variable,
+       input = gidx_in,
+       output = gidx_out,
+       storage = plain,
+       alignment = double
+);
+
+-------------------------------------------------------------------
+-- BTREE indexes
+-------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION geometry_lt(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'lwgeom_lt'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION geometry_le(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'lwgeom_le'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION geometry_gt(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'lwgeom_gt'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION geometry_ge(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'lwgeom_ge'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION geometry_eq(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'lwgeom_eq'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION geometry_cmp(geom1 geometry, geom2 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 (geom1 geometry, geom2 geometry);
+
+
+-----------------------------------------------------------------------------
+-- GiST 2D GEOMETRY-over-GSERIALIZED INDEX
+-----------------------------------------------------------------------------
+
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+-- GiST Support Functions
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_distance_2d(internal,geometry,int4) 
+       RETURNS float8 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_distance_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_consistent_2d(internal,geometry,int4) 
+       RETURNS bool 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_consistent_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_compress_2d(internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME','gserialized_gist_compress_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_penalty_2d(internal,internal,internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_penalty_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_picksplit_2d(internal, internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_picksplit_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_union_2d(bytea, internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_union_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_same_2d(geom1 geometry, geom2 geometry, internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_same_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_decompress_2d(internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_decompress_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_sel_2d (internal, oid, internal, int4)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'geometry_gist_sel_2d'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_joinsel_2d(internal, oid, internal, smallint)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'geometry_gist_joinsel_2d'
+       LANGUAGE 'C';
+
+-----------------------------------------------------------------------------
+-- GEOMETRY Operators
+-----------------------------------------------------------------------------
+
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+-- 2D GEOMETRY Operators
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_overlaps(geom1 geometry, geom2 geometry) 
+       RETURNS boolean 
+       AS 'MODULE_PATHNAME' ,'gserialized_overlaps_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR && (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overlaps,
+       COMMUTATOR = '&&'
+--     ,RESTRICT = contsel, JOIN = contjoinsel
+       ,RESTRICT = geometry_gist_sel_2d, JOIN = geometry_gist_joinsel_2d       
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_same(geom1 geometry, geom2 geometry) 
+       RETURNS boolean 
+       AS 'MODULE_PATHNAME' ,'gserialized_same_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR ~= (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_same,
+       RESTRICT = contsel, JOIN = contjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_distance_centroid(geom1 geometry, geom2 geometry) 
+       RETURNS float8 
+       AS 'MODULE_PATHNAME' ,'gserialized_distance_centroid_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_distance_box(geom1 geometry, geom2 geometry) 
+       RETURNS float8 
+       AS 'MODULE_PATHNAME' ,'gserialized_distance_box_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+#if POSTGIS_PGSQL_VERSION >= 91
+CREATE OPERATOR <-> (
+    LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_distance_centroid,
+    COMMUTATOR = '<->'
+);
+
+CREATE OPERATOR <#> (
+    LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_distance_box,
+    COMMUTATOR = '<#>'
+);
+#endif
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_contains(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_contains_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_within(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_within_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR @ (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_within,
+       COMMUTATOR = '~',
+       RESTRICT = contsel, JOIN = contjoinsel
+);
+
+CREATE OPERATOR ~ (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_contains,
+       COMMUTATOR = '@',
+       RESTRICT = contsel, JOIN = contjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_left(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_left_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR << (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_left,
+       COMMUTATOR = '>>',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_overleft(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_overleft_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR &< (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overleft,
+       COMMUTATOR = '&>',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_below(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_below_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR <<| (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_below,
+       COMMUTATOR = '|>>',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_overbelow(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_overbelow_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR &<| (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overbelow,
+       COMMUTATOR = '|&>',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_overright(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_overright_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR &> (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overright,
+       COMMUTATOR = '&<',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_right(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_right_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR >> (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_right,
+       COMMUTATOR = '<<',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_overabove(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_overabove_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR |&> (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overabove,
+       COMMUTATOR = '&<|',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_above(geom1 geometry, geom2 geometry)
+       RETURNS bool
+       AS 'MODULE_PATHNAME', 'gserialized_above_2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OPERATOR |>> (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_above,
+       COMMUTATOR = '<<|',
+       RESTRICT = positionsel, JOIN = positionjoinsel
+);
+
+-- Availability: 2.0.0
+CREATE OPERATOR CLASS gist_geometry_ops_2d
+       DEFAULT FOR TYPE geometry USING GIST AS
+       STORAGE box2df,
+       OPERATOR        1        <<  ,
+       OPERATOR        2        &<      ,
+       OPERATOR        3        &&  ,
+       OPERATOR        4        &>      ,
+       OPERATOR        5        >>      ,
+       OPERATOR        6        ~=      ,
+       OPERATOR        7        ~       ,
+       OPERATOR        8        @       ,
+       OPERATOR        9        &<| ,
+       OPERATOR        10       <<| ,
+       OPERATOR        11       |>> ,
+       OPERATOR        12       |&> ,
+#if POSTGIS_PGSQL_VERSION >= 91
+       OPERATOR        13       <-> FOR ORDER BY pg_catalog.float_ops,
+       OPERATOR        14       <#> FOR ORDER BY pg_catalog.float_ops,
+       FUNCTION        8        geometry_gist_distance_2d (internal, geometry, int4),
+#endif
+       FUNCTION        1        geometry_gist_consistent_2d (internal, geometry, int4),
+       FUNCTION        2        geometry_gist_union_2d (bytea, internal),
+       FUNCTION        3        geometry_gist_compress_2d (internal),
+       FUNCTION        4        geometry_gist_decompress_2d (internal),
+       FUNCTION        5        geometry_gist_penalty_2d (internal, internal, internal),
+       FUNCTION        6        geometry_gist_picksplit_2d (internal, internal),
+       FUNCTION        7        geometry_gist_same_2d (geom1 geometry, geom2 geometry, internal);
+
+
+-----------------------------------------------------------------------------
+-- GiST ND GEOMETRY-over-GSERIALIZED
+-----------------------------------------------------------------------------
+
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+-- GiST Support Functions
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_consistent_nd(internal,geometry,int4) 
+       RETURNS bool 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_consistent'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_compress_nd(internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME','gserialized_gist_compress'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_penalty_nd(internal,internal,internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_penalty'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_picksplit_nd(internal, internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_picksplit'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_union_nd(bytea, internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_union'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_same_nd(geometry, geometry, internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_same'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_gist_decompress_nd(internal) 
+       RETURNS internal 
+       AS 'MODULE_PATHNAME' ,'gserialized_gist_decompress'
+       LANGUAGE 'C';
+
+-- Availability: 2.0.0
+--CREATE OR REPLACE FUNCTION geometry_gist_selectivity_nd (internal, oid, internal, int4)
+--     RETURNS float8
+--     AS 'MODULE_PATHNAME', 'geometry_gist_selectivity_nd'
+--     LANGUAGE 'C';
+
+-- Availability: 2.0.0
+--CREATE OR REPLACE FUNCTION geography_gist_join_selectivity_nd(internal, oid, internal, smallint)
+--     RETURNS float8
+--     AS 'MODULE_PATHNAME', 'geometry_gist_join_selectivity_nd'
+--     LANGUAGE 'C';
+
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+-- N-D GEOMETRY Operators
+-- ---------- ---------- ---------- ---------- ---------- ---------- ----------
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION geometry_overlaps_nd(geometry, geometry) 
+       RETURNS boolean 
+       AS 'MODULE_PATHNAME' ,'gserialized_overlaps'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 2.0.0
+CREATE OPERATOR &&& (
+       LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_overlaps_nd,
+       COMMUTATOR = '&&&'
+       ,RESTRICT = contsel, JOIN = contjoinsel
+--     ,RESTRICT = geometry_gist_selectivity_nd 
+--     ,JOIN = geometry_gist_join_selectivity_nd
+);
+
+-- Availability: 2.0.0
+CREATE OPERATOR CLASS gist_geometry_ops_nd
+       FOR TYPE geometry USING GIST AS
+       STORAGE         gidx,
+       OPERATOR        3        &&&    ,
+--     OPERATOR        6        ~=     ,
+--     OPERATOR        7        ~      ,
+--     OPERATOR        8        @      ,
+       FUNCTION        1        geometry_gist_consistent_nd (internal, geometry, int4),
+       FUNCTION        2        geometry_gist_union_nd (bytea, internal),
+       FUNCTION        3        geometry_gist_compress_nd (internal),
+       FUNCTION        4        geometry_gist_decompress_nd (internal),
+       FUNCTION        5        geometry_gist_penalty_nd (internal, internal, internal),
+       FUNCTION        6        geometry_gist_picksplit_nd (internal, internal),
+       FUNCTION        7        geometry_gist_same_nd (geometry, geometry, internal);
+
+
+-----------------------------------------------------------------------------
+-- 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_Rotate(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: 2.0.0
+CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8,float8,float8)
+       RETURNS geometry
+       AS 'SELECT ST_Affine($1,  cos($2), -sin($2), 0,  sin($2),  cos($2), 0, 0, 0, 1, $3 - cos($2) * $3 + sin($2) * $4, $4 - sin($2) * $3 - cos($2) * $4, 0)'
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_Rotate(geometry,float8,geometry)
+       RETURNS geometry
+       AS 'SELECT ST_Affine($1,  cos($2), -sin($2), 0,  sin($2),  cos($2), 0, 0, 0, 1, ST_X($3) - cos($2) * ST_X($3) + sin($2) * ST_Y($3), ST_Y($3) - sin($2) * ST_X($3) - cos($2) * ST_Y($3), 0)'
+       LANGUAGE 'sql' IMMUTABLE STRICT;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_RotateZ(geometry,float8)
+       RETURNS geometry
+       AS 'SELECT ST_Rotate($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 FUNCTIONS
+-----------------------------------------------------------------------------
+
+-- 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 FUNCTIONS
+-----------------------------------------------------------------------------
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_expand(box2d,float8)
+       RETURNS box2d
+       AS 'MODULE_PATHNAME', 'BOX2D_expand'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION postgis_getbbox(geometry)
+       RETURNS box2d
+       AS 'MODULE_PATHNAME','LWGEOM_to_BOX2D'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_MakeBox2d(geom1 geometry, geom2 geometry)
+       RETURNS box2d
+       AS 'MODULE_PATHNAME', 'BOX2D_construct'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_Combine_BBox(box2d,geometry)
+       RETURNS box2d
+       AS 'MODULE_PATHNAME', 'BOX2D_combine'
+       LANGUAGE 'C' IMMUTABLE;
+
+-----------------------------------------------------------------------
+-- ESTIMATED_EXTENT( <schema name>, <table name>, <column name> )
+-----------------------------------------------------------------------
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text,text) RETURNS box2d AS
+       'MODULE_PATHNAME', 'geometry_estimated_extent'
+       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;
+
+-----------------------------------------------------------------------
+-- ESTIMATED_EXTENT( <table name>, <column name> )
+-----------------------------------------------------------------------
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_estimated_extent(text,text) RETURNS box2d AS
+       'MODULE_PATHNAME', 'geometry_estimated_extent'
+       LANGUAGE 'C' IMMUTABLE STRICT SECURITY DEFINER;
+
+-----------------------------------------------------------------------
+-- FIND_EXTENT( <schema name>, <table name>, <column name> )
+-----------------------------------------------------------------------
+-- 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 || '") As extent FROM "' || schemaname || '"."' || tablename || '"' LOOP
+               return myrec.extent;
+       END LOOP;
+END;
+$$
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;
+
+
+-----------------------------------------------------------------------
+-- FIND_EXTENT( <table name>, <column name> )
+-----------------------------------------------------------------------
+-- 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 ST_Extent("' || columnname || '") As extent FROM "' || tablename || '"' LOOP
+               return myrec.extent;
+       END LOOP;
+END;
+$$
+LANGUAGE 'plpgsql' IMMUTABLE STRICT;
+
+
+-------------------------------------------
+-- 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.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;
+
+------------------------------------------------------------------------
+-- Measures
+------------------------------------------------------------------------
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_3DLength(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: 2.0.0
+CREATE OR REPLACE FUNCTION ST_3DLength_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: 2.0.0
+CREATE OR REPLACE FUNCTION ST_3DPerimeter(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(geom1 geometry, geom2 geometry,spheroid)
+       RETURNS FLOAT8
+       AS 'MODULE_PATHNAME','LWGEOM_distance_ellipsoid'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Minimum distance. 2d only.
+
+-- PostGIS equivalent function: distance(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION ST_Distance(geom1 geometry, geom2 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(geom1 geometry, geom2 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: 2.0.0
+CREATE OR REPLACE FUNCTION ST_CollectionHomogenize(geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_CollectionHomogenize'
+       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: 2.0.0
+CREATE OR REPLACE FUNCTION ST_3DMakeBox(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_makeline'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_AddPoint(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_addpoint'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_AddPoint(geom1 geometry, geom2 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
+-- Availability: 2.0.0 - made srid optional
+CREATE OR REPLACE FUNCTION ST_MakeEnvelope(float8, float8, float8, float8, integer DEFAULT 0)
+       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', 'ST_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);
+
+-- 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  STRICT;
+
+
+
+-------------------------------------------------------------------
+-- SPATIAL_REF_SYS
+-------------------------------------------------------------------
+CREATE TABLE spatial_ref_sys (
+        srid integer not null primary key
+               check (srid > 0 and srid <= SRID_USR_MAX),
+        auth_name varchar(256),
+        auth_srid integer,
+        srtext varchar(2048),
+        proj4text varchar(2048)
+);
+
+
+-----------------------------------------------------------------------
+-- 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
+-- Revised: 2.0.0 -- no longer deletes from geometry_columns
+-- Has new use_typmod option that defaults to true.  
+-- If use typmod is  set to false will use old constraint behavior.
+-- Will only touch table missing typmod or geometry constraints
+-----------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION populate_geometry_columns(use_typmod boolean DEFAULT true)
+       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;
+
+       -- 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%' AND c.relname != 'raster_columns' ;
+
+       -- 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%' AND c.relname != 'raster_columns' 
+       LOOP
+
+               inserted := inserted + populate_geometry_columns(gcs.oid, use_typmod);
+       END LOOP;
+
+       IF oldcount > inserted THEN
+           stale = oldcount-inserted;
+       ELSE
+           stale = 0;
+       END IF;
+
+       RETURN 'probed:' ||probed|| ' inserted:'||inserted;
+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, use_typmod boolean DEFAULT true)
+       RETURNS integer AS
+$$
+DECLARE
+       gcs         RECORD;
+       gc          RECORD;
+       gc_old      RECORD;
+       gsrid       integer;
+       gndims      integer;
+       gtype       text;
+       query       text;
+       gc_is_valid boolean;
+       inserted    integer;
+       constraint_successful boolean := false;
+
+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;
+    
+        gc_is_valid := true;
+        -- Find the srid, coord_dimension, and type of current geometry
+        -- in geometry_columns -- which is now a view
+        
+        SELECT type, srid, coord_dimension INTO gc_old 
+            FROM geometry_columns 
+            WHERE f_table_schema = gcs.nspname AND f_table_name = gcs.relname AND f_geometry_column = gcs.attname; 
+            
+        IF upper(gc_old.type) = 'GEOMETRY' THEN
+        -- This is an unconstrained geometry we need to do something
+        -- We need to figure out what to set the type by inspecting the data
+            EXECUTE 'SELECT st_srid(' || quote_ident(gcs.attname) || ') As srid, GeometryType(' || quote_ident(gcs.attname) || ') As type, ST_NDims(' || quote_ident(gcs.attname) || ') As dims ' ||
+                     ' FROM ONLY ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || 
+                     ' WHERE ' || quote_ident(gcs.attname) || ' IS NOT NULL LIMIT 1;'
+                INTO gc;
+            IF gc IS NULL THEN -- there is no data so we can not determine geometry type
+               RAISE WARNING 'No data in table %.%, so no information to determine geometry type and srid', gcs.nspname, gcs.relname;
+               RETURN 0;
+            END IF;
+            gsrid := gc.srid; gtype := gc.type; gndims := gc.dims;
+               
+            IF use_typmod THEN
+                BEGIN
+                    EXECUTE 'ALTER TABLE ' || quote_ident(gcs.nspname) || '.' || quote_ident(gcs.relname) || ' ALTER COLUMN ' || quote_ident(gcs.attname) || 
+                        ' TYPE geometry(' || postgis_type_name(gtype, gndims, true) || ', ' || gsrid::text  || ') ';
+                    inserted := inserted + 1;
+                EXCEPTION
+                        WHEN invalid_parameter_value THEN
+                        RAISE WARNING 'Could not convert ''%'' in ''%.%'' to use typmod with srid %, type: % ', quote_ident(gcs.attname), quote_ident(gcs.nspname), quote_ident(gcs.relname), gsrid, postgis_type_name(gtype, gndims, true);
+                            gc_is_valid := false;
+                END;
+                
+            ELSE
+                -- Try to apply srid check to column
+               constraint_successful = false;
+                IF (gsrid > 0 AND postgis_constraint_srid(gcs.nspname, gcs.relname,gcs.attname) IS 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 || ')';
+                        constraint_successful := true;
+                    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;
+                
+                -- Try to apply ndims check to column
+                IF (gndims IS NOT NULL AND postgis_constraint_dims(gcs.nspname, gcs.relname,gcs.attname) IS 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||')';
+                        constraint_successful := true;
+                    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;
+    
+                -- Try to apply geometrytype check to column
+                IF (gtype IS NOT NULL AND postgis_constraint_type(gcs.nspname, gcs.relname,gcs.attname) IS 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))';
+                        constraint_successful := true;
+                    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;
+                 --only count if we were successful in applying at least one constraint
+                IF constraint_successful THEN
+                       inserted := inserted + 1;
+                END IF;
+            END IF;            
+           END IF;
+
+       END LOOP;
+
+       RETURN inserted;
+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(catalog_name varchar,schema_name varchar,table_name varchar,column_name varchar,new_srid_in integer,new_type varchar,new_dim integer, use_typmod boolean DEFAULT true)
+       RETURNS text
+       AS
+$$
+DECLARE
+       rec RECORD;
+       sr varchar;
+       real_schema name;
+       sql text;
+       new_srid integer;
+
+BEGIN
+
+       -- Verify geometry type
+       IF (postgis_type_name(new_type,new_dim) IS NULL )
+       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', new_type, new_dim;
+               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_in > 0 ) THEN
+               IF new_srid_in > SRID_USR_MAX THEN
+                       RAISE EXCEPTION 'AddGeometryColumn() - SRID must be <= %', SRID_USR_MAX;
+               END IF;
+               new_srid := new_srid_in;
+               SELECT SRID INTO sr FROM spatial_ref_sys WHERE SRID = new_srid;
+               IF NOT FOUND THEN
+                       RAISE EXCEPTION 'AddGeometryColumn() - invalid SRID';
+                       RETURN 'fail';
+               END IF;
+       ELSE
+               new_srid := ST_SRID('POINT EMPTY'::geometry);
+               IF ( new_srid_in != new_srid ) THEN
+                       RAISE NOTICE 'SRID value % converted to the officially unknown SRID value %', new_srid_in, new_srid;
+               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
+       IF use_typmod THEN
+            sql := 'ALTER TABLE ' ||
+            quote_ident(real_schema) || '.' || quote_ident(table_name)
+            || ' ADD COLUMN ' || quote_ident(column_name) ||
+            ' geometry(' || postgis_type_name(new_type, new_dim) || ', ' || new_srid::text || ')';
+        RAISE DEBUG '%', sql;
+       ELSE
+        sql := 'ALTER TABLE ' ||
+            quote_ident(real_schema) || '.' || quote_ident(table_name)
+            || ' ADD COLUMN ' || quote_ident(column_name) ||
+            ' geometry ';
+        RAISE DEBUG '%', sql;
+    END IF;
+       EXECUTE sql;
+
+       IF NOT use_typmod THEN
+        -- 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;
+    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(schema_name varchar,table_name varchar,column_name varchar,new_srid integer,new_type varchar,new_dim integer, use_typmod boolean DEFAULT true) RETURNS text AS $$
+DECLARE
+       ret  text;
+BEGIN
+       SELECT AddGeometryColumn('',$1,$2,$3,$4,$5,$6,$7) 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(table_name varchar,column_name varchar,new_srid integer,new_type varchar,new_dim integer, use_typmod boolean DEFAULT true) RETURNS text AS $$
+DECLARE
+       ret  text;
+BEGIN
+       SELECT AddGeometryColumn('','',$1,$2,$3,$4,$5, $6) 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(catalog_name varchar, schema_name varchar,table_name varchar,column_name varchar)
+       RETURNS text
+       AS
+$$
+DECLARE
+       myrec RECORD;
+       okay boolean;
+       real_schema name;
+
+BEGIN
+
+
+       -- Find, check or fix schema_name
+       IF ( schema_name != '' ) THEN
+               okay = false;
+
+               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP
+                       okay := true;
+               END LOOP;
+
+               IF ( okay <>  true ) 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 = false;
+       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 := true;
+       END LOOP;
+       IF (okay <> true) THEN
+               RAISE EXCEPTION 'column not found in geometry_columns table';
+               RETURN false;
+       END IF;
+
+       -- 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(schema_name varchar, table_name varchar,column_name 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(table_name varchar, column_name 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(catalog_name varchar, schema_name varchar, table_name varchar)
+       RETURNS text
+       AS
+$$
+DECLARE
+       real_schema name;
+
+BEGIN
+
+       IF ( schema_name = '' ) THEN
+               SELECT current_schema() into real_schema;
+       ELSE
+               real_schema = schema_name;
+       END IF;
+
+       -- TODO: Should we warn if table doesn't exist probably instead just saying dropped
+       -- Remove table
+       EXECUTE 'DROP TABLE IF EXISTS '
+               || quote_ident(real_schema) || '.' ||
+               quote_ident(table_name) || ' RESTRICT';
+
+       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(schema_name varchar, table_name varchar) RETURNS text AS
+$$ SELECT DropGeometryTable('',$1,$2) $$
+LANGUAGE 'sql' VOLATILE STRICT;
+
+-----------------------------------------------------------------------
+-- DROPGEOMETRYTABLE
+--   <table>
+-----------------------------------------------------------------------
+--
+-- Drop a table and all its references in geometry_columns
+-- For PG>=73 use current_schema()
+--
+-----------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION DropGeometryTable(table_name 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(catalogn_name varchar,schema_name varchar,table_name varchar,column_name varchar,new_srid_in integer)
+       RETURNS text
+       AS
+$$
+DECLARE
+       myrec RECORD;
+       okay boolean;
+       cname varchar;
+       real_schema name;
+       unknown_srid integer;
+       new_srid integer := new_srid_in;
+
+BEGIN
+
+
+       -- Find, check or fix schema_name
+       IF ( schema_name != '' ) THEN
+               okay = false;
+
+               FOR myrec IN SELECT nspname FROM pg_namespace WHERE text(nspname) = schema_name LOOP
+                       okay := true;
+               END LOOP;
+
+               IF ( okay <> true ) THEN
+                       RAISE EXCEPTION 'Invalid schema name';
+               ELSE
+                       real_schema = schema_name;
+               END IF;
+       ELSE
+               SELECT INTO real_schema current_schema()::text;
+       END IF;
+
+       -- Ensure that column_name is in geometry_columns
+       okay = false;
+       FOR myrec IN SELECT type, coord_dimension FROM geometry_columns WHERE f_table_schema = text(real_schema) and f_table_name = table_name and f_geometry_column = column_name LOOP
+               okay := true;
+       END LOOP;
+       IF (NOT okay) THEN
+               RAISE EXCEPTION 'column not found in geometry_columns table';
+               RETURN false;
+       END IF;
+
+       -- Ensure that new_srid is valid
+       IF ( new_srid > 0 ) THEN
+               IF ( SELECT count(*) = 0 from spatial_ref_sys where srid = new_srid ) THEN
+                       RAISE EXCEPTION 'invalid SRID: % not found in spatial_ref_sys', new_srid;
+                       RETURN false;
+               END IF;
+       ELSE
+               unknown_srid := ST_SRID('POINT EMPTY'::geometry);
+               IF ( new_srid != unknown_srid ) THEN
+                       new_srid := unknown_srid;
+                       RAISE NOTICE 'SRID value % converted to the officially unknown SRID value %', new_srid_in, new_srid;
+               END IF;
+       END IF;
+
+       IF postgis_constraint_srid(schema_name, table_name, column_name) IS NOT NULL THEN 
+       -- srid was enforced with constraints before, keep it that way.
+        -- 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 || ')';
+    ELSE 
+        -- We will use typmod to enforce if no srid constraints
+        -- We are using postgis_type_name to lookup the new name 
+        -- (in case Paul changes his mind and flips geometry_columns to return old upper case name) 
+        EXECUTE 'ALTER TABLE ' || quote_ident(real_schema) || '.' || quote_ident(table_name) || 
+        ' ALTER COLUMN ' || quote_ident(column_name) || ' TYPE  geometry(' || postgis_type_name(myrec.type, myrec.coord_dimension, true) || ', ' || new_srid::text || ') USING ST_SetSRID(' || quote_ident(column_name) || ',' || new_srid::text || ');' ;
+    END IF;
+
+       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;
+
+-- PostGIS equivalent of old 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_svn_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;
+       svnver text;
+       projver text;
+       geosver text;
+       gdalver 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;
+       BEGIN
+               SELECT postgis_gdal_version() INTO gdalver;
+       EXCEPTION
+               WHEN undefined_function THEN
+                       gdalver := NULL;
+                       RAISE NOTICE 'Function postgis_gdal_version() not found.  Is raster support enabled and rtpostgis.sql installed?';
+       END;
+       SELECT postgis_libxml_version() INTO libxmlver;
+       SELECT postgis_uses_stats() INTO usestats;
+       SELECT postgis_scripts_installed() INTO dbproc;
+       SELECT postgis_scripts_released() INTO relproc;
+       select postgis_svn_version() INTO svnver;
+
+       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  gdalver IS NOT NULL THEN
+               fullver = fullver || ' GDAL="' || gdalver || '"';
+       END IF;
+
+       IF  libxmlver IS NOT NULL THEN
+               fullver = fullver || ' LIBXML="' || libxmlver || '"';
+       END IF;
+
+       IF  svnver IS NOT NULL THEN
+               fullver = fullver || ' SVN_REVISION=' || svnver;
+       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_BOX2D'
+       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_BOX2D'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION box3d(box2d)
+       RETURNS box3d
+       AS 'MODULE_PATHNAME','BOX2D_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','BOX2D_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;
+
+
+---------------------------------------------------------------
+-- Algorithms
+---------------------------------------------------------------
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_Simplify(geometry, float8)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_simplify2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- ST_SnapToGrid(input, xoff, yoff, xsize, ysize)
+-- 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;
+
+-- ST_SnapToGrid(input, xsize, ysize) # offsets=0
+-- 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION ST_Intersection(geom1 geometry, geom2 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;
+
+-- Availability: 2.0.0 - requires GEOS-3.2 or higher
+CREATE OR REPLACE FUNCTION ST_OffsetCurve(line geometry, distance float8, params text DEFAULT '')
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','ST_OffsetCurve'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- 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(geom1 geometry, geom2 geometry)
+       RETURNS integer
+       AS 'MODULE_PATHNAME', 'ST_LineCrossingDirection'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 1.4.0
+CREATE OR REPLACE FUNCTION ST_LineCrossingDirection(geom1 geometry, geom2 geometry)
+       RETURNS integer AS
+       $$ SELECT CASE WHEN NOT $1 && $2 THEN 0 ELSE _ST_LineCrossingDirection($1,$2) END $$
+       LANGUAGE 'sql' IMMUTABLE;
+
+-- 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;
+
+-- 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;
+
+-- 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;
+
+
+-- Requires GEOS >= 3.2.0
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geom1 geometry, geom2 geometry)
+       RETURNS FLOAT8
+       AS 'MODULE_PATHNAME', 'hausdorffdistance'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Requires GEOS >= 3.2.0
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_HausdorffDistance(geom1 geometry, geom2 geometry, float8)
+       RETURNS FLOAT8
+       AS 'MODULE_PATHNAME', 'hausdorffdistancedensify'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- PostGIS equivalent function: difference(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION ST_Difference(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION ST_SymDifference(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','symdifference'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_symmetricdifference(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','symdifference'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- PostGIS equivalent function: GeomUnion(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION ST_Union(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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;
+
+--------------------------------------------------------------------------------
+-- ST_Node
+--------------------------------------------------------------------------------
+
+-- ST_Node(in geometry)
+--
+-- Fully node lines in input using the least set of nodes while
+-- preserving each of the input ones.
+-- Returns a linestring or a multilinestring containing all parts.
+--
+-- Availability: 2.0.0
+-- Requires GEOS >= 3.3.0
+--
+CREATE OR REPLACE FUNCTION ST_Node(g geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_Node'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+
+--------------------------------------------------------------------------------
+-- Aggregates and their supporting functions
+--------------------------------------------------------------------------------
+
+------------------------------------------------------------------------
+-- 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_Extent(
+       sfunc = ST_combine_bbox,
+       finalfunc = box2d,
+       basetype = geometry,
+       stype = box3d
+       );
+
+-- Availability: 2.0.0
+CREATE AGGREGATE ST_3DExtent(
+       sfunc = ST_combine_bbox,
+       basetype = geometry,
+       stype = box3d
+       );
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_Collect(geom1 geometry, geom2 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';
+
+-- 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
+       );
+
+-- Availability: 1.2.2
+CREATE AGGREGATE ST_Collect (
+       BASETYPE = geometry,
+       SFUNC = pgis_geometry_accum_transfn,
+       STYPE = pgis_abs,
+       FINALFUNC = pgis_geometry_collect_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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry, int4)
+       RETURNS text
+       AS 'MODULE_PATHNAME','relate_full'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- PostGIS equivalent function: relate(geom1 geometry, geom2 geometry,text)
+CREATE OR REPLACE FUNCTION ST_Relate(geom1 geometry, geom2 geometry,text)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME','relate_pattern'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- PostGIS equivalent function: disjoint(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION ST_Disjoint(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME','disjoint'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- PostGIS equivalent function: touches(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION _ST_Touches(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION _ST_Intersects(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT $1 && $2 AND _ST_Intersects($1,$2)'
+       LANGUAGE 'SQL' IMMUTABLE;
+       
+-- PostGIS equivalent function: crosses(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION _ST_Crosses(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT $1 && $2 AND _ST_Crosses($1,$2)'
+       LANGUAGE 'SQL' IMMUTABLE;
+
+-- PostGIS equivalent function: contains(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION _ST_Contains(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'coveredby'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_CoveredBy(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT $1 && $2 AND _ST_ContainsProperly($1,$2)'
+       LANGUAGE 'SQL' IMMUTABLE;
+
+-- PostGIS equivalent function: overlaps(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION _ST_Overlaps(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME','overlaps'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- PostGIS equivalent function: within(geom1 geometry, geom2 geometry)
+CREATE OR REPLACE FUNCTION _ST_Within(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT _ST_Contains($2,$1)'
+       LANGUAGE 'SQL' IMMUTABLE;
+
+-- Availability: 1.2.2
+-- Inlines index magic
+CREATE OR REPLACE FUNCTION ST_Within(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT $1 && $2 AND _ST_Contains($2,$1)'
+       LANGUAGE 'SQL' IMMUTABLE;
+
+-- Availability: 1.2.2
+-- Inlines index magic
+CREATE OR REPLACE FUNCTION ST_Overlaps(geom1 geometry, geom2 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;
+
+-- 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;
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION _ST_Equals(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME','ST_Equals'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 1.2.1
+CREATE OR REPLACE FUNCTION ST_Equals(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT $1 ~= $2 AND _ST_Equals($1,$2)'
+       LANGUAGE 'SQL' IMMUTABLE;
+
+-- Deprecation in 1.2.3 
+-- TODO: drop in 2.0.0 ! 
+CREATE OR REPLACE FUNCTION Equals(geom1 geometry, geom2 geometry) 
+       RETURNS boolean 
+       AS 'MODULE_PATHNAME','ST_Equals' 
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-----------------------------------------------------------------------
+-- GML & KML INPUT
+-----------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION _ST_GeomFromGML(text, int4)
+        RETURNS geometry
+        AS 'MODULE_PATHNAME','geom_from_gml'
+        LANGUAGE 'C' IMMUTABLE;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_GeomFromGML(text, int4)
+        RETURNS geometry
+        AS 'MODULE_PATHNAME','geom_from_gml'
+        LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_GeomFromGML(text)
+        RETURNS geometry
+        AS 'SELECT _ST_GeomFromGML($1, 0)'
+        LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_GMLToSQL(text)
+        RETURNS geometry
+        AS 'SELECT _ST_GeomFromGML($1, 0)'
+        LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_GMLToSQL(text, int4)
+        RETURNS geometry
+        AS 'MODULE_PATHNAME','geom_from_gml'
+        LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_GeomFromKML(text)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','geom_from_kml'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-----------------------------------------------------------------------
+-- GEOJSON INPUT
+-----------------------------------------------------------------------
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_GeomFromGeoJson(text)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','geom_from_geojson'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-----------------------------------------------------------------------
+-- SVG OUTPUT
+-----------------------------------------------------------------------
+-- Availability: 1.2.2
+-- Changed: 2.0.0 changed to use default args and allow calling by named args
+CREATE OR REPLACE FUNCTION ST_AsSVG(geom geometry,rel int4 DEFAULT 0,maxdecimaldigits int4 DEFAULT 15)
+       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(version, geom) / precision=15 
+-- Availability: 1.3.2
+-- ST_AsGML(version, geom, precision)
+-- Availability: 1.3.2
+
+-- ST_AsGML (geom, precision, option) / version=2
+-- Availability: 1.4.0
+-- Changed: 2.0.0 to have default args
+CREATE OR REPLACE FUNCTION ST_AsGML(geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0)
+       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
+-- ST_AsGML(version, geom, precision, option, prefix)
+-- Availability: 2.0.0
+-- Changed: 2.0.0 to use default and named args
+CREATE OR REPLACE FUNCTION ST_AsGML(version int4, geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0, nprefix text DEFAULT null)
+       RETURNS TEXT
+       AS $$ SELECT _ST_AsGML($1, $2, $3, $4,$5); $$
+       LANGUAGE 'SQL' IMMUTABLE;
+
+-----------------------------------------------------------------------
+-- KML OUTPUT
+-----------------------------------------------------------------------
+-- _ST_AsKML(version, geom, precision, nprefix)
+CREATE OR REPLACE FUNCTION _ST_AsKML(int4,geometry, int4, text)
+       RETURNS TEXT
+       AS 'MODULE_PATHNAME','LWGEOM_asKML'
+       LANGUAGE 'C' IMMUTABLE;
+
+-- Availability: 1.2.2
+-- Changed: 2.0.0 to use default args and allow named args
+CREATE OR REPLACE FUNCTION ST_AsKML(geom geometry, maxdecimaldigits int4 DEFAULT 15)
+       RETURNS TEXT
+       AS $$ SELECT _ST_AsKML(2, ST_Transform($1,4326), $2, null); $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+-- ST_AsKML(version, geom, precision, text)
+-- Availability: 2.0.0
+-- Changed: 2.0.0 allows default args and got rid of other permutations
+CREATE OR REPLACE FUNCTION ST_AsKML(version int4, geom geometry, maxdecimaldigits int4 DEFAULT 15, nprefix text DEFAULT null)
+       RETURNS TEXT
+       AS $$ SELECT _ST_AsKML($1, ST_Transform($2,4326), $3, $4); $$
+       LANGUAGE 'SQL' IMMUTABLE;
+
+
+-----------------------------------------------------------------------
+-- 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, options) / version=1
+-- Changed 2.0.0 to use default args and named args
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0)
+       RETURNS TEXT
+       AS $$ SELECT _ST_AsGeoJson(1, $1, $2, $3); $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+-- ST_AsGeoJson(version, geom, precision,options)
+-- Changed 2.0.0 to use default args and named args
+CREATE OR REPLACE FUNCTION ST_AsGeoJson(gj_version int4, geom geometry, maxdecimaldigits int4 DEFAULT 15, options int4 DEFAULT 0)
+       RETURNS TEXT
+       AS $$ SELECT _ST_AsGeoJson($1, $2, $3, $4); $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT;
+
+------------------------------------------------------------------------
+-- GeoHash (geohash.org)
+------------------------------------------------------------------------
+
+-- Availability 1.4.0
+-- Changed 2.0.0 to use default args and named args
+CREATE OR REPLACE FUNCTION ST_GeoHash(geom geometry, maxchars int4 DEFAULT 0)
+       RETURNS TEXT
+               AS 'MODULE_PATHNAME', 'ST_GeoHash'
+       LANGUAGE 'C' 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 of old StartPoint(geometry))
+CREATE OR REPLACE FUNCTION ST_StartPoint(geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_startpoint_linestring'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- PostGIS equivalent function of old 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;
+
+CREATE OR REPLACE FUNCTION ST_SRID(geometry)
+       RETURNS int4
+       AS 'MODULE_PATHNAME','LWGEOM_get_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;
+       
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_AsBinary(geometry,text)
+       RETURNS bytea
+       AS 'MODULE_PATHNAME','LWGEOM_asBinary'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+       
+-- PostGIS equivalent of old function: AsBinary(geometry)
+CREATE OR REPLACE FUNCTION ST_AsBinary(geometry)
+       RETURNS bytea
+       AS 'MODULE_PATHNAME','LWGEOM_asBinary'
+       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;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_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, int4)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','LWGEOM_from_text'
+       LANGUAGE 'C' 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;
+
+-- 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;
+       
+-- PostGIS equivalent function: ST_GeometryFromText(text)
+-- SQL/MM alias for ST_GeomFromText
+CREATE OR REPLACE FUNCTION ST_WKTToSQL(text)
+       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(ST_GeomFromText($1, $2)) = ''LINESTRING''
+       THEN ST_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 ST_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 ST_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;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_GeomFromWKB(bytea)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'
+       LANGUAGE 'C' 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(ST_GeomFromWKB($1)) = ''LINESTRING''
+       THEN ST_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 ST_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 ST_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(ST_GeomFromWKB($1, $2)) = ''GEOMETRYCOLLECTION''
+       THEN ST_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(geom1 geometry, geom2 geometry)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance2d_linestring'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+       
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION ST_MaxDistance(geom1 geometry, geom2 geometry)
+       RETURNS float8
+       AS 'SELECT _ST_MaxDistance(ST_ConvexHull($1), ST_ConvexHull($2))'
+       LANGUAGE 'SQL' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION ST_ClosestPoint(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION ST_ShortestLine(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION _ST_LongestLine(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_longestline2d'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION ST_LongestLine(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'SELECT _ST_LongestLine(ST_ConvexHull($1), ST_ConvexHull($2))'
+       LANGUAGE 'SQL' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION _ST_DFullyWithin(geom1 geometry, geom2 geometry,float8)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+
+CREATE OR REPLACE FUNCTION ST_DFullyWithin(geom1 geometry, geom2 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 "geography.sql.in.c"
+
+
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_distance_sphere(geom1 geometry, geom2 geometry)
+       RETURNS FLOAT8
+       AS $$
+       select st_distance(geography($1),geography($2),false)
+       $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT
+       COST 300;
+
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_distance_sphere(geom1 geometry, geom2 geometry)
+       RETURNS FLOAT8
+       AS $$
+       select st_distance(geography($1),geography($2),false)
+       $$
+       LANGUAGE 'SQL' IMMUTABLE STRICT
+       COST 300;
+
+
+---------------------------------------------------------------
+-- GEOMETRY_COLUMNS view support functions
+---------------------------------------------------------------
+-- New helper function so we can keep list of valid geometry types in one place --
+-- Maps old names to pramsey beautiful names but can take old name or new name as input
+-- By default returns new name but can be overridden to return old name for old constraint like support
+CREATE OR REPLACE FUNCTION postgis_type_name(geomname varchar, coord_dimension integer, use_new_name boolean DEFAULT true) 
+       RETURNS varchar
+AS
+$$
+ SELECT CASE WHEN $3 THEN new_name ELSE old_name END As geomname
+       FROM 
+       ( VALUES
+                ('GEOMETRY', 'Geometry', 2) ,
+                       ('GEOMETRY', 'GeometryZ', 3) ,
+                       ('GEOMETRY', 'GeometryZM', 4) ,
+                       ('GEOMETRYCOLLECTION', 'GeometryCollection', 2) ,
+                       ('GEOMETRYCOLLECTION', 'GeometryCollectionZ', 3) ,
+                       ('GEOMETRYCOLLECTIONM', 'GeometryCollectionM', 3) ,
+                       ('GEOMETRYCOLLECTION', 'GeometryCollectionZM', 4) ,
+                       
+                       ('POINT', 'Point',2) ,
+                       ('POINTM','PointM',3) ,
+                       ('POINT', 'PointZ',3) ,
+                       ('POINT', 'PointZM',4) ,
+                       
+                       ('MULTIPOINT','MultiPoint',2) ,
+                       ('MULTIPOINT','MultiPointZ',3) ,
+                       ('MULTIPOINTM','MultiPointM',3) ,
+                       ('MULTIPOINT','MultiPointZM',4) ,
+                       
+                       ('POLYGON', 'Polygon',2) ,
+                       ('POLYGON', 'PolygonZ',3) ,
+                       ('POLYGONM', 'PolygonM',3) ,
+                       ('POLYGON', 'PolygonZM',4) ,
+                       
+                       ('MULTIPOLYGON', 'MultiPolygon',2) ,
+                       ('MULTIPOLYGON', 'MultiPolygonZ',3) ,
+                       ('MULTIPOLYGONM', 'MultiPolygonM',3) ,
+                       ('MULTIPOLYGON', 'MultiPolygonZM',4) ,
+                       
+                       ('MULTILINESTRING', 'MultiLineString',2) ,
+                       ('MULTILINESTRING', 'MultiLineStringZ',3) ,
+                       ('MULTILINESTRINGM', 'MultiLineStringM',3) ,
+                       ('MULTILINESTRING', 'MultiLineStringZM',4) ,
+                       
+                       ('LINESTRING', 'LineString',2) ,
+                       ('LINESTRING', 'LineStringZ',3) ,
+                       ('LINESTRINGM', 'LineStringM',3) ,
+                       ('LINESTRING', 'LineStringZM',4) ,
+                       
+                       ('CIRCULARSTRING', 'CircularString',2) ,
+                       ('CIRCULARSTRING', 'CircularStringZ',3) ,
+                       ('CIRCULARSTRINGM', 'CircularStringM',3) ,
+                       ('CIRCULARSTRING', 'CircularStringZM',4) ,
+                       
+                       ('COMPOUNDCURVE', 'CompoundCurve',2) ,
+                       ('COMPOUNDCURVE', 'CompoundCurveZ',3) ,
+                       ('COMPOUNDCURVEM', 'CompoundCurveM',3) ,
+                       ('COMPOUNDCURVE', 'CompoundCurveZM',4) ,
+                       
+                       ('CURVEPOLYGON', 'CurvePolygon',2) ,
+                       ('CURVEPOLYGON', 'CurvePolygonZ',3) ,
+                       ('CURVEPOLYGONM', 'CurvePolygonM',3) ,
+                       ('CURVEPOLYGON', 'CurvePolygonZM',4) ,
+                       
+                       ('MULTICURVE', 'MultiCurve',2 ) ,
+                       ('MULTICURVE', 'MultiCurveZ',3 ) ,
+                       ('MULTICURVEM', 'MultiCurveM',3 ) ,
+                       ('MULTICURVE', 'MultiCurveZM',4 ) ,
+                       
+                       ('MULTISURFACE', 'MultiSurface', 2) ,
+                       ('MULTISURFACE', 'MultiSurfaceZ', 3) ,
+                       ('MULTISURFACEM', 'MultiSurfaceM', 3) ,
+                       ('MULTISURFACE', 'MultiSurfaceZM', 4) ,
+                       
+                       ('POLYHEDRALSURFACE', 'PolyhedralSurface',2) ,
+                       ('POLYHEDRALSURFACE', 'PolyhedralSurfaceZ',3) ,
+                       ('POLYHEDRALSURFACEM', 'PolyhedralSurfaceM',3) ,
+                       ('POLYHEDRALSURFACE', 'PolyhedralSurfaceZM',4) ,
+                       
+                       ('TRIANGLE', 'Triangle',2) ,
+                       ('TRIANGLE', 'TriangleZ',3) ,
+                       ('TRIANGLEM', 'TriangleM',3) ,
+                       ('TRIANGLE', 'TriangleZM',4) ,
+
+                       ('TIN', 'Tin', 2),
+                       ('TIN', 'TinZ', 3),
+                       ('TIN', 'TinM', 3),
+                       ('TIN', 'TinZM', 4) )
+                        As g(old_name, new_name, coord_dimension)
+               WHERE (upper(old_name) = upper($1) OR upper(new_name) = upper($1))
+                       AND coord_dimension = $2;
+$$
+language 'sql' IMMUTABLE STRICT COST 200;
+
+CREATE OR REPLACE FUNCTION postgis_constraint_srid(geomschema text, geomtable text, geomcolumn text) RETURNS integer AS
+$$
+SELECT replace(replace(split_part(s.consrc, ' = ', 2), ')', ''), '(', '')::integer
+                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s
+                WHERE n.nspname = $1
+                AND c.relname = $2
+                AND a.attname = $3
+                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(% = %';
+$$
+LANGUAGE 'sql' STABLE STRICT;
+
+CREATE OR REPLACE FUNCTION postgis_constraint_dims(geomschema text, geomtable text, geomcolumn text) RETURNS integer AS
+$$
+SELECT  replace(split_part(s.consrc, ' = ', 2), ')', '')::integer
+                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s
+                WHERE n.nspname = $1
+                AND c.relname = $2
+                AND a.attname = $3
+                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(% = %';
+$$
+LANGUAGE 'sql' STABLE STRICT;
+
+-- support function to pull out geometry type from constraint check
+-- will return pretty name instead of ugly name
+CREATE OR REPLACE FUNCTION postgis_constraint_type(geomschema text, geomtable text, geomcolumn text) RETURNS varchar AS
+$$
+SELECT  replace(split_part(s.consrc, '''', 2), ')', '')::varchar               
+                FROM pg_class c, pg_namespace n, pg_attribute a, pg_constraint s
+                WHERE n.nspname = $1
+                AND c.relname = $2
+                AND a.attname = $3
+                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(% = %';
+$$
+LANGUAGE 'sql' STABLE STRICT;
+
+CREATE OR REPLACE VIEW geometry_columns AS 
+  SELECT current_database()::varchar(256) AS f_table_catalog, 
+    n.nspname::varchar(256) AS f_table_schema, 
+    c.relname::varchar(256) AS f_table_name, 
+    a.attname::varchar(256) AS f_geometry_column, 
+    COALESCE(NULLIF(postgis_typmod_dims(a.atttypmod),2),
+             postgis_constraint_dims(n.nspname, c.relname, a.attname),
+             2) AS coord_dimension, 
+    COALESCE(NULLIF(postgis_typmod_srid(a.atttypmod),0),
+             postgis_constraint_srid(n.nspname, c.relname, a.attname),
+             0) AS srid, 
+    -- force to be uppercase with no ZM so is backwards compatible
+    -- with old geometry_columns
+    replace(
+      replace(
+        COALESCE(
+          NULLIF(upper(postgis_typmod_type(a.atttypmod)::text), 'GEOMETRY'),
+          postgis_constraint_type(n.nspname, c.relname, a.attname),
+          'GEOMETRY'
+        ), 'ZM', ''
+      ), 'Z', ''
+    )::varchar(30) AS type
+  FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
+  WHERE t.typname = 'geometry'::name 
+    AND a.attisdropped = false 
+    AND a.atttypid = t.oid 
+    AND a.attrelid = c.oid 
+    AND c.relnamespace = n.oid 
+    AND (c.relkind = 'r'::"char" OR c.relkind = 'v'::"char")
+    AND NOT pg_is_other_temp_schema(c.relnamespace)
+    AND NOT ( n.nspname = 'public' AND c.relname = 'raster_columns' );
+
+-- TODO: support RETURNING and raise a WARNING
+CREATE OR REPLACE RULE geometry_columns_insert AS
+        ON INSERT TO geometry_columns
+        DO INSTEAD NOTHING;
+
+-- TODO: raise a WARNING
+CREATE OR REPLACE RULE geometry_columns_update AS
+        ON UPDATE TO geometry_columns
+        DO INSTEAD NOTHING;
+
+-- TODO: raise a WARNING
+CREATE OR REPLACE RULE geometry_columns_delete AS
+        ON DELETE TO geometry_columns
+        DO INSTEAD NOTHING;
+
+
+---------------------------------------------------------------
+-- 3D-functions
+---------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION ST_3DDistance(geom1 geometry, geom2 geometry)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'LWGEOM_mindistance3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+       
+CREATE OR REPLACE FUNCTION ST_3DMaxDistance(geom1 geometry, geom2 geometry)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'LWGEOM_maxdistance3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;       
+
+CREATE OR REPLACE FUNCTION ST_3DClosestPoint(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_closestpoint3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+CREATE OR REPLACE FUNCTION ST_3DShortestLine(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_shortestline3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+CREATE OR REPLACE FUNCTION ST_3DLongestLine(geom1 geometry, geom2 geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_longestline3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+       
+CREATE OR REPLACE FUNCTION _ST_3DDWithin(geom1 geometry, geom2 geometry,float8)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'LWGEOM_dwithin3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+       
+CREATE OR REPLACE FUNCTION ST_3DDWithin(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry,float8)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'LWGEOM_dfullywithin3d'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+       
+CREATE OR REPLACE FUNCTION ST_3DDFullyWithin(geom1 geometry, geom2 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(geom1 geometry, geom2 geometry)
+       RETURNS boolean
+       AS 'SELECT $1 && $2 AND _ST_3DDWithin($1, $2, 0.0)'
+       LANGUAGE 'SQL' IMMUTABLE
+       COST 100;
+       
+       
+---------------------------------------------------------------
+-- SQL-MM
+---------------------------------------------------------------
+-- PostGIS equivalent function: ST_ndims(geometry)
+CREATE OR REPLACE FUNCTION ST_CoordDim(Geometry geometry)
+       RETURNS smallint
+       AS 'MODULE_PATHNAME', 'LWGEOM_ndims'
+       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 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 geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'LWGEOM_has_arc'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION ST_LineToCurve(Geometry geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_line_desegmentize'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+       
+-- Availability: 1.5.0
+CREATE OR REPLACE FUNCTION _ST_OrderingEquals(GeometryA geometry, GeometryB geometry)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'LWGEOM_same'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
+-- Availability: 1.3.0
+CREATE OR REPLACE FUNCTION ST_OrderingEquals(GeometryA geometry, GeometryB geometry)
+       RETURNS boolean
+       AS $$ 
+       SELECT $1 ~= $2 AND _ST_OrderingEquals($1, $2)
+       $$      
+       LANGUAGE 'SQL' IMMUTABLE STRICT; 
+       
+-------------------------------------------------------------------------------
+-- SQL/MM - SQL Functions on type ST_Point
+-------------------------------------------------------------------------------
+
+-- PostGIS equivalent function: ST_MakePoint(XCoordinate float8,YCoordinate float8)
+CREATE OR REPLACE FUNCTION ST_Point(float8, float8)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+       
+-- PostGIS equivalent function: ST_MakePolygon(Geometry geometry)
+CREATE OR REPLACE FUNCTION ST_Polygon(geometry, int)
+       RETURNS geometry
+       AS $$ 
+       SELECT ST_SetSRID(ST_MakePolygon($1), $2)
+       $$      
+       LANGUAGE 'SQL' IMMUTABLE STRICT; 
+       
+-- PostGIS equivalent function: GeomFromWKB(WKB bytea))
+-- Note: Defaults to an SRID=-1, not 0 as per SQL/MM specs.
+CREATE OR REPLACE FUNCTION ST_WKBToSQL(WKB bytea)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','LWGEOM_from_WKB'
+       LANGUAGE 'C' IMMUTABLE STRICT; 
+       
+---
+-- Linear referencing functions
+---
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, FromMeasure float8, ToMeasure float8, LeftRightOffset float8 default 0.0)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_LocateBetween'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+       
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, LeftRightOffset float8 default 0.0)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_LocateAlong'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Only accepts LINESTRING as parameters.
+-- Availability: 1.4.0
+CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(Geometry geometry, FromElevation float8, ToElevation float8)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_InterpolatePoint(Line geometry, Point geometry)
+       RETURNS float8
+       AS 'MODULE_PATHNAME', 'ST_InterpolatePoint'
+       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 DEFAULT 48)
+       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 ST_MakeLine(ST_PointN(ring,idx1),ST_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_Rotate(l1,pi()/2,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(ST_X(ST_PointN(l1,2))+sin(a1)*dist,ST_Y(ST_PointN(l1,2))+cos(a1)*dist),-1);
+                               l1 = ST_AddPoint(l1,ST_Makepoint(ST_X(ST_PointN(l1,1))-sin(a1)*dist,ST_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_Rotate(l2,pi()/2,p2);
+                               a2 = ST_Azimuth(ST_PointN(l2,1),ST_PointN(l2,2));
+                               l2 = ST_AddPoint(l2,ST_Makepoint(ST_X(ST_PointN(l2,2))+sin(a2)*dist,ST_Y(ST_PointN(l2,2))+cos(a2)*dist),-1);
+                               l2 = ST_AddPoint(l2,ST_Makepoint(ST_X(ST_PointN(l2,1))-sin(a2)*dist,ST_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;
+
+-- 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;
+       var_inputgeom geometry;
+       vexring GEOMETRY;
+       cavering GEOMETRY;
+       cavept geometry[];
+       seglength double precision;
+       var_tempgeom geometry;
+       scale_factor integer := 1;
+       i integer;
+       
+       BEGIN
+
+               -- First compute the ConvexHull of the geometry
+               vexhull := ST_ConvexHull(param_inputgeom);
+               var_inputgeom := 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;
+               IF abs(ST_X(ST_PointN(vexring,1))) < 1 THEN --scale the geometry to prevent stupid precision errors - not sure it works so make low for now
+                       scale_factor := 100;
+                       vexring := ST_Scale(vexring, scale_factor,scale_factor);
+                       var_inputgeom := ST_Scale(var_inputgeom, scale_factor, scale_factor);
+                       --RAISE NOTICE 'Scaling';
+               END IF;
+               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(var_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_MakeLine(geom) 
+                       FROM ST_Dump(cavering) As foo;
+
+               IF ST_IsSimple(var_resultgeom) THEN
+                       var_resultgeom := ST_MakePolygon(var_resultgeom);
+                       --RAISE NOTICE 'is Simple: %', var_resultgeom;
+               ELSE /** will not result in a valid polygon -- just return convex hull **/
+                       --RAISE NOTICE 'is not Simple: %', var_resultgeom;
+                       var_resultgeom := ST_ConvexHull(var_resultgeom);
+               END IF;
+               
+               IF scale_factor > 1 THEN -- scale the result back
+                       var_resultgeom := ST_Scale(var_resultgeom, 1/scale_factor, 1/scale_factor);
+               END IF;
+               RETURN var_resultgeom;
+       
+       END;
+$$
+  LANGUAGE plpgsql IMMUTABLE STRICT;
+  
+CREATE OR REPLACE FUNCTION ST_ConcaveHull(param_geom geometry, param_pctconvex float, param_allow_holes boolean DEFAULT false) 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;
+-- ST_ConcaveHull and Helper functions end here --
+
+-----------------------------------------------------------------------
+-- X3D OUTPUT
+-----------------------------------------------------------------------
+-- _ST_AsX3D(version, geom, precision, option, attribs)
+CREATE OR REPLACE FUNCTION _ST_AsX3D(int4, geometry, int4, int4, text)
+       RETURNS TEXT
+       AS 'MODULE_PATHNAME','LWGEOM_asX3D'
+       LANGUAGE 'C' IMMUTABLE;
+       
+-- ST_AsX3D(geom, precision, options)
+CREATE OR REPLACE FUNCTION ST_AsX3D(geom geometry, maxdecimaldigits integer DEFAULT 15, options integer DEFAULT 0)
+       RETURNS TEXT
+       AS $$SELECT _ST_AsX3D(3,$1,$2,$3,'');$$
+       LANGUAGE 'sql' IMMUTABLE;
+
+COMMIT;
+
+#include "postgis_drop.sql.in.c"