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