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