1 : /******************************************************************************
2 : * $Id: ogrsqlitelayer.cpp 25125 2012-10-14 15:55:27Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRSQLiteLayer class, code shared between
6 : * the direct table access, and the generic SQL results.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : *
11 : * Contributor: Alessandro Furieri, a.furieri@lqt.it
12 : * Portions of this module supporting SpatiaLite's own 3D geometries
13 : * [XY, XYM, XYZ and XYZM] available since v.2.4.0
14 : * Developed for Faunalia ( http://www.faunalia.it) with funding from
15 : * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
16 : *
17 : ******************************************************************************
18 : * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
19 : *
20 : * Permission is hereby granted, free of charge, to any person obtaining a
21 : * copy of this software and associated documentation files (the "Software"),
22 : * to deal in the Software without restriction, including without limitation
23 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 : * and/or sell copies of the Software, and to permit persons to whom the
25 : * Software is furnished to do so, subject to the following conditions:
26 : *
27 : * The above copyright notice and this permission notice shall be included
28 : * in all copies or substantial portions of the Software.
29 : *
30 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
31 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
33 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
35 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36 : * DEALINGS IN THE SOFTWARE.
37 : ****************************************************************************/
38 :
39 : #include "cpl_conv.h"
40 : #include "cpl_string.h"
41 : #include "ogr_sqlite.h"
42 : #include <cassert>
43 :
44 : CPL_CVSID("$Id: ogrsqlitelayer.cpp 25125 2012-10-14 15:55:27Z rouault $");
45 :
46 : /************************************************************************/
47 : /* OGRSQLiteLayer() */
48 : /************************************************************************/
49 :
50 1943 : OGRSQLiteLayer::OGRSQLiteLayer()
51 :
52 : {
53 1943 : poDS = NULL;
54 :
55 1943 : pszFIDColumn = NULL;
56 :
57 1943 : eGeomFormat = OSGF_None;
58 :
59 1943 : hStmt = NULL;
60 1943 : bDoStep = TRUE;
61 :
62 1943 : iNextShapeId = 0;
63 :
64 1943 : poSRS = NULL;
65 1943 : nSRSId = UNINITIALIZED_SRID; // we haven't even queried the database for it yet.
66 :
67 1943 : panFieldOrdinals = NULL;
68 1943 : iFIDCol = -1;
69 1943 : iGeomCol = -1;
70 :
71 1943 : bTriedAsSpatiaLite = FALSE;
72 1943 : bHasSpatialIndex = FALSE;
73 1943 : bHasM = FALSE;
74 :
75 1943 : bIsVirtualShape = FALSE;
76 :
77 1943 : bUseComprGeom = CSLTestBoolean(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
78 1943 : }
79 :
80 : /************************************************************************/
81 : /* ~OGRSQLiteLayer() */
82 : /************************************************************************/
83 :
84 1943 : OGRSQLiteLayer::~OGRSQLiteLayer()
85 :
86 : {
87 1943 : Finalize();
88 1943 : }
89 :
90 : /************************************************************************/
91 : /* Finalize() */
92 : /************************************************************************/
93 :
94 2140 : void OGRSQLiteLayer::Finalize()
95 : {
96 : /* Caution: this function can be called several times (see */
97 : /* OGRSQLiteExecuteSQLLayer::~OGRSQLiteExecuteSQLLayer()), so it must */
98 : /* be a no-op on second call */
99 :
100 2140 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
101 : {
102 : CPLDebug( "SQLite", "%d features read on layer '%s'.",
103 : (int) m_nFeaturesRead,
104 510 : poFeatureDefn->GetName() );
105 : }
106 :
107 2140 : if( hStmt != NULL )
108 : {
109 352 : sqlite3_finalize( hStmt );
110 352 : hStmt = NULL;
111 : }
112 :
113 2140 : if( poFeatureDefn != NULL )
114 : {
115 1279 : poFeatureDefn->Release();
116 1279 : poFeatureDefn = NULL;
117 : }
118 :
119 2140 : if( poSRS != NULL )
120 : {
121 368 : poSRS->Release();
122 368 : poSRS = NULL;
123 : }
124 :
125 2140 : CPLFree( pszFIDColumn );
126 2140 : pszFIDColumn = NULL;
127 2140 : CPLFree( panFieldOrdinals );
128 2140 : panFieldOrdinals = NULL;
129 2140 : }
130 :
131 : /************************************************************************/
132 : /* OGRIsBinaryGeomCol() */
133 : /************************************************************************/
134 :
135 : static
136 267 : int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt, int iCol,
137 : OGRFieldDefn& oField,
138 : OGRSQLiteGeomFormat& eGeomFormat,
139 : CPLString& osGeomColumn )
140 : {
141 267 : OGRGeometry* poGeometry = NULL;
142 267 : const int nBytes = sqlite3_column_bytes( hStmt, iCol );
143 267 : CPLPushErrorHandler(CPLQuietErrorHandler);
144 : /* Try as spatialite first since createFromWkb() can sometimes */
145 : /* interpret spatialite blobs as WKB for certain SRID values */
146 267 : if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
147 : (GByte*)sqlite3_column_blob( hStmt, iCol ), nBytes,
148 : &poGeometry ) == OGRERR_NONE )
149 : {
150 101 : eGeomFormat = OSGF_SpatiaLite;
151 : }
152 166 : else if( OGRGeometryFactory::createFromWkb(
153 : (GByte*)sqlite3_column_blob( hStmt, iCol ),
154 : NULL, &poGeometry, nBytes ) == OGRERR_NONE )
155 : {
156 8 : eGeomFormat = OSGF_WKB;
157 : }
158 158 : else if( OGRGeometryFactory::createFromFgf(
159 : (GByte*)sqlite3_column_blob( hStmt, iCol ),
160 : NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
161 : {
162 0 : eGeomFormat = OSGF_FGF;
163 : }
164 267 : CPLPopErrorHandler();
165 267 : CPLErrorReset();
166 267 : delete poGeometry;
167 267 : if( eGeomFormat != OSGF_None )
168 : {
169 109 : osGeomColumn = oField.GetNameRef();
170 109 : return TRUE;
171 : }
172 158 : return FALSE;
173 : }
174 :
175 : /************************************************************************/
176 : /* BuildFeatureDefn() */
177 : /* */
178 : /* Build feature definition from a set of column definitions */
179 : /* set on a statement. Sift out geometry and FID fields. */
180 : /************************************************************************/
181 :
182 1279 : void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
183 : sqlite3_stmt *hStmt,
184 : const std::set<CPLString>& aosGeomCols )
185 :
186 : {
187 1279 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
188 1279 : int nRawColumns = sqlite3_column_count( hStmt );
189 :
190 1279 : poFeatureDefn->Reference();
191 :
192 1279 : panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
193 :
194 : int iCol;
195 1279 : for( iCol = 0; iCol < nRawColumns; iCol++ )
196 : {
197 : OGRFieldDefn oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )),
198 6041 : OFTString );
199 :
200 : // In some cases, particularly when there is a real name for
201 : // the primary key/_rowid_ column we will end up getting the
202 : // primary key column appearing twice. Ignore any repeated names.
203 6041 : if( poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
204 7 : continue;
205 :
206 : /* In the case of Spatialite VirtualShape, the PKUID */
207 : /* should be considered as a primary key */
208 6034 : if( bIsVirtualShape && EQUAL(oField.GetNameRef(), "PKUID") )
209 : {
210 4 : CPLFree(pszFIDColumn);
211 4 : pszFIDColumn = CPLStrdup(oField.GetNameRef());
212 : }
213 :
214 6034 : if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oField.GetNameRef()))
215 1232 : continue;
216 :
217 : //oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
218 :
219 4802 : if( osGeomColumn.size()
220 : && EQUAL(oField.GetNameRef(),osGeomColumn) )
221 311 : continue;
222 4491 : if( aosGeomCols.find( oField.GetNameRef() ) != aosGeomCols.end() )
223 6 : continue;
224 :
225 4485 : int nColType = sqlite3_column_type( hStmt, iCol );
226 4485 : const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
227 : //CPLDebug("SQLITE", "decltype(%s) = %s",
228 : // oField.GetNameRef(), pszDeclType ? pszDeclType : "null");
229 4485 : OGRFieldType eFieldType = OFTString;
230 4485 : if (pszDeclType != NULL)
231 : {
232 4138 : if (EQUAL(pszDeclType, "INTEGER"))
233 1073 : nColType = SQLITE_INTEGER;
234 3348 : else if (EQUAL(pszDeclType, "FLOAT") ||
235 : EQUAL(pszDeclType, "DECIMAL"))
236 283 : nColType = SQLITE_FLOAT;
237 2782 : else if (EQUAL(pszDeclType, "BLOB"))
238 484 : nColType = SQLITE_BLOB;
239 3556 : else if (EQUAL(pszDeclType, "TEXT") ||
240 : EQUAL(pszDeclType, "VARCHAR"))
241 1258 : nColType = SQLITE_TEXT;
242 1134 : else if ((EQUAL(pszDeclType, "TIMESTAMP") ||
243 : EQUAL(pszDeclType, "DATETIME")) && nColType == SQLITE_TEXT)
244 94 : eFieldType = OFTDateTime;
245 1040 : else if (EQUAL(pszDeclType, "DATE") && nColType == SQLITE_TEXT)
246 94 : eFieldType = OFTDate;
247 852 : else if (EQUAL(pszDeclType, "TIME") && nColType == SQLITE_TEXT)
248 94 : eFieldType = OFTTime;
249 : }
250 :
251 : // Recognise some common geometry column names.
252 4485 : if( (EQUAL(oField.GetNameRef(),"wkt_geometry")
253 : || EQUAL(oField.GetNameRef(),"geometry")
254 : || EQUALN(oField.GetNameRef(), "asbinary(", 9)
255 : || EQUALN(oField.GetNameRef(), "astext(", 7)
256 : || (EQUALN(oField.GetNameRef(), "st_", 3) && nColType == SQLITE_BLOB ) )
257 : && osGeomColumn.size() == 0 )
258 : {
259 201 : if( nColType == SQLITE_BLOB )
260 : {
261 193 : const int nBytes = sqlite3_column_bytes( hStmt, iCol );
262 193 : if( nBytes > 0 )
263 : {
264 105 : if( OGRIsBinaryGeomCol( hStmt, iCol, oField,
265 : eGeomFormat, osGeomColumn ) )
266 105 : continue;
267 : }
268 : else
269 : {
270 : /* This could also be a SpatialLite geometry, so */
271 : /* we'll also try to decode as SpatialLite if */
272 : /* bTriedAsSpatiaLite is not FALSE */
273 88 : osGeomColumn = oField.GetNameRef();
274 88 : eGeomFormat = OSGF_WKB;
275 88 : continue;
276 : }
277 : }
278 8 : else if( nColType == SQLITE_TEXT )
279 : {
280 4 : char* pszText = (char*) sqlite3_column_text( hStmt, iCol );
281 4 : if( pszText != NULL )
282 : {
283 4 : CPLPushErrorHandler(CPLQuietErrorHandler);
284 4 : OGRGeometry* poGeometry = NULL;
285 4 : if( OGRGeometryFactory::createFromWkt(
286 : &pszText, NULL, &poGeometry ) == OGRERR_NONE )
287 : {
288 3 : osGeomColumn = oField.GetNameRef();
289 3 : eGeomFormat = OSGF_WKT;
290 : }
291 4 : CPLPopErrorHandler();
292 4 : CPLErrorReset();
293 4 : delete poGeometry;
294 4 : if( eGeomFormat != OSGF_None )
295 3 : continue;
296 : }
297 : else
298 : {
299 0 : osGeomColumn = oField.GetNameRef();
300 0 : eGeomFormat = OSGF_WKT;
301 0 : continue;
302 : }
303 : }
304 : }
305 :
306 : // SpatialLite / Gaia
307 4289 : if( EQUAL(oField.GetNameRef(),"GaiaGeometry")
308 : && osGeomColumn.size() == 0 )
309 : {
310 0 : osGeomColumn = oField.GetNameRef();
311 0 : eGeomFormat = OSGF_SpatiaLite;
312 0 : continue;
313 : }
314 :
315 : // Recognize a geometry column from trying to build the geometry
316 : // Usefull for OGRSQLiteSelectLayer
317 4289 : if( nColType == SQLITE_BLOB && osGeomColumn.size() == 0 )
318 : {
319 278 : const int nBytes = sqlite3_column_bytes( hStmt, iCol );
320 278 : if( nBytes > 0 && OGRIsBinaryGeomCol( hStmt, iCol, oField,
321 : eGeomFormat, osGeomColumn ) )
322 4 : continue;
323 : }
324 :
325 : // The rowid is for internal use, not a real column.
326 4285 : if( EQUAL(oField.GetNameRef(),"_rowid_") )
327 0 : continue;
328 :
329 : // The OGC_FID is for internal use, not a real user visible column.
330 4285 : if( EQUAL(oField.GetNameRef(),"OGC_FID") )
331 31 : continue;
332 :
333 4254 : switch( nColType )
334 : {
335 : case SQLITE_INTEGER:
336 1227 : oField.SetType( OFTInteger );
337 1227 : break;
338 :
339 : case SQLITE_FLOAT:
340 629 : oField.SetType( OFTReal );
341 629 : break;
342 :
343 : case SQLITE_BLOB:
344 362 : oField.SetType( OFTBinary );
345 : break;
346 :
347 : default:
348 : /* leave it as OFTString */;
349 : }
350 :
351 : /* config option just in case we wouldn't want that in some cases */
352 4254 : if( (eFieldType == OFTTime || eFieldType == OFTDate ||
353 : eFieldType == OFTDateTime) &&
354 : CSLTestBoolean(
355 : CPLGetConfigOption("OGR_SQLITE_ENABLE_DATETIME", "YES")) )
356 : {
357 282 : oField.SetType( eFieldType );
358 : }
359 :
360 4254 : poFeatureDefn->AddFieldDefn( &oField );
361 4254 : panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
362 : }
363 :
364 1279 : if( pszFIDColumn != NULL )
365 : {
366 741 : for( iCol = 0; iCol < nRawColumns; iCol++ )
367 : {
368 741 : if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmt,iCol)).c_str(),
369 : pszFIDColumn) )
370 : {
371 737 : iFIDCol = iCol;
372 737 : break;
373 : }
374 : }
375 : }
376 :
377 : /* -------------------------------------------------------------------- */
378 : /* If we have no geometry source, we know our geometry type is */
379 : /* none. */
380 : /* -------------------------------------------------------------------- */
381 1279 : if( osGeomColumn.size() == 0 )
382 768 : poFeatureDefn->SetGeomType( wkbNone );
383 : else
384 : {
385 2295 : for( iCol = 0; iCol < nRawColumns; iCol++ )
386 : {
387 2295 : if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmt,iCol)).c_str(),
388 : osGeomColumn) )
389 : {
390 511 : iGeomCol = iCol;
391 511 : break;
392 : }
393 : }
394 : }
395 1279 : }
396 :
397 : /************************************************************************/
398 : /* GetFIDColumn() */
399 : /************************************************************************/
400 :
401 1 : const char *OGRSQLiteLayer::GetFIDColumn()
402 :
403 : {
404 1 : if( pszFIDColumn != NULL )
405 1 : return pszFIDColumn;
406 : else
407 0 : return "";
408 : }
409 :
410 : /************************************************************************/
411 : /* GetGeometryColumn() */
412 : /************************************************************************/
413 :
414 37 : const char *OGRSQLiteLayer::GetGeometryColumn()
415 :
416 : {
417 37 : if( osGeomColumn.size() != 0 )
418 37 : return osGeomColumn.c_str();
419 : else
420 0 : return "";
421 : }
422 :
423 : /************************************************************************/
424 : /* ResetReading() */
425 : /************************************************************************/
426 :
427 1061 : void OGRSQLiteLayer::ResetReading()
428 :
429 : {
430 1061 : ClearStatement();
431 1061 : iNextShapeId = 0;
432 1061 : }
433 :
434 : /************************************************************************/
435 : /* GetNextFeature() */
436 : /************************************************************************/
437 :
438 2672 : OGRFeature *OGRSQLiteLayer::GetNextFeature()
439 :
440 : {
441 216 : for( ; TRUE; )
442 : {
443 : OGRFeature *poFeature;
444 :
445 2672 : poFeature = GetNextRawFeature();
446 2672 : if( poFeature == NULL )
447 220 : return NULL;
448 :
449 2452 : if( (m_poFilterGeom == NULL
450 : || FilterGeometry( poFeature->GetGeometryRef() ) )
451 : && (m_poAttrQuery == NULL
452 : || m_poAttrQuery->Evaluate( poFeature )) )
453 2236 : return poFeature;
454 :
455 216 : delete poFeature;
456 : }
457 : }
458 :
459 : /************************************************************************/
460 : /* GetNextRawFeature() */
461 : /************************************************************************/
462 :
463 2713 : OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
464 :
465 : {
466 2713 : if( hStmt == NULL )
467 : {
468 427 : ResetStatement();
469 427 : if (hStmt == NULL)
470 2 : return NULL;
471 : }
472 :
473 : /* -------------------------------------------------------------------- */
474 : /* Fetch a record (unless otherwise instructed) */
475 : /* -------------------------------------------------------------------- */
476 2711 : if( bDoStep )
477 : {
478 : int rc;
479 :
480 2397 : rc = sqlite3_step( hStmt );
481 2397 : if( rc != SQLITE_ROW )
482 : {
483 234 : if ( rc != SQLITE_DONE )
484 : {
485 0 : sqlite3_reset(hStmt);
486 : CPLError( CE_Failure, CPLE_AppDefined,
487 : "In GetNextRawFeature(): sqlite3_step() : %s",
488 0 : sqlite3_errmsg(poDS->GetDB()) );
489 : }
490 :
491 234 : ClearStatement();
492 :
493 234 : return NULL;
494 : }
495 : }
496 : else
497 314 : bDoStep = TRUE;
498 :
499 : /* -------------------------------------------------------------------- */
500 : /* Create a feature from the current result. */
501 : /* -------------------------------------------------------------------- */
502 : int iField;
503 2477 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
504 :
505 : /* -------------------------------------------------------------------- */
506 : /* Set FID if we have a column to set it from. */
507 : /* -------------------------------------------------------------------- */
508 2477 : if( iFIDCol >= 0 )
509 1171 : poFeature->SetFID( sqlite3_column_int64( hStmt, iFIDCol ) );
510 : else
511 1306 : poFeature->SetFID( iNextShapeId );
512 :
513 2477 : iNextShapeId++;
514 :
515 2477 : m_nFeaturesRead++;
516 :
517 : /* -------------------------------------------------------------------- */
518 : /* Process Geometry if we have a column. */
519 : /* -------------------------------------------------------------------- */
520 2477 : if( iGeomCol >= 0 && !poFeatureDefn->IsGeometryIgnored() )
521 : {
522 2029 : OGRGeometry *poGeometry = NULL;
523 2029 : if ( eGeomFormat == OSGF_WKT )
524 : {
525 10 : char *pszWKTCopy, *pszWKT = NULL;
526 :
527 10 : pszWKT = (char *) sqlite3_column_text( hStmt, iGeomCol );
528 10 : pszWKTCopy = pszWKT;
529 10 : if( OGRGeometryFactory::createFromWkt(
530 : &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
531 10 : poFeature->SetGeometryDirectly( poGeometry );
532 : }
533 2019 : else if ( eGeomFormat == OSGF_WKB )
534 : {
535 915 : const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
536 :
537 : /* Try as spatialite first since createFromWkb() can sometimes */
538 : /* interpret spatialite blobs as WKB for certain SRID values */
539 915 : if (!bTriedAsSpatiaLite)
540 : {
541 : /* If the layer is the result of a sql select, we cannot be sure if it is */
542 : /* WKB or SpatialLite format */
543 70 : if( ImportSpatiaLiteGeometry(
544 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
545 : &poGeometry ) == OGRERR_NONE )
546 : {
547 0 : poFeature->SetGeometryDirectly( poGeometry );
548 0 : eGeomFormat = OSGF_SpatiaLite;
549 : }
550 70 : bTriedAsSpatiaLite = TRUE;
551 : }
552 :
553 915 : if( eGeomFormat == OSGF_WKB && OGRGeometryFactory::createFromWkb(
554 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
555 : NULL, &poGeometry, nBytes ) == OGRERR_NONE )
556 : {
557 774 : poFeature->SetGeometryDirectly( poGeometry );
558 : }
559 : }
560 1104 : else if ( eGeomFormat == OSGF_FGF )
561 : {
562 22 : const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
563 :
564 22 : if( OGRGeometryFactory::createFromFgf(
565 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
566 : NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
567 16 : poFeature->SetGeometryDirectly( poGeometry );
568 : }
569 1082 : else if ( eGeomFormat == OSGF_SpatiaLite )
570 : {
571 1082 : const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
572 :
573 1082 : if( ImportSpatiaLiteGeometry(
574 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
575 : &poGeometry ) == OGRERR_NONE )
576 1079 : poFeature->SetGeometryDirectly( poGeometry );
577 : }
578 :
579 2029 : if (poGeometry != NULL && poSRS != NULL)
580 879 : poGeometry->assignSpatialReference(poSRS);
581 : }
582 :
583 : /* -------------------------------------------------------------------- */
584 : /* set the fields. */
585 : /* -------------------------------------------------------------------- */
586 9114 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
587 : {
588 6637 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
589 6637 : if ( poFieldDefn->IsIgnored() )
590 104 : continue;
591 :
592 6533 : int iRawField = panFieldOrdinals[iField] - 1;
593 :
594 6533 : if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
595 978 : continue;
596 :
597 5555 : switch( poFieldDefn->GetType() )
598 : {
599 : case OFTInteger:
600 : poFeature->SetField( iField,
601 522 : sqlite3_column_int( hStmt, iRawField ) );
602 522 : break;
603 :
604 : case OFTReal:
605 : poFeature->SetField( iField,
606 2694 : sqlite3_column_double( hStmt, iRawField ) );
607 2694 : break;
608 :
609 : case OFTBinary:
610 : {
611 169 : const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
612 :
613 : poFeature->SetField( iField, nBytes,
614 169 : (GByte*)sqlite3_column_blob( hStmt, iRawField ) );
615 : }
616 169 : break;
617 :
618 : case OFTString:
619 : poFeature->SetField( iField,
620 : (const char *)
621 1888 : sqlite3_column_text( hStmt, iRawField ) );
622 1888 : break;
623 :
624 : case OFTDate:
625 : case OFTTime:
626 : case OFTDateTime:
627 : {
628 282 : if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_TEXT )
629 : {
630 : const char* pszValue = (const char *)
631 282 : sqlite3_column_text( hStmt, iRawField );
632 282 : OGRSQLITEStringToDateTimeField( poFeature, iField, pszValue );
633 : }
634 : break;
635 : }
636 :
637 : default:
638 : break;
639 : }
640 : }
641 :
642 2477 : return poFeature;
643 : }
644 :
645 : /************************************************************************/
646 : /* GetFeature() */
647 : /************************************************************************/
648 :
649 12 : OGRFeature *OGRSQLiteLayer::GetFeature( long nFeatureId )
650 :
651 : {
652 12 : return OGRLayer::GetFeature( nFeatureId );
653 : }
654 :
655 :
656 : /************************************************************************/
657 : /* createFromSpatialiteInternal() */
658 : /************************************************************************/
659 :
660 : /* See http://www.gaia-gis.it/spatialite/spatialite-manual-2.3.0.html#t3.3 */
661 : /* for the specification of the spatialite BLOB geometry format */
662 : /* Derived from WKB, but unfortunately it is not practical to reuse existing */
663 : /* WKB encoding/decoding code */
664 :
665 : #ifdef CPL_LSB
666 : #define NEED_SWAP_SPATIALITE() (eByteOrder != wkbNDR)
667 : #else
668 : #define NEED_SWAP_SPATIALITE() (eByteOrder == wkbNDR)
669 : #endif
670 :
671 :
672 1263 : OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
673 : OGRGeometry **ppoReturn,
674 : int nBytes,
675 : OGRwkbByteOrder eByteOrder,
676 : int* pnBytesConsumed,
677 : int nRecLevel)
678 : {
679 1263 : OGRErr eErr = OGRERR_NONE;
680 1263 : OGRGeometry *poGeom = NULL;
681 : GInt32 nGType;
682 : GInt32 compressedSize;
683 :
684 1263 : *ppoReturn = NULL;
685 :
686 : /* Arbitrary value, but certainly large enough for reasonable usages ! */
687 1263 : if( nRecLevel == 32 )
688 : {
689 : CPLError( CE_Failure, CPLE_AppDefined,
690 : "Too many recursiong level (%d) while parsing Spatialite geometry.",
691 0 : nRecLevel );
692 0 : return OGRERR_CORRUPT_DATA;
693 : }
694 :
695 1263 : if (nBytes < 4)
696 0 : return OGRERR_NOT_ENOUGH_DATA;
697 :
698 : /* -------------------------------------------------------------------- */
699 : /* Decode the geometry type. */
700 : /* -------------------------------------------------------------------- */
701 1263 : memcpy( &nGType, pabyData, 4 );
702 1263 : if (NEED_SWAP_SPATIALITE())
703 0 : CPL_SWAP32PTR( &nGType );
704 :
705 1263 : if( ( nGType >= OGRSplitePointXY &&
706 : nGType <= OGRSpliteGeometryCollectionXY ) || // XY types
707 : ( nGType >= OGRSplitePointXYZ &&
708 : nGType <= OGRSpliteGeometryCollectionXYZ ) || // XYZ types
709 : ( nGType >= OGRSplitePointXYM &&
710 : nGType <= OGRSpliteGeometryCollectionXYM ) || // XYM types
711 : ( nGType >= OGRSplitePointXYZM &&
712 : nGType <= OGRSpliteGeometryCollectionXYZM ) || // XYZM types
713 : ( nGType >= OGRSpliteComprLineStringXY &&
714 : nGType <= OGRSpliteComprGeometryCollectionXY ) || // XY compressed
715 : ( nGType >= OGRSpliteComprLineStringXYZ &&
716 : nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
717 : ( nGType >= OGRSpliteComprLineStringXYM &&
718 : nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
719 : ( nGType >= OGRSpliteComprLineStringXYZM &&
720 : nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
721 : ;
722 : else
723 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
724 :
725 : /* -------------------------------------------------------------------- */
726 : /* Point [XY] */
727 : /* -------------------------------------------------------------------- */
728 1263 : if( nGType == OGRSplitePointXY )
729 : {
730 : double adfTuple[2];
731 :
732 410 : if( nBytes < 4 + 2 * 8 )
733 0 : return OGRERR_NOT_ENOUGH_DATA;
734 :
735 410 : memcpy( adfTuple, pabyData + 4, 2*8 );
736 410 : if (NEED_SWAP_SPATIALITE())
737 : {
738 0 : CPL_SWAP64PTR( adfTuple );
739 0 : CPL_SWAP64PTR( adfTuple + 1 );
740 : }
741 :
742 410 : poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
743 :
744 410 : if( pnBytesConsumed )
745 14 : *pnBytesConsumed = 4 + 2 * 8;
746 : }
747 : /* -------------------------------------------------------------------- */
748 : /* Point [XYZ] */
749 : /* -------------------------------------------------------------------- */
750 853 : else if( nGType == OGRSplitePointXYZ )
751 : {
752 : double adfTuple[3];
753 :
754 10 : if( nBytes < 4 + 3 * 8 )
755 0 : return OGRERR_NOT_ENOUGH_DATA;
756 :
757 10 : memcpy( adfTuple, pabyData + 4, 3*8 );
758 10 : if (NEED_SWAP_SPATIALITE())
759 : {
760 0 : CPL_SWAP64PTR( adfTuple );
761 0 : CPL_SWAP64PTR( adfTuple + 1 );
762 0 : CPL_SWAP64PTR( adfTuple + 2 );
763 : }
764 :
765 10 : poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
766 :
767 10 : if( pnBytesConsumed )
768 8 : *pnBytesConsumed = 4 + 3 * 8;
769 : }
770 :
771 : /* -------------------------------------------------------------------- */
772 : /* Point [XYM] */
773 : /* -------------------------------------------------------------------- */
774 843 : else if( nGType == OGRSplitePointXYM )
775 : {
776 : double adfTuple[3];
777 :
778 0 : if( nBytes < 4 + 3 * 8 )
779 0 : return OGRERR_NOT_ENOUGH_DATA;
780 :
781 0 : memcpy( adfTuple, pabyData + 4, 3*8 );
782 0 : if (NEED_SWAP_SPATIALITE())
783 : {
784 0 : CPL_SWAP64PTR( adfTuple );
785 0 : CPL_SWAP64PTR( adfTuple + 1 );
786 0 : CPL_SWAP64PTR( adfTuple + 2 );
787 : }
788 :
789 0 : poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
790 :
791 0 : if( pnBytesConsumed )
792 0 : *pnBytesConsumed = 4 + 3 * 8;
793 : }
794 :
795 : /* -------------------------------------------------------------------- */
796 : /* Point [XYZM] */
797 : /* -------------------------------------------------------------------- */
798 843 : else if( nGType == OGRSplitePointXYZM )
799 : {
800 : double adfTuple[4];
801 :
802 0 : if( nBytes < 4 + 4 * 8 )
803 0 : return OGRERR_NOT_ENOUGH_DATA;
804 :
805 0 : memcpy( adfTuple, pabyData + 4, 4*8 );
806 0 : if (NEED_SWAP_SPATIALITE())
807 : {
808 0 : CPL_SWAP64PTR( adfTuple );
809 0 : CPL_SWAP64PTR( adfTuple + 1 );
810 0 : CPL_SWAP64PTR( adfTuple + 2 );
811 0 : CPL_SWAP64PTR( adfTuple + 3 );
812 : }
813 :
814 0 : poGeom = new OGRPoint( adfTuple[0], adfTuple[1], adfTuple[2] );
815 :
816 0 : if( pnBytesConsumed )
817 0 : *pnBytesConsumed = 4 + 4 * 8;
818 : }
819 :
820 : /* -------------------------------------------------------------------- */
821 : /* LineString [XY] */
822 : /* -------------------------------------------------------------------- */
823 843 : else if( nGType == OGRSpliteLineStringXY )
824 : {
825 : double adfTuple[2];
826 : GInt32 nPointCount;
827 : int iPoint;
828 : OGRLineString *poLS;
829 :
830 23 : if( nBytes < 8 )
831 0 : return OGRERR_NOT_ENOUGH_DATA;
832 :
833 23 : memcpy( &nPointCount, pabyData + 4, 4 );
834 23 : if (NEED_SWAP_SPATIALITE())
835 0 : CPL_SWAP32PTR( &nPointCount );
836 :
837 23 : if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
838 0 : return OGRERR_CORRUPT_DATA;
839 :
840 23 : if (nBytes - 8 < 2 * 8 * nPointCount )
841 0 : return OGRERR_NOT_ENOUGH_DATA;
842 :
843 23 : poGeom = poLS = new OGRLineString();
844 23 : poLS->setNumPoints( nPointCount );
845 :
846 60 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
847 : {
848 37 : memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
849 37 : if (NEED_SWAP_SPATIALITE())
850 : {
851 0 : CPL_SWAP64PTR( adfTuple );
852 0 : CPL_SWAP64PTR( adfTuple + 1 );
853 : }
854 :
855 37 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
856 : }
857 :
858 23 : if( pnBytesConsumed )
859 9 : *pnBytesConsumed = 8 + 2 * 8 * nPointCount;
860 : }
861 :
862 : /* -------------------------------------------------------------------- */
863 : /* LineString [XYZ] */
864 : /* -------------------------------------------------------------------- */
865 820 : else if( nGType == OGRSpliteLineStringXYZ )
866 : {
867 : double adfTuple[3];
868 : GInt32 nPointCount;
869 : int iPoint;
870 : OGRLineString *poLS;
871 :
872 7 : if( nBytes < 8 )
873 0 : return OGRERR_NOT_ENOUGH_DATA;
874 :
875 7 : memcpy( &nPointCount, pabyData + 4, 4 );
876 7 : if (NEED_SWAP_SPATIALITE())
877 0 : CPL_SWAP32PTR( &nPointCount );
878 :
879 7 : if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
880 0 : return OGRERR_CORRUPT_DATA;
881 :
882 7 : if (nBytes - 8 < 3 * 8 * nPointCount )
883 0 : return OGRERR_NOT_ENOUGH_DATA;
884 :
885 7 : poGeom = poLS = new OGRLineString();
886 7 : poLS->setNumPoints( nPointCount );
887 :
888 22 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
889 : {
890 15 : memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
891 15 : if (NEED_SWAP_SPATIALITE())
892 : {
893 0 : CPL_SWAP64PTR( adfTuple );
894 0 : CPL_SWAP64PTR( adfTuple + 1 );
895 0 : CPL_SWAP64PTR( adfTuple + 2 );
896 : }
897 :
898 15 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
899 : }
900 :
901 7 : if( pnBytesConsumed )
902 5 : *pnBytesConsumed = 8 + 3 * 8 * nPointCount;
903 : }
904 :
905 : /* -------------------------------------------------------------------- */
906 : /* LineString [XYM] */
907 : /* -------------------------------------------------------------------- */
908 813 : else if( nGType == OGRSpliteLineStringXYM )
909 : {
910 : double adfTuple[3];
911 : GInt32 nPointCount;
912 : int iPoint;
913 : OGRLineString *poLS;
914 :
915 0 : if( nBytes < 8 )
916 0 : return OGRERR_NOT_ENOUGH_DATA;
917 :
918 0 : memcpy( &nPointCount, pabyData + 4, 4 );
919 0 : if (NEED_SWAP_SPATIALITE())
920 0 : CPL_SWAP32PTR( &nPointCount );
921 :
922 0 : if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
923 0 : return OGRERR_CORRUPT_DATA;
924 :
925 0 : if (nBytes - 8 < 3 * 8 * nPointCount )
926 0 : return OGRERR_NOT_ENOUGH_DATA;
927 :
928 0 : poGeom = poLS = new OGRLineString();
929 0 : poLS->setNumPoints( nPointCount );
930 :
931 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
932 : {
933 0 : memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
934 0 : if (NEED_SWAP_SPATIALITE())
935 : {
936 0 : CPL_SWAP64PTR( adfTuple );
937 0 : CPL_SWAP64PTR( adfTuple + 1 );
938 0 : CPL_SWAP64PTR( adfTuple + 2 );
939 : }
940 :
941 0 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
942 : }
943 :
944 0 : if( pnBytesConsumed )
945 0 : *pnBytesConsumed = 8 + 3 * 8 * nPointCount;
946 : }
947 :
948 : /* -------------------------------------------------------------------- */
949 : /* LineString [XYZM] */
950 : /* -------------------------------------------------------------------- */
951 813 : else if( nGType == OGRSpliteLineStringXYZM )
952 : {
953 : double adfTuple[4];
954 : GInt32 nPointCount;
955 : int iPoint;
956 : OGRLineString *poLS;
957 :
958 0 : if( nBytes < 8 )
959 0 : return OGRERR_NOT_ENOUGH_DATA;
960 :
961 0 : memcpy( &nPointCount, pabyData + 4, 4 );
962 0 : if (NEED_SWAP_SPATIALITE())
963 0 : CPL_SWAP32PTR( &nPointCount );
964 :
965 0 : if( nPointCount < 0 || nPointCount > INT_MAX / (4 * 8))
966 0 : return OGRERR_CORRUPT_DATA;
967 :
968 0 : if (nBytes - 8 < 4 * 8 * nPointCount )
969 0 : return OGRERR_NOT_ENOUGH_DATA;
970 :
971 0 : poGeom = poLS = new OGRLineString();
972 0 : poLS->setNumPoints( nPointCount );
973 :
974 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
975 : {
976 0 : memcpy( adfTuple, pabyData + 8 + 4*8*iPoint, 4*8 );
977 0 : if (NEED_SWAP_SPATIALITE())
978 : {
979 0 : CPL_SWAP64PTR( adfTuple );
980 0 : CPL_SWAP64PTR( adfTuple + 1 );
981 0 : CPL_SWAP64PTR( adfTuple + 2 );
982 0 : CPL_SWAP64PTR( adfTuple + 3 );
983 : }
984 :
985 0 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
986 : }
987 :
988 0 : if( pnBytesConsumed )
989 0 : *pnBytesConsumed = 8 + 4 * 8 * nPointCount;
990 : }
991 :
992 : /* -------------------------------------------------------------------- */
993 : /* LineString [XY] Compressed */
994 : /* -------------------------------------------------------------------- */
995 813 : else if( nGType == OGRSpliteComprLineStringXY )
996 : {
997 : double adfTuple[2];
998 : double adfTupleBase[2];
999 : float asfTuple[2];
1000 : GInt32 nPointCount;
1001 : int iPoint;
1002 : OGRLineString *poLS;
1003 : int nNextByte;
1004 :
1005 5 : if( nBytes < 8 )
1006 0 : return OGRERR_NOT_ENOUGH_DATA;
1007 :
1008 5 : memcpy( &nPointCount, pabyData + 4, 4 );
1009 5 : if (NEED_SWAP_SPATIALITE())
1010 0 : CPL_SWAP32PTR( &nPointCount );
1011 :
1012 5 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
1013 0 : return OGRERR_CORRUPT_DATA;
1014 :
1015 5 : compressedSize = 16 * 2; // first and last Points
1016 5 : compressedSize += 8 * (nPointCount - 2); // intermediate Points
1017 :
1018 5 : if (nBytes - 8 < compressedSize )
1019 0 : return OGRERR_NOT_ENOUGH_DATA;
1020 :
1021 5 : poGeom = poLS = new OGRLineString();
1022 5 : poLS->setNumPoints( nPointCount );
1023 :
1024 5 : nNextByte = 8;
1025 5 : adfTupleBase[0] = 0.0;
1026 5 : adfTupleBase[1] = 0.0;
1027 :
1028 16 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1029 : {
1030 21 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1031 : {
1032 : // first and last Points are uncompressed
1033 10 : memcpy( adfTuple, pabyData + nNextByte, 2*8 );
1034 10 : nNextByte += 2 * 8;
1035 :
1036 10 : if (NEED_SWAP_SPATIALITE())
1037 : {
1038 0 : CPL_SWAP64PTR( adfTuple );
1039 0 : CPL_SWAP64PTR( adfTuple + 1 );
1040 : }
1041 : }
1042 : else
1043 : {
1044 : // any other intermediate Point is compressed
1045 1 : memcpy( asfTuple, pabyData + nNextByte, 2*4 );
1046 1 : nNextByte += 2 * 4;
1047 :
1048 1 : if (NEED_SWAP_SPATIALITE())
1049 : {
1050 0 : CPL_SWAP32PTR( asfTuple );
1051 0 : CPL_SWAP32PTR( asfTuple + 1 );
1052 : }
1053 1 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1054 1 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1055 : }
1056 :
1057 11 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
1058 11 : adfTupleBase[0] = adfTuple[0];
1059 11 : adfTupleBase[1] = adfTuple[1];
1060 : }
1061 :
1062 5 : if( pnBytesConsumed )
1063 3 : *pnBytesConsumed = nNextByte;
1064 : }
1065 :
1066 : /* -------------------------------------------------------------------- */
1067 : /* LineString [XYZ] Compressed */
1068 : /* -------------------------------------------------------------------- */
1069 808 : else if( nGType == OGRSpliteComprLineStringXYZ )
1070 : {
1071 : double adfTuple[3];
1072 : double adfTupleBase[3];
1073 : float asfTuple[3];
1074 : GInt32 nPointCount;
1075 : int iPoint;
1076 : OGRLineString *poLS;
1077 : int nNextByte;
1078 :
1079 5 : if( nBytes < 8 )
1080 0 : return OGRERR_NOT_ENOUGH_DATA;
1081 :
1082 5 : memcpy( &nPointCount, pabyData + 4, 4 );
1083 5 : if (NEED_SWAP_SPATIALITE())
1084 0 : CPL_SWAP32PTR( &nPointCount );
1085 :
1086 5 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 12)
1087 0 : return OGRERR_CORRUPT_DATA;
1088 :
1089 5 : compressedSize = 24 * 2; // first and last Points
1090 5 : compressedSize += 12 * (nPointCount - 2); // intermediate Points
1091 :
1092 5 : if (nBytes - 8 < compressedSize )
1093 0 : return OGRERR_NOT_ENOUGH_DATA;
1094 :
1095 5 : poGeom = poLS = new OGRLineString();
1096 5 : poLS->setNumPoints( nPointCount );
1097 :
1098 5 : nNextByte = 8;
1099 5 : adfTupleBase[0] = 0.0;
1100 5 : adfTupleBase[1] = 0.0;
1101 5 : adfTupleBase[2] = 0.0;
1102 :
1103 16 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1104 : {
1105 21 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1106 : {
1107 : // first and last Points are uncompressed
1108 10 : memcpy( adfTuple, pabyData + nNextByte, 3*8 );
1109 10 : nNextByte += 3 * 8;
1110 :
1111 10 : if (NEED_SWAP_SPATIALITE())
1112 : {
1113 0 : CPL_SWAP64PTR( adfTuple );
1114 0 : CPL_SWAP64PTR( adfTuple + 1 );
1115 0 : CPL_SWAP64PTR( adfTuple + 2 );
1116 : }
1117 : }
1118 : else
1119 : {
1120 : // any other intermediate Point is compressed
1121 1 : memcpy( asfTuple, pabyData + nNextByte, 3*4 );
1122 1 : nNextByte += 3 * 4;
1123 :
1124 1 : if (NEED_SWAP_SPATIALITE())
1125 : {
1126 0 : CPL_SWAP32PTR( asfTuple );
1127 0 : CPL_SWAP32PTR( asfTuple + 1 );
1128 0 : CPL_SWAP32PTR( asfTuple + 2 );
1129 : }
1130 1 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1131 1 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1132 1 : adfTuple[2] = asfTuple[2] + adfTupleBase[2];
1133 : }
1134 :
1135 11 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
1136 11 : adfTupleBase[0] = adfTuple[0];
1137 11 : adfTupleBase[1] = adfTuple[1];
1138 11 : adfTupleBase[2] = adfTuple[2];
1139 : }
1140 :
1141 5 : if( pnBytesConsumed )
1142 3 : *pnBytesConsumed = nNextByte;
1143 : }
1144 :
1145 : /* -------------------------------------------------------------------- */
1146 : /* LineString [XYM] Compressed */
1147 : /* -------------------------------------------------------------------- */
1148 803 : else if( nGType == OGRSpliteComprLineStringXYM )
1149 : {
1150 : double adfTuple[2];
1151 : double adfTupleBase[2];
1152 : float asfTuple[2];
1153 : GInt32 nPointCount;
1154 : int iPoint;
1155 : OGRLineString *poLS;
1156 : int nNextByte;
1157 :
1158 0 : if( nBytes < 8 )
1159 0 : return OGRERR_NOT_ENOUGH_DATA;
1160 :
1161 0 : memcpy( &nPointCount, pabyData + 4, 4 );
1162 0 : if (NEED_SWAP_SPATIALITE())
1163 0 : CPL_SWAP32PTR( &nPointCount );
1164 :
1165 0 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
1166 0 : return OGRERR_CORRUPT_DATA;
1167 :
1168 0 : compressedSize = 24 * 2; // first and last Points
1169 0 : compressedSize += 16 * (nPointCount - 2); // intermediate Points
1170 :
1171 0 : if (nBytes - 8 < compressedSize )
1172 0 : return OGRERR_NOT_ENOUGH_DATA;
1173 :
1174 0 : poGeom = poLS = new OGRLineString();
1175 0 : poLS->setNumPoints( nPointCount );
1176 :
1177 0 : nNextByte = 8;
1178 0 : adfTupleBase[0] = 0.0;
1179 0 : adfTupleBase[1] = 0.0;
1180 :
1181 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1182 : {
1183 0 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1184 : {
1185 : // first and last Points are uncompressed
1186 0 : memcpy( adfTuple, pabyData + nNextByte, 2*8 );
1187 0 : nNextByte += 3 * 8;
1188 :
1189 0 : if (NEED_SWAP_SPATIALITE())
1190 : {
1191 0 : CPL_SWAP64PTR( adfTuple );
1192 0 : CPL_SWAP64PTR( adfTuple + 1 );
1193 : }
1194 : }
1195 : else
1196 : {
1197 : // any other intermediate Point is compressed
1198 0 : memcpy( asfTuple, pabyData + nNextByte, 2*4 );
1199 0 : nNextByte += 2 * 4 + 8;
1200 :
1201 0 : if (NEED_SWAP_SPATIALITE())
1202 : {
1203 0 : CPL_SWAP32PTR( asfTuple );
1204 0 : CPL_SWAP32PTR( asfTuple + 1 );
1205 : }
1206 0 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1207 0 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1208 : }
1209 :
1210 0 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
1211 0 : adfTupleBase[0] = adfTuple[0];
1212 0 : adfTupleBase[1] = adfTuple[1];
1213 : }
1214 :
1215 0 : if( pnBytesConsumed )
1216 0 : *pnBytesConsumed = nNextByte;
1217 : }
1218 :
1219 : /* -------------------------------------------------------------------- */
1220 : /* LineString [XYZM] Compressed */
1221 : /* -------------------------------------------------------------------- */
1222 803 : else if( nGType == OGRSpliteComprLineStringXYZM )
1223 : {
1224 : double adfTuple[3];
1225 : double adfTupleBase[3];
1226 : float asfTuple[3];
1227 : GInt32 nPointCount;
1228 : int iPoint;
1229 : OGRLineString *poLS;
1230 : int nNextByte;
1231 :
1232 0 : if( nBytes < 8 )
1233 0 : return OGRERR_NOT_ENOUGH_DATA;
1234 :
1235 0 : memcpy( &nPointCount, pabyData + 4, 4 );
1236 0 : if (NEED_SWAP_SPATIALITE())
1237 0 : CPL_SWAP32PTR( &nPointCount );
1238 :
1239 0 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 32 * 2) / 20)
1240 0 : return OGRERR_CORRUPT_DATA;
1241 :
1242 0 : compressedSize = 32 * 2; // first and last Points
1243 : /* Note 20 is not an error : x,y,z are float and the m is a double */
1244 0 : compressedSize += 20 * (nPointCount - 2); // intermediate Points
1245 :
1246 0 : if (nBytes - 8 < compressedSize )
1247 0 : return OGRERR_NOT_ENOUGH_DATA;
1248 :
1249 0 : poGeom = poLS = new OGRLineString();
1250 0 : poLS->setNumPoints( nPointCount );
1251 :
1252 0 : nNextByte = 8;
1253 0 : adfTupleBase[0] = 0.0;
1254 0 : adfTupleBase[1] = 0.0;
1255 0 : adfTupleBase[2] = 0.0;
1256 :
1257 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1258 : {
1259 0 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1260 : {
1261 : // first and last Points are uncompressed
1262 0 : memcpy( adfTuple, pabyData + nNextByte, 3*8 );
1263 0 : nNextByte += 4 * 8;
1264 :
1265 0 : if (NEED_SWAP_SPATIALITE())
1266 : {
1267 0 : CPL_SWAP64PTR( adfTuple );
1268 0 : CPL_SWAP64PTR( adfTuple + 1 );
1269 0 : CPL_SWAP64PTR( adfTuple + 2 );
1270 : }
1271 : }
1272 : else
1273 : {
1274 : // any other intermediate Point is compressed
1275 0 : memcpy( asfTuple, pabyData + nNextByte, 3*4 );
1276 0 : nNextByte += 3 * 4 + 8;
1277 :
1278 0 : if (NEED_SWAP_SPATIALITE())
1279 : {
1280 0 : CPL_SWAP32PTR( asfTuple );
1281 0 : CPL_SWAP32PTR( asfTuple + 1 );
1282 0 : CPL_SWAP32PTR( asfTuple + 2 );
1283 : }
1284 0 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1285 0 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1286 0 : adfTuple[2] = asfTuple[2] + adfTupleBase[2];
1287 : }
1288 :
1289 0 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
1290 0 : adfTupleBase[0] = adfTuple[0];
1291 0 : adfTupleBase[1] = adfTuple[1];
1292 0 : adfTupleBase[2] = adfTuple[2];
1293 : }
1294 :
1295 0 : if( pnBytesConsumed )
1296 0 : *pnBytesConsumed = nNextByte;
1297 : }
1298 :
1299 : /* -------------------------------------------------------------------- */
1300 : /* Polygon [XY] */
1301 : /* -------------------------------------------------------------------- */
1302 803 : else if( nGType == OGRSplitePolygonXY )
1303 : {
1304 : double adfTuple[2];
1305 : GInt32 nPointCount;
1306 : GInt32 nRingCount;
1307 : int iPoint, iRing;
1308 : OGRLinearRing *poLR;
1309 : OGRPolygon *poPoly;
1310 : int nNextByte;
1311 :
1312 426 : if( nBytes < 8 )
1313 0 : return OGRERR_NOT_ENOUGH_DATA;
1314 :
1315 426 : memcpy( &nRingCount, pabyData + 4, 4 );
1316 426 : if (NEED_SWAP_SPATIALITE())
1317 0 : CPL_SWAP32PTR( &nRingCount );
1318 :
1319 426 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1320 0 : return OGRERR_CORRUPT_DATA;
1321 :
1322 : // Each ring has a minimum of 4 bytes
1323 426 : if (nBytes - 8 < nRingCount * 4)
1324 0 : return OGRERR_NOT_ENOUGH_DATA;
1325 :
1326 426 : nNextByte = 8;
1327 :
1328 426 : poGeom = poPoly = new OGRPolygon();
1329 :
1330 853 : for( iRing = 0; iRing < nRingCount; iRing++ )
1331 : {
1332 427 : if( nBytes - nNextByte < 4 )
1333 0 : return OGRERR_NOT_ENOUGH_DATA;
1334 :
1335 427 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1336 427 : if (NEED_SWAP_SPATIALITE())
1337 0 : CPL_SWAP32PTR( &nPointCount );
1338 :
1339 427 : if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
1340 0 : return OGRERR_CORRUPT_DATA;
1341 :
1342 427 : nNextByte += 4;
1343 :
1344 427 : if( nBytes - nNextByte < 2 * 8 * nPointCount )
1345 0 : return OGRERR_NOT_ENOUGH_DATA;
1346 :
1347 427 : poLR = new OGRLinearRing();
1348 427 : poLR->setNumPoints( nPointCount );
1349 :
1350 6487 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1351 : {
1352 6060 : memcpy( adfTuple, pabyData + nNextByte, 2*8 );
1353 6060 : nNextByte += 2 * 8;
1354 :
1355 6060 : if (NEED_SWAP_SPATIALITE())
1356 : {
1357 0 : CPL_SWAP64PTR( adfTuple );
1358 0 : CPL_SWAP64PTR( adfTuple + 1 );
1359 : }
1360 :
1361 6060 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
1362 : }
1363 :
1364 427 : poPoly->addRingDirectly( poLR );
1365 : }
1366 :
1367 426 : if( pnBytesConsumed )
1368 26 : *pnBytesConsumed = nNextByte;
1369 : }
1370 :
1371 : /* -------------------------------------------------------------------- */
1372 : /* Polygon [XYZ] */
1373 : /* -------------------------------------------------------------------- */
1374 377 : else if( nGType == OGRSplitePolygonXYZ )
1375 : {
1376 : double adfTuple[3];
1377 : GInt32 nPointCount;
1378 : GInt32 nRingCount;
1379 : int iPoint, iRing;
1380 : OGRLinearRing *poLR;
1381 : OGRPolygon *poPoly;
1382 : int nNextByte;
1383 :
1384 7 : if( nBytes < 8 )
1385 0 : return OGRERR_NOT_ENOUGH_DATA;
1386 :
1387 7 : memcpy( &nRingCount, pabyData + 4, 4 );
1388 7 : if (NEED_SWAP_SPATIALITE())
1389 0 : CPL_SWAP32PTR( &nRingCount );
1390 :
1391 7 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1392 0 : return OGRERR_CORRUPT_DATA;
1393 :
1394 : // Each ring has a minimum of 4 bytes
1395 7 : if (nBytes - 8 < nRingCount * 4)
1396 0 : return OGRERR_NOT_ENOUGH_DATA;
1397 :
1398 7 : nNextByte = 8;
1399 :
1400 7 : poGeom = poPoly = new OGRPolygon();
1401 :
1402 14 : for( iRing = 0; iRing < nRingCount; iRing++ )
1403 : {
1404 7 : if( nBytes - nNextByte < 4 )
1405 0 : return OGRERR_NOT_ENOUGH_DATA;
1406 :
1407 7 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1408 7 : if (NEED_SWAP_SPATIALITE())
1409 0 : CPL_SWAP32PTR( &nPointCount );
1410 :
1411 7 : if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
1412 0 : return OGRERR_CORRUPT_DATA;
1413 :
1414 7 : nNextByte += 4;
1415 :
1416 7 : if( nBytes - nNextByte < 3 * 8 * nPointCount )
1417 0 : return OGRERR_NOT_ENOUGH_DATA;
1418 :
1419 7 : poLR = new OGRLinearRing();
1420 7 : poLR->setNumPoints( nPointCount );
1421 :
1422 42 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1423 : {
1424 35 : memcpy( adfTuple, pabyData + nNextByte, 3*8 );
1425 35 : nNextByte += 3 * 8;
1426 :
1427 35 : if (NEED_SWAP_SPATIALITE())
1428 : {
1429 0 : CPL_SWAP64PTR( adfTuple );
1430 0 : CPL_SWAP64PTR( adfTuple + 1 );
1431 0 : CPL_SWAP64PTR( adfTuple + 2 );
1432 : }
1433 :
1434 35 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
1435 : }
1436 :
1437 7 : poPoly->addRingDirectly( poLR );
1438 : }
1439 :
1440 7 : if( pnBytesConsumed )
1441 5 : *pnBytesConsumed = nNextByte;
1442 : }
1443 :
1444 : /* -------------------------------------------------------------------- */
1445 : /* Polygon [XYM] */
1446 : /* -------------------------------------------------------------------- */
1447 370 : else if( nGType == OGRSplitePolygonXYM )
1448 : {
1449 : double adfTuple[3];
1450 : GInt32 nPointCount;
1451 : GInt32 nRingCount;
1452 : int iPoint, iRing;
1453 : OGRLinearRing *poLR;
1454 : OGRPolygon *poPoly;
1455 : int nNextByte;
1456 :
1457 0 : if( nBytes < 8 )
1458 0 : return OGRERR_NOT_ENOUGH_DATA;
1459 :
1460 0 : memcpy( &nRingCount, pabyData + 4, 4 );
1461 0 : if (NEED_SWAP_SPATIALITE())
1462 0 : CPL_SWAP32PTR( &nRingCount );
1463 :
1464 0 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1465 0 : return OGRERR_CORRUPT_DATA;
1466 :
1467 : // Each ring has a minimum of 4 bytes
1468 0 : if (nBytes - 8 < nRingCount * 4)
1469 0 : return OGRERR_NOT_ENOUGH_DATA;
1470 :
1471 0 : nNextByte = 8;
1472 :
1473 0 : poGeom = poPoly = new OGRPolygon();
1474 :
1475 0 : for( iRing = 0; iRing < nRingCount; iRing++ )
1476 : {
1477 0 : if( nBytes - nNextByte < 4 )
1478 0 : return OGRERR_NOT_ENOUGH_DATA;
1479 :
1480 0 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1481 0 : if (NEED_SWAP_SPATIALITE())
1482 0 : CPL_SWAP32PTR( &nPointCount );
1483 :
1484 0 : if( nPointCount < 0 || nPointCount > INT_MAX / (3 * 8))
1485 0 : return OGRERR_CORRUPT_DATA;
1486 :
1487 0 : nNextByte += 4;
1488 :
1489 0 : if( nBytes - nNextByte < 3 * 8 * nPointCount )
1490 0 : return OGRERR_NOT_ENOUGH_DATA;
1491 :
1492 0 : poLR = new OGRLinearRing();
1493 0 : poLR->setNumPoints( nPointCount );
1494 :
1495 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1496 : {
1497 0 : memcpy( adfTuple, pabyData + nNextByte, 3*8 );
1498 0 : nNextByte += 3 * 8;
1499 :
1500 0 : if (NEED_SWAP_SPATIALITE())
1501 : {
1502 0 : CPL_SWAP64PTR( adfTuple );
1503 0 : CPL_SWAP64PTR( adfTuple + 1 );
1504 0 : CPL_SWAP64PTR( adfTuple + 2 );
1505 : }
1506 :
1507 0 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
1508 : }
1509 :
1510 0 : poPoly->addRingDirectly( poLR );
1511 : }
1512 :
1513 0 : if( pnBytesConsumed )
1514 0 : *pnBytesConsumed = nNextByte;
1515 : }
1516 :
1517 : /* -------------------------------------------------------------------- */
1518 : /* Polygon [XYZM] */
1519 : /* -------------------------------------------------------------------- */
1520 370 : else if( nGType == OGRSplitePolygonXYZM )
1521 : {
1522 : double adfTuple[4];
1523 : GInt32 nPointCount;
1524 : GInt32 nRingCount;
1525 : int iPoint, iRing;
1526 : OGRLinearRing *poLR;
1527 : OGRPolygon *poPoly;
1528 : int nNextByte;
1529 :
1530 0 : if( nBytes < 8 )
1531 0 : return OGRERR_NOT_ENOUGH_DATA;
1532 :
1533 0 : memcpy( &nRingCount, pabyData + 4, 4 );
1534 0 : if (NEED_SWAP_SPATIALITE())
1535 0 : CPL_SWAP32PTR( &nRingCount );
1536 :
1537 0 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1538 0 : return OGRERR_CORRUPT_DATA;
1539 :
1540 : // Each ring has a minimum of 4 bytes
1541 0 : if (nBytes - 8 < nRingCount * 4)
1542 0 : return OGRERR_NOT_ENOUGH_DATA;
1543 :
1544 0 : nNextByte = 8;
1545 :
1546 0 : poGeom = poPoly = new OGRPolygon();
1547 :
1548 0 : for( iRing = 0; iRing < nRingCount; iRing++ )
1549 : {
1550 0 : if( nBytes - nNextByte < 4 )
1551 0 : return OGRERR_NOT_ENOUGH_DATA;
1552 :
1553 0 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1554 0 : if (NEED_SWAP_SPATIALITE())
1555 0 : CPL_SWAP32PTR( &nPointCount );
1556 :
1557 0 : if( nPointCount < 0 || nPointCount > INT_MAX / (4 * 8))
1558 0 : return OGRERR_CORRUPT_DATA;
1559 :
1560 0 : nNextByte += 4;
1561 :
1562 0 : if( nBytes - nNextByte < 4 * 8 * nPointCount )
1563 0 : return OGRERR_NOT_ENOUGH_DATA;
1564 :
1565 0 : poLR = new OGRLinearRing();
1566 0 : poLR->setNumPoints( nPointCount );
1567 :
1568 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1569 : {
1570 0 : memcpy( adfTuple, pabyData + nNextByte, 4*8 );
1571 0 : nNextByte += 4 * 8;
1572 :
1573 0 : if (NEED_SWAP_SPATIALITE())
1574 : {
1575 0 : CPL_SWAP64PTR( adfTuple );
1576 0 : CPL_SWAP64PTR( adfTuple + 1 );
1577 0 : CPL_SWAP64PTR( adfTuple + 2 );
1578 0 : CPL_SWAP64PTR( adfTuple + 3 );
1579 : }
1580 :
1581 0 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
1582 : }
1583 :
1584 0 : poPoly->addRingDirectly( poLR );
1585 : }
1586 :
1587 0 : if( pnBytesConsumed )
1588 0 : *pnBytesConsumed = nNextByte;
1589 : }
1590 :
1591 : /* -------------------------------------------------------------------- */
1592 : /* Polygon [XY] Compressed */
1593 : /* -------------------------------------------------------------------- */
1594 370 : else if( nGType == OGRSpliteComprPolygonXY )
1595 : {
1596 : double adfTuple[2];
1597 : double adfTupleBase[2];
1598 : float asfTuple[2];
1599 : GInt32 nPointCount;
1600 : GInt32 nRingCount;
1601 : int iPoint, iRing;
1602 : OGRLinearRing *poLR;
1603 : OGRPolygon *poPoly;
1604 : int nNextByte;
1605 :
1606 300 : if( nBytes < 8 )
1607 0 : return OGRERR_NOT_ENOUGH_DATA;
1608 :
1609 300 : memcpy( &nRingCount, pabyData + 4, 4 );
1610 300 : if (NEED_SWAP_SPATIALITE())
1611 0 : CPL_SWAP32PTR( &nRingCount );
1612 :
1613 300 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1614 0 : return OGRERR_CORRUPT_DATA;
1615 :
1616 : // Each ring has a minimum of 4 bytes
1617 300 : if (nBytes - 8 < nRingCount * 4)
1618 0 : return OGRERR_NOT_ENOUGH_DATA;
1619 :
1620 300 : nNextByte = 8;
1621 :
1622 300 : poGeom = poPoly = new OGRPolygon();
1623 :
1624 601 : for( iRing = 0; iRing < nRingCount; iRing++ )
1625 : {
1626 301 : if( nBytes - nNextByte < 4 )
1627 0 : return OGRERR_NOT_ENOUGH_DATA;
1628 :
1629 301 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1630 301 : if (NEED_SWAP_SPATIALITE())
1631 0 : CPL_SWAP32PTR( &nPointCount );
1632 :
1633 301 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 16 * 2) / 8)
1634 0 : return OGRERR_CORRUPT_DATA;
1635 :
1636 301 : compressedSize = 16 * 2; // first and last Points
1637 301 : compressedSize += 8 * (nPointCount - 2); // intermediate Points
1638 :
1639 301 : nNextByte += 4;
1640 301 : adfTupleBase[0] = 0.0;
1641 301 : adfTupleBase[1] = 0.0;
1642 :
1643 301 : if (nBytes - nNextByte < compressedSize )
1644 0 : return OGRERR_NOT_ENOUGH_DATA;
1645 :
1646 301 : poLR = new OGRLinearRing();
1647 301 : poLR->setNumPoints( nPointCount );
1648 :
1649 9110 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1650 : {
1651 9411 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1652 : {
1653 : // first and last Points are uncompressed
1654 602 : memcpy( adfTuple, pabyData + nNextByte, 2*8 );
1655 602 : nNextByte += 2 * 8;
1656 :
1657 602 : if (NEED_SWAP_SPATIALITE())
1658 : {
1659 0 : CPL_SWAP64PTR( adfTuple );
1660 0 : CPL_SWAP64PTR( adfTuple + 1 );
1661 : }
1662 : }
1663 : else
1664 : {
1665 : // any other intermediate Point is compressed
1666 8207 : memcpy( asfTuple, pabyData + nNextByte, 2*4 );
1667 8207 : nNextByte += 2 * 4;
1668 :
1669 8207 : if (NEED_SWAP_SPATIALITE())
1670 : {
1671 0 : CPL_SWAP32PTR( asfTuple );
1672 0 : CPL_SWAP32PTR( asfTuple + 1 );
1673 : }
1674 8207 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1675 8207 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1676 : }
1677 :
1678 8809 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
1679 8809 : adfTupleBase[0] = adfTuple[0];
1680 8809 : adfTupleBase[1] = adfTuple[1];
1681 : }
1682 :
1683 301 : poPoly->addRingDirectly( poLR );
1684 : }
1685 :
1686 300 : if( pnBytesConsumed )
1687 5 : *pnBytesConsumed = nNextByte;
1688 : }
1689 :
1690 : /* -------------------------------------------------------------------- */
1691 : /* Polygon [XYZ] Compressed */
1692 : /* -------------------------------------------------------------------- */
1693 70 : else if( nGType == OGRSpliteComprPolygonXYZ )
1694 : {
1695 : double adfTuple[3];
1696 : double adfTupleBase[3];
1697 : float asfTuple[3];
1698 : GInt32 nPointCount;
1699 : GInt32 nRingCount;
1700 : int iPoint, iRing;
1701 : OGRLinearRing *poLR;
1702 : OGRPolygon *poPoly;
1703 : int nNextByte;
1704 :
1705 5 : if( nBytes < 8 )
1706 0 : return OGRERR_NOT_ENOUGH_DATA;
1707 :
1708 5 : memcpy( &nRingCount, pabyData + 4, 4 );
1709 5 : if (NEED_SWAP_SPATIALITE())
1710 0 : CPL_SWAP32PTR( &nRingCount );
1711 :
1712 5 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1713 0 : return OGRERR_CORRUPT_DATA;
1714 :
1715 : // Each ring has a minimum of 4 bytes
1716 5 : if (nBytes - 8 < nRingCount * 4)
1717 0 : return OGRERR_NOT_ENOUGH_DATA;
1718 :
1719 5 : nNextByte = 8;
1720 :
1721 5 : poGeom = poPoly = new OGRPolygon();
1722 :
1723 10 : for( iRing = 0; iRing < nRingCount; iRing++ )
1724 : {
1725 5 : if( nBytes - nNextByte < 4 )
1726 0 : return OGRERR_NOT_ENOUGH_DATA;
1727 :
1728 5 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1729 5 : if (NEED_SWAP_SPATIALITE())
1730 0 : CPL_SWAP32PTR( &nPointCount );
1731 :
1732 5 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 12)
1733 0 : return OGRERR_CORRUPT_DATA;
1734 :
1735 5 : compressedSize = 24 * 2; // first and last Points
1736 5 : compressedSize += 12 * (nPointCount - 2); // intermediate Points
1737 :
1738 5 : nNextByte += 4;
1739 5 : adfTupleBase[0] = 0.0;
1740 5 : adfTupleBase[1] = 0.0;
1741 5 : adfTupleBase[2] = 0.0;
1742 :
1743 5 : if (nBytes - nNextByte < compressedSize )
1744 0 : return OGRERR_NOT_ENOUGH_DATA;
1745 :
1746 5 : poLR = new OGRLinearRing();
1747 5 : poLR->setNumPoints( nPointCount );
1748 :
1749 30 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1750 : {
1751 35 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1752 : {
1753 : // first and last Points are uncompressed
1754 10 : memcpy( adfTuple, pabyData + nNextByte, 3*8 );
1755 10 : nNextByte += 3 * 8;
1756 :
1757 10 : if (NEED_SWAP_SPATIALITE())
1758 : {
1759 0 : CPL_SWAP64PTR( adfTuple );
1760 0 : CPL_SWAP64PTR( adfTuple + 1 );
1761 0 : CPL_SWAP64PTR( adfTuple + 2 );
1762 : }
1763 : }
1764 : else
1765 : {
1766 : // any other intermediate Point is compressed
1767 15 : memcpy( asfTuple, pabyData + nNextByte, 3*4 );
1768 15 : nNextByte += 3 * 4;
1769 :
1770 15 : if (NEED_SWAP_SPATIALITE())
1771 : {
1772 0 : CPL_SWAP32PTR( asfTuple );
1773 0 : CPL_SWAP32PTR( asfTuple + 1 );
1774 0 : CPL_SWAP32PTR( asfTuple + 2 );
1775 : }
1776 15 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1777 15 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1778 15 : adfTuple[2] = asfTuple[2] + adfTupleBase[2];
1779 : }
1780 :
1781 25 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
1782 25 : adfTupleBase[0] = adfTuple[0];
1783 25 : adfTupleBase[1] = adfTuple[1];
1784 25 : adfTupleBase[2] = adfTuple[2];
1785 : }
1786 :
1787 5 : poPoly->addRingDirectly( poLR );
1788 : }
1789 :
1790 5 : if( pnBytesConsumed )
1791 3 : *pnBytesConsumed = nNextByte;
1792 : }
1793 :
1794 : /* -------------------------------------------------------------------- */
1795 : /* Polygon [XYM] Compressed */
1796 : /* -------------------------------------------------------------------- */
1797 65 : else if( nGType == OGRSpliteComprPolygonXYM )
1798 : {
1799 : double adfTuple[2];
1800 : double adfTupleBase[3];
1801 : float asfTuple[2];
1802 : GInt32 nPointCount;
1803 : GInt32 nRingCount;
1804 : int iPoint, iRing;
1805 : OGRLinearRing *poLR;
1806 : OGRPolygon *poPoly;
1807 : int nNextByte;
1808 :
1809 0 : if( nBytes < 8 )
1810 0 : return OGRERR_NOT_ENOUGH_DATA;
1811 :
1812 0 : memcpy( &nRingCount, pabyData + 4, 4 );
1813 0 : if (NEED_SWAP_SPATIALITE())
1814 0 : CPL_SWAP32PTR( &nRingCount );
1815 :
1816 0 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1817 0 : return OGRERR_CORRUPT_DATA;
1818 :
1819 : // Each ring has a minimum of 4 bytes
1820 0 : if (nBytes - 8 < nRingCount * 4)
1821 0 : return OGRERR_NOT_ENOUGH_DATA;
1822 :
1823 0 : nNextByte = 8;
1824 :
1825 0 : poGeom = poPoly = new OGRPolygon();
1826 :
1827 0 : for( iRing = 0; iRing < nRingCount; iRing++ )
1828 : {
1829 0 : if( nBytes - nNextByte < 4 )
1830 0 : return OGRERR_NOT_ENOUGH_DATA;
1831 :
1832 0 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1833 0 : if (NEED_SWAP_SPATIALITE())
1834 0 : CPL_SWAP32PTR( &nPointCount );
1835 :
1836 :
1837 0 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
1838 0 : return OGRERR_CORRUPT_DATA;
1839 :
1840 0 : compressedSize = 24 * 2; // first and last Points
1841 0 : compressedSize += 16 * (nPointCount - 2); // intermediate Points
1842 :
1843 0 : nNextByte += 4;
1844 0 : adfTupleBase[0] = 0.0;
1845 0 : adfTupleBase[1] = 0.0;
1846 :
1847 0 : if (nBytes - nNextByte < compressedSize )
1848 0 : return OGRERR_NOT_ENOUGH_DATA;
1849 :
1850 0 : poLR = new OGRLinearRing();
1851 0 : poLR->setNumPoints( nPointCount );
1852 :
1853 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1854 : {
1855 0 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1856 : {
1857 : // first and last Points are uncompressed
1858 0 : memcpy( adfTuple, pabyData + nNextByte, 2*8 );
1859 0 : nNextByte += 2 * 8;
1860 :
1861 0 : if (NEED_SWAP_SPATIALITE())
1862 : {
1863 0 : CPL_SWAP64PTR( adfTuple );
1864 0 : CPL_SWAP64PTR( adfTuple + 1 );
1865 : }
1866 : }
1867 : else
1868 : {
1869 : // any other intermediate Point is compressed
1870 0 : memcpy( asfTuple, pabyData + nNextByte, 2*4 );
1871 0 : nNextByte += 2 * 4 + 8;
1872 :
1873 0 : if (NEED_SWAP_SPATIALITE())
1874 : {
1875 0 : CPL_SWAP32PTR( asfTuple );
1876 0 : CPL_SWAP32PTR( asfTuple + 1 );
1877 : }
1878 0 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1879 0 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1880 : }
1881 :
1882 0 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
1883 0 : adfTupleBase[0] = adfTuple[0];
1884 0 : adfTupleBase[1] = adfTuple[1];
1885 : }
1886 :
1887 0 : poPoly->addRingDirectly( poLR );
1888 : }
1889 :
1890 0 : if( pnBytesConsumed )
1891 0 : *pnBytesConsumed = nNextByte;
1892 : }
1893 :
1894 : /* -------------------------------------------------------------------- */
1895 : /* Polygon [XYZM] Compressed */
1896 : /* -------------------------------------------------------------------- */
1897 65 : else if( nGType == OGRSpliteComprPolygonXYZM )
1898 : {
1899 : double adfTuple[3];
1900 : double adfTupleBase[3];
1901 : float asfTuple[3];
1902 : GInt32 nPointCount;
1903 : GInt32 nRingCount;
1904 : int iPoint, iRing;
1905 : OGRLinearRing *poLR;
1906 : OGRPolygon *poPoly;
1907 : int nNextByte;
1908 :
1909 0 : if( nBytes < 8 )
1910 0 : return OGRERR_NOT_ENOUGH_DATA;
1911 :
1912 0 : memcpy( &nRingCount, pabyData + 4, 4 );
1913 0 : if (NEED_SWAP_SPATIALITE())
1914 0 : CPL_SWAP32PTR( &nRingCount );
1915 :
1916 0 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
1917 0 : return OGRERR_CORRUPT_DATA;
1918 :
1919 : // Each ring has a minimum of 4 bytes
1920 0 : if (nBytes - 8 < nRingCount * 4)
1921 0 : return OGRERR_NOT_ENOUGH_DATA;
1922 :
1923 0 : nNextByte = 8;
1924 :
1925 0 : poGeom = poPoly = new OGRPolygon();
1926 :
1927 0 : for( iRing = 0; iRing < nRingCount; iRing++ )
1928 : {
1929 0 : if( nBytes - nNextByte < 4 )
1930 0 : return OGRERR_NOT_ENOUGH_DATA;
1931 :
1932 0 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
1933 0 : if (NEED_SWAP_SPATIALITE())
1934 0 : CPL_SWAP32PTR( &nPointCount );
1935 :
1936 0 : if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 32 * 2) / 20)
1937 0 : return OGRERR_CORRUPT_DATA;
1938 :
1939 0 : compressedSize = 32 * 2; // first and last Points
1940 : /* Note 20 is not an error : x,y,z are float and the m is a double */
1941 0 : compressedSize += 20 * (nPointCount - 2); // intermediate Points
1942 :
1943 0 : nNextByte += 4;
1944 0 : adfTupleBase[0] = 0.0;
1945 0 : adfTupleBase[1] = 0.0;
1946 0 : adfTupleBase[2] = 0.0;
1947 :
1948 0 : if (nBytes - nNextByte < compressedSize )
1949 0 : return OGRERR_NOT_ENOUGH_DATA;
1950 :
1951 0 : poLR = new OGRLinearRing();
1952 0 : poLR->setNumPoints( nPointCount );
1953 :
1954 0 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
1955 : {
1956 0 : if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
1957 : {
1958 : // first and last Points are uncompressed
1959 0 : memcpy( adfTuple, pabyData + nNextByte, 3*8 );
1960 0 : nNextByte += 4 * 8;
1961 :
1962 0 : if (NEED_SWAP_SPATIALITE())
1963 : {
1964 0 : CPL_SWAP64PTR( adfTuple );
1965 0 : CPL_SWAP64PTR( adfTuple + 1 );
1966 0 : CPL_SWAP64PTR( adfTuple + 2 );
1967 : }
1968 : }
1969 : else
1970 : {
1971 : // any other intermediate Point is compressed
1972 0 : memcpy( asfTuple, pabyData + nNextByte, 3*4 );
1973 0 : nNextByte += 3 * 4 + 8;
1974 :
1975 0 : if (NEED_SWAP_SPATIALITE())
1976 : {
1977 0 : CPL_SWAP32PTR( asfTuple );
1978 0 : CPL_SWAP32PTR( asfTuple + 1 );
1979 0 : CPL_SWAP32PTR( asfTuple + 2 );
1980 : }
1981 0 : adfTuple[0] = asfTuple[0] + adfTupleBase[0];
1982 0 : adfTuple[1] = asfTuple[1] + adfTupleBase[1];
1983 0 : adfTuple[2] = asfTuple[2] + adfTupleBase[2];
1984 : }
1985 :
1986 0 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
1987 0 : adfTupleBase[0] = adfTuple[0];
1988 0 : adfTupleBase[1] = adfTuple[1];
1989 0 : adfTupleBase[2] = adfTuple[2];
1990 : }
1991 :
1992 0 : poPoly->addRingDirectly( poLR );
1993 : }
1994 :
1995 0 : if( pnBytesConsumed )
1996 0 : *pnBytesConsumed = nNextByte;
1997 : }
1998 :
1999 : /* -------------------------------------------------------------------- */
2000 : /* GeometryCollections of various kinds. */
2001 : /* -------------------------------------------------------------------- */
2002 130 : else if( ( nGType >= OGRSpliteMultiPointXY &&
2003 : nGType <= OGRSpliteGeometryCollectionXY ) || // XY types
2004 : ( nGType >= OGRSpliteMultiPointXYZ &&
2005 : nGType <= OGRSpliteGeometryCollectionXYZ ) || // XYZ types
2006 : ( nGType >= OGRSpliteMultiPointXYM &&
2007 : nGType <= OGRSpliteGeometryCollectionXYM ) || // XYM types
2008 : ( nGType >= OGRSpliteMultiPointXYZM &&
2009 : nGType <= OGRSpliteGeometryCollectionXYZM ) || // XYZM types
2010 : ( nGType >= OGRSpliteComprMultiLineStringXY &&
2011 : nGType <= OGRSpliteComprGeometryCollectionXY ) || // XY compressed
2012 : ( nGType >= OGRSpliteComprMultiLineStringXYZ &&
2013 : nGType <= OGRSpliteComprGeometryCollectionXYZ ) || // XYZ compressed
2014 : ( nGType >= OGRSpliteComprMultiLineStringXYM &&
2015 : nGType <= OGRSpliteComprGeometryCollectionXYM ) || // XYM compressed
2016 : ( nGType >= OGRSpliteComprMultiLineStringXYZM &&
2017 : nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
2018 : {
2019 65 : OGRGeometryCollection *poGC = NULL;
2020 65 : GInt32 nGeomCount = 0;
2021 65 : int iGeom = 0;
2022 65 : int nBytesUsed = 0;
2023 :
2024 65 : switch ( nGType )
2025 : {
2026 : case OGRSpliteMultiPointXY:
2027 : case OGRSpliteMultiPointXYZ:
2028 : case OGRSpliteMultiPointXYM:
2029 : case OGRSpliteMultiPointXYZM:
2030 10 : poGC = new OGRMultiPoint();
2031 10 : break;
2032 : case OGRSpliteMultiLineStringXY:
2033 : case OGRSpliteMultiLineStringXYZ:
2034 : case OGRSpliteMultiLineStringXYM:
2035 : case OGRSpliteMultiLineStringXYZM:
2036 : case OGRSpliteComprMultiLineStringXY:
2037 : case OGRSpliteComprMultiLineStringXYZ:
2038 : case OGRSpliteComprMultiLineStringXYM:
2039 : case OGRSpliteComprMultiLineStringXYZM:
2040 10 : poGC = new OGRMultiLineString();
2041 10 : break;
2042 : case OGRSpliteMultiPolygonXY:
2043 : case OGRSpliteMultiPolygonXYZ:
2044 : case OGRSpliteMultiPolygonXYM:
2045 : case OGRSpliteMultiPolygonXYZM:
2046 : case OGRSpliteComprMultiPolygonXY:
2047 : case OGRSpliteComprMultiPolygonXYZ:
2048 : case OGRSpliteComprMultiPolygonXYM:
2049 : case OGRSpliteComprMultiPolygonXYZM:
2050 21 : poGC = new OGRMultiPolygon();
2051 21 : break;
2052 : case OGRSpliteGeometryCollectionXY:
2053 : case OGRSpliteGeometryCollectionXYZ:
2054 : case OGRSpliteGeometryCollectionXYM:
2055 : case OGRSpliteGeometryCollectionXYZM:
2056 : case OGRSpliteComprGeometryCollectionXY:
2057 : case OGRSpliteComprGeometryCollectionXYZ:
2058 : case OGRSpliteComprGeometryCollectionXYM:
2059 : case OGRSpliteComprGeometryCollectionXYZM:
2060 24 : poGC = new OGRGeometryCollection();
2061 : break;
2062 : }
2063 :
2064 65 : assert(NULL != poGC);
2065 :
2066 65 : if( nBytes < 8 )
2067 0 : return OGRERR_NOT_ENOUGH_DATA;
2068 :
2069 65 : memcpy( &nGeomCount, pabyData + 4, 4 );
2070 65 : if (NEED_SWAP_SPATIALITE())
2071 0 : CPL_SWAP32PTR( &nGeomCount );
2072 :
2073 65 : if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
2074 0 : return OGRERR_CORRUPT_DATA;
2075 :
2076 : // Each sub geometry takes at least 9 bytes
2077 65 : if (nBytes - 8 < nGeomCount * 9)
2078 0 : return OGRERR_NOT_ENOUGH_DATA;
2079 :
2080 65 : nBytesUsed = 8;
2081 :
2082 146 : for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
2083 : {
2084 : int nThisGeomSize;
2085 81 : OGRGeometry *poThisGeom = NULL;
2086 :
2087 81 : if (nBytes - nBytesUsed < 5)
2088 0 : return OGRERR_NOT_ENOUGH_DATA;
2089 :
2090 81 : if (pabyData[nBytesUsed] != 0x69)
2091 0 : return OGRERR_CORRUPT_DATA;
2092 :
2093 81 : nBytesUsed ++;
2094 :
2095 : eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
2096 : &poThisGeom, nBytes - nBytesUsed,
2097 81 : eByteOrder, &nThisGeomSize, nRecLevel + 1);
2098 81 : if( eErr != OGRERR_NONE )
2099 : {
2100 0 : delete poGC;
2101 0 : return eErr;
2102 : }
2103 :
2104 81 : nBytesUsed += nThisGeomSize;
2105 81 : eErr = poGC->addGeometryDirectly( poThisGeom );
2106 81 : if( eErr != OGRERR_NONE )
2107 : {
2108 0 : delete poGC;
2109 0 : return eErr;
2110 : }
2111 : }
2112 :
2113 65 : poGeom = poGC;
2114 65 : if( pnBytesConsumed )
2115 0 : *pnBytesConsumed = nBytesUsed;
2116 : }
2117 :
2118 : /* -------------------------------------------------------------------- */
2119 : /* Currently unsupported geometry. */
2120 : /* -------------------------------------------------------------------- */
2121 : else
2122 : {
2123 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
2124 : }
2125 :
2126 : /* -------------------------------------------------------------------- */
2127 : /* Assign spatial reference system. */
2128 : /* -------------------------------------------------------------------- */
2129 1263 : if( eErr == OGRERR_NONE )
2130 : {
2131 1263 : *ppoReturn = poGeom;
2132 : }
2133 : else
2134 : {
2135 0 : delete poGeom;
2136 : }
2137 :
2138 1263 : return eErr;
2139 : }
2140 :
2141 : /************************************************************************/
2142 : /* ImportSpatiaLiteGeometry() */
2143 : /************************************************************************/
2144 :
2145 1421 : OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
2146 : int nBytes,
2147 : OGRGeometry **ppoGeometry )
2148 :
2149 : {
2150 : OGRwkbByteOrder eByteOrder;
2151 :
2152 1421 : *ppoGeometry = NULL;
2153 :
2154 5079 : if( nBytes < 44
2155 1267 : || pabyData[0] != 0
2156 1209 : || pabyData[38] != 0x7C
2157 1182 : || pabyData[nBytes-1] != 0xFE )
2158 239 : return OGRERR_CORRUPT_DATA;
2159 :
2160 1182 : eByteOrder = (OGRwkbByteOrder) pabyData[1];
2161 :
2162 : return createFromSpatialiteInternal(pabyData + 39, ppoGeometry,
2163 1182 : nBytes - 39, eByteOrder, NULL, 0);
2164 : }
2165 :
2166 :
2167 : /************************************************************************/
2168 : /* CanBeCompressedSpatialiteGeometry() */
2169 : /************************************************************************/
2170 :
2171 93 : int OGRSQLiteLayer::CanBeCompressedSpatialiteGeometry(const OGRGeometry *poGeometry)
2172 : {
2173 93 : switch (wkbFlatten(poGeometry->getGeometryType()))
2174 : {
2175 : case wkbLineString:
2176 : case wkbLinearRing:
2177 : {
2178 40 : int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
2179 40 : return nPoints >= 2;
2180 : }
2181 :
2182 : case wkbPolygon:
2183 : {
2184 26 : OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
2185 26 : if (poPoly->getExteriorRing() != NULL)
2186 : {
2187 24 : if (!CanBeCompressedSpatialiteGeometry(poPoly->getExteriorRing()))
2188 0 : return FALSE;
2189 :
2190 24 : int nInteriorRingCount = poPoly->getNumInteriorRings();
2191 28 : for(int i=0;i<nInteriorRingCount;i++)
2192 : {
2193 4 : if (!CanBeCompressedSpatialiteGeometry(poPoly->getInteriorRing(i)))
2194 0 : return FALSE;
2195 : }
2196 : }
2197 26 : return TRUE;
2198 : }
2199 :
2200 : case wkbMultiPoint:
2201 : case wkbMultiLineString:
2202 : case wkbMultiPolygon:
2203 : case wkbGeometryCollection:
2204 : {
2205 19 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
2206 19 : int nParts = poGeomCollection->getNumGeometries();
2207 33 : for(int i=0;i<nParts;i++)
2208 : {
2209 20 : if (!CanBeCompressedSpatialiteGeometry(poGeomCollection->getGeometryRef(i)))
2210 6 : return FALSE;
2211 : }
2212 13 : return TRUE;
2213 : }
2214 :
2215 : default:
2216 8 : return FALSE;
2217 : }
2218 : }
2219 :
2220 : /************************************************************************/
2221 : /* ComputeSpatiaLiteGeometrySize() */
2222 : /************************************************************************/
2223 :
2224 546 : int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
2225 : int bHasM, int bSpatialite2D,
2226 : int bUseComprGeom)
2227 : {
2228 546 : switch (wkbFlatten(poGeometry->getGeometryType()))
2229 : {
2230 : case wkbPoint:
2231 148 : if ( bSpatialite2D == TRUE )
2232 4 : return 16;
2233 144 : else if (poGeometry->getCoordinateDimension() == 3)
2234 : {
2235 10 : if (bHasM == TRUE)
2236 0 : return 32;
2237 : else
2238 10 : return 24;
2239 : }
2240 : else
2241 : {
2242 134 : if (bHasM == TRUE)
2243 0 : return 24;
2244 : else
2245 134 : return 16;
2246 : }
2247 :
2248 : case wkbLineString:
2249 : case wkbLinearRing:
2250 : {
2251 192 : int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
2252 : int nDimension;
2253 192 : int nPointsDouble = nPoints;
2254 192 : int nPointsFloat = 0;
2255 192 : if ( bSpatialite2D == TRUE )
2256 : {
2257 12 : nDimension = 2;
2258 12 : bHasM = FALSE;
2259 : }
2260 : else
2261 : {
2262 180 : if ( bUseComprGeom && nPoints >= 2 )
2263 : {
2264 24 : nPointsDouble = 2;
2265 24 : nPointsFloat = nPoints - 2;
2266 : }
2267 180 : nDimension = poGeometry->getCoordinateDimension();
2268 : }
2269 192 : return 4 + nDimension * (8 * nPointsDouble + 4 * nPointsFloat) + ((bHasM) ? nPoints * 8 : 0);
2270 : }
2271 :
2272 : case wkbPolygon:
2273 : {
2274 150 : int nSize = 4;
2275 150 : OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
2276 150 : bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poGeometry);
2277 150 : if (poPoly->getExteriorRing() != NULL)
2278 : {
2279 : nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing(),
2280 146 : bHasM, bSpatialite2D, bUseComprGeom);
2281 :
2282 146 : int nInteriorRingCount = poPoly->getNumInteriorRings();
2283 152 : for(int i=0;i<nInteriorRingCount;i++)
2284 : nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i),
2285 6 : bHasM, bSpatialite2D, bUseComprGeom );
2286 : }
2287 150 : return nSize;
2288 : }
2289 :
2290 : case wkbMultiPoint:
2291 : case wkbMultiLineString:
2292 : case wkbMultiPolygon:
2293 : case wkbGeometryCollection:
2294 : {
2295 56 : int nSize = 4;
2296 56 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
2297 56 : int nParts = poGeomCollection->getNumGeometries();
2298 128 : for(int i=0;i<nParts;i++)
2299 : nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i),
2300 72 : bHasM, bSpatialite2D, bUseComprGeom );
2301 56 : return nSize;
2302 : }
2303 :
2304 : default:
2305 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
2306 0 : return 0;
2307 : }
2308 : }
2309 :
2310 : /************************************************************************/
2311 : /* GetSpatialiteGeometryCode() */
2312 : /************************************************************************/
2313 :
2314 394 : int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
2315 : int bHasM, int bSpatialite2D,
2316 : int bUseComprGeom,
2317 : int bAcceptMultiGeom)
2318 : {
2319 394 : OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
2320 394 : switch (eType)
2321 : {
2322 : case wkbPoint:
2323 148 : if ( bSpatialite2D == TRUE )
2324 4 : return OGRSplitePointXY;
2325 144 : else if (poGeometry->getCoordinateDimension() == 3)
2326 : {
2327 10 : if (bHasM == TRUE)
2328 0 : return OGRSplitePointXYZM;
2329 : else
2330 10 : return OGRSplitePointXYZ;
2331 : }
2332 : else
2333 : {
2334 134 : if (bHasM == TRUE)
2335 0 : return OGRSplitePointXYM;
2336 : else
2337 134 : return OGRSplitePointXY;
2338 : }
2339 : break;
2340 :
2341 : case wkbLineString:
2342 : case wkbLinearRing:
2343 40 : if ( bSpatialite2D == TRUE )
2344 4 : return OGRSpliteLineStringXY;
2345 36 : else if (poGeometry->getCoordinateDimension() == 3)
2346 : {
2347 12 : if (bHasM == TRUE)
2348 0 : return (bUseComprGeom) ? OGRSpliteComprLineStringXYZM : OGRSpliteLineStringXYZM;
2349 : else
2350 12 : return (bUseComprGeom) ? OGRSpliteComprLineStringXYZ : OGRSpliteLineStringXYZ;
2351 : }
2352 : else
2353 : {
2354 24 : if (bHasM == TRUE)
2355 0 : return (bUseComprGeom) ? OGRSpliteComprLineStringXYM : OGRSpliteLineStringXYM;
2356 : else
2357 24 : return (bUseComprGeom) ? OGRSpliteComprLineStringXY : OGRSpliteLineStringXY;
2358 : }
2359 : break;
2360 :
2361 : case wkbPolygon:
2362 150 : if ( bSpatialite2D == TRUE )
2363 8 : return OGRSplitePolygonXY;
2364 142 : else if (poGeometry->getCoordinateDimension() == 3)
2365 : {
2366 12 : if (bHasM == TRUE)
2367 0 : return (bUseComprGeom) ? OGRSpliteComprPolygonXYZM : OGRSplitePolygonXYZM;
2368 : else
2369 12 : return (bUseComprGeom) ? OGRSpliteComprPolygonXYZ : OGRSplitePolygonXYZ;
2370 : }
2371 : else
2372 : {
2373 130 : if (bHasM == TRUE)
2374 0 : return (bUseComprGeom) ? OGRSpliteComprPolygonXYM : OGRSplitePolygonXYM;
2375 : else
2376 130 : return (bUseComprGeom) ? OGRSpliteComprPolygonXY : OGRSplitePolygonXY;
2377 : }
2378 : break;
2379 :
2380 : default:
2381 : break;
2382 : }
2383 :
2384 56 : if (!bAcceptMultiGeom)
2385 : {
2386 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
2387 0 : return 0;
2388 : }
2389 :
2390 56 : switch (eType)
2391 : {
2392 : case wkbMultiPoint:
2393 10 : if ( bSpatialite2D == TRUE )
2394 2 : return OGRSpliteMultiPointXY;
2395 8 : else if (poGeometry->getCoordinateDimension() == 3)
2396 : {
2397 2 : if (bHasM == TRUE)
2398 0 : return OGRSpliteMultiPointXYZM;
2399 : else
2400 2 : return OGRSpliteMultiPointXYZ;
2401 : }
2402 : else
2403 : {
2404 6 : if (bHasM == TRUE)
2405 0 : return OGRSpliteMultiPointXYM;
2406 : else
2407 6 : return OGRSpliteMultiPointXY;
2408 : }
2409 : break;
2410 :
2411 : case wkbMultiLineString:
2412 10 : if ( bSpatialite2D == TRUE )
2413 2 : return OGRSpliteMultiLineStringXY;
2414 8 : else if (poGeometry->getCoordinateDimension() == 3)
2415 : {
2416 2 : if (bHasM == TRUE)
2417 0 : return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZM :*/ OGRSpliteMultiLineStringXYZM;
2418 : else
2419 2 : return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYZ :*/ OGRSpliteMultiLineStringXYZ;
2420 : }
2421 : else
2422 : {
2423 6 : if (bHasM == TRUE)
2424 0 : return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXYM :*/ OGRSpliteMultiLineStringXYM;
2425 : else
2426 6 : return /*(bUseComprGeom) ? OGRSpliteComprMultiLineStringXY :*/ OGRSpliteMultiLineStringXY;
2427 : }
2428 : break;
2429 :
2430 : case wkbMultiPolygon:
2431 12 : if ( bSpatialite2D == TRUE )
2432 2 : return OGRSpliteMultiPolygonXY;
2433 10 : else if (poGeometry->getCoordinateDimension() == 3)
2434 : {
2435 2 : if (bHasM == TRUE)
2436 0 : return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZM :*/ OGRSpliteMultiPolygonXYZM;
2437 : else
2438 2 : return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYZ :*/ OGRSpliteMultiPolygonXYZ;
2439 : }
2440 : else
2441 : {
2442 8 : if (bHasM == TRUE)
2443 0 : return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXYM :*/ OGRSpliteMultiPolygonXYM;
2444 : else
2445 8 : return /*(bUseComprGeom) ? OGRSpliteComprMultiPolygonXY :*/ OGRSpliteMultiPolygonXY;
2446 : }
2447 : break;
2448 :
2449 :
2450 : case wkbGeometryCollection:
2451 24 : if ( bSpatialite2D == TRUE )
2452 3 : return OGRSpliteGeometryCollectionXY;
2453 21 : else if (poGeometry->getCoordinateDimension() == 3)
2454 : {
2455 8 : if (bHasM == TRUE)
2456 0 : return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZM :*/ OGRSpliteGeometryCollectionXYZM;
2457 : else
2458 8 : return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYZ :*/ OGRSpliteGeometryCollectionXYZ;
2459 : }
2460 : else
2461 : {
2462 13 : if (bHasM == TRUE)
2463 0 : return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXYM :*/ OGRSpliteGeometryCollectionXYM;
2464 : else
2465 13 : return /*(bUseComprGeom) ? OGRSpliteComprGeometryCollectionXY :*/ OGRSpliteGeometryCollectionXY;
2466 : }
2467 : break;
2468 :
2469 : default:
2470 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
2471 0 : return 0;
2472 : }
2473 : }
2474 :
2475 : /************************************************************************/
2476 : /* ExportSpatiaLiteGeometry() */
2477 : /************************************************************************/
2478 :
2479 546 : int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
2480 : OGRwkbByteOrder eByteOrder,
2481 : int bHasM, int bSpatialite2D,
2482 : int bUseComprGeom,
2483 : GByte* pabyData )
2484 : {
2485 546 : switch (wkbFlatten(poGeometry->getGeometryType()))
2486 : {
2487 : case wkbPoint:
2488 : {
2489 148 : OGRPoint* poPoint = (OGRPoint*) poGeometry;
2490 148 : double x = poPoint->getX();
2491 148 : double y = poPoint->getY();
2492 148 : memcpy(pabyData, &x, 8);
2493 148 : memcpy(pabyData + 8, &y, 8);
2494 148 : if (NEED_SWAP_SPATIALITE())
2495 : {
2496 0 : CPL_SWAP64PTR( pabyData );
2497 0 : CPL_SWAP64PTR( pabyData + 8 );
2498 : }
2499 148 : if ( bSpatialite2D == TRUE )
2500 4 : return 16;
2501 144 : else if (poGeometry->getCoordinateDimension() == 3)
2502 : {
2503 10 : double z = poPoint->getZ();
2504 10 : memcpy(pabyData + 16, &z, 8);
2505 10 : if (NEED_SWAP_SPATIALITE())
2506 0 : CPL_SWAP64PTR( pabyData + 16 );
2507 10 : if (bHasM == TRUE)
2508 : {
2509 0 : double m = 0.0;
2510 0 : memcpy(pabyData + 24, &m, 8);
2511 0 : if (NEED_SWAP_SPATIALITE())
2512 0 : CPL_SWAP64PTR( pabyData + 24 );
2513 0 : return 32;
2514 : }
2515 : else
2516 10 : return 24;
2517 : }
2518 : else
2519 : {
2520 134 : if (bHasM == TRUE)
2521 : {
2522 0 : double m = 0.0;
2523 0 : memcpy(pabyData + 16, &m, 8);
2524 0 : if (NEED_SWAP_SPATIALITE())
2525 0 : CPL_SWAP64PTR( pabyData + 16 );
2526 0 : return 24;
2527 : }
2528 : else
2529 134 : return 16;
2530 : }
2531 : }
2532 :
2533 : case wkbLineString:
2534 : case wkbLinearRing:
2535 : {
2536 192 : OGRLineString* poLineString = (OGRLineString*) poGeometry;
2537 192 : int nTotalSize = 4;
2538 192 : int nPointCount = poLineString->getNumPoints();
2539 192 : memcpy(pabyData, &nPointCount, 4);
2540 192 : if (NEED_SWAP_SPATIALITE())
2541 0 : CPL_SWAP32PTR( pabyData );
2542 :
2543 2318 : for(int i=0;i<nPointCount;i++)
2544 : {
2545 2126 : double x = poLineString->getX(i);
2546 2126 : double y = poLineString->getY(i);
2547 :
2548 4208 : if (!bUseComprGeom || i == 0 || i == nPointCount - 1)
2549 : {
2550 2082 : memcpy(pabyData + nTotalSize, &x, 8);
2551 2082 : memcpy(pabyData + nTotalSize + 8, &y, 8);
2552 2082 : if (NEED_SWAP_SPATIALITE())
2553 : {
2554 0 : CPL_SWAP64PTR( pabyData + nTotalSize );
2555 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
2556 : }
2557 2082 : if (!bSpatialite2D && poGeometry->getCoordinateDimension() == 3)
2558 : {
2559 70 : double z = poLineString->getZ(i);
2560 70 : memcpy(pabyData + nTotalSize + 16, &z, 8);
2561 70 : if (NEED_SWAP_SPATIALITE())
2562 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
2563 70 : if (bHasM == TRUE)
2564 : {
2565 0 : double m = 0.0;
2566 0 : memcpy(pabyData + nTotalSize + 24, &m, 8);
2567 0 : if (NEED_SWAP_SPATIALITE())
2568 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 24 );
2569 0 : nTotalSize += 32;
2570 : }
2571 : else
2572 70 : nTotalSize += 24;
2573 : }
2574 : else
2575 : {
2576 2012 : if (bHasM == TRUE)
2577 : {
2578 0 : double m = 0.0;
2579 0 : memcpy(pabyData + nTotalSize + 16, &m, 8);
2580 0 : if (NEED_SWAP_SPATIALITE())
2581 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 16 );
2582 0 : nTotalSize += 24;
2583 : }
2584 : else
2585 2012 : nTotalSize += 16;
2586 : }
2587 : }
2588 : else /* Compressed intermediate points */
2589 : {
2590 44 : float deltax = (float)(x - poLineString->getX(i-1));
2591 44 : float deltay = (float)(y - poLineString->getY(i-1));
2592 44 : memcpy(pabyData + nTotalSize, &deltax, 4);
2593 44 : memcpy(pabyData + nTotalSize + 4, &deltay, 4);
2594 44 : if (NEED_SWAP_SPATIALITE())
2595 : {
2596 0 : CPL_SWAP32PTR( pabyData + nTotalSize );
2597 0 : CPL_SWAP32PTR( pabyData + nTotalSize + 4 );
2598 : }
2599 44 : if (poGeometry->getCoordinateDimension() == 3)
2600 : {
2601 16 : double z = poLineString->getZ(i);
2602 16 : float deltaz = (float)(z - poLineString->getZ(i-1));
2603 16 : memcpy(pabyData + nTotalSize + 8, &deltaz, 4);
2604 16 : if (NEED_SWAP_SPATIALITE())
2605 0 : CPL_SWAP32PTR( pabyData + nTotalSize + 8 );
2606 16 : if (bHasM == TRUE)
2607 : {
2608 0 : double m = 0.0;
2609 0 : memcpy(pabyData + nTotalSize + 12, &m, 8);
2610 0 : if (NEED_SWAP_SPATIALITE())
2611 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 12 );
2612 0 : nTotalSize += 20;
2613 : }
2614 : else
2615 16 : nTotalSize += 12;
2616 : }
2617 : else
2618 : {
2619 28 : if (bHasM == TRUE)
2620 : {
2621 0 : double m = 0.0;
2622 0 : memcpy(pabyData + nTotalSize + 8, &m, 8);
2623 0 : if (NEED_SWAP_SPATIALITE())
2624 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
2625 0 : nTotalSize += 16;
2626 : }
2627 : else
2628 28 : nTotalSize += 8;
2629 : }
2630 : }
2631 : }
2632 192 : return nTotalSize;
2633 : }
2634 :
2635 : case wkbPolygon:
2636 : {
2637 150 : OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
2638 150 : int nParts = 0;
2639 150 : int nTotalSize = 4;
2640 150 : if (poPoly->getExteriorRing() != NULL)
2641 : {
2642 146 : int nInteriorRingCount = poPoly->getNumInteriorRings();
2643 146 : nParts = 1 + nInteriorRingCount;
2644 146 : memcpy(pabyData, &nParts, 4);
2645 146 : if (NEED_SWAP_SPATIALITE())
2646 0 : CPL_SWAP32PTR( pabyData );
2647 :
2648 : nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getExteriorRing(),
2649 : eByteOrder,
2650 : bHasM, bSpatialite2D,
2651 : bUseComprGeom,
2652 146 : pabyData + nTotalSize);
2653 :
2654 152 : for(int i=0;i<nInteriorRingCount;i++)
2655 : {
2656 : nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getInteriorRing(i),
2657 : eByteOrder,
2658 : bHasM, bSpatialite2D,
2659 : bUseComprGeom,
2660 6 : pabyData + nTotalSize);
2661 : }
2662 : }
2663 : else
2664 : {
2665 4 : memset(pabyData, 0, 4);
2666 : }
2667 150 : return nTotalSize;
2668 : }
2669 :
2670 : case wkbMultiPoint:
2671 : case wkbMultiLineString:
2672 : case wkbMultiPolygon:
2673 : case wkbGeometryCollection:
2674 : {
2675 56 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
2676 56 : int nTotalSize = 4;
2677 56 : int nParts = poGeomCollection->getNumGeometries();
2678 56 : memcpy(pabyData, &nParts, 4);
2679 56 : if (NEED_SWAP_SPATIALITE())
2680 0 : CPL_SWAP32PTR( pabyData );
2681 :
2682 128 : for(int i=0;i<nParts;i++)
2683 : {
2684 72 : pabyData[nTotalSize] = 0x69;
2685 72 : nTotalSize ++;
2686 : int nCode = GetSpatialiteGeometryCode(poGeomCollection->getGeometryRef(i),
2687 : bHasM, bSpatialite2D,
2688 72 : bUseComprGeom, FALSE);
2689 72 : if (nCode == 0)
2690 0 : return 0;
2691 72 : memcpy(pabyData + nTotalSize, &nCode, 4);
2692 72 : if (NEED_SWAP_SPATIALITE())
2693 0 : CPL_SWAP32PTR( pabyData + nTotalSize );
2694 72 : nTotalSize += 4;
2695 : nTotalSize += ExportSpatiaLiteGeometryInternal(poGeomCollection->getGeometryRef(i),
2696 : eByteOrder,
2697 : bHasM, bSpatialite2D,
2698 : bUseComprGeom,
2699 72 : pabyData + nTotalSize);
2700 : }
2701 56 : return nTotalSize;
2702 : }
2703 :
2704 : default:
2705 0 : return 0;
2706 : }
2707 : }
2708 :
2709 :
2710 322 : OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
2711 : GInt32 nSRID,
2712 : OGRwkbByteOrder eByteOrder,
2713 : int bHasM, int bSpatialite2D,
2714 : int bUseComprGeom,
2715 : GByte **ppabyData,
2716 : int *pnDataLenght )
2717 :
2718 : {
2719 :
2720 322 : bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poGeometry);
2721 :
2722 : int nDataLen = 44 + ComputeSpatiaLiteGeometrySize( poGeometry,
2723 : bHasM,
2724 : bSpatialite2D,
2725 322 : bUseComprGeom );
2726 322 : OGREnvelope sEnvelope;
2727 :
2728 322 : *ppabyData = (GByte *) CPLMalloc( nDataLen );
2729 :
2730 322 : (*ppabyData)[0] = 0x00;
2731 322 : (*ppabyData)[1] = (GByte) eByteOrder;
2732 :
2733 : // Write out SRID
2734 322 : memcpy( *ppabyData + 2, &nSRID, 4 );
2735 :
2736 : // Write out the geometry bounding rectangle
2737 322 : poGeometry->getEnvelope( &sEnvelope );
2738 322 : memcpy( *ppabyData + 6, &sEnvelope.MinX, 8 );
2739 322 : memcpy( *ppabyData + 14, &sEnvelope.MinY, 8 );
2740 322 : memcpy( *ppabyData + 22, &sEnvelope.MaxX, 8 );
2741 322 : memcpy( *ppabyData + 30, &sEnvelope.MaxY, 8 );
2742 :
2743 322 : (*ppabyData)[38] = 0x7C;
2744 :
2745 : int nCode = GetSpatialiteGeometryCode(poGeometry,
2746 : bHasM, bSpatialite2D,
2747 322 : bUseComprGeom, TRUE);
2748 322 : if (nCode == 0)
2749 : {
2750 0 : CPLFree(*ppabyData);
2751 0 : *ppabyData = NULL;
2752 0 : *pnDataLenght = 0;
2753 0 : return CE_Failure;
2754 : }
2755 322 : memcpy( *ppabyData + 39, &nCode, 4 );
2756 :
2757 : int nWritten = ExportSpatiaLiteGeometryInternal(poGeometry,
2758 : eByteOrder,
2759 : bHasM, bSpatialite2D,
2760 : bUseComprGeom,
2761 322 : *ppabyData + 43);
2762 322 : if (nWritten == 0)
2763 : {
2764 0 : CPLFree(*ppabyData);
2765 0 : *ppabyData = NULL;
2766 0 : *pnDataLenght = 0;
2767 0 : return CE_Failure;
2768 : }
2769 :
2770 322 : (*ppabyData)[nDataLen - 1] = 0xFE;
2771 :
2772 322 : if( NEED_SWAP_SPATIALITE() )
2773 : {
2774 0 : CPL_SWAP32PTR( *ppabyData + 2 );
2775 0 : CPL_SWAP64PTR( *ppabyData + 6 );
2776 0 : CPL_SWAP64PTR( *ppabyData + 14 );
2777 0 : CPL_SWAP64PTR( *ppabyData + 22 );
2778 0 : CPL_SWAP64PTR( *ppabyData + 30 );
2779 0 : CPL_SWAP32PTR( *ppabyData + 39 );
2780 : }
2781 :
2782 322 : *pnDataLenght = nDataLen;
2783 :
2784 322 : return CE_None;
2785 : }
2786 :
2787 : /************************************************************************/
2788 : /* TestCapability() */
2789 : /************************************************************************/
2790 :
2791 66 : int OGRSQLiteLayer::TestCapability( const char * pszCap )
2792 :
2793 : {
2794 66 : if( EQUAL(pszCap,OLCRandomRead) )
2795 4 : return FALSE;
2796 :
2797 62 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
2798 0 : return FALSE;
2799 :
2800 62 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
2801 0 : return FALSE;
2802 :
2803 62 : else if( EQUAL(pszCap,OLCIgnoreFields) )
2804 11 : return TRUE;
2805 :
2806 51 : else if( EQUAL(pszCap,OLCTransactions) )
2807 9 : return TRUE;
2808 :
2809 : else
2810 42 : return FALSE;
2811 : }
2812 :
2813 : /************************************************************************/
2814 : /* GetSpatialRef() */
2815 : /************************************************************************/
2816 :
2817 70 : OGRSpatialReference *OGRSQLiteLayer::GetSpatialRef()
2818 :
2819 : {
2820 70 : return poSRS;
2821 : }
2822 :
2823 : /************************************************************************/
2824 : /* StartTransaction() */
2825 : /************************************************************************/
2826 :
2827 35 : OGRErr OGRSQLiteLayer::StartTransaction()
2828 :
2829 : {
2830 35 : return poDS->SoftStartTransaction();
2831 : }
2832 :
2833 : /************************************************************************/
2834 : /* CommitTransaction() */
2835 : /************************************************************************/
2836 :
2837 24 : OGRErr OGRSQLiteLayer::CommitTransaction()
2838 :
2839 : {
2840 24 : return poDS->SoftCommit();
2841 : }
2842 :
2843 : /************************************************************************/
2844 : /* RollbackTransaction() */
2845 : /************************************************************************/
2846 :
2847 11 : OGRErr OGRSQLiteLayer::RollbackTransaction()
2848 :
2849 : {
2850 11 : return poDS->SoftRollback();
2851 : }
2852 :
2853 : /************************************************************************/
2854 : /* ClearStatement() */
2855 : /************************************************************************/
2856 :
2857 3164 : void OGRSQLiteLayer::ClearStatement()
2858 :
2859 : {
2860 3164 : if( hStmt != NULL )
2861 : {
2862 501 : CPLDebug( "OGR_SQLITE", "finalize %p", hStmt );
2863 501 : sqlite3_finalize( hStmt );
2864 501 : hStmt = NULL;
2865 : }
2866 3164 : }
2867 :
2868 : /************************************************************************/
2869 : /* OGRSQLITEStringToDateTimeField() */
2870 : /************************************************************************/
2871 :
2872 306 : int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
2873 : const char* pszValue )
2874 : {
2875 306 : int nYear = 0, nMonth = 0, nDay = 0,
2876 306 : nHour = 0, nMinute = 0;
2877 306 : float fSecond = 0;
2878 :
2879 : /* YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SS.SSS */
2880 306 : nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
2881 306 : nMinute = 0; fSecond = 0;
2882 306 : if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d:%f",
2883 : &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
2884 : {
2885 : poFeature->SetField( iField, nYear, nMonth,
2886 0 : nDay, nHour, nMinute, (int)(fSecond + 0.5), 0 );
2887 0 : return TRUE;
2888 : }
2889 :
2890 : /* YYYY-MM-DD HH:MM */
2891 306 : nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
2892 306 : nMinute = 0;
2893 306 : if( sscanf(pszValue, "%04d-%02d-%02d %02d:%02d",
2894 : &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
2895 : {
2896 : poFeature->SetField( iField, nYear, nMonth,
2897 4 : nDay, nHour, nMinute, 0, 0 );
2898 4 : return TRUE;
2899 : }
2900 :
2901 : /* YYYY-MM-DDTHH:MM:SS or YYYY-MM-DDTHH:MM:SS.SSS */
2902 302 : nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
2903 302 : nMinute = 0; fSecond = 0;
2904 302 : if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d:%f",
2905 : &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) == 6 )
2906 : {
2907 : poFeature->SetField( iField, nYear, nMonth, nDay,
2908 98 : nHour, nMinute, (int)(fSecond + 0.5), 0 );
2909 98 : return TRUE;
2910 : }
2911 :
2912 : /* YYYY-MM-DDTHH:MM */
2913 204 : nYear = 0; nMonth = 0; nDay = 0; nHour = 0;
2914 204 : nMinute = 0;
2915 204 : if( sscanf(pszValue, "%04d-%02d-%02dT%02d:%02d",
2916 : &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 )
2917 : {
2918 : poFeature->SetField( iField, nYear, nMonth, nDay,
2919 0 : nHour, nMinute, 0, 0 );
2920 0 : return TRUE;
2921 : }
2922 :
2923 : /* YYYY-MM-DD */
2924 204 : nYear = 0; nMonth = 0; nDay = 0;
2925 204 : if( sscanf(pszValue, "%04d-%02d-%02d",
2926 : &nYear, &nMonth, &nDay) == 3 )
2927 : {
2928 : poFeature->SetField( iField, nYear, nMonth, nDay,
2929 102 : 0, 0, 0, 0 );
2930 102 : return TRUE;
2931 : }
2932 :
2933 : /* HH:MM:SS or HH:MM:SS.SSS */
2934 102 : nDay = 0; nHour = 0; fSecond = 0;
2935 102 : if( sscanf(pszValue, "%02d:%02d:%f",
2936 : &nHour, &nMinute, &fSecond) == 3 )
2937 : {
2938 : poFeature->SetField( iField, 0, 0, 0,
2939 94 : nHour, nMinute, (int)(fSecond + 0.5), 0 );
2940 94 : return TRUE;
2941 : }
2942 :
2943 : /* HH:MM */
2944 8 : nHour = 0; nMinute = 0;
2945 8 : if( sscanf(pszValue, "%02d:%02d", &nHour, &nMinute) == 2 )
2946 : {
2947 : poFeature->SetField( iField, 0, 0, 0,
2948 8 : nHour, nMinute, 0, 0 );
2949 8 : return TRUE;
2950 : }
2951 :
2952 0 : return FALSE;
2953 : }
|