1 : /******************************************************************************
2 : * $Id: ogrsqlitedatasource.cpp 23528 2011-12-11 16:35:32Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRSQLiteDataSource class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : *
10 : * Contributor: Alessandro Furieri, a.furieri@lqt.it
11 : * Portions of this module properly supporting SpatiaLite Table/Geom creation
12 : * Developed for Faunalia ( http://www.faunalia.it) with funding from
13 : * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
14 : *
15 : ******************************************************************************
16 : * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
17 : *
18 : * Permission is hereby granted, free of charge, to any person obtaining a
19 : * copy of this software and associated documentation files (the "Software"),
20 : * to deal in the Software without restriction, including without limitation
21 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22 : * and/or sell copies of the Software, and to permit persons to whom the
23 : * Software is furnished to do so, subject to the following conditions:
24 : *
25 : * The above copyright notice and this permission notice shall be included
26 : * in all copies or substantial portions of the Software.
27 : *
28 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
34 : * DEALINGS IN THE SOFTWARE.
35 : ****************************************************************************/
36 :
37 : #include "ogr_sqlite.h"
38 : #include "cpl_conv.h"
39 : #include "cpl_string.h"
40 : #include "cpl_hash_set.h"
41 : #include "cpl_csv.h"
42 :
43 : #ifdef HAVE_SPATIALITE
44 : #include "spatialite.h"
45 : #endif
46 :
47 : static int bSpatialiteLoaded = FALSE;
48 :
49 : CPL_CVSID("$Id: ogrsqlitedatasource.cpp 23528 2011-12-11 16:35:32Z rouault $");
50 :
51 : /************************************************************************/
52 : /* OGRSQLiteInitSpatialite() */
53 : /************************************************************************/
54 :
55 95 : static int OGRSQLiteInitSpatialite()
56 : {
57 : /* -------------------------------------------------------------------- */
58 : /* Try loading SpatiaLite. */
59 : /* -------------------------------------------------------------------- */
60 : #ifdef HAVE_SPATIALITE
61 95 : if (!bSpatialiteLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
62 : {
63 2 : bSpatialiteLoaded = TRUE;
64 2 : spatialite_init(CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
65 : }
66 : #endif
67 95 : return bSpatialiteLoaded;
68 : }
69 :
70 : /************************************************************************/
71 : /* OGRSQLiteGetSpatialiteVersionNumber() */
72 : /************************************************************************/
73 :
74 232 : int OGRSQLiteGetSpatialiteVersionNumber()
75 : {
76 232 : double v = 0.0;
77 : #ifdef HAVE_SPATIALITE
78 232 : v = ( atof( spatialite_version() ) + 0.001 ) * 10.0;
79 : #endif
80 232 : return (int)v;
81 : }
82 :
83 : /************************************************************************/
84 : /* OGRSQLiteDataSource() */
85 : /************************************************************************/
86 :
87 102 : OGRSQLiteDataSource::OGRSQLiteDataSource()
88 :
89 : {
90 102 : pszName = NULL;
91 102 : papoLayers = NULL;
92 102 : nLayers = 0;
93 :
94 102 : nSoftTransactionLevel = 0;
95 :
96 102 : nKnownSRID = 0;
97 102 : panSRID = NULL;
98 102 : papoSRS = NULL;
99 :
100 102 : bHaveGeometryColumns = FALSE;
101 102 : bIsSpatiaLite = FALSE;
102 102 : bUpdate = FALSE;
103 :
104 102 : hDB = NULL;
105 :
106 : #ifdef HAVE_SQLITE_VFS
107 102 : pMyVFS = NULL;
108 : #endif
109 102 : }
110 :
111 : /************************************************************************/
112 : /* ~OGRSQLiteDataSource() */
113 : /************************************************************************/
114 :
115 102 : OGRSQLiteDataSource::~OGRSQLiteDataSource()
116 :
117 : {
118 : int i;
119 :
120 102 : CPLFree( pszName );
121 :
122 1115 : for( i = 0; i < nLayers; i++ )
123 1013 : delete papoLayers[i];
124 :
125 102 : CPLFree( papoLayers );
126 :
127 180 : for( i = 0; i < nKnownSRID; i++ )
128 : {
129 78 : if( papoSRS[i] != NULL )
130 78 : papoSRS[i]->Release();
131 : }
132 102 : CPLFree( panSRID );
133 102 : CPLFree( papoSRS );
134 :
135 102 : if( hDB != NULL )
136 102 : sqlite3_close( hDB );
137 :
138 : #ifdef HAVE_SQLITE_VFS
139 102 : if (pMyVFS)
140 : {
141 3 : sqlite3_vfs_unregister(pMyVFS);
142 3 : CPLFree(pMyVFS);
143 : }
144 : #endif
145 102 : }
146 :
147 : /************************************************************************/
148 : /* SetSynchronous() */
149 : /************************************************************************/
150 :
151 100 : int OGRSQLiteDataSource::SetSynchronous()
152 : {
153 : int rc;
154 100 : const char* pszSqliteSync = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL);
155 100 : if (pszSqliteSync != NULL)
156 : {
157 100 : char* pszErrMsg = NULL;
158 200 : if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
159 : EQUAL(pszSqliteSync, "FALSE"))
160 100 : rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
161 0 : else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
162 0 : rc = sqlite3_exec( hDB, "PRAGMA synchronous = NORMAL", NULL, NULL, &pszErrMsg );
163 0 : else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
164 : EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
165 0 : rc = sqlite3_exec( hDB, "PRAGMA synchronous = FULL", NULL, NULL, &pszErrMsg );
166 : else
167 : {
168 : CPLError( CE_Warning, CPLE_AppDefined, "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
169 0 : pszSqliteSync);
170 0 : rc = SQLITE_OK;
171 : }
172 :
173 100 : if( rc != SQLITE_OK )
174 : {
175 : CPLError( CE_Failure, CPLE_AppDefined,
176 : "Unable to run PRAGMA synchronous : %s",
177 0 : pszErrMsg );
178 0 : sqlite3_free( pszErrMsg );
179 0 : return FALSE;
180 : }
181 : }
182 100 : return TRUE;
183 : }
184 :
185 : /************************************************************************/
186 : /* SetCacheSize() */
187 : /************************************************************************/
188 :
189 100 : int OGRSQLiteDataSource::SetCacheSize()
190 : {
191 : int rc;
192 100 : const char* pszSqliteCacheMB = CPLGetConfigOption("OGR_SQLITE_CACHE", NULL);
193 100 : if (pszSqliteCacheMB != NULL)
194 : {
195 0 : char* pszErrMsg = NULL;
196 : char **papszResult;
197 : int nRowCount, nColCount;
198 : int iSqliteCachePages;
199 0 : int iSqlitePageSize = -1;
200 0 : int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
201 :
202 : /* querying the current PageSize */
203 : rc = sqlite3_get_table( hDB, "PRAGMA page_size",
204 : &papszResult, &nRowCount, &nColCount,
205 0 : &pszErrMsg );
206 0 : if( rc == SQLITE_OK )
207 : {
208 : int iRow;
209 0 : for (iRow = 1; iRow <= nRowCount; iRow++)
210 : {
211 0 : iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
212 : }
213 0 : sqlite3_free_table(papszResult);
214 : }
215 0 : if( iSqlitePageSize < 0 )
216 : {
217 : CPLError( CE_Failure, CPLE_AppDefined,
218 : "Unable to run PRAGMA page_size : %s",
219 0 : pszErrMsg );
220 0 : sqlite3_free( pszErrMsg );
221 0 : return TRUE;
222 : }
223 :
224 : /* computing the CacheSize as #Pages */
225 0 : iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
226 0 : if( iSqliteCachePages <= 0)
227 0 : return TRUE;
228 :
229 : rc = sqlite3_exec( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
230 : iSqliteCachePages ),
231 0 : NULL, NULL, &pszErrMsg );
232 0 : if( rc != SQLITE_OK )
233 : {
234 : CPLError( CE_Warning, CPLE_AppDefined,
235 : "Unrecognized value for PRAGMA cache_size : %s",
236 0 : pszErrMsg );
237 0 : sqlite3_free( pszErrMsg );
238 0 : rc = SQLITE_OK;
239 : }
240 : }
241 100 : return TRUE;
242 : }
243 :
244 : /************************************************************************/
245 : /* OpenOrCreateDB() */
246 : /************************************************************************/
247 :
248 102 : int OGRSQLiteDataSource::OpenOrCreateDB(int flags)
249 : {
250 : int rc;
251 :
252 : #ifdef HAVE_SQLITE_VFS
253 102 : int bUseOGRVFS = CSLTestBoolean(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
254 105 : if (bUseOGRVFS || strncmp(pszName, "/vsi", 4) == 0)
255 : {
256 3 : pMyVFS = OGRSQLiteCreateVFS();
257 3 : sqlite3_vfs_register(pMyVFS, 0);
258 3 : rc = sqlite3_open_v2( pszName, &hDB, flags, pMyVFS->zName );
259 : }
260 : else
261 99 : rc = sqlite3_open_v2( pszName, &hDB, flags, NULL );
262 : #else
263 : rc = sqlite3_open( pszName, &hDB );
264 : #endif
265 102 : if( rc != SQLITE_OK )
266 : {
267 : CPLError( CE_Failure, CPLE_OpenFailed,
268 : "sqlite3_open(%s) failed: %s",
269 2 : pszName, sqlite3_errmsg( hDB ) );
270 2 : return FALSE;
271 : }
272 :
273 100 : if (!SetCacheSize())
274 0 : return FALSE;
275 :
276 100 : if (!SetSynchronous())
277 0 : return FALSE;
278 :
279 100 : return TRUE;
280 : }
281 :
282 : /************************************************************************/
283 : /* Create() */
284 : /************************************************************************/
285 :
286 33 : int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
287 : {
288 : int rc;
289 33 : CPLString osCommand;
290 33 : char *pszErrMsg = NULL;
291 :
292 33 : pszName = CPLStrdup( pszNameIn );
293 :
294 : /* -------------------------------------------------------------------- */
295 : /* Check that spatialite extensions are loaded if required to */
296 : /* create a spatialite database */
297 : /* -------------------------------------------------------------------- */
298 33 : int bSpatialite = CSLFetchBoolean( papszOptions, "SPATIALITE", FALSE );
299 33 : int bMetadata = CSLFetchBoolean( papszOptions, "METADATA", TRUE );
300 :
301 33 : if (bSpatialite == TRUE)
302 : {
303 : #ifdef HAVE_SPATIALITE
304 26 : int bSpatialiteLoaded = OGRSQLiteInitSpatialite();
305 26 : if (!bSpatialiteLoaded)
306 : {
307 : CPLError( CE_Failure, CPLE_NotSupported,
308 0 : "Creating a Spatialite database, but Spatialite extensions are not loaded." );
309 0 : return FALSE;
310 : }
311 : #else
312 : CPLError( CE_Failure, CPLE_NotSupported,
313 : "OGR was built without libspatialite support\n"
314 : "... sorry, creating/writing any SpatiaLite DB is unsupported\n" );
315 :
316 : return FALSE;
317 : #endif
318 : }
319 :
320 33 : bIsSpatiaLite = bSpatialite;
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Create the database file. */
324 : /* -------------------------------------------------------------------- */
325 33 : if (!OpenOrCreateDB(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE))
326 2 : return FALSE;
327 :
328 : /* -------------------------------------------------------------------- */
329 : /* Create the SpatiaLite metadata tables. */
330 : /* -------------------------------------------------------------------- */
331 31 : if ( bSpatialite )
332 : {
333 : /*
334 : / SpatiaLite full support: calling InitSpatialMetadata()
335 : /
336 : / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
337 : / to directly CREATE "geometry_columns" and "spatial_ref_sys"
338 : / [by-passing InitSpatialMetadata() as absolutely required]
339 : / will severely [and irremediably] corrupt the DB !!!
340 : */
341 24 : osCommand = "SELECT InitSpatialMetadata()";
342 24 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
343 24 : if( rc != SQLITE_OK )
344 : {
345 : CPLError( CE_Failure, CPLE_AppDefined,
346 : "Unable to Initialize SpatiaLite Metadata: %s",
347 0 : pszErrMsg );
348 0 : sqlite3_free( pszErrMsg );
349 0 : return FALSE;
350 : }
351 : }
352 :
353 : /* -------------------------------------------------------------------- */
354 : /* Create the geometry_columns and spatial_ref_sys metadata tables. */
355 : /* -------------------------------------------------------------------- */
356 7 : else if( bMetadata )
357 : {
358 : osCommand =
359 : "CREATE TABLE geometry_columns ("
360 : " f_table_name VARCHAR, "
361 : " f_geometry_column VARCHAR, "
362 : " geometry_type INTEGER, "
363 : " coord_dimension INTEGER, "
364 : " srid INTEGER,"
365 7 : " geometry_format VARCHAR )";
366 7 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
367 7 : if( rc != SQLITE_OK )
368 : {
369 : CPLError( CE_Failure, CPLE_AppDefined,
370 : "Unable to create table geometry_columns: %s",
371 0 : pszErrMsg );
372 0 : sqlite3_free( pszErrMsg );
373 0 : return FALSE;
374 : }
375 :
376 : osCommand =
377 : "CREATE TABLE spatial_ref_sys ("
378 : " srid INTEGER UNIQUE,"
379 : " auth_name TEXT,"
380 : " auth_srid TEXT,"
381 7 : " srtext TEXT)";
382 7 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
383 7 : if( rc != SQLITE_OK )
384 : {
385 : CPLError( CE_Failure, CPLE_AppDefined,
386 : "Unable to create table spatial_ref_sys: %s",
387 0 : pszErrMsg );
388 0 : sqlite3_free( pszErrMsg );
389 0 : return FALSE;
390 : }
391 : }
392 :
393 : /* -------------------------------------------------------------------- */
394 : /* Optionnaly initialize the content of the spatial_ref_sys table */
395 : /* with the EPSG database */
396 : /* -------------------------------------------------------------------- */
397 31 : if ( (bSpatialite || bMetadata) &&
398 : CSLFetchBoolean( papszOptions, "INIT_WITH_EPSG", FALSE ) )
399 : {
400 1 : if (!InitWithEPSG())
401 0 : return FALSE;
402 : }
403 :
404 31 : return Open(pszName, TRUE);
405 : }
406 :
407 : /************************************************************************/
408 : /* InitWithEPSG() */
409 : /************************************************************************/
410 :
411 1 : int OGRSQLiteDataSource::InitWithEPSG()
412 : {
413 1 : CPLString osCommand;
414 1 : char* pszErrMsg = NULL;
415 :
416 1 : if ( bIsSpatiaLite )
417 : {
418 : /*
419 : / if v.2.4.0 (or any subsequent) InitWithEPSG make no sense at all
420 : / because the EPSG dataset is already self-initialized at DB creation
421 : */
422 0 : int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
423 0 : if ( iSpatialiteVersion >= 24 )
424 0 : return TRUE;
425 : }
426 :
427 1 : int rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
428 1 : if( rc != SQLITE_OK )
429 : {
430 : CPLError( CE_Failure, CPLE_AppDefined,
431 : "Unable to insert into spatial_ref_sys: %s",
432 0 : pszErrMsg );
433 0 : sqlite3_free( pszErrMsg );
434 0 : return FALSE;
435 : }
436 :
437 : FILE* fp;
438 : int i;
439 3 : for(i=0;i<2 && rc == SQLITE_OK;i++)
440 : {
441 2 : const char* pszFilename = (i == 0) ? "gcs.csv" : "pcs.csv";
442 2 : fp = VSIFOpen(CSVFilename(pszFilename), "rt");
443 2 : if (fp == NULL)
444 : {
445 : CPLError( CE_Failure, CPLE_OpenFailed,
446 : "Unable to open EPSG support file %s.\n"
447 : "Try setting the GDAL_DATA environment variable to point to the\n"
448 : "directory containing EPSG csv files.",
449 0 : pszFilename );
450 :
451 0 : continue;
452 : }
453 :
454 2 : OGRSpatialReference oSRS;
455 : char** papszTokens;
456 2 : CSLDestroy(CSVReadParseLine( fp ));
457 4215 : while ( (papszTokens = CSVReadParseLine( fp )) != NULL && rc == SQLITE_OK)
458 : {
459 4211 : int nSRSId = atoi(papszTokens[0]);
460 4211 : CSLDestroy(papszTokens);
461 :
462 4211 : CPLPushErrorHandler(CPLQuietErrorHandler);
463 4211 : oSRS.importFromEPSG(nSRSId);
464 4211 : CPLPopErrorHandler();
465 :
466 4211 : if (bIsSpatiaLite)
467 : {
468 0 : char *pszProj4 = NULL;
469 :
470 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
471 0 : OGRErr eErr = oSRS.exportToProj4( &pszProj4 );
472 0 : CPLPopErrorHandler();
473 :
474 0 : char *pszWKT = NULL;
475 0 : if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
476 : {
477 0 : CPLFree(pszWKT);
478 0 : pszWKT = NULL;
479 : }
480 :
481 0 : if( eErr == OGRERR_NONE )
482 : {
483 0 : const char *pszProjCS = oSRS.GetAttrValue("PROJCS");
484 0 : if (pszProjCS == NULL)
485 0 : pszProjCS = oSRS.GetAttrValue("GEOGCS");
486 :
487 0 : int bHasSrsWkt = FALSE;
488 :
489 : /* testing for SRS_WKT column presence */
490 : char **papszResult;
491 : int nRowCount, nColCount;
492 : rc = sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
493 : &papszResult, &nRowCount, &nColCount,
494 0 : &pszErrMsg );
495 :
496 0 : if( rc == SQLITE_OK )
497 : {
498 : int iRow;
499 0 : for (iRow = 1; iRow <= nRowCount; iRow++)
500 : {
501 0 : if (EQUAL("srs_wkt",
502 : papszResult[(iRow * nColCount) + 1]))
503 0 : bHasSrsWkt = TRUE;
504 : }
505 0 : sqlite3_free_table(papszResult);
506 : }
507 :
508 0 : if (bHasSrsWkt == TRUE)
509 : {
510 : /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
511 0 : if ( pszProjCS )
512 : osCommand.Printf(
513 : "INSERT INTO spatial_ref_sys "
514 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text, srs_wkt) "
515 : "VALUES (%d, 'EPSG', '%d', ?, ?, ?)",
516 0 : nSRSId, nSRSId);
517 : else
518 : osCommand.Printf(
519 : "INSERT INTO spatial_ref_sys "
520 : "(srid, auth_name, auth_srid, proj4text, srs_wkt) "
521 : "VALUES (%d, 'EPSG', '%d', ?, ?)",
522 0 : nSRSId, nSRSId);
523 : }
524 : else
525 : {
526 : /* the SPATIAL_REF_SYS table does not support a SRS_WKT column */
527 0 : if ( pszProjCS )
528 : osCommand.Printf(
529 : "INSERT INTO spatial_ref_sys "
530 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
531 : "VALUES (%d, 'EPSG', '%d', ?, ?)",
532 0 : nSRSId, nSRSId);
533 : else
534 : osCommand.Printf(
535 : "INSERT INTO spatial_ref_sys "
536 : "(srid, auth_name, auth_srid, proj4text) "
537 : "VALUES (%d, 'EPSG', '%d', ?)",
538 0 : nSRSId, nSRSId);
539 : }
540 :
541 0 : sqlite3_stmt *hInsertStmt = NULL;
542 0 : rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
543 :
544 0 : if ( pszProjCS )
545 : {
546 0 : if( rc == SQLITE_OK)
547 0 : rc = sqlite3_bind_text( hInsertStmt, 1, pszProjCS, -1, SQLITE_STATIC );
548 0 : if( rc == SQLITE_OK)
549 0 : rc = sqlite3_bind_text( hInsertStmt, 2, pszProj4, -1, SQLITE_STATIC );
550 0 : if (bHasSrsWkt == TRUE)
551 : {
552 : /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
553 0 : if( rc == SQLITE_OK && pszWKT != NULL)
554 0 : rc = sqlite3_bind_text( hInsertStmt, 3, pszWKT, -1, SQLITE_STATIC );
555 : }
556 : }
557 : else
558 : {
559 0 : if( rc == SQLITE_OK)
560 0 : rc = sqlite3_bind_text( hInsertStmt, 1, pszProj4, -1, SQLITE_STATIC );
561 0 : if (bHasSrsWkt == TRUE)
562 : {
563 : /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
564 0 : if( rc == SQLITE_OK && pszWKT != NULL)
565 0 : rc = sqlite3_bind_text( hInsertStmt, 2, pszWKT, -1, SQLITE_STATIC );
566 : }
567 : }
568 :
569 0 : if( rc == SQLITE_OK)
570 0 : rc = sqlite3_step( hInsertStmt );
571 :
572 0 : if( rc != SQLITE_OK && rc != SQLITE_DONE )
573 : {
574 : CPLError( CE_Failure, CPLE_AppDefined,
575 : "Cannot insert %s into spatial_ref_sys : %s",
576 : pszProj4,
577 0 : sqlite3_errmsg(hDB) );
578 :
579 0 : sqlite3_finalize( hInsertStmt );
580 0 : CPLFree(pszProj4);
581 0 : CPLFree(pszWKT);
582 0 : break;
583 : }
584 0 : rc = SQLITE_OK;
585 :
586 0 : sqlite3_finalize( hInsertStmt );
587 : }
588 :
589 0 : CPLFree(pszProj4);
590 0 : CPLFree(pszWKT);
591 : }
592 : else
593 : {
594 4211 : char *pszWKT = NULL;
595 4211 : if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
596 : {
597 : osCommand.Printf(
598 : "INSERT INTO spatial_ref_sys "
599 : "(srid, auth_name, auth_srid, srtext) "
600 : "VALUES (%d, 'EPSG', '%d', ?)",
601 4211 : nSRSId, nSRSId );
602 :
603 4211 : sqlite3_stmt *hInsertStmt = NULL;
604 4211 : rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
605 :
606 4211 : if( rc == SQLITE_OK)
607 4211 : rc = sqlite3_bind_text( hInsertStmt, 1, pszWKT, -1, SQLITE_STATIC );
608 :
609 4211 : if( rc == SQLITE_OK)
610 4211 : rc = sqlite3_step( hInsertStmt );
611 :
612 4211 : if( rc != SQLITE_OK && rc != SQLITE_DONE )
613 : {
614 : CPLError( CE_Failure, CPLE_AppDefined,
615 : "Cannot insert %s into spatial_ref_sys : %s",
616 : pszWKT,
617 0 : sqlite3_errmsg(hDB) );
618 :
619 0 : sqlite3_finalize( hInsertStmt );
620 0 : CPLFree(pszWKT);
621 0 : break;
622 : }
623 4211 : rc = SQLITE_OK;
624 :
625 4211 : sqlite3_finalize( hInsertStmt );
626 : }
627 :
628 4211 : CPLFree(pszWKT);
629 : }
630 : }
631 2 : VSIFClose(fp);
632 : }
633 :
634 1 : if (rc == SQLITE_OK)
635 1 : rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
636 : else
637 0 : rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, &pszErrMsg );
638 :
639 1 : if( rc != SQLITE_OK )
640 : {
641 : CPLError( CE_Failure, CPLE_AppDefined,
642 : "Unable to insert into spatial_ref_sys: %s",
643 0 : pszErrMsg );
644 0 : sqlite3_free( pszErrMsg );
645 : }
646 :
647 1 : return (rc == SQLITE_OK);
648 : }
649 :
650 : /************************************************************************/
651 : /* Open() */
652 : /************************************************************************/
653 :
654 100 : int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
655 :
656 : {
657 100 : CPLAssert( nLayers == 0 );
658 :
659 100 : if (pszName == NULL)
660 69 : pszName = CPLStrdup( pszNewName );
661 100 : bUpdate = bUpdateIn;
662 :
663 100 : int bListAllTables = CSLTestBoolean(CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO"));
664 :
665 : /* -------------------------------------------------------------------- */
666 : /* Try to open the sqlite database properly now. */
667 : /* -------------------------------------------------------------------- */
668 100 : if (hDB == NULL)
669 : {
670 69 : OGRSQLiteInitSpatialite();
671 :
672 69 : if (!OpenOrCreateDB((bUpdateIn) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY) )
673 0 : return FALSE;
674 : }
675 :
676 : int rc;
677 100 : char *pszErrMsg = NULL;
678 :
679 100 : CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
680 :
681 : /* -------------------------------------------------------------------- */
682 : /* If we have a GEOMETRY_COLUMNS tables, initialize on the basis */
683 : /* of that. */
684 : /* -------------------------------------------------------------------- */
685 : char **papszResult;
686 : int nRowCount, iRow, nColCount;
687 :
688 : rc = sqlite3_get_table(
689 : hDB,
690 : "SELECT f_table_name, f_geometry_column, geometry_type, coord_dimension, geometry_format, srid"
691 : " FROM geometry_columns",
692 100 : &papszResult, &nRowCount, &nColCount, &pszErrMsg );
693 :
694 100 : if( rc == SQLITE_OK )
695 : {
696 18 : CPLDebug("SQLITE", "OGR style SQLite DB found !");
697 :
698 18 : bHaveGeometryColumns = TRUE;
699 :
700 59 : for( iRow = 0; iRow < nRowCount; iRow++ )
701 : {
702 41 : char **papszRow = papszResult + iRow * 6 + 6;
703 41 : OGRwkbGeometryType eGeomType = wkbUnknown;
704 41 : int nSRID = 0;
705 :
706 164 : if (papszRow[0] == NULL ||
707 41 : papszRow[1] == NULL ||
708 41 : papszRow[2] == NULL ||
709 41 : papszRow[3] == NULL)
710 0 : continue;
711 :
712 41 : eGeomType = (OGRwkbGeometryType) atoi(papszRow[2]);
713 :
714 41 : if( atoi(papszRow[3]) > 2 )
715 0 : eGeomType = (OGRwkbGeometryType) (((int)eGeomType) | wkb25DBit);
716 :
717 41 : if( papszRow[5] != NULL )
718 10 : nSRID = atoi(papszRow[5]);
719 :
720 82 : OpenTable( papszRow[0], papszRow[1], eGeomType, papszRow[4],
721 123 : FetchSRS( nSRID ) );
722 :
723 41 : if (bListAllTables)
724 0 : CPLHashSetInsert(hSet, CPLStrdup(papszRow[0]));
725 : }
726 :
727 18 : sqlite3_free_table(papszResult);
728 :
729 18 : if (bListAllTables)
730 0 : goto all_tables;
731 :
732 18 : CPLHashSetDestroy(hSet);
733 :
734 18 : return TRUE;
735 : }
736 :
737 : /* -------------------------------------------------------------------- */
738 : /* Otherwise we can deal with SpatiaLite database. */
739 : /* -------------------------------------------------------------------- */
740 82 : sqlite3_free( pszErrMsg );
741 : rc = sqlite3_get_table( hDB,
742 : "SELECT f_table_name, f_geometry_column, "
743 : "type, coord_dimension, srid, "
744 : "spatial_index_enabled FROM geometry_columns",
745 : &papszResult, &nRowCount,
746 82 : &nColCount, &pszErrMsg );
747 :
748 82 : if ( rc == SQLITE_OK )
749 : {
750 :
751 82 : bIsSpatiaLite = TRUE;
752 82 : bHaveGeometryColumns = TRUE;
753 :
754 82 : int bSpatialiteReadOnly = TRUE;
755 82 : int iSpatialiteVersion = -1;
756 :
757 : /* Only enables write-mode if linked against SpatiaLite */
758 82 : if( bSpatialiteLoaded == TRUE )
759 : {
760 82 : iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
761 82 : bSpatialiteReadOnly = FALSE;
762 : }
763 :
764 82 : if (bSpatialiteReadOnly && bUpdate)
765 : {
766 0 : CPLDebug("SQLITE", "SpatiaLite-style SQLite DB found, but updating tables disabled because no linking against spatialite library !");
767 : }
768 : else
769 : {
770 82 : CPLDebug("SQLITE", "SpatiaLite-style SQLite DB found !");
771 : }
772 :
773 : /*
774 : / SpatiaLite v.2.4.0 (or any subsequent) is required
775 : / to support 2.5D: if an obsolete version of the library
776 : / is found we'll unconditionally activate 2D casting mode
777 : */
778 82 : int bForce2D = FALSE;
779 82 : iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
780 82 : if ( iSpatialiteVersion < 24)
781 0 : bForce2D = TRUE;
782 :
783 214 : for ( iRow = 0; iRow < nRowCount; iRow++ )
784 : {
785 132 : char **papszRow = papszResult + iRow * 6 + 6;
786 : OGRwkbGeometryType eGeomType;
787 132 : int nSRID = 0;
788 132 : int bHasM = FALSE;
789 132 : int bHasSpatialIndex = FALSE;
790 :
791 528 : if (papszRow[0] == NULL ||
792 132 : papszRow[1] == NULL ||
793 132 : papszRow[2] == NULL ||
794 132 : papszRow[3] == NULL)
795 0 : continue;
796 :
797 132 : eGeomType = OGRFromOGCGeomType(papszRow[2]);
798 :
799 348 : if( strcmp ( papszRow[3], "XYZ" ) == 0 ||
800 108 : strcmp ( papszRow[3], "XYZM" ) == 0 ||
801 108 : strcmp ( papszRow[3], "3" ) == 0) // SpatiaLite's own 3D geometries
802 24 : eGeomType = (OGRwkbGeometryType) (((int)eGeomType) | wkb25DBit);
803 :
804 264 : if( strcmp ( papszRow[3], "XYM" ) == 0 ||
805 132 : strcmp ( papszRow[3], "XYZM" ) == 0 ) // M coordinate declared
806 0 : bHasM = TRUE;
807 :
808 :
809 132 : if( papszRow[4] != NULL )
810 132 : nSRID = atoi(papszRow[4]);
811 :
812 : /* Only look for presence of a spatial index if linked against SpatiaLite */
813 132 : if( bSpatialiteLoaded && papszRow[5] != NULL )
814 132 : bHasSpatialIndex = atoi(papszRow[5]);
815 :
816 132 : OpenTable( papszRow[0], papszRow[1], eGeomType, "SpatiaLite",
817 : FetchSRS( nSRID ), nSRID, bHasSpatialIndex, bHasM,
818 : bSpatialiteReadOnly, bSpatialiteLoaded,
819 264 : iSpatialiteVersion, bForce2D );
820 :
821 132 : if (bListAllTables)
822 44 : CPLHashSetInsert(hSet, CPLStrdup(papszRow[0]));
823 : }
824 :
825 82 : sqlite3_free_table(papszResult);
826 :
827 : /* -------------------------------------------------------------------- */
828 : /* Detect VirtualShape layers */
829 : /* -------------------------------------------------------------------- */
830 : #ifdef HAVE_SPATIALITE
831 82 : if (bSpatialiteLoaded)
832 : {
833 : rc = sqlite3_get_table( hDB,
834 : "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
835 : &papszResult, &nRowCount,
836 82 : &nColCount, &pszErrMsg );
837 :
838 82 : if ( rc == SQLITE_OK )
839 : {
840 293 : for( iRow = 0; iRow < nRowCount; iRow++ )
841 : {
842 211 : char **papszRow = papszResult + iRow * 2 + 2;
843 211 : const char *pszName = papszRow[0];
844 211 : const char *pszSQL = papszRow[1];
845 211 : if( pszName == NULL || pszSQL == NULL )
846 0 : continue;
847 :
848 211 : if( strstr(pszSQL, "VirtualShape") || strstr(pszSQL, "VirtualXL") )
849 : {
850 2 : OpenVirtualTable(pszName, pszSQL);
851 :
852 2 : if (bListAllTables)
853 0 : CPLHashSetInsert(hSet, CPLStrdup(pszName));
854 : }
855 : }
856 : }
857 : else
858 : {
859 : CPLError( CE_Failure, CPLE_AppDefined,
860 : "Unable to fetch list of tables: %s",
861 0 : pszErrMsg );
862 0 : sqlite3_free( pszErrMsg );
863 : }
864 :
865 82 : sqlite3_free_table(papszResult);
866 : }
867 : #endif
868 :
869 : /* -------------------------------------------------------------------- */
870 : /* Detect spatial views */
871 : /* -------------------------------------------------------------------- */
872 : rc = sqlite3_get_table( hDB,
873 : "SELECT view_name, view_geometry, view_rowid, f_table_name, f_geometry_column FROM views_geometry_columns",
874 : &papszResult, &nRowCount,
875 82 : &nColCount, &pszErrMsg );
876 82 : if ( rc == SQLITE_OK )
877 : {
878 81 : for( iRow = 0; iRow < nRowCount; iRow++ )
879 : {
880 3 : char **papszRow = papszResult + iRow * 5 + 5;
881 3 : const char* pszViewName = papszRow[0];
882 3 : const char* pszViewGeometry = papszRow[1];
883 3 : const char* pszViewRowid = papszRow[2];
884 3 : const char* pszTableName = papszRow[3];
885 3 : const char* pszGeometryColumn = papszRow[4];
886 :
887 3 : if (pszViewName == NULL ||
888 : pszViewGeometry == NULL ||
889 : pszViewRowid == NULL ||
890 : pszTableName == NULL ||
891 : pszGeometryColumn == NULL)
892 0 : continue;
893 :
894 : OpenView( pszViewName, pszViewGeometry, pszViewRowid,
895 3 : pszTableName, pszGeometryColumn, bSpatialiteLoaded );
896 :
897 3 : if (bListAllTables)
898 0 : CPLHashSetInsert(hSet, CPLStrdup(pszViewName));
899 : }
900 78 : sqlite3_free_table(papszResult);
901 : }
902 :
903 :
904 82 : if (bListAllTables)
905 62 : goto all_tables;
906 :
907 20 : CPLHashSetDestroy(hSet);
908 :
909 20 : return TRUE;
910 : }
911 :
912 : /* -------------------------------------------------------------------- */
913 : /* Otherwise our final resort is to return all tables and views */
914 : /* as non-spatial tables. */
915 : /* -------------------------------------------------------------------- */
916 0 : sqlite3_free( pszErrMsg );
917 :
918 : all_tables:
919 : rc = sqlite3_get_table( hDB,
920 : "SELECT name FROM sqlite_master "
921 : "WHERE type IN ('table','view') "
922 : "UNION ALL "
923 : "SELECT name FROM sqlite_temp_master "
924 : "WHERE type IN ('table','view') "
925 : "ORDER BY 1",
926 : &papszResult, &nRowCount,
927 62 : &nColCount, &pszErrMsg );
928 :
929 62 : if( rc != SQLITE_OK )
930 : {
931 : CPLError( CE_Failure, CPLE_AppDefined,
932 : "Unable to fetch list of tables: %s",
933 0 : pszErrMsg );
934 0 : sqlite3_free( pszErrMsg );
935 0 : CPLHashSetDestroy(hSet);
936 0 : return FALSE;
937 : }
938 :
939 868 : for( iRow = 0; iRow < nRowCount; iRow++ )
940 : {
941 806 : if (CPLHashSetLookup(hSet, papszResult[iRow+1]) == NULL)
942 762 : OpenTable( papszResult[iRow+1] );
943 : }
944 :
945 62 : sqlite3_free_table(papszResult);
946 62 : CPLHashSetDestroy(hSet);
947 :
948 62 : return TRUE;
949 : }
950 :
951 : /************************************************************************/
952 : /* OpenVirtualTable() */
953 : /************************************************************************/
954 :
955 5 : int OGRSQLiteDataSource::OpenVirtualTable(const char* pszName, const char* pszSQL)
956 : {
957 5 : int nSRID = -1;
958 5 : const char* pszVirtualShape = strstr(pszSQL, "VirtualShape");
959 5 : if (pszVirtualShape != NULL)
960 : {
961 4 : const char* pszParenthesis = strchr(pszVirtualShape, '(');
962 4 : if (pszParenthesis)
963 : {
964 : /* CREATE VIRTUAL TABLE table_name VirtualShape(shapename, codepage, srid) */
965 : /* Extract 3rd parameter */
966 4 : char** papszTokens = CSLTokenizeString2( pszParenthesis + 1, ",", CSLT_HONOURSTRINGS );
967 4 : if (CSLCount(papszTokens) == 3)
968 : {
969 4 : nSRID = atoi(papszTokens[2]);
970 : }
971 4 : CSLDestroy(papszTokens);
972 : }
973 : }
974 :
975 5 : if (OpenTable(pszName, NULL, wkbUnknown, NULL,
976 : (nSRID > 0) ? FetchSRS( nSRID ) : NULL, nSRID,
977 : FALSE, FALSE, TRUE, FALSE, -1, FALSE,
978 : pszVirtualShape != NULL))
979 : {
980 5 : OGRSQLiteLayer* poLayer = papoLayers[nLayers-1];
981 5 : OGRFeature* poFeature = poLayer->GetNextFeature();
982 5 : if (poFeature)
983 : {
984 4 : OGRGeometry* poGeom = poFeature->GetGeometryRef();
985 4 : if (poGeom)
986 4 : poLayer->GetLayerDefn()->SetGeomType(poGeom->getGeometryType());
987 4 : delete poFeature;
988 : }
989 5 : poLayer->ResetReading();
990 5 : return TRUE;
991 : }
992 0 : return FALSE;
993 : }
994 :
995 : /************************************************************************/
996 : /* OpenTable() */
997 : /************************************************************************/
998 :
999 940 : int OGRSQLiteDataSource::OpenTable( const char *pszNewName,
1000 : const char *pszGeomCol,
1001 : OGRwkbGeometryType eGeomType,
1002 : const char *pszGeomFormat,
1003 : OGRSpatialReference *poSRS, int nSRID,
1004 : int bHasSpatialIndex, int bHasM,
1005 : int bSpatialiteReadOnly,
1006 : int bSpatialiteLoaded,
1007 : int iSpatialiteVersion,
1008 : int bForce2D,
1009 : int bIsVirtualShapeIn )
1010 :
1011 : {
1012 : /* -------------------------------------------------------------------- */
1013 : /* Create the layer object. */
1014 : /* -------------------------------------------------------------------- */
1015 : OGRSQLiteTableLayer *poLayer;
1016 :
1017 940 : poLayer = new OGRSQLiteTableLayer( this );
1018 :
1019 940 : if( poLayer->Initialize( pszNewName, pszGeomCol,
1020 : eGeomType, pszGeomFormat,
1021 : poSRS, nSRID, bHasSpatialIndex,
1022 : bHasM, bSpatialiteReadOnly,
1023 : bSpatialiteLoaded,
1024 : iSpatialiteVersion,
1025 : bIsVirtualShapeIn) != CE_None )
1026 : {
1027 0 : delete poLayer;
1028 0 : return FALSE;
1029 : }
1030 940 : poLayer->SetSpatialite2D ( bForce2D );
1031 :
1032 : /* -------------------------------------------------------------------- */
1033 : /* Add layer to data source layer list. */
1034 : /* -------------------------------------------------------------------- */
1035 : papoLayers = (OGRSQLiteLayer **)
1036 940 : CPLRealloc( papoLayers, sizeof(OGRSQLiteLayer *) * (nLayers+1) );
1037 940 : papoLayers[nLayers++] = poLayer;
1038 :
1039 940 : return TRUE;
1040 : }
1041 :
1042 : /************************************************************************/
1043 : /* OpenView() */
1044 : /************************************************************************/
1045 :
1046 3 : int OGRSQLiteDataSource::OpenView( const char *pszViewName,
1047 : const char *pszViewGeometry,
1048 : const char *pszViewRowid,
1049 : const char *pszTableName,
1050 : const char *pszGeometryColumn,
1051 : int bSpatialiteLoaded)
1052 :
1053 : {
1054 : /* -------------------------------------------------------------------- */
1055 : /* Create the layer object. */
1056 : /* -------------------------------------------------------------------- */
1057 : OGRSQLiteViewLayer *poLayer;
1058 :
1059 3 : poLayer = new OGRSQLiteViewLayer( this );
1060 :
1061 3 : if( poLayer->Initialize( pszViewName, pszViewGeometry,
1062 : pszViewRowid, pszTableName, pszGeometryColumn,
1063 : bSpatialiteLoaded ) != CE_None )
1064 : {
1065 0 : delete poLayer;
1066 0 : return FALSE;
1067 : }
1068 :
1069 : /* -------------------------------------------------------------------- */
1070 : /* Add layer to data source layer list. */
1071 : /* -------------------------------------------------------------------- */
1072 : papoLayers = (OGRSQLiteLayer **)
1073 3 : CPLRealloc( papoLayers, sizeof(OGRSQLiteLayer *) * (nLayers+1) );
1074 3 : papoLayers[nLayers++] = poLayer;
1075 :
1076 3 : return TRUE;
1077 : }
1078 :
1079 : /************************************************************************/
1080 : /* TestCapability() */
1081 : /************************************************************************/
1082 :
1083 2 : int OGRSQLiteDataSource::TestCapability( const char * pszCap )
1084 :
1085 : {
1086 2 : if( EQUAL(pszCap,ODsCCreateLayer) )
1087 2 : return bUpdate;
1088 0 : else if( EQUAL(pszCap,ODsCDeleteLayer) )
1089 0 : return bUpdate;
1090 : else
1091 0 : return FALSE;
1092 : }
1093 :
1094 : /************************************************************************/
1095 : /* GetLayer() */
1096 : /************************************************************************/
1097 :
1098 1794 : OGRLayer *OGRSQLiteDataSource::GetLayer( int iLayer )
1099 :
1100 : {
1101 1794 : if( iLayer < 0 || iLayer >= nLayers )
1102 0 : return NULL;
1103 : else
1104 1794 : return papoLayers[iLayer];
1105 : }
1106 :
1107 : /************************************************************************/
1108 : /* ExecuteSQL() */
1109 : /************************************************************************/
1110 :
1111 : static const char* apszSpatialiteFuncs[] =
1112 : {
1113 : "InitSpatialMetaData",
1114 : "AddGeometryColumn",
1115 : "RecoverGeometryColumn",
1116 : "DiscardGeometryColumn",
1117 : "CreateSpatialIndex",
1118 : "CreateMbrCache",
1119 : "DisableSpatialIndex"
1120 : };
1121 :
1122 306 : OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
1123 : OGRGeometry *poSpatialFilter,
1124 : const char *pszDialect )
1125 :
1126 : {
1127 306 : if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
1128 : return OGRDataSource::ExecuteSQL( pszSQLCommand,
1129 : poSpatialFilter,
1130 2 : pszDialect );
1131 :
1132 : /* -------------------------------------------------------------------- */
1133 : /* Special case DELLAYER: command. */
1134 : /* -------------------------------------------------------------------- */
1135 304 : if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
1136 : {
1137 11 : const char *pszLayerName = pszSQLCommand + 9;
1138 :
1139 22 : while( *pszLayerName == ' ' )
1140 0 : pszLayerName++;
1141 :
1142 11 : DeleteLayer( pszLayerName );
1143 11 : return NULL;
1144 : }
1145 :
1146 : /* -------------------------------------------------------------------- */
1147 : /* Prepare statement. */
1148 : /* -------------------------------------------------------------------- */
1149 : int rc;
1150 293 : sqlite3_stmt *hSQLStmt = NULL;
1151 :
1152 : rc = sqlite3_prepare( GetDB(), pszSQLCommand, strlen(pszSQLCommand),
1153 293 : &hSQLStmt, NULL );
1154 :
1155 293 : if( rc != SQLITE_OK )
1156 : {
1157 : CPLError( CE_Failure, CPLE_AppDefined,
1158 : "In ExecuteSQL(): sqlite3_prepare(%s):\n %s",
1159 1 : pszSQLCommand, sqlite3_errmsg(GetDB()) );
1160 :
1161 1 : if( hSQLStmt != NULL )
1162 : {
1163 0 : sqlite3_finalize( hSQLStmt );
1164 : }
1165 :
1166 1 : return NULL;
1167 : }
1168 :
1169 : /* -------------------------------------------------------------------- */
1170 : /* Do we get a resultset? */
1171 : /* -------------------------------------------------------------------- */
1172 292 : rc = sqlite3_step( hSQLStmt );
1173 292 : if( rc != SQLITE_ROW )
1174 : {
1175 108 : if ( rc != SQLITE_DONE )
1176 : {
1177 : CPLError( CE_Failure, CPLE_AppDefined,
1178 : "In ExecuteSQL(): sqlite3_step(%s):\n %s",
1179 0 : pszSQLCommand, sqlite3_errmsg(GetDB()) );
1180 : }
1181 :
1182 108 : if( EQUALN(pszSQLCommand, "CREATE ", 7) )
1183 : {
1184 42 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
1185 87 : if ( CSLCount(papszTokens) >= 4 &&
1186 42 : EQUAL(papszTokens[1], "VIRTUAL") &&
1187 3 : EQUAL(papszTokens[2], "TABLE") )
1188 : {
1189 3 : OpenVirtualTable(papszTokens[3], pszSQLCommand);
1190 : }
1191 42 : CSLDestroy(papszTokens);
1192 : }
1193 :
1194 108 : sqlite3_finalize( hSQLStmt );
1195 108 : return NULL;
1196 : }
1197 :
1198 : /* -------------------------------------------------------------------- */
1199 : /* Special case for some spatialite functions which must be run */
1200 : /* only once */
1201 : /* -------------------------------------------------------------------- */
1202 184 : if( EQUALN(pszSQLCommand,"SELECT ",7) &&
1203 : bIsSpatiaLite && bSpatialiteLoaded )
1204 : {
1205 : unsigned int i;
1206 1220 : for(i=0;i<sizeof(apszSpatialiteFuncs)/
1207 : sizeof(apszSpatialiteFuncs[0]);i++)
1208 : {
1209 1085 : if( EQUALN(apszSpatialiteFuncs[i], pszSQLCommand + 7,
1210 : strlen(apszSpatialiteFuncs[i])) )
1211 : {
1212 38 : if (sqlite3_column_count( hSQLStmt ) == 1 &&
1213 : sqlite3_column_type( hSQLStmt, 0 ) == SQLITE_INTEGER )
1214 : {
1215 38 : int ret = sqlite3_column_int( hSQLStmt, 0 );
1216 :
1217 38 : sqlite3_finalize( hSQLStmt );
1218 :
1219 : return new OGRSQLiteSingleFeatureLayer
1220 38 : ( apszSpatialiteFuncs[i], ret );
1221 : }
1222 : }
1223 : }
1224 : }
1225 :
1226 : /* -------------------------------------------------------------------- */
1227 : /* Create layer. */
1228 : /* -------------------------------------------------------------------- */
1229 146 : OGRSQLiteSelectLayer *poLayer = NULL;
1230 :
1231 146 : CPLString osSQL = pszSQLCommand;
1232 146 : poLayer = new OGRSQLiteSelectLayer( this, osSQL, hSQLStmt );
1233 :
1234 146 : if( poSpatialFilter != NULL )
1235 0 : poLayer->SetSpatialFilter( poSpatialFilter );
1236 :
1237 146 : return poLayer;
1238 : }
1239 :
1240 : /************************************************************************/
1241 : /* ReleaseResultSet() */
1242 : /************************************************************************/
1243 :
1244 186 : void OGRSQLiteDataSource::ReleaseResultSet( OGRLayer * poLayer )
1245 :
1246 : {
1247 186 : delete poLayer;
1248 186 : }
1249 :
1250 : /************************************************************************/
1251 : /* CreateLayer() */
1252 : /************************************************************************/
1253 :
1254 : OGRLayer *
1255 80 : OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
1256 : OGRSpatialReference *poSRS,
1257 : OGRwkbGeometryType eType,
1258 : char ** papszOptions )
1259 :
1260 : {
1261 : char *pszLayerName;
1262 80 : int bForce2D = FALSE;
1263 : const char *pszGeomFormat;
1264 :
1265 : /* -------------------------------------------------------------------- */
1266 : /* Verify we are in update mode. */
1267 : /* -------------------------------------------------------------------- */
1268 80 : if( !bUpdate )
1269 : {
1270 : CPLError( CE_Failure, CPLE_NoWriteAccess,
1271 : "Data source %s opened read-only.\n"
1272 : "New layer %s cannot be created.\n",
1273 0 : pszName, pszLayerNameIn );
1274 :
1275 0 : return NULL;
1276 : }
1277 :
1278 80 : if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
1279 80 : pszLayerName = LaunderName( pszLayerNameIn );
1280 : else
1281 0 : pszLayerName = CPLStrdup( pszLayerNameIn );
1282 :
1283 80 : CPLString osEscapedLayerName = OGRSQLiteEscape(pszLayerName);
1284 80 : const char* pszEscapedLayerName = osEscapedLayerName.c_str();
1285 :
1286 80 : pszGeomFormat = CSLFetchNameValue( papszOptions, "FORMAT" );
1287 80 : if( pszGeomFormat == NULL )
1288 : {
1289 77 : if ( !bIsSpatiaLite )
1290 9 : pszGeomFormat = "WKB";
1291 : else
1292 68 : pszGeomFormat = "SpatiaLite";
1293 : }
1294 :
1295 80 : if( !EQUAL(pszGeomFormat,"WKT")
1296 : && !EQUAL(pszGeomFormat,"WKB")
1297 : && !EQUAL(pszGeomFormat, "SpatiaLite") )
1298 : {
1299 : CPLError( CE_Failure, CPLE_NotSupported,
1300 : "FORMAT=%s not recognised or supported.",
1301 0 : pszGeomFormat );
1302 0 : return NULL;
1303 : }
1304 :
1305 80 : if (bIsSpatiaLite && !EQUAL(pszGeomFormat, "SpatiaLite") )
1306 : {
1307 : CPLError( CE_Failure, CPLE_NotSupported,
1308 : "FORMAT=%s not support on a SpatiaLite enabled database.",
1309 0 : pszGeomFormat );
1310 0 : return NULL;
1311 : }
1312 80 : if (bIsSpatiaLite && !bSpatialiteLoaded)
1313 : {
1314 : CPLError( CE_Failure, CPLE_NotSupported,
1315 : "Creating layers on a SpatiaLite enabled database, "
1316 0 : "without Spatialite extensions loaded, is not supported." );
1317 0 : return NULL;
1318 : }
1319 :
1320 : /* -------------------------------------------------------------------- */
1321 : /* Do we already have this layer? If so, should we blow it */
1322 : /* away? */
1323 : /* -------------------------------------------------------------------- */
1324 : int iLayer;
1325 :
1326 1113 : for( iLayer = 0; iLayer < nLayers; iLayer++ )
1327 : {
1328 1033 : if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
1329 : {
1330 0 : if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
1331 : && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
1332 : {
1333 0 : DeleteLayer( pszLayerName );
1334 : }
1335 : else
1336 : {
1337 : CPLError( CE_Failure, CPLE_AppDefined,
1338 : "Layer %s already exists, CreateLayer failed.\n"
1339 : "Use the layer creation option OVERWRITE=YES to "
1340 : "replace it.",
1341 0 : pszLayerName );
1342 0 : CPLFree( pszLayerName );
1343 0 : return NULL;
1344 : }
1345 : }
1346 : }
1347 :
1348 : /* -------------------------------------------------------------------- */
1349 : /* Try to get the SRS Id of this spatial reference system, */
1350 : /* adding to the srs table if needed. */
1351 : /* -------------------------------------------------------------------- */
1352 80 : int nSRSId = -1;
1353 :
1354 80 : if( poSRS != NULL )
1355 71 : nSRSId = FetchSRSId( poSRS );
1356 :
1357 : /* -------------------------------------------------------------------- */
1358 : /* Create a basic table with the FID. Also include the */
1359 : /* geometry if this is not a PostGIS enabled table. */
1360 : /* -------------------------------------------------------------------- */
1361 : int rc;
1362 : char *pszErrMsg;
1363 80 : const char *pszGeomCol = NULL;
1364 80 : CPLString osCommand;
1365 :
1366 80 : if( eType == wkbNone )
1367 : osCommand.Printf(
1368 : "CREATE TABLE '%s' ( OGC_FID INTEGER PRIMARY KEY )",
1369 0 : pszEscapedLayerName );
1370 : else
1371 : {
1372 80 : if( EQUAL(pszGeomFormat,"WKT") )
1373 : {
1374 1 : pszGeomCol = "WKT_GEOMETRY";
1375 : osCommand.Printf(
1376 : "CREATE TABLE '%s' ( "
1377 : " OGC_FID INTEGER PRIMARY KEY,"
1378 : " %s VARCHAR )",
1379 1 : pszEscapedLayerName, pszGeomCol );
1380 : }
1381 : else
1382 : {
1383 79 : pszGeomCol = "GEOMETRY";
1384 :
1385 : /* Only if was created as a SpatiaLite DB */
1386 79 : if ( bIsSpatiaLite )
1387 : {
1388 : /*
1389 : / SpatiaLite full support: we must create the
1390 : / Geometry in a second time using AddGeometryColumn()
1391 : /
1392 : / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
1393 : / to directly creating some Geometry column
1394 : / [by-passing AddGeometryColumn() as absolutely required]
1395 : / will severely [and irremediably] corrupt the DB !!!
1396 : */
1397 : osCommand.Printf( "CREATE TABLE '%s' ( "
1398 : " OGC_FID INTEGER PRIMARY KEY)",
1399 68 : pszLayerName);
1400 : }
1401 : else
1402 : {
1403 : osCommand.Printf( "CREATE TABLE '%s' ( "
1404 : " OGC_FID INTEGER PRIMARY KEY,"
1405 : " %s BLOB )",
1406 11 : pszLayerName, pszGeomCol );
1407 : }
1408 : }
1409 : }
1410 :
1411 : #ifdef DEBUG
1412 80 : CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
1413 : #endif
1414 :
1415 80 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
1416 80 : if( rc != SQLITE_OK )
1417 : {
1418 : CPLError( CE_Failure, CPLE_AppDefined,
1419 : "Unable to create table %s: %s",
1420 0 : pszLayerName, pszErrMsg );
1421 0 : sqlite3_free( pszErrMsg );
1422 0 : return FALSE;
1423 : }
1424 :
1425 : /* -------------------------------------------------------------------- */
1426 : /* Eventually we should be adding this table to a table of */
1427 : /* "geometric layers", capturing the WKT projection, and */
1428 : /* perhaps some other housekeeping. */
1429 : /* -------------------------------------------------------------------- */
1430 80 : if( bHaveGeometryColumns && eType != wkbNone )
1431 : {
1432 : int nCoordDim;
1433 :
1434 : /* Sometimes there is an old cruft entry in the geometry_columns
1435 : * table if things were not properly cleaned up before. We make
1436 : * an effort to clean out such cruft.
1437 : */
1438 : osCommand.Printf(
1439 : "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
1440 80 : pszEscapedLayerName );
1441 :
1442 : #ifdef DEBUG
1443 80 : CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
1444 : #endif
1445 :
1446 80 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
1447 80 : if( rc != SQLITE_OK )
1448 : {
1449 0 : sqlite3_free( pszErrMsg );
1450 0 : return FALSE;
1451 : }
1452 :
1453 80 : if( eType == wkbFlatten(eType) )
1454 56 : nCoordDim = 2;
1455 : else
1456 24 : nCoordDim = 3;
1457 :
1458 80 : if ( bIsSpatiaLite )
1459 : {
1460 : /*
1461 : / SpatiaLite full support: calling AddGeometryColumn()
1462 : /
1463 : / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
1464 : / to directly INSERT a row into GEOMETRY_COLUMNS
1465 : / [by-passing AddGeometryColumn() as absolutely required]
1466 : / will severely [and irremediably] corrupt the DB !!!
1467 : */
1468 68 : const char *pszType = OGRToOGCGeomType(eType);
1469 68 : if (pszType[0] == '\0')
1470 0 : pszType = "GEOMETRY";
1471 :
1472 : /*
1473 : / SpatiaLite v.2.4.0 (or any subsequent) is required
1474 : / to support 2.5D: if an obsolete version of the library
1475 : / is found we'll unconditionally activate 2D casting mode
1476 : */
1477 68 : int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
1478 68 : if ( iSpatialiteVersion < 24 && nCoordDim == 3 )
1479 : {
1480 0 : CPLDebug("SQLITE", "Spatialite < 2.4.0 --> 2.5D geometry not supported. Casting to 2D");
1481 0 : nCoordDim = 2;
1482 0 : bForce2D = TRUE;
1483 : }
1484 :
1485 : osCommand.Printf( "SELECT AddGeometryColumn("
1486 : "'%s', '%s', %d, '%s', %d)",
1487 : pszLayerName, pszGeomCol, nSRSId,
1488 68 : pszType, nCoordDim );
1489 : }
1490 : else
1491 : {
1492 12 : if( nSRSId > 0 )
1493 : {
1494 : osCommand.Printf(
1495 : "INSERT INTO geometry_columns "
1496 : "(f_table_name, f_geometry_column, geometry_format, "
1497 : "geometry_type, coord_dimension, srid) VALUES "
1498 : "('%s','%s','%s', %d, %d, %d)",
1499 : pszEscapedLayerName, pszGeomCol, pszGeomFormat,
1500 3 : (int) wkbFlatten(eType), nCoordDim, nSRSId );
1501 : }
1502 : else
1503 : {
1504 : osCommand.Printf(
1505 : "INSERT INTO geometry_columns "
1506 : "(f_table_name, f_geometry_column, geometry_format, "
1507 : "geometry_type, coord_dimension) VALUES "
1508 : "('%s','%s','%s', %d, %d)",
1509 : pszEscapedLayerName, pszGeomCol, pszGeomFormat,
1510 9 : (int) wkbFlatten(eType), nCoordDim );
1511 : }
1512 : }
1513 :
1514 : #ifdef DEBUG
1515 80 : CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
1516 : #endif
1517 :
1518 80 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
1519 80 : if( rc != SQLITE_OK )
1520 : {
1521 : CPLError( CE_Failure, CPLE_AppDefined,
1522 : "Unable to add %s table to geometry_columns:\n%s",
1523 0 : pszLayerName, pszErrMsg );
1524 0 : sqlite3_free( pszErrMsg );
1525 0 : return FALSE;
1526 : }
1527 :
1528 : /* -------------------------------------------------------------------- */
1529 : /* Create the spatial index. */
1530 : /* */
1531 : /* We're doing this before we add geometry and record to the table */
1532 : /* so this may not be exactly the best way to do it. */
1533 : /* -------------------------------------------------------------------- */
1534 :
1535 80 : const char* pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
1536 80 : if ( pszSI != NULL && CSLTestBoolean(pszSI) &&
1537 : (bIsSpatiaLite || EQUAL(pszGeomFormat, "SpatiaLite")) && !bSpatialiteLoaded )
1538 : {
1539 : CPLError( CE_Warning, CPLE_OpenFailed,
1540 0 : "Cannot create a spatial index when Spatialite extensions are not loaded." );
1541 : }
1542 :
1543 : #ifdef HAVE_SPATIALITE
1544 : /* Only if linked against SpatiaLite and the datasource was created as a SpatiaLite DB */
1545 80 : if ( bIsSpatiaLite && bSpatialiteLoaded )
1546 : #else
1547 : if ( 0 )
1548 : #endif
1549 : {
1550 68 : if( pszSI == NULL || CSLTestBoolean(pszSI) )
1551 : {
1552 : osCommand.Printf("SELECT CreateSpatialIndex('%s', '%s')",
1553 68 : pszEscapedLayerName, pszGeomCol);
1554 :
1555 68 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
1556 68 : if( rc != SQLITE_OK )
1557 : {
1558 : CPLError( CE_Failure, CPLE_AppDefined,
1559 0 : "Unable to create spatial index:\n%s", pszErrMsg );
1560 0 : sqlite3_free( pszErrMsg );
1561 0 : return FALSE;
1562 : }
1563 : }
1564 : }
1565 : }
1566 :
1567 : /* -------------------------------------------------------------------- */
1568 : /* Create the layer object. */
1569 : /* -------------------------------------------------------------------- */
1570 : OGRSQLiteTableLayer *poLayer;
1571 :
1572 80 : poLayer = new OGRSQLiteTableLayer( this );
1573 :
1574 160 : if ( poLayer->Initialize( pszLayerName, pszGeomCol, eType, pszGeomFormat,
1575 : FetchSRS(nSRSId), nSRSId ) != CE_None )
1576 : {
1577 0 : delete poLayer;
1578 0 : CPLFree( pszLayerName );
1579 0 : return NULL;
1580 : }
1581 :
1582 80 : poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
1583 80 : if ( CSLFetchBoolean(papszOptions,"COMPRESS_GEOM",FALSE) )
1584 32 : poLayer->SetUseCompressGeom( TRUE );
1585 80 : poLayer->SetSpatialite2D ( bForce2D );
1586 :
1587 : /* -------------------------------------------------------------------- */
1588 : /* Add layer to data source layer list. */
1589 : /* -------------------------------------------------------------------- */
1590 : papoLayers = (OGRSQLiteLayer **)
1591 80 : CPLRealloc( papoLayers, sizeof(OGRSQLiteLayer *) * (nLayers+1) );
1592 :
1593 80 : papoLayers[nLayers++] = poLayer;
1594 :
1595 80 : CPLFree( pszLayerName );
1596 :
1597 80 : return poLayer;
1598 : }
1599 :
1600 : /************************************************************************/
1601 : /* LaunderName() */
1602 : /************************************************************************/
1603 :
1604 108 : char *OGRSQLiteDataSource::LaunderName( const char *pszSrcName )
1605 :
1606 : {
1607 108 : char *pszSafeName = CPLStrdup( pszSrcName );
1608 : int i;
1609 :
1610 793 : for( i = 0; pszSafeName[i] != '\0'; i++ )
1611 : {
1612 685 : pszSafeName[i] = (char) tolower( pszSafeName[i] );
1613 685 : if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
1614 0 : pszSafeName[i] = '_';
1615 : }
1616 :
1617 108 : return pszSafeName;
1618 : }
1619 :
1620 : /************************************************************************/
1621 : /* OGRSQLiteEscape() */
1622 : /************************************************************************/
1623 :
1624 1116 : CPLString OGRSQLiteEscape( const char *pszSrcName )
1625 : {
1626 1116 : CPLString osVal;
1627 19335 : for( int i = 0; pszSrcName[i] != '\0'; i++ )
1628 : {
1629 18219 : if ( pszSrcName[i] == '\'' )
1630 0 : osVal += '\'';
1631 18219 : osVal += pszSrcName[i];
1632 : }
1633 0 : return osVal;
1634 : }
1635 :
1636 : /************************************************************************/
1637 : /* DeleteLayer() */
1638 : /************************************************************************/
1639 :
1640 11 : void OGRSQLiteDataSource::DeleteLayer( const char *pszLayerName )
1641 :
1642 : {
1643 : int iLayer;
1644 :
1645 : /* -------------------------------------------------------------------- */
1646 : /* Verify we are in update mode. */
1647 : /* -------------------------------------------------------------------- */
1648 11 : if( !bUpdate )
1649 : {
1650 : CPLError( CE_Failure, CPLE_NoWriteAccess,
1651 : "Data source %s opened read-only.\n"
1652 : "Layer %s cannot be deleted.\n",
1653 0 : pszName, pszLayerName );
1654 :
1655 0 : return;
1656 : }
1657 :
1658 : /* -------------------------------------------------------------------- */
1659 : /* Try to find layer. */
1660 : /* -------------------------------------------------------------------- */
1661 28 : for( iLayer = 0; iLayer < nLayers; iLayer++ )
1662 : {
1663 27 : if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
1664 10 : break;
1665 : }
1666 :
1667 11 : if( iLayer == nLayers )
1668 : {
1669 : CPLError( CE_Failure, CPLE_AppDefined,
1670 : "Attempt to delete layer '%s', but this layer is not known to OGR.",
1671 1 : pszLayerName );
1672 1 : return;
1673 : }
1674 :
1675 10 : DeleteLayer(iLayer);
1676 : }
1677 :
1678 : /************************************************************************/
1679 : /* DeleteLayer() */
1680 : /************************************************************************/
1681 :
1682 10 : OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
1683 : {
1684 10 : if( iLayer < 0 || iLayer >= nLayers )
1685 : {
1686 : CPLError( CE_Failure, CPLE_AppDefined,
1687 : "Layer %d not in legal range of 0 to %d.",
1688 0 : iLayer, nLayers-1 );
1689 0 : return OGRERR_FAILURE;
1690 : }
1691 :
1692 10 : CPLString osLayerName = GetLayer(iLayer)->GetName();
1693 10 : CPLString osGeometryColumn = GetLayer(iLayer)->GetGeometryColumn();
1694 :
1695 : /* -------------------------------------------------------------------- */
1696 : /* Blow away our OGR structures related to the layer. This is */
1697 : /* pretty dangerous if anything has a reference to this layer! */
1698 : /* -------------------------------------------------------------------- */
1699 10 : CPLDebug( "OGR_SQLITE", "DeleteLayer(%s)", osLayerName.c_str() );
1700 :
1701 10 : delete papoLayers[iLayer];
1702 : memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
1703 10 : sizeof(void *) * (nLayers - iLayer - 1) );
1704 10 : nLayers--;
1705 :
1706 : /* -------------------------------------------------------------------- */
1707 : /* Remove from the database. */
1708 : /* -------------------------------------------------------------------- */
1709 : int rc;
1710 : char *pszErrMsg;
1711 :
1712 10 : CPLString osEscapedLayerName = OGRSQLiteEscape(osLayerName);
1713 10 : const char* pszEscapedLayerName = osEscapedLayerName.c_str();
1714 10 : const char* pszGeometryColumn = osGeometryColumn.size() ? osGeometryColumn.c_str() : NULL;
1715 :
1716 : rc = sqlite3_exec( hDB, CPLSPrintf( "DROP TABLE '%s'", pszEscapedLayerName ),
1717 10 : NULL, NULL, &pszErrMsg );
1718 10 : if( rc != SQLITE_OK )
1719 : {
1720 : CPLError( CE_Failure, CPLE_AppDefined,
1721 : "Unable to drop table %s: %s",
1722 0 : osLayerName.c_str(), pszErrMsg );
1723 0 : sqlite3_free( pszErrMsg );
1724 0 : return OGRERR_FAILURE;
1725 : }
1726 :
1727 : /* -------------------------------------------------------------------- */
1728 : /* Drop from geometry_columns table. */
1729 : /* -------------------------------------------------------------------- */
1730 10 : if( bHaveGeometryColumns )
1731 : {
1732 10 : CPLString osCommand;
1733 :
1734 : osCommand.Printf(
1735 : "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
1736 10 : pszEscapedLayerName );
1737 :
1738 10 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
1739 10 : if( rc != SQLITE_OK )
1740 : {
1741 : CPLError( CE_Warning, CPLE_AppDefined,
1742 : "Removal from geometry_columns failed.\n%s: %s",
1743 0 : osCommand.c_str(), pszErrMsg );
1744 0 : sqlite3_free( pszErrMsg );
1745 0 : return OGRERR_FAILURE;
1746 : }
1747 :
1748 : /* -------------------------------------------------------------------- */
1749 : /* Drop spatialite spatial index tables */
1750 : /* -------------------------------------------------------------------- */
1751 10 : if( bIsSpatiaLite && pszGeometryColumn )
1752 : {
1753 : osCommand.Printf( "DROP TABLE idx_%s_%s", pszEscapedLayerName,
1754 0 : pszGeometryColumn);
1755 0 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
1756 :
1757 : osCommand.Printf( "DROP TABLE idx_%s_%s_node", pszEscapedLayerName,
1758 0 : pszGeometryColumn);
1759 0 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
1760 :
1761 : osCommand.Printf( "DROP TABLE idx_%s_%s_parent", pszEscapedLayerName,
1762 0 : pszGeometryColumn);
1763 0 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
1764 :
1765 : osCommand.Printf( "DROP TABLE idx_%s_%s_rowid", pszEscapedLayerName,
1766 0 : pszGeometryColumn);
1767 0 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
1768 0 : }
1769 : }
1770 10 : return OGRERR_NONE;
1771 : }
1772 :
1773 : /************************************************************************/
1774 : /* SoftStartTransaction() */
1775 : /* */
1776 : /* Create a transaction scope. If we already have a */
1777 : /* transaction active this isn't a real transaction, but just */
1778 : /* an increment to the scope count. */
1779 : /************************************************************************/
1780 :
1781 30 : OGRErr OGRSQLiteDataSource::SoftStartTransaction()
1782 :
1783 : {
1784 30 : nSoftTransactionLevel++;
1785 :
1786 30 : if( nSoftTransactionLevel == 1 )
1787 : {
1788 : int rc;
1789 : char *pszErrMsg;
1790 :
1791 : #ifdef DEBUG
1792 30 : CPLDebug( "OGR_SQLITE", "BEGIN Transaction" );
1793 : #endif
1794 :
1795 30 : rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
1796 30 : if( rc != SQLITE_OK )
1797 : {
1798 0 : nSoftTransactionLevel--;
1799 : CPLError( CE_Failure, CPLE_AppDefined,
1800 : "BEGIN transaction failed: %s",
1801 0 : pszErrMsg );
1802 0 : sqlite3_free( pszErrMsg );
1803 0 : return OGRERR_FAILURE;
1804 : }
1805 : }
1806 :
1807 30 : return OGRERR_NONE;
1808 : }
1809 :
1810 : /************************************************************************/
1811 : /* SoftCommit() */
1812 : /* */
1813 : /* Commit the current transaction if we are at the outer */
1814 : /* scope. */
1815 : /************************************************************************/
1816 :
1817 29 : OGRErr OGRSQLiteDataSource::SoftCommit()
1818 :
1819 : {
1820 29 : if( nSoftTransactionLevel <= 0 )
1821 : {
1822 0 : CPLDebug( "OGR_SQLITE", "SoftCommit() with no transaction active." );
1823 0 : return OGRERR_FAILURE;
1824 : }
1825 :
1826 29 : nSoftTransactionLevel--;
1827 :
1828 29 : if( nSoftTransactionLevel == 0 )
1829 : {
1830 : int rc;
1831 : char *pszErrMsg;
1832 :
1833 : #ifdef DEBUG
1834 29 : CPLDebug( "OGR_SQLITE", "COMMIT Transaction" );
1835 : #endif
1836 :
1837 29 : rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
1838 29 : if( rc != SQLITE_OK )
1839 : {
1840 : CPLError( CE_Failure, CPLE_AppDefined,
1841 : "COMMIT transaction failed: %s",
1842 0 : pszErrMsg );
1843 0 : sqlite3_free( pszErrMsg );
1844 0 : return OGRERR_FAILURE;
1845 : }
1846 : }
1847 :
1848 29 : return OGRERR_NONE;
1849 : }
1850 :
1851 : /************************************************************************/
1852 : /* SoftRollback() */
1853 : /* */
1854 : /* Force a rollback of the current transaction if there is one, */
1855 : /* even if we are nested several levels deep. */
1856 : /************************************************************************/
1857 :
1858 1 : OGRErr OGRSQLiteDataSource::SoftRollback()
1859 :
1860 : {
1861 1 : if( nSoftTransactionLevel <= 0 )
1862 : {
1863 0 : CPLDebug( "OGR_SQLITE", "SoftRollback() with no transaction active." );
1864 0 : return OGRERR_FAILURE;
1865 : }
1866 :
1867 1 : nSoftTransactionLevel = 0;
1868 :
1869 : int rc;
1870 : char *pszErrMsg;
1871 :
1872 : #ifdef DEBUG
1873 1 : CPLDebug( "OGR_SQLITE", "ROLLBACK Transaction" );
1874 : #endif
1875 :
1876 1 : rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, &pszErrMsg );
1877 1 : if( rc != SQLITE_OK )
1878 : {
1879 : CPLError( CE_Failure, CPLE_AppDefined,
1880 : "ROLLBACK transaction failed: %s",
1881 0 : pszErrMsg );
1882 0 : sqlite3_free( pszErrMsg );
1883 0 : return OGRERR_FAILURE;
1884 : }
1885 :
1886 1 : return OGRERR_NONE;
1887 : }
1888 :
1889 : /************************************************************************/
1890 : /* FlushSoftTransaction() */
1891 : /* */
1892 : /* Force the unwinding of any active transaction, and it's */
1893 : /* commit. */
1894 : /************************************************************************/
1895 :
1896 0 : OGRErr OGRSQLiteDataSource::FlushSoftTransaction()
1897 :
1898 : {
1899 0 : if( nSoftTransactionLevel <= 0 )
1900 0 : return OGRERR_NONE;
1901 :
1902 0 : nSoftTransactionLevel = 1;
1903 :
1904 0 : return SoftCommit();
1905 : }
1906 :
1907 : /************************************************************************/
1908 : /* DetectSRSWktColumn() */
1909 : /************************************************************************/
1910 :
1911 71 : int OGRSQLiteDataSource::DetectSRSWktColumn()
1912 : {
1913 71 : int bHasSrsWkt = FALSE;
1914 :
1915 : /* testing for SRS_WKT column presence */
1916 : char **papszResult;
1917 : int nRowCount, nColCount;
1918 71 : char *pszErrMsg = NULL;
1919 : int rc = sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
1920 : &papszResult, &nRowCount, &nColCount,
1921 71 : &pszErrMsg );
1922 :
1923 71 : if( rc == SQLITE_OK )
1924 : {
1925 : int iRow;
1926 493 : for (iRow = 1; iRow <= nRowCount; iRow++)
1927 : {
1928 422 : if (EQUAL("srs_wkt",
1929 : papszResult[(iRow * nColCount) + 1]))
1930 67 : bHasSrsWkt = TRUE;
1931 : }
1932 71 : sqlite3_free_table(papszResult);
1933 : }
1934 : else
1935 : {
1936 0 : sqlite3_free( pszErrMsg );
1937 : }
1938 :
1939 71 : return bHasSrsWkt;
1940 : }
1941 :
1942 : /************************************************************************/
1943 : /* FetchSRSId() */
1944 : /* */
1945 : /* Fetch the id corresponding to an SRS, and if not found, add */
1946 : /* it to the table. */
1947 : /************************************************************************/
1948 :
1949 71 : int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
1950 :
1951 : {
1952 71 : int nSRSId = -1;
1953 71 : const char *pszAuthorityName, *pszAuthorityCode = NULL;
1954 71 : CPLString osCommand;
1955 : char *pszErrMsg;
1956 : int rc;
1957 : char **papszResult;
1958 : int nRowCount, nColCount;
1959 :
1960 71 : if( poSRS == NULL )
1961 0 : return -1;
1962 :
1963 71 : OGRSpatialReference oSRS(*poSRS);
1964 71 : poSRS = NULL;
1965 :
1966 71 : pszAuthorityName = oSRS.GetAuthorityName(NULL);
1967 :
1968 71 : if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
1969 : {
1970 : /* -------------------------------------------------------------------- */
1971 : /* Try to identify an EPSG code */
1972 : /* -------------------------------------------------------------------- */
1973 2 : oSRS.AutoIdentifyEPSG();
1974 :
1975 2 : pszAuthorityName = oSRS.GetAuthorityName(NULL);
1976 2 : if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
1977 : {
1978 1 : pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
1979 1 : if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
1980 : {
1981 : /* Import 'clean' SRS */
1982 1 : oSRS.importFromEPSG( atoi(pszAuthorityCode) );
1983 :
1984 1 : pszAuthorityName = oSRS.GetAuthorityName(NULL);
1985 1 : pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
1986 : }
1987 : }
1988 : }
1989 :
1990 : /* -------------------------------------------------------------------- */
1991 : /* Check whether the EPSG authority code is already mapped to a */
1992 : /* SRS ID. */
1993 : /* -------------------------------------------------------------------- */
1994 71 : if( pszAuthorityName != NULL && strlen(pszAuthorityName) > 0 )
1995 : {
1996 70 : pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
1997 :
1998 70 : if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
1999 : {
2000 : // XXX: We are using case insensitive comparison for "auth_name"
2001 : // values, because there are variety of options exist. By default
2002 : // the driver uses 'EPSG' in upper case, but SpatiaLite extension
2003 : // uses 'epsg' in lower case.
2004 : osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
2005 : "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s'",
2006 70 : pszAuthorityName, pszAuthorityCode );
2007 :
2008 : rc = sqlite3_get_table( hDB, osCommand, &papszResult,
2009 70 : &nRowCount, &nColCount, &pszErrMsg );
2010 70 : if( rc != SQLITE_OK )
2011 : {
2012 : /* Retry without COLLATE NOCASE which may not be understood by older sqlite3 */
2013 0 : sqlite3_free( pszErrMsg );
2014 :
2015 : osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
2016 : "auth_name = '%s' AND auth_srid = '%s'",
2017 0 : pszAuthorityName, pszAuthorityCode );
2018 :
2019 : rc = sqlite3_get_table( hDB, osCommand, &papszResult,
2020 0 : &nRowCount, &nColCount, &pszErrMsg );
2021 :
2022 : /* Retry in lower case for SpatiaLite */
2023 0 : if( rc != SQLITE_OK )
2024 : {
2025 0 : sqlite3_free( pszErrMsg );
2026 : }
2027 0 : else if ( nRowCount == 0 &&
2028 : strcmp(pszAuthorityName, "EPSG") == 0)
2029 : {
2030 : /* If it's in upper case, look for lower case */
2031 0 : sqlite3_free_table(papszResult);
2032 :
2033 : osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
2034 : "auth_name = 'epsg' AND auth_srid = '%s'",
2035 0 : pszAuthorityCode );
2036 :
2037 : rc = sqlite3_get_table( hDB, osCommand, &papszResult,
2038 0 : &nRowCount, &nColCount, &pszErrMsg );
2039 :
2040 0 : if( rc != SQLITE_OK )
2041 : {
2042 0 : sqlite3_free( pszErrMsg );
2043 : }
2044 : }
2045 : }
2046 :
2047 70 : if( rc == SQLITE_OK && nRowCount == 1 )
2048 : {
2049 69 : nSRSId = (papszResult[1] != NULL) ? atoi(papszResult[1]) : -1;
2050 69 : sqlite3_free_table(papszResult);
2051 69 : return nSRSId;
2052 : }
2053 1 : sqlite3_free_table(papszResult);
2054 : }
2055 : }
2056 :
2057 : /* -------------------------------------------------------------------- */
2058 : /* Search for existing record using either WKT definition or */
2059 : /* PROJ.4 string (SpatiaLite variant). */
2060 : /* -------------------------------------------------------------------- */
2061 2 : CPLString osWKT, osProj4;
2062 :
2063 : /* -------------------------------------------------------------------- */
2064 : /* Translate SRS to WKT. */
2065 : /* -------------------------------------------------------------------- */
2066 2 : char *pszWKT = NULL;
2067 :
2068 2 : if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
2069 : {
2070 0 : CPLFree(pszWKT);
2071 0 : return -1;
2072 : }
2073 :
2074 2 : osWKT = pszWKT;
2075 2 : CPLFree( pszWKT );
2076 2 : pszWKT = NULL;
2077 :
2078 2 : if ( !bIsSpatiaLite )
2079 : {
2080 : /* -------------------------------------------------------------------- */
2081 : /* Try to find based on the WKT match. */
2082 : /* -------------------------------------------------------------------- */
2083 1 : osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE srtext = ?");
2084 : }
2085 :
2086 : /* -------------------------------------------------------------------- */
2087 : /* Handle SpatiaLite flavour of the spatial_ref_sys. */
2088 : /* -------------------------------------------------------------------- */
2089 : else
2090 : {
2091 : /* -------------------------------------------------------------------- */
2092 : /* Translate SRS to PROJ.4 string. */
2093 : /* -------------------------------------------------------------------- */
2094 1 : char *pszProj4 = NULL;
2095 :
2096 1 : if( oSRS.exportToProj4( &pszProj4 ) != OGRERR_NONE )
2097 : {
2098 0 : CPLFree(pszProj4);
2099 0 : return -1;
2100 : }
2101 :
2102 1 : osProj4 = pszProj4;
2103 1 : CPLFree( pszProj4 );
2104 1 : pszProj4 = NULL;
2105 :
2106 : /* -------------------------------------------------------------------- */
2107 : /* Try to find based on the PROJ.4 match. */
2108 : /* -------------------------------------------------------------------- */
2109 : osCommand.Printf(
2110 1 : "SELECT srid FROM spatial_ref_sys WHERE proj4text = ?");
2111 : }
2112 :
2113 2 : sqlite3_stmt *hSelectStmt = NULL;
2114 2 : rc = sqlite3_prepare( hDB, osCommand, -1, &hSelectStmt, NULL );
2115 :
2116 2 : if( rc == SQLITE_OK)
2117 2 : rc = sqlite3_bind_text( hSelectStmt, 1, ( !bIsSpatiaLite ) ? osWKT.c_str() : osProj4.c_str(), -1, SQLITE_STATIC );
2118 :
2119 2 : if( rc == SQLITE_OK)
2120 2 : rc = sqlite3_step( hSelectStmt );
2121 :
2122 2 : if (rc == SQLITE_ROW)
2123 : {
2124 0 : if (sqlite3_column_type( hSelectStmt, 0 ) == SQLITE_INTEGER)
2125 0 : nSRSId = sqlite3_column_int( hSelectStmt, 0 );
2126 : else
2127 0 : nSRSId = -1;
2128 :
2129 0 : sqlite3_finalize( hSelectStmt );
2130 0 : return nSRSId;
2131 : }
2132 :
2133 : /* -------------------------------------------------------------------- */
2134 : /* If the command actually failed, then the metadata table is */
2135 : /* likely missing, so we give up. */
2136 : /* -------------------------------------------------------------------- */
2137 2 : if (rc != SQLITE_DONE && rc != SQLITE_ROW)
2138 : {
2139 0 : sqlite3_finalize( hSelectStmt );
2140 0 : return -1;
2141 : }
2142 :
2143 2 : sqlite3_finalize( hSelectStmt );
2144 :
2145 : /* -------------------------------------------------------------------- */
2146 : /* If we have an authority code try to assign SRS ID the same */
2147 : /* as that code. */
2148 : /* -------------------------------------------------------------------- */
2149 2 : if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
2150 : {
2151 : osCommand.Printf( "SELECT * FROM spatial_ref_sys WHERE auth_srid='%s'",
2152 1 : pszAuthorityCode );
2153 : rc = sqlite3_get_table( hDB, osCommand, &papszResult,
2154 1 : &nRowCount, &nColCount, &pszErrMsg );
2155 :
2156 1 : if( rc != SQLITE_OK )
2157 : {
2158 : CPLError( CE_Failure, CPLE_AppDefined,
2159 : "exec(SELECT '%s' FROM spatial_ref_sys) failed: %s",
2160 0 : pszAuthorityCode, pszErrMsg );
2161 0 : sqlite3_free( pszErrMsg );
2162 : }
2163 :
2164 : /* -------------------------------------------------------------------- */
2165 : /* If there is no SRS ID with such auth_srid, use it as SRS ID. */
2166 : /* -------------------------------------------------------------------- */
2167 1 : if ( nRowCount < 1 )
2168 1 : nSRSId = atoi(pszAuthorityCode);
2169 1 : sqlite3_free_table(papszResult);
2170 : }
2171 :
2172 : /* -------------------------------------------------------------------- */
2173 : /* Otherwise get the current maximum srid in the srs table. */
2174 : /* -------------------------------------------------------------------- */
2175 2 : if ( nSRSId == -1 )
2176 : {
2177 : rc = sqlite3_get_table( hDB, "SELECT MAX(srid) FROM spatial_ref_sys",
2178 : &papszResult, &nRowCount, &nColCount,
2179 1 : &pszErrMsg );
2180 :
2181 1 : if( rc != SQLITE_OK )
2182 : {
2183 : CPLError( CE_Failure, CPLE_AppDefined,
2184 0 : "SELECT of the maximum SRS ID failed: %s", pszErrMsg );
2185 0 : sqlite3_free( pszErrMsg );
2186 0 : return -1;
2187 : }
2188 :
2189 1 : if ( nRowCount < 1 || !papszResult[1] )
2190 0 : nSRSId = 50000;
2191 : else
2192 1 : nSRSId = atoi(papszResult[1]) + 1; // Insert as the next SRS ID
2193 1 : sqlite3_free_table(papszResult);
2194 : }
2195 :
2196 : /* -------------------------------------------------------------------- */
2197 : /* Try adding the SRS to the SRS table. */
2198 : /* -------------------------------------------------------------------- */
2199 :
2200 2 : const char* apszToInsert[] = { NULL, NULL, NULL, NULL, NULL, NULL };
2201 :
2202 2 : if ( !bIsSpatiaLite )
2203 : {
2204 1 : if( pszAuthorityName != NULL )
2205 : {
2206 : osCommand.Printf(
2207 : "INSERT INTO spatial_ref_sys (srid,srtext,auth_name,auth_srid) "
2208 : " VALUES (%d, ?, ?, ?)",
2209 1 : nSRSId );
2210 1 : apszToInsert[0] = osWKT.c_str();
2211 1 : apszToInsert[1] = pszAuthorityName;
2212 1 : apszToInsert[2] = pszAuthorityCode;
2213 : }
2214 : else
2215 : {
2216 : osCommand.Printf(
2217 : "INSERT INTO spatial_ref_sys (srid,srtext) "
2218 : " VALUES (%d, ?)",
2219 0 : nSRSId );
2220 0 : apszToInsert[0] = osWKT.c_str();
2221 : }
2222 : }
2223 : else
2224 : {
2225 1 : int bHasSrsWkt = DetectSRSWktColumn();
2226 :
2227 1 : const char *pszProjCS = oSRS.GetAttrValue("PROJCS");
2228 1 : if (pszProjCS == NULL)
2229 0 : pszProjCS = oSRS.GetAttrValue("GEOGCS");
2230 :
2231 1 : if( pszAuthorityName != NULL )
2232 : {
2233 0 : if ( pszProjCS )
2234 : {
2235 : osCommand.Printf(
2236 : "INSERT INTO spatial_ref_sys "
2237 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) "
2238 : "VALUES (%d, ?, ?, ?, ?%s)",
2239 : bHasSrsWkt ? ", srs_wkt" : "",
2240 : nSRSId,
2241 0 : bHasSrsWkt ? ", ?" : "");
2242 0 : apszToInsert[0] = pszAuthorityName;
2243 0 : apszToInsert[1] = pszAuthorityCode;
2244 0 : apszToInsert[2] = pszProjCS;
2245 0 : apszToInsert[3] = osProj4.c_str();
2246 0 : apszToInsert[4] = bHasSrsWkt ? osWKT.c_str() : NULL;
2247 : }
2248 : else
2249 : {
2250 : osCommand.Printf(
2251 : "INSERT INTO spatial_ref_sys "
2252 : "(srid, auth_name, auth_srid, proj4text%s) "
2253 : "VALUES (%d, ?, ?, ?%s)",
2254 : bHasSrsWkt ? ", srs_wkt" : "",
2255 : nSRSId,
2256 0 : bHasSrsWkt ? ", ?" : "");
2257 0 : apszToInsert[0] = pszAuthorityName;
2258 0 : apszToInsert[1] = pszAuthorityCode;
2259 0 : apszToInsert[2] = osProj4.c_str();
2260 0 : apszToInsert[3] = bHasSrsWkt ? osWKT.c_str() : NULL;
2261 : }
2262 : }
2263 : else
2264 : {
2265 : /* SpatiaLite spatial_ref_sys auth_name and auth_srid columns must be NOT NULL */
2266 : /* so insert within a fake OGR "authority" */
2267 1 : if ( pszProjCS )
2268 : {
2269 : osCommand.Printf(
2270 : "INSERT INTO spatial_ref_sys "
2271 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) VALUES (%d, 'OGR', %d, ?, ?%s)",
2272 : bHasSrsWkt ? ", srs_wkt" : "",
2273 : nSRSId, nSRSId,
2274 1 : bHasSrsWkt ? ", ?" : "");
2275 1 : apszToInsert[0] = pszProjCS;
2276 1 : apszToInsert[1] = osProj4.c_str();
2277 1 : apszToInsert[2] = bHasSrsWkt ? osWKT.c_str() : NULL;
2278 : }
2279 : else
2280 : {
2281 : osCommand.Printf(
2282 : "INSERT INTO spatial_ref_sys "
2283 : "(srid, auth_name, auth_srid, proj4text%s) VALUES (%d, 'OGR', %d, ?%s)",
2284 : bHasSrsWkt ? ", srs_wkt" : "",
2285 : nSRSId, nSRSId,
2286 0 : bHasSrsWkt ? ", ?" : "");
2287 0 : apszToInsert[0] = osProj4.c_str();
2288 0 : apszToInsert[1] = bHasSrsWkt ? osWKT.c_str() : NULL;
2289 : }
2290 : }
2291 : }
2292 :
2293 2 : sqlite3_stmt *hInsertStmt = NULL;
2294 2 : rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
2295 :
2296 : int i;
2297 8 : for(i=0;apszToInsert[i]!=NULL;i++)
2298 : {
2299 6 : if( rc == SQLITE_OK)
2300 6 : rc = sqlite3_bind_text( hInsertStmt, i+1, apszToInsert[i], -1, SQLITE_STATIC );
2301 : }
2302 :
2303 2 : if( rc == SQLITE_OK)
2304 2 : rc = sqlite3_step( hInsertStmt );
2305 :
2306 2 : if( rc != SQLITE_OK && rc != SQLITE_DONE )
2307 : {
2308 : CPLError( CE_Failure, CPLE_AppDefined,
2309 : "Unable to insert SRID (%s): %s",
2310 0 : osCommand.c_str(), sqlite3_errmsg(hDB) );
2311 :
2312 0 : sqlite3_finalize( hInsertStmt );
2313 0 : return FALSE;
2314 : }
2315 :
2316 2 : sqlite3_finalize( hInsertStmt );
2317 :
2318 2 : return nSRSId;
2319 : }
2320 :
2321 : /************************************************************************/
2322 : /* FetchSRS() */
2323 : /* */
2324 : /* Return a SRS corresponding to a particular id. Note that */
2325 : /* reference counting should be honoured on the returned */
2326 : /* OGRSpatialReference, as handles may be cached. */
2327 : /************************************************************************/
2328 :
2329 253 : OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
2330 :
2331 : {
2332 253 : if( nId <= 0 )
2333 40 : return NULL;
2334 :
2335 : /* -------------------------------------------------------------------- */
2336 : /* First, we look through our SRID cache, is it there? */
2337 : /* -------------------------------------------------------------------- */
2338 : int i;
2339 :
2340 221 : for( i = 0; i < nKnownSRID; i++ )
2341 : {
2342 143 : if( panSRID[i] == nId )
2343 135 : return papoSRS[i];
2344 : }
2345 :
2346 : /* -------------------------------------------------------------------- */
2347 : /* Try looking up in spatial_ref_sys table. */
2348 : /* -------------------------------------------------------------------- */
2349 : char *pszErrMsg;
2350 : int rc;
2351 : char **papszResult;
2352 : int nRowCount, nColCount;
2353 78 : CPLString osCommand;
2354 78 : OGRSpatialReference *poSRS = NULL;
2355 :
2356 : osCommand.Printf( "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
2357 78 : nId );
2358 : rc = sqlite3_get_table( hDB, osCommand,
2359 78 : &papszResult, &nRowCount, &nColCount, &pszErrMsg );
2360 :
2361 78 : if ( rc == SQLITE_OK )
2362 : {
2363 8 : if( nRowCount < 1 )
2364 : {
2365 0 : sqlite3_free_table(papszResult);
2366 0 : return NULL;
2367 : }
2368 :
2369 8 : char** papszRow = papszResult + nColCount;
2370 8 : if (papszRow[0] != NULL)
2371 : {
2372 8 : CPLString osWKT = papszRow[0];
2373 :
2374 : /* -------------------------------------------------------------------- */
2375 : /* Translate into a spatial reference. */
2376 : /* -------------------------------------------------------------------- */
2377 8 : char *pszWKT = (char *) osWKT.c_str();
2378 :
2379 8 : poSRS = new OGRSpatialReference();
2380 16 : if( poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
2381 : {
2382 0 : delete poSRS;
2383 0 : poSRS = NULL;
2384 8 : }
2385 : }
2386 :
2387 8 : sqlite3_free_table(papszResult);
2388 : }
2389 :
2390 : /* -------------------------------------------------------------------- */
2391 : /* Next try SpatiaLite flavour. SpatiaLite uses PROJ.4 strings */
2392 : /* in 'proj4text' column instead of WKT in 'srtext'. Note: recent */
2393 : /* versions of spatialite have a srs_wkt column too */
2394 : /* -------------------------------------------------------------------- */
2395 : else
2396 : {
2397 70 : sqlite3_free( pszErrMsg );
2398 70 : pszErrMsg = NULL;
2399 :
2400 70 : int bHasSrsWkt = DetectSRSWktColumn();
2401 :
2402 : osCommand.Printf(
2403 : "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys WHERE srid = %d",
2404 70 : bHasSrsWkt ? ", srs_wkt" : "", nId );
2405 : rc = sqlite3_get_table( hDB, osCommand,
2406 : &papszResult, &nRowCount,
2407 70 : &nColCount, &pszErrMsg );
2408 70 : if ( rc == SQLITE_OK )
2409 : {
2410 70 : if( nRowCount < 1 )
2411 : {
2412 0 : sqlite3_free_table(papszResult);
2413 0 : return NULL;
2414 : }
2415 :
2416 : /* -------------------------------------------------------------------- */
2417 : /* Translate into a spatial reference. */
2418 : /* -------------------------------------------------------------------- */
2419 70 : char** papszRow = papszResult + nColCount;
2420 :
2421 70 : const char* pszProj4Text = papszRow[0];
2422 70 : const char* pszAuthName = papszRow[1];
2423 70 : int nAuthSRID = (papszRow[2] != NULL) ? atoi(papszRow[2]) : 0;
2424 70 : char* pszWKT = (bHasSrsWkt) ? (char*) papszRow[3] : NULL;
2425 :
2426 70 : poSRS = new OGRSpatialReference();
2427 :
2428 : /* Try first from EPSG code */
2429 140 : if (pszAuthName != NULL &&
2430 : EQUAL(pszAuthName, "EPSG") &&
2431 : poSRS->importFromEPSG( nAuthSRID ) == OGRERR_NONE)
2432 : {
2433 : /* Do nothing */
2434 : }
2435 : /* Then from WKT string */
2436 8 : else if( pszWKT != NULL &&
2437 : poSRS->importFromWkt( &pszWKT ) == OGRERR_NONE )
2438 : {
2439 : /* Do nothing */
2440 : }
2441 : /* Finally from Proj4 string */
2442 0 : else if( pszProj4Text != NULL &&
2443 : poSRS->importFromProj4( pszProj4Text ) == OGRERR_NONE )
2444 : {
2445 : /* Do nothing */
2446 : }
2447 : else
2448 : {
2449 0 : delete poSRS;
2450 0 : poSRS = NULL;
2451 : }
2452 :
2453 70 : sqlite3_free_table(papszResult);
2454 : }
2455 :
2456 : /* -------------------------------------------------------------------- */
2457 : /* No success, report an error. */
2458 : /* -------------------------------------------------------------------- */
2459 : else
2460 : {
2461 : CPLError( CE_Failure, CPLE_AppDefined,
2462 0 : "%s: %s", osCommand.c_str(), pszErrMsg );
2463 0 : sqlite3_free( pszErrMsg );
2464 0 : return NULL;
2465 : }
2466 : }
2467 :
2468 : /* -------------------------------------------------------------------- */
2469 : /* Add to the cache. */
2470 : /* -------------------------------------------------------------------- */
2471 78 : panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
2472 : papoSRS = (OGRSpatialReference **)
2473 78 : CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
2474 78 : panSRID[nKnownSRID] = nId;
2475 78 : papoSRS[nKnownSRID] = poSRS;
2476 78 : nKnownSRID++;
2477 :
2478 78 : return poSRS;
2479 : }
2480 :
2481 : /************************************************************************/
2482 : /* SetName() */
2483 : /************************************************************************/
2484 :
2485 1 : void OGRSQLiteDataSource::SetName(const char* pszNameIn)
2486 : {
2487 1 : CPLFree(pszName);
2488 1 : pszName = CPLStrdup(pszNameIn);
2489 1 : }
|