1 : /******************************************************************************
2 : * $Id: ogrsqlitetablelayer.cpp 24314 2012-04-24 21:01:34Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRSQLiteTableLayer class, access to an existing table.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 : #include "cpl_string.h"
32 : #include "ogr_sqlite.h"
33 : #include "ogr_p.h"
34 : #include <string>
35 :
36 : #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
37 :
38 : CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 24314 2012-04-24 21:01:34Z rouault $");
39 :
40 : /************************************************************************/
41 : /* OGRSQLiteTableLayer() */
42 : /************************************************************************/
43 :
44 2168 : OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
45 :
46 : {
47 2168 : poDS = poDSIn;
48 :
49 2168 : bSpatialite2D = FALSE;
50 2168 : bLaunderColumnNames = TRUE;
51 :
52 2168 : iNextShapeId = 0;
53 :
54 2168 : nSRSId = -1;
55 :
56 2168 : poFeatureDefn = NULL;
57 2168 : pszTableName = NULL;
58 2168 : pszEscapedTableName = NULL;
59 :
60 2168 : bHasCheckedSpatialIndexTable = FALSE;
61 :
62 2168 : hInsertStmt = NULL;
63 :
64 2168 : eGeomType = wkbUnknown;
65 2168 : bLayerDefnError = FALSE;
66 :
67 2168 : bCachedExtentIsValid = FALSE;
68 2168 : }
69 :
70 : /************************************************************************/
71 : /* ~OGRSQLiteTableLayer() */
72 : /************************************************************************/
73 :
74 2168 : OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
75 :
76 : {
77 2168 : ClearStatement();
78 2168 : ClearInsertStmt();
79 2168 : CPLFree(pszTableName);
80 2168 : CPLFree(pszEscapedTableName);
81 2168 : }
82 :
83 : /************************************************************************/
84 : /* ClearInsertStmt() */
85 : /************************************************************************/
86 :
87 2608 : void OGRSQLiteTableLayer::ClearInsertStmt()
88 : {
89 2608 : if( hInsertStmt != NULL )
90 : {
91 328 : sqlite3_finalize( hInsertStmt );
92 328 : hInsertStmt = NULL;
93 : }
94 2608 : osLastInsertStmt = "";
95 2608 : }
96 :
97 : /************************************************************************/
98 : /* Initialize() */
99 : /************************************************************************/
100 :
101 2168 : CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName,
102 : const char *pszGeomCol,
103 : OGRwkbGeometryType eGeomType,
104 : const char *pszGeomFormat,
105 : OGRSpatialReference *poSRS,
106 : int nSRSId,
107 : int bHasSpatialIndex,
108 : int bHasM,
109 : int bSpatialiteReadOnly,
110 : int bSpatialiteLoaded,
111 : int iSpatialiteVersion,
112 : int bIsVirtualShapeIn )
113 :
114 : {
115 : int rc;
116 2168 : sqlite3 *hDB = poDS->GetDB();
117 :
118 2168 : if( pszGeomCol == NULL )
119 1630 : osGeomColumn = "";
120 : else
121 538 : osGeomColumn = pszGeomCol;
122 :
123 2168 : if( pszGeomFormat )
124 : {
125 538 : if ( EQUAL(pszGeomFormat, "WKT") )
126 14 : eGeomFormat = OSGF_WKT;
127 524 : else if ( EQUAL(pszGeomFormat,"WKB") )
128 102 : eGeomFormat = OSGF_WKB;
129 422 : else if ( EQUAL(pszGeomFormat,"FGF") )
130 2 : eGeomFormat = OSGF_FGF;
131 420 : else if( EQUAL(pszGeomFormat,"SpatiaLite") )
132 420 : eGeomFormat = OSGF_SpatiaLite;
133 : }
134 :
135 2168 : CPLFree( pszFIDColumn );
136 2168 : pszFIDColumn = NULL;
137 :
138 2168 : this->poSRS = poSRS;
139 2168 : this->nSRSId = nSRSId;
140 2168 : this->bHasSpatialIndex = bHasSpatialIndex;
141 2168 : this->bHasM = bHasM;
142 2168 : this->bSpatialiteReadOnly = bSpatialiteReadOnly;
143 2168 : this->bSpatialiteLoaded = bSpatialiteLoaded;
144 2168 : this->iSpatialiteVersion = iSpatialiteVersion;
145 2168 : this->bIsVirtualShape = bIsVirtualShapeIn;
146 2168 : this->pszTableName = CPLStrdup(pszTableName);
147 2168 : this->eGeomType = eGeomType;
148 :
149 2168 : pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
150 :
151 2168 : sqlite3_stmt *hColStmt = NULL;
152 : const char *pszSQL;
153 :
154 2588 : if ( eGeomFormat == OSGF_SpatiaLite &&
155 : bSpatialiteLoaded == TRUE &&
156 : iSpatialiteVersion < 24 && poDS->GetUpdate() )
157 : {
158 : // we need to test version required by Spatialite TRIGGERs
159 0 : hColStmt = NULL;
160 : pszSQL = CPLSPrintf( "SELECT sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = '%s' AND sql LIKE '%%RTreeAlign%%'",
161 0 : pszEscapedTableName );
162 :
163 : int nRowTriggerCount, nColTriggerCount;
164 : char **papszTriggerResult, *pszErrMsg;
165 :
166 : rc = sqlite3_get_table( hDB, pszSQL, &papszTriggerResult,
167 0 : &nRowTriggerCount, &nColTriggerCount, &pszErrMsg );
168 0 : if( nRowTriggerCount >= 1 )
169 : {
170 : // obsolete library version not supporting new triggers
171 : // enforcing ReadOnly mode
172 0 : CPLDebug("SQLITE", "Enforcing ReadOnly mode : obsolete library version not supporting new triggers");
173 0 : this->bSpatialiteReadOnly = TRUE;
174 : }
175 :
176 0 : sqlite3_free_table( papszTriggerResult );
177 : }
178 :
179 2168 : if( poSRS )
180 450 : poSRS->Reference();
181 :
182 2168 : return CE_None;
183 : }
184 :
185 : /************************************************************************/
186 : /* EstablishFeatureDefn() */
187 : /************************************************************************/
188 :
189 1192 : CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn()
190 : {
191 1192 : sqlite3 *hDB = poDS->GetDB();
192 : int rc;
193 : const char *pszSQL;
194 1192 : sqlite3_stmt *hColStmt = NULL;
195 :
196 : /* -------------------------------------------------------------------- */
197 : /* Get the column definitions for this table. */
198 : /* -------------------------------------------------------------------- */
199 :
200 : pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
201 1192 : pszEscapedTableName );
202 :
203 1192 : rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL );
204 1192 : if( rc != SQLITE_OK )
205 : {
206 : CPLError( CE_Failure, CPLE_AppDefined,
207 : "Unable to query table %s for column definitions : %s.",
208 0 : pszTableName, sqlite3_errmsg(hDB) );
209 :
210 0 : return CE_Failure;
211 : }
212 :
213 1192 : rc = sqlite3_step( hColStmt );
214 1192 : if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
215 : {
216 : CPLError( CE_Failure, CPLE_AppDefined,
217 : "In Initialize(): sqlite3_step(%s):\n %s",
218 0 : pszSQL, sqlite3_errmsg(hDB) );
219 0 : sqlite3_finalize( hColStmt );
220 0 : return CE_Failure;
221 : }
222 :
223 : /* -------------------------------------------------------------------- */
224 : /* What should we use as FID? If there is a primary key */
225 : /* integer field, then this will be used as the _rowid_, and we */
226 : /* will pick up the real column name here. Otherwise, we will */
227 : /* just use fid. */
228 : /* */
229 : /* Note that the select _rowid_ will return the real column */
230 : /* name if the rowid corresponds to another primary key */
231 : /* column. */
232 : /* -------------------------------------------------------------------- */
233 1192 : pszFIDColumn = CPLStrdup(sqlite3_column_name( hColStmt, 0 ));
234 :
235 : /* -------------------------------------------------------------------- */
236 : /* Collect the rest of the fields. */
237 : /* -------------------------------------------------------------------- */
238 1192 : BuildFeatureDefn( pszTableName, hColStmt );
239 1192 : sqlite3_finalize( hColStmt );
240 :
241 : /* -------------------------------------------------------------------- */
242 : /* Set the geometry type if we know it. */
243 : /* -------------------------------------------------------------------- */
244 1192 : if( eGeomType != wkbUnknown )
245 368 : poFeatureDefn->SetGeomType( eGeomType );
246 :
247 1192 : return CE_None;
248 : }
249 :
250 : /************************************************************************/
251 : /* GetLayerDefn() */
252 : /************************************************************************/
253 :
254 5820 : OGRFeatureDefn* OGRSQLiteTableLayer::GetLayerDefn()
255 : {
256 5820 : if (poFeatureDefn)
257 4628 : return poFeatureDefn;
258 :
259 1192 : EstablishFeatureDefn();
260 :
261 1192 : if (poFeatureDefn == NULL)
262 : {
263 0 : bLayerDefnError = TRUE;
264 :
265 0 : poFeatureDefn = new OGRFeatureDefn( pszTableName );
266 0 : poFeatureDefn->Reference();
267 : }
268 :
269 1192 : return poFeatureDefn;
270 : }
271 :
272 : /************************************************************************/
273 : /* ResetStatement() */
274 : /************************************************************************/
275 :
276 418 : OGRErr OGRSQLiteTableLayer::ResetStatement()
277 :
278 : {
279 : int rc;
280 418 : CPLString osSQL;
281 :
282 418 : ClearStatement();
283 :
284 418 : iNextShapeId = 0;
285 :
286 : osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s",
287 : pszEscapedTableName,
288 418 : osWHERE.c_str() );
289 :
290 :
291 : //#ifdef HAVE_SQLITE3_PREPARE_V2
292 : // rc = sqlite3_prepare_v2( poDS->GetDB(), osSQL, osSQL.size(),
293 : // &hStmt, NULL );
294 : //#else
295 : rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
296 418 : &hStmt, NULL );
297 : //#endif
298 :
299 418 : if( rc == SQLITE_OK )
300 : {
301 416 : return OGRERR_NONE;
302 : }
303 : else
304 : {
305 : CPLError( CE_Failure, CPLE_AppDefined,
306 : "In ResetStatement(): sqlite3_prepare(%s):\n %s",
307 2 : osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
308 2 : hStmt = NULL;
309 2 : return OGRERR_FAILURE;
310 0 : }
311 : }
312 :
313 : /************************************************************************/
314 : /* GetNextFeature() */
315 : /************************************************************************/
316 :
317 1148 : OGRFeature *OGRSQLiteTableLayer::GetNextFeature()
318 :
319 : {
320 1148 : if (HasLayerDefnError())
321 0 : return NULL;
322 :
323 1148 : return OGRSQLiteLayer::GetNextFeature();
324 : }
325 :
326 : /************************************************************************/
327 : /* GetFeature() */
328 : /************************************************************************/
329 :
330 16 : OGRFeature *OGRSQLiteTableLayer::GetFeature( long nFeatureId )
331 :
332 : {
333 16 : if (HasLayerDefnError())
334 0 : return NULL;
335 :
336 : /* -------------------------------------------------------------------- */
337 : /* If we don't have an explicit FID column, just read through */
338 : /* the result set iteratively to find our target. */
339 : /* -------------------------------------------------------------------- */
340 16 : if( pszFIDColumn == NULL )
341 0 : return OGRSQLiteLayer::GetFeature( nFeatureId );
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Setup explicit query statement to fetch the record we want. */
345 : /* -------------------------------------------------------------------- */
346 16 : CPLString osSQL;
347 : int rc;
348 :
349 16 : ClearStatement();
350 :
351 16 : iNextShapeId = nFeatureId;
352 :
353 : osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = %ld",
354 : pszEscapedTableName,
355 16 : pszFIDColumn, nFeatureId );
356 :
357 16 : CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
358 :
359 : rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
360 16 : &hStmt, NULL );
361 16 : if( rc != SQLITE_OK )
362 : {
363 : CPLError( CE_Failure, CPLE_AppDefined,
364 : "In GetFeature(): sqlite3_prepare(%s):\n %s",
365 0 : osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
366 :
367 0 : return NULL;
368 : }
369 : /* -------------------------------------------------------------------- */
370 : /* Get the feature if possible. */
371 : /* -------------------------------------------------------------------- */
372 16 : OGRFeature *poFeature = NULL;
373 :
374 16 : poFeature = GetNextRawFeature();
375 :
376 16 : ResetReading();
377 :
378 16 : return poFeature;
379 : }
380 :
381 : /************************************************************************/
382 : /* SetAttributeFilter() */
383 : /************************************************************************/
384 :
385 80 : OGRErr OGRSQLiteTableLayer::SetAttributeFilter( const char *pszQuery )
386 :
387 : {
388 80 : if( pszQuery == NULL )
389 38 : osQuery = "";
390 : else
391 42 : osQuery = pszQuery;
392 :
393 80 : BuildWhere();
394 :
395 80 : ResetReading();
396 :
397 80 : return OGRERR_NONE;
398 : }
399 :
400 :
401 : /************************************************************************/
402 : /* SetSpatialFilter() */
403 : /************************************************************************/
404 :
405 52 : void OGRSQLiteTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
406 :
407 : {
408 52 : if( InstallFilter( poGeomIn ) )
409 : {
410 22 : BuildWhere();
411 :
412 22 : ResetReading();
413 : }
414 52 : }
415 :
416 : /************************************************************************/
417 : /* CheckSpatialIndexTable() */
418 : /************************************************************************/
419 :
420 100 : int OGRSQLiteTableLayer::CheckSpatialIndexTable()
421 : {
422 100 : if (bHasSpatialIndex && !bHasCheckedSpatialIndexTable)
423 : {
424 56 : bHasCheckedSpatialIndexTable = TRUE;
425 : char **papszResult;
426 : int nRowCount, nColCount;
427 56 : char *pszErrMsg = NULL;
428 :
429 56 : CPLString osSQL;
430 :
431 : /* This will ensure that RTree support is available */
432 : osSQL.Printf("SELECT pkid FROM 'idx_%s_%s' WHERE xmax > 0 AND xmin < 0 AND ymax > 0 AND ymin < 0",
433 56 : pszEscapedTableName, osGeomColumn.c_str());
434 :
435 : int rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
436 : &papszResult, &nRowCount,
437 56 : &nColCount, &pszErrMsg );
438 :
439 56 : if( rc != SQLITE_OK )
440 : {
441 : CPLDebug("SQLITE", "Count not find or use idx_%s_%s layer (%s). Disabling spatial index",
442 0 : pszEscapedTableName, osGeomColumn.c_str(), pszErrMsg);
443 0 : sqlite3_free( pszErrMsg );
444 0 : bHasSpatialIndex = FALSE;
445 : }
446 : else
447 : {
448 56 : sqlite3_free_table(papszResult);
449 56 : }
450 : }
451 :
452 100 : return bHasSpatialIndex;
453 : }
454 :
455 : /************************************************************************/
456 : /* GetSpatialWhere() */
457 : /************************************************************************/
458 :
459 118 : CPLString OGRSQLiteTableLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
460 : {
461 118 : CPLString osSpatialWHERE;
462 :
463 118 : if( poFilterGeom != NULL && CheckSpatialIndexTable() )
464 : {
465 22 : OGREnvelope sEnvelope;
466 :
467 22 : CPLLocaleC oLocaleEnforcer;
468 :
469 22 : poFilterGeom->getEnvelope( &sEnvelope );
470 :
471 : osSpatialWHERE.Printf("ROWID IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
472 : "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f)",
473 : pszEscapedTableName, osGeomColumn.c_str(),
474 : sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
475 22 : sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
476 : }
477 :
478 118 : if( poFilterGeom != NULL && bSpatialiteLoaded && !bHasSpatialIndex)
479 : {
480 2 : OGREnvelope sEnvelope;
481 :
482 2 : CPLLocaleC oLocaleEnforcer;
483 :
484 2 : poFilterGeom->getEnvelope( &sEnvelope );
485 :
486 : /* A bit inefficient but still faster than OGR filtering */
487 : osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f, %d))",
488 : osGeomColumn.c_str(),
489 : sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
490 : sEnvelope.MaxX + 1e-11, sEnvelope.MaxY + 1e-11,
491 2 : nSRSId);
492 : }
493 :
494 0 : return osSpatialWHERE;
495 : }
496 :
497 : /************************************************************************/
498 : /* BuildWhere() */
499 : /* */
500 : /* Build the WHERE statement appropriate to the current set of */
501 : /* criteria (spatial and attribute queries). */
502 : /************************************************************************/
503 :
504 102 : void OGRSQLiteTableLayer::BuildWhere()
505 :
506 : {
507 102 : osWHERE = "";
508 :
509 102 : CPLString osSpatialWHERE = GetSpatialWhere(m_poFilterGeom);
510 204 : if (osSpatialWHERE.size() != 0)
511 : {
512 8 : osWHERE = "WHERE ";
513 8 : osWHERE += osSpatialWHERE;
514 : }
515 :
516 102 : if( osQuery.size() > 0 )
517 : {
518 38 : if( osWHERE.size() == 0 )
519 : {
520 38 : osWHERE = "WHERE ";
521 38 : osWHERE += osQuery;
522 : }
523 : else
524 : {
525 0 : osWHERE += " AND (";
526 0 : osWHERE += osQuery;
527 0 : osWHERE += ")";
528 : }
529 102 : }
530 102 : }
531 :
532 : /************************************************************************/
533 : /* TestCapability() */
534 : /************************************************************************/
535 :
536 126 : int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
537 :
538 : {
539 126 : if (EQUAL(pszCap,OLCFastFeatureCount))
540 : return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
541 78 : bHasSpatialIndex;
542 :
543 48 : else if (EQUAL(pszCap,OLCFastSpatialFilter))
544 4 : return bHasSpatialIndex;
545 :
546 44 : else if( EQUAL(pszCap,OLCRandomRead) )
547 8 : return pszFIDColumn != NULL;
548 :
549 36 : else if( EQUAL(pszCap,OLCSequentialWrite)
550 : || EQUAL(pszCap,OLCRandomWrite) )
551 : {
552 8 : if ( bSpatialiteReadOnly == TRUE)
553 0 : return FALSE;
554 8 : return poDS->GetUpdate();
555 : }
556 :
557 28 : else if( EQUAL(pszCap,OLCDeleteFeature) )
558 : {
559 6 : if ( bSpatialiteReadOnly == TRUE)
560 0 : return FALSE;
561 6 : return poDS->GetUpdate() && pszFIDColumn != NULL;
562 : }
563 :
564 22 : else if( EQUAL(pszCap,OLCCreateField) )
565 0 : return poDS->GetUpdate();
566 :
567 22 : else if( EQUAL(pszCap,OLCDeleteField) )
568 2 : return poDS->GetUpdate();
569 :
570 20 : else if( EQUAL(pszCap,OLCAlterFieldDefn) )
571 2 : return poDS->GetUpdate();
572 :
573 18 : else if( EQUAL(pszCap,OLCReorderFields) )
574 2 : return poDS->GetUpdate();
575 :
576 : else
577 16 : return OGRSQLiteLayer::TestCapability( pszCap );
578 : }
579 :
580 : /************************************************************************/
581 : /* GetFeatureCount() */
582 : /* */
583 : /* If a spatial filter is in effect, we turn control over to */
584 : /* the generic counter. Otherwise we return the total count. */
585 : /* Eventually we should consider implementing a more efficient */
586 : /* way of counting features matching a spatial query. */
587 : /************************************************************************/
588 :
589 74 : int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
590 :
591 : {
592 74 : if (HasLayerDefnError())
593 0 : return 0;
594 :
595 74 : if( !TestCapability(OLCFastFeatureCount) )
596 10 : return OGRSQLiteLayer::GetFeatureCount( bForce );
597 :
598 : /* -------------------------------------------------------------------- */
599 : /* Form count SQL. */
600 : /* -------------------------------------------------------------------- */
601 : const char *pszSQL;
602 :
603 64 : if (m_poFilterGeom != NULL && CheckSpatialIndexTable() &&
604 : strlen(osQuery) == 0)
605 : {
606 6 : OGREnvelope sEnvelope;
607 :
608 6 : m_poFilterGeom->getEnvelope( &sEnvelope );
609 : pszSQL = CPLSPrintf("SELECT count(*) FROM 'idx_%s_%s' WHERE "
610 : "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f",
611 : pszEscapedTableName, osGeomColumn.c_str(),
612 : sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
613 6 : sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
614 : }
615 : else
616 : {
617 : pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
618 58 : pszEscapedTableName, osWHERE.c_str() );
619 : }
620 :
621 64 : CPLDebug("SQLITE", "Running %s", pszSQL);
622 :
623 : /* -------------------------------------------------------------------- */
624 : /* Execute. */
625 : /* -------------------------------------------------------------------- */
626 : char **papszResult, *pszErrMsg;
627 : int nRowCount, nColCount;
628 64 : int nResult = -1;
629 :
630 64 : if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
631 : &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
632 0 : return -1;
633 :
634 64 : if( nRowCount == 1 && nColCount == 1 )
635 64 : nResult = atoi(papszResult[1]);
636 :
637 64 : sqlite3_free_table( papszResult );
638 :
639 64 : return nResult;
640 : }
641 :
642 : /************************************************************************/
643 : /* GetExtent() */
644 : /************************************************************************/
645 :
646 60 : OGRErr OGRSQLiteTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
647 : {
648 60 : if (HasLayerDefnError())
649 0 : return OGRERR_FAILURE;
650 :
651 60 : if (GetGeomType() == wkbNone)
652 0 : return OGRERR_FAILURE;
653 :
654 60 : if (bCachedExtentIsValid)
655 : {
656 2 : memcpy(psExtent, &oCachedExtent, sizeof(oCachedExtent));
657 2 : return OGRERR_NONE;
658 : }
659 :
660 58 : if (CheckSpatialIndexTable() &&
661 : !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO")))
662 : {
663 : const char* pszSQL;
664 :
665 : pszSQL = CPLSPrintf("SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM 'idx_%s_%s'",
666 4 : pszEscapedTableName, osGeomColumn.c_str());
667 :
668 4 : CPLDebug("SQLITE", "Running %s", pszSQL);
669 :
670 : /* -------------------------------------------------------------------- */
671 : /* Execute. */
672 : /* -------------------------------------------------------------------- */
673 : char **papszResult, *pszErrMsg;
674 : int nRowCount, nColCount;
675 :
676 4 : if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
677 : &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
678 0 : return OGRSQLiteLayer::GetExtent(psExtent, bForce);
679 :
680 4 : OGRErr eErr = OGRERR_FAILURE;
681 :
682 20 : if( nRowCount == 1 && nColCount == 4 &&
683 4 : papszResult[4+0] != NULL &&
684 4 : papszResult[4+1] != NULL &&
685 4 : papszResult[4+2] != NULL &&
686 4 : papszResult[4+3] != NULL)
687 : {
688 4 : psExtent->MinX = atof(papszResult[4+0]);
689 4 : psExtent->MinY = atof(papszResult[4+1]);
690 4 : psExtent->MaxX = atof(papszResult[4+2]);
691 4 : psExtent->MaxY = atof(papszResult[4+3]);
692 4 : eErr = OGRERR_NONE;
693 :
694 4 : bCachedExtentIsValid = TRUE;
695 4 : memcpy(&oCachedExtent, psExtent, sizeof(oCachedExtent));
696 : }
697 :
698 4 : sqlite3_free_table( papszResult );
699 :
700 4 : if (eErr == OGRERR_NONE)
701 4 : return eErr;
702 : }
703 :
704 54 : OGRErr eErr = OGRSQLiteLayer::GetExtent(psExtent, bForce);
705 54 : if (eErr == OGRERR_NONE)
706 : {
707 54 : bCachedExtentIsValid = TRUE;
708 54 : memcpy(&oCachedExtent, psExtent, sizeof(oCachedExtent));
709 : }
710 54 : return eErr;
711 : }
712 :
713 : /************************************************************************/
714 : /* OGRFieldTypeToSQliteType() */
715 : /************************************************************************/
716 :
717 256 : static const char* OGRFieldTypeToSQliteType( OGRFieldType eType )
718 : {
719 256 : if( eType == OFTInteger )
720 26 : return "INTEGER";
721 230 : else if( eType == OFTReal )
722 22 : return "FLOAT";
723 208 : else if( eType == OFTBinary )
724 10 : return "BLOB";
725 : else
726 198 : return "VARCHAR";
727 : }
728 :
729 : /************************************************************************/
730 : /* CreateField() */
731 : /************************************************************************/
732 :
733 78 : OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
734 : int bApproxOK )
735 :
736 : {
737 78 : OGRFieldDefn oField( poFieldIn );
738 :
739 78 : if (HasLayerDefnError())
740 0 : return OGRERR_FAILURE;
741 :
742 78 : ResetReading();
743 :
744 78 : if (!poDS->GetUpdate())
745 : {
746 : CPLError( CE_Failure, CPLE_NotSupported,
747 : UNSUPPORTED_OP_READ_ONLY,
748 0 : "CreateField");
749 0 : return OGRERR_FAILURE;
750 : }
751 :
752 78 : ClearInsertStmt();
753 :
754 : /* -------------------------------------------------------------------- */
755 : /* Do we want to "launder" the column names into SQLite */
756 : /* friendly format? */
757 : /* -------------------------------------------------------------------- */
758 78 : if( bLaunderColumnNames )
759 : {
760 78 : char *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
761 :
762 78 : oField.SetName( pszSafeName );
763 78 : CPLFree( pszSafeName );
764 : }
765 :
766 : /* ADD COLUMN only avaliable since sqlite 3.1.3 */
767 78 : if (CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_USE_ADD_COLUMN", "YES")) &&
768 : sqlite3_libversion_number() > 3 * 1000000 + 1 * 1000 + 3)
769 : {
770 : int rc;
771 78 : char *pszErrMsg = NULL;
772 78 : sqlite3 *hDB = poDS->GetDB();
773 78 : CPLString osCommand;
774 :
775 : osCommand.Printf("ALTER TABLE '%s' ADD COLUMN '%s' %s",
776 : pszEscapedTableName,
777 : oField.GetNameRef(),
778 78 : OGRFieldTypeToSQliteType(oField.GetType()));
779 :
780 : #ifdef DEBUG
781 78 : CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
782 : #endif
783 :
784 78 : rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
785 78 : if( rc != SQLITE_OK )
786 : {
787 : CPLError( CE_Failure, CPLE_AppDefined,
788 : "Failed to add field %s to table %s:\n %s",
789 : oField.GetNameRef(), poFeatureDefn->GetName(),
790 0 : pszErrMsg );
791 0 : sqlite3_free( pszErrMsg );
792 0 : return OGRERR_FAILURE;
793 0 : }
794 : }
795 : else
796 : {
797 0 : OGRErr eErr = AddColumnAncientMethod(oField);
798 0 : if (eErr != OGRERR_NONE)
799 0 : return eErr;
800 : }
801 :
802 : /* -------------------------------------------------------------------- */
803 : /* Add the field to the OGRFeatureDefn. */
804 : /* -------------------------------------------------------------------- */
805 : int iNewField;
806 78 : int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
807 :
808 78 : if( poFeatureDefn->GetGeomType() != wkbNone )
809 : {
810 78 : iNextOrdinal++;
811 : }
812 :
813 182 : for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
814 : {
815 104 : OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
816 :
817 : // we already added OGC_FID so don't do it again
818 104 : if( EQUAL(poFldDefn->GetNameRef(),"OGC_FID") )
819 0 : continue;
820 :
821 104 : iNextOrdinal++;
822 : }
823 :
824 78 : poFeatureDefn->AddFieldDefn( &oField );
825 :
826 78 : iNewField = poFeatureDefn->GetFieldCount() - 1;
827 : panFieldOrdinals = (int *)
828 78 : CPLRealloc(panFieldOrdinals, (iNewField+1) * sizeof(int) );
829 78 : panFieldOrdinals[iNewField] = iNextOrdinal;
830 :
831 78 : return OGRERR_NONE;
832 : }
833 :
834 : /************************************************************************/
835 : /* InitFieldListForRecrerate() */
836 : /************************************************************************/
837 :
838 46 : void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
839 : char* & pszFieldListForSelect,
840 : int nExtraSpace)
841 : {
842 46 : int iField, nFieldListLen = 100 + nExtraSpace;
843 :
844 236 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
845 : {
846 : nFieldListLen +=
847 190 : strlen(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) + 50;
848 : }
849 :
850 46 : pszFieldListForSelect = (char *) CPLCalloc(1,nFieldListLen);
851 46 : pszNewFieldList = (char *) CPLCalloc(1,nFieldListLen);
852 :
853 : /* -------------------------------------------------------------------- */
854 : /* Build list of old fields, and the list of new fields. */
855 : /* -------------------------------------------------------------------- */
856 46 : sprintf( pszFieldListForSelect, "%s", pszFIDColumn ? pszFIDColumn : "OGC_FID" );
857 46 : sprintf( pszNewFieldList, "%s INTEGER PRIMARY KEY",pszFIDColumn ? pszFIDColumn : "OGC_FID" );
858 :
859 46 : if( poFeatureDefn->GetGeomType() != wkbNone )
860 : {
861 46 : strcat( pszFieldListForSelect, "," );
862 46 : strcat( pszNewFieldList, "," );
863 :
864 46 : strcat( pszFieldListForSelect, osGeomColumn );
865 46 : strcat( pszNewFieldList, osGeomColumn );
866 :
867 46 : if ( eGeomFormat == OSGF_WKT )
868 0 : strcat( pszNewFieldList, " VARCHAR" );
869 : else
870 46 : strcat( pszNewFieldList, " BLOB" );
871 : }
872 46 : }
873 :
874 : /************************************************************************/
875 : /* AddColumnAncientMethod() */
876 : /************************************************************************/
877 :
878 0 : OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
879 : {
880 :
881 : /* -------------------------------------------------------------------- */
882 : /* How much space do we need for the list of fields. */
883 : /* -------------------------------------------------------------------- */
884 : int iField;
885 : char *pszOldFieldList, *pszNewFieldList;
886 :
887 : InitFieldListForRecrerate(pszNewFieldList, pszOldFieldList,
888 0 : strlen( oField.GetNameRef() ));
889 :
890 : /* -------------------------------------------------------------------- */
891 : /* Build list of old fields, and the list of new fields. */
892 : /* -------------------------------------------------------------------- */
893 :
894 0 : int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
895 :
896 0 : if( poFeatureDefn->GetGeomType() != wkbNone )
897 : {
898 0 : iNextOrdinal++;
899 : }
900 :
901 0 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
902 : {
903 0 : OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
904 :
905 : // we already added OGC_FID so don't do it again
906 0 : if( EQUAL(poFldDefn->GetNameRef(),pszFIDColumn ? pszFIDColumn : "OGC_FID") )
907 0 : continue;
908 :
909 : sprintf( pszOldFieldList+strlen(pszOldFieldList),
910 0 : ", \"%s\"", poFldDefn->GetNameRef() );
911 :
912 : sprintf( pszNewFieldList+strlen(pszNewFieldList),
913 : ", '%s' %s", poFldDefn->GetNameRef(),
914 0 : OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
915 :
916 0 : iNextOrdinal++;
917 : }
918 :
919 : /* -------------------------------------------------------------------- */
920 : /* Add the new field. */
921 : /* -------------------------------------------------------------------- */
922 :
923 : sprintf( pszNewFieldList+strlen(pszNewFieldList),
924 : ", '%s' %s", oField.GetNameRef(),
925 0 : OGRFieldTypeToSQliteType(oField.GetType()) );
926 :
927 : /* ==================================================================== */
928 : /* Backup, destroy, recreate and repopulate the table. SQLite */
929 : /* has no ALTER TABLE so we have to do all this to add a */
930 : /* column. */
931 : /* ==================================================================== */
932 :
933 : /* -------------------------------------------------------------------- */
934 : /* Do this all in a transaction. */
935 : /* -------------------------------------------------------------------- */
936 0 : poDS->SoftStartTransaction();
937 :
938 : /* -------------------------------------------------------------------- */
939 : /* Save existing related triggers and index */
940 : /* -------------------------------------------------------------------- */
941 : int rc;
942 0 : char *pszErrMsg = NULL;
943 0 : sqlite3 *hDB = poDS->GetDB();
944 0 : CPLString osSQL;
945 :
946 : osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
947 0 : pszEscapedTableName );
948 :
949 : int nRowTriggerIndexCount, nColTriggerIndexCount;
950 0 : char **papszTriggerIndexResult = NULL;
951 : rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
952 0 : &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
953 :
954 : /* -------------------------------------------------------------------- */
955 : /* Make a backup of the table. */
956 : /* -------------------------------------------------------------------- */
957 :
958 0 : if( rc == SQLITE_OK )
959 : rc = sqlite3_exec( hDB,
960 : CPLSPrintf( "CREATE TEMPORARY TABLE t1_back(%s)",
961 : pszOldFieldList ),
962 0 : NULL, NULL, &pszErrMsg );
963 :
964 0 : if( rc == SQLITE_OK )
965 : rc = sqlite3_exec( hDB,
966 : CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
967 : pszOldFieldList,
968 : pszEscapedTableName ),
969 0 : NULL, NULL, &pszErrMsg );
970 :
971 :
972 : /* -------------------------------------------------------------------- */
973 : /* Drop the original table, and recreate with new field. */
974 : /* -------------------------------------------------------------------- */
975 0 : if( rc == SQLITE_OK )
976 : rc = sqlite3_exec( hDB,
977 : CPLSPrintf( "DROP TABLE '%s'",
978 : pszEscapedTableName ),
979 0 : NULL, NULL, &pszErrMsg );
980 :
981 0 : if( rc == SQLITE_OK )
982 : {
983 : const char *pszCmd =
984 : CPLSPrintf( "CREATE TABLE '%s' (%s)",
985 : pszEscapedTableName,
986 0 : pszNewFieldList );
987 : rc = sqlite3_exec( hDB, pszCmd,
988 0 : NULL, NULL, &pszErrMsg );
989 :
990 0 : CPLDebug( "OGR_SQLITE", "exec(%s)", pszCmd );
991 : }
992 :
993 : /* -------------------------------------------------------------------- */
994 : /* Copy backup field values into new table. */
995 : /* -------------------------------------------------------------------- */
996 :
997 0 : if( rc == SQLITE_OK )
998 : rc = sqlite3_exec( hDB,
999 : CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
1000 : pszEscapedTableName,
1001 : pszOldFieldList ),
1002 0 : NULL, NULL, &pszErrMsg );
1003 :
1004 0 : CPLFree( pszOldFieldList );
1005 0 : CPLFree( pszNewFieldList );
1006 :
1007 : /* -------------------------------------------------------------------- */
1008 : /* Cleanup backup table. */
1009 : /* -------------------------------------------------------------------- */
1010 :
1011 0 : if( rc == SQLITE_OK )
1012 : rc = sqlite3_exec( hDB,
1013 : CPLSPrintf( "DROP TABLE t1_back" ),
1014 0 : NULL, NULL, &pszErrMsg );
1015 :
1016 : /* -------------------------------------------------------------------- */
1017 : /* Recreate existing related tables, triggers and index */
1018 : /* -------------------------------------------------------------------- */
1019 :
1020 0 : if( rc == SQLITE_OK )
1021 : {
1022 : int i;
1023 :
1024 0 : for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
1025 : {
1026 0 : if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
1027 : rc = sqlite3_exec( hDB,
1028 0 : papszTriggerIndexResult[i],
1029 0 : NULL, NULL, &pszErrMsg );
1030 : }
1031 : }
1032 :
1033 : /* -------------------------------------------------------------------- */
1034 : /* COMMIT on success or ROLLBACK on failuire. */
1035 : /* -------------------------------------------------------------------- */
1036 :
1037 0 : sqlite3_free_table( papszTriggerIndexResult );
1038 :
1039 0 : if( rc == SQLITE_OK )
1040 : {
1041 0 : poDS->SoftCommit();
1042 : }
1043 : else
1044 : {
1045 : CPLError( CE_Failure, CPLE_AppDefined,
1046 : "Failed to add field %s to table %s:\n %s",
1047 : oField.GetNameRef(), poFeatureDefn->GetName(),
1048 0 : pszErrMsg );
1049 0 : sqlite3_free( pszErrMsg );
1050 :
1051 0 : poDS->SoftRollback();
1052 :
1053 0 : return OGRERR_FAILURE;
1054 : }
1055 :
1056 0 : return OGRERR_NONE;
1057 : }
1058 :
1059 : /************************************************************************/
1060 : /* RecreateTable() */
1061 : /************************************************************************/
1062 :
1063 46 : OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
1064 : const char* pszNewFieldList,
1065 : const char* pszGenericErrorMessage)
1066 : {
1067 : /* -------------------------------------------------------------------- */
1068 : /* Do this all in a transaction. */
1069 : /* -------------------------------------------------------------------- */
1070 46 : poDS->SoftStartTransaction();
1071 :
1072 : /* -------------------------------------------------------------------- */
1073 : /* Save existing related triggers and index */
1074 : /* -------------------------------------------------------------------- */
1075 : int rc;
1076 46 : char *pszErrMsg = NULL;
1077 46 : sqlite3 *hDB = poDS->GetDB();
1078 46 : CPLString osSQL;
1079 :
1080 : osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
1081 46 : pszEscapedTableName );
1082 :
1083 : int nRowTriggerIndexCount, nColTriggerIndexCount;
1084 46 : char **papszTriggerIndexResult = NULL;
1085 : rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
1086 46 : &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
1087 :
1088 : /* -------------------------------------------------------------------- */
1089 : /* Make a backup of the table. */
1090 : /* -------------------------------------------------------------------- */
1091 :
1092 46 : if( rc == SQLITE_OK )
1093 : rc = sqlite3_exec( hDB,
1094 : CPLSPrintf( "CREATE TABLE t1_back(%s)",
1095 : pszNewFieldList ),
1096 46 : NULL, NULL, &pszErrMsg );
1097 :
1098 46 : if( rc == SQLITE_OK )
1099 : rc = sqlite3_exec( hDB,
1100 : CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
1101 : pszFieldListForSelect,
1102 : pszEscapedTableName ),
1103 46 : NULL, NULL, &pszErrMsg );
1104 :
1105 :
1106 : /* -------------------------------------------------------------------- */
1107 : /* Drop the original table */
1108 : /* -------------------------------------------------------------------- */
1109 46 : if( rc == SQLITE_OK )
1110 : rc = sqlite3_exec( hDB,
1111 : CPLSPrintf( "DROP TABLE '%s'",
1112 : pszEscapedTableName ),
1113 46 : NULL, NULL, &pszErrMsg );
1114 :
1115 : /* -------------------------------------------------------------------- */
1116 : /* Rename backup table as new table */
1117 : /* -------------------------------------------------------------------- */
1118 46 : if( rc == SQLITE_OK )
1119 : {
1120 : const char *pszCmd =
1121 : CPLSPrintf( "ALTER TABLE t1_back RENAME TO '%s'",
1122 46 : pszEscapedTableName);
1123 : rc = sqlite3_exec( hDB, pszCmd,
1124 46 : NULL, NULL, &pszErrMsg );
1125 : }
1126 :
1127 : /* -------------------------------------------------------------------- */
1128 : /* Recreate existing related tables, triggers and index */
1129 : /* -------------------------------------------------------------------- */
1130 :
1131 46 : if( rc == SQLITE_OK )
1132 : {
1133 : int i;
1134 :
1135 46 : for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
1136 : {
1137 0 : if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
1138 : rc = sqlite3_exec( hDB,
1139 0 : papszTriggerIndexResult[i],
1140 0 : NULL, NULL, &pszErrMsg );
1141 : }
1142 : }
1143 :
1144 : /* -------------------------------------------------------------------- */
1145 : /* COMMIT on success or ROLLBACK on failuire. */
1146 : /* -------------------------------------------------------------------- */
1147 :
1148 46 : sqlite3_free_table( papszTriggerIndexResult );
1149 :
1150 46 : if( rc == SQLITE_OK )
1151 : {
1152 46 : poDS->SoftCommit();
1153 :
1154 46 : return OGRERR_NONE;
1155 : }
1156 : else
1157 : {
1158 : CPLError( CE_Failure, CPLE_AppDefined,
1159 : "%s:\n %s",
1160 : pszGenericErrorMessage,
1161 0 : pszErrMsg );
1162 0 : sqlite3_free( pszErrMsg );
1163 :
1164 0 : poDS->SoftRollback();
1165 :
1166 0 : return OGRERR_FAILURE;
1167 0 : }
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* DeleteField() */
1172 : /************************************************************************/
1173 :
1174 16 : OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
1175 : {
1176 16 : if (HasLayerDefnError())
1177 0 : return OGRERR_FAILURE;
1178 :
1179 16 : if (!poDS->GetUpdate())
1180 : {
1181 : CPLError( CE_Failure, CPLE_NotSupported,
1182 : UNSUPPORTED_OP_READ_ONLY,
1183 0 : "DeleteField");
1184 0 : return OGRERR_FAILURE;
1185 : }
1186 :
1187 16 : if (iFieldToDelete < 0 || iFieldToDelete >= poFeatureDefn->GetFieldCount())
1188 : {
1189 : CPLError( CE_Failure, CPLE_NotSupported,
1190 4 : "Invalid field index");
1191 4 : return OGRERR_FAILURE;
1192 : }
1193 :
1194 12 : ResetReading();
1195 :
1196 : /* -------------------------------------------------------------------- */
1197 : /* Build list of old fields, and the list of new fields. */
1198 : /* -------------------------------------------------------------------- */
1199 : int iField;
1200 : char *pszNewFieldList, *pszFieldListForSelect;
1201 12 : InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
1202 :
1203 52 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
1204 : {
1205 40 : OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
1206 :
1207 40 : if (iField == iFieldToDelete)
1208 12 : continue;
1209 :
1210 : sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
1211 28 : ", \"%s\"", poFldDefn->GetNameRef() );
1212 :
1213 : sprintf( pszNewFieldList+strlen(pszNewFieldList),
1214 : ", '%s' %s", poFldDefn->GetNameRef(),
1215 28 : OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
1216 : }
1217 :
1218 : /* -------------------------------------------------------------------- */
1219 : /* Recreate table. */
1220 : /* -------------------------------------------------------------------- */
1221 12 : CPLString osErrorMsg;
1222 : osErrorMsg.Printf("Failed to remove field %s from table %s",
1223 : poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef(),
1224 12 : poFeatureDefn->GetName());
1225 :
1226 : OGRErr eErr = RecreateTable(pszFieldListForSelect,
1227 : pszNewFieldList,
1228 12 : osErrorMsg.c_str());
1229 :
1230 12 : CPLFree( pszFieldListForSelect );
1231 12 : CPLFree( pszNewFieldList );
1232 :
1233 12 : if (eErr != OGRERR_NONE)
1234 0 : return eErr;
1235 :
1236 : /* -------------------------------------------------------------------- */
1237 : /* Finish */
1238 : /* -------------------------------------------------------------------- */
1239 12 : int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
1240 :
1241 12 : if( poFeatureDefn->GetGeomType() != wkbNone )
1242 : {
1243 12 : iNextOrdinal++;
1244 : }
1245 :
1246 12 : int iNewField = 0;
1247 52 : for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
1248 : {
1249 40 : if (iField == iFieldToDelete)
1250 12 : continue;
1251 :
1252 28 : panFieldOrdinals[iNewField ++] = iNextOrdinal++;
1253 : }
1254 :
1255 12 : return poFeatureDefn->DeleteFieldDefn( iFieldToDelete );
1256 : }
1257 :
1258 : /************************************************************************/
1259 : /* AlterFieldDefn() */
1260 : /************************************************************************/
1261 :
1262 18 : OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
1263 : {
1264 18 : if (HasLayerDefnError())
1265 0 : return OGRERR_FAILURE;
1266 :
1267 18 : if (!poDS->GetUpdate())
1268 : {
1269 : CPLError( CE_Failure, CPLE_NotSupported,
1270 : UNSUPPORTED_OP_READ_ONLY,
1271 0 : "AlterFieldDefn");
1272 0 : return OGRERR_FAILURE;
1273 : }
1274 :
1275 18 : if (iFieldToAlter < 0 || iFieldToAlter >= poFeatureDefn->GetFieldCount())
1276 : {
1277 : CPLError( CE_Failure, CPLE_NotSupported,
1278 4 : "Invalid field index");
1279 4 : return OGRERR_FAILURE;
1280 : }
1281 :
1282 14 : ClearInsertStmt();
1283 14 : ResetReading();
1284 :
1285 : /* -------------------------------------------------------------------- */
1286 : /* Build list of old fields, and the list of new fields. */
1287 : /* -------------------------------------------------------------------- */
1288 : int iField;
1289 : char *pszNewFieldList, *pszFieldListForSelect;
1290 : InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect,
1291 14 : strlen(poNewFieldDefn->GetNameRef()));
1292 :
1293 80 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
1294 : {
1295 66 : OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
1296 :
1297 : sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
1298 66 : ", \"%s\"", poFldDefn->GetNameRef() );
1299 :
1300 66 : if (iField == iFieldToAlter)
1301 : {
1302 : sprintf( pszNewFieldList+strlen(pszNewFieldList),
1303 : ", '%s' %s",
1304 : (nFlags & ALTER_NAME_FLAG) ? poNewFieldDefn->GetNameRef() :
1305 : poFldDefn->GetNameRef(),
1306 : OGRFieldTypeToSQliteType((nFlags & ALTER_TYPE_FLAG) ?
1307 14 : poNewFieldDefn->GetType() : poFldDefn->GetType()) );
1308 : }
1309 : else
1310 : {
1311 : sprintf( pszNewFieldList+strlen(pszNewFieldList),
1312 : ", '%s' %s", poFldDefn->GetNameRef(),
1313 52 : OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
1314 : }
1315 : }
1316 :
1317 : /* -------------------------------------------------------------------- */
1318 : /* Recreate table. */
1319 : /* -------------------------------------------------------------------- */
1320 14 : CPLString osErrorMsg;
1321 : osErrorMsg.Printf("Failed to alter field %s from table %s",
1322 : poFeatureDefn->GetFieldDefn(iFieldToAlter)->GetNameRef(),
1323 14 : poFeatureDefn->GetName());
1324 :
1325 : OGRErr eErr = RecreateTable(pszFieldListForSelect,
1326 : pszNewFieldList,
1327 14 : osErrorMsg.c_str());
1328 :
1329 14 : CPLFree( pszFieldListForSelect );
1330 14 : CPLFree( pszNewFieldList );
1331 :
1332 14 : if (eErr != OGRERR_NONE)
1333 0 : return eErr;
1334 :
1335 : /* -------------------------------------------------------------------- */
1336 : /* Finish */
1337 : /* -------------------------------------------------------------------- */
1338 :
1339 14 : OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iFieldToAlter);
1340 :
1341 14 : if (nFlags & ALTER_TYPE_FLAG)
1342 14 : poFieldDefn->SetType(poNewFieldDefn->GetType());
1343 14 : if (nFlags & ALTER_NAME_FLAG)
1344 14 : poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
1345 14 : if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
1346 : {
1347 14 : poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
1348 14 : poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
1349 : }
1350 14 : return OGRERR_NONE;
1351 : }
1352 :
1353 : /************************************************************************/
1354 : /* ReorderFields() */
1355 : /************************************************************************/
1356 :
1357 24 : OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
1358 : {
1359 24 : if (HasLayerDefnError())
1360 0 : return OGRERR_FAILURE;
1361 :
1362 24 : if (!poDS->GetUpdate())
1363 : {
1364 : CPLError( CE_Failure, CPLE_NotSupported,
1365 : UNSUPPORTED_OP_READ_ONLY,
1366 0 : "ReorderFields");
1367 0 : return OGRERR_FAILURE;
1368 : }
1369 :
1370 24 : if (poFeatureDefn->GetFieldCount() == 0)
1371 2 : return OGRERR_NONE;
1372 :
1373 22 : OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
1374 22 : if (eErr != OGRERR_NONE)
1375 2 : return eErr;
1376 :
1377 20 : ClearInsertStmt();
1378 20 : ResetReading();
1379 :
1380 : /* -------------------------------------------------------------------- */
1381 : /* Build list of old fields, and the list of new fields. */
1382 : /* -------------------------------------------------------------------- */
1383 : int iField;
1384 : char *pszNewFieldList, *pszFieldListForSelect;
1385 20 : InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
1386 :
1387 104 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
1388 : {
1389 84 : OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(panMap[iField]);
1390 :
1391 : sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
1392 84 : ", \"%s\"", poFldDefn->GetNameRef() );
1393 :
1394 : sprintf( pszNewFieldList+strlen(pszNewFieldList),
1395 : ", '%s' %s", poFldDefn->GetNameRef(),
1396 84 : OGRFieldTypeToSQliteType(poFldDefn->GetType()) );
1397 : }
1398 :
1399 : /* -------------------------------------------------------------------- */
1400 : /* Recreate table. */
1401 : /* -------------------------------------------------------------------- */
1402 20 : CPLString osErrorMsg;
1403 : osErrorMsg.Printf("Failed to reorder fields from table %s",
1404 20 : poFeatureDefn->GetName());
1405 :
1406 : eErr = RecreateTable(pszFieldListForSelect,
1407 : pszNewFieldList,
1408 20 : osErrorMsg.c_str());
1409 :
1410 20 : CPLFree( pszFieldListForSelect );
1411 20 : CPLFree( pszNewFieldList );
1412 :
1413 20 : if (eErr != OGRERR_NONE)
1414 0 : return eErr;
1415 :
1416 : /* -------------------------------------------------------------------- */
1417 : /* Finish */
1418 : /* -------------------------------------------------------------------- */
1419 :
1420 20 : return poFeatureDefn->ReorderFieldDefns( panMap );
1421 : }
1422 :
1423 : /************************************************************************/
1424 : /* BindValues() */
1425 : /************************************************************************/
1426 :
1427 : /* the bBindNullValues is set to TRUE by SetFeature() for UPDATE statements, */
1428 : /* and to FALSE by CreateFeature() for INSERT statements; */
1429 :
1430 670 : OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
1431 : sqlite3_stmt* hStmt,
1432 : int bBindNullValues )
1433 : {
1434 : int rc;
1435 670 : sqlite3 *hDB = poDS->GetDB();
1436 :
1437 : /* -------------------------------------------------------------------- */
1438 : /* Bind the geometry */
1439 : /* -------------------------------------------------------------------- */
1440 670 : int nBindField = 1;
1441 :
1442 670 : if( osGeomColumn.size() != 0 &&
1443 : eGeomFormat != OSGF_FGF )
1444 : {
1445 630 : OGRGeometry* poGeom = poFeature->GetGeometryRef();
1446 630 : if ( poGeom != NULL )
1447 : {
1448 604 : if ( eGeomFormat == OSGF_WKT )
1449 : {
1450 2 : char *pszWKT = NULL;
1451 2 : poGeom->exportToWkt( &pszWKT );
1452 2 : rc = sqlite3_bind_text( hStmt, nBindField++, pszWKT, -1, CPLFree );
1453 : }
1454 602 : else if( eGeomFormat == OSGF_WKB )
1455 : {
1456 190 : int nWKBLen = poGeom->WkbSize();
1457 190 : GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
1458 :
1459 190 : poGeom->exportToWkb( wkbNDR, pabyWKB );
1460 190 : rc = sqlite3_bind_blob( hStmt, nBindField++, pabyWKB, nWKBLen, CPLFree );
1461 : }
1462 412 : else if ( eGeomFormat == OSGF_SpatiaLite )
1463 : {
1464 : int nBLOBLen;
1465 : GByte *pabySLBLOB;
1466 :
1467 : ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR, bHasM,
1468 412 : bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen );
1469 : rc = sqlite3_bind_blob( hStmt, nBindField++, pabySLBLOB,
1470 412 : nBLOBLen, CPLFree );
1471 : }
1472 : else
1473 : {
1474 0 : rc = SQLITE_OK;
1475 0 : CPLAssert(0);
1476 : }
1477 : }
1478 : else
1479 : {
1480 26 : if (bBindNullValues)
1481 4 : rc = sqlite3_bind_null( hStmt, nBindField++ );
1482 : else
1483 22 : rc = SQLITE_OK;
1484 : }
1485 :
1486 630 : if( rc != SQLITE_OK )
1487 : {
1488 : CPLError( CE_Failure, CPLE_AppDefined,
1489 : "sqlite3_bind_blob/text() failed:\n %s",
1490 0 : sqlite3_errmsg(hDB) );
1491 0 : return OGRERR_FAILURE;
1492 : }
1493 : }
1494 :
1495 : /* -------------------------------------------------------------------- */
1496 : /* Bind field values. */
1497 : /* -------------------------------------------------------------------- */
1498 : int iField;
1499 670 : int nFieldCount = poFeatureDefn->GetFieldCount();
1500 1904 : for( iField = 0; iField < nFieldCount; iField++ )
1501 : {
1502 : const char *pszRawValue;
1503 :
1504 1234 : if( !poFeature->IsFieldSet( iField ) )
1505 : {
1506 442 : if (bBindNullValues)
1507 14 : rc = sqlite3_bind_null( hStmt, nBindField++ );
1508 : else
1509 428 : rc = SQLITE_OK;
1510 : }
1511 : else
1512 : {
1513 792 : switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
1514 : {
1515 : case OFTInteger:
1516 : {
1517 198 : int nFieldVal = poFeature->GetFieldAsInteger( iField );
1518 198 : rc = sqlite3_bind_int(hStmt, nBindField++, nFieldVal);
1519 198 : break;
1520 : }
1521 :
1522 : case OFTReal:
1523 : {
1524 226 : double dfFieldVal = poFeature->GetFieldAsDouble( iField );
1525 226 : rc = sqlite3_bind_double(hStmt, nBindField++, dfFieldVal);
1526 226 : break;
1527 : }
1528 :
1529 : case OFTBinary:
1530 : {
1531 42 : int nDataLength = 0;
1532 : GByte* pabyData =
1533 42 : poFeature->GetFieldAsBinary( iField, &nDataLength );
1534 : rc = sqlite3_bind_blob(hStmt, nBindField++,
1535 42 : pabyData, nDataLength, SQLITE_TRANSIENT);
1536 42 : break;
1537 : }
1538 :
1539 : default:
1540 : {
1541 326 : pszRawValue = poFeature->GetFieldAsString( iField );
1542 : rc = sqlite3_bind_text(hStmt, nBindField++,
1543 326 : pszRawValue, -1, SQLITE_TRANSIENT);
1544 : break;
1545 : }
1546 : }
1547 : }
1548 :
1549 1234 : if( rc != SQLITE_OK )
1550 : {
1551 : CPLError( CE_Failure, CPLE_AppDefined,
1552 : "sqlite3_bind_() for column %s failed:\n %s",
1553 : poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
1554 0 : sqlite3_errmsg(hDB) );
1555 0 : return OGRERR_FAILURE;
1556 : }
1557 : }
1558 :
1559 670 : return OGRERR_NONE;
1560 : }
1561 :
1562 : /************************************************************************/
1563 : /* SetFeature() */
1564 : /************************************************************************/
1565 :
1566 16 : OGRErr OGRSQLiteTableLayer::SetFeature( OGRFeature *poFeature )
1567 :
1568 : {
1569 16 : if (HasLayerDefnError())
1570 0 : return OGRERR_FAILURE;
1571 :
1572 16 : if( pszFIDColumn == NULL )
1573 : {
1574 : CPLError( CE_Failure, CPLE_AppDefined,
1575 0 : "SetFeature() without any FID column." );
1576 0 : return OGRERR_FAILURE;
1577 : }
1578 :
1579 16 : if( poFeature->GetFID() == OGRNullFID )
1580 : {
1581 : CPLError( CE_Failure, CPLE_AppDefined,
1582 0 : "SetFeature() with unset FID fails." );
1583 0 : return OGRERR_FAILURE;
1584 : }
1585 :
1586 16 : if (bSpatialiteReadOnly || !poDS->GetUpdate())
1587 : {
1588 : CPLError( CE_Failure, CPLE_NotSupported,
1589 : UNSUPPORTED_OP_READ_ONLY,
1590 0 : "SetFeature");
1591 0 : return OGRERR_FAILURE;
1592 : }
1593 :
1594 16 : sqlite3 *hDB = poDS->GetDB();
1595 16 : CPLString osCommand;
1596 16 : int bNeedComma = FALSE;
1597 :
1598 16 : bCachedExtentIsValid = FALSE;
1599 :
1600 16 : ResetReading();
1601 :
1602 : /* -------------------------------------------------------------------- */
1603 : /* Form the UPDATE command. */
1604 : /* -------------------------------------------------------------------- */
1605 16 : osCommand += CPLSPrintf( "UPDATE '%s' SET ", pszEscapedTableName );
1606 :
1607 : /* -------------------------------------------------------------------- */
1608 : /* Add geometry field name. */
1609 : /* -------------------------------------------------------------------- */
1610 16 : if( osGeomColumn.size() != 0 &&
1611 : eGeomFormat != OSGF_FGF )
1612 : {
1613 16 : osCommand += "\"";
1614 16 : osCommand += osGeomColumn;
1615 16 : osCommand += "\" = ?";
1616 :
1617 16 : bNeedComma = TRUE;
1618 : }
1619 :
1620 : /* -------------------------------------------------------------------- */
1621 : /* Add field names. */
1622 : /* -------------------------------------------------------------------- */
1623 : int iField;
1624 16 : int nFieldCount = poFeatureDefn->GetFieldCount();
1625 :
1626 72 : for( iField = 0; iField < nFieldCount; iField++ )
1627 : {
1628 56 : if( bNeedComma )
1629 56 : osCommand += ",";
1630 :
1631 56 : osCommand += "\"";
1632 56 : osCommand +=poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
1633 56 : osCommand += "\" = ?";
1634 :
1635 56 : bNeedComma = TRUE;
1636 : }
1637 :
1638 16 : if (!bNeedComma)
1639 0 : return OGRERR_NONE;
1640 :
1641 : /* -------------------------------------------------------------------- */
1642 : /* Merge final command. */
1643 : /* -------------------------------------------------------------------- */
1644 16 : osCommand += " WHERE \"";
1645 16 : osCommand += pszFIDColumn;
1646 16 : osCommand += CPLSPrintf("\" = %ld", poFeature->GetFID());
1647 :
1648 : /* -------------------------------------------------------------------- */
1649 : /* Prepare the statement. */
1650 : /* -------------------------------------------------------------------- */
1651 : int rc;
1652 : sqlite3_stmt *hUpdateStmt;
1653 :
1654 : #ifdef DEBUG
1655 16 : CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
1656 : #endif
1657 :
1658 16 : rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
1659 16 : if( rc != SQLITE_OK )
1660 : {
1661 : CPLError( CE_Failure, CPLE_AppDefined,
1662 : "In SetFeature(): sqlite3_prepare(%s):\n %s",
1663 0 : osCommand.c_str(), sqlite3_errmsg(hDB) );
1664 :
1665 0 : return OGRERR_FAILURE;
1666 : }
1667 :
1668 : /* -------------------------------------------------------------------- */
1669 : /* Bind values. */
1670 : /* -------------------------------------------------------------------- */
1671 16 : OGRErr eErr = BindValues( poFeature, hUpdateStmt, TRUE );
1672 16 : if (eErr != OGRERR_NONE)
1673 : {
1674 0 : sqlite3_finalize( hUpdateStmt );
1675 0 : return eErr;
1676 : }
1677 :
1678 : /* -------------------------------------------------------------------- */
1679 : /* Execute the update. */
1680 : /* -------------------------------------------------------------------- */
1681 16 : rc = sqlite3_step( hUpdateStmt );
1682 :
1683 16 : if( rc != SQLITE_OK && rc != SQLITE_DONE )
1684 : {
1685 : CPLError( CE_Failure, CPLE_AppDefined,
1686 : "sqlite3_step() failed:\n %s",
1687 0 : sqlite3_errmsg(hDB) );
1688 :
1689 0 : sqlite3_finalize( hUpdateStmt );
1690 0 : return OGRERR_FAILURE;
1691 : }
1692 :
1693 16 : sqlite3_finalize( hUpdateStmt );
1694 :
1695 16 : return OGRERR_NONE;
1696 : }
1697 :
1698 : /************************************************************************/
1699 : /* CreateFeature() */
1700 : /************************************************************************/
1701 :
1702 654 : OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
1703 :
1704 : {
1705 654 : sqlite3 *hDB = poDS->GetDB();
1706 654 : CPLString osCommand;
1707 654 : CPLString osValues;
1708 654 : int bNeedComma = FALSE;
1709 :
1710 654 : if (HasLayerDefnError())
1711 0 : return OGRERR_FAILURE;
1712 :
1713 654 : if (bSpatialiteReadOnly || !poDS->GetUpdate())
1714 : {
1715 : CPLError( CE_Failure, CPLE_NotSupported,
1716 : UNSUPPORTED_OP_READ_ONLY,
1717 0 : "CreateFeature");
1718 0 : return OGRERR_FAILURE;
1719 : }
1720 :
1721 654 : bCachedExtentIsValid = FALSE;
1722 :
1723 654 : ResetReading();
1724 :
1725 : /* -------------------------------------------------------------------- */
1726 : /* Form the INSERT command. */
1727 : /* -------------------------------------------------------------------- */
1728 654 : osCommand += CPLSPrintf( "INSERT INTO '%s' (", pszEscapedTableName );
1729 :
1730 : /* -------------------------------------------------------------------- */
1731 : /* Add FID if we have a cleartext FID column. */
1732 : /* -------------------------------------------------------------------- */
1733 654 : if( pszFIDColumn != NULL // && !EQUAL(pszFIDColumn,"OGC_FID")
1734 : && poFeature->GetFID() != OGRNullFID )
1735 : {
1736 116 : osCommand += "\"";
1737 116 : osCommand += pszFIDColumn;
1738 116 : osCommand += "\"";
1739 :
1740 116 : osValues += CPLSPrintf( "%ld", poFeature->GetFID() );
1741 116 : bNeedComma = TRUE;
1742 : }
1743 :
1744 : /* -------------------------------------------------------------------- */
1745 : /* Add geometry. */
1746 : /* -------------------------------------------------------------------- */
1747 654 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
1748 :
1749 654 : if( osGeomColumn.size() != 0 &&
1750 : poGeom != NULL &&
1751 : eGeomFormat != OSGF_FGF )
1752 : {
1753 :
1754 592 : if( bNeedComma )
1755 : {
1756 116 : osCommand += ",";
1757 116 : osValues += ",";
1758 : }
1759 :
1760 592 : osCommand += "\"";
1761 592 : osCommand += osGeomColumn;
1762 592 : osCommand += "\"";
1763 :
1764 592 : osValues += "?";
1765 :
1766 592 : bNeedComma = TRUE;
1767 : }
1768 :
1769 : /* -------------------------------------------------------------------- */
1770 : /* Add field values. */
1771 : /* -------------------------------------------------------------------- */
1772 : int iField;
1773 654 : int nFieldCount = poFeatureDefn->GetFieldCount();
1774 :
1775 1832 : for( iField = 0; iField < nFieldCount; iField++ )
1776 : {
1777 1178 : if( !poFeature->IsFieldSet( iField ) )
1778 428 : continue;
1779 :
1780 750 : if( bNeedComma )
1781 : {
1782 690 : osCommand += ",";
1783 690 : osValues += ",";
1784 : }
1785 :
1786 750 : osCommand += "\"";
1787 750 : osCommand +=poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
1788 750 : osCommand += "\"";
1789 :
1790 750 : osValues += "?";
1791 :
1792 750 : bNeedComma = TRUE;
1793 : }
1794 :
1795 : /* -------------------------------------------------------------------- */
1796 : /* Merge final command. */
1797 : /* -------------------------------------------------------------------- */
1798 654 : osCommand += ") VALUES (";
1799 654 : osCommand += osValues;
1800 654 : osCommand += ")";
1801 :
1802 654 : if (bNeedComma == FALSE)
1803 2 : osCommand = CPLSPrintf( "INSERT INTO '%s' DEFAULT VALUES", pszEscapedTableName );
1804 :
1805 : /* -------------------------------------------------------------------- */
1806 : /* Prepare the statement. */
1807 : /* -------------------------------------------------------------------- */
1808 : int rc;
1809 :
1810 654 : if (hInsertStmt == NULL ||
1811 : osCommand != osLastInsertStmt)
1812 : {
1813 : #ifdef DEBUG
1814 328 : CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
1815 : #endif
1816 :
1817 328 : ClearInsertStmt();
1818 328 : osLastInsertStmt = osCommand;
1819 :
1820 : #ifdef HAVE_SQLITE3_PREPARE_V2
1821 328 : rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
1822 : #else
1823 : rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
1824 : #endif
1825 328 : if( rc != SQLITE_OK )
1826 : {
1827 : CPLError( CE_Failure, CPLE_AppDefined,
1828 : "In CreateFeature(): sqlite3_prepare(%s):\n %s",
1829 0 : osCommand.c_str(), sqlite3_errmsg(hDB) );
1830 :
1831 0 : ClearInsertStmt();
1832 0 : return OGRERR_FAILURE;
1833 : }
1834 : }
1835 :
1836 : /* -------------------------------------------------------------------- */
1837 : /* Bind values. */
1838 : /* -------------------------------------------------------------------- */
1839 654 : OGRErr eErr = BindValues( poFeature, hInsertStmt, FALSE );
1840 654 : if (eErr != OGRERR_NONE)
1841 : {
1842 0 : sqlite3_reset( hInsertStmt );
1843 0 : return eErr;
1844 : }
1845 :
1846 : /* -------------------------------------------------------------------- */
1847 : /* Execute the insert. */
1848 : /* -------------------------------------------------------------------- */
1849 654 : rc = sqlite3_step( hInsertStmt );
1850 :
1851 654 : if( rc != SQLITE_OK && rc != SQLITE_DONE )
1852 : {
1853 : CPLError( CE_Failure, CPLE_AppDefined,
1854 : "sqlite3_step() failed:\n %s (%d)",
1855 0 : sqlite3_errmsg(hDB), rc );
1856 0 : sqlite3_reset( hInsertStmt );
1857 0 : return OGRERR_FAILURE;
1858 : }
1859 :
1860 : /* -------------------------------------------------------------------- */
1861 : /* Capture the FID/rowid. */
1862 : /* -------------------------------------------------------------------- */
1863 654 : const sqlite_int64 nFID = sqlite3_last_insert_rowid( hDB );
1864 654 : if(nFID > 0)
1865 : {
1866 652 : poFeature->SetFID( (long)nFID ); /* Possible truncation if nFID is 64bit */
1867 : }
1868 :
1869 654 : sqlite3_reset( hInsertStmt );
1870 :
1871 654 : return OGRERR_NONE;
1872 : }
1873 :
1874 : /************************************************************************/
1875 : /* DeleteFeature() */
1876 : /************************************************************************/
1877 :
1878 4 : OGRErr OGRSQLiteTableLayer::DeleteFeature( long nFID )
1879 :
1880 : {
1881 4 : CPLString osSQL;
1882 : int rc;
1883 4 : char *pszErrMsg = NULL;
1884 :
1885 4 : if (HasLayerDefnError())
1886 0 : return OGRERR_FAILURE;
1887 :
1888 4 : if( pszFIDColumn == NULL )
1889 : {
1890 : CPLError( CE_Failure, CPLE_NotSupported,
1891 0 : "Can't delete feature on a layer without FID column.");
1892 0 : return OGRERR_FAILURE;
1893 : }
1894 :
1895 4 : if (bSpatialiteReadOnly || !poDS->GetUpdate())
1896 : {
1897 : CPLError( CE_Failure, CPLE_NotSupported,
1898 : UNSUPPORTED_OP_READ_ONLY,
1899 0 : "DeleteFeature");
1900 0 : return OGRERR_FAILURE;
1901 : }
1902 :
1903 4 : bCachedExtentIsValid = FALSE;
1904 :
1905 4 : ResetReading();
1906 :
1907 : osSQL.Printf( "DELETE FROM '%s' WHERE \"%s\" = %ld",
1908 : pszEscapedTableName,
1909 4 : pszFIDColumn, nFID );
1910 :
1911 4 : CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
1912 :
1913 4 : rc = sqlite3_exec( poDS->GetDB(), osSQL, NULL, NULL, &pszErrMsg );
1914 4 : if( rc != SQLITE_OK )
1915 : {
1916 : CPLError( CE_Failure, CPLE_AppDefined,
1917 : "In DeleteFeature(): sqlite3_exec(%s):\n %s",
1918 0 : osSQL.c_str(), pszErrMsg );
1919 0 : sqlite3_free( pszErrMsg );
1920 0 : return OGRERR_FAILURE;
1921 : }
1922 :
1923 4 : return OGRERR_NONE;
1924 : }
|