1 : /******************************************************************************
2 : * $Id: ogrdatasource.cpp 19745 2010-05-21 21:41:30Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: The generic portions of the OGRDataSource class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Les Technologies SoftMap Inc.
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogrsf_frmts.h"
31 : #include "ogr_api.h"
32 : #include "ogr_p.h"
33 : #include "ogr_gensql.h"
34 : #include "ogr_attrind.h"
35 : #include "cpl_multiproc.h"
36 :
37 : CPL_CVSID("$Id: ogrdatasource.cpp 19745 2010-05-21 21:41:30Z rouault $");
38 :
39 : /************************************************************************/
40 : /* ~OGRDataSource() */
41 : /************************************************************************/
42 :
43 4754 : OGRDataSource::OGRDataSource()
44 :
45 : {
46 4754 : m_poStyleTable = NULL;
47 4754 : m_nRefCount = 0;
48 4754 : m_poDriver = NULL;
49 4754 : m_hMutex = NULL;
50 4754 : }
51 :
52 : /************************************************************************/
53 : /* ~OGRDataSource() */
54 : /************************************************************************/
55 :
56 4754 : OGRDataSource::~OGRDataSource()
57 :
58 : {
59 4754 : if ( m_poStyleTable )
60 : {
61 1 : delete m_poStyleTable;
62 1 : m_poStyleTable = NULL;
63 : }
64 :
65 4754 : if( m_hMutex != NULL )
66 292 : CPLDestroyMutex( m_hMutex );
67 4754 : }
68 :
69 : /************************************************************************/
70 : /* DestroyDataSource() */
71 : /************************************************************************/
72 :
73 101 : void OGRDataSource::DestroyDataSource( OGRDataSource *poDS )
74 :
75 : {
76 101 : delete poDS;
77 101 : }
78 :
79 : /************************************************************************/
80 : /* OGR_DS_Destroy() */
81 : /************************************************************************/
82 :
83 20 : void OGR_DS_Destroy( OGRDataSourceH hDS )
84 :
85 : {
86 20 : VALIDATE_POINTER0( hDS, "OGR_DS_Destroy" );
87 20 : delete (OGRDataSource *) hDS;
88 : }
89 :
90 : /************************************************************************/
91 : /* Release() */
92 : /************************************************************************/
93 :
94 0 : OGRErr OGRDataSource::Release()
95 :
96 : {
97 0 : return OGRSFDriverRegistrar::GetRegistrar()->ReleaseDataSource( this );
98 : }
99 :
100 : /************************************************************************/
101 : /* Reference() */
102 : /************************************************************************/
103 :
104 542 : int OGRDataSource::Reference()
105 :
106 : {
107 542 : return ++m_nRefCount;
108 : }
109 :
110 : /************************************************************************/
111 : /* OGR_DS_Reference() */
112 : /************************************************************************/
113 :
114 0 : int OGR_DS_Reference( OGRDataSourceH hDataSource )
115 :
116 : {
117 0 : VALIDATE_POINTER1( hDataSource, "OGR_DS_Reference", 0 );
118 :
119 0 : return ((OGRDataSource *) hDataSource)->Reference();
120 : }
121 :
122 : /************************************************************************/
123 : /* Dereference() */
124 : /************************************************************************/
125 :
126 24 : int OGRDataSource::Dereference()
127 :
128 : {
129 24 : return --m_nRefCount;
130 : }
131 :
132 : /************************************************************************/
133 : /* OGR_DS_Dereference() */
134 : /************************************************************************/
135 :
136 0 : int OGR_DS_Dereference( OGRDataSourceH hDataSource )
137 :
138 : {
139 0 : VALIDATE_POINTER1( hDataSource, "OGR_DS_Dereference", 0 );
140 :
141 0 : return ((OGRDataSource *) hDataSource)->Dereference();
142 : }
143 :
144 : /************************************************************************/
145 : /* GetRefCount() */
146 : /************************************************************************/
147 :
148 44 : int OGRDataSource::GetRefCount() const
149 :
150 : {
151 44 : return m_nRefCount;
152 : }
153 :
154 : /************************************************************************/
155 : /* OGR_DS_GetRefCount() */
156 : /************************************************************************/
157 :
158 4 : int OGR_DS_GetRefCount( OGRDataSourceH hDataSource )
159 :
160 : {
161 4 : VALIDATE_POINTER1( hDataSource, "OGR_DS_GetRefCount", 0 );
162 :
163 4 : return ((OGRDataSource *) hDataSource)->GetRefCount();
164 : }
165 :
166 : /************************************************************************/
167 : /* GetSummaryRefCount() */
168 : /************************************************************************/
169 :
170 10 : int OGRDataSource::GetSummaryRefCount() const
171 :
172 : {
173 10 : CPLMutexHolderD( (void **) &m_hMutex );
174 10 : int nSummaryCount = m_nRefCount;
175 : int iLayer;
176 10 : OGRDataSource *poUseThis = (OGRDataSource *) this;
177 :
178 20 : for( iLayer=0; iLayer < poUseThis->GetLayerCount(); iLayer++ )
179 10 : nSummaryCount += poUseThis->GetLayer( iLayer )->GetRefCount();
180 :
181 10 : return nSummaryCount;
182 : }
183 :
184 : /************************************************************************/
185 : /* OGR_DS_GetSummaryRefCount() */
186 : /************************************************************************/
187 :
188 0 : int OGR_DS_GetSummaryRefCount( OGRDataSourceH hDataSource )
189 :
190 : {
191 0 : VALIDATE_POINTER1( hDataSource, "OGR_DS_GetSummaryRefCount", 0 );
192 :
193 0 : return ((OGRDataSource *) hDataSource)->GetSummaryRefCount();
194 : }
195 :
196 : /************************************************************************/
197 : /* CreateLayer() */
198 : /************************************************************************/
199 :
200 : OGRLayer *OGRDataSource::CreateLayer( const char * pszName,
201 : OGRSpatialReference * poSpatialRef,
202 : OGRwkbGeometryType eGType,
203 0 : char **papszOptions )
204 :
205 : {
206 : (void) eGType;
207 : (void) poSpatialRef;
208 : (void) pszName;
209 : (void) papszOptions;
210 :
211 : CPLError( CE_Failure, CPLE_NotSupported,
212 0 : "CreateLayer() not supported by this data source." );
213 :
214 0 : return NULL;
215 : }
216 :
217 : /************************************************************************/
218 : /* OGR_DS_CreateLayer() */
219 : /************************************************************************/
220 :
221 : OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
222 : const char * pszName,
223 : OGRSpatialReferenceH hSpatialRef,
224 : OGRwkbGeometryType eType,
225 237 : char ** papszOptions )
226 :
227 : {
228 237 : VALIDATE_POINTER1( hDS, "OGR_DS_CreateLayer", NULL );
229 :
230 237 : if (pszName == NULL)
231 : {
232 0 : CPLError ( CE_Failure, CPLE_ObjectNull, "Name was NULL in OGR_DS_CreateLayer");
233 0 : return 0;
234 : }
235 : return (OGRLayerH) ((OGRDataSource *)hDS)->CreateLayer(
236 237 : pszName, (OGRSpatialReference *) hSpatialRef, eType, papszOptions );
237 : }
238 :
239 : /************************************************************************/
240 : /* CopyLayer() */
241 : /************************************************************************/
242 :
243 : OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
244 : const char *pszNewName,
245 2 : char **papszOptions )
246 :
247 : {
248 2 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
249 2 : OGRLayer *poDstLayer = NULL;
250 :
251 : /* -------------------------------------------------------------------- */
252 : /* Create the layer. */
253 : /* -------------------------------------------------------------------- */
254 2 : if( !TestCapability( ODsCCreateLayer ) )
255 : {
256 : CPLError( CE_Failure, CPLE_NotSupported,
257 0 : "This datasource does not support creation of layers." );
258 0 : return NULL;
259 : }
260 :
261 2 : CPLErrorReset();
262 : poDstLayer = CreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
263 2 : poSrcDefn->GetGeomType(), papszOptions );
264 :
265 2 : if( poDstLayer == NULL )
266 0 : return NULL;
267 :
268 : /* -------------------------------------------------------------------- */
269 : /* Add fields. Default to copy all field. */
270 : /* If only a subset of all fields requested, then output only */
271 : /* the selected fields, and in the order that they were */
272 : /* selected. */
273 : /* -------------------------------------------------------------------- */
274 : int iField;
275 :
276 10 : for( iField = 0; iField < poSrcDefn->GetFieldCount(); iField++ )
277 8 : poDstLayer->CreateField( poSrcDefn->GetFieldDefn(iField) );
278 :
279 : /* -------------------------------------------------------------------- */
280 : /* Check if the destination layer supports transactions and set a */
281 : /* default number of features in a single transaction. */
282 : /* -------------------------------------------------------------------- */
283 2 : int nGroupTransactions = 0;
284 2 : if( poDstLayer->TestCapability( OLCTransactions ) )
285 2 : nGroupTransactions = 128;
286 :
287 : /* -------------------------------------------------------------------- */
288 : /* Transfer features. */
289 : /* -------------------------------------------------------------------- */
290 : OGRFeature *poFeature;
291 :
292 2 : poSrcLayer->ResetReading();
293 :
294 2 : if( nGroupTransactions <= 0 )
295 : {
296 0 : while( TRUE )
297 : {
298 0 : OGRFeature *poDstFeature = NULL;
299 :
300 0 : poFeature = poSrcLayer->GetNextFeature();
301 :
302 0 : if( poFeature == NULL )
303 0 : break;
304 :
305 0 : CPLErrorReset();
306 0 : poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
307 :
308 0 : if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
309 : {
310 0 : delete poFeature;
311 : CPLError( CE_Failure, CPLE_AppDefined,
312 : "Unable to translate feature %ld from layer %s.\n",
313 0 : poFeature->GetFID(), poSrcDefn->GetName() );
314 0 : return poDstLayer;
315 : }
316 :
317 0 : poDstFeature->SetFID( poFeature->GetFID() );
318 :
319 0 : OGRFeature::DestroyFeature( poFeature );
320 :
321 0 : CPLErrorReset();
322 0 : if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
323 : {
324 0 : OGRFeature::DestroyFeature( poDstFeature );
325 0 : return poDstLayer;
326 : }
327 :
328 0 : OGRFeature::DestroyFeature( poDstFeature );
329 : }
330 : }
331 : else
332 : {
333 2 : int i, bStopTransfer = FALSE, bStopTransaction = FALSE;
334 2 : int nFeatCount = 0; // Number of features in the temporary array
335 2 : int nFeaturesToAdd = 0;
336 6 : while( !bStopTransfer )
337 : {
338 : OGRFeature **papoDstFeature =
339 2 : (OGRFeature **)CPLCalloc(sizeof(OGRFeature *), nGroupTransactions);
340 :
341 : /* -------------------------------------------------------------------- */
342 : /* Fill the array with features */
343 : /* -------------------------------------------------------------------- */
344 38 : for( nFeatCount = 0; nFeatCount < nGroupTransactions; nFeatCount++ )
345 : {
346 38 : poFeature = poSrcLayer->GetNextFeature();
347 :
348 38 : if( poFeature == NULL )
349 : {
350 2 : bStopTransfer = 1;
351 2 : break;
352 : }
353 :
354 36 : CPLErrorReset();
355 : papoDstFeature[nFeatCount] =
356 36 : OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
357 :
358 36 : if( papoDstFeature[nFeatCount]->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
359 : {
360 0 : OGRFeature::DestroyFeature( poFeature );
361 : CPLError( CE_Failure, CPLE_AppDefined,
362 : "Unable to translate feature %ld from layer %s.\n",
363 0 : poFeature->GetFID(), poSrcDefn->GetName() );
364 0 : bStopTransfer = TRUE;
365 0 : break;
366 : }
367 :
368 36 : papoDstFeature[nFeatCount]->SetFID( poFeature->GetFID() );
369 :
370 36 : OGRFeature::DestroyFeature( poFeature );
371 : }
372 2 : nFeaturesToAdd = nFeatCount;
373 :
374 2 : CPLErrorReset();
375 2 : bStopTransaction = FALSE;
376 6 : while( !bStopTransaction )
377 : {
378 2 : bStopTransaction = TRUE;
379 2 : poDstLayer->StartTransaction();
380 38 : for( i = 0; i < nFeaturesToAdd; i++ )
381 : {
382 36 : if( poDstLayer->CreateFeature( papoDstFeature[i] ) != OGRERR_NONE )
383 : {
384 0 : nFeaturesToAdd = i;
385 0 : bStopTransfer = TRUE;
386 0 : bStopTransaction = FALSE;
387 : }
388 : }
389 2 : if( bStopTransaction )
390 2 : poDstLayer->CommitTransaction();
391 : else
392 0 : poDstLayer->RollbackTransaction();
393 : }
394 :
395 38 : for( i = 0; i < nFeatCount; i++ )
396 36 : OGRFeature::DestroyFeature( papoDstFeature[i] );
397 : }
398 : }
399 2 : return poDstLayer;
400 : }
401 :
402 : /************************************************************************/
403 : /* OGR_DS_CopyLayer() */
404 : /************************************************************************/
405 :
406 : OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
407 : OGRLayerH hSrcLayer, const char *pszNewName,
408 2 : char **papszOptions )
409 :
410 : {
411 2 : VALIDATE_POINTER1( hDS, "OGR_DS_CopyLayer", NULL );
412 2 : VALIDATE_POINTER1( hSrcLayer, "OGR_DS_CopyLayer", NULL );
413 :
414 : return (OGRLayerH)
415 : ((OGRDataSource *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer,
416 2 : pszNewName, papszOptions );
417 : }
418 :
419 : /************************************************************************/
420 : /* DeleteLayer() */
421 : /************************************************************************/
422 :
423 0 : OGRErr OGRDataSource::DeleteLayer( int iLayer )
424 :
425 : {
426 : (void) iLayer;
427 : CPLError( CE_Failure, CPLE_NotSupported,
428 0 : "DeleteLayer() not supported by this data source." );
429 :
430 0 : return OGRERR_UNSUPPORTED_OPERATION;
431 : }
432 :
433 : /************************************************************************/
434 : /* OGR_DS_DeleteLayer() */
435 : /************************************************************************/
436 :
437 2 : OGRErr OGR_DS_DeleteLayer( OGRDataSourceH hDS, int iLayer )
438 :
439 : {
440 2 : VALIDATE_POINTER1( hDS, "OGR_DS_DeleteLayer", OGRERR_INVALID_HANDLE );
441 :
442 2 : return ((OGRDataSource *) hDS)->DeleteLayer( iLayer );
443 : }
444 :
445 : /************************************************************************/
446 : /* GetLayerByName() */
447 : /************************************************************************/
448 :
449 738 : OGRLayer *OGRDataSource::GetLayerByName( const char *pszName )
450 :
451 : {
452 738 : CPLMutexHolderD( &m_hMutex );
453 :
454 738 : if ( ! pszName )
455 0 : return NULL;
456 :
457 : int i;
458 :
459 : /* first a case sensitive check */
460 3962 : for( i = 0; i < GetLayerCount(); i++ )
461 : {
462 3914 : OGRLayer *poLayer = GetLayer(i);
463 :
464 3914 : if( strcmp( pszName, poLayer->GetLayerDefn()->GetName() ) == 0 )
465 690 : return poLayer;
466 : }
467 :
468 : /* then case insensitive */
469 353 : for( i = 0; i < GetLayerCount(); i++ )
470 : {
471 308 : OGRLayer *poLayer = GetLayer(i);
472 :
473 308 : if( EQUAL( pszName, poLayer->GetLayerDefn()->GetName() ) )
474 3 : return poLayer;
475 : }
476 :
477 45 : return NULL;
478 : }
479 :
480 : /************************************************************************/
481 : /* OGR_DS_GetLayerByName() */
482 : /************************************************************************/
483 :
484 551 : OGRLayerH OGR_DS_GetLayerByName( OGRDataSourceH hDS, const char *pszName )
485 :
486 : {
487 551 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayerByName", NULL );
488 :
489 551 : return (OGRLayerH) ((OGRDataSource *) hDS)->GetLayerByName( pszName );
490 : }
491 :
492 : /************************************************************************/
493 : /* ProcessSQLCreateIndex() */
494 : /* */
495 : /* The correct syntax for creating an index in our dialect of */
496 : /* SQL is: */
497 : /* */
498 : /* CREATE INDEX ON <layername> USING <columnname> */
499 : /************************************************************************/
500 :
501 4 : OGRErr OGRDataSource::ProcessSQLCreateIndex( const char *pszSQLCommand )
502 :
503 : {
504 4 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
505 :
506 : /* -------------------------------------------------------------------- */
507 : /* Do some general syntax checking. */
508 : /* -------------------------------------------------------------------- */
509 4 : if( CSLCount(papszTokens) != 6
510 : || !EQUAL(papszTokens[0],"CREATE")
511 : || !EQUAL(papszTokens[1],"INDEX")
512 : || !EQUAL(papszTokens[2],"ON")
513 : || !EQUAL(papszTokens[4],"USING") )
514 : {
515 0 : CSLDestroy( papszTokens );
516 : CPLError( CE_Failure, CPLE_AppDefined,
517 : "Syntax error in CREATE INDEX command.\n"
518 : "Was '%s'\n"
519 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
520 0 : pszSQLCommand );
521 0 : return OGRERR_FAILURE;
522 : }
523 :
524 : /* -------------------------------------------------------------------- */
525 : /* Find the named layer. */
526 : /* -------------------------------------------------------------------- */
527 : int i;
528 4 : OGRLayer *poLayer = NULL;
529 :
530 : {
531 4 : CPLMutexHolderD( &m_hMutex );
532 :
533 4 : for( i = 0; i < GetLayerCount(); i++ )
534 : {
535 4 : poLayer = GetLayer(i);
536 :
537 4 : if( EQUAL(poLayer->GetLayerDefn()->GetName(),papszTokens[3]) )
538 4 : break;
539 : }
540 :
541 4 : if( i >= GetLayerCount() )
542 : {
543 : CPLError( CE_Failure, CPLE_AppDefined,
544 : "CREATE INDEX ON failed, no such layer as `%s'.",
545 0 : papszTokens[3] );
546 0 : CSLDestroy( papszTokens );
547 0 : return OGRERR_FAILURE;
548 0 : }
549 : }
550 :
551 : /* -------------------------------------------------------------------- */
552 : /* Does this layer even support attribute indexes? */
553 : /* -------------------------------------------------------------------- */
554 4 : if( poLayer->GetIndex() == NULL )
555 : {
556 : CPLError( CE_Failure, CPLE_AppDefined,
557 0 : "CREATE INDEX ON not supported by this driver." );
558 0 : CSLDestroy( papszTokens );
559 0 : return OGRERR_FAILURE;
560 : }
561 :
562 : /* -------------------------------------------------------------------- */
563 : /* Find the named field. */
564 : /* -------------------------------------------------------------------- */
565 6 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
566 : {
567 6 : if( EQUAL(papszTokens[5],
568 : poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
569 4 : break;
570 : }
571 :
572 4 : CSLDestroy( papszTokens );
573 :
574 4 : if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
575 : {
576 : CPLError( CE_Failure, CPLE_AppDefined,
577 : "`%s' failed, field not found.",
578 0 : pszSQLCommand );
579 0 : return OGRERR_FAILURE;
580 : }
581 :
582 : /* -------------------------------------------------------------------- */
583 : /* Attempt to create the index. */
584 : /* -------------------------------------------------------------------- */
585 : OGRErr eErr;
586 :
587 4 : eErr = poLayer->GetIndex()->CreateIndex( i );
588 4 : if( eErr == OGRERR_NONE )
589 4 : eErr = poLayer->GetIndex()->IndexAllFeatures( i );
590 : else
591 : {
592 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
593 : CPLError( CE_Failure, CPLE_AppDefined,
594 0 : "Cannot '%s'", pszSQLCommand);
595 : }
596 :
597 4 : return eErr;
598 : }
599 :
600 : /************************************************************************/
601 : /* ProcessSQLDropIndex() */
602 : /* */
603 : /* The correct syntax for droping one or more indexes in */
604 : /* the OGR SQL dialect is: */
605 : /* */
606 : /* DROP INDEX ON <layername> [USING <columnname>] */
607 : /************************************************************************/
608 :
609 2 : OGRErr OGRDataSource::ProcessSQLDropIndex( const char *pszSQLCommand )
610 :
611 : {
612 2 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
613 :
614 : /* -------------------------------------------------------------------- */
615 : /* Do some general syntax checking. */
616 : /* -------------------------------------------------------------------- */
617 2 : if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
618 : || !EQUAL(papszTokens[0],"DROP")
619 : || !EQUAL(papszTokens[1],"INDEX")
620 : || !EQUAL(papszTokens[2],"ON")
621 : || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4],"USING")) )
622 : {
623 0 : CSLDestroy( papszTokens );
624 : CPLError( CE_Failure, CPLE_AppDefined,
625 : "Syntax error in DROP INDEX command.\n"
626 : "Was '%s'\n"
627 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
628 0 : pszSQLCommand );
629 0 : return OGRERR_FAILURE;
630 : }
631 :
632 : /* -------------------------------------------------------------------- */
633 : /* Find the named layer. */
634 : /* -------------------------------------------------------------------- */
635 : int i;
636 2 : OGRLayer *poLayer=NULL;
637 :
638 : {
639 2 : CPLMutexHolderD( &m_hMutex );
640 :
641 2 : for( i = 0; i < GetLayerCount(); i++ )
642 : {
643 2 : poLayer = GetLayer(i);
644 :
645 2 : if( EQUAL(poLayer->GetLayerDefn()->GetName(),papszTokens[3]) )
646 2 : break;
647 : }
648 :
649 2 : if( i >= GetLayerCount() )
650 : {
651 : CPLError( CE_Failure, CPLE_AppDefined,
652 : "CREATE INDEX ON failed, no such layer as `%s'.",
653 0 : papszTokens[3] );
654 0 : CSLDestroy( papszTokens );
655 0 : return OGRERR_FAILURE;
656 0 : }
657 : }
658 :
659 : /* -------------------------------------------------------------------- */
660 : /* Does this layer even support attribute indexes? */
661 : /* -------------------------------------------------------------------- */
662 2 : if( poLayer->GetIndex() == NULL )
663 : {
664 : CPLError( CE_Failure, CPLE_AppDefined,
665 0 : "Indexes not supported by this driver." );
666 0 : CSLDestroy( papszTokens );
667 0 : return OGRERR_FAILURE;
668 : }
669 :
670 : /* -------------------------------------------------------------------- */
671 : /* If we weren't given a field name, drop all indexes. */
672 : /* -------------------------------------------------------------------- */
673 : OGRErr eErr;
674 :
675 2 : if( CSLCount(papszTokens) == 4 )
676 : {
677 0 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
678 : {
679 : OGRAttrIndex *poAttrIndex;
680 :
681 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
682 0 : if( poAttrIndex != NULL )
683 : {
684 0 : eErr = poLayer->GetIndex()->DropIndex( i );
685 0 : if( eErr != OGRERR_NONE )
686 0 : return eErr;
687 : }
688 : }
689 :
690 0 : CSLDestroy(papszTokens);
691 0 : return OGRERR_NONE;
692 : }
693 :
694 : /* -------------------------------------------------------------------- */
695 : /* Find the named field. */
696 : /* -------------------------------------------------------------------- */
697 3 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
698 : {
699 3 : if( EQUAL(papszTokens[5],
700 : poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
701 2 : break;
702 : }
703 :
704 2 : CSLDestroy( papszTokens );
705 :
706 2 : if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
707 : {
708 : CPLError( CE_Failure, CPLE_AppDefined,
709 : "`%s' failed, field not found.",
710 0 : pszSQLCommand );
711 0 : return OGRERR_FAILURE;
712 : }
713 :
714 : /* -------------------------------------------------------------------- */
715 : /* Attempt to drop the index. */
716 : /* -------------------------------------------------------------------- */
717 2 : eErr = poLayer->GetIndex()->DropIndex( i );
718 :
719 2 : return eErr;
720 : }
721 :
722 : /************************************************************************/
723 : /* ExecuteSQL() */
724 : /************************************************************************/
725 :
726 : OGRLayer * OGRDataSource::ExecuteSQL( const char *pszStatement,
727 : OGRGeometry *poSpatialFilter,
728 70 : const char *pszDialect )
729 :
730 : {
731 : const char *pszError;
732 70 : swq_select *psSelectInfo = NULL;
733 :
734 : (void) pszDialect;
735 :
736 : swq_field_list sFieldList;
737 70 : int nFIDIndex = 0;
738 70 : OGRGenSQLResultsLayer *poResults = NULL;
739 :
740 70 : memset( &sFieldList, 0, sizeof(sFieldList) );
741 :
742 : /* -------------------------------------------------------------------- */
743 : /* Handle CREATE INDEX statements specially. */
744 : /* -------------------------------------------------------------------- */
745 70 : if( EQUALN(pszStatement,"CREATE INDEX",12) )
746 : {
747 4 : ProcessSQLCreateIndex( pszStatement );
748 4 : return NULL;
749 : }
750 :
751 : /* -------------------------------------------------------------------- */
752 : /* Handle DROP INDEX statements specially. */
753 : /* -------------------------------------------------------------------- */
754 66 : if( EQUALN(pszStatement,"DROP INDEX",10) )
755 : {
756 2 : ProcessSQLDropIndex( pszStatement );
757 2 : return NULL;
758 : }
759 :
760 : /* -------------------------------------------------------------------- */
761 : /* Preparse the SQL statement. */
762 : /* -------------------------------------------------------------------- */
763 64 : pszError = swq_select_preparse( pszStatement, &psSelectInfo );
764 64 : if( pszError != NULL )
765 : {
766 : CPLError( CE_Failure, CPLE_AppDefined,
767 1 : "SQL: %s", pszError );
768 1 : return NULL;
769 : }
770 :
771 : /* -------------------------------------------------------------------- */
772 : /* Validate that all the source tables are recognised, count */
773 : /* fields. */
774 : /* -------------------------------------------------------------------- */
775 63 : int nFieldCount = 0, iTable, iField;
776 : int iEDS;
777 63 : int nExtraDSCount = 0;
778 63 : OGRDataSource** papoExtraDS = NULL;
779 63 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
780 :
781 140 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
782 : {
783 77 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
784 : OGRLayer *poSrcLayer;
785 77 : OGRDataSource *poTableDS = this;
786 :
787 77 : if( psTableDef->data_source != NULL )
788 : {
789 : poTableDS = (OGRDataSource *)
790 4 : OGROpenShared( psTableDef->data_source, FALSE, NULL );
791 4 : if( poTableDS == NULL )
792 : {
793 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
794 : CPLError( CE_Failure, CPLE_AppDefined,
795 : "Unable to open secondary datasource\n"
796 : "`%s' required by JOIN.",
797 0 : psTableDef->data_source );
798 :
799 0 : swq_select_free( psSelectInfo );
800 0 : goto end;
801 : }
802 :
803 : /* Keep in an array to release at the end of this function */
804 : papoExtraDS = (OGRDataSource** )CPLRealloc(papoExtraDS,
805 4 : sizeof(OGRDataSource*) * (nExtraDSCount + 1));
806 4 : papoExtraDS[nExtraDSCount++] = poTableDS;
807 : }
808 :
809 77 : poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
810 :
811 77 : if( poSrcLayer == NULL )
812 : {
813 : CPLError( CE_Failure, CPLE_AppDefined,
814 : "SELECT from table %s failed, no such table/featureclass.",
815 0 : psTableDef->table_name );
816 0 : swq_select_free( psSelectInfo );
817 0 : goto end;
818 : }
819 :
820 77 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
821 : }
822 :
823 : /* -------------------------------------------------------------------- */
824 : /* Build the field list for all indicated tables. */
825 : /* -------------------------------------------------------------------- */
826 :
827 63 : sFieldList.table_count = psSelectInfo->table_count;
828 63 : sFieldList.table_defs = psSelectInfo->table_defs;
829 :
830 63 : sFieldList.count = 0;
831 63 : sFieldList.names = (char **) CPLMalloc( sizeof(char *) * (nFieldCount+SPECIAL_FIELD_COUNT) );
832 : sFieldList.types = (swq_field_type *)
833 63 : CPLMalloc( sizeof(swq_field_type) * (nFieldCount+SPECIAL_FIELD_COUNT) );
834 : sFieldList.table_ids = (int *)
835 63 : CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
836 : sFieldList.ids = (int *)
837 63 : CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
838 :
839 140 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
840 : {
841 77 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
842 77 : OGRDataSource *poTableDS = this;
843 : OGRLayer *poSrcLayer;
844 :
845 77 : if( psTableDef->data_source != NULL )
846 : {
847 : poTableDS = (OGRDataSource *)
848 4 : OGROpenShared( psTableDef->data_source, FALSE, NULL );
849 4 : CPLAssert( poTableDS != NULL );
850 4 : poTableDS->Dereference();
851 : }
852 :
853 77 : poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
854 :
855 300 : for( iField = 0;
856 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
857 : iField++ )
858 : {
859 223 : OGRFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
860 223 : int iOutField = sFieldList.count++;
861 223 : sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
862 223 : if( poFDefn->GetType() == OFTInteger )
863 44 : sFieldList.types[iOutField] = SWQ_INTEGER;
864 179 : else if( poFDefn->GetType() == OFTReal )
865 76 : sFieldList.types[iOutField] = SWQ_FLOAT;
866 103 : else if( poFDefn->GetType() == OFTString )
867 100 : sFieldList.types[iOutField] = SWQ_STRING;
868 : else
869 3 : sFieldList.types[iOutField] = SWQ_OTHER;
870 :
871 223 : sFieldList.table_ids[iOutField] = iTable;
872 223 : sFieldList.ids[iOutField] = iField;
873 : }
874 :
875 77 : if( iTable == 0 )
876 63 : nFIDIndex = poSrcLayer->GetLayerDefn()->GetFieldCount();
877 : }
878 :
879 : /* -------------------------------------------------------------------- */
880 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
881 : /* -------------------------------------------------------------------- */
882 : pszError =
883 63 : swq_select_expand_wildcard( psSelectInfo, &sFieldList );
884 :
885 63 : if( pszError != NULL )
886 : {
887 0 : swq_select_free( psSelectInfo );
888 : CPLError( CE_Failure, CPLE_AppDefined,
889 0 : "SQL: %s", pszError );
890 0 : goto end;
891 : }
892 :
893 378 : for (iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
894 : {
895 315 : sFieldList.names[sFieldList.count] = (char*) SpecialFieldNames[iField];
896 315 : sFieldList.types[sFieldList.count] = SpecialFieldTypes[iField];
897 315 : sFieldList.table_ids[sFieldList.count] = 0;
898 315 : sFieldList.ids[sFieldList.count] = nFIDIndex + iField;
899 315 : sFieldList.count++;
900 : }
901 :
902 : /* -------------------------------------------------------------------- */
903 : /* Finish the parse operation. */
904 : /* -------------------------------------------------------------------- */
905 :
906 63 : pszError = swq_select_parse( psSelectInfo, &sFieldList, 0 );
907 :
908 63 : if( pszError != NULL )
909 : {
910 0 : swq_select_free( psSelectInfo );
911 : CPLError( CE_Failure, CPLE_AppDefined,
912 0 : "SQL: %s", pszError );
913 0 : goto end;
914 : }
915 :
916 : /* -------------------------------------------------------------------- */
917 : /* Everything seems OK, try to instantiate a results layer. */
918 : /* -------------------------------------------------------------------- */
919 :
920 : poResults = new OGRGenSQLResultsLayer( this, psSelectInfo,
921 63 : poSpatialFilter );
922 :
923 : // Eventually, we should keep track of layers to cleanup.
924 :
925 63 : end:
926 63 : CPLFree( sFieldList.names );
927 63 : CPLFree( sFieldList.types );
928 63 : CPLFree( sFieldList.table_ids );
929 63 : CPLFree( sFieldList.ids );
930 :
931 : /* Release the datasets we have opened with OGROpenShared() */
932 : /* It is safe to do that as the 'new OGRGenSQLResultsLayer' itself */
933 : /* has taken a reference on them, which it will release in its */
934 : /* destructor */
935 67 : for(iEDS = 0; iEDS < nExtraDSCount; iEDS++)
936 4 : poReg->ReleaseDataSource( papoExtraDS[iEDS] );
937 63 : CPLFree(papoExtraDS);
938 :
939 63 : return poResults;
940 : }
941 :
942 : /************************************************************************/
943 : /* OGR_DS_ExecuteSQL() */
944 : /************************************************************************/
945 :
946 : OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS,
947 : const char *pszStatement,
948 : OGRGeometryH hSpatialFilter,
949 651 : const char *pszDialect )
950 :
951 : {
952 651 : VALIDATE_POINTER1( hDS, "OGR_DS_ExecuteSQL", NULL );
953 :
954 : return (OGRLayerH)
955 : ((OGRDataSource *)hDS)->ExecuteSQL( pszStatement,
956 : (OGRGeometry *) hSpatialFilter,
957 651 : pszDialect );
958 : }
959 :
960 : /************************************************************************/
961 : /* ReleaseResultSet() */
962 : /************************************************************************/
963 :
964 63 : void OGRDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
965 :
966 : {
967 63 : delete poResultsSet;
968 63 : }
969 :
970 : /************************************************************************/
971 : /* OGR_DS_ReleaseResultSet() */
972 : /************************************************************************/
973 :
974 244 : void OGR_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer )
975 :
976 : {
977 244 : VALIDATE_POINTER0( hDS, "OGR_DS_ReleaseResultSet" );
978 :
979 244 : ((OGRDataSource *) hDS)->ReleaseResultSet( (OGRLayer *) hLayer );
980 : }
981 :
982 : /************************************************************************/
983 : /* OGR_DS_TestCapability() */
984 : /************************************************************************/
985 :
986 26 : int OGR_DS_TestCapability( OGRDataSourceH hDS, const char *pszCap )
987 :
988 : {
989 26 : VALIDATE_POINTER1( hDS, "OGR_DS_TestCapability", 0 );
990 26 : VALIDATE_POINTER1( pszCap, "OGR_DS_TestCapability", 0 );
991 :
992 26 : return ((OGRDataSource *) hDS)->TestCapability( pszCap );
993 : }
994 :
995 : /************************************************************************/
996 : /* OGR_DS_GetLayerCount() */
997 : /************************************************************************/
998 :
999 148 : int OGR_DS_GetLayerCount( OGRDataSourceH hDS )
1000 :
1001 : {
1002 148 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayerCount", 0 );
1003 :
1004 148 : return ((OGRDataSource *)hDS)->GetLayerCount();
1005 : }
1006 :
1007 : /************************************************************************/
1008 : /* OGR_DS_GetLayer() */
1009 : /************************************************************************/
1010 :
1011 1336 : OGRLayerH OGR_DS_GetLayer( OGRDataSourceH hDS, int iLayer )
1012 :
1013 : {
1014 1336 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayer", NULL );
1015 :
1016 1336 : return (OGRLayerH) ((OGRDataSource*)hDS)->GetLayer( iLayer );
1017 : }
1018 :
1019 : /************************************************************************/
1020 : /* OGR_DS_GetName() */
1021 : /************************************************************************/
1022 :
1023 30 : const char *OGR_DS_GetName( OGRDataSourceH hDS )
1024 :
1025 : {
1026 30 : VALIDATE_POINTER1( hDS, "OGR_DS_GetName", NULL );
1027 :
1028 30 : return ((OGRDataSource*)hDS)->GetName();
1029 : }
1030 :
1031 : /************************************************************************/
1032 : /* SyncToDisk() */
1033 : /************************************************************************/
1034 :
1035 0 : OGRErr OGRDataSource::SyncToDisk()
1036 :
1037 : {
1038 0 : CPLMutexHolderD( &m_hMutex );
1039 : int i;
1040 : OGRErr eErr;
1041 :
1042 0 : for( i = 0; i < GetLayerCount(); i++ )
1043 : {
1044 0 : OGRLayer *poLayer = GetLayer(i);
1045 :
1046 0 : if( poLayer )
1047 : {
1048 0 : eErr = poLayer->SyncToDisk();
1049 0 : if( eErr != OGRERR_NONE )
1050 0 : return eErr;
1051 : }
1052 : }
1053 :
1054 0 : return OGRERR_NONE;
1055 : }
1056 :
1057 : /************************************************************************/
1058 : /* OGR_DS_SyncToDisk() */
1059 : /************************************************************************/
1060 :
1061 0 : OGRErr OGR_DS_SyncToDisk( OGRDataSourceH hDS )
1062 :
1063 : {
1064 0 : VALIDATE_POINTER1( hDS, "OGR_DS_SyncToDisk", OGRERR_INVALID_HANDLE );
1065 :
1066 0 : return ((OGRDataSource *) hDS)->SyncToDisk();
1067 : }
1068 :
1069 : /************************************************************************/
1070 : /* GetDriver() */
1071 : /************************************************************************/
1072 :
1073 1254 : OGRSFDriver *OGRDataSource::GetDriver() const
1074 :
1075 : {
1076 1254 : return m_poDriver;
1077 : }
1078 :
1079 : /************************************************************************/
1080 : /* OGR_DS_GetDriver() */
1081 : /************************************************************************/
1082 :
1083 14 : OGRSFDriverH OGR_DS_GetDriver( OGRDataSourceH hDS )
1084 :
1085 : {
1086 14 : VALIDATE_POINTER1( hDS, "OGR_DS_GetDriver", NULL );
1087 :
1088 14 : return (OGRSFDriverH) ((OGRDataSource *) hDS)->GetDriver();
1089 : }
1090 :
1091 : /************************************************************************/
1092 : /* SetDriver() */
1093 : /************************************************************************/
1094 :
1095 184 : void OGRDataSource::SetDriver( OGRSFDriver *poDriver )
1096 :
1097 : {
1098 184 : m_poDriver = poDriver;
1099 184 : }
1100 :
1101 : /************************************************************************/
1102 : /* GetStyleTable() */
1103 : /************************************************************************/
1104 :
1105 34 : OGRStyleTable *OGRDataSource::GetStyleTable()
1106 : {
1107 34 : return m_poStyleTable;
1108 : }
1109 :
1110 : /************************************************************************/
1111 : /* SetStyleTableDirectly() */
1112 : /************************************************************************/
1113 :
1114 0 : void OGRDataSource::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
1115 : {
1116 0 : if ( m_poStyleTable )
1117 0 : delete m_poStyleTable;
1118 0 : m_poStyleTable = poStyleTable;
1119 0 : }
1120 :
1121 : /************************************************************************/
1122 : /* SetStyleTable() */
1123 : /************************************************************************/
1124 :
1125 34 : void OGRDataSource::SetStyleTable(OGRStyleTable *poStyleTable)
1126 : {
1127 34 : if ( m_poStyleTable )
1128 0 : delete m_poStyleTable;
1129 34 : if ( poStyleTable )
1130 0 : m_poStyleTable = poStyleTable->Clone();
1131 34 : }
1132 :
1133 : /************************************************************************/
1134 : /* OGR_DS_GetStyleTable() */
1135 : /************************************************************************/
1136 :
1137 0 : OGRStyleTableH OGR_DS_GetStyleTable( OGRDataSourceH hDS )
1138 :
1139 : {
1140 0 : VALIDATE_POINTER1( hDS, "OGR_DS_GetStyleTable", NULL );
1141 :
1142 0 : return (OGRStyleTableH) ((OGRDataSource *) hDS)->GetStyleTable( );
1143 : }
1144 :
1145 : /************************************************************************/
1146 : /* OGR_DS_SetStyleTableDirectly() */
1147 : /************************************************************************/
1148 :
1149 : void OGR_DS_SetStyleTableDirectly( OGRDataSourceH hDS,
1150 0 : OGRStyleTableH hStyleTable )
1151 :
1152 : {
1153 0 : VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTableDirectly" );
1154 :
1155 0 : ((OGRDataSource *) hDS)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
1156 : }
1157 :
1158 : /************************************************************************/
1159 : /* OGR_DS_SetStyleTable() */
1160 : /************************************************************************/
1161 :
1162 0 : void OGR_DS_SetStyleTable( OGRDataSourceH hDS, OGRStyleTableH hStyleTable )
1163 :
1164 : {
1165 0 : VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTable" );
1166 0 : VALIDATE_POINTER0( hStyleTable, "OGR_DS_SetStyleTable" );
1167 :
1168 0 : ((OGRDataSource *) hDS)->SetStyleTable( (OGRStyleTable *) hStyleTable);
1169 : }
|