tinyows 1.2.2
ows_psql.c
Go to the documentation of this file.
1/*
2 Copyright (c) <2007-2012> <Barbara Philippot - Olivier Courtin>
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 IN THE SOFTWARE.
21*/
22
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <assert.h>
27#include <string.h>
28#include <time.h>
29
30#include "ows.h"
31
32
33/*
34 * Return the name of the id column from table matching layer name
35 */
37{
38 ows_layer_node *ln = NULL;
39
40 assert(o);
41 assert(o->layers);
42 assert(layer_name);
43
44 for (ln = o->layers->first ; ln ; ln = ln->next)
45 if (ln->layer->name && ln->layer->storage
46 && !strcmp(ln->layer->name->buf, layer_name->buf))
47 return ln->layer->storage->pkey;
48
49 return NULL;
50}
51
52
53/*
54 * Execute an SQL request
55 */
56PGresult * ows_psql_exec(ows *o, const char *sql)
57{
58 PGresult* res;
59
60 assert(o);
61 assert(sql);
62 assert(o->pg);
63
64 ows_log(o, 8, sql);
65 res = PQexecParams(o->pg, sql, 0, NULL, NULL, NULL, NULL, 0);
66 if (strlen(PQresultErrorMessage(res)))
67 ows_log(o, 1, PQresultErrorMessage(res));
68
69 return res;
70}
71
72
73/*
74 * Return geometry columns from the table matching layer name
75 */
77{
78 ows_layer_node *ln = NULL;
79
80 assert(o);
81 assert(o->layers);
82 assert(layer_name);
83
84 for (ln = o->layers->first ; ln ; ln = ln->next)
85 if (ln->layer->name && ln->layer->storage
86 && !strcmp(ln->layer->name->buf, layer_name->buf))
87 return ln->layer->storage->geom_columns;
88
89 return NULL;
90}
91
92
93/*
94 * Return schema name from a given layer
95 */
97{
98 ows_layer_node *ln = NULL;
99
100 assert(o);
101 assert(o->layers);
102 assert(layer_name);
103
104 for (ln = o->layers->first ; ln ; ln = ln->next)
105 if (ln->layer->name && ln->layer->storage
106 && !strcmp(ln->layer->name->buf, layer_name->buf))
107 return ln->layer->storage->schema;
108
109 return NULL;
110}
111
112
113/*
114 * Return table name from a given layer
115 */
117{
118 ows_layer_node *ln = NULL;
119
120 assert(o);
121 assert(o->layers);
122 assert(layer_name);
123
124 for (ln = o->layers->first ; ln ; ln = ln->next)
125 if (ln->layer->name && ln->layer->storage
126 && !strcmp(ln->layer->name->buf, layer_name->buf))
127 return ln->layer->storage->table;
128
129 return NULL;
130}
131
132
133/*
134 * Check if a given WKT geometry is or not valid
135 */
137{
138 buffer *sql;
139 PGresult *res;
140 bool ret = false;
141
142 assert(o);
143 assert(geom);
144
145 sql = buffer_init();
146 buffer_add_str(sql, "SELECT ST_isvalid(ST_geometryfromtext('");
147 buffer_copy(sql, geom);
148 buffer_add_str(sql, "', -1));");
149
150 res = ows_psql_exec(o, sql->buf);
151 buffer_free(sql);
152
153 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1
154 && (char) PQgetvalue(res, 0, 0)[0] == 't') ret = true;
155
156 PQclear(res);
157 return ret;
158}
159
160
161/*
162 * Check if the specified column from a layer_name is (or not) a geometry column
163 */
164bool ows_psql_is_geometry_column(ows * o, buffer * layer_name, buffer * column)
165{
166 ows_layer_node *ln;
167
168 assert(o);
169 assert(o->layers);
170 assert(layer_name);
171 assert(column);
172
173 for (ln = o->layers->first ; ln ; ln = ln->next)
174 if (ln->layer->name && ln->layer->storage
175 && !strcmp(ln->layer->name->buf, layer_name->buf))
176 return in_list(ln->layer->storage->geom_columns, column);
177
178 return false;
179}
180
181
182/*
183 * Return a list of not null properties from the table matching layer name
184 */
186{
187 ows_layer_node *ln;
188
189 assert(o);
190 assert(o->layers);
191 assert(layer_name);
192
193 for (ln = o->layers->first ; ln ; ln = ln->next)
194 if (ln->layer->name && ln->layer->storage
195 && !strcmp(ln->layer->name->buf, layer_name->buf))
196 return ln->layer->storage->not_null_columns;
197
198 return NULL;
199}
200
201
202/*
203 * Returns the constraint name for a table column.
204 * Used to return enumeration constraints in describe feature type request.
205 */
206buffer *ows_psql_column_constraint_name(ows * o, buffer * column_name, buffer * table_name)
207{
208 buffer *sql;
209 PGresult *res;
210 buffer *constraint_name;
211
212 constraint_name = buffer_init();
213
214 assert(o);
215 assert(column_name);
216 assert(table_name);
217
218 sql = buffer_init();
219
220 buffer_add_str(sql, "SELECT constraint_name FROM information_schema.constraint_column_usage WHERE table_name = '");
221 buffer_add_str(sql, table_name->buf);
222 buffer_add_str(sql, "' AND column_name='");
223 buffer_add_str(sql, column_name->buf);
224 buffer_add_str(sql, "'");
225
226 res = ows_psql_exec(o, sql->buf);
227 buffer_free(sql);
228
229 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
230 PQclear(res);
231 return constraint_name;
232 }
233
234 buffer_add_str(constraint_name, PQgetvalue(res, 0, 0));
235 PQclear(res);
236
237 return constraint_name;
238}
239
240/*
241 * Returns the list of possible values for a column according to the constraint value.
242 * Used to return enumeration constraints in describe feature type request.
243 */
245{
246 buffer *sql;
247 PGresult *res;
248 list *constraints;
249 buffer *constraint_value;
250 buffer *buf;
251 size_t i;
252 size_t j;
253
254 constraints = list_init();
255 constraint_value = buffer_init();
256
257 assert(o);
258 assert(constraint_name);
259
260 sql = buffer_init();
261
262 buffer_add_str(sql, "SELECT check_clause FROM information_schema.check_constraints WHERE constraint_name = '");
263 buffer_add_str(sql, constraint_name->buf);
264 buffer_add_str(sql, "'");
265
266 res = ows_psql_exec(o, sql->buf);
267
268 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
269 PQclear(res);
270 return constraints;
271 }
272
273 buffer_add_str(constraint_value, PQgetvalue(res, 0, 0));
274 PQclear(res);
275
276 j=0;
277 buf = buffer_init();
278 for (i = 0; constraint_value->buf[i] != '\0'; i++) {
279 if(constraint_value->buf[i] == '\'') {
280 j++;
281 if(j%2==1) {
282 buf = buffer_init();
283 } else {
284 list_add(constraints, buf);
285 }
286 } else if(j%2==1)
287 buffer_add(buf, constraint_value->buf[i]);
288 }
289
290 return constraints;
291}
292
293
294/*
295 * Return the column's name matching the specified number from table
296 * (Only use in specific FE position function, so not directly inside
297 * storage handle mechanism)
298 */
299buffer *ows_psql_column_name(ows * o, buffer * layer_name, int number)
300{
301 buffer *sql;
302 PGresult *res;
303 buffer *column;
304
305 assert(o);
306 assert(layer_name);
307
308 sql = buffer_init();
309 column = buffer_init();
310
311 buffer_add_str(sql, "SELECT a.attname FROM pg_class c, pg_attribute a, pg_type t WHERE c.relname ='");
312 buffer_copy(sql, layer_name);
313 buffer_add_str(sql, "' AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid AND a.attnum = ");
314 buffer_add_int(sql, number);
315
316 res = ows_psql_exec(o, sql->buf);
317 buffer_free(sql);
318
319 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
320 PQclear(res);
321 return column;
322 }
323
324 buffer_add_str(column, PQgetvalue(res, 0, 0));
325 PQclear(res);
326
327 return column;
328}
329
330/*
331 * Returns the column character_maximum_length value from the database
332 * information schema.
333 * Used to return maxLength constraint in describe feature type request.
334 */
336{
337 buffer *sql;
338 PGresult *res;
339 buffer *character_maximum_length;
340
341 character_maximum_length = buffer_init();
342
343 assert(o);
344 assert(column_name);
345 assert(table_name);
346
347 sql = buffer_init();
348
349 buffer_add_str(sql, "SELECT character_maximum_length FROM information_schema.columns WHERE table_name = '");
350 buffer_add_str(sql, table_name->buf);
351 buffer_add_str(sql, "' and column_name = '");
352 buffer_add_str(sql, column_name->buf);
353 buffer_add_str(sql, "'");
354
355 res = ows_psql_exec(o, sql->buf);
356 buffer_free(sql);
357
358 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
359 PQclear(res);
360 return character_maximum_length;
361 }
362
363 buffer_add_str(character_maximum_length, PQgetvalue(res, 0, 0));
364 PQclear(res);
365
366 return character_maximum_length;
367}
368
369
370/*
371 * Retrieve description of a table matching a given layer name
372 */
374{
375 ows_layer_node *ln = NULL;
376
377 assert(o);
378 assert(o->layers);
379 assert(layer_name);
380
381 for (ln = o->layers->first ; ln ; ln = ln->next)
382 if (ln->layer->name && ln->layer->storage
383 && !strcmp(ln->layer->name->buf, layer_name->buf))
384 return ln->layer->storage->attributes;
385
386 return NULL;
387}
388
389
390/*
391 * Retrieve an ows_version, related to current PostGIS version.
392 */
394{
395 list *l;
396 PGresult * res;
397 ows_version * v = NULL;
398
399 res = ows_psql_exec(o, "SELECT substr(postgis_full_version(), 10, 5)");
400 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
401 PQclear(res);
402 return NULL;
403 }
404
405 l = list_explode_str('.', (char *) PQgetvalue(res, 0, 0));
406
407 if ( l->size == 3
408 && check_regexp(l->first->value->buf, "^[0-9]+$")
409 && check_regexp(l->first->next->value->buf, "^[0-9]+$")
410 && check_regexp(l->last->value->buf, "^[0-9]+$") ) {
411 v = ows_version_init();
412 v->major = atoi(l->first->value->buf);
413 v->minor = atoi(l->first->next->value->buf);
414 v->release = atoi(l->last->value->buf);
415 }
416
417 list_free(l);
418 PQclear(res);
419 return v;
420}
421
422
423/*
424 * TODO
425 */
427{
428 assert(type);
429
430 if (buffer_cmp(type, "int2")) return true;
431 if (buffer_cmp(type, "int4")) return true;
432 if (buffer_cmp(type, "int8")) return true;
433 if (buffer_cmp(type, "float4")) return true;
434 if (buffer_cmp(type, "float8")) return true;
435 if (buffer_ncmp(type, "numeric", 7)) return true;
436
437 return false;
438}
439
440
441/*
442 * Convert a PostgreSql type to a valid
443 * OGC XMLSchema's type
444 */
445char *ows_psql_to_xsd(buffer * type, enum wfs_format format)
446{
447 int gml_version = 311;
448
449 assert(type);
450 assert(format);
451
452 if (format == WFS_GML212) gml_version = 212;
453
454 if (buffer_case_cmp(type, "geometry")) return "gml:GeometryPropertyType";
455 if (buffer_cmp(type, "geography")) return "gml:GeometryPropertyType";
456 if (buffer_cmp(type, "int2")) return "short";
457 if (buffer_cmp(type, "int4")) return "int";
458 if (buffer_cmp(type, "int8")) return "long";
459 if (buffer_cmp(type, "float4")) return "float";
460 if (buffer_cmp(type, "float8")) return "double";
461 if (buffer_cmp(type, "bool")) return "boolean";
462 if (buffer_cmp(type, "bytea")) return "byte";
463 if (buffer_cmp(type, "date")) return "date";
464 if (buffer_cmp(type, "time")) return "time";
465 if (buffer_ncmp(type, "numeric", 7)) return "decimal";
466 if (buffer_ncmp(type, "timestamp", 9)) return "dateTime"; /* Could be also timestamptz */
467 if (buffer_cmp(type, "POINT")) return "gml:PointPropertyType";
468 if (buffer_cmp(type, "LINESTRING") && gml_version == 212) return "gml:LineStringPropertyType";
469 if (buffer_cmp(type, "LINESTRING") && gml_version >= 311) return "gml:CurvePropertyType";
470 if (buffer_cmp(type, "POLYGON") && gml_version == 212) return "gml:PolygonPropertyType";
471 if (buffer_cmp(type, "POLYGON") && gml_version >= 311) return "gml:SurfacePropertyType";
472 if (buffer_cmp(type, "TRIANGLE")) return "gml:TrianglePropertyType";
473 if (buffer_cmp(type, "MULTIPOINT")) return "gml:MultiPointPropertyType";
474 if (buffer_cmp(type, "MULTILINESTRING") && gml_version == 212) return "gml:MultiLineStringPropertyType";
475 if (buffer_cmp(type, "MULTILINESTRING") && gml_version >= 311) return "gml:MultiCurvePropertyType";
476 if (buffer_cmp(type, "MULTIPOLYGON") && gml_version == 212) return "gml:MultiPolygonPropertyType";
477 if (buffer_cmp(type, "MULTIPOLYGON") && gml_version >= 311) return "gml:MultiSurfacePropertyType";
478 if (buffer_cmp(type, "TIN")) return "gml:TriangulatedSurfacePropertyType";
479 if (buffer_cmp(type, "POLYHEDRALSURFACE")) return "gml:PolyhedralSurfacePropertyType";
480 if (buffer_cmp(type, "GEOMETRYCOLLECTION")) return "gml:MultiGeometryPropertyType";
481
482 return "string";
483}
484
485
486/*
487 * Convert a date from PostgreSQL to XML
488 */
490{
491 buffer *time;
492
493 assert(timestamp);
494
495 time = buffer_init();
496 buffer_add_str(time, timestamp);
497 if (!time->use) return time;
498
499 buffer_replace(time, " ", "T");
500
501 if (check_regexp(time->buf, "\\+"))
502 buffer_add_str(time, ":00");
503 else
504 buffer_add_str(time, "Z");
505
506 return time;
507}
508
509
510/*
511 * Return the type of the property passed in parameter
512 */
513buffer *ows_psql_type(ows * o, buffer * layer_name, buffer * property)
514{
515 ows_layer_node *ln;
516
517 assert(o);
518 assert(o->layers);
519 assert(layer_name);
520 assert(property);
521
522 for (ln = o->layers->first ; ln ; ln = ln->next) {
523 if (ln->layer->name && ln->layer->storage
524 && !strcmp(ln->layer->name->buf, layer_name->buf))
525 return array_get(ln->layer->storage->attributes, property->buf);
526 }
527
528 return NULL;
529}
530
531
532/*
533 * Generate a new buffer id supposed to be unique for a given layer name
534 */
536{
537 ows_layer_node *ln;
538 buffer * id, *sql_id;
539 FILE *fp;
540 PGresult * res;
541 int i, seed_len;
542 char * seed = NULL;
543
544 assert(o);
545 assert(o->layers);
546 assert(layer_name);
547
548 /* Retrieve layer node pointer */
549 for (ln = o->layers->first ; ln ; ln = ln->next) {
550 if (ln->layer->name && ln->layer->storage
551 && !strcmp(ln->layer->name->buf, layer_name->buf)) break;
552 }
553 assert(ln);
554
555 id = buffer_init();
556
557 /* If PK have a sequence in PostgreSQL database,
558 * retrieve next available sequence value
559 */
560 if (ln->layer->storage->pkey_sequence) {
561 sql_id = buffer_init();
562 buffer_add_str(sql_id, "SELECT nextval('");
563 buffer_copy(sql_id, ln->layer->storage->pkey_sequence);
564 buffer_add_str(sql_id, "');");
565 res = ows_psql_exec(o, sql_id->buf);
566 buffer_free(sql_id);
567
568 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) {
569 buffer_add_str(id, (char *) PQgetvalue(res, 0, 0));
570 PQclear(res);
571 return id;
572 }
573
574 /* FIXME: Shouldn't we return an error there instead ? */
575 PQclear(res);
576 }
577
578 /* If PK have a DEFAULT in PostgreSQL database,
579 * retrieve next available DEFAULT value
580 */
581 if (ln->layer->storage->pkey_default) {
582 sql_id = buffer_init();
583 buffer_add_str(sql_id, "SELECT ");
584 buffer_copy(sql_id, ln->layer->storage->pkey_default);
585 buffer_add_str(sql_id, ";");
586 res = ows_psql_exec(o, sql_id->buf);
587 buffer_free(sql_id);
588
589 if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) {
590 buffer_add_str(id, (char *) PQgetvalue(res, 0, 0));
591 PQclear(res);
592 return id;
593 }
594
595 /* FIXME: Shouldn't we return an error there instead ? */
596 PQclear(res);
597 }
598
599 /*
600 * If we don't have a PostgreSQL Sequence, we will try to
601 * generate a pseudo random keystring using /dev/urandom
602 * Will so work only on somes/commons Unix system
603 */
604 seed_len = 6;
605 seed = malloc(sizeof(char) * (seed_len * 3 + 1)); /* multiply by 3 to be able to deal
606 with hex2dec conversion */
607 assert(seed);
608 seed[0] = '\0';
609
610 fp = fopen("/dev/urandom","r");
611 if (fp) {
612 for (i=0 ; i<seed_len ; i++) {
613 char szBuf[4];
614 sprintf(szBuf, "%03d", fgetc(fp));
615 strcat(seed, szBuf);
616 }
617 fclose(fp);
618 buffer_add_str(id, seed);
619 free(seed);
620
621 return id;
622 }
623 free(seed);
624
625 /* Case where we not using PostgreSQL sequence,
626 * and OS don't have a /dev/urandom support
627 * This case don't prevent to produce ID collision
628 * Don't use it unless really no others choices !!!
629 */
630 srand((int) (time(NULL) ^ rand() % 1000) + 42);
631 srand((rand() % 1000 ^ rand() % 1000) + 42);
632 buffer_add_int(id, rand());
633
634 return id;
635}
636
637
638/*
639 * Return the number of rows returned by the specified requests
640 */
641int ows_psql_number_features(ows * o, list * from, list * where)
642{
643 buffer *sql;
644 PGresult *res;
645 list_node *ln_from, *ln_where;
646 int nb;
647
648 assert(o);
649 assert(from);
650 assert(where);
651
652 nb = 0;
653
654 /* checks if from list and where list have the same size */
655 if (from->size != where->size) return nb;
656
657
658 for (ln_from = from->first, ln_where = where->first;
659 ln_from;
660 ln_from = ln_from->next, ln_where = ln_where->next) {
661 sql = buffer_init();
662
663 /* execute the request */
664 buffer_add_str(sql, "SELECT count(*) FROM \"");
665 buffer_copy(sql, ln_from->value);
666 buffer_add_str(sql, "\" ");
667 buffer_copy(sql, ln_where->value);
668 res = ows_psql_exec(o, sql->buf);
669 buffer_free(sql);
670
671 if (PQresultStatus(res) != PGRES_TUPLES_OK) {
672 PQclear(res);
673 return -1;
674 }
675 nb = nb + atoi(PQgetvalue(res, 0, 0));
676 PQclear(res);
677 }
678
679 return nb;
680}
681
682
683static xmlNodePtr ows_psql_recursive_parse_gml(ows * o, xmlNodePtr n, xmlNodePtr result)
684{
685 xmlNodePtr c;
686
687 assert(o);
688 assert(n);
689
690 if (result) return result; /* avoid recursive loop */
691
692 /* We are looking for the geometry part inside GML doc */
693 for (; n ; n = n->next) {
694
695 if (n->type != XML_ELEMENT_NODE) continue;
696
697 /* Check on namespace GML 3 and GML 3.2 */
698 if ( strcmp("http://www.opengis.net/gml", (char *) n->ns->href)
699 && strcmp("http://www.opengis.net/gml/3.2", (char *) n->ns->href)) continue;
700
701 /* GML SF Geometries Types */
702 if ( !strcmp((char *) n->name, "Point")
703 || !strcmp((char *) n->name, "LineString")
704 || !strcmp((char *) n->name, "LinearRing")
705 || !strcmp((char *) n->name, "Curve")
706 || !strcmp((char *) n->name, "Polygon")
707 || !strcmp((char *) n->name, "Triangle")
708 || !strcmp((char *) n->name, "Surface")
709 || !strcmp((char *) n->name, "MultiPoint")
710 || !strcmp((char *) n->name, "MultiLineString")
711 || !strcmp((char *) n->name, "MultiCurve")
712 || !strcmp((char *) n->name, "MultiPolygon")
713 || !strcmp((char *) n->name, "MultiSurface")
714 || !strcmp((char *) n->name, "PolyhedralSurface")
715 || !strcmp((char *) n->name, "Tin")
716 || !strcmp((char *) n->name, "TriangulatedSurface")
717 || !strcmp((char *) n->name, "MultiGeometry")) return n;
718
719 /* Recursive exploration */
720 if (n->children)
721 for (c = n->children ; c ; c = c->next)
722 if ((result = ows_psql_recursive_parse_gml(o, c, NULL)))
723 return result;
724 }
725
726 return NULL;
727}
728
729
730/*
731 * Transform a GML geometry to PostGIS EWKT
732 * Return NULL on error
733 */
734buffer * ows_psql_gml_to_sql(ows * o, xmlNodePtr n, const ows_srs* parent_srs)
735{
736 PGresult *res;
737 xmlNodePtr g;
738 buffer *result, *sql, *gml;
739 ows_srs* srs_geom = NULL;
740
741 assert(o);
742 assert(n);
743
744 g = ows_psql_recursive_parse_gml(o, n, NULL);
745 if (!g) return NULL; /* No Geometry founded in GML doc */
746
747 /* Look for a srsName attribute on the geometry itself */
748 if (xmlHasProp(g, (xmlChar *) "srsName")) {
749 xmlChar* attr = xmlGetProp(g, (xmlChar *) "srsName");
750 srs_geom = ows_srs_init();
751
752 if (!ows_srs_set_from_srsname(o, srs_geom, (char *) attr)) {
753 ows_srs_free(srs_geom);
754 xmlFree(attr);
755 return NULL;
756 }
757
758 xmlFree(attr);
759 }
760
761 /* Retrieve the sub doc and launch GML parse via PostGIS */
762 gml = buffer_init();
764
765 sql = buffer_init();
766 buffer_add_str(sql, "SELECT ");
767 if (srs_geom == NULL && parent_srs != NULL &&
768 parent_srs->honours_authority_axis_order &&
769 !parent_srs->is_axis_order_gis_friendly) {
770 buffer_add_str(sql, "ST_FlipCoordinates(");
771 }
772 /* ST_GeomFromGML handles the axis swapping if the geometry has a srsName */
773 buffer_add_str(sql, "ST_GeomFromGML('");
774 buffer_add_str(sql, gml->buf);
775
776 if (ows_version_get(o->postgis_version) >= 200 &&
777 (srs_geom != NULL || parent_srs != NULL)) {
778 buffer_add_str(sql, "',");
779 buffer_add_int(sql, srs_geom ? srs_geom->srid : parent_srs->srid);
780 buffer_add_str(sql, ")");
781 } else {
782 /* Means PostGIS 1.5 */
783 buffer_add_str(sql, "')");
784 }
785 if (srs_geom == NULL && parent_srs != NULL &&
786 parent_srs->honours_authority_axis_order &&
787 !parent_srs->is_axis_order_gis_friendly) {
788 /* Close ST_FlipCoordinates */
789 buffer_add_str(sql, ")");
790 }
791
792 if (srs_geom) ows_srs_free(srs_geom);
793
794 res = ows_psql_exec(o, sql->buf);
795 buffer_free(gml);
796
797 /* GML Parse errors cases */
798 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
799 buffer_free(sql);
800 PQclear(res);
801 return NULL;
802 }
803
804 result = buffer_init();
805 buffer_add_str(result, PQgetvalue(res, 0, 0));
806 PQclear(res);
807
808 /* Check if geometry is valid */
809 if (o->check_valid_geom) {
810
811 buffer_empty(sql);
812 buffer_add_str(sql, "SELECT ST_IsValid('");
813 buffer_add_str(sql, result->buf);
814 buffer_add_str(sql, "')");
815
816 res = ows_psql_exec(o, sql->buf);
817
818 if ( PQresultStatus(res) != PGRES_TUPLES_OK
819 || PQntuples(res) != 1
820 || (char) PQgetvalue(res, 0, 0)[0] != 't') {
821 buffer_free(sql);
822 buffer_free(result);
823 PQclear(res);
824 return NULL;
825 }
826 PQclear(res);
827 }
828
829 buffer_free(sql);
830
831 return result;
832}
833
834
835/*
836 * Use PostgreSQL native handling to escape string
837 * string returned must be freed by the caller
838 * return NULL on error
839 */
840char *ows_psql_escape_string(ows *o, const char *content)
841{
842 char *content_escaped;
843 int error = 0;
844
845 assert(o);
846 assert(o->pg);
847 assert(content);
848
849 content_escaped = malloc(strlen(content) * 2 + 1);
850 PQescapeStringConn(o->pg, content_escaped, content, strlen(content), &error);
851
852 if (error != 0) return NULL;
853
854 return content_escaped;
855}
856
857
858/*
859 * Return SRID from a given geometry
860 */
861int ows_psql_geometry_srid(ows *o, const char *geom)
862{
863 int srid;
864 buffer *sql;
865 PGresult *res;
866
867 assert(o);
868 assert(o->pg);
869 assert(geom);
870
871 sql = buffer_from_str("SELECT ST_SRID('");
872 buffer_add_str(sql, geom);
873 buffer_add_str(sql, "'::geometry)");
874
875 res = ows_psql_exec(o, sql->buf);
876
877 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) srid = -1;
878 else srid = atoi((char *) PQgetvalue(res, 0, 0));
879
880 buffer_free(sql);
881 PQclear(res);
882
883 return srid;
884}
885
886
887/*
888 * vim: expandtab sw=4 ts=4
889 */
void ows_log(ows *o, int log_level, const char *log)
Definition ows.c:235
void buffer_add(buffer *buf, char c)
Definition buffer.c:123
int ows_version_get(ows_version *v)
void buffer_empty(buffer *buf)
Definition buffer.c:100
void buffer_copy(buffer *dest, const buffer *src)
Definition buffer.c:350
ows_srs * ows_srs_init()
Definition ows_srs.c:37
bool buffer_cmp(const buffer *buf, const char *str)
Definition buffer.c:290
bool in_list(const list *l, const buffer *value)
Definition list.c:259
void list_free(list *l)
Definition list.c:54
void buffer_add_str(buffer *buf, const char *str)
Definition buffer.c:254
list * list_init()
Definition list.c:36
bool buffer_case_cmp(const buffer *buf, const char *str)
Definition buffer.c:330
bool ows_srs_set_from_srsname(ows *o, ows_srs *s, const char *srsname)
Definition ows_srs.c:303
buffer * cgi_add_xml_into_buffer(buffer *element, xmlNodePtr n)
buffer * array_get(const array *a, const char *key)
Definition array.c:147
bool buffer_ncmp(const buffer *buf, const char *str, size_t n)
Definition buffer.c:310
void list_add(list *l, buffer *value)
Definition list.c:71
ows_version * ows_version_init()
Definition ows_version.c:33
buffer * buffer_replace(buffer *buf, char *before, char *after)
Definition buffer.c:412
buffer * buffer_from_str(const char *str)
Definition buffer.c:202
void buffer_free(buffer *buf)
Definition buffer.c:83
void buffer_add_int(buffer *buf, int i)
Definition buffer.c:173
void ows_srs_free(ows_srs *c)
Definition ows_srs.c:76
buffer * buffer_init()
Definition buffer.c:61
bool check_regexp(const char *str_request, const char *str_regex)
Definition regexp.c:36
list * list_explode_str(char separator, const char *value)
Definition list.c:401
list * ows_psql_not_null_properties(ows *o, buffer *layer_name)
Definition ows_psql.c:185
int ows_psql_geometry_srid(ows *o, const char *geom)
Definition ows_psql.c:861
buffer * ows_psql_column_name(ows *o, buffer *layer_name, int number)
Definition ows_psql.c:299
ows_version * ows_psql_postgis_version(ows *o)
Definition ows_psql.c:393
buffer * ows_psql_column_constraint_name(ows *o, buffer *column_name, buffer *table_name)
Definition ows_psql.c:206
PGresult * ows_psql_exec(ows *o, const char *sql)
Definition ows_psql.c:56
buffer * ows_psql_gml_to_sql(ows *o, xmlNodePtr n, const ows_srs *parent_srs)
Definition ows_psql.c:734
buffer * ows_psql_column_character_maximum_length(ows *o, buffer *column_name, buffer *table_name)
Definition ows_psql.c:335
list * ows_psql_geometry_column(ows *o, buffer *layer_name)
Definition ows_psql.c:76
buffer * ows_psql_type(ows *o, buffer *layer_name, buffer *property)
Definition ows_psql.c:513
bool ows_psql_is_geometry_valid(ows *o, buffer *geom)
Definition ows_psql.c:136
char * ows_psql_escape_string(ows *o, const char *content)
Definition ows_psql.c:840
buffer * ows_psql_id_column(ows *o, buffer *layer_name)
Definition ows_psql.c:36
list * ows_psql_column_check_constraint(ows *o, buffer *constraint_name)
Definition ows_psql.c:244
array * ows_psql_describe_table(ows *o, buffer *layer_name)
Definition ows_psql.c:373
buffer * ows_psql_timestamp_to_xml_time(char *timestamp)
Definition ows_psql.c:489
bool ows_psql_is_numeric(buffer *type)
Definition ows_psql.c:426
char * ows_psql_to_xsd(buffer *type, enum wfs_format format)
Definition ows_psql.c:445
static xmlNodePtr ows_psql_recursive_parse_gml(ows *o, xmlNodePtr n, xmlNodePtr result)
Definition ows_psql.c:683
bool ows_psql_is_geometry_column(ows *o, buffer *layer_name, buffer *column)
Definition ows_psql.c:164
buffer * ows_psql_generate_id(ows *o, buffer *layer_name)
Definition ows_psql.c:535
int ows_psql_number_features(ows *o, list *from, list *where)
Definition ows_psql.c:641
buffer * ows_psql_table_name(ows *o, buffer *layer_name)
Definition ows_psql.c:116
buffer * ows_psql_schema_name(ows *o, buffer *layer_name)
Definition ows_psql.c:96
struct List_node list_node
struct Ows_version ows_version
struct Ows_layer_node ows_layer_node
struct Buffer buffer
struct Ows ows
wfs_format
Definition ows_struct.h:277
@ WFS_GML212
Definition ows_struct.h:280
struct Ows_srs ows_srs
struct Array array
struct List list
char * buf
size to next realloc
Definition ows_struct.h:39
size_t use
Definition ows_struct.h:36
struct List_node * next
Definition ows_struct.h:45
buffer * value
Definition ows_struct.h:44
unsigned int size
Definition ows_struct.h:52
list_node * last
Definition ows_struct.h:51
list_node * first
Definition ows_struct.h:50
ows_layer_node * first
Definition ows_struct.h:205
ows_layer * layer
Definition ows_struct.h:199
struct Ows_layer_node * next
Definition ows_struct.h:200
buffer * pkey_default
Definition ows_struct.h:103
buffer * pkey_sequence
Definition ows_struct.h:102
list * not_null_columns
Definition ows_struct.h:99
buffer * name
Definition ows_struct.h:177
ows_layer_storage * storage
Definition ows_struct.h:195
bool honours_authority_axis_order
Definition ows_struct.h:126
bool is_axis_order_gis_friendly
Definition ows_struct.h:118
bool check_valid_geom
Definition ows_struct.h:398
PGconn * pg
Definition ows_struct.h:369
ows_version * postgis_version
Definition ows_struct.h:405
ows_layer_list * layers
Definition ows_struct.h:402

Generated for tinyows by doxygen 1.13.2