1 /*
2 
3  gaia_topostmts.c -- implementation of Topology prepared statements
4 
5  version 5.0, 2020 August 1
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2015-2021
28 the Initial Developer. All Rights Reserved.
29 
30 Contributor(s):
31 
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43 
44 */
45 
46 /*
47 
48 CREDITS:
49 
50 this module has been completely funded by:
51 Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
52 (Topology support)
53 
54 CIG: 6038019AE5
55 
56 */
57 
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <string.h>
61 
62 #if defined(_WIN32) && !defined(__MINGW32__)
63 #include "config-msvc.h"
64 #else
65 #include "config.h"
66 #endif
67 
68 #ifdef ENABLE_RTTOPO		/* only if RTTOPO is enabled */
69 
70 #include <spatialite/sqlite.h>
71 #include <spatialite/debug.h>
72 #include <spatialite/gaiageo.h>
73 #include <spatialite/gaiaaux.h>
74 #include <spatialite/gaia_topology.h>
75 
76 #include <spatialite_private.h>
77 
78 #include <librttopo.h>
79 
80 #include "topology_private.h"
81 
82 #define GAIA_UNUSED() if (argc || argv) argc = argc;
83 
84 
85 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getNodeWithinDistance2D(GaiaTopologyAccessorPtr accessor)86 do_create_stmt_getNodeWithinDistance2D (GaiaTopologyAccessorPtr accessor)
87 {
88 /* attempting to create the getNodeWithinDistance2D prepared statement */
89     struct gaia_topology *topo = (struct gaia_topology *) accessor;
90     sqlite3_stmt *stmt = NULL;
91     int ret;
92     char *sql;
93     char *table;
94     char *xtable;
95     if (topo == NULL)
96 	return NULL;
97 
98     table = sqlite3_mprintf ("%s_node", topo->topology_name);
99     xtable = gaiaDoubleQuotedSql (table);
100     sql =
101 	sqlite3_mprintf ("SELECT node_id FROM MAIN.\"%s\" "
102 			 "WHERE ST_Distance(geom, MakePoint(?, ?)) <= ? AND ROWID IN ("
103 			 "SELECT ROWID FROM SpatialIndex WHERE f_table_name = %Q AND "
104 			 "f_geometry_column = 'geom' AND search_frame = BuildCircleMBR(?, ?, ?))",
105 			 xtable, table);
106     free (xtable);
107     sqlite3_free (table);
108     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
109     sqlite3_free (sql);
110     if (ret != SQLITE_OK)
111       {
112 	  char *msg =
113 	      sqlite3_mprintf ("Prepare_getNodeWithinDistance2D error: \"%s\"",
114 			       sqlite3_errmsg (topo->db_handle));
115 	  gaiatopo_set_last_error_msg (accessor, msg);
116 	  sqlite3_free (msg);
117 	  return NULL;
118       }
119 
120     return stmt;
121 }
122 
123 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getNodeWithinBox2D(GaiaTopologyAccessorPtr accessor)124 do_create_stmt_getNodeWithinBox2D (GaiaTopologyAccessorPtr accessor)
125 {
126 /* attempting to create the getNodeWithinBox2D prepared statement */
127     struct gaia_topology *topo = (struct gaia_topology *) accessor;
128     sqlite3_stmt *stmt = NULL;
129     int ret;
130     char *sql;
131     char *table;
132     char *xtable;
133     if (topo == NULL)
134 	return NULL;
135 
136     table = sqlite3_mprintf ("%s_node", topo->topology_name);
137     xtable = gaiaDoubleQuotedSql (table);
138     sql =
139 	sqlite3_mprintf ("SELECT node_id FROM MAIN.\"%s\" WHERE ROWID IN ("
140 			 "SELECT ROWID FROM SpatialIndex WHERE f_table_name = %Q AND "
141 			 "f_geometry_column = 'geom' AND search_frame = BuildMBR(?, ?, ?, ?))",
142 			 xtable, table);
143     free (xtable);
144     sqlite3_free (table);
145     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
146     sqlite3_free (sql);
147     if (ret != SQLITE_OK)
148       {
149 	  char *msg =
150 	      sqlite3_mprintf ("Prepare_getNodeWithinBox2D error: \"%s\"",
151 			       sqlite3_errmsg (topo->db_handle));
152 	  gaiatopo_set_last_error_msg (accessor, msg);
153 	  sqlite3_free (msg);
154 	  return NULL;
155       }
156     return stmt;
157 }
158 
159 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_insertNodes(GaiaTopologyAccessorPtr accessor)160 do_create_stmt_insertNodes (GaiaTopologyAccessorPtr accessor)
161 {
162 /* attempting to create the insertNodes prepared statement */
163     struct gaia_topology *topo = (struct gaia_topology *) accessor;
164     sqlite3_stmt *stmt = NULL;
165     int ret;
166     char *sql;
167     char *table;
168     char *xtable;
169     if (topo == NULL)
170 	return NULL;
171 
172     table = sqlite3_mprintf ("%s_node", topo->topology_name);
173     xtable = gaiaDoubleQuotedSql (table);
174     sqlite3_free (table);
175     sql =
176 	sqlite3_mprintf
177 	("INSERT INTO MAIN.\"%s\" (node_id, containing_face, geom) "
178 	 "VALUES (?, ?, ?)", xtable);
179     free (xtable);
180     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
181     sqlite3_free (sql);
182     if (ret != SQLITE_OK)
183       {
184 	  char *msg = sqlite3_mprintf ("Prepare_insertNodes error: \"%s\"",
185 				       sqlite3_errmsg (topo->db_handle));
186 	  gaiatopo_set_last_error_msg (accessor, msg);
187 	  sqlite3_free (msg);
188 	  return NULL;
189       }
190 
191     return stmt;
192 }
193 
194 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getEdgeWithinDistance2D(GaiaTopologyAccessorPtr accessor)195 do_create_stmt_getEdgeWithinDistance2D (GaiaTopologyAccessorPtr accessor)
196 {
197 /* attempting to create the getEdgeWithinDistance2D prepared statement */
198     struct gaia_topology *topo = (struct gaia_topology *) accessor;
199     sqlite3_stmt *stmt = NULL;
200     int ret;
201     char *sql;
202     char *table;
203     char *xtable;
204     if (topo == NULL)
205 	return NULL;
206 
207     table = sqlite3_mprintf ("%s_edge", topo->topology_name);
208     xtable = gaiaDoubleQuotedSql (table);
209     sql =
210 	sqlite3_mprintf ("SELECT edge_id FROM MAIN.\"%s\" "
211 			 "WHERE ST_Distance(geom, MakePoint(?, ?)) <= ? AND ROWID IN ("
212 			 "SELECT ROWID FROM SpatialIndex WHERE f_table_name = %Q AND "
213 			 "f_geometry_column = 'geom' AND search_frame = BuildCircleMBR(?, ?, ?))",
214 			 xtable, table);
215     free (xtable);
216     sqlite3_free (table);
217     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
218     sqlite3_free (sql);
219     if (ret != SQLITE_OK)
220       {
221 	  char *msg =
222 	      sqlite3_mprintf ("Prepare_getEdgeWithinDistance2D error: \"%s\"",
223 			       sqlite3_errmsg (topo->db_handle));
224 	  gaiatopo_set_last_error_msg (accessor, msg);
225 	  sqlite3_free (msg);
226 	  return NULL;
227       }
228 
229     return stmt;
230 }
231 
232 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getEdgeWithinBox2D(GaiaTopologyAccessorPtr accessor)233 do_create_stmt_getEdgeWithinBox2D (GaiaTopologyAccessorPtr accessor)
234 {
235 /* attempting to create the getEdgeWithinBox2D prepared statement */
236     struct gaia_topology *topo = (struct gaia_topology *) accessor;
237     sqlite3_stmt *stmt = NULL;
238     int ret;
239     char *sql;
240     char *table;
241     char *xtable;
242     if (topo == NULL)
243 	return NULL;
244 
245     table = sqlite3_mprintf ("%s_edge", topo->topology_name);
246     xtable = gaiaDoubleQuotedSql (table);
247     sql =
248 	sqlite3_mprintf ("SELECT edge_id FROM MAIN.\"%s\" WHERE ROWID IN ("
249 			 "SELECT ROWID FROM SpatialIndex WHERE f_table_name = %Q AND "
250 			 "f_geometry_column = 'geom' AND search_frame = BuildMBR(?, ?, ?, ?))",
251 			 xtable, table);
252     free (xtable);
253     sqlite3_free (table);
254     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
255     sqlite3_free (sql);
256     if (ret != SQLITE_OK)
257       {
258 	  char *msg =
259 	      sqlite3_mprintf ("Prepare_getEdgeWithinBox2D error: \"%s\"",
260 			       sqlite3_errmsg (topo->db_handle));
261 	  gaiatopo_set_last_error_msg (accessor, msg);
262 	  sqlite3_free (msg);
263 	  return NULL;
264       }
265 
266     return stmt;
267 }
268 
269 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getAllEdges(GaiaTopologyAccessorPtr accessor)270 do_create_stmt_getAllEdges (GaiaTopologyAccessorPtr accessor)
271 {
272 /* attempting to create the getAllEdges prepared statement */
273     struct gaia_topology *topo = (struct gaia_topology *) accessor;
274     sqlite3_stmt *stmt = NULL;
275     int ret;
276     char *sql;
277     char *table;
278     char *xtable;
279     if (topo == NULL)
280 	return NULL;
281 
282     table = sqlite3_mprintf ("%s_edge", topo->topology_name);
283     xtable = gaiaDoubleQuotedSql (table);
284     sqlite3_free (table);
285     sql =
286 	sqlite3_mprintf
287 	("SELECT edge_id, start_node, end_node, left_face, right_face, "
288 	 "next_left_edge, next_right_edge, geom  FROM MAIN.\"%s\"", xtable);
289     free (xtable);
290     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
291     sqlite3_free (sql);
292     if (ret != SQLITE_OK)
293       {
294 	  char *msg = sqlite3_mprintf ("Prepare_getAllEdges error: \"%s\"",
295 				       sqlite3_errmsg (topo->db_handle));
296 	  gaiatopo_set_last_error_msg (accessor, msg);
297 	  sqlite3_free (msg);
298 	  return NULL;
299       }
300     return stmt;
301 }
302 
303 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getFaceContainingPoint_1(GaiaTopologyAccessorPtr accessor)304 do_create_stmt_getFaceContainingPoint_1 (GaiaTopologyAccessorPtr accessor)
305 {
306 /* attempting to create the getFaceContainingPoint #1 prepared statement */
307     struct gaia_topology *topo = (struct gaia_topology *) accessor;
308     sqlite3_stmt *stmt = NULL;
309     int ret;
310     char *sql;
311     char *rtree;
312     char *xrtree;
313     if (topo == NULL)
314 	return NULL;
315 
316     rtree = sqlite3_mprintf ("idx_%s_face_mbr", topo->topology_name);
317     xrtree = gaiaDoubleQuotedSql (rtree);
318     sql =
319 	sqlite3_mprintf
320 	("SELECT pkid FROM MAIN.\"%s\" WHERE xmin <= ? AND xmax >= ? AND ymin <= ? AND ymax >= ?",
321 	 xrtree);
322     free (xrtree);
323     sqlite3_free (rtree);
324     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
325     sqlite3_free (sql);
326     if (ret != SQLITE_OK)
327       {
328 	  char *msg =
329 	      sqlite3_mprintf
330 	      ("Prepare_getFaceContainingPoint #1 error: \"%s\"",
331 	       sqlite3_errmsg (topo->db_handle));
332 	  gaiatopo_set_last_error_msg (accessor, msg);
333 	  sqlite3_free (msg);
334 	  return NULL;
335       }
336 
337     return stmt;
338 }
339 
340 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getFaceContainingPoint_2(GaiaTopologyAccessorPtr accessor)341 do_create_stmt_getFaceContainingPoint_2 (GaiaTopologyAccessorPtr accessor)
342 {
343 /* attempting to create the getFaceContainingPoint #2 prepared statement */
344     struct gaia_topology *topo = (struct gaia_topology *) accessor;
345     sqlite3_stmt *stmt = NULL;
346     int ret;
347     char *sql;
348     if (topo == NULL)
349 	return NULL;
350 
351     sql =
352 	sqlite3_mprintf
353 	("SELECT ST_Contains(ST_GetFaceGeometry(%Q, ?), MakePoint(?, ?))",
354 	 topo->topology_name);
355     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
356     sqlite3_free (sql);
357     if (ret != SQLITE_OK)
358       {
359 	  char *msg =
360 	      sqlite3_mprintf
361 	      ("Prepare_getFaceContainingPoint #2 error: \"%s\"",
362 	       sqlite3_errmsg (topo->db_handle));
363 	  gaiatopo_set_last_error_msg (accessor, msg);
364 	  sqlite3_free (msg);
365 	  return NULL;
366       }
367 
368     return stmt;
369 }
370 
371 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_insertEdges(GaiaTopologyAccessorPtr accessor)372 do_create_stmt_insertEdges (GaiaTopologyAccessorPtr accessor)
373 {
374 /* attempting to create the insertEdges prepared statement */
375     struct gaia_topology *topo = (struct gaia_topology *) accessor;
376     sqlite3_stmt *stmt = NULL;
377     int ret;
378     char *sql;
379     char *table;
380     char *xtable;
381     if (topo == NULL)
382 	return NULL;
383 
384     table = sqlite3_mprintf ("%s_edge", topo->topology_name);
385     xtable = gaiaDoubleQuotedSql (table);
386     sqlite3_free (table);
387     sql =
388 	sqlite3_mprintf
389 	("INSERT INTO MAIN.\"%s\" (edge_id, start_node, end_node, left_face, "
390 	 "right_face, next_left_edge, next_right_edge, geom) "
391 	 "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", xtable);
392     free (xtable);
393     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
394     sqlite3_free (sql);
395     if (ret != SQLITE_OK)
396       {
397 	  char *msg = sqlite3_mprintf ("Prepare_insertEdges error: \"%s\"",
398 				       sqlite3_errmsg (topo->db_handle));
399 	  gaiatopo_set_last_error_msg (accessor, msg);
400 	  sqlite3_free (msg);
401 	  return NULL;
402       }
403 
404     return stmt;
405 }
406 
407 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getNextEdgeId(GaiaTopologyAccessorPtr accessor)408 do_create_stmt_getNextEdgeId (GaiaTopologyAccessorPtr accessor)
409 {
410 /* attempting to create the getNextEdgeId prepared statement */
411     struct gaia_topology *topo = (struct gaia_topology *) accessor;
412     sqlite3_stmt *stmt = NULL;
413     int ret;
414     char *sql;
415     if (topo == NULL)
416 	return NULL;
417 
418     sql =
419 	sqlite3_mprintf
420 	("SELECT next_edge_id FROM MAIN.topologies WHERE Lower(topology_name) = Lower(%Q)",
421 	 topo->topology_name);
422     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
423     sqlite3_free (sql);
424     if (ret != SQLITE_OK)
425       {
426 	  char *msg = sqlite3_mprintf ("Prepare_getNextEdgeId error: \"%s\"",
427 				       sqlite3_errmsg (topo->db_handle));
428 	  gaiatopo_set_last_error_msg (accessor, msg);
429 	  sqlite3_free (msg);
430 	  return NULL;
431       }
432 
433     return stmt;
434 }
435 
436 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_setNextEdgeId(GaiaTopologyAccessorPtr accessor)437 do_create_stmt_setNextEdgeId (GaiaTopologyAccessorPtr accessor)
438 {
439 /* attempting to create the setNextEdgeId prepared statement */
440     struct gaia_topology *topo = (struct gaia_topology *) accessor;
441     sqlite3_stmt *stmt = NULL;
442     int ret;
443     char *sql;
444     if (topo == NULL)
445 	return NULL;
446 
447     sql =
448 	sqlite3_mprintf
449 	("UPDATE MAIN.topologies SET next_edge_id = next_edge_id + 1 "
450 	 "WHERE Lower(topology_name) = Lower(%Q)", topo->topology_name);
451     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
452     sqlite3_free (sql);
453     if (ret != SQLITE_OK)
454       {
455 	  char *msg = sqlite3_mprintf ("Prepare_setNextEdgeId error: \"%s\"",
456 				       sqlite3_errmsg (topo->db_handle));
457 	  gaiatopo_set_last_error_msg (accessor, msg);
458 	  sqlite3_free (msg);
459 	  return NULL;
460       }
461 
462     return stmt;
463 }
464 
465 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getRingEdges(GaiaTopologyAccessorPtr accessor)466 do_create_stmt_getRingEdges (GaiaTopologyAccessorPtr accessor)
467 {
468 /* attempting to create the getRingEdges prepared statement */
469     struct gaia_topology *topo = (struct gaia_topology *) accessor;
470     sqlite3_stmt *stmt = NULL;
471     int ret;
472     char *sql;
473     char *table;
474     char *xtable;
475     if (topo == NULL)
476 	return NULL;
477 
478     table = sqlite3_mprintf ("%s_edge", topo->topology_name);
479     xtable = gaiaDoubleQuotedSql (table);
480     sqlite3_free (table);
481     sql =
482 	sqlite3_mprintf ("WITH RECURSIVE edgering AS ("
483 			 "SELECT ? as signed_edge_id, edge_id, next_left_edge, next_right_edge "
484 			 "FROM MAIN.\"%s\" WHERE edge_id = ABS(?) UNION SELECT CASE WHEN "
485 			 "p.signed_edge_id < 0 THEN p.next_right_edge ELSE p.next_left_edge END, "
486 			 "e.edge_id, e.next_left_edge, e.next_right_edge "
487 			 "FROM MAIN.\"%s\" AS e, edgering AS p WHERE "
488 			 "e.edge_id = CASE WHEN p.signed_edge_id < 0 THEN "
489 			 "ABS(p.next_right_edge) ELSE ABS(p.next_left_edge) END ) "
490 			 "SELECT * FROM edgering", xtable, xtable);
491     free (xtable);
492     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
493     sqlite3_free (sql);
494     if (ret != SQLITE_OK)
495       {
496 	  char *msg = sqlite3_mprintf ("Prepare_getRingEdges error: \"%s\"",
497 				       sqlite3_errmsg (topo->db_handle));
498 	  gaiatopo_set_last_error_msg (accessor, msg);
499 	  sqlite3_free (msg);
500 	  return NULL;
501       }
502 
503     return stmt;
504 }
505 
506 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_insertFaces(GaiaTopologyAccessorPtr accessor)507 do_create_stmt_insertFaces (GaiaTopologyAccessorPtr accessor)
508 {
509 /* attempting to create the insertFaces prepared statement */
510     struct gaia_topology *topo = (struct gaia_topology *) accessor;
511     sqlite3_stmt *stmt = NULL;
512     int ret;
513     char *sql;
514     char *table;
515     char *xtable;
516     if (topo == NULL)
517 	return NULL;
518 
519     table = sqlite3_mprintf ("%s_face", topo->topology_name);
520     xtable = gaiaDoubleQuotedSql (table);
521     sqlite3_free (table);
522     sql =
523 	sqlite3_mprintf
524 	("INSERT INTO MAIN.\"%s\" (face_id, mbr) VALUES (?, BuildMBR(?, ?, ?, ?, %d))",
525 	 xtable, topo->srid);
526     free (xtable);
527     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
528     sqlite3_free (sql);
529     if (ret != SQLITE_OK)
530       {
531 	  char *msg = sqlite3_mprintf ("Prepare_insertFaces error: \"%s\"",
532 				       sqlite3_errmsg (topo->db_handle));
533 	  gaiatopo_set_last_error_msg (accessor, msg);
534 	  sqlite3_free (msg);
535 	  return NULL;
536       }
537 
538     return stmt;
539 }
540 
541 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_updateFacesById(GaiaTopologyAccessorPtr accessor)542 do_create_stmt_updateFacesById (GaiaTopologyAccessorPtr accessor)
543 {
544 /* attempting to create the updateFacesById prepared statement */
545     struct gaia_topology *topo = (struct gaia_topology *) accessor;
546     sqlite3_stmt *stmt = NULL;
547     int ret;
548     char *sql;
549     char *table;
550     char *xtable;
551     if (topo == NULL)
552 	return NULL;
553 
554     table = sqlite3_mprintf ("%s_face", topo->topology_name);
555     xtable = gaiaDoubleQuotedSql (table);
556     sqlite3_free (table);
557     sql =
558 	sqlite3_mprintf
559 	("UPDATE MAIN.\"%s\" SET mbr = BuildMBR(?, ?, ?, ?, %d) WHERE face_id = ?",
560 	 xtable, topo->srid);
561     free (xtable);
562     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
563     sqlite3_free (sql);
564     if (ret != SQLITE_OK)
565       {
566 	  char *msg = sqlite3_mprintf ("Prepare_updateFacesById error: \"%s\"",
567 				       sqlite3_errmsg (topo->db_handle));
568 	  gaiatopo_set_last_error_msg (accessor, msg);
569 	  sqlite3_free (msg);
570 	  return NULL;
571       }
572 
573     return stmt;
574 }
575 
576 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_deleteFacesById(GaiaTopologyAccessorPtr accessor)577 do_create_stmt_deleteFacesById (GaiaTopologyAccessorPtr accessor)
578 {
579 /* attempting to create the deleteFacesById prepared statement */
580     struct gaia_topology *topo = (struct gaia_topology *) accessor;
581     sqlite3_stmt *stmt = NULL;
582     int ret;
583     char *sql;
584     char *table;
585     char *xtable;
586     if (topo == NULL)
587 	return NULL;
588 
589     table = sqlite3_mprintf ("%s_face", topo->topology_name);
590     xtable = gaiaDoubleQuotedSql (table);
591     sqlite3_free (table);
592     sql = sqlite3_mprintf ("DELETE FROM MAIN.\"%s\" WHERE face_id = ?", xtable);
593     free (xtable);
594     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
595     sqlite3_free (sql);
596     if (ret != SQLITE_OK)
597       {
598 	  char *msg = sqlite3_mprintf ("Prepare_deleteFacesById error: \"%s\"",
599 				       sqlite3_errmsg (topo->db_handle));
600 	  gaiatopo_set_last_error_msg (accessor, msg);
601 	  sqlite3_free (msg);
602 	  return NULL;
603       }
604 
605     return stmt;
606 }
607 
608 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_deleteNodesById(GaiaTopologyAccessorPtr accessor)609 do_create_stmt_deleteNodesById (GaiaTopologyAccessorPtr accessor)
610 {
611 /* attempting to create the deleteNodesById prepared statement */
612     struct gaia_topology *topo = (struct gaia_topology *) accessor;
613     sqlite3_stmt *stmt = NULL;
614     int ret;
615     char *sql;
616     char *table;
617     char *xtable;
618     if (topo == NULL)
619 	return NULL;
620 
621     table = sqlite3_mprintf ("%s_node", topo->topology_name);
622     xtable = gaiaDoubleQuotedSql (table);
623     sqlite3_free (table);
624     sql = sqlite3_mprintf ("DELETE FROM MAIN.\"%s\" WHERE node_id = ?", xtable);
625     free (xtable);
626     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
627     sqlite3_free (sql);
628     if (ret != SQLITE_OK)
629       {
630 	  char *msg = sqlite3_mprintf ("Prepare_deleteNodesById error: \"%s\"",
631 				       sqlite3_errmsg (topo->db_handle));
632 	  gaiatopo_set_last_error_msg (accessor, msg);
633 	  sqlite3_free (msg);
634 	  return NULL;
635       }
636 
637     return stmt;
638 }
639 
640 TOPOLOGY_PRIVATE sqlite3_stmt *
do_create_stmt_getFaceWithinBox2D(GaiaTopologyAccessorPtr accessor)641 do_create_stmt_getFaceWithinBox2D (GaiaTopologyAccessorPtr accessor)
642 {
643 /* attempting to create the getFaceWithinBox2D prepared statement */
644     struct gaia_topology *topo = (struct gaia_topology *) accessor;
645     sqlite3_stmt *stmt = NULL;
646     int ret;
647     char *sql;
648     char *table;
649     char *xtable;
650     if (topo == NULL)
651 	return NULL;
652 
653     table = sqlite3_mprintf ("idx_%s_face_mbr", topo->topology_name);
654     xtable = gaiaDoubleQuotedSql (table);
655     sql =
656 	sqlite3_mprintf
657 	("SELECT pkid, xmin, ymin, xmax, ymax FROM MAIN.\"%s\" "
658 	 "WHERE xmin <= ? AND xmax >= ? AND ymin <= ? AND ymax >= ?", xtable);
659     free (xtable);
660     sqlite3_free (table);
661     ret = sqlite3_prepare_v2 (topo->db_handle, sql, strlen (sql), &stmt, NULL);
662     sqlite3_free (sql);
663     if (ret != SQLITE_OK)
664       {
665 	  char *msg =
666 	      sqlite3_mprintf ("Prepare_getFaceWithinBox2D error: \"%s\"",
667 			       sqlite3_errmsg (topo->db_handle));
668 	  gaiatopo_set_last_error_msg (accessor, msg);
669 	  sqlite3_free (msg);
670 	  return NULL;
671       }
672     return stmt;
673 }
674 
675 #endif /* end RTTOPO conditionals */
676