@@ -71,13 +71,38 @@ QgsSpatiaLiteConnection::Error QgsSpatiaLiteConnection::fetchTables( bool loadGe
71
71
return FailedToOpen;
72
72
}
73
73
74
- checkHasMetadataTables ( handle );
75
- if ( !mErrorMsg .isNull () )
74
+ int ret = checkHasMetadataTables ( handle );
75
+ if ( !mErrorMsg .isNull () || ret == LayoutUnknown )
76
76
{
77
77
// unexpected error; invalid SpatiaLite DB
78
78
return FailedToCheckMetadata;
79
79
}
80
80
81
+ bool recentVersion = false ;
82
+ #ifdef SPATIALITE_RECENT_VERSION
83
+ // only if libspatialite version is >= 4.0.0
84
+ recentVersion = true ;
85
+ #endif
86
+
87
+ if ( ret == LayoutCurrent && recentVersion == false )
88
+ {
89
+ // obsolete library version
90
+ mErrorMsg = tr ( " obsolete libspatialite: connecting to this DB requires using v.4.0 (or any subsequent)" );
91
+ return FailedToCheckMetadata;
92
+ }
93
+
94
+ #ifdef SPATIALITE_RECENT_VERSION
95
+ // only if libspatialite version is >= 4.0.0
96
+ // using v.4.0 Abstract Interface
97
+ if (!getTableInfoAbstractInterface ( handle, loadGeometrylessTables ) )
98
+ {
99
+ return FailedToGetTables;
100
+ }
101
+ closeSpatiaLiteDb ( handle );
102
+ return NoError;
103
+ #endif
104
+
105
+ // obsolete library: still using the traditional approach
81
106
if ( !getTableInfo ( handle, loadGeometrylessTables ) )
82
107
{
83
108
return FailedToGetTables;
@@ -87,11 +112,40 @@ QgsSpatiaLiteConnection::Error QgsSpatiaLiteConnection::fetchTables( bool loadGe
87
112
return NoError;
88
113
}
89
114
115
+ bool QgsSpatiaLiteConnection::updateStatistics ()
116
+ {
117
+ QFileInfo fi ( mPath );
118
+ if ( !fi.exists () )
119
+ {
120
+ return false ;
121
+ }
122
+
123
+ sqlite3* handle = openSpatiaLiteDb ( fi.canonicalFilePath () );
124
+ if ( handle == NULL )
125
+ {
126
+ return false ;
127
+ }
128
+
129
+ // checking the library version
130
+ bool recentVersion = false ;
131
+ const char *version = spatialite_version ();
132
+ if ( isdigit (*version) && *version >= ' 4' )
133
+ recentVersion = true ;
134
+
135
+ bool ret = update_layer_statistics ( handle, NULL , NULL );
136
+
137
+ closeSpatiaLiteDb ( handle );
138
+
139
+ return ret;
140
+ }
90
141
91
142
sqlite3 *QgsSpatiaLiteConnection::openSpatiaLiteDb ( QString path )
92
143
{
93
144
sqlite3 *handle = NULL ;
94
145
int ret;
146
+ // activating the SpatiaLite library
147
+ spatialite_init (0 );
148
+
95
149
// trying to open the SQLite DB
96
150
ret = sqlite3_open_v2 ( path.toUtf8 ().constData (), &handle, SQLITE_OPEN_READWRITE, NULL );
97
151
if ( ret )
@@ -109,21 +163,25 @@ void QgsSpatiaLiteConnection::closeSpatiaLiteDb( sqlite3 * handle )
109
163
sqlite3_close ( handle );
110
164
}
111
165
112
- bool QgsSpatiaLiteConnection::checkHasMetadataTables ( sqlite3* handle )
166
+ int QgsSpatiaLiteConnection::checkHasMetadataTables ( sqlite3* handle )
113
167
{
114
168
bool gcSpatiaLite = false ;
115
169
bool rsSpatiaLite = false ;
170
+ bool gcSpatiaLite4 = false ;
171
+ bool rsSpatiaLite4 = false ;
116
172
bool tableName = false ;
117
173
bool geomColumn = false ;
118
174
bool coordDims = false ;
119
175
bool gcSrid = false ;
120
176
bool type = false ;
177
+ bool geometry_type = false ;
121
178
bool spatialIndex = false ;
122
179
bool srsSrid = false ;
123
180
bool authName = false ;
124
181
bool authSrid = false ;
125
182
bool refSysName = false ;
126
183
bool proj4text = false ;
184
+ bool srtext = false ;
127
185
int ret;
128
186
const char *name;
129
187
int i;
@@ -153,13 +211,17 @@ bool QgsSpatiaLiteConnection::checkHasMetadataTables( sqlite3* handle )
153
211
gcSrid = true ;
154
212
if ( strcasecmp ( name, " type" ) == 0 )
155
213
type = true ;
214
+ if ( strcasecmp ( name, " geometry_type" ) == 0 )
215
+ geometry_type = true ;
156
216
if ( strcasecmp ( name, " spatial_index_enabled" ) == 0 )
157
217
spatialIndex = true ;
158
218
}
159
219
}
160
220
sqlite3_free_table ( results );
161
221
if ( tableName && geomColumn && type && coordDims && gcSrid && spatialIndex )
162
222
gcSpatiaLite = true ;
223
+ if ( tableName && geomColumn && geometry_type && coordDims && gcSrid && spatialIndex )
224
+ gcSpatiaLite4 = true ;
163
225
164
226
// checking if table SPATIAL_REF_SYS exists and has the expected layout
165
227
ret = sqlite3_get_table ( handle, " PRAGMA table_info(spatial_ref_sys)" , &results, &rows, &columns, &errMsg );
@@ -182,18 +244,139 @@ bool QgsSpatiaLiteConnection::checkHasMetadataTables( sqlite3* handle )
182
244
refSysName = true ;
183
245
if ( strcasecmp ( name, " proj4text" ) == 0 )
184
246
proj4text = true ;
247
+ if ( strcasecmp ( name, " srtext" ) == 0 )
248
+ srtext = true ;
185
249
}
186
250
}
187
251
sqlite3_free_table ( results );
188
252
if ( srsSrid && authName && authSrid && refSysName && proj4text )
189
253
rsSpatiaLite = true ;
254
+ if ( srsSrid && authName && authSrid && refSysName && proj4text )
255
+ rsSpatiaLite4 = true ;
190
256
191
257
// OK, this one seems to be a valid SpatiaLite DB
258
+ if ( gcSpatiaLite4 && rsSpatiaLite4 )
259
+ return LayoutCurrent;
192
260
if ( gcSpatiaLite && rsSpatiaLite )
193
- return true ;
261
+ return LayoutLegacy ;
194
262
195
263
// this seems to be a valid SQLite DB, but not a SpatiaLite's one
264
+ return LayoutUnknown;
265
+
266
+ error:
267
+ // unexpected IO error
268
+ mErrorMsg = tr ( " unknown error cause" );
269
+ if ( errMsg != NULL )
270
+ {
271
+ mErrorMsg = errMsg;
272
+ sqlite3_free ( errMsg );
273
+ }
196
274
return false ;
275
+ }
276
+
277
+ #ifdef SPATIALITE_RECENT_VERSION
278
+ // only if libspatialite version is >= 4.0.0
279
+ bool QgsSpatiaLiteConnection::getTableInfoAbstractInterface ( sqlite3 * handle, bool loadGeometrylessTables )
280
+ {
281
+ int ret;
282
+ int i;
283
+ char **results;
284
+ int rows;
285
+ int columns;
286
+ char *errMsg = NULL ;
287
+ bool ok = false ;
288
+ QString sql;
289
+ gaiaVectorLayersListPtr list;
290
+
291
+ const char *version = spatialite_version ();
292
+ if ( isdigit (*version) && *version >= ' 4' )
293
+ ; // OK, linked against libspatialite v.4.0 (or any subsequent)
294
+ else
295
+ {
296
+ mErrorMsg = tr ( " obsolete libspatialite: AbstractInterface is unsupported" );
297
+ return false ;
298
+ }
299
+
300
+ // attempting to load the VectorLayersList
301
+ list = gaiaGetVectorLayersList (handle, NULL , NULL , GAIA_VECTORS_LIST_FAST);
302
+ if (list != NULL )
303
+ {
304
+ gaiaVectorLayerPtr lyr = list->First ;
305
+ while ( lyr != NULL )
306
+ {
307
+ // populating the QGIS own Layers List
308
+ if (lyr->AuthInfos )
309
+ {
310
+ if ( lyr->AuthInfos ->IsHidden )
311
+ {
312
+ // skipping any Hidden layer
313
+ lyr = lyr->Next ;
314
+ continue ;
315
+ }
316
+ }
317
+
318
+ QString tableName = QString::fromUtf8 ( lyr->TableName );
319
+ QString column = QString::fromUtf8 ( lyr->GeometryName );
320
+ QString type = tr ( " UNKNOWN" );
321
+ switch (lyr->GeometryType )
322
+ {
323
+ case GAIA_VECTOR_GEOMETRY:
324
+ type = tr ( " GEOMETRY" );
325
+ break ;
326
+ case GAIA_VECTOR_POINT:
327
+ type = tr ( " POINT" );
328
+ break ;
329
+ case GAIA_VECTOR_LINESTRING:
330
+ type = tr ( " LINESTRING" );
331
+ break ;
332
+ case GAIA_VECTOR_POLYGON:
333
+ type = tr ( " POLYGON" );
334
+ break ;
335
+ case GAIA_VECTOR_MULTIPOINT:
336
+ type = tr ( " MULTIPOINT" );
337
+ break ;
338
+ case GAIA_VECTOR_MULTILINESTRING:
339
+ type = tr ( " MULTILINESTRING" );
340
+ break ;
341
+ case GAIA_VECTOR_MULTIPOLYGON:
342
+ type = tr ( " MULTIPOLYGON" );
343
+ break ;
344
+ case GAIA_VECTOR_GEOMETRYCOLLECTION:
345
+ type = tr ( " GEOMETRYCOLLECTION" );
346
+ break ;
347
+ };
348
+ mTables .append ( TableEntry ( tableName, column, type ) );
349
+ ok = true ;
350
+
351
+ lyr = lyr->Next ;
352
+ }
353
+ gaiaFreeVectorLayersList (list);
354
+ }
355
+
356
+ if ( loadGeometrylessTables )
357
+ {
358
+ // get all tables
359
+ sql = " SELECT name "
360
+ " FROM sqlite_master "
361
+ " WHERE type in ('table', 'view')" ;
362
+ ret = sqlite3_get_table ( handle, sql.toUtf8 (), &results, &rows, &columns, &errMsg );
363
+ if ( ret != SQLITE_OK )
364
+ goto error;
365
+ if ( rows < 1 )
366
+ ;
367
+ else
368
+ {
369
+ for ( i = 1 ; i <= rows; i++ )
370
+ {
371
+ QString tableName = QString::fromUtf8 ( results[( i * columns ) + 0 ] );
372
+ mTables .append ( TableEntry ( tableName, QString (), " qgis_table" ) );
373
+ }
374
+ ok = true ;
375
+ }
376
+ sqlite3_free_table ( results );
377
+ }
378
+
379
+ return ok;
197
380
198
381
error:
199
382
// unexpected IO error
@@ -205,6 +388,7 @@ bool QgsSpatiaLiteConnection::checkHasMetadataTables( sqlite3* handle )
205
388
}
206
389
return false ;
207
390
}
391
+ #endif
208
392
209
393
bool QgsSpatiaLiteConnection::getTableInfo ( sqlite3 * handle, bool loadGeometrylessTables )
210
394
{
0 commit comments