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