~ubuntu-branches/ubuntu/feisty/postgis/feisty

« back to all changes in this revision

Viewing changes to doc/postgis.xml

  • Committer: Bazaar Package Importer
  • Author(s): Alex Bodnaru
  • Date: 2005-05-05 10:02:45 UTC
  • Revision ID: james.westby@ubuntu.com-20050505100245-3005l6jn1jwvpsrw
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="UTF-8"?>
 
2
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
 
3
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
4
<book>
 
5
  <title>PostGIS Manual</title>
 
6
 
 
7
  <bookinfo>
 
8
    <editor>
 
9
      <firstname>Paul</firstname>
 
10
 
 
11
      <surname>Ramsey</surname>
 
12
 
 
13
      <affiliation>
 
14
        <orgname><ulink url="http://www.refractions.net">Refractions Research
 
15
        Inc</ulink></orgname>
 
16
 
 
17
        <address>
 
18
     <street>Suite 400, 1207 Douglas Street</street>
 
19
     <city>Victoria</city>
 
20
     <state>British Columbia</state>
 
21
     <country>Canada</country>
 
22
     <email>pramsey@refractions.net</email>
 
23
    </address>
 
24
      </affiliation>
 
25
    </editor>
 
26
 
 
27
    <abstract>
 
28
      <para>PostGIS is an extension to the PostgreSQL object-relational
 
29
      database system which allows GIS (Geographic Information Systems)
 
30
      objects to be stored in the database. PostGIS includes support for
 
31
      GiST-based R-Tree spatial indexes, and functions for analysis and
 
32
      processing of GIS objects.</para>
 
33
    </abstract>
 
34
  </bookinfo>
 
35
 
 
36
  <chapter>
 
37
    <title>Introduction</title>
 
38
 
 
39
    <para>PostGIS is developed by Refractions Research Inc, as a spatial
 
40
    database technology research project. Refractions is a GIS and database
 
41
    consulting company in Victoria, British Columbia, Canada, specializing in
 
42
    data integration and custom software development. We plan on supporting
 
43
    and developing PostGIS to support a range of important GIS functionality,
 
44
    including full OpenGIS support, advanced topological constructs
 
45
    (coverages, surfaces, networks), desktop user interface tools for viewing
 
46
    and editing GIS data, and web-based access tools.</para>
 
47
 
 
48
    <sect1>
 
49
      <title>Credits</title>
 
50
 
 
51
      <variablelist>
 
52
        <varlistentry>
 
53
          <term>Sandro Santilli &lt;strk@refractions.net&gt;</term>
 
54
 
 
55
          <listitem>
 
56
            <para>Coordinates all bug fixing and maintainance effort,
 
57
            integration of new GEOS functionality, and new function
 
58
            enhancements.</para>
 
59
          </listitem>
 
60
        </varlistentry>
 
61
 
 
62
        <varlistentry>
 
63
          <term>Chris Hodgson &lt;chodgson@refractions.net&gt;</term>
 
64
 
 
65
          <listitem>
 
66
            <para>Maintains new functions and the 7.2 index bindings.</para>
 
67
          </listitem>
 
68
        </varlistentry>
 
69
 
 
70
        <varlistentry>
 
71
          <term>Paul Ramsey &lt;pramsey@refractions.net&gt;</term>
 
72
 
 
73
          <listitem>
 
74
            <para>Maintains the JDBC objects and keeps track of the
 
75
            documentation and packaging.</para>
 
76
          </listitem>
 
77
        </varlistentry>
 
78
 
 
79
        <varlistentry>
 
80
          <term>Jeff Lounsbury &lt;jeffloun@refractions.net&gt;</term>
 
81
 
 
82
          <listitem>
 
83
            <para>Original development of the Shape file loader/dumper.</para>
 
84
          </listitem>
 
85
        </varlistentry>
 
86
 
 
87
        <varlistentry>
 
88
          <term>Dave Blasby &lt;dblasby@gmail.com&gt;</term>
 
89
 
 
90
          <listitem>
 
91
            <para>The original developer of PostGIS. Dave wrote the server
 
92
            side objects, index bindings, and many of the server side
 
93
            analytical functions.</para>
 
94
          </listitem>
 
95
        </varlistentry>
 
96
 
 
97
        <varlistentry>
 
98
          <term>Other contributors</term>
 
99
 
 
100
          <listitem>
 
101
            <para>
 
102
                In alphabetical order: 
 
103
                Alex Bodnaru, Bernhard Reiter, Bruno Wolff III,
 
104
                Carl Anderson, David Skea, David Techer, 
 
105
                IIDA Tetsushi, Geographic Data BC, Gerald Fenoy,
 
106
                Gino Lucrezi, Klaus Foerster, Kris Jurka, Mark Cave-Ayland,
 
107
                Mark Sondheim, Markus Schaber, Norman Vine, 
 
108
                Olivier Courtin, Ralph Mason,
 
109
                Steffen Macke.
 
110
            </para>
 
111
          </listitem>
 
112
        </varlistentry>
 
113
      </variablelist>
 
114
    </sect1>
 
115
 
 
116
    <sect1>
 
117
      <title>More Information</title>
 
118
 
 
119
      <itemizedlist>
 
120
        <listitem>
 
121
          <para>The latest software, documentation and news items are
 
122
          available at the PostGIS web site, <ulink
 
123
          url="http://postgis.refractions.net">http://postgis.refractions.net</ulink>.</para>
 
124
        </listitem>
 
125
 
 
126
        <listitem>
 
127
          <para>More information about the GEOS geometry operations library is
 
128
          available at<ulink url="http://geos.refractions.net">
 
129
          http://geos.refractions.net</ulink>.</para>
 
130
        </listitem>
 
131
 
 
132
        <listitem>
 
133
          <para>More information about the Proj4 reprojection library is
 
134
          available at <ulink
 
135
          url="http://www.remotesensing.org/proj">http://www.remotesensing.org/proj</ulink>.</para>
 
136
        </listitem>
 
137
 
 
138
        <listitem>
 
139
          <para>More information about the PostgreSQL database server is
 
140
          available at the PostgreSQL main site <ulink
 
141
          url="http://www.postgresql.org">http://www.postgresql.org</ulink>.</para>
 
142
        </listitem>
 
143
 
 
144
        <listitem>
 
145
          <para>More information about GiST indexing is available at the
 
146
          PostgreSQL GiST development site, <ulink
 
147
          url="http://www.sai.msu.su/~megera/postgres/gist">http://www.sai.msu.su/~megera/postgres/gist</ulink>.</para>
 
148
        </listitem>
 
149
 
 
150
        <listitem>
 
151
          <para>More information about Mapserver internet map server is
 
152
          available at <ulink
 
153
          url="http://mapserver.gis.umn.edu/">http://mapserver.gis.umn.edu</ulink>.</para>
 
154
        </listitem>
 
155
 
 
156
        <listitem>
 
157
          <para>The "<ulink
 
158
          url="http://www.opengis.org/techno/specs/99-049.pdf">Simple Features
 
159
          for Specification for SQL</ulink>" is available at the OpenGIS
 
160
          Consortium web site: <ulink
 
161
          url="http://www.opengis.org">http://www.opengis.org</ulink>.</para>
 
162
        </listitem>
 
163
      </itemizedlist>
 
164
    </sect1>
 
165
  </chapter>
 
166
 
 
167
  <chapter>
 
168
    <title>Installation</title>
 
169
 
 
170
    <sect1>
 
171
      <title>Requirements</title>
 
172
 
 
173
      <para>PostGIS has the following requirements for building and
 
174
      usage:</para>
 
175
 
 
176
      <itemizedlist>
 
177
        <listitem>
 
178
          <para>A complete configured and built PostgreSQL source code tree.
 
179
          PostGIS uses definitions from the PostgreSQL configure/build process
 
180
          to conform to the particular platform you are building on.
 
181
          PostgreSQL is available from <ulink
 
182
          url="http://www.postgresql.org">http://www.postgresql.org</ulink>.</para>
 
183
        </listitem>
 
184
 
 
185
        <listitem>
 
186
          <para>GNU C compiler (<filename>gcc</filename>). Some other ANSI C
 
187
          compilers can be used to compile PostGIS, but we find far fewer
 
188
          problems when compiling with <filename>gcc</filename>.</para>
 
189
        </listitem>
 
190
 
 
191
        <listitem>
 
192
          <para>GNU Make (<filename>gmake</filename> or
 
193
          <filename>make</filename>). For many systems, GNU
 
194
          <filename>make</filename> is the default version of make. Check the
 
195
          version by invoking <filename>make -v</filename>. Other versions of
 
196
          <filename>make</filename> may not process the PostGIS
 
197
          <filename>Makefile</filename> properly.</para>
 
198
        </listitem>
 
199
 
 
200
        <listitem>
 
201
          <para>(Recommended) Proj4 reprojection library. The Proj4 library is
 
202
          used to provide coordinate reprojection support within PostGIS.
 
203
          Proj4 is available for download from <ulink
 
204
          url="http://www.remotesensing.org/proj">http://www.remotesensing.org/proj</ulink>.</para>
 
205
        </listitem>
 
206
 
 
207
        <listitem>
 
208
          <para>(Recommended) GEOS geometry library. The GEOS library is used
 
209
          to provide geometry tests (Touches(), Contains(), Intersects()) and
 
210
          operations (Buffer(), GeomUnion(), Difference()) within PostGIS.
 
211
          GEOS is available for download from <ulink
 
212
          url="http://geos.refractions.net">http://geos.refractions.net</ulink>.</para>
 
213
        </listitem>
 
214
      </itemizedlist>
 
215
    </sect1>
 
216
 
 
217
    <sect1 id="PGInstall">
 
218
      <title>PostGIS</title>
 
219
 
 
220
      <para>The PostGIS module is a extension to the PostgreSQL backend
 
221
      server. As such, PostGIS @@LAST_RELEASE_VERSION@@
 
222
      <emphasis>requires</emphasis> a full copy of the PostgreSQL source tree
 
223
      in order to compile. The PostgreSQL source code is available at <ulink
 
224
      url="http://www.postgresql.org">http://www.postgresql.org</ulink>.</para>
 
225
 
 
226
      <para>PostGIS @@LAST_RELEASE_VERSION@@ can be built against PostgreSQL
 
227
      versions 7.2.0 to 7.4.x. Earlier versions of PostgreSQL are
 
228
      <emphasis>not</emphasis> supported.</para>
 
229
 
 
230
      <orderedlist>
 
231
        <listitem>
 
232
          <para>Before you can compile the PostGIS server modules, you must
 
233
          compile and install the PostgreSQL package.</para>
 
234
 
 
235
          <note>
 
236
            <para>If you plan to use GEOS functionality you might need to
 
237
            explicitly link PostgreSQL against the standard C++
 
238
            library:</para>
 
239
 
 
240
            <programlisting>LDFLAGS=-lstdc++ ./configure [YOUR OPTIONS HERE]</programlisting>
 
241
 
 
242
            <para>This is a workaround for bogus C++ exceptions interaction
 
243
            with older development tools. If you experience weird problems
 
244
            (backend unexpectedly closed or similar things) try this trick.
 
245
            This will require recompiling your PostgreSQL from scratch, of
 
246
            course.</para>
 
247
          </note>
 
248
        </listitem>
 
249
 
 
250
        <listitem>
 
251
          <para>Retrieve the PostGIS source archive from <ulink
 
252
          url="http://postgis.refractions.net/postgis-@@LAST_RELEASE_VERSION@@.tar.gz">http://postgis.refractions.net/postgis-@@LAST_RELEASE_VERSION@@.tar.gz</ulink>.
 
253
          Uncompress and untar the archive in the "contrib" directory of the
 
254
          PostgreSQL source tree.</para>
 
255
 
 
256
          <programlisting># cd [postgresql source tree]/contrib 
 
257
# gzip -d -c postgis-@@LAST_RELEASE_VERSION@@.tar.gz | tar xvf -</programlisting>
 
258
        </listitem>
 
259
 
 
260
        <listitem>
 
261
          <para>Once your PostgreSQL installation is up-to-date, enter the
 
262
          "postgis" directory, and edit the
 
263
          <filename>Makefile.config</filename> file.</para>
 
264
 
 
265
          <itemizedlist>
 
266
            <listitem>
 
267
              <para>If want support for coordinate reprojection you must have
 
268
              the Proj4 library installed, set the <varname>USE_PROJ</varname>
 
269
              variable to <emphasis>1</emphasis>, and adjust the
 
270
              <varname>PROJ_DIR</varname> variable to point to your Proj4
 
271
              installation directory.</para>
 
272
            </listitem>
 
273
 
 
274
            <listitem>
 
275
              <para>If want to use GEOS functionality you must have the GEOS
 
276
              library installed, set the <varname>USE_GEOS</varname> variable
 
277
              to <emphasis>1</emphasis>, and adjust the
 
278
              <varname>GEOS_DIR</varname> variable to point to your GEOS
 
279
              installation directory.</para>
 
280
            </listitem>
 
281
          </itemizedlist>
 
282
        </listitem>
 
283
 
 
284
        <listitem>
 
285
          <para>Run the compile and install commands.</para>
 
286
 
 
287
          <programlisting># make 
 
288
# make install</programlisting>
 
289
 
 
290
          <para>All files are installed relative to the PostgreSQL install
 
291
          directory, <filename>[prefix]</filename>.</para>
 
292
 
 
293
          <itemizedlist>
 
294
            <listitem>
 
295
              <para>Libraries are installed
 
296
              <filename>[prefix]/lib/contrib</filename>.</para>
 
297
            </listitem>
 
298
 
 
299
            <listitem>
 
300
              <para>Important support files such as
 
301
              <filename>lwpostgis.sql</filename> are installed in
 
302
              <filename>[prefix]/share/contrib</filename>.</para>
 
303
            </listitem>
 
304
 
 
305
            <listitem>
 
306
              <para>Loader and dumber binaries are installed in
 
307
              <filename>[prefix]/bin</filename>.</para>
 
308
            </listitem>
 
309
          </itemizedlist>
 
310
        </listitem>
 
311
 
 
312
        <listitem>
 
313
          <para>PostGIS requires the PL/pgSQL procedural language extension.
 
314
          Before loading the <filename>lwpostgis.sql</filename> file, you must
 
315
          first enable PL/pgSQL. You should use the
 
316
          <filename>createlang</filename> command. The PostgreSQL 
 
317
          Programmer's Guide has the details if you want to this manually for
 
318
          some reason.</para>
 
319
 
 
320
          <programlisting># createlang plpgsql [yourdatabase]</programlisting>
 
321
        </listitem>
 
322
 
 
323
        <listitem>
 
324
          <para>Now load the PostGIS object and function definitions into your
 
325
          database by loading the <filename>lwpostgis.sql</filename> definitions
 
326
          file.</para>
 
327
 
 
328
          <programlisting># psql -d [yourdatabase] -f lwpostgis.sql</programlisting>
 
329
 
 
330
          <para>The PostGIS server extensions are now loaded and ready to
 
331
          use.</para>
 
332
        </listitem>
 
333
 
 
334
        <listitem>
 
335
          <para>For a complete set of EPSG coordinate system definition
 
336
          identifiers, you can also load the
 
337
          <filename>spatial_ref_sys.sql</filename> definitions file and
 
338
          populate the <varname>SPATIAL_REF_SYS</varname> table.</para>
 
339
 
 
340
          <programlisting># psql -d [yourdatabase] -f spatial_ref_sys.sql</programlisting>
 
341
        </listitem>
 
342
      </orderedlist>
 
343
 
 
344
      <sect2 id="upgrading">
 
345
        <title>Upgrading</title>
 
346
 
 
347
        <para>
 
348
Upgrading PostGIS can be tricky, because the underlying C libraries which 
 
349
support the object types and geometries may have changed between versions.
 
350
        </para>
 
351
 
 
352
        <para>
 
353
For this purpose PostGIS provides an utility script to restore a dump
 
354
produced with the pg_dump -Fc command. It is experimental so redirecting
 
355
its output to a file will help in case of problems. The procedure is
 
356
as follow:
 
357
        </para>
 
358
 
 
359
        <programlisting>
 
360
        # Create a "custom-format" dump of the database you want
 
361
        # to upgrade (let's call it "olddb")
 
362
        $ pg_dump -Fc olddb olddb.dump
 
363
 
 
364
        # Restore the dump contextually upgrading postgis into
 
365
        # a new database. The new database doesn't have to exist.
 
366
        # Let's call it "newdb"
 
367
        $ sh utils/postgis_restore.pl lwpostgis.sql newdb olddb.dump &gt; restore.log
 
368
 
 
369
        # Check that all restored dump objects really had to be restored from dump
 
370
        # and do not conflict with the ones defined in lwpostgis.sql
 
371
        $ grep ^KEEPING restore.log | less
 
372
 
 
373
        # If upgrading from PostgreSQL &lt; 7.5 to &gt;= 7.5 you might want to 
 
374
        # drop the attrelid, varattnum and stats columns in the geometry_columns
 
375
        # table, which are no-more needed. Keeping them won't hurt.
 
376
        # !!! DROPPING THEM WHEN REALLY NEEDED WILL DO HURT !!!!
 
377
        $ psql newdb -c "ALTER TABLE geometry_columns DROP attrelid"
 
378
        $ psql newdb -c "ALTER TABLE geometry_columns DROP varattnum"
 
379
        $ psql newdb -c "ALTER TABLE geometry_columns DROP stats"
 
380
 
 
381
        # spatial_ref_sys table is restore from the dump, to ensure your custom
 
382
        # additions are kept, but the distributed one might contain modification
 
383
        # so you should backup your entries, drop the table and source the new one.
 
384
        # If you did make additions we assume you know how to backup them before
 
385
        # upgrading the table. Replace of it with the new one is done like this:
 
386
        $ psql newdb
 
387
        newdb=&gt; drop table spatial_ref_sys;
 
388
        DROP
 
389
        newdb=&gt; \i spatial_ref_sys.sql
 
390
        </programlisting>
 
391
 
 
392
        <para>
 
393
Following is the "old" procedure description. IT SHOULD BE AVOIDED if possible,
 
394
as it will leave in the database many spurious functions. It is kept in this document
 
395
as a "backup" in case postgis_restore.pl won't work for you:
 
396
        </para>
 
397
 
 
398
        <programlisting>
 
399
        pg_dump -t "*" -f dumpfile.sql yourdatabase
 
400
        dropdb yourdatabase
 
401
        createdb yourdatabase
 
402
        createlang plpgsql yourdatabase
 
403
        psql -f lwpostgis.sql -d yourdatabase
 
404
        psql -f dumpfile.sql -d yourdatabase
 
405
        vacuumdb -z yourdatabase
 
406
        </programlisting>
 
407
 
 
408
 
 
409
      </sect2>
 
410
 
 
411
      <sect2>
 
412
        <title>Common Problems</title>
 
413
 
 
414
        <para>There are several things to check when your installation or
 
415
        upgrade doesn't go as you expected.</para>
 
416
 
 
417
        <orderedlist>
 
418
          <listitem>
 
419
            <para>It is easiest if you untar the PostGIS distribution into the
 
420
            contrib directory under the PostgreSQL source tree. However, if
 
421
            this is not possible for some reason, you can set the
 
422
            <varname>PGSQL_SRC</varname> environment variable to the path to
 
423
            the PostgreSQL source directory. This will allow you to compile
 
424
            PostGIS, but the <command>make install</command> may not work, so
 
425
            be prepared to copy the PostGIS library and executable files to
 
426
            the appropriate locations yourself.</para>
 
427
          </listitem>
 
428
 
 
429
          <listitem>
 
430
            <para>Check that you you have installed PostgreSQL 7.2 or newer,
 
431
            and that you are compiling against the same version of the
 
432
            PostgreSQL source as the version of PostgreSQL that is running.
 
433
            Mix-ups can occur when your (Linux) distrubution has already
 
434
            installed PostgreSQL, or you have otherwise installed PostgreSQL
 
435
            before and forgotten about it. PostGIS will only work with
 
436
            PostgreSQL 7.2 or newer, and strange, unexpected error messages
 
437
            will result if you use an older version. To check the version of
 
438
            PostgreSQL which is running, connect to the database using psql
 
439
            and run this query:</para>
 
440
 
 
441
            <programlisting>SELECT version();</programlisting>
 
442
 
 
443
            <para>If you are running an RPM based distribution, you can check
 
444
            for the existence of pre-installed packages using the
 
445
            <command>rpm</command> command as follows: <command>rpm -qa | grep
 
446
            postgresql</command></para>
 
447
          </listitem>
 
448
        </orderedlist>
 
449
 
 
450
        <para>Also check that you have made any necessary changes to the top
 
451
        of the Makefile.config. This includes:</para>
 
452
 
 
453
        <orderedlist>
 
454
          <listitem>
 
455
            <para>If you want to be able to do coordinate reprojections, you
 
456
            must install the Proj4 library on your system, set the
 
457
            <varname>USE_PROJ</varname> variable to 1 and the
 
458
            <varname>PROJ_DIR</varname> to your installation prefix in the
 
459
            Makefile.config.</para>
 
460
          </listitem>
 
461
 
 
462
          <listitem>
 
463
            <para>If you want to be able to use GEOS functions you must
 
464
            install the GEOS library on your system, and set the
 
465
            <varname>USE_GEOS</varname> to 1 and the
 
466
            <varname>GEOS_DIR</varname> to your installation prefix in the
 
467
            Makefile.config</para>
 
468
          </listitem>
 
469
        </orderedlist>
 
470
      </sect2>
 
471
    </sect1>
 
472
 
 
473
    <sect1>
 
474
      <title>JDBC</title>
 
475
 
 
476
      <para>The JDBC extensions provide Java objects corresponding to the
 
477
      internal PostGIS types. These objects can be used to write Java clients
 
478
      which query the PostGIS database and draw or do calculations on the GIS
 
479
      data in PostGIS.</para>
 
480
 
 
481
      <orderedlist>
 
482
        <listitem>
 
483
          <para>Enter the <filename>jdbc</filename> sub-directory of the
 
484
          PostGIS distribution.</para>
 
485
        </listitem>
 
486
 
 
487
        <listitem>
 
488
          <para>Edit the <filename>Makefile</filename> to provide the correct
 
489
          paths of your java compiler (<varname>JAVAC</varname>) and
 
490
          interpreter (<varname>JAVA</varname>).</para>
 
491
        </listitem>
 
492
 
 
493
        <listitem>
 
494
          <para>Run the <filename>make</filename> command. Copy the
 
495
          <filename>postgis.jar</filename> file to wherever you keep your java
 
496
          libraries.</para>
 
497
        </listitem>
 
498
      </orderedlist>
 
499
    </sect1>
 
500
 
 
501
    <sect1>
 
502
      <title>Loader/Dumper</title>
 
503
 
 
504
      <para>The data loader and dumper are built and installed automatically
 
505
      as part of the PostGIS build. To build and install them manually:</para>
 
506
 
 
507
      <programlisting># cd postgis-@@LAST_RELEASE_VERSION@@/loader 
 
508
# make
 
509
# make install</programlisting>
 
510
 
 
511
      <para>The loader is called <filename>shp2pgsql</filename> and converts
 
512
      ESRI Shape files into SQL suitable for loading in PostGIS/PostgreSQL.
 
513
      The dumper is called <filename>pgsql2shp</filename> and converts PostGIS
 
514
      tables (or queries) into ESRI Shape files.</para>
 
515
    </sect1>
 
516
  </chapter>
 
517
 
 
518
  <chapter>
 
519
    <title>Frequently Asked Questions</title>
 
520
 
 
521
    <qandaset>
 
522
      <qandaentry>
 
523
        <question>
 
524
          <para>What kind of geometric objects can I store?</para>
 
525
        </question>
 
526
 
 
527
        <answer>
 
528
          <para>You can store point, line, polygon, multipoint, multiline,
 
529
          multipolygon, and geometrycollections. These are specified in the
 
530
          Open GIS Well Known Text Format (with XYZ,XYM,XYZM extentions).</para>
 
531
        </answer>
 
532
      </qandaentry>
 
533
 
 
534
      <qandaentry>
 
535
        <question>
 
536
          <para>How do I insert a GIS object into the database?</para>
 
537
        </question>
 
538
 
 
539
        <answer>
 
540
          <para>First, you need to create a table with a column of type
 
541
          "geometry" to hold your GIS data. Connect to your database with
 
542
          <filename>psql</filename> and try the following SQL:</para>
 
543
 
 
544
          <programlisting>CREATE TABLE gtest ( ID int4, NAME varchar(20) );
 
545
SELECT AddGeometryColumn('', 'gtest','geom',-1,'LINESTRING',2);</programlisting>
 
546
 
 
547
          <para>If the geometry column addition fails, you probably have not
 
548
          loaded the PostGIS functions and objects into this database. See the
 
549
          <link linkend="PGInstall">installation instructions</link>.</para>
 
550
 
 
551
          <para>Then, you can insert a geometry into the table using a SQL
 
552
          insert statement. The GIS object itself is formatted using the
 
553
          OpenGIS Consortium "well-known text" format:</para>
 
554
 
 
555
          <programlisting>INSERT INTO gtest (ID, NAME, GEOM) VALUES (1, 'First Geometry', GeomFromText('LINESTRING(2 3,4 5,6 5,7 8)', -1));</programlisting>
 
556
 
 
557
          <para>For more information about other GIS objects, see the <link
 
558
          linkend="RefObject">object reference</link>.</para>
 
559
 
 
560
          <para>To view your GIS data in the table:</para>
 
561
 
 
562
          <programlisting>SELECT id, name, AsText(geom) AS geom FROM gtest;</programlisting>
 
563
 
 
564
          <para>The return value should look something like this:</para>
 
565
 
 
566
          <programlisting> id | name           | geom
 
567
----+----------------+-----------------------------
 
568
  1 | First Geometry | LINESTRING(2 3,4 5,6 5,7 8) 
 
569
(1 row)</programlisting>
 
570
        </answer>
 
571
      </qandaentry>
 
572
 
 
573
      <qandaentry>
 
574
        <question>
 
575
          <para>How do I construct a spatial query?</para>
 
576
        </question>
 
577
 
 
578
        <answer>
 
579
          <para>The same way you construct any other database query, as an SQL
 
580
          combination of return values, functions, and boolean tests.</para>
 
581
 
 
582
          <para>For spatial queries, there are two issues that are important
 
583
          to keep in mind while constructing your query: is there a spatial
 
584
          index you can make use of; and, are you doing expensive calculations
 
585
          on a large number of geometries.</para>
 
586
 
 
587
          <para>In general, you will want to use the "intersects operator"
 
588
          (&amp;&amp;) which tests whether the bounding boxes of features
 
589
          intersect. The reason the &amp;&amp; operator is useful is because
 
590
          if a spatial index is available to speed up the test, the &amp;&amp;
 
591
          operator will make use of this. This can make queries much much
 
592
          faster.</para>
 
593
 
 
594
          <para>You will also make use of spatial functions, such as
 
595
          Distance(), Intersects(), Contains() and Within(), among others, to
 
596
          narrow down the results of your search. Most spatial queries include
 
597
          both an indexed test and a spatial function test. The index test
 
598
          serves to limit the number of return tuples to only tuples that
 
599
          <emphasis>might</emphasis> meet the condition of interest. The
 
600
          spatial functions are then use to test the condition exactly.</para>
 
601
 
 
602
          <programlisting>SELECT id, the_geom FROM thetable
 
603
WHERE
 
604
  the_geom &amp;&amp; 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'
 
605
AND
 
606
  Contains(the_geom,'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))';</programlisting>
 
607
        </answer>
 
608
      </qandaentry>
 
609
 
 
610
      <qandaentry>
 
611
        <question>
 
612
          <para>How do I speed up spatial queries on large tables?</para>
 
613
        </question>
 
614
 
 
615
        <answer>
 
616
          <para>Fast queries on large tables is the <emphasis>raison
 
617
          d'etre</emphasis> of spatial databases (along with transaction
 
618
          support) so having a good index is important.</para>
 
619
 
 
620
          <para>To build a spatial index on a table with a
 
621
          <varname>geometry</varname> column, use the "CREATE INDEX" function
 
622
          as follows:</para>
 
623
 
 
624
          <programlisting>CREATE INDEX [indexname] ON [tablename]  
 
625
  USING GIST ( [geometrycolumn] );</programlisting>
 
626
 
 
627
          <para>The "USING GIST" option tells the server to use a GiST
 
628
          (Generalized Search Tree) index.</para>
 
629
 
 
630
          <note>
 
631
            <para>
 
632
            GiST indexes are assumed to be lossy.
 
633
            Lossy indexes uses a proxy object (in the spatial case,
 
634
            a bounding box) for building the index.</para>
 
635
          </note>
 
636
 
 
637
          <para>You should also ensure that the PostgreSQL query planner has
 
638
          enough information about your index to make rational decisions about
 
639
          when to use it. To do this, you have to "gather statistics" on your
 
640
          geometry tables.</para>
 
641
 
 
642
          <para>For PostgreSQL 8.0.x and greater, just run the <command>VACUUM
 
643
          ANALYZE</command> command.</para>
 
644
 
 
645
          <para>For PostgreSQL 7.4.x and below, run the <command>SELECT
 
646
          UPDATE_GEOMETRY_STATS()</command> command.</para>
 
647
        </answer>
 
648
      </qandaentry>
 
649
 
 
650
      <qandaentry>
 
651
        <question>
 
652
          <para>Why aren't PostgreSQL R-Tree indexes supported?</para>
 
653
        </question>
 
654
 
 
655
        <answer>
 
656
          <para>Early versions of PostGIS used the PostgreSQL R-Tree indexes.
 
657
          However, PostgreSQL R-Trees have been completely discarded since
 
658
          version 0.6, and spatial indexing is provided with an
 
659
          R-Tree-over-GiST scheme.</para>
 
660
 
 
661
          <para>Our tests have shown search speed for native R-Tree and GiST
 
662
          to be comparable. Native PostgreSQL R-Trees have two limitations
 
663
          which make them undesirable for use with GIS features (note that
 
664
          these limitations are due to the current PostgreSQL native R-Tree
 
665
          implementation, not the R-Tree concept in general):</para>
 
666
 
 
667
          <itemizedlist>
 
668
            <listitem>
 
669
              <para>R-Tree indexes in PostgreSQL cannot handle features which
 
670
              are larger than 8K in size. GiST indexes can, using the "lossy"
 
671
              trick of substituting the bounding box for the feature
 
672
              itself.</para>
 
673
            </listitem>
 
674
 
 
675
            <listitem>
 
676
              <para>R-Tree indexes in PostgreSQL are not "null safe", so
 
677
              building an index on a geometry column which contains null
 
678
              geometries will fail.</para>
 
679
            </listitem>
 
680
          </itemizedlist>
 
681
        </answer>
 
682
      </qandaentry>
 
683
 
 
684
      <qandaentry>
 
685
        <question>
 
686
          <para>Why should I use the <varname>AddGeometryColumn()</varname>
 
687
          function and all the other OpenGIS stuff?</para>
 
688
        </question>
 
689
 
 
690
        <answer>
 
691
          <para>If you do not want to use the OpenGIS support functions, you
 
692
          do not have to. Simply create tables as in older versions, defining
 
693
          your geometry columns in the CREATE statement. All your geometries
 
694
          will have SRIDs of -1, and the OpenGIS meta-data tables will
 
695
          <emphasis>not</emphasis> be filled in properly. However, this will
 
696
          cause most applications based on PostGIS to fail, and it is
 
697
          generally suggested that you do use
 
698
          <varname>AddGeometryColumn()</varname> to create geometry
 
699
          tables.</para>
 
700
 
 
701
          <para>Mapserver is one application which makes use of the
 
702
          <varname>geometry_columns</varname> meta-data. Specifically,
 
703
          Mapserver can use the SRID of the geometry column to do on-the-fly
 
704
          reprojection of features into the correct map projection.</para>
 
705
        </answer>
 
706
      </qandaentry>
 
707
 
 
708
      <qandaentry>
 
709
        <question>
 
710
          <para>What is the best way to find all objects within a radius of
 
711
          another object?</para>
 
712
        </question>
 
713
 
 
714
        <answer>
 
715
          <para>To use the database most efficiently, it is best to do radius
 
716
          queries which combine the radius test with a bounding box test: the
 
717
          bounding box test uses the spatial index, giving fast access to a
 
718
          subset of data which the radius test is then applied to.</para>
 
719
 
 
720
          <para>The <varname>Expand()</varname> function is a handy way of
 
721
          enlarging a bounding box to allow an index search of a region of
 
722
          interest. The combination of a fast access index clause and a slower
 
723
          accurate distance test provides the best combination of speed and
 
724
          precision for this query.</para>
 
725
 
 
726
          <para>For example, to find all objects with 100 meters of POINT(1000
 
727
          1000) the following query would work well:</para>
 
728
 
 
729
          <programlisting>SELECT * 
 
730
FROM GEOTABLE 
 
731
WHERE 
 
732
  GEOCOLUMN &amp;&amp; Expand(GeomFromText('POINT(1000 1000)',-1),100)
 
733
AND
 
734
  Distance(GeomFromText('POINT(1000 1000)',-1),GEOCOLUMN) &lt; 100;</programlisting>
 
735
        </answer>
 
736
      </qandaentry>
 
737
 
 
738
      <qandaentry>
 
739
        <question>
 
740
          <para>How do I perform a coordinate reprojection as part of a
 
741
          query?</para>
 
742
        </question>
 
743
 
 
744
        <answer>
 
745
          <para>To perform a reprojection, both the source and destination
 
746
          coordinate systems must be defined in the SPATIAL_REF_SYS table, and
 
747
          the geometries being reprojected must already have an SRID set on
 
748
          them. Once that is done, a reprojection is as simple as referring to
 
749
          the desired destination SRID.</para>
 
750
 
 
751
          <programlisting>SELECT Transform(GEOM,4269) FROM GEOTABLE;</programlisting>
 
752
        </answer>
 
753
      </qandaentry>
 
754
    </qandaset>
 
755
  </chapter>
 
756
 
 
757
  <chapter>
 
758
    <title>Using PostGIS</title>
 
759
 
 
760
    <sect1 id="RefObject">
 
761
      <title>GIS Objects</title>
 
762
 
 
763
      <para>The GIS objects supported by PostGIS are a superset of
 
764
      the "Simple Features" defined by the OpenGIS Consortium (OGC).
 
765
      As of version 0.9, PostGIS supports all the objects and functions
 
766
      specified in the OGC "Simple Features for SQL" specification.</para>
 
767
 
 
768
      <para>PostGIS extends the standard with support for 3DZ,3DM and 4D
 
769
      coordinates.</para>
 
770
 
 
771
      <sect2>
 
772
        <title>OpenGIS WKB and WKT</title>
 
773
 
 
774
        <para>The OpenGIS specification defines two standard ways of
 
775
        expressing spatial objects: the Well-Known Text (WKT) form and
 
776
        the Well-Known Binary (WKB) form. Both WKT and WKB include
 
777
        information about the type of the object and the
 
778
        coordinates which form the object.</para>
 
779
 
 
780
      <para>Examples of the text representations (WKT) of the spatial
 
781
      objects of the features are as follows:</para>
 
782
 
 
783
      <itemizedlist>
 
784
        <listitem>
 
785
          <para>POINT(0 0)</para>
 
786
        </listitem>
 
787
 
 
788
        <listitem>
 
789
          <para>LINESTRING(0 0,1 1,1 2)</para>
 
790
        </listitem>
 
791
 
 
792
        <listitem>
 
793
          <para>POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))</para>
 
794
        </listitem>
 
795
 
 
796
        <listitem>
 
797
          <para>MULTIPOINT(0 0,1 2)</para>
 
798
        </listitem>
 
799
 
 
800
        <listitem>
 
801
          <para>MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))</para>
 
802
        </listitem>
 
803
 
 
804
        <listitem>
 
805
          <para>MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)),
 
806
          ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))</para>
 
807
        </listitem>
 
808
 
 
809
        <listitem>
 
810
          <para>GEOMETRYCOLLECTION(POINT(2 3),LINESTRING((2 3,3 4)))</para>
 
811
        </listitem>
 
812
 
 
813
      </itemizedlist>
 
814
 
 
815
 
 
816
        <para>The OpenGIS specification also requires that the
 
817
        internal storage format of spatial objects include a spatial
 
818
        referencing system identifier (SRID). The SRID is required when
 
819
        creating spatial objects for insertion into the database.</para>
 
820
 
 
821
<para>
 
822
Input/Output of these formats are available using the following
 
823
interfaces:
 
824
</para>
 
825
 
 
826
        <programlisting>
 
827
        bytea WKB = asBinary(geometry);
 
828
        text WKT = asText(geometry);
 
829
        geometry = GeomFromWKB(bytea WKB, SRID); 
 
830
        geometry = GeometryFromText(text WKT, SRID);
 
831
        </programlisting>
 
832
 
 
833
        <para> For example, a valid insert statement to create and insert an OGC spatial object would be:</para>
 
834
 
 
835
        <programlisting>
 
836
        INSERT INTO SPATIALTABLE ( 
 
837
                  THE_GEOM, 
 
838
                  THE_NAME 
 
839
        ) 
 
840
        VALUES ( 
 
841
                  GeomFromText('POINT(-126.4 45.32)', 312), 
 
842
                  'A Place' 
 
843
        )</programlisting>
 
844
 
 
845
 
 
846
      </sect2>
 
847
 
 
848
        <sect2>
 
849
        <title>PostGIS EWKB, EWKT and Canonical Forms</title>
 
850
 
 
851
 
 
852
<para>
 
853
OGC formats only support 2d geometries, and the associated SRID
 
854
is *never* embedded in the input/output representations.
 
855
</para>
 
856
 
 
857
<para>
 
858
Postgis extended formats are currently superset of OGC one (every
 
859
valid WKB/WKT is a valid EWKB/EWKT) but this might vary in the
 
860
future, specifically if OGC comes out with a new format conflicting
 
861
with our extensions. Thus you SHOULD NOT rely on this feature!
 
862
</para>
 
863
 
 
864
<para>
 
865
Postgis EWKB/EWKT add 3dm,3dz,4d coordinates support and embedded
 
866
SRID information.
 
867
</para>
 
868
 
 
869
      <para>Examples of the text representations (EWKT) of the
 
870
      extended spatial objects of the features are as follows:</para>
 
871
 
 
872
      <itemizedlist>
 
873
 
 
874
        <listitem>
 
875
          <para>POINT(0 0 0) -- XYZ</para>
 
876
        </listitem>
 
877
 
 
878
        <listitem>
 
879
          <para>SRID=32632;POINT(0 0) -- XY with SRID</para>
 
880
        </listitem>
 
881
 
 
882
        <listitem>
 
883
          <para>POINTM(0 0 0) -- XYM</para>
 
884
        </listitem>
 
885
 
 
886
        <listitem>
 
887
          <para>POINT(0 0 0 0) -- XYZM</para>
 
888
        </listitem>
 
889
 
 
890
        <listitem>
 
891
          <para>SRID=4326;MULTIPOINTM(0 0 0,1 2 1) -- XYM with SRID</para>
 
892
        </listitem>
 
893
 
 
894
        <listitem>
 
895
          <para>MULTILINESTRING((0 0 0,1 1 0,1 2 1),(2 3 1,3 2 1,5 4
 
896
          1))</para>
 
897
        </listitem>
 
898
 
 
899
        <listitem>
 
900
          <para>POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2
 
901
          0,1 1 0))</para>
 
902
        </listitem>
 
903
 
 
904
        <listitem>
 
905
          <para>MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2
 
906
          0,1 2 0,1 1 0)),((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0)))</para>
 
907
        </listitem>
 
908
 
 
909
        <listitem>
 
910
          <para>GEOMETRYCOLLECTIONM(POINTM(2 3 9),LINESTRINGM((2 3 4,3 4
 
911
          5)))</para>
 
912
        </listitem>
 
913
 
 
914
      </itemizedlist>
 
915
 
 
916
 
 
917
<para>
 
918
Input/Output of these formats are available using the following
 
919
interfaces:
 
920
</para>
 
921
 
 
922
        <programlisting>
 
923
        bytea EWKB = asEWKB(geometry);
 
924
        text EWKT = asEWKT(geometry);
 
925
        geometry = GeomFromEWKB(bytea EWKB);
 
926
        geometry = GeomFromEWKT(text EWKT);
 
927
        </programlisting>
 
928
 
 
929
<para>
 
930
For example, a valid insert statement to create and insert a PostGIS spatial object would be:
 
931
</para>
 
932
 
 
933
        <programlisting>
 
934
        INSERT INTO SPATIALTABLE ( 
 
935
                  THE_GEOM, 
 
936
                  THE_NAME 
 
937
        ) 
 
938
        VALUES ( 
 
939
                  GeomFromEWKT('SRID=312;POINTM(-126.4 45.32 15)'), 
 
940
                  'A Place' 
 
941
        )</programlisting>
 
942
 
 
943
<para>
 
944
The "canonical forms" of a PostgreSQL type are the representations
 
945
you get with a simple query (without any function call) and the one
 
946
which is guaranteed to be accepted with a simple insert, update or
 
947
copy. For the postgis 'geometry' type these are:
 
948
 
 
949
        <programlisting>
 
950
        - Output -
 
951
        binary: EWKB
 
952
         ascii: HEXEWKB (EWKB in hex form)
 
953
 
 
954
        - Input -
 
955
        binary: EWKB
 
956
         ascii: HEXEWKB|EWKT
 
957
        </programlisting>
 
958
</para>
 
959
 
 
960
<para>
 
961
For example this statement reads EWKT and returns HEXEWKB in the
 
962
process of canonical ascii input/output:
 
963
</para>
 
964
 
 
965
        <programlisting>
 
966
        =# SELECT 'SRID=4;POINT(0 0)'::geometry;
 
967
                              geometry
 
968
        ----------------------------------------------------
 
969
         01010000200400000000000000000000000000000000000000
 
970
        (1 row)
 
971
        </programlisting>
 
972
 
 
973
 
 
974
      </sect2>
 
975
    </sect1>
 
976
 
 
977
    <sect1>
 
978
      <title>Using OpenGIS Standards</title>
 
979
 
 
980
      <para>The OpenGIS "Simple Features Specification for SQL" defines
 
981
      standard GIS object types, the functions required to manipulate them,
 
982
      and a set of meta-data tables. In order to ensure that meta-data remain
 
983
      consistent, operations such as creating and removing a spatial column
 
984
      are carried out through special procedures defined by OpenGIS.</para>
 
985
 
 
986
      <para>There are two OpenGIS meta-data tables:
 
987
      <varname>SPATIAL_REF_SYS</varname> and
 
988
      <varname>GEOMETRY_COLUMNS</varname>. The
 
989
      <varname>SPATIAL_REF_SYS</varname> table holds the numeric IDs and
 
990
      textual descriptions of coordinate systems used in the spatial
 
991
      database.</para>
 
992
 
 
993
      <sect2>
 
994
        <title>The SPATIAL_REF_SYS Table</title>
 
995
 
 
996
        <para>The <varname>SPATIAL_REF_SYS</varname> table definition is as
 
997
        follows:</para>
 
998
 
 
999
        <programlisting>CREATE TABLE SPATIAL_REF_SYS ( 
 
1000
  SRID INTEGER NOT NULL PRIMARY KEY, 
 
1001
  AUTH_NAME VARCHAR(256), 
 
1002
  AUTH_SRID INTEGER, 
 
1003
  SRTEXT VARCHAR(2048), 
 
1004
  PROJ4TEXT VARCHAR(2048)
 
1005
)</programlisting>
 
1006
 
 
1007
        <para>The <varname>SPATIAL_REF_SYS</varname> columns are as
 
1008
        follows:</para>
 
1009
 
 
1010
        <variablelist>
 
1011
          <varlistentry>
 
1012
            <term>SRID</term>
 
1013
 
 
1014
            <listitem>
 
1015
              <para>An integer value that uniquely identifies the Spatial
 
1016
              Referencing System (SRS) within the database.</para>
 
1017
            </listitem>
 
1018
          </varlistentry>
 
1019
 
 
1020
          <varlistentry>
 
1021
            <term>AUTH_NAME</term>
 
1022
 
 
1023
            <listitem>
 
1024
              <para>The name of the standard or standards body that is being
 
1025
              cited for this reference system. For example, "EPSG" would be a
 
1026
              valid <varname>AUTH_NAME</varname>.</para>
 
1027
            </listitem>
 
1028
          </varlistentry>
 
1029
 
 
1030
          <varlistentry>
 
1031
            <term>AUTH_SRID</term>
 
1032
 
 
1033
            <listitem>
 
1034
              <para>The ID of the Spatial Reference System as defined by the
 
1035
              Authority cited in the <varname>AUTH_NAME</varname>. In the case
 
1036
              of EPSG, this is where the EPSG projection code would go.</para>
 
1037
            </listitem>
 
1038
          </varlistentry>
 
1039
 
 
1040
          <varlistentry>
 
1041
            <term>SRTEXT</term>
 
1042
 
 
1043
            <listitem>
 
1044
              <para>The Well-Known Text representation of the Spatial
 
1045
              Reference System. An example of a WKT SRS representation
 
1046
              is:</para>
 
1047
 
 
1048
              <programlisting>PROJCS["NAD83 / UTM Zone 10N", 
 
1049
  GEOGCS["NAD83",
 
1050
    DATUM["North_American_Datum_1983", 
 
1051
      SPHEROID["GRS 1980",6378137,298.257222101]
 
1052
    ], 
 
1053
    PRIMEM["Greenwich",0], 
 
1054
    UNIT["degree",0.0174532925199433] 
 
1055
  ],
 
1056
  PROJECTION["Transverse_Mercator"], 
 
1057
  PARAMETER["latitude_of_origin",0],
 
1058
  PARAMETER["central_meridian",-123], 
 
1059
  PARAMETER["scale_factor",0.9996],
 
1060
  PARAMETER["false_easting",500000], 
 
1061
  PARAMETER["false_northing",0],
 
1062
  UNIT["metre",1] 
 
1063
]</programlisting>
 
1064
 
 
1065
              <para>For a listing of EPSG projection codes and their
 
1066
              corresponding WKT representations, see <ulink
 
1067
              url="http://www.opengis.org/techno/interop/EPSG2WKT.TXT">http://www.opengis.org/techno/interop/EPSG2WKT.TXT</ulink>.
 
1068
              For a discussion of WKT in general, see the OpenGIS "Coordinate
 
1069
              Transformation Services Implementation Specification" at <ulink
 
1070
              url="http://www.opengis.org/techno/specs.htm">http://www.opengis.org/techno/specs.htm</ulink>.
 
1071
              For information on the European Petroleum Survey Group (EPSG)
 
1072
              and their database of spatial reference systems, see <ulink
 
1073
              url="http://epsg.org">http://epsg.org</ulink>.</para>
 
1074
            </listitem>
 
1075
          </varlistentry>
 
1076
 
 
1077
          <varlistentry>
 
1078
            <term>PROJ4TEXT</term>
 
1079
 
 
1080
            <listitem>
 
1081
              <para>PostGIS uses the Proj4 library to provide coordinate
 
1082
              transformation capabilities. The <varname>PROJ4TEXT</varname>
 
1083
              column contains the Proj4 coordinate definition string for a
 
1084
              particular SRID. For example:</para>
 
1085
 
 
1086
              <programlisting>+proj=utm +zone=10 +ellps=clrk66 +datum=NAD27 +units=m</programlisting>
 
1087
 
 
1088
              <para>For more information about, see the Proj4 web site at
 
1089
              <ulink
 
1090
              url="http://www.remotesensing.org/proj">http://www.remotesensing.org/proj</ulink>.
 
1091
              The <filename>spatial_ref_sys.sql</filename> file contains both
 
1092
              <varname>SRTEXT</varname> and <varname>PROJ4TEXT</varname>
 
1093
              definitions for all EPSG projections.</para>
 
1094
            </listitem>
 
1095
          </varlistentry>
 
1096
        </variablelist>
 
1097
      </sect2>
 
1098
 
 
1099
      <sect2>
 
1100
        <title>The GEOMETRY_COLUMNS Table</title>
 
1101
 
 
1102
        <para>The <varname>GEOMETRY_COLUMNS</varname> table definition is as
 
1103
        follows:</para>
 
1104
 
 
1105
        <programlisting>CREATE TABLE GEOMETRY_COLUMNS ( 
 
1106
  F_TABLE_CATALOG VARCHAR(256) NOT NULL, 
 
1107
  F_TABLE_SCHEMA VARCHAR(256) NOT NULL, 
 
1108
  F_TABLE_NAME VARCHAR(256) NOT NULL, 
 
1109
  F_GEOMETRY_COLUMN VARCHAR(256) NOT NULL,
 
1110
  COORD_DIMENSION INTEGER NOT NULL, 
 
1111
  SRID INTEGER NOT NULL, 
 
1112
  TYPE VARCHAR(30) NOT NULL 
 
1113
)</programlisting>
 
1114
 
 
1115
        <para>The columns are as follows:</para>
 
1116
 
 
1117
        <variablelist>
 
1118
          <varlistentry>
 
1119
            <term>F_TABLE_CATALOG, F_TABLE_SCHEMA, F_TABLE_NAME</term>
 
1120
 
 
1121
            <listitem>
 
1122
              <para>The fully qualified name of the feature table containing
 
1123
              the geometry column. Note that the terms "catalog" and "schema"
 
1124
              are Oracle-ish. There is not PostgreSQL analogue of "catalog" so
 
1125
              that column is left blank -- for "schema" the PostgreSQL schema
 
1126
              name is used (<varname>public</varname> is the default).</para>
 
1127
            </listitem>
 
1128
          </varlistentry>
 
1129
 
 
1130
          <varlistentry>
 
1131
            <term>F_GEOMETRY_COLUMN</term>
 
1132
 
 
1133
            <listitem>
 
1134
              <para>The name of the geometry column in the feature
 
1135
              table.</para>
 
1136
            </listitem>
 
1137
          </varlistentry>
 
1138
 
 
1139
          <varlistentry>
 
1140
            <term>COORD_DIMENSION</term>
 
1141
 
 
1142
            <listitem>
 
1143
              <para>The spatial dimension (2, 3 or 4 dimensional) of the
 
1144
              column.</para>
 
1145
            </listitem>
 
1146
          </varlistentry>
 
1147
 
 
1148
          <varlistentry>
 
1149
            <term>SRID</term>
 
1150
 
 
1151
            <listitem>
 
1152
              <para>The ID of the spatial reference system used for the
 
1153
              coordinate geometry in this table. It is a foreign key reference
 
1154
              to the <varname>SPATIAL_REF_SYS</varname>.</para>
 
1155
            </listitem>
 
1156
          </varlistentry>
 
1157
 
 
1158
          <varlistentry>
 
1159
            <term>TYPE</term>
 
1160
 
 
1161
            <listitem>
 
1162
              <para>The type of the spatial object. To restrict the spatial
 
1163
              column to a single type, use one of: POINT, LINESTRING, POLYGON,
 
1164
              MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION or
 
1165
              corresponding XYM versions POINTM, LINESTRINGM, POLYGONM,
 
1166
              MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM.
 
1167
              For heterogeneous (mixed-type) collections, you can use
 
1168
              "GEOMETRY" as the type.</para>
 
1169
 
 
1170
              <note>
 
1171
                <para>This attribute is (probably) not part of the OpenGIS
 
1172
                specification, but is required for ensuring type
 
1173
                homogeneity.</para>
 
1174
              </note>
 
1175
            </listitem>
 
1176
          </varlistentry>
 
1177
        </variablelist>
 
1178
      </sect2>
 
1179
 
 
1180
      <sect2>
 
1181
        <title>Creating a Spatial Table</title>
 
1182
 
 
1183
        <para>Creating a table with spatial data is done in two stages:</para>
 
1184
 
 
1185
        <itemizedlist>
 
1186
          <listitem>
 
1187
            <para>Create a normal non-spatial table.</para>
 
1188
 
 
1189
            <para>For example: <command>CREATE TABLE ROADS_GEOM ( ID int4,
 
1190
            NAME varchar(25) )</command></para>
 
1191
          </listitem>
 
1192
 
 
1193
          <listitem>
 
1194
            <para>Add a spatial column to the table using the OpenGIS
 
1195
            "AddGeometryColumn" function.</para>
 
1196
            
 
1197
            <para>The syntax is:
 
1198
            <programlisting>AddGeometryColumn(&lt;schema_name&gt;, &lt;table_name&gt;,
 
1199
            &lt;column_name&gt;, &lt;srid&gt;, &lt;type&gt;,
 
1200
            &lt;dimension&gt;)</programlisting>
 
1201
 
 
1202
            Or, using current schema:
 
1203
            <programlisting>AddGeometryColumn(&lt;table_name&gt;,
 
1204
            &lt;column_name&gt;, &lt;srid&gt;, &lt;type&gt;,
 
1205
            &lt;dimension&gt;)</programlisting>
 
1206
            </para>
 
1207
 
 
1208
            <para>Example1: <command>SELECT AddGeometryColumn('public',
 
1209
            'roads_geom', 'geom', 423, 'LINESTRING', 2)</command></para>
 
1210
            <para>Example2: <command>SELECT AddGeometryColumn(
 
1211
            'roads_geom', 'geom', 423, 'LINESTRING', 2)</command></para>
 
1212
          </listitem>
 
1213
        </itemizedlist>
 
1214
 
 
1215
        <para>Here is an example of SQL used to create a table and add a
 
1216
        spatial column (assuming that an SRID of 128
 
1217
        exists already):</para>
 
1218
 
 
1219
        <programlisting>CREATE TABLE parks ( PARK_ID int4, PARK_NAME varchar(128), PARK_DATE date, PARK_TYPE varchar(2) );
 
1220
SELECT AddGeometryColumn('parks', 'park_geom', 128, 'MULTIPOLYGON', 2 );</programlisting>
 
1221
 
 
1222
        <para>Here is another example, using the generic "geometry" type and
 
1223
        the undefined SRID value of -1:</para>
 
1224
 
 
1225
        <programlisting>CREATE TABLE roads ( ROAD_ID int4, ROAD_NAME varchar(128) ); 
 
1226
SELECT AddGeometryColumn( 'roads', 'roads_geom', -1, 'GEOMETRY', 3 );</programlisting>
 
1227
      </sect2>
 
1228
 
 
1229
      <sect2>
 
1230
        <title>Ensuring OpenGIS compliancy of geometries</title>
 
1231
 
 
1232
        <para>Most of the functions implemented by the GEOS library
 
1233
        rely on the assumption that your geometries are valid
 
1234
        as specified by the OpenGIS Simple Feature Specification.
 
1235
        To check validity of geometries you can use the
 
1236
        <link linkend="IsValid">IsValid()</link> function:</para>
 
1237
 
 
1238
        <programlisting>gisdb=# select isvalid('LINESTRING(0 0, 1 1)'), isvalid('LINESTRING(0 0,0 0)');
 
1239
 isvalid | isvalid
 
1240
---------+---------
 
1241
 t       | f</programlisting>
 
1242
        
 
1243
        
 
1244
        <para>By default, PostGIS does not apply this validity check on geometry input, because
 
1245
        testing for validity needs lots of CPU time for complex geometries, especially polygons.
 
1246
        If you do not trust your data sources, you can manually enforce such a check to your tables
 
1247
        by adding a check constraint:</para>
 
1248
 
 
1249
        <programlisting>ALTER TABLE mytable ADD CONSTRAINT geometry_valid_check CHECK (isvalid(the_geom));</programlisting>
 
1250
 
 
1251
        <para>If you encounter any strange error messages such as "GEOS Intersection() threw an 
 
1252
        error!" or "JTS Intersection() threw an error!" when calling PostGIS functions with valid
 
1253
        input geometries, you likely found an error in either PostGIS or one of the libraries it
 
1254
        uses, and you should contact the PostGIS developers. The same is true if a PostGIS function returns
 
1255
        an invalid geometry for valid input.</para>
 
1256
 
 
1257
        <note>
 
1258
        <para>
 
1259
        Strictly compliant OGC geometries cannot have Z or M values.
 
1260
        The <link linkend="IsValid">IsValid()</link> function won't
 
1261
        consider higher dimensioned geometries invalid! Invocations
 
1262
        of <link linkend="AddGeometryColumn">AddGeometryColumn()</link>
 
1263
        will add a constraint checking geometry dimensions, so it is
 
1264
        enough to specify 2 there.
 
1265
        </para>
 
1266
        </note>
 
1267
 
 
1268
      </sect2>    
 
1269
    </sect1>
 
1270
 
 
1271
    <sect1>
 
1272
      <title>Loading GIS Data</title>
 
1273
 
 
1274
      <para>Once you have created a spatial table, you are ready to upload GIS
 
1275
      data to the database. Currently, there are two ways to get data into a
 
1276
      PostGIS/PostgreSQL database: using formatted SQL statements or using the
 
1277
      Shape file loader/dumper.</para>
 
1278
 
 
1279
      <sect2>
 
1280
        <title>Using SQL</title>
 
1281
 
 
1282
        <para>If you can convert your data to a text representation, then
 
1283
        using formatted SQL might be the easiest way to get your data into
 
1284
        PostGIS. As with Oracle and other SQL databases, data can be bulk
 
1285
        loaded by piping a large text file full of SQL "INSERT" statements
 
1286
        into the SQL terminal monitor.</para>
 
1287
 
 
1288
        <para>A data upload file (<filename>roads.sql</filename> for example)
 
1289
        might look like this:</para>
 
1290
 
 
1291
        <programlisting>BEGIN;
 
1292
INSERT INTO ROADS_GEOM (ID,GEOM,NAME ) VALUES (1,GeomFromText('LINESTRING(191232 243118,191108 243242)',-1),'Jeff Rd'); 
 
1293
INSERT INTO ROADS_GEOM (ID,GEOM,NAME ) VALUES (2,GeomFromText('LINESTRING(189141 244158,189265 244817)',-1),'Geordie Rd'); 
 
1294
INSERT INTO ROADS_GEOM (ID,GEOM,NAME ) VALUES (3,GeomFromText('LINESTRING(192783 228138,192612 229814)',-1),'Paul St'); 
 
1295
INSERT INTO ROADS_GEOM (ID,GEOM,NAME ) VALUES (4,GeomFromText('LINESTRING(189412 252431,189631 259122)',-1),'Graeme Ave'); 
 
1296
INSERT INTO ROADS_GEOM (ID,GEOM,NAME ) VALUES (5,GeomFromText('LINESTRING(190131 224148,190871 228134)',-1),'Phil Tce'); 
 
1297
INSERT INTO ROADS_GEOM (ID,GEOM,NAME ) VALUES (6,GeomFromText('LINESTRING(198231 263418,198213 268322)',-1),'Dave Cres');
 
1298
COMMIT;</programlisting>
 
1299
 
 
1300
        <para>The data file can be piped into PostgreSQL very easily using the
 
1301
        "psql" SQL terminal monitor:</para>
 
1302
 
 
1303
        <programlisting>psql -d [database] -f roads.sql</programlisting>
 
1304
      </sect2>
 
1305
 
 
1306
      <sect2>
 
1307
        <title>Using the Loader</title>
 
1308
 
 
1309
        <para>The <filename>shp2pgsql</filename> data loader converts ESRI
 
1310
        Shape files into SQL suitable for insertion into a PostGIS/PostgreSQL
 
1311
        database. The loader has several operating modes distinguished by
 
1312
        command line flags:</para>
 
1313
 
 
1314
        <variablelist>
 
1315
          <varlistentry>
 
1316
            <term>-d</term>
 
1317
 
 
1318
            <listitem>
 
1319
              <para>Drops the database table before creating a new table with
 
1320
              the data in the Shape file.</para>
 
1321
            </listitem>
 
1322
          </varlistentry>
 
1323
 
 
1324
          <varlistentry>
 
1325
            <term>-a</term>
 
1326
 
 
1327
            <listitem>
 
1328
              <para>Appends data from the Shape file into the database table.
 
1329
              Note that to use this option to load multiple files, the files
 
1330
              must have the same attributes and same data types.</para>
 
1331
            </listitem>
 
1332
          </varlistentry>
 
1333
 
 
1334
          <varlistentry>
 
1335
            <term>-c</term>
 
1336
 
 
1337
            <listitem>
 
1338
              <para>Creates a new table and populates it from the Shape file.
 
1339
              <emphasis>This is the default mode.</emphasis></para>
 
1340
            </listitem>
 
1341
          </varlistentry>
 
1342
 
 
1343
          <varlistentry>
 
1344
            <term>-p</term>
 
1345
 
 
1346
            <listitem>
 
1347
              <para>Only produces the table creation SQL code, without adding 
 
1348
              any actual data. This can be used if you need to completely
 
1349
              separate the table creation and data loading steps.</para>
 
1350
            </listitem>
 
1351
          </varlistentry>
 
1352
 
 
1353
          <varlistentry>
 
1354
            <term>-D</term>
 
1355
 
 
1356
            <listitem>
 
1357
              <para>Use the PostgreSQL "dump" format for the output data. This 
 
1358
              can be combined with -a, -c and -d. It is much faster to load
 
1359
              than the default "insert" SQL format. Use this for very large data
 
1360
              sets.</para>
 
1361
            </listitem>
 
1362
          </varlistentry>
 
1363
 
 
1364
          <varlistentry>
 
1365
            <term>-s &lt;SRID&gt;</term>
 
1366
 
 
1367
            <listitem>
 
1368
              <para>Creates and populates the geometry tables with the
 
1369
              specified SRID.</para>
 
1370
            </listitem>
 
1371
          </varlistentry>
 
1372
 
 
1373
          <varlistentry>
 
1374
            <term>-k</term>
 
1375
 
 
1376
            <listitem>
 
1377
              <para>Keep idendifiers case (column, schema and attributes). Note that attributes in Shapefile are all UPPERCASE.</para>
 
1378
            </listitem>
 
1379
          </varlistentry>
 
1380
 
 
1381
          <varlistentry>
 
1382
            <term>-i</term>
 
1383
 
 
1384
            <listitem>
 
1385
              <para>Coerce all integers to standard 32-bit integers, do not
 
1386
              create 64-bit bigints, even if the DBF header signature appears
 
1387
              to warrant it.</para>
 
1388
            </listitem>
 
1389
          </varlistentry>
 
1390
 
 
1391
          <varlistentry>
 
1392
            <term>-w</term>
 
1393
 
 
1394
            <listitem>
 
1395
              <para>
 
1396
              Output WKT format, for use with older (0.x) versions of PostGIS.
 
1397
              Note  that this will introduce coordinate drifts and will drop M
 
1398
              values from shapefiles.
 
1399
              </para>
 
1400
            </listitem>
 
1401
          </varlistentry>
 
1402
 
 
1403
        </variablelist>
 
1404
 
 
1405
        <para>Note that -a, -c, -d and -p are mutually exclusive.</para>
 
1406
 
 
1407
        <para>An example session using the loader to create an input file and
 
1408
        uploading it might look like this:</para>
 
1409
 
 
1410
        <programlisting># shp2pgsql shaperoads myschema.roadstable &gt; roads.sql 
 
1411
# psql -d roadsdb -f roads.sql</programlisting>
 
1412
 
 
1413
        <para>A conversion and upload can be done all in one step using UNIX
 
1414
        pipes:</para>
 
1415
 
 
1416
        <programlisting># shp2pgsql shaperoads myschema.roadstable | psql -d roadsdb</programlisting>
 
1417
      </sect2>
 
1418
    </sect1>
 
1419
 
 
1420
    <sect1>
 
1421
      <title>Retrieving GIS Data</title>
 
1422
 
 
1423
      <para>Data can be extracted from the database using either SQL or the
 
1424
      Shape file loader/dumper. In the section on SQL we will discuss some of
 
1425
      the operators available to do comparisons and queries on spatial
 
1426
      tables.</para>
 
1427
 
 
1428
      <sect2>
 
1429
        <title>Using SQL</title>
 
1430
 
 
1431
        <para>The most straightforward means of pulling data out of the
 
1432
        database is to use a SQL select query and dump the resulting columns
 
1433
        into a parsable text file:</para>
 
1434
 
 
1435
        <programlisting>db=# SELECT id, AsText(geom) AS geom, name FROM ROADS_GEOM; 
 
1436
id | geom                                    | name 
 
1437
---+-----------------------------------------+-----------
 
1438
 1 | LINESTRING(191232 243118,191108 243242) | Jeff Rd  
 
1439
 2 | LINESTRING(189141 244158,189265 244817) | Geordie Rd 
 
1440
 3 | LINESTRING(192783 228138,192612 229814) | Paul St 
 
1441
 4 | LINESTRING(189412 252431,189631 259122) | Graeme Ave 
 
1442
 5 | LINESTRING(190131 224148,190871 228134) | Phil Tce 
 
1443
 6 | LINESTRING(198231 263418,198213 268322) | Dave Cres 
 
1444
 7 | LINESTRING(218421 284121,224123 241231) | Chris Way 
 
1445
(6 rows)</programlisting>
 
1446
 
 
1447
        <para>However, there will be times when some kind of restriction is
 
1448
        necessary to cut down the number of fields returned. In the case of
 
1449
        attribute-based restrictions, just use the same SQL syntax as normal
 
1450
        with a non-spatial table. In the case of spatial restrictions, the
 
1451
        following operators are available/useful:</para>
 
1452
 
 
1453
        <variablelist>
 
1454
          <varlistentry>
 
1455
            <term>&amp;&amp;</term>
 
1456
 
 
1457
            <listitem>
 
1458
              <para>This operator tells whether the bounding box of one
 
1459
              geometry intersects the bounding box of another.</para>
 
1460
            </listitem>
 
1461
          </varlistentry>
 
1462
 
 
1463
          <varlistentry>
 
1464
            <term>~=</term>
 
1465
 
 
1466
            <listitem>
 
1467
              <para>This operators tests whether two geometries are
 
1468
              geometrically identical. For example, if 'POLYGON((0 0,1 1,1 0,0
 
1469
              0))' is the same as 'POLYGON((0 0,1 1,1 0,0 0))' (it is).</para>
 
1470
            </listitem>
 
1471
          </varlistentry>
 
1472
 
 
1473
          <varlistentry>
 
1474
            <term>=</term>
 
1475
 
 
1476
            <listitem>
 
1477
              <para>This operator is a little more naive, it only tests
 
1478
              whether the bounding boxes of to geometries are the same.</para>
 
1479
            </listitem>
 
1480
          </varlistentry>
 
1481
        </variablelist>
 
1482
 
 
1483
        <para>Next, you can use these operators in queries. Note that when
 
1484
        specifying geometries and boxes on the SQL command line, you must
 
1485
        explicitly turn the string representations into geometries by using
 
1486
        the "GeomFromText()" function. So, for example:</para>
 
1487
 
 
1488
        <programlisting>SELECT 
 
1489
  ID, NAME 
 
1490
FROM ROADS_GEOM 
 
1491
WHERE 
 
1492
  GEOM ~= GeomFromText('LINESTRING(191232 243118,191108 243242)',-1);</programlisting>
 
1493
 
 
1494
        <para>The above query would return the single record from the
 
1495
        "ROADS_GEOM" table in which the geometry was equal to that
 
1496
        value.</para>
 
1497
 
 
1498
        <para>When using the "&amp;&amp;" operator, you can specify either a
 
1499
        BOX3D as the comparison feature or a GEOMETRY. When you specify a
 
1500
        GEOMETRY, however, its bounding box will be used for the
 
1501
        comparison.</para>
 
1502
 
 
1503
        <programlisting>SELECT 
 
1504
  ID, NAME 
 
1505
FROM ROADS_GEOM 
 
1506
WHERE 
 
1507
  GEOM &amp;&amp; GeomFromText('POLYGON((191232 243117,191232 243119,191234 243117,191232 243117))',-1);</programlisting>
 
1508
 
 
1509
        <para>The above query will use the bounding box of the polygon for
 
1510
        comparison purposes.</para>
 
1511
 
 
1512
        <para>The most common spatial query will probably be a "frame-based"
 
1513
        query, used by client software, like data browsers and web mappers, to
 
1514
        grab a "map frame" worth of data for display. Using a "BOX3D" object
 
1515
        for the frame, such a query looks like this:</para>
 
1516
 
 
1517
        <programlisting>SELECT 
 
1518
  AsText(GEOM) AS GEOM 
 
1519
FROM ROADS_GEOM 
 
1520
WHERE 
 
1521
  GEOM &amp;&amp; GeomFromText('BOX3D(191232 243117,191232 243119)'::box3d,-1);</programlisting>
 
1522
 
 
1523
        <para>Note the use of the SRID, to specify the projection of the
 
1524
        BOX3D. The value -1 is used to indicate no specified SRID.</para>
 
1525
      </sect2>
 
1526
 
 
1527
      <sect2>
 
1528
        <title>Using the Dumper</title>
 
1529
 
 
1530
        <para>The <filename>pgsql2shp</filename> table dumper connects
 
1531
        directly to the database and converts a table (possibly defined by
 
1532
        a query) into a shape file. The
 
1533
        basic syntax is:</para>
 
1534
 
 
1535
        <programlisting>pgsql2shp [&lt;options&gt;] &lt;database&gt; [&lt;schema&gt;.]&lt;table&gt;</programlisting>
 
1536
        <programlisting>pgsql2shp [&lt;options&gt;] &lt;database&gt; &lt;query&gt;</programlisting>
 
1537
 
 
1538
        <para>The commandline options are:</para>
 
1539
 
 
1540
        <variablelist>
 
1541
          <varlistentry>
 
1542
            <term>-f &lt;filename&gt;</term>
 
1543
 
 
1544
            <listitem>
 
1545
              <para>Write the output to a particular filename.</para>
 
1546
            </listitem>
 
1547
          </varlistentry>
 
1548
 
 
1549
          <varlistentry>
 
1550
            <term>-h &lt;host&gt;</term>
 
1551
 
 
1552
            <listitem>
 
1553
              <para>The database host to connect to.</para>
 
1554
            </listitem>
 
1555
          </varlistentry>
 
1556
 
 
1557
          <varlistentry>
 
1558
            <term>-p &lt;port&gt;</term>
 
1559
 
 
1560
            <listitem>
 
1561
              <para>The port to connect to on the database host.</para>
 
1562
            </listitem>
 
1563
          </varlistentry>
 
1564
 
 
1565
          <varlistentry>
 
1566
            <term>-P &lt;password&gt;</term>
 
1567
 
 
1568
            <listitem>
 
1569
              <para>The password to use when connecting to the
 
1570
              database.</para>
 
1571
            </listitem>
 
1572
          </varlistentry>
 
1573
 
 
1574
          <varlistentry>
 
1575
            <term>-u &lt;user&gt;</term>
 
1576
 
 
1577
            <listitem>
 
1578
              <para>The username to use when connecting to the
 
1579
              database.</para>
 
1580
            </listitem>
 
1581
          </varlistentry>
 
1582
 
 
1583
          <varlistentry>
 
1584
            <term>-g &lt;geometry column&gt;</term>
 
1585
 
 
1586
            <listitem>
 
1587
              <para>In the case of tables with multiple geometry columns, the
 
1588
              geometry column to use when writing the shape file.</para>
 
1589
            </listitem>
 
1590
          </varlistentry>
 
1591
 
 
1592
          <varlistentry>
 
1593
            <term>-b</term>
 
1594
 
 
1595
            <listitem>
 
1596
              <para>Use a binary cursor. This will make the operation faster,
 
1597
              but will not work if any NON-geometry attribute in the table
 
1598
              lacks a cast to text.</para>
 
1599
            </listitem>
 
1600
          </varlistentry>
 
1601
 
 
1602
          <varlistentry>
 
1603
            <term>-r</term>
 
1604
 
 
1605
            <listitem>
 
1606
              <para>Raw mode. Do not drop the <varname>gid</varname> field, or
 
1607
              escape column names.</para>
 
1608
            </listitem>
 
1609
          </varlistentry>
 
1610
 
 
1611
          <varlistentry>
 
1612
            <term>-d</term>
 
1613
 
 
1614
            <listitem>
 
1615
              <para>For backward compatibility: write a 3-dimensional shape
 
1616
              file when dumping from old (pre-1.0.0) postgis databases (the
 
1617
              default is to write a 2-dimensional shape file in that case).
 
1618
              Starting from postgis-1.0.0+, dimensions are fully encoded.
 
1619
              </para>
 
1620
            </listitem>
 
1621
          </varlistentry>
 
1622
 
 
1623
        </variablelist>
 
1624
      </sect2>
 
1625
    </sect1>
 
1626
 
 
1627
    <sect1>
 
1628
      <title>Building Indexes</title>
 
1629
 
 
1630
      <para>Indexes are what make using a spatial database for large data sets
 
1631
      possible. Without indexing, any search for a feature would require a
 
1632
      "sequential scan" of every record in the database. Indexing speeds up
 
1633
      searching by organizing the data into a search tree which can be quickly
 
1634
      traversed to find a particular record. PostgreSQL supports three kinds
 
1635
      of indexes by default: B-Tree indexes, R-Tree indexes, and GiST
 
1636
      indexes.</para>
 
1637
 
 
1638
      <itemizedlist>
 
1639
        <listitem>
 
1640
          <para>B-Trees are used for data which can be sorted along one axis;
 
1641
          for example, numbers, letters, dates. GIS data cannot be rationally
 
1642
          sorted along one axis (which is greater, (0,0) or (0,1) or (1,0)?)
 
1643
          so B-Tree indexing is of no use for us.</para>
 
1644
        </listitem>
 
1645
 
 
1646
        <listitem>
 
1647
          <para>R-Trees break up data into rectangles, and sub-rectangles, and
 
1648
          sub-sub rectangles, etc. R-Trees are used by some spatial databases
 
1649
          to index GIS data, but the PostgreSQL R-Tree implementation is not
 
1650
          as robust as the GiST implementation.</para>
 
1651
        </listitem>
 
1652
 
 
1653
        <listitem>
 
1654
          <para>GiST (Generalized Search Trees) indexes break up data into
 
1655
          "things to one side", "things which overlap", "things which are
 
1656
          inside" and can be used on a wide range of data-types, including GIS
 
1657
          data. PostGIS uses an R-Tree index implemented on top of GiST to
 
1658
          index GIS data.</para>
 
1659
        </listitem>
 
1660
      </itemizedlist>
 
1661
 
 
1662
      <sect2>
 
1663
        <title>GiST Indexes</title>
 
1664
 
 
1665
        <para>GiST stands for "Generalized Search Tree" and is a generic form
 
1666
        of indexing. In addition to GIS indexing, GiST is used to speed up
 
1667
        searches on all kinds of irregular data structures (integer arrays,
 
1668
        spectral data, etc) which are not amenable to normal B-Tree
 
1669
        indexing.</para>
 
1670
 
 
1671
        <para>Once a GIS data table exceeds a few thousand rows, you will want
 
1672
        to build an index to speed up spatial searches of the data (unless all
 
1673
        your searches are based on attributes, in which case you'll want to
 
1674
        build a normal index on the attribute fields).</para>
 
1675
 
 
1676
        <para>The syntax for building a GiST index on a "geometry" column is
 
1677
        as follows:</para>
 
1678
 
 
1679
        <para><programlisting>CREATE INDEX [indexname] ON [tablename] 
 
1680
  USING GIST ( [geometryfield] GIST_GEOMETRY_OPS ); </programlisting></para>
 
1681
 
 
1682
        <para>Building a spatial index is a computationally intensive
 
1683
        exercise: on tables of around 1 million rows, on a 300MHz Solaris
 
1684
        machine, we have found building a GiST index takes about 1 hour. After
 
1685
        building an index, it is important to force PostgreSQL to collect
 
1686
        table statistics, which are used to optimize query plans:</para>
 
1687
 
 
1688
        <para><programlisting>VACUUM ANALYZE [table_name] [column_name];
 
1689
 
 
1690
-- This is only needed for PostgreSQL 7.4 installations and below
 
1691
SELECT UPDATE_GEOMETRY_STATS([table_name], [column_name]);</programlisting></para>
 
1692
 
 
1693
        <para>GiST indexes have two advantages over R-Tree indexes in
 
1694
        PostgreSQL. Firstly, GiST indexes are "null safe", meaning they can
 
1695
        index columns which include null values. Secondly, GiST indexes
 
1696
        support the concept of "lossiness" which is important when dealing
 
1697
        with GIS objects larger than the PostgreSQL 8K page size. Lossiness
 
1698
        allows PostgreSQL to store only the "important" part of an object in
 
1699
        an index -- in the case of GIS objects, just the bounding box. GIS
 
1700
        objects larger than 8K will cause R-Tree indexes to fail in the
 
1701
        process of being built.</para>
 
1702
      </sect2>
 
1703
 
 
1704
      <sect2>
 
1705
        <title>Using Indexes</title>
 
1706
 
 
1707
        <para>Ordinarily, indexes invisibly speed up data access: once the
 
1708
        index is built, the query planner transparently decides when to use
 
1709
        index information to speed up a query plan. Unfortunately, the
 
1710
        PostgreSQL query planner does not optimize the use of GiST indexes
 
1711
        well, so sometimes searches which should use a spatial index instead
 
1712
        default to a sequence scan of the whole table.</para>
 
1713
 
 
1714
        <para>If you find your spatial indexes are not being used (or your
 
1715
        attribute indexes, for that matter) there are a couple things you can
 
1716
        do:</para>
 
1717
 
 
1718
        <itemizedlist>
 
1719
          <listitem>
 
1720
            <para>Firstly, make sure statistics are gathered about the number
 
1721
            and distributions of values in a table, to provide the query
 
1722
            planner with better information to make decisions around index
 
1723
            usage. For PostgreSQL 7.4 installations and below this is done by
 
1724
            running <command>update_geometry_stats([table_name,
 
1725
            column_name])</command> (compute distribution) and <command>VACUUM
 
1726
            ANALYZE [table_name] [column_name]</command> (compute number of
 
1727
            values). Starting with PostgreSQL 8.0 running <command>VACUUM
 
1728
            ANALYZE</command> will do both operations. You should regularly
 
1729
            vacuum your databases anyways -- many PostgreSQL DBAs have
 
1730
            <command>VACUUM</command> run as an off-peak cron job on a regular
 
1731
            basis.</para>
 
1732
          </listitem>
 
1733
 
 
1734
          <listitem>
 
1735
            <para>If vacuuming does not work, you can force the planner to use
 
1736
            the index information by using the <command>SET
 
1737
            ENABLE_SEQSCAN=OFF</command> command. You should only use this
 
1738
            command sparingly, and only on spatially indexed queries:
 
1739
            generally speaking, the planner knows better than you do about
 
1740
            when to use normal B-Tree indexes. Once you have run your query,
 
1741
            you should consider setting <varname>ENABLE_SEQSCAN</varname> back
 
1742
            on, so that other queries will utilize the planner as
 
1743
            normal.</para>
 
1744
 
 
1745
            <note>
 
1746
              <para>As of version 0.6, it should not be necessary to force the
 
1747
              planner to use the index with
 
1748
              <varname>ENABLE_SEQSCAN</varname>.</para>
 
1749
            </note>
 
1750
          </listitem>
 
1751
 
 
1752
          <listitem>
 
1753
            <para>If you find the planner wrong about the cost of sequencial
 
1754
            vs index scans try reducing the value of random_page_cost in
 
1755
            postgresql.conf or using SET random_page_cost=#. Default value for
 
1756
            the parameter is 4, try setting it to 1 or 2. Decrementing the
 
1757
            value makes the planner more inclined of using Index scans.</para>
 
1758
          </listitem>
 
1759
        </itemizedlist>
 
1760
      </sect2>
 
1761
    </sect1>
 
1762
 
 
1763
    <sect1>
 
1764
      <title>Complex Queries</title>
 
1765
 
 
1766
      <para>The <emphasis>raison d'etre</emphasis> of spatial database
 
1767
      functionality is performing queries inside the database which would
 
1768
      ordinarily require desktop GIS functionality. Using PostGIS effectively
 
1769
      requires knowing what spatial functions are available, and ensuring that
 
1770
      appropriate indexes are in place to provide good performance.</para>
 
1771
 
 
1772
      <sect2>
 
1773
        <title>Taking Advantage of Indexes</title>
 
1774
 
 
1775
        <para>When constructing a query it is important to remember that only
 
1776
        the bounding-box-based operators such as &amp;&amp; can take advatage
 
1777
        of the GiST spatial index. Functions such as
 
1778
        <varname>distance()</varname> cannot use the index to optimize their
 
1779
        operation. For example, the following query would be quite slow on a
 
1780
        large table:</para>
 
1781
 
 
1782
        <programlisting>SELECT the_geom FROM geom_table
 
1783
WHERE distance( the_geom, GeomFromText( 'POINT(100000 200000)', -1 ) ) &lt; 100</programlisting>
 
1784
 
 
1785
        <para>This query is selecting all the geometries in geom_table which
 
1786
        are within 100 units of the point (100000, 200000). It will be slow
 
1787
        because it is calculating the distance between each point in the table
 
1788
        and our specified point, ie. one <varname>distance()</varname>
 
1789
        calculation for each row in the table. We can avoid this by using the
 
1790
        &amp;&amp; operator to reduce the number of distance calculations
 
1791
        required:</para>
 
1792
 
 
1793
        <programlisting>SELECT the_geom FROM geom_table
 
1794
WHERE the_geom &amp;&amp; 'BOX3D(90900 190900, 100100 200100)'::box3d
 
1795
  AND distance( the_geom, GeomFromText( 'POINT(100000 200000)', -1 ) ) &lt; 100</programlisting>
 
1796
 
 
1797
        <para>This query selects the same geometries, but it does it in a more
 
1798
        efficient way. Assuming there is a GiST index on the_geom, the query
 
1799
        planner will recognize that it can use the index to reduce the number
 
1800
        of rows before calculating the result of the
 
1801
        <varname>distance()</varname> function. Notice that the
 
1802
        <varname>BOX3D</varname> geometry which is used in the &amp;&amp;
 
1803
        operation is a 200 unit square box centered on the original point -
 
1804
        this is our "query box". The &amp;&amp; operator uses the index to
 
1805
        quickly reduce the result set down to only those geometries which have
 
1806
        bounding boxes that overlap the "query box". Assuming that our query
 
1807
        box is much smaller than the extents of the entire geometry table,
 
1808
        this will drastically reduce the number of distance calculations that
 
1809
        need to be done.</para>
 
1810
      </sect2>
 
1811
 
 
1812
      <sect2>
 
1813
        <title>Examples of Spatial SQL</title>
 
1814
 
 
1815
        <para>The examples in this section will make use of two tables, a
 
1816
        table of linear roads, and a table of polygonal municipality
 
1817
        boundaries. The table definitions for the <varname>bc_roads</varname>
 
1818
        table is:</para>
 
1819
 
 
1820
        <programlisting>  Column    |       Type        |   Description
 
1821
------------+-------------------+-------------------
 
1822
 gid        | integer           | Unique ID
 
1823
 name       | character varying | Road Name
 
1824
 the_geom   | geometry          | Location Geometry (Linestring)</programlisting>
 
1825
 
 
1826
        <para>The table definition for the <varname>bc_municipality</varname>
 
1827
        table is:</para>
 
1828
 
 
1829
        <programlisting>  Column   |       Type        |   Description
 
1830
-----------+-------------------+-------------------
 
1831
 gid       | integer           | Unique ID
 
1832
 code      | integer           | Unique ID
 
1833
 name      | character varying | City / Town Name
 
1834
 the_geom  | geometry          | Location Geometry (Polygon)</programlisting>
 
1835
 
 
1836
        <qandaset>
 
1837
          <qandadiv>
 
1838
            <qandaentry>
 
1839
              <question>
 
1840
                <para>What is the total length of all roads, expressed in
 
1841
                kilometers?</para>
 
1842
              </question>
 
1843
 
 
1844
              <answer>
 
1845
                <para>You can answer this question with a very simple piece of
 
1846
                SQL:</para>
 
1847
 
 
1848
                <programlisting>postgis=# SELECT sum(length(the_geom))/1000 AS km_roads FROM bc_roads;
 
1849
     km_roads
 
1850
------------------
 
1851
 70842.1243039643
 
1852
(1 row)</programlisting>
 
1853
              </answer>
 
1854
            </qandaentry>
 
1855
 
 
1856
            <qandaentry>
 
1857
              <question>
 
1858
                <para>How large is the city of Prince George, in
 
1859
                hectares?</para>
 
1860
              </question>
 
1861
 
 
1862
              <answer>
 
1863
                <para>This query combines an attribute condition (on the
 
1864
                municipality name) with a spatial calculation (of the
 
1865
                area):</para>
 
1866
 
 
1867
                <programlisting>postgis=# SELECT area(the_geom)/10000 AS hectares FROM bc_municipality 
 
1868
          WHERE name = 'PRINCE GEORGE';
 
1869
     hectares
 
1870
------------------
 
1871
 32657.9103824927
 
1872
(1 row) </programlisting>
 
1873
              </answer>
 
1874
            </qandaentry>
 
1875
 
 
1876
            <qandaentry>
 
1877
              <question>
 
1878
                <para>What is the largest municipality in the province, by
 
1879
                area?</para>
 
1880
              </question>
 
1881
 
 
1882
              <answer>
 
1883
                <para>This query brings a spatial measurement into the query
 
1884
                condition. There are several ways of approaching this problem,
 
1885
                but the most efficient is below:</para>
 
1886
 
 
1887
                <programlisting>postgis=# SELECT name, area(the_geom)/10000 AS hectares 
 
1888
          FROM bc_municipality 
 
1889
          ORDER BY hectares DESC 
 
1890
          LIMIT 1;
 
1891
     name      |    hectares
 
1892
---------------+-----------------
 
1893
 TUMBLER RIDGE | 155020.02556131
 
1894
(1 row)</programlisting>
 
1895
 
 
1896
                <para>Note that in order to answer this query we have to
 
1897
                calculate the area of every polygon. If we were doing this a
 
1898
                lot it would make sense to add an area column to the table
 
1899
                that we could separately index for performance. By ordering
 
1900
                the results in a descending direction, and them using the
 
1901
                PostgreSQL "LIMIT" command we can easily pick off the largest
 
1902
                value without using an aggregate function like max().</para>
 
1903
              </answer>
 
1904
            </qandaentry>
 
1905
 
 
1906
            <qandaentry>
 
1907
              <question>
 
1908
                <para>What is the length of roads fully contained within each
 
1909
                municipality?</para>
 
1910
              </question>
 
1911
 
 
1912
              <answer>
 
1913
                <para>This is an example of a "spatial join", because we are
 
1914
                bringing together data from two tables (doing a join) but
 
1915
                using a spatial interaction condition ("contained") as the
 
1916
                join condition rather than the usual relational approach of
 
1917
                joining on a common key:</para>
 
1918
 
 
1919
                <programlisting>postgis=# SELECT m.name, sum(length(r.the_geom))/1000 as roads_km 
 
1920
          FROM bc_roads AS r,bc_municipality AS m 
 
1921
          WHERE r.the_geom &amp;&amp; m.the_geom 
 
1922
          AND contains(m.the_geom,r.the_geom) 
 
1923
          GROUP BY m.name 
 
1924
          ORDER BY roads_km;
 
1925
 
 
1926
            name            |     roads_km
 
1927
----------------------------+------------------
 
1928
 SURREY                     | 1539.47553551242
 
1929
 VANCOUVER                  | 1450.33093486576
 
1930
 LANGLEY DISTRICT           | 833.793392535662
 
1931
 BURNABY                    | 773.769091404338
 
1932
 PRINCE GEORGE              |  694.37554369147
 
1933
 ...</programlisting>
 
1934
 
 
1935
                <para>This query takes a while, because every road in the
 
1936
                table is summarized into the final result (about 250K roads
 
1937
                for our particular example table). For smaller overlays
 
1938
                (several thousand records on several hundred) the response can
 
1939
                be very fast.</para>
 
1940
              </answer>
 
1941
            </qandaentry>
 
1942
 
 
1943
            <qandaentry>
 
1944
              <question>
 
1945
                <para>Create a new table with all the roads within the city of
 
1946
                Prince George.</para>
 
1947
              </question>
 
1948
 
 
1949
              <answer>
 
1950
                <para>This is an example of an "overlay", which takes in two
 
1951
                tables and outputs a new table that consists of spatially
 
1952
                clipped or cut resultants. Unlike the "spatial join"
 
1953
                demonstrated above, this query actually creates new
 
1954
                geometries. An overlay is like a turbo-charged spatial join,
 
1955
                and is useful for more exact analysis work:</para>
 
1956
 
 
1957
                <programlisting>postgis=# CREATE TABLE pg_roads as
 
1958
          SELECT intersection(r.the_geom, m.the_geom) AS intersection_geom, 
 
1959
                 length(r.the_geom) AS rd_orig_length, 
 
1960
                 r.* 
 
1961
          FROM bc_roads AS r, bc_municipality AS m 
 
1962
          WHERE r.the_geom &amp;&amp; m.the_geom 
 
1963
          AND intersects(r.the_geom, m.the_geom) 
 
1964
          AND m.name = 'PRINCE GEORGE';</programlisting>
 
1965
              </answer>
 
1966
            </qandaentry>
 
1967
 
 
1968
            <qandaentry>
 
1969
              <question>
 
1970
                <para>What is the length in kilometers of "Douglas St" in
 
1971
                Victoria?</para>
 
1972
              </question>
 
1973
 
 
1974
              <answer>
 
1975
                <programlisting>postgis=# SELECT sum(length(r.the_geom))/1000 AS kilometers 
 
1976
          FROM bc_roads r, bc_municipality m 
 
1977
          WHERE r.the_geom &amp;&amp; m.the_geom 
 
1978
          AND r.name = 'Douglas St' 
 
1979
          AND m.name = 'VICTORIA';
 
1980
    kilometers
 
1981
------------------
 
1982
 4.89151904172838
 
1983
(1 row)</programlisting>
 
1984
              </answer>
 
1985
            </qandaentry>
 
1986
 
 
1987
            <qandaentry>
 
1988
              <question>
 
1989
                <para>What is the largest municipality polygon that has a
 
1990
                hole?</para>
 
1991
              </question>
 
1992
 
 
1993
              <answer>
 
1994
                <programlisting>postgis=# SELECT gid, name, area(the_geom) AS area 
 
1995
          FROM bc_municipality 
 
1996
          WHERE nrings(the_geom) &gt; 1 
 
1997
          ORDER BY area DESC LIMIT 1;
 
1998
 gid |     name     |       area
 
1999
-----+--------------+------------------
 
2000
  12 | SPALLUMCHEEN | 257374619.430216
 
2001
(1 row)</programlisting>
 
2002
              </answer>
 
2003
            </qandaentry>
 
2004
          </qandadiv>
 
2005
        </qandaset>
 
2006
      </sect2>
 
2007
    </sect1>
 
2008
 
 
2009
    <sect1>
 
2010
      <title>Using Mapserver</title>
 
2011
 
 
2012
      <para>The Minnesota Mapserver is an internet web-mapping server which
 
2013
      conforms to the OpenGIS Web Mapping Server specification.</para>
 
2014
 
 
2015
      <itemizedlist>
 
2016
        <listitem>
 
2017
          <para>The Mapserver homepage is at <ulink
 
2018
          url="http://mapserver.gis.umn.edu">http://mapserver.gis.umn.edu</ulink>.</para>
 
2019
        </listitem>
 
2020
 
 
2021
        <listitem>
 
2022
          <para>The OpenGIS Web Map Specification is at <ulink
 
2023
          url="http://www.opengis.org/techno/specs/01-047r2.pdf">http://www.opengis.org/techno/specs/01-047r2.pdf</ulink>.</para>
 
2024
        </listitem>
 
2025
      </itemizedlist>
 
2026
 
 
2027
      <sect2>
 
2028
        <title>Basic Usage</title>
 
2029
 
 
2030
        <para>To use PostGIS with Mapserver, you will need to know about how
 
2031
        to configure Mapserver, which is beyond the scope of this
 
2032
        documentation. This section will cover specific PostGIS issues and
 
2033
        configuration details.</para>
 
2034
 
 
2035
        <para>To use PostGIS with Mapserver, you will need:</para>
 
2036
 
 
2037
        <itemizedlist>
 
2038
          <listitem>
 
2039
            <para>Version 0.6 or newer of PostGIS.</para>
 
2040
          </listitem>
 
2041
 
 
2042
          <listitem>
 
2043
            <para>Version 3.5 or newer of Mapserver.</para>
 
2044
          </listitem>
 
2045
        </itemizedlist>
 
2046
 
 
2047
        <para>Mapserver accesses PostGIS/PostgreSQL data like any other
 
2048
        PostgreSQL client -- using <filename>libpq</filename>. This means that
 
2049
        Mapserver can be installed on any machine with network access to the
 
2050
        PostGIS server, as long as the system has the
 
2051
        <filename>libpq</filename> PostgreSQL client libraries.</para>
 
2052
 
 
2053
        <orderedlist>
 
2054
          <listitem>
 
2055
            <para>Compile and install Mapserver, with whatever options you
 
2056
            desire, including the "--with-postgis" configuration
 
2057
            option.</para>
 
2058
          </listitem>
 
2059
 
 
2060
          <listitem>
 
2061
            <para>In your Mapserver map file, add a PostGIS layer. For
 
2062
            example:</para>
 
2063
 
 
2064
            <programlisting>LAYER
 
2065
  CONNECTIONTYPE postgis
 
2066
  NAME "widehighways"
 
2067
  # Connect to a remote spatial database
 
2068
  CONNECTION "user=dbuser dbname=gisdatabase host=bigserver"
 
2069
  # Get the lines from the 'geom' column of the 'roads' table
 
2070
  DATA "geom from roads"
 
2071
  STATUS ON
 
2072
  TYPE LINE
 
2073
  # Of the lines in the extents, only render the wide highways
 
2074
  FILTER "type = 'highway' and numlanes &gt;= 4"
 
2075
  CLASS
 
2076
    # Make the superhighways brighter and 2 pixels wide
 
2077
    EXPRESSION ([numlanes] &gt;= 6)
 
2078
    COLOR 255 22 22      
 
2079
    SYMBOL "solid"
 
2080
    SIZE 2
 
2081
  END
 
2082
  CLASS
 
2083
    # All the rest are darker and only 1 pixel wide
 
2084
    EXPRESSION ([numlanes] &lt; 6)
 
2085
    COLOR 205 92 82      
 
2086
  END
 
2087
END</programlisting>
 
2088
 
 
2089
            <para>In the example above, the PostGIS-specific directives are as
 
2090
            follows:</para>
 
2091
 
 
2092
            <variablelist>
 
2093
              <varlistentry>
 
2094
                <term>CONNECTIONTYPE</term>
 
2095
 
 
2096
                <listitem>
 
2097
                  <para>For PostGIS layers, this is always "postgis".</para>
 
2098
                </listitem>
 
2099
              </varlistentry>
 
2100
 
 
2101
              <varlistentry>
 
2102
                <term>CONNECTION</term>
 
2103
 
 
2104
                <listitem>
 
2105
                  <para>The database connection is governed by the a
 
2106
                  'connection string' which is a standard set of keys and
 
2107
                  values like this (with the default values in
 
2108
                  &lt;&gt;):</para>
 
2109
 
 
2110
                  <para>user=&lt;username&gt; password=&lt;password&gt;
 
2111
                  dbname=&lt;username&gt; hostname=&lt;server&gt;
 
2112
                  port=&lt;5432&gt;</para>
 
2113
 
 
2114
                  <para>An empty connection string is still valid, and any of
 
2115
                  the key/value pairs can be omitted. At a minimum you will
 
2116
                  generally supply the database name and username to connect
 
2117
                  with.</para>
 
2118
                </listitem>
 
2119
              </varlistentry>
 
2120
 
 
2121
              <varlistentry>
 
2122
                <term>DATA</term>
 
2123
 
 
2124
                <listitem>
 
2125
                  <para>The form of this parameter is "&lt;column&gt; from
 
2126
                  &lt;tablename&gt;" where the column is the spatial column to
 
2127
                  be rendered to the map.</para>
 
2128
                </listitem>
 
2129
              </varlistentry>
 
2130
 
 
2131
              <varlistentry>
 
2132
                <term>FILTER</term>
 
2133
 
 
2134
                <listitem>
 
2135
                  <para>The filter must be a valid SQL string corresponding to
 
2136
                  the logic normally following the "WHERE" keyword in a SQL
 
2137
                  query. So, for example, to render only roads with 6 or more
 
2138
                  lanes, use a filter of "num_lanes &gt;= 6".</para>
 
2139
                </listitem>
 
2140
              </varlistentry>
 
2141
            </variablelist>
 
2142
          </listitem>
 
2143
 
 
2144
          <listitem>
 
2145
            <para>In your spatial database, ensure you have spatial (GiST)
 
2146
            indexes built for any the layers you will be drawing.</para>
 
2147
 
 
2148
            <programlisting>CREATE INDEX [indexname]
 
2149
  ON [tablename] 
 
2150
  USING GIST ( [geometrycolumn] GIST_GEOMETRY_OPS );</programlisting>
 
2151
          </listitem>
 
2152
 
 
2153
          <listitem>
 
2154
            <para>If you will be querying your layers using Mapserver you will
 
2155
            also need an "oid index".</para>
 
2156
 
 
2157
            <para>Mapserver requires unique identifiers for each spatial
 
2158
            record when doing queries, and the PostGIS module of Mapserver
 
2159
            uses the PostgreSQL <varname>oid</varname> value to provide these
 
2160
            unique identifiers. A side-effect of this is that in order to do
 
2161
            fast random access of records during queries, an index on the
 
2162
            <varname>oid</varname> is needed.</para>
 
2163
 
 
2164
            <para>To build an "oid index", use the following SQL:</para>
 
2165
 
 
2166
            <programlisting>CREATE INDEX [indexname] ON [tablename] ( oid );</programlisting>
 
2167
          </listitem>
 
2168
        </orderedlist>
 
2169
      </sect2>
 
2170
 
 
2171
      <sect2>
 
2172
        <title>Frequently Asked Questions</title>
 
2173
 
 
2174
        <qandaset>
 
2175
          <qandadiv>
 
2176
            <qandaentry>
 
2177
              <question>
 
2178
                <para>When I use an <varname>EXPRESSION</varname> in my map
 
2179
                file, the condition never returns as true, even though I know
 
2180
                the values exist in my table.</para>
 
2181
              </question>
 
2182
 
 
2183
              <answer>
 
2184
                <para>Unlike shape files, PostGIS field names have to be
 
2185
                referenced in EXPRESSIONS using <emphasis>lower
 
2186
                case</emphasis>.</para>
 
2187
 
 
2188
                <programlisting>EXPRESSION ([numlanes] &gt;= 6)</programlisting>
 
2189
              </answer>
 
2190
            </qandaentry>
 
2191
 
 
2192
            <qandaentry>
 
2193
              <question>
 
2194
                <para>The FILTER I use for my Shape files is not working for
 
2195
                my PostGIS table of the same data.</para>
 
2196
              </question>
 
2197
 
 
2198
              <answer>
 
2199
                <para>Unlike shape files, filters for PostGIS layers use SQL
 
2200
                syntax (they are appended to the SQL statement the PostGIS
 
2201
                connector generates for drawing layers in Mapserver).</para>
 
2202
 
 
2203
                <programlisting>FILTER "type = 'highway' and numlanes &gt;= 4"</programlisting>
 
2204
              </answer>
 
2205
            </qandaentry>
 
2206
 
 
2207
            <qandaentry>
 
2208
              <question>
 
2209
                <para>My PostGIS layer draws much slower than my Shape file
 
2210
                layer, is this normal?</para>
 
2211
              </question>
 
2212
 
 
2213
              <answer>
 
2214
                <para>In general, expect PostGIS layers to be 10% slower than
 
2215
                equivalent Shape files layers, due to the extra overhead
 
2216
                involved in database connections, data transformations and
 
2217
                data transit between the database and Mapserver.</para>
 
2218
 
 
2219
                <para>If you are finding substantial draw performance
 
2220
                problems, it is likely that you have not build a spatial index
 
2221
                on your table.</para>
 
2222
 
 
2223
                <programlisting>postgis# CREATE INDEX geotable_gix ON geotable USING GIST ( geocolumn );
 
2224
postgis# SELECT update_geometry_stats();  -- For PGSQL &lt; 8.0
 
2225
postgis# VACUUM ANALYZE;                  -- For PGSQL &gt;= 8.0</programlisting>
 
2226
              </answer>
 
2227
            </qandaentry>
 
2228
 
 
2229
            <qandaentry>
 
2230
              <question>
 
2231
                <para>My PostGIS layer draws fine, but queries are really
 
2232
                slow. What is wrong?</para>
 
2233
              </question>
 
2234
 
 
2235
              <answer>
 
2236
                <para>For queries to be fast, you must have a unique key for
 
2237
                your spatial table and you must have an index on that unique
 
2238
                key.</para>
 
2239
 
 
2240
                <para>You can specify what unique key for mapserver to use
 
2241
                with the <varname>USING UNIQUE</varname> clause in your
 
2242
                <varname>DATA</varname> line:</para>
 
2243
 
 
2244
                <programlisting>DATA "the_geom FROM geotable USING UNIQUE gid"</programlisting>
 
2245
 
 
2246
                <para>If your table does not have an explicit unique column,
 
2247
                you can "fake" a unique column by using the PostgreSQL row
 
2248
                "oid" for your unique column. "oid" is the default unique
 
2249
                column if you do not declare one, so enhancing your query
 
2250
                speed is a matter of building an index on your spatial table
 
2251
                oid value.</para>
 
2252
 
 
2253
                <programlisting>postgis# CREATE INDEX geotable_oid_idx ON geotable (oid);</programlisting>
 
2254
              </answer>
 
2255
            </qandaentry>
 
2256
          </qandadiv>
 
2257
        </qandaset>
 
2258
      </sect2>
 
2259
 
 
2260
      <sect2>
 
2261
        <title>Advanced Usage</title>
 
2262
 
 
2263
        <para>The <varname>USING</varname> pseudo-SQL clause is used to add
 
2264
        some information to help mapserver understand the results of more
 
2265
        complex queries. More specifically, when either a view or a subselect
 
2266
        is used as the source table (the thing to the right of "FROM" in a
 
2267
        <varname>DATA</varname> definition) it is more difficult for mapserver
 
2268
        to automatically determine a unique identifier for each row and also
 
2269
        the SRID for the table. The <varname>USING</varname> clause can
 
2270
        provide mapserver with these two pieces of information as
 
2271
        follows:</para>
 
2272
 
 
2273
        <programlisting>DATA "the_geom FROM (SELECT table1.the_geom AS the_geom, table1.oid AS oid, table2.data AS data
 
2274
 FROM table1 LEFT JOIN table2 ON table1.id = table2.id) AS new_table USING UNIQUE oid USING SRID=-1"</programlisting>
 
2275
 
 
2276
        <variablelist>
 
2277
          <varlistentry>
 
2278
            <term>USING UNIQUE &lt;uniqueid&gt;</term>
 
2279
 
 
2280
            <listitem>
 
2281
              <para>Mapserver requires a unique id for each row in order to
 
2282
              identify the row when doing map queries. Normally, it would use
 
2283
              the oid as the unique identifier, but views and subselects don't
 
2284
              automatically have an oid column. If you want to use Mapserver's
 
2285
              query functionality, you need to add a unique column to your
 
2286
              view or subselect, and declare it with <varname>USING
 
2287
              UNIQUE</varname>. For example, you could explicitly select one
 
2288
              of the table's oid values for this purpose, or any other column
 
2289
              which is guaranteed to be unique for the result set.</para>
 
2290
 
 
2291
              <para>The <varname>USING</varname> statement can also be useful
 
2292
              even for simple <varname>DATA</varname> statements, if you are
 
2293
              doing map queries. It was previously recommended to add an index
 
2294
              on the oid column of tables used in query-able layers, in order
 
2295
              to speed up the performance of map queries. However, with the
 
2296
              <varname>USING</varname> clause, it is possible to tell
 
2297
              mapserver to use your table's primary key as the identifier for
 
2298
              map queries, and then it is no longer necessary to have an
 
2299
              additional index.</para>
 
2300
 
 
2301
              <note>
 
2302
                <para>"Querying a Map" is the action of clicking on a map to
 
2303
                ask for information about the map features in that location.
 
2304
                Don't confuse "map queries" with the SQL query in a
 
2305
                <varname>DATA</varname> definition.</para>
 
2306
              </note>
 
2307
            </listitem>
 
2308
          </varlistentry>
 
2309
 
 
2310
          <varlistentry>
 
2311
            <term>USING SRID=&lt;srid&gt;</term>
 
2312
 
 
2313
            <listitem>
 
2314
              <para>PostGIS needs to know which spatial referencing system is
 
2315
              being used by the geometries in order to return the correct data
 
2316
              back to mapserver. Normally it is possible to find this
 
2317
              information in the "geometry_columns" table in the PostGIS
 
2318
              database, however, this is not possible for tables which are
 
2319
              created on the fly such as subselects and views. So the
 
2320
              <varname>USING SRID=</varname> option allows the correct SRID to
 
2321
              be specified in the <varname>DATA</varname> definition.</para>
 
2322
            </listitem>
 
2323
          </varlistentry>
 
2324
        </variablelist>
 
2325
 
 
2326
        <warning>
 
2327
          <para>The parser for Mapserver PostGIS layers is fairly primitive,
 
2328
          and is case sensitive in a few areas. Be careful to ensure that all
 
2329
          SQL keywords and all your <varname>USING</varname> clauses are in
 
2330
          upper case, and that your <varname>USING UNIQUE</varname> clause
 
2331
          precedes your <varname>USING SRID</varname> clause.</para>
 
2332
        </warning>
 
2333
      </sect2>
 
2334
 
 
2335
      <sect2>
 
2336
        <title>Examples</title>
 
2337
 
 
2338
        <para>Lets start with a simple example and work our way up. Consider
 
2339
        the following Mapserver layer definition:</para>
 
2340
 
 
2341
        <programlisting>LAYER
 
2342
 CONNECTIONTYPE postgis
 
2343
 NAME "roads"
 
2344
 CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
 
2345
 DATA "the_geom FROM roads"
 
2346
 STATUS ON
 
2347
 TYPE LINE
 
2348
 CLASS
 
2349
  COLOR 0 0 0
 
2350
 END
 
2351
END</programlisting>
 
2352
 
 
2353
        <para>This layer will display all the road geometries in the roads
 
2354
        table as black lines.</para>
 
2355
 
 
2356
        <para>Now lets say we want to show only the highways until we get
 
2357
        zoomed in to at least a 1:100000 scale - the next two layers will
 
2358
        acheive this effect:</para>
 
2359
 
 
2360
        <programlisting>LAYER
 
2361
 CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
 
2362
 DATA "the_geom FROM roads"
 
2363
 MINSCALE 100000
 
2364
 STATUS ON
 
2365
 TYPE LINE
 
2366
 FILTER "road_type = 'highway'"
 
2367
 CLASS
 
2368
  COLOR 0 0 0
 
2369
 END
 
2370
END
 
2371
 
 
2372
LAYER
 
2373
 CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
 
2374
 DATA "the_geom FROM roads"
 
2375
 MAXSCALE 100000
 
2376
 STATUS ON
 
2377
 TYPE LINE
 
2378
 CLASSITEM road_type
 
2379
 CLASS
 
2380
  EXPRESSION "highway"
 
2381
  SIZE 2
 
2382
  COLOR 255 0 0
 
2383
 END
 
2384
 CLASS
 
2385
  COLOR 0 0 0
 
2386
 END
 
2387
END</programlisting>
 
2388
 
 
2389
        <para>The first layer is used when the scale is greater than 1:100000,
 
2390
        and displays only the roads of type "highway" as black lines. The
 
2391
        <varname>FILTER</varname> option causes only roads of type "highway"
 
2392
        to be displayed.</para>
 
2393
 
 
2394
        <para>The second layer is used when the scale is less than 1:100000,
 
2395
        and will display highways as double-thick red lines, and other roads
 
2396
        as regular black lines.</para>
 
2397
 
 
2398
        <para>So, we have done a couple of interesting things using only
 
2399
        mapserver functionality, but our <varname>DATA</varname> SQL statement
 
2400
        has remained simple. Suppose that the name of the road is stored in
 
2401
        another table (for whatever reason) and we need to do a join to get it
 
2402
        and label our roads.</para>
 
2403
 
 
2404
        <programlisting>LAYER
 
2405
 CONNECTION "user=theuser password=thepass dbname=thedb host=theserver"
 
2406
 DATA "the_geom FROM (SELECT roads.oid AS oid, roads.the_geom AS the_geom, road_names.name as name
 
2407
   FROM roads LEFT JOIN road_names ON roads.road_name_id = road_names.road_name_id) AS named_roads
 
2408
   USING UNIQUE oid USING SRID=-1"
 
2409
 MAXSCALE 20000
 
2410
 STATUS ON
 
2411
 TYPE ANNOTATION
 
2412
 LABELITEM name
 
2413
 CLASS
 
2414
  LABEL
 
2415
   ANGLE auto
 
2416
   SIZE 8
 
2417
   COLOR 0 192 0
 
2418
   TYPE truetype
 
2419
   FONT arial
 
2420
  END
 
2421
 END
 
2422
END</programlisting>
 
2423
 
 
2424
        <para>This annotation layer adds green labels to all the roads when
 
2425
        the scale gets down to 1:20000 or less. It also demonstrates how to
 
2426
        use an SQL join in a <varname>DATA</varname> definition.</para>
 
2427
      </sect2>
 
2428
    </sect1>
 
2429
 
 
2430
    <sect1>
 
2431
      <title>Java Clients (JDBC)</title>
 
2432
 
 
2433
      <para>Java clients can access PostGIS "geometry" objects in the
 
2434
      PostgreSQL database either directly as text representations or using the
 
2435
      JDBC extension objects bundled with PostGIS. In order to use the
 
2436
      extension objects, the "postgis.jar" file must be in your CLASSPATH
 
2437
      along with the "postgresql.jar" JDBC driver package.</para>
 
2438
 
 
2439
      <programlisting>import java.sql.*; 
 
2440
import java.util.*; 
 
2441
import java.lang.*; 
 
2442
import org.postgis.*; 
 
2443
 
 
2444
public class JavaGIS { 
 
2445
  public static void main(String[] args) 
 
2446
  { 
 
2447
    java.sql.Connection conn; 
 
2448
    try 
 
2449
    { 
 
2450
      /* 
 
2451
      * Load the JDBC driver and establish a connection. 
 
2452
      */  
 
2453
      Class.forName("org.postgresql.Driver"); 
 
2454
      String url = "jdbc:postgresql://localhost:5432/database"; 
 
2455
      conn = DriverManager.getConnection(url, "postgres", ""); 
 
2456
    
 
2457
      /* 
 
2458
      * Add the geometry types to the connection. Note that you 
 
2459
      * must cast the connection to the pgsql-specific connection * implementation before calling the addDataType() method. 
 
2460
      */
 
2461
      ((org.postgresql.Connection)conn).addDataType("geometry","org.postgis.PGgeometry");
 
2462
      ((org.postgresql.Connection)conn).addDataType("box3d","org.postgis.PGbox3d");
 
2463
 
 
2464
      /* 
 
2465
      * Create a statement and execute a select query. 
 
2466
      */ 
 
2467
      Statement s = conn.createStatement(); 
 
2468
      ResultSet r = s.executeQuery("select AsText(geom) as geom,id from geomtable"); 
 
2469
      while( r.next() ) 
 
2470
      { 
 
2471
        /* 
 
2472
        * Retrieve the geometry as an object then cast it to the geometry type. 
 
2473
        * Print things out. 
 
2474
        */ 
 
2475
        PGgeometry geom = (PGgeometry)r.getObject(1); 
 
2476
        int id = r.getInt(2);
 
2477
        System.out.println("Row " + id + ":"); 
 
2478
        System.out.println(geom.toString()); 
 
2479
      }
 
2480
      s.close(); 
 
2481
      conn.close(); 
 
2482
    } 
 
2483
    catch( Exception e ) 
 
2484
    { 
 
2485
      e.printStackTrace(); 
 
2486
    }  
 
2487
  }
 
2488
}</programlisting>
 
2489
 
 
2490
      <para>The "PGgeometry" object is a wrapper object which contains a
 
2491
      specific topological geometry object (subclasses of the abstract class
 
2492
      "Geometry") depending on the type: Point, LineString, Polygon,
 
2493
      MultiPoint, MultiLineString, MultiPolygon.</para>
 
2494
 
 
2495
      <programlisting>PGgeometry geom = (PGgeometry)r.getObject(1); 
 
2496
if( geom.getType() = Geometry.POLYGON ) 
 
2497
 
2498
  Polygon pl = (Polygon)geom.getGeometry();
 
2499
  for( int r = 0; r &lt; pl.numRings(); r++ ) 
 
2500
  { 
 
2501
    LinearRing rng = pl.getRing(r);
 
2502
    System.out.println("Ring: " + r); 
 
2503
    for( int p = 0; p &lt; rng.numPoints(); p++ ) 
 
2504
    { 
 
2505
      Point pt = rng.getPoint(p); 
 
2506
      System.out.println("Point: " + p);
 
2507
      System.out.println(pt.toString()); 
 
2508
    } 
 
2509
  } 
 
2510
}</programlisting>
 
2511
 
 
2512
      <para>The JavaDoc for the extension objects provides a reference for the
 
2513
      various data accessor functions in the geometric objects.</para>
 
2514
    </sect1>
 
2515
 
 
2516
    <sect1>
 
2517
      <title>C Clients (libpq)</title>
 
2518
 
 
2519
      <para>...</para>
 
2520
 
 
2521
      <sect2>
 
2522
        <title>Text Cursors</title>
 
2523
 
 
2524
        <para>...</para>
 
2525
      </sect2>
 
2526
 
 
2527
      <sect2>
 
2528
        <title>Binary Cursors</title>
 
2529
 
 
2530
        <para>...</para>
 
2531
      </sect2>
 
2532
    </sect1>
 
2533
  </chapter>
 
2534
 
 
2535
<chapter> <title>Performance tips</title>
 
2536
 
 
2537
<sect1> <title>Small tables of large geometries</title>
 
2538
 
 
2539
<sect2><title>Problem description</title>
 
2540
 
 
2541
<para>
 
2542
Current PostgreSQL versions (including 8.0) suffer from a query
 
2543
optimizer weakness regarding TOAST tables. TOAST tables are a kind of
 
2544
"extension room" used to store large (in the sense of data size) values
 
2545
that do not fit into normal data pages (like long texts, images or
 
2546
complex geometries with lots of vertices), see
 
2547
http://www.postgresql.org/docs/8.0/static/storage-toast.html for more
 
2548
information).
 
2549
</para>
 
2550
 
 
2551
<para>
 
2552
The problem appears if you happen to have a table with rather large
 
2553
geometries, but not too much rows of them (like a table containing the
 
2554
boundaries of all european countries in high resolution). Then the table
 
2555
itsself is small, but it uses lots of TOAST space. In our example case,
 
2556
the table itsself had about 80 rows and used only 3 data pages, but the
 
2557
TOAST table used 8225 pages.
 
2558
</para>
 
2559
 
 
2560
<para>
 
2561
Now issue a query where you use the geometry operator &amp;&amp; to search for a
 
2562
bounding box that matches only very few of those rows. Now the query
 
2563
optimizer sees that the table has only 3 pages and 80 rows. He estimates
 
2564
that a sequential scan on such a small table is much faster than using
 
2565
an index. And so he decides to ignore the GIST index. Usually, this
 
2566
estimation is correct. But in our case, the &amp;&amp; operator has to fetch
 
2567
every geometry from disk to compare the bounding boxes, thus reading all
 
2568
TOAST pages, too.
 
2569
</para>
 
2570
 
 
2571
<para>
 
2572
To see whether your suffer from this bug, use the "EXPLAIN ANALYZE"
 
2573
postgresql command. For more information and the technical details, you
 
2574
can read the thread on the postgres performance mailing list:
 
2575
http://archives.postgresql.org/pgsql-performance/2005-02/msg00030.php
 
2576
</para>
 
2577
 
 
2578
</sect2>
 
2579
 
 
2580
<sect2><title>Workarounds</title>
 
2581
 
 
2582
<para>
 
2583
The PostgreSQL people are trying to solve this issue by making the query
 
2584
estimation TOAST-aware. For now, here are two workarounds:
 
2585
</para>
 
2586
 
 
2587
<para>
 
2588
The first workaround is to force the query planner to use the index.
 
2589
Send "SET enable_seqscan TO off;" to the server before issuing the
 
2590
query. This basically forces the query planner to avoid sequential scans
 
2591
whenever possible. So it uses the GIST index as usual. But this flag has
 
2592
to be set on every connection, and it causes the query planner to make
 
2593
misestimations in other cases, so you should "SET enable_seqscan TO on;"
 
2594
after the query.
 
2595
</para>
 
2596
 
 
2597
<para>
 
2598
The second workaround is to make the sequential scan as fast as the
 
2599
query planner thinks. This can be achieved by creating an additional
 
2600
column that "caches" the bbox, and matching against this. In our
 
2601
example, the commands are like:
 
2602
</para>
 
2603
 
 
2604
<programlisting>
 
2605
SELECT addGeometryColumn('myschema','mytable','bbox','4326','GEOMETRY','2');
 
2606
 
 
2607
UPDATE mytable set bbox = Envelope(Force_2d(the_geom));
 
2608
</programlisting>
 
2609
 
 
2610
<para>
 
2611
Now change your query to use the &amp;&amp; operator against bbox instead of
 
2612
geom_column, like:
 
2613
</para>
 
2614
 
 
2615
<programlisting>
 
2616
SELECT geom_column FROM mytable WHERE bbox &amp;&amp; SetSrid('BOX3D(0 0,1 1)'::box3d,4326);
 
2617
</programlisting>
 
2618
 
 
2619
<para>
 
2620
Of yourse, if you change or add rows to mytable, you have to keep the
 
2621
bbox "in sync". The most transparent way to do this would be triggers,
 
2622
but you also can modify your application to keep the bbox column current
 
2623
or run the UPDATE query above after every modification.
 
2624
</para>
 
2625
 
 
2626
</sect2>
 
2627
 
 
2628
</sect1>
 
2629
 
 
2630
 
 
2631
<sect1> <title>CLUSTERing on geometry indices</title>
 
2632
 
 
2633
<para>
 
2634
For tables that are mostly read-only, and where a single index is used for the
 
2635
majority of queries, PostgreSQL offers the CLUSTER command. This command 
 
2636
physically reorders all the data rows in the same order as the index criteria,
 
2637
yielding two performance advantages: First, for index range scans, the number of 
 
2638
seeks on the data table is drastically reduced. Second, if your working set
 
2639
concentrates to some small intervals on the indices, you have a more efficient
 
2640
caching because the data rows are spread along fewer data pages. (Feel invited
 
2641
to read the CLUSTER command documentation from the PostgreSQL manual at this
 
2642
point.)
 
2643
</para>
 
2644
 
 
2645
<para>
 
2646
However, currently PostgreSQL does not allow clustering on PostGIS GIST indices
 
2647
because GIST indices simply ignores NULL values, you get an error message like:
 
2648
</para>
 
2649
 
 
2650
<programlisting>
 
2651
lwgeom=# CLUSTER my_geom_index ON my_table;
 
2652
ERROR:  cannot cluster when index access method does not handle null values
 
2653
HINT:  You may be able to work around this by marking column "the_geom" NOT NULL.
 
2654
</programlisting>
 
2655
 
 
2656
<para>
 
2657
As the HINT message tells you, one can work around this deficiency by adding a
 
2658
"not null" constraint to the table:
 
2659
</para>
 
2660
 
 
2661
<programlisting>
 
2662
lwgeom=# ALTER TABLE my_table ALTER COLUMN the_geom SET not null;
 
2663
ALTER TABLE
 
2664
</programlisting>
 
2665
 
 
2666
<para>
 
2667
Of course, this will not work if you in fact need NULL values in your geometry
 
2668
column. Additionally, you must use the above method to add the constraint, using
 
2669
a CHECK constraint like "ALTER TABLE blubb ADD CHECK (geometry is not null);" will
 
2670
not work.
 
2671
</para>
 
2672
 
 
2673
</sect1>
 
2674
 
 
2675
<sect1><title>Avoiding dimension conversion</title>
 
2676
 
 
2677
<para>
 
2678
Sometimes, you happen to have 3D or 4D data in your table, but always access
 
2679
it using OpenGIS compliant asText() or asBinary() functions that only output
 
2680
2D geometries. They do this by internally calling the force_2d() function,
 
2681
which introduces a significant overhead for large geometries. To avoid this
 
2682
overhead, it may be feasible to pre-drop those additional dimensions once and
 
2683
forever:
 
2684
</para>
 
2685
 
 
2686
<programlisting>
 
2687
UPDATE mytable SET the_geom = force_2d(the_geom);
 
2688
VACUUM FULL ANALYZE mytable;
 
2689
</programlisting>
 
2690
 
 
2691
<para>
 
2692
Note that if you added your geometry column using AddGeometryColumn()
 
2693
there'll be a constraint on geometry dimension.
 
2694
To bypass it you will need to drop the constraint.
 
2695
Remember to update the entry in the geometry_columns table and
 
2696
recreate the constraint afterwards.
 
2697
</para>
 
2698
 
 
2699
<para>
 
2700
In case of large tables, it may be wise to divide this UPDATE into smaller portions
 
2701
by constraining the UPDATE to a part of the table via a WHERE clause and your
 
2702
primary key or another feasible criteria, and running a simple "VACUUM;" between
 
2703
your UPDATEs. This drastically reduces the need for temporary disk space.
 
2704
Additionally, if you have mixed dimension geometries, restricting the UPDATE by "WHERE 
 
2705
dimension(the_geom)>2" skips re-writing of geometries that already are in 2D. 
 
2706
</para>
 
2707
 
 
2708
</sect1>
 
2709
 
 
2710
</chapter>
 
2711
 
 
2712
  <chapter>
 
2713
    <title>PostGIS Reference</title>
 
2714
 
 
2715
    <para>The functions given below are the ones which a user of PostGIS is
 
2716
    likely to need. There are other functions which are required support
 
2717
    functions to the PostGIS objects which are not of use to a general
 
2718
    user.</para>
 
2719
 
 
2720
    <sect1>
 
2721
      <title>OpenGIS Functions</title>
 
2722
 
 
2723
      <sect2>
 
2724
        <title>Management Functions</title>
 
2725
 
 
2726
        <variablelist>
 
2727
          <varlistentry id="AddGeometryColumn">
 
2728
            <term>AddGeometryColumn(varchar, varchar, varchar, integer,
 
2729
            varchar, integer)</term>
 
2730
 
 
2731
            <listitem>
 
2732
              <para>Syntax: AddGeometryColumn(&lt;schema_name&gt;,
 
2733
              &lt;table_name&gt;, &lt;column_name&gt;, &lt;srid&gt;,
 
2734
              &lt;type&gt;, &lt;dimension&gt;). Adds a geometry column to an
 
2735
              existing table of attributes. The <varname>schema_name</varname>
 
2736
              is the name of the table schema (unused for pre-schema
 
2737
              PostgreSQL installations). The <varname>srid</varname> must be
 
2738
              an integer value reference to an entry in the SPATIAL_REF_SYS
 
2739
              table. The <varname>type</varname> must be an uppercase string
 
2740
              corresponding to the geometry type, eg, 'POLYGON' or
 
2741
              'MULTILINESTRING'.</para>
 
2742
            </listitem>
 
2743
          </varlistentry>
 
2744
 
 
2745
          <varlistentry>
 
2746
            <term>DropGeometryColumn(varchar, varchar, varchar)</term>
 
2747
 
 
2748
            <listitem>
 
2749
              <para>Syntax: DropGeometryColumn(&lt;schema_name&gt;,
 
2750
              &lt;table_name&gt;, &lt;column_name&gt;). Remove a geometry
 
2751
              column from a spatial table. Note that schema_name will need to
 
2752
              match the f_schema_name field of the table's row in the
 
2753
              geometry_columns table.</para>
 
2754
            </listitem>
 
2755
          </varlistentry>
 
2756
 
 
2757
          <varlistentry>
 
2758
            <term>SetSRID(geometry)</term>
 
2759
 
 
2760
            <listitem>
 
2761
              <para>Set the SRID on a geometry to a particular integer value.
 
2762
              Useful in constructing bounding boxes for queries.</para>
 
2763
            </listitem>
 
2764
          </varlistentry>
 
2765
        </variablelist>
 
2766
      </sect2>
 
2767
 
 
2768
      <sect2>
 
2769
        <title>Geometry Relationship Functions</title>
 
2770
 
 
2771
        <variablelist>
 
2772
          <varlistentry>
 
2773
            <term>Distance(geometry,geometry)</term>
 
2774
 
 
2775
            <listitem>
 
2776
              <para>Return the cartesian distance between two geometries in
 
2777
              projected units.</para>
 
2778
            </listitem>
 
2779
          </varlistentry>
 
2780
 
 
2781
          <varlistentry>
 
2782
            <term>Equals(geometry,geometry)</term>
 
2783
 
 
2784
            <listitem>
 
2785
              <para>Returns 1 (TRUE) if this Geometry is "spatially equal" to
 
2786
              anotherGeometry. Use this for a 'better' answer than '='. equals
 
2787
              ('LINESTRING(0 0, 10 10)','LINESTRING(0 0, 5 5, 10 10)') is
 
2788
              true.</para>
 
2789
 
 
2790
              <para>Performed by the GEOS module</para>
 
2791
 
 
2792
              <para>OGC SPEC s2.1.1.2</para>
 
2793
            </listitem>
 
2794
          </varlistentry>
 
2795
 
 
2796
          <varlistentry>
 
2797
            <term>Disjoint(geometry,geometry)</term>
 
2798
 
 
2799
            <listitem>
 
2800
              <para>Returns 1 (TRUE) if this Geometry is "spatially disjoint"
 
2801
              from anotherGeometry.</para>
 
2802
 
 
2803
              <para>Performed by the GEOS module</para>
 
2804
 
 
2805
              <para>Do not call with a GeometryCollection as an
 
2806
              argument</para>
 
2807
 
 
2808
              <para>NOTE: this is the "allowable" version that returns a
 
2809
              boolean, not an integer.</para>
 
2810
 
 
2811
              <para>OGC SPEC s2.1.1.2 //s2.1.13.3 - a.Relate(b,
 
2812
              'FF*FF****')</para>
 
2813
            </listitem>
 
2814
          </varlistentry>
 
2815
 
 
2816
          <varlistentry>
 
2817
            <term>Intersects(geometry,geometry)</term>
 
2818
 
 
2819
            <listitem>
 
2820
              <para>Returns 1 (TRUE) if this Geometry "spatially intersects"
 
2821
              anotherGeometry.</para>
 
2822
 
 
2823
              <para>Performed by the GEOS module</para>
 
2824
 
 
2825
              <para>Do not call with a GeometryCollection as an
 
2826
              argument</para>
 
2827
 
 
2828
              <para>NOTE: this is the "allowable" version that returns a
 
2829
              boolean, not an integer.</para>
 
2830
 
 
2831
              <para>OGC SPEC s2.1.1.2 //s2.1.13.3 - Intersects(g1, g2 ) --&gt;
 
2832
              Not (Disjoint(g1, g2 ))</para>
 
2833
            </listitem>
 
2834
          </varlistentry>
 
2835
 
 
2836
          <varlistentry>
 
2837
            <term>Touches(geometry,geometry)</term>
 
2838
 
 
2839
            <listitem>
 
2840
              <para>Returns 1 (TRUE) if this Geometry "spatially touches"
 
2841
              anotherGeometry.</para>
 
2842
 
 
2843
              <para>Performed by the GEOS module</para>
 
2844
 
 
2845
              <para>Do not call with a GeometryCollection as an
 
2846
              argument</para>
 
2847
 
 
2848
              <para>NOTE: this is the "allowable" version that returns a
 
2849
              boolean, not an integer.</para>
 
2850
 
 
2851
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3- a.Touches(b) -&gt; (I(a)
 
2852
              intersection I(b) = {empty set} ) and (a intersection b) not
 
2853
              empty</para>
 
2854
            </listitem>
 
2855
          </varlistentry>
 
2856
 
 
2857
          <varlistentry>
 
2858
            <term>Crosses(geometry,geometry)</term>
 
2859
 
 
2860
            <listitem>
 
2861
              <para>Returns 1 (TRUE) if this Geometry "spatially crosses"
 
2862
              anotherGeometry.</para>
 
2863
 
 
2864
              <para>Performed by the GEOS module</para>
 
2865
 
 
2866
              <para>Do not call with a GeometryCollection as an
 
2867
              argument</para>
 
2868
 
 
2869
              <para>NOTE: this is the "allowable" version that returns a
 
2870
              boolean, not an integer.</para>
 
2871
 
 
2872
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3 - a.Relate(b,
 
2873
              'T*T******')</para>
 
2874
            </listitem>
 
2875
          </varlistentry>
 
2876
 
 
2877
          <varlistentry>
 
2878
            <term>Within(geometry,geometry)</term>
 
2879
 
 
2880
            <listitem>
 
2881
              <para>Returns 1 (TRUE) if this Geometry is "spatially within"
 
2882
              anotherGeometry.</para>
 
2883
 
 
2884
              <para>Performed by the GEOS module</para>
 
2885
 
 
2886
              <para>Do not call with a GeometryCollection as an
 
2887
              argument</para>
 
2888
 
 
2889
              <para>NOTE: this is the "allowable" version that returns a
 
2890
              boolean, not an integer.</para>
 
2891
 
 
2892
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3 - a.Relate(b,
 
2893
              'T*F**F***')</para>
 
2894
            </listitem>
 
2895
          </varlistentry>
 
2896
 
 
2897
          <varlistentry>
 
2898
            <term>Overlaps(geometry,geometry)</term>
 
2899
 
 
2900
            <listitem>
 
2901
              <para>Returns 1 (TRUE) if this Geometry is "spatially
 
2902
              overlapping" anotherGeometry.</para>
 
2903
 
 
2904
              <para>Performed by the GEOS module</para>
 
2905
 
 
2906
              <para>Do not call with a GeometryCollection as an
 
2907
              argument</para>
 
2908
 
 
2909
              <para>NOTE: this is the "allowable" version that returns a
 
2910
              boolean, not an integer.</para>
 
2911
 
 
2912
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3</para>
 
2913
            </listitem>
 
2914
          </varlistentry>
 
2915
 
 
2916
          <varlistentry>
 
2917
            <term>Contains(geometry,geometry)</term>
 
2918
 
 
2919
            <listitem>
 
2920
              <para>Returns 1 (TRUE) if this Geometry is "spatially contains"
 
2921
              anotherGeometry.</para>
 
2922
 
 
2923
              <para>Performed by the GEOS module</para>
 
2924
 
 
2925
              <para>Do not call with a GeometryCollection as an
 
2926
              argument</para>
 
2927
 
 
2928
              <para>NOTE: this is the "allowable" version that returns a
 
2929
              boolean, not an integer.</para>
 
2930
 
 
2931
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3 - same as
 
2932
              within(geometry,geometry)</para>
 
2933
            </listitem>
 
2934
          </varlistentry>
 
2935
 
 
2936
          <varlistentry>
 
2937
            <term>Intersects(geometry,geometry)</term>
 
2938
 
 
2939
            <listitem>
 
2940
              <para>Returns 1 (TRUE) if this Geometry is "spatially
 
2941
              intersects" anotherGeometry.</para>
 
2942
 
 
2943
              <para>Performed by the GEOS module</para>
 
2944
 
 
2945
              <para>Do not call with a GeometryCollection as an
 
2946
              argument</para>
 
2947
 
 
2948
              <para>NOTE: this is the "allowable" version that returns a
 
2949
              boolean, not an integer.</para>
 
2950
 
 
2951
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3 - NOT
 
2952
              disjoint(geometry,geometry)</para>
 
2953
            </listitem>
 
2954
          </varlistentry>
 
2955
 
 
2956
          <varlistentry>
 
2957
            <term>Relate(geometry,geometry, intersectionPatternMatrix)</term>
 
2958
 
 
2959
            <listitem>
 
2960
              <para>Returns 1 (TRUE) if this Geometry is spatially related to
 
2961
              anotherGeometry, by testing for intersections between the
 
2962
              Interior, Boundary and Exterior of the two geometries as
 
2963
              specified by the values in the intersectionPatternMatrix.</para>
 
2964
 
 
2965
              <para>Performed by the GEOS module</para>
 
2966
 
 
2967
              <para>Do not call with a GeometryCollection as an
 
2968
              argument</para>
 
2969
 
 
2970
              <para>NOTE: this is the "allowable" version that returns a
 
2971
              boolean, not an integer.</para>
 
2972
 
 
2973
              <para>OGC SPEC s2.1.1.2 // s2.1.13.3</para>
 
2974
            </listitem>
 
2975
          </varlistentry>
 
2976
 
 
2977
          <varlistentry>
 
2978
            <term>Relate(geometry,geometry)</term>
 
2979
 
 
2980
            <listitem>
 
2981
              <para>returns the DE-9IM (dimensionally extended
 
2982
              nine-intersection matrix)</para>
 
2983
 
 
2984
              <para>Performed by the GEOS module</para>
 
2985
 
 
2986
              <para>Do not call with a GeometryCollection as an
 
2987
              argument</para>
 
2988
 
 
2989
              <para>not in OGC spec, but implied. see s2.1.13.2</para>
 
2990
            </listitem>
 
2991
          </varlistentry>
 
2992
        </variablelist>
 
2993
      </sect2>
 
2994
 
 
2995
      <sect2>
 
2996
        <title>Geometry Processing Functions</title>
 
2997
 
 
2998
        <variablelist>
 
2999
          <varlistentry>
 
3000
            <term>Centroid(geometry)</term>
 
3001
 
 
3002
            <listitem>
 
3003
              <para>Returns the centroid of the geometry as a point.</para>
 
3004
 
 
3005
              <para>Computation will be more accurate if performed by the GEOS
 
3006
              module (enabled at compile time).</para>
 
3007
            </listitem>
 
3008
          </varlistentry>
 
3009
 
 
3010
          <varlistentry>
 
3011
            <term>Area(geometry)</term>
 
3012
 
 
3013
            <listitem>
 
3014
              <para>Returns the area of the geometry if it is a polygon or
 
3015
              multi-polygon. </para>
 
3016
            </listitem>
 
3017
          </varlistentry>
 
3018
 
 
3019
          <varlistentry>
 
3020
            <term>Length(geometry)</term>
 
3021
 
 
3022
            <listitem>
 
3023
              <para>The length of this Curve in its associated spatial
 
3024
              reference.</para>
 
3025
 
 
3026
              <para>synonym for length2d()</para>
 
3027
 
 
3028
              <para>OGC SPEC 2.1.5.1</para>
 
3029
            </listitem>
 
3030
          </varlistentry>
 
3031
 
 
3032
          <varlistentry>
 
3033
            <term>PointOnSurface(geometry)</term>
 
3034
 
 
3035
            <listitem>
 
3036
              <para>Return a Point guaranteed to lie on the surface</para>
 
3037
 
 
3038
              <para>Implemented using GEOS</para>
 
3039
 
 
3040
              <para>OGC SPEC 3.2.14.2 and 3.2.18.2 -</para>
 
3041
            </listitem>
 
3042
          </varlistentry>
 
3043
 
 
3044
          <varlistentry>
 
3045
            <term>Boundary(geometry)</term>
 
3046
 
 
3047
            <listitem>
 
3048
              <para>Returns the closure of the combinatorial boundary of this
 
3049
              Geometry. The combinatorial boundary is defined as described in
 
3050
              section 3.12.3.2 of the OGC SPEC. Because the result of this
 
3051
              function is a closure, and hence topologically closed, the
 
3052
              resulting boundary can be represented using representational
 
3053
              geometry primitives as discussed in the OGC SPEC, section
 
3054
              3.12.2.</para>
 
3055
 
 
3056
              <para>Performed by the GEOS module</para>
 
3057
 
 
3058
              <para>OGC SPEC s2.1.1.1</para>
 
3059
            </listitem>
 
3060
          </varlistentry>
 
3061
 
 
3062
          <varlistentry>
 
3063
            <term>Buffer(geometry,double,[integer])</term>
 
3064
 
 
3065
            <listitem>
 
3066
              <para>Returns a geometry that represents all points whose
 
3067
              distance from this Geometry is less than or equal to distance.
 
3068
              Calculations are in the Spatial Reference System of this
 
3069
              Geometry. The optional third parameter sets the
 
3070
              number of segment used to approximate a quarter circle
 
3071
              (defaults to 8).</para>
 
3072
 
 
3073
              <para>Performed by the GEOS module</para>
 
3074
 
 
3075
              <para>Do not call with a GeometryCollection as an
 
3076
              argument</para>
 
3077
 
 
3078
              <para>OGC SPEC s2.1.1.3</para>
 
3079
            </listitem>
 
3080
          </varlistentry>
 
3081
 
 
3082
          <varlistentry>
 
3083
            <term>ConvexHull(geometry)</term>
 
3084
 
 
3085
            <listitem>
 
3086
              <para>Returns a geometry that represents the convex hull of this
 
3087
              Geometry.</para>
 
3088
 
 
3089
              <para>Performed by the GEOS module</para>
 
3090
 
 
3091
              <para>OGC SPEC s2.1.1.3</para>
 
3092
            </listitem>
 
3093
          </varlistentry>
 
3094
 
 
3095
          <varlistentry>
 
3096
            <term>Intersection(geometry,geometry)</term>
 
3097
 
 
3098
            <listitem>
 
3099
              <para>Returns a geometry that represents the point set
 
3100
              intersection of this Geometry with anotherGeometry.</para>
 
3101
 
 
3102
              <para>Performed by the GEOS module</para>
 
3103
 
 
3104
              <para>Do not call with a GeometryCollection as an
 
3105
              argument</para>
 
3106
 
 
3107
              <para>OGC SPEC s2.1.1.3</para>
 
3108
            </listitem>
 
3109
          </varlistentry>
 
3110
 
 
3111
          <varlistentry>
 
3112
            <term>SymDifference(geometry,geometry)</term>
 
3113
 
 
3114
            <listitem>
 
3115
              <para>Returns a geometry that represents the point set symmetric
 
3116
              difference of this Geometry with anotherGeometry.</para>
 
3117
 
 
3118
              <para>Performed by the GEOS module</para>
 
3119
 
 
3120
              <para>Do not call with a GeometryCollection as an
 
3121
              argument</para>
 
3122
 
 
3123
              <para>OGC SPEC s2.1.1.3</para>
 
3124
            </listitem>
 
3125
          </varlistentry>
 
3126
 
 
3127
          <varlistentry>
 
3128
            <term>Difference(geometry,geometry)</term>
 
3129
 
 
3130
            <listitem>
 
3131
              <para>Returns a geometry that represents the point set symmetric
 
3132
              difference of this Geometry with anotherGeometry.</para>
 
3133
 
 
3134
              <para>Performed by the GEOS module</para>
 
3135
 
 
3136
              <para>Do not call with a GeometryCollection as an
 
3137
              argument</para>
 
3138
 
 
3139
              <para>OGC SPEC s2.1.1.3</para>
 
3140
            </listitem>
 
3141
          </varlistentry>
 
3142
 
 
3143
          <varlistentry>
 
3144
            <term>GeomUnion(geometry,geometry)</term>
 
3145
 
 
3146
            <listitem>
 
3147
              <para>Returns a geometry that represents the point set union of
 
3148
              this Geometry with anotherGeometry.</para>
 
3149
 
 
3150
              <para>Performed by the GEOS module</para>
 
3151
 
 
3152
              <para>Do not call with a GeometryCollection as an
 
3153
              argument</para>
 
3154
 
 
3155
              <para>NOTE: this is renamed from "union" because union is an SQL
 
3156
              reserved word</para>
 
3157
 
 
3158
              <para>OGC SPEC s2.1.1.3</para>
 
3159
            </listitem>
 
3160
          </varlistentry>
 
3161
 
 
3162
          <varlistentry>
 
3163
            <term>GeomUnion(geometry set)</term>
 
3164
 
 
3165
            <listitem>
 
3166
              <para>Returns a geometry that represents the point set union of
 
3167
              this all Geometries in given set.</para>
 
3168
 
 
3169
              <para>Performed by the GEOS module</para>
 
3170
 
 
3171
              <para>Do not call with a GeometryCollection in the argument
 
3172
              set</para>
 
3173
 
 
3174
              <para>Not explicitly defined in OGC SPEC</para>
 
3175
            </listitem>
 
3176
          </varlistentry>
 
3177
 
 
3178
          <varlistentry>
 
3179
            <term>MemGeomUnion(geometry set)</term>
 
3180
 
 
3181
            <listitem>
 
3182
              <para>Same as the above, only memory-friendly (uses less memory
 
3183
              and more processor time).</para>
 
3184
            </listitem>
 
3185
          </varlistentry>
 
3186
        </variablelist>
 
3187
      </sect2>
 
3188
 
 
3189
      <sect2>
 
3190
        <title>Geometry Accessors</title>
 
3191
 
 
3192
        <variablelist>
 
3193
          <varlistentry>
 
3194
            <term>AsText(geometry)</term>
 
3195
 
 
3196
            <listitem>
 
3197
              <para>Return the Well-Known Text representation of the geometry.
 
3198
              For example: POLYGON(0 0,0 1,1 1,1 0,0 0)</para>
 
3199
 
 
3200
              <para>OGC SPEC s2.1.1.1</para>
 
3201
            </listitem>
 
3202
          </varlistentry>
 
3203
 
 
3204
          <varlistentry>
 
3205
            <term>AsBinary(geometry)</term>
 
3206
 
 
3207
            <listitem>
 
3208
              <para>Returns the geometry in the OGC "well-known-binary"
 
3209
              format, using the endian encoding of the server on which the
 
3210
              database is running. This is useful in binary cursors to pull
 
3211
              data out of the database without converting it to a string
 
3212
              representation.</para>
 
3213
 
 
3214
              <para>OGC SPEC s2.1.1.1 - also see
 
3215
              asBinary(&lt;geometry&gt;,'XDR') and
 
3216
              asBinary(&lt;geometry&gt;,'NDR')</para>
 
3217
            </listitem>
 
3218
          </varlistentry>
 
3219
 
 
3220
          <varlistentry>
 
3221
            <term>SRID(geometry)</term>
 
3222
 
 
3223
            <listitem>
 
3224
              <para>Returns the integer SRID number of the spatial reference
 
3225
              system of the geometry.</para>
 
3226
 
 
3227
              <para>OGC SPEC s2.1.1.1</para>
 
3228
            </listitem>
 
3229
          </varlistentry>
 
3230
 
 
3231
          <varlistentry>
 
3232
            <term>Dimension(geometry)</term>
 
3233
 
 
3234
            <listitem>
 
3235
              <para>The inherent dimension of this Geometry object, which must
 
3236
              be less than or equal to the coordinate dimension. OGC SPEC
 
3237
              s2.1.1.1 - returns 0 for points, 1 for lines, 2 for polygons,
 
3238
              and the largest dimension of the components of a
 
3239
              GEOMETRYCOLLECTION.</para>
 
3240
 
 
3241
              <programlisting>select dimension('GEOMETRYCOLLECTION(LINESTRING(1 1,0 0),POINT(0 0)'); 
 
3242
dimension 
 
3243
-----------
 
3244
1</programlisting>
 
3245
            </listitem>
 
3246
          </varlistentry>
 
3247
 
 
3248
          <varlistentry>
 
3249
            <term>Envelope(geometry)</term>
 
3250
 
 
3251
            <listitem>
 
3252
              <para>Returns a POLYGON representing the bounding box of the
 
3253
              geometry.</para>
 
3254
 
 
3255
              <para>OGC SPEC s2.1.1.1 - The minimum bounding box for this
 
3256
              Geometry, returned as a Geometry. The polygon is defined by the
 
3257
              corner points of the bounding box ((MINX, MINY), (MAXX, MINY),
 
3258
              (MAXX, MAXY), (MINX, MAXY), (MINX, MINY)).</para>
 
3259
 
 
3260
              <para>NOTE:PostGIS will add a Zmin/Zmax coordinate as
 
3261
              well.</para>
 
3262
            </listitem>
 
3263
          </varlistentry>
 
3264
 
 
3265
          <varlistentry>
 
3266
            <term>IsEmpty(geometry)</term>
 
3267
 
 
3268
            <listitem>
 
3269
              <para>Returns 1 (TRUE) if this Geometry is the empty geometry .
 
3270
              If true, then this Geometry represents the empty point set -
 
3271
              i.e. GEOMETRYCOLLECTION(EMPTY).</para>
 
3272
 
 
3273
              <para>OGC SPEC s2.1.1.1</para>
 
3274
            </listitem>
 
3275
          </varlistentry>
 
3276
 
 
3277
          <varlistentry id="IsSimple">
 
3278
            <term>IsSimple(geometry)</term>
 
3279
 
 
3280
            <listitem>
 
3281
              <para>Returns 1 (TRUE) if this Geometry has no anomalous
 
3282
              geometric points, such as self intersection or self
 
3283
              tangency.</para>
 
3284
 
 
3285
              <para>Performed by the GEOS module</para>
 
3286
 
 
3287
              <para>OGC SPEC s2.1.1.1</para>
 
3288
            </listitem>
 
3289
          </varlistentry>
 
3290
 
 
3291
          <varlistentry id="IsClosed">
 
3292
            <term>IsClosed(geometry)</term>
 
3293
            <listitem>
 
3294
              <para>Returns true of the geometry start and end points are
 
3295
              coincident.</para>
 
3296
            </listitem>
 
3297
          </varlistentry>
 
3298
 
 
3299
          <varlistentry>
 
3300
            <term>IsRing(geometry)</term>
 
3301
 
 
3302
            <listitem>
 
3303
              <para>Returns 1 (TRUE) if this Curve is closed (StartPoint ( ) =
 
3304
              EndPoint ( )) and this Curve is simple (does not pass through
 
3305
              the same point more than once).</para>
 
3306
 
 
3307
              <para>performed by GEOS</para>
 
3308
 
 
3309
              <para>OGC spec 2.1.5.1</para>
 
3310
            </listitem>
 
3311
          </varlistentry>
 
3312
 
 
3313
          <varlistentry>
 
3314
            <term>NumGeometries(geometry)</term>
 
3315
 
 
3316
            <listitem>
 
3317
              <para>If geometry is a GEOMETRYCOLLECTION (or MULTI*) return the
 
3318
              number of geometries, otherwise return NULL.</para>
 
3319
            </listitem>
 
3320
          </varlistentry>
 
3321
 
 
3322
          <varlistentry>
 
3323
            <term>GeometryN(geometry,int)</term>
 
3324
 
 
3325
            <listitem>
 
3326
              <para>Return the N'th geometry if the geometry is a
 
3327
              GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING or MULTIPOLYGON.
 
3328
              Otherwise, return NULL.</para>
 
3329
 
 
3330
              <para>1 is 1st geometry</para>
 
3331
            </listitem>
 
3332
          </varlistentry>
 
3333
 
 
3334
          <varlistentry>
 
3335
            <term>NumPoints(geometry)</term>
 
3336
 
 
3337
            <listitem>
 
3338
              <para>Find and return the number of points in the first
 
3339
              linestring in the geometry. Return NULL if there is no
 
3340
              linestring in the geometry.</para>
 
3341
            </listitem>
 
3342
          </varlistentry>
 
3343
 
 
3344
          <varlistentry>
 
3345
            <term>PointN(geometry,integer)</term>
 
3346
 
 
3347
            <listitem>
 
3348
              <para>Return the N'th point in the first linestring in the
 
3349
              geometry. Return NULL if there is no linestring in the
 
3350
              geometry.</para>
 
3351
            </listitem>
 
3352
          </varlistentry>
 
3353
 
 
3354
          <varlistentry>
 
3355
            <term>ExteriorRing(geometry)</term>
 
3356
 
 
3357
            <listitem>
 
3358
              <para>Return the exterior ring of the polygon geometry.
 
3359
              Return NULL if the geometry is not a polygon.</para>
 
3360
            </listitem>
 
3361
          </varlistentry>
 
3362
 
 
3363
          <varlistentry>
 
3364
            <term>NumInteriorRings(geometry)</term>
 
3365
 
 
3366
            <listitem>
 
3367
              <para>Return the number of interior rings of the first polygon
 
3368
              in the geometry. Return NULL if there is no polygon in the
 
3369
              geometry.</para>
 
3370
            </listitem>
 
3371
          </varlistentry>
 
3372
 
 
3373
          <varlistentry>
 
3374
            <term>InteriorRingN(geometry,integer)</term>
 
3375
 
 
3376
            <listitem>
 
3377
              <para>Return the N'th interior ring of the polygon geometry.
 
3378
              Return NULL if the geometry is not a polygon or the given
 
3379
              N is out of range (1-based).</para>
 
3380
            </listitem>
 
3381
          </varlistentry>
 
3382
 
 
3383
          <varlistentry>
 
3384
            <term>EndPoint(geometry)</term>
 
3385
 
 
3386
            <listitem>
 
3387
              <para>Returns the last point of the LineString geometry as a point.</para>
 
3388
            </listitem>
 
3389
          </varlistentry>
 
3390
 
 
3391
          <varlistentry>
 
3392
            <term>StartPoint(geometry)</term>
 
3393
 
 
3394
            <listitem>
 
3395
              <para>Returns the first point of the LineString geometry as a point.</para>
 
3396
            </listitem>
 
3397
          </varlistentry>
 
3398
 
 
3399
          <varlistentry id="GeometryType">
 
3400
            <term>GeometryType(geometry)</term>
 
3401
            <listitem>
 
3402
              <para>Returns the type of the geometry as a string. Eg:
 
3403
              'LINESTRING', 'POLYGON', 'MULTIPOINT', etc.</para>
 
3404
 
 
3405
              <para>OGC SPEC s2.1.1.1 - Returns the name of the instantiable
 
3406
              subtype of Geometry of which this Geometry instance is a member.
 
3407
              The name of the instantiable subtype of Geometry is returned as
 
3408
              a string.</para>
 
3409
            </listitem>
 
3410
          </varlistentry>
 
3411
 
 
3412
          <varlistentry>
 
3413
            <term>X(geometry)</term>
 
3414
 
 
3415
            <listitem>
 
3416
              <para>Find and return the X coordinate of the first point in the
 
3417
              geometry. Return NULL if there is no point in the
 
3418
              geometry.</para>
 
3419
            </listitem>
 
3420
          </varlistentry>
 
3421
 
 
3422
          <varlistentry>
 
3423
            <term>Y(geometry)</term>
 
3424
 
 
3425
            <listitem>
 
3426
              <para>Find and return the Y coordinate of the first point in the
 
3427
              geometry. Return NULL if there is no point in the
 
3428
              geometry.</para>
 
3429
            </listitem>
 
3430
          </varlistentry>
 
3431
 
 
3432
          <varlistentry>
 
3433
            <term>Z(geometry)</term>
 
3434
 
 
3435
            <listitem>
 
3436
              <para>Find and return the Z coordinate of the first point in the
 
3437
              geometry. Return NULL if there is no point in the
 
3438
              geometry.</para>
 
3439
            </listitem>
 
3440
          </varlistentry>
 
3441
        </variablelist>
 
3442
      </sect2>
 
3443
 
 
3444
      <sect2>
 
3445
        <title>Geometry Constructors</title>
 
3446
 
 
3447
        <variablelist>
 
3448
 
 
3449
          <varlistentry>
 
3450
            <term>GeomFromText(text,[&lt;srid&gt;])</term>
 
3451
            <listitem>
 
3452
              <para>Makes a Geometry from WKT with the given SRID.</para>
 
3453
 
 
3454
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3455
              suite</para>
 
3456
            </listitem>
 
3457
          </varlistentry>
 
3458
 
 
3459
          <varlistentry>
 
3460
            <term>PointFromText(text,[&lt;srid&gt;])</term>
 
3461
 
 
3462
            <listitem>
 
3463
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3464
              not give, it defaults to -1.</para>
 
3465
 
 
3466
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3467
              suite</para>
 
3468
 
 
3469
              <para>Throws an error if the WKT is not a Point</para>
 
3470
            </listitem>
 
3471
          </varlistentry>
 
3472
 
 
3473
          <varlistentry>
 
3474
            <term>LineFromText(text,[&lt;srid&gt;])</term>
 
3475
 
 
3476
            <listitem>
 
3477
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3478
              not give, it defaults to -1.</para>
 
3479
 
 
3480
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3481
              suite</para>
 
3482
 
 
3483
              <para>Throws an error if the WKT is not a Line</para>
 
3484
            </listitem>
 
3485
          </varlistentry>
 
3486
 
 
3487
          <varlistentry>
 
3488
            <term>LinestringFromText(text,[&lt;srid&gt;])</term>
 
3489
 
 
3490
            <listitem>
 
3491
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3492
              not give, it defaults to -1.</para>
 
3493
 
 
3494
              <para>from the conformance suite</para>
 
3495
 
 
3496
              <para>Throws an error if the WKT is not a Line</para>
 
3497
            </listitem>
 
3498
          </varlistentry>
 
3499
 
 
3500
          <varlistentry>
 
3501
            <term>PolyFromText(text,[&lt;srid&gt;])</term>
 
3502
 
 
3503
            <listitem>
 
3504
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3505
              not give, it defaults to -1.</para>
 
3506
 
 
3507
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3508
              suite</para>
 
3509
 
 
3510
              <para>Throws an error if the WKT is not a Polygon</para>
 
3511
            </listitem>
 
3512
          </varlistentry>
 
3513
 
 
3514
          <varlistentry>
 
3515
            <term>PolygonFromText(text,[&lt;srid&gt;])</term>
 
3516
 
 
3517
            <listitem>
 
3518
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3519
              not give, it defaults to -1.</para>
 
3520
 
 
3521
              <para>from the conformance suite</para>
 
3522
 
 
3523
              <para>Throws an error if the WKT is not a Polygon</para>
 
3524
            </listitem>
 
3525
          </varlistentry>
 
3526
 
 
3527
          <varlistentry>
 
3528
            <term>MPointFromText(text,[&lt;srid&gt;])</term>
 
3529
 
 
3530
            <listitem>
 
3531
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3532
              not give, it defaults to -1.</para>
 
3533
 
 
3534
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3535
              suite</para>
 
3536
 
 
3537
              <para>Throws an error if the WKT is not a MULTIPOINT</para>
 
3538
            </listitem>
 
3539
          </varlistentry>
 
3540
 
 
3541
          <varlistentry>
 
3542
            <term>MLineFromText(text,[&lt;srid&gt;])</term>
 
3543
 
 
3544
            <listitem>
 
3545
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3546
              not give, it defaults to -1.</para>
 
3547
 
 
3548
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3549
              suite</para>
 
3550
 
 
3551
              <para>Throws an error if the WKT is not a MULTILINESTRING</para>
 
3552
            </listitem>
 
3553
          </varlistentry>
 
3554
 
 
3555
          <varlistentry>
 
3556
            <term>MPolyFromText(text,[&lt;srid&gt;])</term>
 
3557
 
 
3558
            <listitem>
 
3559
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3560
              not give, it defaults to -1.</para>
 
3561
 
 
3562
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3563
              suite</para>
 
3564
 
 
3565
              <para>Throws an error if the WKT is not a MULTIPOLYGON</para>
 
3566
            </listitem>
 
3567
          </varlistentry>
 
3568
 
 
3569
          <varlistentry>
 
3570
            <term>GeomCollFromText(text,[&lt;srid&gt;])</term>
 
3571
 
 
3572
            <listitem>
 
3573
              <para>Makes a Geometry from WKT with the given SRID. If SRID is
 
3574
              not give, it defaults to -1.</para>
 
3575
 
 
3576
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3577
              suite</para>
 
3578
 
 
3579
              <para>Throws an error if the WKT is not a
 
3580
              GEOMETRYCOLLECTION</para>
 
3581
            </listitem>
 
3582
          </varlistentry>
 
3583
 
 
3584
          <varlistentry>
 
3585
            <term>GeomFromWKB(bytea,[&lt;srid&gt;])</term>
 
3586
 
 
3587
            <listitem>
 
3588
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3589
              not give, it defaults to -1.</para>
 
3590
 
 
3591
              <para>OGC SPEC 3.2.6.2 - option SRID is from the conformance
 
3592
              suite</para>
 
3593
            </listitem>
 
3594
          </varlistentry>
 
3595
 
 
3596
          <varlistentry>
 
3597
            <term>GeomFromWKB(bytea,[&lt;srid&gt;])</term>
 
3598
 
 
3599
            <listitem>
 
3600
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3601
              not give, it defaults to -1.</para>
 
3602
 
 
3603
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3604
              suite</para>
 
3605
            </listitem>
 
3606
          </varlistentry>
 
3607
 
 
3608
          <varlistentry>
 
3609
            <term>PointFromWKB(bytea,[&lt;srid&gt;])</term>
 
3610
 
 
3611
            <listitem>
 
3612
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3613
              not give, it defaults to -1.</para>
 
3614
 
 
3615
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3616
              suite</para>
 
3617
 
 
3618
              <para>throws an error if WKB is not a POINT</para>
 
3619
            </listitem>
 
3620
          </varlistentry>
 
3621
 
 
3622
          <varlistentry>
 
3623
            <term>LineFromWKB(bytea,[&lt;srid&gt;])</term>
 
3624
 
 
3625
            <listitem>
 
3626
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3627
              not give, it defaults to -1.</para>
 
3628
 
 
3629
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3630
              suite</para>
 
3631
 
 
3632
              <para>throws an error if WKB is not a LINESTRING</para>
 
3633
            </listitem>
 
3634
          </varlistentry>
 
3635
 
 
3636
          <varlistentry>
 
3637
            <term>LinestringFromWKB(bytea,[&lt;srid&gt;])</term>
 
3638
 
 
3639
            <listitem>
 
3640
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3641
              not give, it defaults to -1.</para>
 
3642
 
 
3643
              <para>from the conformance suite</para>
 
3644
 
 
3645
              <para>throws an error if WKB is not a LINESTRING</para>
 
3646
            </listitem>
 
3647
          </varlistentry>
 
3648
 
 
3649
          <varlistentry>
 
3650
            <term>PolyFromWKB(bytea,[&lt;srid&gt;])</term>
 
3651
 
 
3652
            <listitem>
 
3653
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3654
              not give, it defaults to -1.</para>
 
3655
 
 
3656
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3657
              suite</para>
 
3658
 
 
3659
              <para>throws an error if WKB is not a POLYGON</para>
 
3660
            </listitem>
 
3661
          </varlistentry>
 
3662
 
 
3663
          <varlistentry>
 
3664
            <term>PolygonFromWKB(bytea,[&lt;srid&gt;])</term>
 
3665
 
 
3666
            <listitem>
 
3667
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3668
              not give, it defaults to -1.</para>
 
3669
 
 
3670
              <para>from the conformance suite</para>
 
3671
 
 
3672
              <para>throws an error if WKB is not a POLYGON</para>
 
3673
            </listitem>
 
3674
          </varlistentry>
 
3675
 
 
3676
          <varlistentry>
 
3677
            <term>MPointFromWKB(bytea,[&lt;srid&gt;])</term>
 
3678
 
 
3679
            <listitem>
 
3680
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3681
              not give, it defaults to -1.</para>
 
3682
 
 
3683
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3684
              suite</para>
 
3685
 
 
3686
              <para>throws an error if WKB is not a MULTIPOINT</para>
 
3687
            </listitem>
 
3688
          </varlistentry>
 
3689
 
 
3690
          <varlistentry>
 
3691
            <term>MLineFromWKB(bytea,[&lt;srid&gt;])</term>
 
3692
 
 
3693
            <listitem>
 
3694
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3695
              not give, it defaults to -1.</para>
 
3696
 
 
3697
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3698
              suite</para>
 
3699
 
 
3700
              <para>throws an error if WKB is not a MULTILINESTRING</para>
 
3701
            </listitem>
 
3702
          </varlistentry>
 
3703
 
 
3704
          <varlistentry>
 
3705
            <term>MPolyFromWKB(bytea,[&lt;srid&gt;])</term>
 
3706
 
 
3707
            <listitem>
 
3708
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3709
              not give, it defaults to -1.</para>
 
3710
 
 
3711
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3712
              suite</para>
 
3713
 
 
3714
              <para>throws an error if WKB is not a MULTIPOLYGON</para>
 
3715
            </listitem>
 
3716
          </varlistentry>
 
3717
 
 
3718
          <varlistentry>
 
3719
            <term>GeomCollFromWKB(bytea,[&lt;srid&gt;])</term>
 
3720
 
 
3721
            <listitem>
 
3722
              <para>Makes a Geometry from WKB with the given SRID. If SRID is
 
3723
              not give, it defaults to -1.</para>
 
3724
 
 
3725
              <para>OGC SPEC 3.2.7.2 - option SRID is from the conformance
 
3726
              suite</para>
 
3727
 
 
3728
              <para>throws an error if WKB is not a GEOMETRYCOLLECTION</para>
 
3729
            </listitem>
 
3730
          </varlistentry>
 
3731
        </variablelist>
 
3732
      </sect2>
 
3733
    </sect1>
 
3734
 
 
3735
    <sect1>
 
3736
      <title>Postgis Extensions</title>
 
3737
 
 
3738
      <sect2>
 
3739
        <title>Management Functions</title>
 
3740
          <variablelist>
 
3741
                <varlistentry>
 
3742
                  <term>DropGeometryTable([&lt;schema_name&gt;],
 
3743
                  &lt;table_name&gt;)</term>
 
3744
 
 
3745
                  <listitem>
 
3746
                    <para>Drops a table and all its references in geometry_columns.
 
3747
                    Note: uses current_schema() on schema-aware pgsql installations if
 
3748
                    schema is not provided.</para>
 
3749
                  </listitem>
 
3750
                </varlistentry>
 
3751
 
 
3752
                <varlistentry>
 
3753
                  <term>UpdateGeometrySRID([&lt;schema_name&gt;],
 
3754
                  &lt;table_name&gt;, &lt;column_name&gt;, &lt;srid&gt;)</term>
 
3755
                  <listitem>
 
3756
                    <para>Update the SRID of all features in a geometry column updating constraints and reference in geometry_columns.
 
3757
                    Note: uses current_schema() on schema-aware pgsql installations if schema is not provided.</para>
 
3758
                  </listitem>
 
3759
                </varlistentry>
 
3760
 
 
3761
                <varlistentry>
 
3762
                  <term>update_geometry_stats([&lt;table_name&gt;,
 
3763
                  &lt;column_name&gt;])</term>
 
3764
 
 
3765
                  <listitem>
 
3766
                    <para>Update statistics about spatial tables for use by the query
 
3767
                    planner. You will also need to run "VACUUM ANALYZE [table_name]
 
3768
                    [column_name]" for the statistics gathering process to be
 
3769
                    complete. NOTE: starting with PostgreSQL 8.0 statistics gathering
 
3770
                    is automatically performed running "VACUUM ANALYZE".</para>
 
3771
                  </listitem>
 
3772
                </varlistentry>
 
3773
 
 
3774
        <varlistentry>
 
3775
          <term>postgis_version()</term>
 
3776
 
 
3777
          <listitem>
 
3778
            <para>Returns the version number of the PostGIS functions
 
3779
            installed in this database (deprecated, use postgis_full_version()
 
3780
            instead).</para>
 
3781
          </listitem>
 
3782
        </varlistentry>
 
3783
 
 
3784
        <varlistentry>
 
3785
          <term>postgis_lib_version()</term>
 
3786
          <listitem>
 
3787
            <para>Returns the version number of the PostGIS library.</para>
 
3788
          </listitem>
 
3789
        </varlistentry>
 
3790
 
 
3791
        <varlistentry>
 
3792
          <term>postgis_lib_build_date()</term>
 
3793
          <listitem>
 
3794
            <para>Returns build date of the PostGIS library.</para>
 
3795
          </listitem>
 
3796
        </varlistentry>
 
3797
 
 
3798
        <varlistentry>
 
3799
          <term>postgis_script_build_date()</term>
 
3800
          <listitem>
 
3801
            <para>Returns build date of the PostGIS scripts.</para>
 
3802
          </listitem>
 
3803
        </varlistentry>
 
3804
 
 
3805
        <varlistentry>
 
3806
          <term>postgis_scripts_installed()</term>
 
3807
 
 
3808
          <listitem>
 
3809
            <para>Returns the version number of the lwpostgis.sql script
 
3810
            installed in this database.</para>
 
3811
          </listitem>
 
3812
        </varlistentry>
 
3813
 
 
3814
        <varlistentry>
 
3815
          <term>postgis_scripts_released()</term>
 
3816
 
 
3817
          <listitem>
 
3818
            <para>Returns the version number of the lwpostgis.sql script
 
3819
            released with the installed postgis lib.</para>
 
3820
          </listitem>
 
3821
        </varlistentry>
 
3822
 
 
3823
        <varlistentry>
 
3824
          <term>postgis_geos_version()</term>
 
3825
 
 
3826
          <listitem>
 
3827
            <para>Returns the version number of the GEOS library, or NULL if
 
3828
            GEOS support is not enabled.</para>
 
3829
          </listitem>
 
3830
        </varlistentry>
 
3831
 
 
3832
        <varlistentry>
 
3833
          <term>postgis_proj_version()</term>
 
3834
 
 
3835
          <listitem>
 
3836
            <para>Returns the version number of the PROJ4 library, or NULL if
 
3837
            PROJ4 support is not enabled.</para>
 
3838
          </listitem>
 
3839
        </varlistentry>
 
3840
 
 
3841
        <varlistentry>
 
3842
          <term>postgis_uses_stats()</term>
 
3843
 
 
3844
          <listitem>
 
3845
            <para>Returns true if STATS usage has been enabled, false
 
3846
            otherwise.</para>
 
3847
          </listitem>
 
3848
        </varlistentry>
 
3849
 
 
3850
        <varlistentry>
 
3851
          <term>postgis_full_version()</term>
 
3852
 
 
3853
          <listitem>
 
3854
            <para>Reports full postgis version and build configuration
 
3855
            infos.</para>
 
3856
          </listitem>
 
3857
        </varlistentry>
 
3858
 
 
3859
           </variablelist>
 
3860
 
 
3861
        </sect2>
 
3862
 
 
3863
        <sect2>
 
3864
          <title>Operators</title>
 
3865
            <variablelist>
 
3866
 
 
3867
                <varlistentry>
 
3868
                  <term>A &amp;&lt; B</term>
 
3869
 
 
3870
                  <listitem>
 
3871
                    <para>The "&amp;&lt;" operator returns true if A's bounding box
 
3872
                    overlaps or is to the left of B's bounding box.</para>
 
3873
                  </listitem>
 
3874
                </varlistentry>
 
3875
 
 
3876
                <varlistentry>
 
3877
                  <term>A &amp;&gt; B</term>
 
3878
 
 
3879
                  <listitem>
 
3880
                    <para>The "&amp;&gt;" operator returns true if A's bounding box
 
3881
                    overlaps or is to the right of B's bounding box.</para>
 
3882
                  </listitem>
 
3883
                </varlistentry>
 
3884
 
 
3885
                <varlistentry>
 
3886
                  <term>A &lt;&lt; B</term>
 
3887
 
 
3888
                  <listitem>
 
3889
                    <para>The "&lt;&lt;" operator returns true if A's bounding box is
 
3890
                    strictly to the left of B's bounding box.</para>
 
3891
                  </listitem>
 
3892
                </varlistentry>
 
3893
 
 
3894
                <varlistentry>
 
3895
                  <term>A &gt;&gt; B</term>
 
3896
 
 
3897
                  <listitem>
 
3898
                    <para>The "&gt;&gt;" operator returns true if A's bounding box is
 
3899
                    strictly to the right of B's bounding box.</para>
 
3900
                  </listitem>
 
3901
                </varlistentry>
 
3902
 
 
3903
                <varlistentry>
 
3904
                  <term>A &amp;&lt;| B</term>
 
3905
 
 
3906
                  <listitem>
 
3907
                    <para>The "&amp;&lt;|" operator returns true if A's bounding box
 
3908
                    overlaps or is below B's bounding box.</para>
 
3909
                  </listitem>
 
3910
                </varlistentry>
 
3911
 
 
3912
                <varlistentry>
 
3913
                  <term>A |&amp;&gt; B</term>
 
3914
 
 
3915
                  <listitem>
 
3916
                    <para>The "|&amp;&gt;" operator returns true if A's bounding box
 
3917
                    overlaps or is above B's bounding box.</para>
 
3918
                  </listitem>
 
3919
                </varlistentry>
 
3920
 
 
3921
                <varlistentry>
 
3922
                  <term>A &lt;&lt;| B</term>
 
3923
 
 
3924
                  <listitem>
 
3925
                    <para>The "&lt;&lt;|" operator returns true if A's bounding box is
 
3926
                    strictly below B's bounding box.</para>
 
3927
                  </listitem>
 
3928
                </varlistentry>
 
3929
 
 
3930
                <varlistentry>
 
3931
                  <term>A |&gt;&gt; B</term>
 
3932
 
 
3933
                  <listitem>
 
3934
                    <para>The "|&gt;&gt;" operator returns true if A's bounding box is
 
3935
                    strictly above B's bounding box.</para>
 
3936
                  </listitem>
 
3937
                </varlistentry>
 
3938
 
 
3939
                <varlistentry>
 
3940
                  <term>A ~= B</term>
 
3941
 
 
3942
                  <listitem>
 
3943
                    <para>The "~=" operator is the "same as" operator. It tests actual
 
3944
                    geometric equality of two features. So if A and B are the same
 
3945
                    feature, vertex-by-vertex, the operator returns true.</para>
 
3946
                  </listitem>
 
3947
                </varlistentry>
 
3948
 
 
3949
                <varlistentry>
 
3950
                  <term>A @ B</term>
 
3951
 
 
3952
                  <listitem>
 
3953
                    <para>The "@" operator returns true if A's bounding box is
 
3954
                    completely contained by B's bounding box.</para>
 
3955
                  </listitem>
 
3956
                </varlistentry>
 
3957
 
 
3958
                <varlistentry>
 
3959
                  <term>A ~ B</term>
 
3960
 
 
3961
                  <listitem>
 
3962
                    <para>The "~" operator returns true if A's bounding box completely
 
3963
                    contains B's bounding box.</para>
 
3964
                  </listitem>
 
3965
                </varlistentry>
 
3966
 
 
3967
                <varlistentry>
 
3968
                  <term>A &amp;&amp; B</term>
 
3969
 
 
3970
                  <listitem>
 
3971
                    <para>The "&amp;&amp;" operator is the "overlaps" operator. If A's
 
3972
                    bounding boux overlaps B's bounding box the operator returns
 
3973
                    true.</para>
 
3974
                  </listitem>
 
3975
                </varlistentry>
 
3976
          </variablelist>
 
3977
      </sect2>
 
3978
 
 
3979
      <sect2>
 
3980
        <title>Measurement Functions</title>
 
3981
          <variablelist>
 
3982
 
 
3983
                <varlistentry>
 
3984
                  <term>area2d(geometry)</term>
 
3985
 
 
3986
                  <listitem>
 
3987
                    <para>Returns the area of the geometry if it is a polygon or
 
3988
                    multi-polygon.</para>
 
3989
                  </listitem>
 
3990
                </varlistentry>
 
3991
 
 
3992
        <varlistentry>
 
3993
          <term>distance_sphere(point, point)</term>
 
3994
 
 
3995
          <listitem>
 
3996
            <para>Returns linear distance in meters between two lat/lon
 
3997
            points. Uses a spherical earth and radius of 6370986 meters.
 
3998
            Faster than <link linkend="distance_spheroid">distance_spheroid()</link>, but
 
3999
            less accurate.
 
4000
                        Only implemented for points.</para>                     
 
4001
          </listitem>
 
4002
        </varlistentry>
 
4003
 
 
4004
        <varlistentry id="distance_spheroid">
 
4005
          <term>distance_spheroid(point, point, spheroid)</term>
 
4006
 
 
4007
          <listitem>
 
4008
            <para>Returns linear distance between two lat/lon points given a
 
4009
            particular spheroid. See the explanation of spheroids given for
 
4010
            <link linkend="length_spheroid">length_spheroid()</link>.
 
4011
            Currently only implemented for points.</para>
 
4012
          </listitem>
 
4013
        </varlistentry>
 
4014
 
 
4015
        <varlistentry>
 
4016
          <term>length2d(geometry)</term>
 
4017
 
 
4018
          <listitem>
 
4019
            <para>Returns the 2-dimensional length of the geometry if it is a
 
4020
            linestring or multi-linestring.</para>
 
4021
          </listitem>
 
4022
        </varlistentry>
 
4023
 
 
4024
        <varlistentry>
 
4025
          <term>length3d(geometry)</term>
 
4026
 
 
4027
          <listitem>
 
4028
            <para>Returns the 3-dimensional length of the geometry if it is a
 
4029
            linestring or multi-linestring.</para>
 
4030
          </listitem>
 
4031
        </varlistentry>
 
4032
 
 
4033
        <varlistentry id="length_spheroid">
 
4034
          <term>length_spheroid(geometry,spheroid)</term>
 
4035
 
 
4036
          <listitem>
 
4037
            <para>Calculates the length of of a geometry on an elipsoid. This
 
4038
            is useful if the coordinates of the geometry are in
 
4039
            latitude/longitude and a length is desired without reprojection.
 
4040
            The elipsoid is a separate database type and can be constructed as
 
4041
            follows:</para>
 
4042
 
 
4043
            <literallayout>SPHEROID[&lt;NAME&gt;,&lt;SEMI-MAJOR AXIS&gt;,&lt;INVERSE FLATTENING&gt;]</literallayout>
 
4044
 
 
4045
            <para>Eg:</para>
 
4046
 
 
4047
            <literallayout>SPHEROID["GRS_1980",6378137,298.257222101]</literallayout>
 
4048
 
 
4049
            <para>An example calculation might look like this:</para>
 
4050
 
 
4051
            <literallayout>SELECT
 
4052
 length_spheroid(
 
4053
  geometry_column,
 
4054
  'SPHEROID["GRS_1980",6378137,298.257222101]'
 
4055
 )
 
4056
FROM geometry_table;</literallayout>
 
4057
          </listitem>
 
4058
        </varlistentry>
 
4059
 
 
4060
        <varlistentry>
 
4061
          <term>length3d_spheroid(geometry,spheroid)</term>
 
4062
 
 
4063
          <listitem>
 
4064
            <para>Calculates the length of of a geometry on an elipsoid,
 
4065
            taking the elevation into account. This is just like
 
4066
            length_spheroid except vertical coordinates (expressed in the same
 
4067
            units as the spheroid axes) are used to calculate the extra
 
4068
            distance vertical displacement adds.</para>
 
4069
          </listitem>
 
4070
        </varlistentry>
 
4071
 
 
4072
        <varlistentry>
 
4073
          <term>distance(geometry, geometry)</term>
 
4074
 
 
4075
          <listitem>
 
4076
            <para>Returns the smaller distance between two geometries.</para>
 
4077
          </listitem>
 
4078
        </varlistentry>
 
4079
 
 
4080
        <varlistentry>
 
4081
          <term>max_distance(linestring,linestring)</term>
 
4082
 
 
4083
          <listitem>
 
4084
            <para>Returns the largest distance between two line
 
4085
            strings.</para>
 
4086
          </listitem>
 
4087
        </varlistentry>
 
4088
 
 
4089
        <varlistentry>
 
4090
          <term>perimeter(geometry)</term>
 
4091
 
 
4092
          <listitem>
 
4093
            <para>Returns the 2-dimensional perimeter of the geometry, if it
 
4094
            is a polygon or multi-polygon.</para>
 
4095
          </listitem>
 
4096
        </varlistentry>
 
4097
 
 
4098
        <varlistentry>
 
4099
          <term>perimeter2d(geometry)</term>
 
4100
 
 
4101
          <listitem>
 
4102
            <para>Returns the 2-dimensional perimeter of the geometry, if it
 
4103
            is a polygon or multi-polygon.</para>
 
4104
          </listitem>
 
4105
        </varlistentry>
 
4106
 
 
4107
        <varlistentry>
 
4108
          <term>perimeter3d(geometry)</term>
 
4109
 
 
4110
          <listitem>
 
4111
            <para>Returns the 3-dimensional perimeter of the geometry, if it
 
4112
            is a polygon or multi-polygon.</para>
 
4113
          </listitem>
 
4114
        </varlistentry>
 
4115
 
 
4116
 
 
4117
          </variablelist>
 
4118
 
 
4119
      </sect2>
 
4120
 
 
4121
        <sect2>
 
4122
                <title>Geometry Outputs</title>
 
4123
                <variablelist>
 
4124
 
 
4125
                        <varlistentry>
 
4126
                                <term>AsBinary(geometry,{'NDR'|'XDR'})</term>
 
4127
 
 
4128
                                <listitem>
 
4129
                                        <para>Returns the geometry in the OGC "well-known-binary" format as a bytea, using little-endian (NDR) or big-endian (XDR) encoding. This is useful in binary cursors to pull data out of the database without converting it to a string representation.</para>
 
4130
                                </listitem>
 
4131
                        </varlistentry>
 
4132
 
 
4133
                        <varlistentry>
 
4134
                                <term>AsEWKT(geometry)</term>
 
4135
                                <listitem>
 
4136
                                        <para>Returns a Geometry in EWKT format (as text).</para>
 
4137
                                </listitem>
 
4138
                        </varlistentry>
 
4139
 
 
4140
                        <varlistentry>
 
4141
                                <term>AsEWKB(geometry, {'NDR'|'XDR'})</term>
 
4142
                                <listitem>
 
4143
                                        <para>Returns a Geometry in EWKB format (as bytea) using either little-endian (NDR) or big-endian (XDR) encoding.</para>
 
4144
                                </listitem>
 
4145
                        </varlistentry>
 
4146
 
 
4147
                        <varlistentry>
 
4148
                                <term>AsSVG(geometry, [rel], [precision])</term>
 
4149
                                <listitem>
 
4150
                                        <para>Return the geometry as an SVG path data. Use 1 as second argument to have the path data implemented in terms of relative moves, the default (or 0) uses absolute moves. Third argument may be used to reduce the maximum number of decimal digits used in output (defaults to 15). Point geometries will be rendered as cx/cy when 'rel' arg is 0, x/y when 'rel' is 1.</para>
 
4151
                                </listitem>
 
4152
                        </varlistentry>
 
4153
 
 
4154
                        <varlistentry>
 
4155
                                <term>AsGML(geometry, [precision])</term>
 
4156
                                <listitem>
 
4157
                                        <para>Return the geometry as a GML element.  Second argument may be used to reduce the maximum number of significant digits used in output (defaults to 15).</para>
 
4158
                                </listitem>
 
4159
                        </varlistentry>
 
4160
 
 
4161
                </variablelist>
 
4162
        </sect2>
 
4163
 
 
4164
 
 
4165
      <sect2>
 
4166
        <title>Geometry Constructors</title>
 
4167
 
 
4168
          <variablelist>
 
4169
 
 
4170
                <varlistentry>
 
4171
                        <term>GeomFromEWKT(text)</term>
 
4172
                        <listitem>
 
4173
                                <para>Makes a Geometry from EWKT.</para>
 
4174
                        </listitem>
 
4175
                </varlistentry>
 
4176
 
 
4177
                <varlistentry>
 
4178
                        <term>GeomFromEWKB(bytea)</term>
 
4179
                        <listitem>
 
4180
                                <para>Makes a Geometry from EWKB.</para>
 
4181
                        </listitem>
 
4182
                </varlistentry>
 
4183
 
 
4184
                <varlistentry>
 
4185
                  <term>MakePoint(&lt;x&gt;, &lt;y&gt;, [&lt;z&gt;], [&lt;m&gt;])</term>
 
4186
                  <listitem>
 
4187
                    <para>Creates a 2d,3dz or 4d point geometry.</para>
 
4188
                  </listitem>
 
4189
                </varlistentry>
 
4190
 
 
4191
                <varlistentry>
 
4192
                  <term>MakePointM(&lt;x&gt;, &lt;y&gt;, &lt;m&gt;)</term>
 
4193
 
 
4194
                  <listitem>
 
4195
                    <para>Creates a 3dm point geometry.</para>
 
4196
                  </listitem>
 
4197
                </varlistentry>
 
4198
 
 
4199
                <varlistentry>
 
4200
                  <term>MakeBox2D(&lt;LL&gt;, &lt;UR&gt;)</term>
 
4201
 
 
4202
                  <listitem>
 
4203
                    <para>Creates a BOX2D defined by the given point geometries.</para>
 
4204
                  </listitem>
 
4205
                </varlistentry>
 
4206
 
 
4207
                <varlistentry>
 
4208
                  <term>MakeBox3D(&lt;LLB&gt;, &lt;URT&gt;)</term>
 
4209
 
 
4210
                  <listitem>
 
4211
                    <para>Creates a BOX3D defined by the given point geometries.</para>
 
4212
                  </listitem>
 
4213
                </varlistentry>
 
4214
 
 
4215
                <varlistentry>
 
4216
                  <term>MakeLine(geometry set)</term>
 
4217
 
 
4218
                  <listitem>
 
4219
                    <para>Creates a Linestring from a set of point geometries.
 
4220
                    You might want to use a subselect to order points before
 
4221
                    feeding them to this aggregate.</para>
 
4222
                  </listitem>
 
4223
                </varlistentry>
 
4224
 
 
4225
                <varlistentry>
 
4226
                  <term>MakeLine(geometry, geometry)</term>
 
4227
                  <listitem>
 
4228
                    <para>Creates a Linestring from the two given point
 
4229
                    geometries.</para>
 
4230
                  </listitem>
 
4231
                </varlistentry>
 
4232
 
 
4233
                <varlistentry>
 
4234
                  <term>LineFromMultiPoint(multipoint)</term>
 
4235
 
 
4236
                  <listitem>
 
4237
                    <para>Creates a LineString from a MultiPoint geometry.</para>
 
4238
                  </listitem>
 
4239
                </varlistentry>
 
4240
 
 
4241
                <varlistentry>
 
4242
                  <term>AddPoint(linestring, point, [&lt;position&gt;])</term>
 
4243
 
 
4244
                  <listitem>
 
4245
                    <para>Adds a point to a LineString at position &lt;pos&gt;.
 
4246
                    Third parameter can be omitted or set to -1 for appending.
 
4247
                    </para>
 
4248
                  </listitem>
 
4249
                </varlistentry>
 
4250
 
 
4251
                <varlistentry>
 
4252
                  <term>MakePolygon(linestring, [linestring[]])</term>
 
4253
                  <listitem>
 
4254
                    <para>Creates a Polygon formed by the given 
 
4255
                    shell and array of holes. You can construct
 
4256
                    a geometry array using <link linkend="Accum">Accum</link>.
 
4257
                    Input geometries must be closed LINESTRINGS (see <link linkend="IsClosed">IsClosed</link> and <link linkend="GeometryType">GeometryType</link>).
 
4258
                    </para>
 
4259
                  </listitem>
 
4260
                </varlistentry>
 
4261
 
 
4262
                <varlistentry>
 
4263
                  <term>Polygonize(geometry set)</term>
 
4264
 
 
4265
                  <listitem>
 
4266
                    <para>Aggregate. Creates a GeometryCollection containing
 
4267
                    possible polygons formed from the costituent linework of
 
4268
                    a set of geometries.
 
4269
                    Only available when compiled against GEOS >= 2.1.0.</para>
 
4270
                  </listitem>
 
4271
                </varlistentry>
 
4272
 
 
4273
                <varlistentry>
 
4274
                  <term>Collect(geometry set)</term>
 
4275
 
 
4276
                  <listitem>
 
4277
                    <para>This function returns a GEOMETRYCOLLECTION or a MULTI object from a set
 
4278
                    of geometries. The collect() function is an "aggregate" function
 
4279
                    in the terminology of PostgreSQL. That means that it operators on
 
4280
                    lists of data, in the same way the sum() and mean() functions do.
 
4281
                    For example, "SELECT COLLECT(GEOM) FROM GEOMTABLE GROUP BY
 
4282
                    ATTRCOLUMN" will return a separate GEOMETRYCOLLECTION for each
 
4283
                    distinct value of ATTRCOLUMN.</para>
 
4284
                  </listitem>
 
4285
                </varlistentry>
 
4286
 
 
4287
                <varlistentry>
 
4288
                  <term>Collect(geometry, geometry)</term>
 
4289
 
 
4290
                  <listitem>
 
4291
                    <para>This function returns a geometry being a collection
 
4292
                    of two input geometries. Output type can be a MULTI* or 
 
4293
                    a GEOMETRYCOLLECTION.</para>
 
4294
                  </listitem>
 
4295
                </varlistentry>
 
4296
 
 
4297
                <varlistentry>
 
4298
                  <term>Dump(geometry)</term>
 
4299
 
 
4300
                  <listitem>
 
4301
                    <para>This is a set-returning function (SRF).
 
4302
                    It returns a set of geometry_dump rows, formed
 
4303
                    by a geometry (geom) and an array of integers (path).
 
4304
                    When the input geometry is a simple type
 
4305
                    (POINT,LINESTRING,POLYGON)
 
4306
                    a single record will be returned with an empty
 
4307
                    path array and the input geometry as geom.
 
4308
                    When the input geometry is a collection or multi
 
4309
                    it will return a record for each of the collection
 
4310
                    components, and the path will express the position
 
4311
                    of the component inside the collection.
 
4312
                    </para>
 
4313
 
 
4314
                    <para>NOTE: this function is not available for
 
4315
                    builds against PostgreSQL 7.2.x</para>
 
4316
                  </listitem>
 
4317
                </varlistentry>
 
4318
 
 
4319
          </variablelist>
 
4320
      </sect2>
 
4321
 
 
4322
      <sect2>
 
4323
        <title>Geometry Editors</title>
 
4324
          <variablelist>
 
4325
 
 
4326
        <varlistentry id="addbbox">
 
4327
          <term>AddBBOX(geometry)</term>
 
4328
          <listitem>
 
4329
            <para>Add bounding box to the geometry. This would make bounding
 
4330
            box based queries faster, but will increase the size of the
 
4331
            geometry.</para>
 
4332
          </listitem>
 
4333
        </varlistentry>
 
4334
 
 
4335
        <varlistentry id="dropbbox">
 
4336
          <term>DropBBOX(geometry)</term>
 
4337
          <listitem>
 
4338
            <para>Drop the bounding box cache from the geometry.
 
4339
            This reduces geometry size, but makes bounding-box based
 
4340
            queries slower.</para>
 
4341
          </listitem>
 
4342
        </varlistentry>
 
4343
 
 
4344
        <varlistentry>
 
4345
          <term>Force_collection(geometry)</term>
 
4346
 
 
4347
          <listitem>
 
4348
            <para>Converts the geometry into a GEOMETRYCOLLECTION. This is
 
4349
            useful for simplifying the WKB representation.</para>
 
4350
          </listitem>
 
4351
        </varlistentry>
 
4352
 
 
4353
        <varlistentry id="force_2d">
 
4354
          <term>Force_2d(geometry)</term>
 
4355
 
 
4356
          <listitem>
 
4357
            <para>Forces the geometries into a "2-dimensional mode" so that
 
4358
            all output representations will only have the X and Y coordinates.
 
4359
            This is useful for force OGC-compliant output (since OGC only
 
4360
            specifies 2-D geometries).</para>
 
4361
          </listitem>
 
4362
        </varlistentry>
 
4363
 
 
4364
        <varlistentry id="force_3dz">
 
4365
          <term>Force_3dz(geometry)</term>
 
4366
          <term>Force_3d(geometry)</term>
 
4367
 
 
4368
          <listitem>
 
4369
            <para>Forces the geometries into XYZ mode.</para>
 
4370
          </listitem>
 
4371
        </varlistentry>
 
4372
 
 
4373
        <varlistentry id="force_3dm">
 
4374
          <term>Force_3dm(geometry)</term>
 
4375
 
 
4376
          <listitem>
 
4377
            <para>Forces the geometries into XYM mode.</para>
 
4378
          </listitem>
 
4379
        </varlistentry>
 
4380
 
 
4381
        <varlistentry id="force_4d">
 
4382
          <term>Force_4d(geometry)</term>
 
4383
 
 
4384
          <listitem>
 
4385
            <para>Forces the geometries into XYZM mode.</para>
 
4386
          </listitem>
 
4387
        </varlistentry>
 
4388
 
 
4389
        <varlistentry>
 
4390
          <term>Multi(geometry)</term>
 
4391
 
 
4392
          <listitem>
 
4393
            <para>Returns the geometry as a MULTI* geometry. If the geometry
 
4394
            is already a MULTI*, it is returned unchanged.</para>
 
4395
          </listitem>
 
4396
        </varlistentry>
 
4397
 
 
4398
        <varlistentry>
 
4399
          <term>Transform(geometry,integer)</term>
 
4400
 
 
4401
          <listitem>
 
4402
            <para>Returns a new geometry with its coordinates transformed to
 
4403
            the SRID referenced by the integer parameter. The destination SRID
 
4404
            must exist in the <varname>SPATIAL_REF_SYS</varname> table.</para>
 
4405
          </listitem>
 
4406
        </varlistentry>
 
4407
 
 
4408
        <varlistentry>
 
4409
          <term>Translate(geometry,float8,float8,float8)</term>
 
4410
 
 
4411
          <listitem>
 
4412
            <para>Translates the geometry to a new location using the numeric
 
4413
            parameters as offsets. Ie: translate(geom,X,Y,Z).</para>
 
4414
          </listitem>
 
4415
        </varlistentry>
 
4416
 
 
4417
        <varlistentry>
 
4418
          <term>Reverse(geometry)</term>
 
4419
          <listitem>
 
4420
            <para>Returns the geometry with vertex order reversed.</para>
 
4421
          </listitem>
 
4422
        </varlistentry>
 
4423
 
 
4424
        <varlistentry>
 
4425
          <term>ForceRHR(geometry)</term>
 
4426
          <listitem>
 
4427
            <para>Force polygons of the collection to obey Right-Hand-Rule.</para>
 
4428
          </listitem>
 
4429
        </varlistentry>
 
4430
 
 
4431
        <varlistentry>
 
4432
          <term>Simplify(geometry, tolerance)</term>
 
4433
 
 
4434
          <listitem>
 
4435
            <para>Returns a "simplified" version of the given geometry using
 
4436
            the Douglas-Peuker algorithm. Will actually do something only with
 
4437
            (multi)lines and (multi)polygons but you can safely call it with
 
4438
            any kind of geometry. Since simplification occurs on a
 
4439
            object-by-object basis you can also feed a GeometryCollection to
 
4440
            this function. Note that returned geometry might loose its
 
4441
            simplicity (see <link linkend="IsSimple">IsSimple</link>)</para>
 
4442
          </listitem>
 
4443
        </varlistentry>
 
4444
 
 
4445
        <varlistentry>
 
4446
          <term>SnapToGrid(geometry, originX, originY, sizeX, sizeY)</term>
 
4447
          <term>SnapToGrid(geometry, sizeX, sizeY)</term>
 
4448
          <term>SnapToGrid(geometry, size)</term>
 
4449
 
 
4450
          <listitem>
 
4451
            <para>Snap all points of the input geometry to the grid
 
4452
            defined by its origin and cell size.
 
4453
            Remove consecutive points falling on the same cell,
 
4454
            eventually returning NULL if output points are not
 
4455
            enough to define a geometry of the given type.
 
4456
            Collapsed geometries in a collection are stripped
 
4457
            from it.
 
4458
            Note that returned geometry might loose its
 
4459
            simplicity (see <link linkend="IsSimple">IsSimple</link>).
 
4460
            </para>
 
4461
          </listitem>
 
4462
        </varlistentry>
 
4463
 
 
4464
        <varlistentry>
 
4465
          <term>Segmentize(geometry, maxlength)</term>
 
4466
 
 
4467
          <listitem>
 
4468
            <para>Return a modified [multi]polygon having no ring segment
 
4469
            longer then the given distance. Interpolated points will have Z
 
4470
            and M values (if needed) set to 0. Distance computation is
 
4471
            performed in 2d only.</para>
 
4472
          </listitem>
 
4473
        </varlistentry>
 
4474
 
 
4475
 
 
4476
          </variablelist>
 
4477
      </sect2>
 
4478
 
 
4479
      <sect2>
 
4480
        <title>Misc</title>
 
4481
          <variablelist>
 
4482
 
 
4483
                        <varlistentry>
 
4484
                                <term>Summary(geometry)</term>
 
4485
                                <listitem>
 
4486
                                        <para>Returns a text summary of the contents of the geometry.</para>
 
4487
                                </listitem>
 
4488
                        </varlistentry>
 
4489
 
 
4490
                        <varlistentry>
 
4491
                                <term>box2d(geometry)</term>
 
4492
                                <listitem>
 
4493
                                        <para>Returns a BOX2D representing the maximum extents of the geometry.</para>
 
4494
                                </listitem>
 
4495
                        </varlistentry>
 
4496
 
 
4497
                        <varlistentry>
 
4498
                                <term>box3d(geometry)</term>
 
4499
                                <listitem>
 
4500
                                        <para>Returns a BOX3D representing the maximum extents of the geometry.</para>
 
4501
                                </listitem>
 
4502
                        </varlistentry>
 
4503
 
 
4504
                        <varlistentry>
 
4505
                                <term>extent(geometry set)</term>
 
4506
 
 
4507
                                <listitem>
 
4508
                                        <para>The extent() function is an "aggregate" function in the terminology of PostgreSQL. That means that it operators on lists of data, in the same way the sum() and mean() functions do. For example, "SELECT EXTENT(GEOM) FROM GEOMTABLE" will return a BOX3D giving the maximum extend of all features in the table. Similarly, "SELECT EXTENT(GEOM) FROM GEOMTABLE GROUP BY CATEGORY" will return one extent result for each category.</para>
 
4509
                                </listitem>
 
4510
                        </varlistentry>
 
4511
 
 
4512
                        <varlistentry id="zmflag">
 
4513
                                <term>zmflag(geometry)</term>
 
4514
                                <listitem>
 
4515
                                        <para>Returns ZM (dimension semantic) flag of the geometries as a small int. Values are: 0=2d, 1=3dm, 2=3dz, 3=4d.  </para>
 
4516
                                </listitem>
 
4517
                        </varlistentry>
 
4518
 
 
4519
                        <varlistentry id="hasbbox">
 
4520
                                <term>HasBBOX(geometry)</term>
 
4521
                                <listitem>
 
4522
                                        <para>Returns TRUE if the bbox of this geometry is cached, FALSE otherwise. Use <link linkend="addbbox">addBBOX()</link> and <link linkend="dropbbox">dropBBOX()</link> to control caching.</para>
 
4523
                                </listitem>
 
4524
                        </varlistentry>
 
4525
 
 
4526
                        <varlistentry id="ndims">
 
4527
                                <term>ndims(geometry)</term>
 
4528
                                <listitem>
 
4529
                                        <para>Returns number of dimensions of the geometry as a small int. Values are: 2,3 or 4.</para>
 
4530
                                </listitem>
 
4531
                        </varlistentry>
 
4532
 
 
4533
                        <varlistentry>
 
4534
                                <term>nrings(geometry)</term>
 
4535
                                <listitem>
 
4536
                                        <para>If the geometry is a polygon or multi-polygon returns the number of rings.</para>
 
4537
                                </listitem>
 
4538
                        </varlistentry>
 
4539
 
 
4540
                        <varlistentry>
 
4541
                                <term>npoints(geometry)</term>
 
4542
                                <listitem>
 
4543
                                        <para>Returns the number of points in the geometry.</para>
 
4544
                                </listitem>
 
4545
                        </varlistentry>
 
4546
 
 
4547
                <varlistentry id="IsValid">
 
4548
                  <term>isvalid(geometry)</term>
 
4549
 
 
4550
                  <listitem>
 
4551
                    <para>returns true if this geometry is valid.</para>
 
4552
                  </listitem>
 
4553
                </varlistentry>
 
4554
 
 
4555
                <varlistentry>
 
4556
                  <term>expand(geometry, float)</term>
 
4557
 
 
4558
                  <listitem>
 
4559
                    <para>This function returns a bounding box expanded in all
 
4560
                    directions from the bounding box of the input geometry, by an
 
4561
                    amount specified in the second argument. Very useful for
 
4562
                    distance() queries, to add an index filter to the query.</para>
 
4563
                  </listitem>
 
4564
                </varlistentry>
 
4565
 
 
4566
                <varlistentry>
 
4567
                        <term>estimated_extent([schema], table, geocolumn)</term>
 
4568
                        <listitem>
 
4569
                                <para> Return the 'estimated' extent of the given spatial table.  The estimated is taken from the geometry column's statistics. The current schema will be used if not specified.</para>
 
4570
 
 
4571
                                <para>For PostgreSQL&gt;=8.0.0 statistics are gathered by VACUUM ANALYZE and resulting extent will be about 95% of the real one.</para>
 
4572
                                <para>For PostgreSQL&lt;8.0.0 statistics are gathered by update_geometry_stats() and resulting extent will be exact.</para>
 
4573
                        </listitem>
 
4574
                </varlistentry>
 
4575
 
 
4576
        <varlistentry>
 
4577
          <term>find_srid(varchar,varchar,varchar)</term>
 
4578
 
 
4579
          <listitem>
 
4580
            <para>The syntax is find_srid(&lt;db/schema&gt;, &lt;table&gt;,
 
4581
            &lt;column&gt;) and the function returns the integer SRID of the
 
4582
            specified column by searching through the GEOMETRY_COLUMNS table.
 
4583
            If the geometry column has not been properly added with the
 
4584
            AddGeometryColumns() function, this function will not work
 
4585
            either.</para>
 
4586
          </listitem>
 
4587
        </varlistentry>
 
4588
 
 
4589
 
 
4590
        <varlistentry>
 
4591
          <term>mem_size(geometry)</term>
 
4592
 
 
4593
          <listitem>
 
4594
            <para>Returns the amount of space (in bytes) the geometry
 
4595
            takes.</para>
 
4596
          </listitem>
 
4597
        </varlistentry>
 
4598
 
 
4599
        <varlistentry>
 
4600
          <term>numb_sub_objects(geometry)</term>
 
4601
 
 
4602
          <listitem>
 
4603
            <para>Returns the number of objects stored in the geometry. This
 
4604
            is useful for MULTI-geometries and GEOMETRYCOLLECTIONs.</para>
 
4605
          </listitem>
 
4606
        </varlistentry>
 
4607
 
 
4608
        <varlistentry>
 
4609
          <term>point_inside_circle(geometry,float,float,float)</term>
 
4610
 
 
4611
          <listitem>
 
4612
            <para>The syntax for this functions is
 
4613
            point_inside_circle(&lt;geometry&gt;,&lt;circle_center_x&gt;,&lt;circle_center_y&gt;,&lt;radius&gt;).
 
4614
            Returns the true if the geometry is a point and is inside the
 
4615
            circle. Returns false otherwise.</para>
 
4616
          </listitem>
 
4617
        </varlistentry>
 
4618
 
 
4619
        <varlistentry>
 
4620
          <term>xmin(box3d) ymin(box3d) zmin(box3d)</term>
 
4621
 
 
4622
          <listitem>
 
4623
            <para>Returns the requested minima of a bounding box.</para>
 
4624
          </listitem>
 
4625
        </varlistentry>
 
4626
 
 
4627
        <varlistentry>
 
4628
          <term>xmax(box3d) ymax(box3d) zmax(box3d)</term>
 
4629
 
 
4630
          <listitem>
 
4631
            <para>Returns the requested maxima of a bounding box.</para>
 
4632
          </listitem>
 
4633
        </varlistentry>
 
4634
 
 
4635
        <varlistentry>
 
4636
          <term>line_interpolate_point(geometry, proportion)</term>
 
4637
 
 
4638
          <listitem>
 
4639
            <para>Interpolates a point along a line. First argument must be a
 
4640
            LINESTRING. Second argument is a float between 0 and 1. Returns a
 
4641
            point.</para>
 
4642
          </listitem>
 
4643
        </varlistentry>
 
4644
 
 
4645
        <varlistentry id="Accum">
 
4646
          <term>Accum(geometry set)</term>
 
4647
 
 
4648
          <listitem>
 
4649
            <para>Aggregate. Constructs an array of geometries.</para>
 
4650
          </listitem>
 
4651
        </varlistentry>
 
4652
 
 
4653
 
 
4654
        </variablelist>
 
4655
      </sect2>
 
4656
 
 
4657
 
 
4658
    </sect1>
 
4659
  </chapter>
 
4660
 
 
4661
        <appendix>
 
4662
                <title>Release Notes</title>
 
4663
 
 
4664
                <sect1>
 
4665
                        <title>Release 1.0.0</title>
 
4666
                        <para>Release date: 2005/04/19</para>
 
4667
 
 
4668
                        <para>Final 1.0.0 release.
 
4669
                        Contains a few bug fixes, some improvements
 
4670
                        in the loader (most notably support for older
 
4671
                        postgis versions), and more docs.
 
4672
                        </para>
 
4673
 
 
4674
                        <sect2>
 
4675
                                <title>Upgrading</title>
 
4676
 
 
4677
                                <para>If you are upgrading from
 
4678
                                release 1.0.0RC6 you <emphasis>DO
 
4679
                                NOT</emphasis> need a dump/reload.</para>
 
4680
 
 
4681
                                <para>Upgrading from any other precedent
 
4682
                                release requires a dump/reload. 
 
4683
                                See the <link
 
4684
                                linkend="upgrading">upgrading</link>
 
4685
                                chapter for more informations.</para>
 
4686
                        </sect2>
 
4687
 
 
4688
                        <sect2>
 
4689
                                <title>Library changes</title>
 
4690
        <para>BUGFIX in transform() releasing random memory address</para>
 
4691
        <para>BUGFIX in force_3dm() allocating less memory then required</para>
 
4692
        <para>BUGFIX in join selectivity estimator (defaults, leaks, tuplecount, sd)</para>
 
4693
                        </sect2>
 
4694
 
 
4695
                        <sect2>
 
4696
                                <title>Other changes/additions</title>
 
4697
        <para>BUGFIX in shp2pgsql escape of values starting with tab or single-quote</para>
 
4698
        <para>NEW manual pages for loader/dumper</para>
 
4699
        <para>NEW shp2pgsql support for old (HWGEOM) postgis versions</para>
 
4700
        <para>NEW -p (prepare) flag for shp2pgsql</para>
 
4701
        <para>NEW manual chapter about OGC compliancy enforcement</para>
 
4702
        <para>NEW autoconf support for JTS lib</para>
 
4703
        <para>BUGFIX in estimator testers (support for LWGEOM and schema parsing)</para>
 
4704
                        </sect2>
 
4705
 
 
4706
                </sect1>
 
4707
 
 
4708
 
 
4709
                <sect1>
 
4710
                        <title>Release 1.0.0RC6</title>
 
4711
                        <para>Release date: 2005/03/30</para>
 
4712
 
 
4713
                        <para>Sixth release candidate for 1.0.0.
 
4714
                        Contains a few bug fixes and cleanups.</para>
 
4715
 
 
4716
                        <sect2>
 
4717
                                <title>Upgrading</title>
 
4718
                                <para>You need a dump/reload to upgrade
 
4719
                                from precedent releases. See the <link
 
4720
                                linkend="upgrading">upgrading</link>
 
4721
                                chapter for more informations.</para>
 
4722
                        </sect2>
 
4723
 
 
4724
                        <sect2>
 
4725
                                <title>Library changes</title>
 
4726
        <para>BUGFIX in multi()</para>
 
4727
        <para>early return [when noop] from multi()</para>
 
4728
                        </sect2>
 
4729
 
 
4730
                        <sect2>
 
4731
                                <title>Scripts changes</title>
 
4732
        <para>dropped {x,y}{min,max}(box2d) functions</para>
 
4733
                        </sect2>
 
4734
 
 
4735
                        <sect2>
 
4736
                                <title>Other changes</title>
 
4737
        <para>BUGFIX in postgis_restore.pl scrip</para>
 
4738
        <para>BUGFIX in dumper's 64bit support</para>
 
4739
                        </sect2>
 
4740
 
 
4741
                </sect1>
 
4742
 
 
4743
 
 
4744
                <sect1>
 
4745
                        <title>Release 1.0.0RC5</title>
 
4746
                        <para>Release date: 2005/03/25</para>
 
4747
 
 
4748
                        <para>Fifth release candidate for 1.0.0.
 
4749
                        Contains a few bug fixes and a improvements.</para>
 
4750
 
 
4751
                        <sect2>
 
4752
                                <title>Upgrading</title>
 
4753
 
 
4754
                                <para>If you are upgrading from
 
4755
                                release 1.0.0RC4 you <emphasis>DO
 
4756
                                NOT</emphasis> need a dump/reload.</para>
 
4757
 
 
4758
                                <para>Upgrading from any other precedent
 
4759
                                release requires a dump/reload. 
 
4760
                                See the <link
 
4761
                                linkend="upgrading">upgrading</link>
 
4762
                                chapter for more informations.</para>
 
4763
                        </sect2>
 
4764
 
 
4765
                        <sect2>
 
4766
                                <title>Library changes</title>
 
4767
        <para>BUGFIX (segfaulting) in box3d computation (yes, another!).</para>
 
4768
        <para>BUGFIX (segfaulting) in estimated_extent().</para>
 
4769
                        </sect2>
 
4770
 
 
4771
                        <sect2>
 
4772
                                <title>Other changes</title>
 
4773
        <para>Small build scripts and utilities refinements.</para>
 
4774
        <para>Additional performance tips documented.</para>
 
4775
                        </sect2>
 
4776
 
 
4777
                </sect1>
 
4778
 
 
4779
                <sect1>
 
4780
                        <title>Release 1.0.0RC4</title>
 
4781
                        <para>Release date: 2005/03/18</para>
 
4782
 
 
4783
                        <para>Fourth release candidate for 1.0.0.
 
4784
                        Contains bug fixes and a few improvements.</para>
 
4785
 
 
4786
                        <sect2>
 
4787
                                <title>Upgrading</title>
 
4788
                                <para>You need a dump/reload to upgrade
 
4789
                                from precedent releases. See the <link
 
4790
                                linkend="upgrading">upgrading</link>
 
4791
                                chapter for more informations.</para>
 
4792
                        </sect2>
 
4793
 
 
4794
                        <sect2>
 
4795
                                <title>Library changes</title>
 
4796
<para>BUGFIX (segfaulting) in geom_accum().</para>
 
4797
<para>BUGFIX in 64bit architectures support.</para>
 
4798
<para>BUGFIX in box3d computation function with collections.</para>
 
4799
<para>NEW subselects support in selectivity estimator.</para>
 
4800
<para>Early return from force_collection.</para>
 
4801
<para>Consistency check fix in SnapToGrid().</para>
 
4802
<para>Box2d output changed back to 15 significant digits.</para>
 
4803
                        </sect2>
 
4804
 
 
4805
                        <sect2>
 
4806
                                <title>Scripts changes</title>
 
4807
<para>NEW distance_sphere() function.</para>
 
4808
<para>Changed get_proj4_from_srid implementation to use PL/PGSQL instead of SQL.</para>
 
4809
                        </sect2>
 
4810
 
 
4811
                        <sect2>
 
4812
                                <title>Other changes</title>
 
4813
<para>BUGFIX in loader and dumper handling of MultiLine shapes</para>
 
4814
<para>BUGFIX in loader, skipping all but first hole of polygons.</para>
 
4815
<para>jdbc2: code cleanups, Makefile improvements</para>
 
4816
<para>FLEX and YACC variables set *after* pgsql Makefile.global is included and only if the pgsql *stripped* version evaulates to the empty string</para>
 
4817
<para>Added already generated parser in release</para>
 
4818
<para>Build scripts refinements</para>
 
4819
<para>improved version handling, central Version.config</para>
 
4820
<para>improvements in postgis_restore.pl</para>
 
4821
                        </sect2>
 
4822
 
 
4823
                </sect1>
 
4824
 
 
4825
                <sect1>
 
4826
                        <title>Release 1.0.0RC3</title>
 
4827
                        <para>Release date: 2005/02/24</para>
 
4828
 
 
4829
                        <para>Third release candidate for 1.0.0.
 
4830
                        Contains many bug fixes and improvements.</para>
 
4831
 
 
4832
                        <sect2>
 
4833
                                <title>Upgrading</title>
 
4834
                                <para>You need a dump/reload to upgrade
 
4835
                                from precedent releases. See the <link
 
4836
                                linkend="upgrading">upgrading</link>
 
4837
                                chapter for more informations.</para>
 
4838
                        </sect2>
 
4839
 
 
4840
                        <sect2>
 
4841
                                <title>Library changes</title>
 
4842
        <para>BUGFIX in transform(): missing SRID, better error handling.</para>
 
4843
        <para>BUGFIX in memory alignment handling</para>
 
4844
        <para>BUGFIX in force_collection() causing mapserver connector failures on simple (single) geometry types.</para>
 
4845
        <para>BUGFIX in GeometryFromText() missing to add a bbox cache.</para>
 
4846
        <para>reduced precision of box2d output.</para>
 
4847
        <para>prefixed DEBUG macros with PGIS_ to avoid clash with pgsql one</para>
 
4848
        <para>plugged a leak in GEOS2POSTGIS converter</para>
 
4849
        <para>Reduced memory usage by early releasing query-context palloced one.</para>
 
4850
                        </sect2>
 
4851
 
 
4852
                        <sect2>
 
4853
                                <title>Scripts changes</title>
 
4854
        <para>BUGFIX in 72 index bindings.</para>
 
4855
        <para>BUGFIX in probe_geometry_columns() to work with PG72 and support multiple geometry columns in a single table</para>
 
4856
        <para>NEW bool::text cast</para>
 
4857
        <para>Some functions made IMMUTABLE from STABLE, for performance
 
4858
        improvement.</para>
 
4859
                        </sect2>
 
4860
 
 
4861
                        <sect2>
 
4862
                                <title>JDBC changes</title>
 
4863
        <para>jdbc2: small patches, box2d/3d tests, revised docs and license.</para>
 
4864
        <para>jdbc2: bug fix and testcase in for pgjdbc 8.0 type autoregistration</para>
 
4865
        <para>jdbc2: Removed use of jdk1.4 only features to enable build with older jdk releases.</para>
 
4866
        <para>jdbc2: Added support for building against pg72jdbc2.jar</para>
 
4867
        <para>jdbc2: updated and cleaned makefile</para>
 
4868
        <para>jdbc2: added BETA support for jts geometry classes</para>
 
4869
        <para>jdbc2: Skip known-to-fail tests against older PostGIS servers.</para>
 
4870
        <para>jdbc2: Fixed handling of measured geometries in EWKT.</para>
 
4871
                        </sect2>
 
4872
 
 
4873
                        <sect2>
 
4874
                                <title>Other changes</title>
 
4875
        <para>new performance tips chapter in manual</para>
 
4876
        <para>documentation updates: pgsql72 requirement, lwpostgis.sql</para>
 
4877
        <para>few changes in autoconf </para>
 
4878
        <para>BUILDDATE extraction made more portable</para>
 
4879
        <para>fixed spatial_ref_sys.sql to avoid vacuuming the whole
 
4880
        database.</para>
 
4881
        <para>spatial_ref_sys: changed Paris entries to match the ones
 
4882
        distributed with 0.x.</para>
 
4883
                        </sect2>
 
4884
 
 
4885
                </sect1>
 
4886
 
 
4887
                <sect1>
 
4888
                        <title>Release 1.0.0RC2</title>
 
4889
                        <para>Release date: 2005/01/26</para>
 
4890
 
 
4891
                        <para>Second release candidate for 1.0.0
 
4892
                        containing bug fixes and a few improvements.</para>
 
4893
 
 
4894
                        <sect2>
 
4895
                                <title>Upgrading</title>
 
4896
        
 
4897
                                <para>You need a dump/reload to upgrade
 
4898
                                from precedent releases. See the <link
 
4899
                                linkend="upgrading">upgrading</link>
 
4900
                                chapter for more informations.</para>
 
4901
                        </sect2>
 
4902
 
 
4903
                        <sect2>
 
4904
                                <title>Library changes</title>
 
4905
 
 
4906
<para>BUGFIX in pointarray box3d computation</para>
 
4907
<para>BUGFIX in distance_spheroid definition</para>
 
4908
<para>BUGFIX in transform() missing to update bbox cache</para>
 
4909
<para>NEW jdbc driver (jdbc2)</para>
 
4910
<para>GEOMETRYCOLLECTION(EMPTY) syntax support for backward compatibility</para>
 
4911
<para>Faster binary outputs</para>
 
4912
<para>Stricter OGC WKB/WKT constructors</para>
 
4913
 
 
4914
                        </sect2>
 
4915
 
 
4916
                        <sect2>
 
4917
                                <title>Scripts changes</title>
 
4918
 
 
4919
<para>More correct STABLE, IMMUTABLE, STRICT uses in lwpostgis.sql</para>
 
4920
<para>stricter OGC WKB/WKT constructors</para>
 
4921
 
 
4922
                        </sect2>
 
4923
 
 
4924
                        <sect2>
 
4925
                                <title>Other changes</title>
 
4926
 
 
4927
<para>Faster and more robust loader (both i18n and not)</para>
 
4928
<para>Initial autoconf script</para>
 
4929
 
 
4930
                        </sect2>
 
4931
 
 
4932
                </sect1>
 
4933
 
 
4934
                <sect1>
 
4935
                        <title>Release 1.0.0RC1</title>
 
4936
                        <para>Release date: 2005/01/13</para>
 
4937
 
 
4938
                        <para>This is the first candidate of a
 
4939
                        major postgis release, with internal
 
4940
                        storage of postgis types redesigned to be smaller
 
4941
                        and faster on indexed queries.</para>
 
4942
 
 
4943
                        <sect2>
 
4944
                                <title>Upgrading</title>
 
4945
 
 
4946
                                <para>You need a dump/reload to upgrade
 
4947
                                from precedent releases. See the <link
 
4948
                                linkend="upgrading">upgrading</link>
 
4949
                                chapter for more informations.</para>
 
4950
                        </sect2>
 
4951
 
 
4952
                        <sect2>
 
4953
                                <title>Changes</title>
 
4954
 
 
4955
                                <para>
 
4956
                                Faster canonical input parsing.
 
4957
                                </para>
 
4958
 
 
4959
                                <para>
 
4960
                                Lossless canonical output.
 
4961
                                </para>
 
4962
 
 
4963
                                <para>
 
4964
                                EWKB Canonical binary IO with PG>73.
 
4965
                                </para>
 
4966
 
 
4967
                                <para>
 
4968
                                Support for up to 4d coordinates, providing
 
4969
                                lossless shapefile->postgis->shapefile
 
4970
                                conversion.
 
4971
                                </para>
 
4972
 
 
4973
                                <para>
 
4974
                                New function: UpdateGeometrySRID(), AsGML(),
 
4975
                                SnapToGrid(), ForceRHR(), estimated_extent(),
 
4976
                                accum().
 
4977
                                </para>
 
4978
 
 
4979
                                <para>
 
4980
                                Vertical positioning indexed operators.
 
4981
                                </para>
 
4982
 
 
4983
                                <para>
 
4984
                                JOIN selectivity function.
 
4985
                                </para>
 
4986
 
 
4987
                                <para>
 
4988
                                More geometry constructors / editors.
 
4989
                                </para>
 
4990
 
 
4991
                                <para>
 
4992
                                Postgis extension API.
 
4993
                                </para>
 
4994
 
 
4995
                                <para>
 
4996
                                UTF8 support in loader.
 
4997
                                </para>
 
4998
 
 
4999
                        </sect2>
 
5000
                </sect1>
 
5001
        </appendix>
 
5002
</book>