1 : /******************************************************************************
2 : * $Id: ogrsqlitelayer.cpp 19800 2010-06-04 21:38:03Z 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 : * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "ogr_sqlite.h"
34 : #include <cassert>
35 :
36 : CPL_CVSID("$Id: ogrsqlitelayer.cpp 19800 2010-06-04 21:38:03Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRSQLiteLayer() */
40 : /************************************************************************/
41 :
42 708 : OGRSQLiteLayer::OGRSQLiteLayer()
43 :
44 : {
45 708 : poDS = NULL;
46 :
47 708 : pszFIDColumn = NULL;
48 :
49 708 : eGeomFormat = OSGF_None;
50 :
51 708 : hStmt = NULL;
52 :
53 708 : iNextShapeId = 0;
54 :
55 708 : poSRS = NULL;
56 708 : nSRSId = -2; // we haven't even queried the database for it yet.
57 :
58 708 : panFieldOrdinals = NULL;
59 :
60 708 : bTriedAsSpatiaLite = FALSE;
61 708 : bHasSpatialIndex = FALSE;
62 708 : }
63 :
64 : /************************************************************************/
65 : /* ~OGRSQLiteLayer() */
66 : /************************************************************************/
67 :
68 708 : OGRSQLiteLayer::~OGRSQLiteLayer()
69 :
70 : {
71 708 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
72 : {
73 : CPLDebug( "SQLite", "%d features read on layer '%s'.",
74 : (int) m_nFeaturesRead,
75 145 : poFeatureDefn->GetName() );
76 : }
77 :
78 708 : if( hStmt != NULL )
79 : {
80 30 : sqlite3_finalize( hStmt );
81 30 : hStmt = NULL;
82 : }
83 :
84 708 : if( poFeatureDefn != NULL )
85 : {
86 708 : poFeatureDefn->Release();
87 708 : poFeatureDefn = NULL;
88 : }
89 :
90 708 : if( poSRS != NULL )
91 85 : poSRS->Dereference();
92 :
93 708 : CPLFree( pszFIDColumn );
94 708 : CPLFree( panFieldOrdinals );
95 708 : }
96 :
97 : /************************************************************************/
98 : /* BuildFeatureDefn() */
99 : /* */
100 : /* Build feature definition from a set of column definitions */
101 : /* set on a statement. Sift out geometry and FID fields. */
102 : /************************************************************************/
103 :
104 : CPLErr OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
105 708 : sqlite3_stmt *hStmt )
106 :
107 : {
108 708 : poFeatureDefn = new OGRFeatureDefn( pszLayerName );
109 708 : int nRawColumns = sqlite3_column_count( hStmt );
110 :
111 708 : poFeatureDefn->Reference();
112 :
113 708 : panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
114 :
115 4172 : for( int iCol = 0; iCol < nRawColumns; iCol++ )
116 : {
117 : OGRFieldDefn oField( sqlite3_column_name( hStmt, iCol ),
118 3464 : OFTString );
119 :
120 : // In some cases, particularly when there is a real name for
121 : // the primary key/_rowid_ column we will end up getting the
122 : // primary key column appearing twice. Ignore any repeated names.
123 3464 : if( poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
124 1135 : continue;
125 :
126 3464 : if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oField.GetNameRef()))
127 : continue;
128 :
129 : //oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
130 :
131 2510 : if( osGeomColumn.size()
132 : && EQUAL(oField.GetNameRef(),osGeomColumn) )
133 : continue;
134 :
135 2394 : int nColType = sqlite3_column_type( hStmt, iCol );
136 2394 : const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
137 : //CPLDebug("SQLITE", "decltype(%s) = %s",
138 : // oField.GetNameRef(), pszDeclType ? pszDeclType : "null");
139 2394 : if (pszDeclType != NULL)
140 : {
141 2038 : if (EQUAL(pszDeclType, "INTEGER"))
142 793 : nColType = SQLITE_INTEGER;
143 1245 : else if (EQUAL(pszDeclType, "FLOAT"))
144 12 : nColType = SQLITE_FLOAT;
145 1233 : else if (EQUAL(pszDeclType, "BLOB"))
146 164 : nColType = SQLITE_BLOB;
147 1069 : else if (EQUAL(pszDeclType, "TEXT") ||
148 : EQUAL(pszDeclType, "VARCHAR"))
149 812 : nColType = SQLITE_TEXT;
150 : }
151 :
152 : // Recognise some common geometry column names.
153 2394 : if( (EQUAL(oField.GetNameRef(),"wkt_geometry")
154 : || EQUAL(oField.GetNameRef(),"geometry")
155 : || EQUALN(oField.GetNameRef(), "asbinary(", 9)
156 : || EQUALN(oField.GetNameRef(), "astext(", 7))
157 : && osGeomColumn.size() == 0 )
158 : {
159 60 : if( nColType == SQLITE_BLOB )
160 : {
161 57 : osGeomColumn = oField.GetNameRef();
162 57 : eGeomFormat = OSGF_WKB;
163 : /* This could also be a SpatialLite geometry, so */
164 : /* we'll also try to decode as SpatialLite if */
165 : /* bTriedAsSpatiaLite is not FALSE */
166 : continue;
167 : }
168 3 : else if( nColType == SQLITE_TEXT )
169 : {
170 3 : osGeomColumn = oField.GetNameRef();
171 3 : eGeomFormat = OSGF_WKT;
172 : continue;
173 : }
174 : }
175 :
176 : // SpatialLite / Gaia
177 2334 : if( EQUAL(oField.GetNameRef(),"GaiaGeometry")
178 : && osGeomColumn.size() == 0 )
179 : {
180 0 : osGeomColumn = oField.GetNameRef();
181 0 : eGeomFormat = OSGF_SpatiaLite;
182 : continue;
183 : }
184 :
185 : // The rowid is for internal use, not a real column.
186 2334 : if( EQUAL(oField.GetNameRef(),"_rowid_") )
187 : continue;
188 :
189 : // The OGC_FID is for internal use, not a real user visible column.
190 2334 : if( EQUAL(oField.GetNameRef(),"OGC_FID") )
191 : continue;
192 :
193 2329 : switch( nColType )
194 : {
195 : case SQLITE_INTEGER:
196 868 : oField.SetType( OFTInteger );
197 868 : break;
198 :
199 : case SQLITE_FLOAT:
200 252 : oField.SetType( OFTReal );
201 252 : break;
202 :
203 : case SQLITE_BLOB:
204 158 : oField.SetType( OFTBinary );
205 : break;
206 :
207 : default:
208 : /* leave it as OFTString */;
209 : }
210 :
211 2329 : poFeatureDefn->AddFieldDefn( &oField );
212 2329 : panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
213 : }
214 :
215 : /* -------------------------------------------------------------------- */
216 : /* If we have no geometry source, we know our geometry type is */
217 : /* none. */
218 : /* -------------------------------------------------------------------- */
219 708 : if( osGeomColumn.size() == 0 )
220 532 : poFeatureDefn->SetGeomType( wkbNone );
221 :
222 708 : return CE_None;
223 : }
224 :
225 : /************************************************************************/
226 : /* GetFIDColumn() */
227 : /************************************************************************/
228 :
229 0 : const char *OGRSQLiteLayer::GetFIDColumn()
230 :
231 : {
232 0 : if( pszFIDColumn != NULL )
233 0 : return pszFIDColumn;
234 : else
235 0 : return "";
236 : }
237 :
238 : /************************************************************************/
239 : /* GetGeometryColumn() */
240 : /************************************************************************/
241 :
242 0 : const char *OGRSQLiteLayer::GetGeometryColumn()
243 :
244 : {
245 0 : if( osGeomColumn.size() != 0 )
246 0 : return osGeomColumn.c_str();
247 : else
248 0 : return "";
249 : }
250 :
251 : /************************************************************************/
252 : /* ResetReading() */
253 : /************************************************************************/
254 :
255 404 : void OGRSQLiteLayer::ResetReading()
256 :
257 : {
258 404 : ClearStatement();
259 404 : iNextShapeId = 0;
260 404 : }
261 :
262 : /************************************************************************/
263 : /* GetNextFeature() */
264 : /************************************************************************/
265 :
266 654 : OGRFeature *OGRSQLiteLayer::GetNextFeature()
267 :
268 : {
269 94 : for( ; TRUE; )
270 : {
271 : OGRFeature *poFeature;
272 :
273 654 : poFeature = GetNextRawFeature();
274 654 : if( poFeature == NULL )
275 117 : return NULL;
276 :
277 537 : if( (m_poFilterGeom == NULL
278 : || FilterGeometry( poFeature->GetGeometryRef() ) )
279 : && (m_poAttrQuery == NULL
280 : || m_poAttrQuery->Evaluate( poFeature )) )
281 443 : return poFeature;
282 :
283 94 : delete poFeature;
284 : }
285 : }
286 :
287 : /************************************************************************/
288 : /* GetNextRawFeature() */
289 : /************************************************************************/
290 :
291 655 : OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
292 :
293 : {
294 655 : if( hStmt == NULL )
295 : {
296 197 : ResetStatement();
297 197 : if (hStmt == NULL)
298 0 : return NULL;
299 : }
300 :
301 : /* -------------------------------------------------------------------- */
302 : /* If we are marked to restart then do so, and fetch a record. */
303 : /* -------------------------------------------------------------------- */
304 : int rc;
305 :
306 655 : rc = sqlite3_step( hStmt );
307 655 : if( rc != SQLITE_ROW )
308 : {
309 117 : if ( rc != SQLITE_DONE )
310 : {
311 0 : sqlite3_reset(hStmt);
312 : CPLError( CE_Failure, CPLE_AppDefined,
313 : "In GetNextRawFeature(): sqlite3_step() : %s",
314 0 : sqlite3_errmsg(poDS->GetDB()) );
315 : }
316 :
317 117 : ClearStatement();
318 :
319 117 : return NULL;
320 : }
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Create a feature from the current result. */
324 : /* -------------------------------------------------------------------- */
325 : int iField;
326 538 : OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
327 :
328 : /* -------------------------------------------------------------------- */
329 : /* Set FID if we have a column to set it from. */
330 : /* -------------------------------------------------------------------- */
331 538 : if( pszFIDColumn != NULL )
332 : {
333 : int iFIDCol;
334 :
335 292 : for( iFIDCol = 0; iFIDCol < sqlite3_column_count(hStmt); iFIDCol++ )
336 : {
337 292 : if( EQUAL(sqlite3_column_name(hStmt,iFIDCol),
338 : pszFIDColumn) )
339 292 : break;
340 : }
341 :
342 292 : if( iFIDCol == sqlite3_column_count(hStmt) )
343 : {
344 : CPLError( CE_Failure, CPLE_AppDefined,
345 : "Unable to find FID column '%s'.",
346 0 : pszFIDColumn );
347 0 : return NULL;
348 : }
349 :
350 292 : poFeature->SetFID( sqlite3_column_int( hStmt, iFIDCol ) );
351 : }
352 : else
353 246 : poFeature->SetFID( iNextShapeId );
354 :
355 538 : iNextShapeId++;
356 :
357 538 : m_nFeaturesRead++;
358 :
359 : /* -------------------------------------------------------------------- */
360 : /* Process Geometry if we have a column. */
361 : /* -------------------------------------------------------------------- */
362 538 : if( osGeomColumn.size() )
363 : {
364 : int iGeomCol;
365 :
366 1077 : for( iGeomCol = 0; iGeomCol < sqlite3_column_count(hStmt); iGeomCol++ )
367 : {
368 1077 : if( EQUAL(sqlite3_column_name(hStmt,iGeomCol),
369 : osGeomColumn) )
370 316 : break;
371 : }
372 :
373 316 : if( iGeomCol == sqlite3_column_count(hStmt) )
374 : {
375 : CPLError( CE_Failure, CPLE_AppDefined,
376 : "Unable to find Geometry column '%s'.",
377 0 : osGeomColumn.c_str() );
378 0 : return NULL;
379 : }
380 :
381 316 : OGRGeometry *poGeometry = NULL;
382 316 : if ( eGeomFormat == OSGF_WKT )
383 : {
384 3 : char *pszWKTCopy, *pszWKT = NULL;
385 :
386 3 : pszWKT = (char *) sqlite3_column_text( hStmt, iGeomCol );
387 3 : pszWKTCopy = pszWKT;
388 3 : if( OGRGeometryFactory::createFromWkt(
389 : &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
390 3 : poFeature->SetGeometryDirectly( poGeometry );
391 : }
392 313 : else if ( eGeomFormat == OSGF_WKB )
393 : {
394 141 : const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
395 :
396 141 : if( OGRGeometryFactory::createFromWkb(
397 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
398 : NULL, &poGeometry, nBytes ) == OGRERR_NONE )
399 119 : poFeature->SetGeometryDirectly( poGeometry );
400 22 : else if (!bTriedAsSpatiaLite)
401 : {
402 : /* If the layer is the result of a sql select, we cannot be sure if it is */
403 : /* WKB or SpatialLite format */
404 20 : if( ImportSpatiaLiteGeometry(
405 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
406 : &poGeometry ) == OGRERR_NONE )
407 : {
408 19 : poFeature->SetGeometryDirectly( poGeometry );
409 19 : eGeomFormat = OSGF_SpatiaLite;
410 : }
411 20 : bTriedAsSpatiaLite = TRUE;
412 : }
413 : }
414 172 : else if ( eGeomFormat == OSGF_FGF )
415 : {
416 8 : const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
417 :
418 8 : if( OGRGeometryFactory::createFromFgf(
419 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
420 : NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
421 8 : poFeature->SetGeometryDirectly( poGeometry );
422 : }
423 164 : else if ( eGeomFormat == OSGF_SpatiaLite )
424 : {
425 164 : const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
426 :
427 164 : if( ImportSpatiaLiteGeometry(
428 : (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
429 : &poGeometry ) == OGRERR_NONE )
430 161 : poFeature->SetGeometryDirectly( poGeometry );
431 : }
432 :
433 316 : if (poGeometry != NULL && poSRS != NULL)
434 132 : poGeometry->assignSpatialReference(poSRS);
435 : }
436 :
437 : /* -------------------------------------------------------------------- */
438 : /* set the fields. */
439 : /* -------------------------------------------------------------------- */
440 1890 : for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
441 : {
442 1352 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
443 1352 : int iRawField = panFieldOrdinals[iField] - 1;
444 :
445 1352 : if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
446 224 : continue;
447 :
448 1128 : switch( poFieldDefn->GetType() )
449 : {
450 : case OFTInteger:
451 : poFeature->SetField( iField,
452 362 : sqlite3_column_int( hStmt, iRawField ) );
453 362 : break;
454 :
455 : case OFTReal:
456 : poFeature->SetField( iField,
457 301 : sqlite3_column_double( hStmt, iRawField ) );
458 301 : break;
459 :
460 : case OFTBinary:
461 : {
462 54 : const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
463 :
464 : poFeature->SetField( iField, nBytes,
465 54 : (GByte*)sqlite3_column_blob( hStmt, iRawField ) );
466 : }
467 54 : break;
468 :
469 : case OFTString:
470 : poFeature->SetField( iField,
471 : (const char *)
472 411 : sqlite3_column_text( hStmt, iRawField ) );
473 : break;
474 :
475 : default:
476 : break;
477 : }
478 : }
479 :
480 538 : return poFeature;
481 : }
482 :
483 : /************************************************************************/
484 : /* GetFeature() */
485 : /************************************************************************/
486 :
487 2 : OGRFeature *OGRSQLiteLayer::GetFeature( long nFeatureId )
488 :
489 : {
490 2 : return OGRLayer::GetFeature( nFeatureId );
491 : }
492 :
493 :
494 : /************************************************************************/
495 : /* createFromSpatialiteInternal() */
496 : /************************************************************************/
497 :
498 : /* See http://www.gaia-gis.it/spatialite/spatialite-manual-2.3.0.html#t3.3 */
499 : /* for the specification of the spatialite BLOB geometry format */
500 : /* Derived from WKB, but unfortunately it is not practical to reuse existing */
501 : /* WKB encoding/decoding code */
502 :
503 : #ifdef CPL_LSB
504 : #define NEED_SWAP_SPATIALITE() (eByteOrder != wkbNDR)
505 : #else
506 : #define NEED_SWAP_SPATIALITE() (eByteOrder == wkbNDR)
507 : #endif
508 :
509 :
510 : OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
511 : OGRGeometry **ppoReturn,
512 : int nBytes,
513 : OGRwkbByteOrder eByteOrder,
514 205 : int* pnBytesConsumed)
515 : {
516 205 : OGRErr eErr = OGRERR_NONE;
517 205 : OGRGeometry *poGeom = NULL;
518 : GInt32 nGType;
519 :
520 205 : *ppoReturn = NULL;
521 :
522 205 : if (nBytes < 4)
523 0 : return OGRERR_NOT_ENOUGH_DATA;
524 :
525 : /* -------------------------------------------------------------------- */
526 : /* Decode the geometry type. */
527 : /* -------------------------------------------------------------------- */
528 205 : memcpy( &nGType, pabyData, 4 );
529 205 : if (NEED_SWAP_SPATIALITE())
530 0 : CPL_SWAP32PTR( &nGType );
531 :
532 205 : if( nGType < 1 || nGType > 7 )
533 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
534 :
535 : /* -------------------------------------------------------------------- */
536 : /* Point */
537 : /* -------------------------------------------------------------------- */
538 205 : if( nGType == 1 )
539 : {
540 : double adfTuple[2];
541 :
542 108 : if( nBytes < 4 + 2 * 8 )
543 0 : return OGRERR_NOT_ENOUGH_DATA;
544 :
545 108 : memcpy( adfTuple, pabyData + 4, 2*8 );
546 108 : if (NEED_SWAP_SPATIALITE())
547 : {
548 0 : CPL_SWAP64PTR( adfTuple );
549 0 : CPL_SWAP64PTR( adfTuple + 1 );
550 : }
551 :
552 108 : poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
553 :
554 108 : if( pnBytesConsumed )
555 3 : *pnBytesConsumed = 4 + 2 * 8;
556 : }
557 :
558 : /* -------------------------------------------------------------------- */
559 : /* LineString */
560 : /* -------------------------------------------------------------------- */
561 97 : else if( nGType == 2 )
562 : {
563 : double adfTuple[2];
564 : GInt32 nPointCount;
565 : int iPoint;
566 : OGRLineString *poLS;
567 :
568 4 : if( nBytes < 8 )
569 0 : return OGRERR_NOT_ENOUGH_DATA;
570 :
571 4 : memcpy( &nPointCount, pabyData + 4, 4 );
572 4 : if (NEED_SWAP_SPATIALITE())
573 0 : CPL_SWAP32PTR( &nPointCount );
574 :
575 4 : if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
576 0 : return OGRERR_CORRUPT_DATA;
577 :
578 4 : if (nBytes - 8 < 2 * 8 * nPointCount )
579 0 : return OGRERR_NOT_ENOUGH_DATA;
580 :
581 4 : poGeom = poLS = new OGRLineString();
582 4 : poLS->setNumPoints( nPointCount );
583 :
584 10 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
585 : {
586 6 : memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
587 6 : if (NEED_SWAP_SPATIALITE())
588 : {
589 0 : CPL_SWAP64PTR( adfTuple );
590 0 : CPL_SWAP64PTR( adfTuple + 1 );
591 : }
592 :
593 6 : poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
594 : }
595 :
596 4 : if( pnBytesConsumed )
597 2 : *pnBytesConsumed = 8 + 2 * 8 * nPointCount;
598 : }
599 :
600 : /* -------------------------------------------------------------------- */
601 : /* Polygon */
602 : /* -------------------------------------------------------------------- */
603 93 : else if( nGType == 3 )
604 : {
605 : double adfTuple[2];
606 : GInt32 nPointCount;
607 : GInt32 nRingCount;
608 : int iPoint, iRing;
609 : OGRLinearRing *poLR;
610 : OGRPolygon *poPoly;
611 : int nNextByte;
612 :
613 70 : if( nBytes < 8 )
614 0 : return OGRERR_NOT_ENOUGH_DATA;
615 :
616 70 : memcpy( &nRingCount, pabyData + 4, 4 );
617 70 : if (NEED_SWAP_SPATIALITE())
618 0 : CPL_SWAP32PTR( &nRingCount );
619 :
620 70 : if (nRingCount < 0 || nRingCount > INT_MAX / 4)
621 0 : return OGRERR_CORRUPT_DATA;
622 :
623 : /* Each ring has a minimum of 4 bytes */
624 70 : if (nBytes - 8 < nRingCount * 4)
625 0 : return OGRERR_NOT_ENOUGH_DATA;
626 :
627 70 : nNextByte = 8;
628 :
629 70 : poGeom = poPoly = new OGRPolygon();
630 :
631 140 : for( iRing = 0; iRing < nRingCount; iRing++ )
632 : {
633 70 : if( nBytes - nNextByte < 4 )
634 0 : return OGRERR_NOT_ENOUGH_DATA;
635 :
636 70 : memcpy( &nPointCount, pabyData + nNextByte, 4 );
637 70 : if (NEED_SWAP_SPATIALITE())
638 0 : CPL_SWAP32PTR( &nPointCount );
639 :
640 70 : if (nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
641 0 : return OGRERR_CORRUPT_DATA;
642 :
643 70 : nNextByte += 4;
644 :
645 70 : if( nBytes - nNextByte < 2 * 8 * nPointCount )
646 0 : return OGRERR_NOT_ENOUGH_DATA;
647 :
648 70 : poLR = new OGRLinearRing();
649 70 : poLR->setNumPoints( nPointCount );
650 :
651 400 : for( iPoint = 0; iPoint < nPointCount; iPoint++ )
652 : {
653 330 : memcpy( adfTuple, pabyData + nNextByte, 2*8 );
654 330 : nNextByte += 2 * 8;
655 :
656 330 : if (NEED_SWAP_SPATIALITE())
657 : {
658 0 : CPL_SWAP64PTR( adfTuple );
659 0 : CPL_SWAP64PTR( adfTuple + 1 );
660 : }
661 :
662 330 : poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
663 : }
664 :
665 70 : poPoly->addRingDirectly( poLR );
666 : }
667 :
668 70 : if( pnBytesConsumed )
669 20 : *pnBytesConsumed = nNextByte;
670 : }
671 :
672 : /* -------------------------------------------------------------------- */
673 : /* GeometryCollections of various kinds. */
674 : /* -------------------------------------------------------------------- */
675 46 : else if( nGType == 4 // MultiPoint
676 : || nGType == 5 // MultiLineString
677 : || nGType == 6 // MultiPolygon
678 : || nGType == 7 ) // MultiGeometry
679 : {
680 23 : OGRGeometryCollection *poGC = NULL;
681 23 : GInt32 nGeomCount = 0;
682 23 : int iGeom = 0;
683 23 : int nBytesUsed = 0;
684 :
685 23 : if( nGType == 4 )
686 2 : poGC = new OGRMultiPoint();
687 21 : else if( nGType == 5 )
688 2 : poGC = new OGRMultiLineString();
689 19 : else if( nGType == 6 )
690 16 : poGC = new OGRMultiPolygon();
691 3 : else if( nGType == 7 )
692 3 : poGC = new OGRGeometryCollection();
693 :
694 23 : assert(NULL != poGC);
695 :
696 23 : if( nBytes < 8 )
697 0 : return OGRERR_NOT_ENOUGH_DATA;
698 :
699 23 : memcpy( &nGeomCount, pabyData + 4, 4 );
700 23 : if (NEED_SWAP_SPATIALITE())
701 0 : CPL_SWAP32PTR( &nGeomCount );
702 :
703 23 : if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
704 0 : return OGRERR_CORRUPT_DATA;
705 :
706 : /* Each sub geometry takes at least 9 bytes */
707 23 : if (nBytes - 8 < nGeomCount * 9)
708 0 : return OGRERR_NOT_ENOUGH_DATA;
709 :
710 23 : nBytesUsed = 8;
711 :
712 48 : for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
713 : {
714 : int nThisGeomSize;
715 25 : OGRGeometry *poThisGeom = NULL;
716 :
717 25 : if (nBytes - nBytesUsed < 5)
718 0 : return OGRERR_NOT_ENOUGH_DATA;
719 :
720 25 : if (pabyData[nBytesUsed] != 0x69)
721 0 : return OGRERR_CORRUPT_DATA;
722 :
723 25 : nBytesUsed ++;
724 :
725 : eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
726 : &poThisGeom, nBytes - nBytesUsed,
727 25 : eByteOrder, &nThisGeomSize);
728 25 : if( eErr != OGRERR_NONE )
729 : {
730 0 : delete poGC;
731 0 : return eErr;
732 : }
733 :
734 25 : nBytesUsed += nThisGeomSize;
735 25 : eErr = poGC->addGeometryDirectly( poThisGeom );
736 25 : if( eErr != OGRERR_NONE )
737 : {
738 0 : delete poGC;
739 0 : return eErr;
740 : }
741 : }
742 :
743 23 : poGeom = poGC;
744 23 : if( pnBytesConsumed )
745 0 : *pnBytesConsumed = nBytesUsed;
746 : }
747 :
748 : /* -------------------------------------------------------------------- */
749 : /* Currently unsupported geometry. */
750 : /* -------------------------------------------------------------------- */
751 : else
752 : {
753 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
754 : }
755 :
756 : /* -------------------------------------------------------------------- */
757 : /* Assign spatial reference system. */
758 : /* -------------------------------------------------------------------- */
759 205 : if( eErr == OGRERR_NONE )
760 : {
761 205 : *ppoReturn = poGeom;
762 : }
763 : else
764 : {
765 0 : delete poGeom;
766 : }
767 :
768 205 : return eErr;
769 : }
770 :
771 : /************************************************************************/
772 : /* ImportSpatiaLiteGeometry() */
773 : /************************************************************************/
774 :
775 : OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
776 : int nBytes,
777 184 : OGRGeometry **ppoGeometry )
778 :
779 : {
780 : OGRwkbByteOrder eByteOrder;
781 :
782 184 : *ppoGeometry = NULL;
783 :
784 184 : if( nBytes < 44
785 : || pabyData[0] != 0
786 : || pabyData[38] != 0x7C
787 : || pabyData[nBytes-1] != 0xFE )
788 4 : return OGRERR_CORRUPT_DATA;
789 :
790 180 : eByteOrder = (OGRwkbByteOrder) pabyData[1];
791 :
792 : return createFromSpatialiteInternal(pabyData + 39, ppoGeometry,
793 180 : nBytes - 39, eByteOrder, NULL);
794 : }
795 :
796 : /************************************************************************/
797 : /* ComputeSpatiaLiteGeometrySize() */
798 : /************************************************************************/
799 :
800 175 : int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry)
801 : {
802 175 : switch (wkbFlatten(poGeometry->getGeometryType()))
803 : {
804 : case wkbPoint:
805 106 : return 16;
806 :
807 : case wkbLineString:
808 : case wkbLinearRing:
809 32 : return 4 + 16 * ((OGRLineString*)poGeometry)->getNumPoints();
810 :
811 : case wkbPolygon:
812 : {
813 28 : int nSize = 4;
814 28 : OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
815 28 : if (poPoly->getExteriorRing() != NULL)
816 : {
817 27 : nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing());
818 :
819 27 : int nInteriorRingCount = poPoly->getNumInteriorRings();
820 28 : for(int i=0;i<nInteriorRingCount;i++)
821 1 : nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i));
822 : }
823 28 : return nSize;
824 : }
825 :
826 : case wkbMultiPoint:
827 : case wkbMultiLineString:
828 : case wkbMultiPolygon:
829 : case wkbGeometryCollection:
830 : {
831 9 : int nSize = 4;
832 9 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
833 9 : int nParts = poGeomCollection->getNumGeometries();
834 19 : for(int i=0;i<nParts;i++)
835 10 : nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i));
836 9 : return nSize;
837 : }
838 :
839 : default:
840 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
841 0 : return 0;
842 : }
843 : }
844 :
845 : /************************************************************************/
846 : /* ExportSpatiaLiteGeometry() */
847 : /************************************************************************/
848 :
849 : int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
850 : OGRwkbByteOrder eByteOrder,
851 175 : GByte* pabyData)
852 : {
853 175 : switch (wkbFlatten(poGeometry->getGeometryType()))
854 : {
855 : case wkbPoint:
856 : {
857 106 : OGRPoint* poPoint = (OGRPoint*) poGeometry;
858 106 : double x = poPoint->getX();
859 106 : double y = poPoint->getY();
860 106 : memcpy(pabyData, &x, 8);
861 106 : memcpy(pabyData + 8, &y, 8);
862 106 : if (NEED_SWAP_SPATIALITE())
863 : {
864 0 : CPL_SWAP64PTR( pabyData );
865 0 : CPL_SWAP64PTR( pabyData + 8 );
866 : }
867 106 : return 16;
868 : }
869 :
870 : case wkbLineString:
871 : case wkbLinearRing:
872 : {
873 32 : OGRLineString* poLineString = (OGRLineString*) poGeometry;
874 32 : int nTotalSize = 4;
875 32 : int nPointCount = poLineString->getNumPoints();
876 32 : memcpy(pabyData, &nPointCount, 4);
877 32 : if (NEED_SWAP_SPATIALITE())
878 0 : CPL_SWAP32PTR( pabyData );
879 154 : for(int i=0;i<nPointCount;i++)
880 : {
881 122 : double x = poLineString->getX(i);
882 122 : double y = poLineString->getY(i);
883 122 : memcpy(pabyData + nTotalSize, &x, 8);
884 122 : memcpy(pabyData + nTotalSize + 8, &y, 8);
885 122 : if (NEED_SWAP_SPATIALITE())
886 : {
887 0 : CPL_SWAP64PTR( pabyData + nTotalSize );
888 0 : CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
889 : }
890 122 : nTotalSize += 16;
891 : }
892 32 : return nTotalSize;
893 : }
894 :
895 : case wkbPolygon:
896 : {
897 28 : OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
898 28 : int nParts = 0;
899 28 : int nTotalSize = 4;
900 28 : if (poPoly->getExteriorRing() != NULL)
901 : {
902 27 : int nInteriorRingCount = poPoly->getNumInteriorRings();
903 27 : nParts = 1 + nInteriorRingCount;
904 27 : memcpy(pabyData, &nParts, 4);
905 27 : if (NEED_SWAP_SPATIALITE())
906 0 : CPL_SWAP32PTR( pabyData );
907 :
908 : nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getExteriorRing(),
909 27 : eByteOrder, pabyData + nTotalSize);
910 :
911 28 : for(int i=0;i<nInteriorRingCount;i++)
912 : {
913 : nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getInteriorRing(i),
914 1 : eByteOrder, pabyData + nTotalSize);
915 : }
916 : }
917 : else
918 : {
919 1 : memset(pabyData, 0, 4);
920 : }
921 28 : return nTotalSize;
922 : }
923 :
924 : case wkbMultiPoint:
925 : case wkbMultiLineString:
926 : case wkbMultiPolygon:
927 : case wkbGeometryCollection:
928 : {
929 9 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
930 9 : int nTotalSize = 4;
931 9 : int nParts = poGeomCollection->getNumGeometries();
932 9 : memcpy(pabyData, &nParts, 4);
933 9 : if (NEED_SWAP_SPATIALITE())
934 0 : CPL_SWAP32PTR( pabyData );
935 :
936 19 : for(int i=0;i<nParts;i++)
937 : {
938 10 : pabyData[nTotalSize] = 0x69;
939 10 : nTotalSize ++;
940 : int nCode;
941 10 : switch (wkbFlatten(poGeomCollection->getGeometryRef(i)->getGeometryType()))
942 : {
943 3 : case wkbPoint: nCode = 1; break;
944 2 : case wkbLineString: nCode = 2; break;
945 5 : case wkbPolygon: nCode = 3; break;
946 0 : default: CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type"); return 0;
947 : }
948 10 : memcpy(pabyData + nTotalSize, &nCode, 4);
949 10 : if (NEED_SWAP_SPATIALITE())
950 0 : CPL_SWAP32PTR( pabyData + nTotalSize );
951 10 : nTotalSize += 4;
952 : nTotalSize += ExportSpatiaLiteGeometryInternal(poGeomCollection->getGeometryRef(i),
953 10 : eByteOrder, pabyData + nTotalSize);
954 : }
955 9 : return nTotalSize;
956 : }
957 :
958 : default:
959 0 : return 0;
960 : }
961 : }
962 :
963 :
964 : OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
965 : GInt32 nSRID,
966 : OGRwkbByteOrder eByteOrder,
967 : GByte **ppabyData,
968 137 : int *pnDataLenght )
969 :
970 : {
971 137 : int nDataLen = 44 + ComputeSpatiaLiteGeometrySize(poGeometry);
972 137 : OGREnvelope sEnvelope;
973 :
974 137 : *ppabyData = (GByte *) CPLMalloc( nDataLen );
975 :
976 137 : (*ppabyData)[0] = 0x00;
977 137 : (*ppabyData)[1] = eByteOrder;
978 :
979 : // Write out SRID
980 137 : memcpy( *ppabyData + 2, &nSRID, 4 );
981 :
982 : // Write out the geometry bounding rectangle
983 137 : poGeometry->getEnvelope( &sEnvelope );
984 137 : memcpy( *ppabyData + 6, &sEnvelope.MinX, 8 );
985 137 : memcpy( *ppabyData + 14, &sEnvelope.MinY, 8 );
986 137 : memcpy( *ppabyData + 22, &sEnvelope.MaxX, 8 );
987 137 : memcpy( *ppabyData + 30, &sEnvelope.MaxY, 8 );
988 :
989 137 : (*ppabyData)[38] = 0x7C;
990 :
991 137 : int nCode = 0;
992 137 : switch (wkbFlatten(poGeometry->getGeometryType()))
993 : {
994 : case wkbPoint:
995 103 : nCode = 1;
996 103 : break;
997 :
998 : case wkbLineString:
999 : case wkbLinearRing:
1000 2 : nCode = 2;
1001 2 : break;
1002 :
1003 : case wkbPolygon:
1004 23 : nCode = 3;
1005 23 : break;
1006 :
1007 : case wkbMultiPoint:
1008 2 : nCode = 4;
1009 2 : break;
1010 :
1011 : case wkbMultiLineString:
1012 2 : nCode = 5;
1013 2 : break;
1014 :
1015 : case wkbMultiPolygon:
1016 2 : nCode = 6;
1017 2 : break;
1018 :
1019 : case wkbGeometryCollection:
1020 3 : nCode = 7;
1021 3 : break;
1022 :
1023 : default:
1024 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
1025 0 : CPLFree(*ppabyData);
1026 0 : *ppabyData = NULL;
1027 0 : *pnDataLenght = 0;
1028 0 : return CE_Failure;
1029 : }
1030 137 : memcpy( *ppabyData + 39, &nCode, 4 );
1031 :
1032 137 : int nWritten = ExportSpatiaLiteGeometryInternal(poGeometry, eByteOrder, *ppabyData + 43);
1033 137 : if (nWritten == 0)
1034 : {
1035 0 : CPLFree(*ppabyData);
1036 0 : *ppabyData = NULL;
1037 0 : *pnDataLenght = 0;
1038 0 : return CE_Failure;
1039 : }
1040 :
1041 137 : (*ppabyData)[nDataLen - 1] = 0xFE;
1042 :
1043 137 : if( NEED_SWAP_SPATIALITE() )
1044 : {
1045 0 : CPL_SWAP32PTR( *ppabyData + 2 );
1046 0 : CPL_SWAP64PTR( *ppabyData + 6 );
1047 0 : CPL_SWAP64PTR( *ppabyData + 14 );
1048 0 : CPL_SWAP64PTR( *ppabyData + 22 );
1049 0 : CPL_SWAP64PTR( *ppabyData + 30 );
1050 0 : CPL_SWAP32PTR( *ppabyData + 39 );
1051 : }
1052 :
1053 137 : *pnDataLenght = nDataLen;
1054 :
1055 137 : return CE_None;
1056 : }
1057 :
1058 : /************************************************************************/
1059 : /* TestCapability() */
1060 : /************************************************************************/
1061 :
1062 2 : int OGRSQLiteLayer::TestCapability( const char * pszCap )
1063 :
1064 : {
1065 2 : if( EQUAL(pszCap,OLCRandomRead) )
1066 0 : return FALSE;
1067 :
1068 2 : else if( EQUAL(pszCap,OLCFastFeatureCount) )
1069 0 : return FALSE;
1070 :
1071 2 : else if( EQUAL(pszCap,OLCFastSpatialFilter) )
1072 0 : return FALSE;
1073 :
1074 2 : else if( EQUAL(pszCap,OLCTransactions) )
1075 2 : return TRUE;
1076 :
1077 : else
1078 0 : return FALSE;
1079 : }
1080 :
1081 : /************************************************************************/
1082 : /* GetSpatialRef() */
1083 : /************************************************************************/
1084 :
1085 30 : OGRSpatialReference *OGRSQLiteLayer::GetSpatialRef()
1086 :
1087 : {
1088 30 : return poSRS;
1089 : }
1090 :
1091 : /************************************************************************/
1092 : /* StartTransaction() */
1093 : /************************************************************************/
1094 :
1095 7 : OGRErr OGRSQLiteLayer::StartTransaction()
1096 :
1097 : {
1098 7 : return poDS->SoftStartTransaction();
1099 : }
1100 :
1101 : /************************************************************************/
1102 : /* CommitTransaction() */
1103 : /************************************************************************/
1104 :
1105 6 : OGRErr OGRSQLiteLayer::CommitTransaction()
1106 :
1107 : {
1108 6 : return poDS->SoftCommit();
1109 : }
1110 :
1111 : /************************************************************************/
1112 : /* RollbackTransaction() */
1113 : /************************************************************************/
1114 :
1115 1 : OGRErr OGRSQLiteLayer::RollbackTransaction()
1116 :
1117 : {
1118 1 : return poDS->SoftRollback();
1119 : }
1120 :
1121 : /************************************************************************/
1122 : /* ClearStatement() */
1123 : /************************************************************************/
1124 :
1125 1309 : void OGRSQLiteLayer::ClearStatement()
1126 :
1127 : {
1128 1309 : if( hStmt != NULL )
1129 : {
1130 168 : CPLDebug( "OGR_SQLITE", "finalize %p", hStmt );
1131 168 : sqlite3_finalize( hStmt );
1132 168 : hStmt = NULL;
1133 : }
1134 1309 : }
|