1 : /******************************************************************************
2 : * $Id: ogrdatasource.cpp 23403 2011-11-20 21:01:21Z ajolma $
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 "swq.h"
31 : #include "ogrsf_frmts.h"
32 : #include "ogr_api.h"
33 : #include "ogr_p.h"
34 : #include "ogr_gensql.h"
35 : #include "ogr_attrind.h"
36 : #include "cpl_multiproc.h"
37 :
38 : CPL_CVSID("$Id: ogrdatasource.cpp 23403 2011-11-20 21:01:21Z ajolma $");
39 :
40 : /************************************************************************/
41 : /* ~OGRDataSource() */
42 : /************************************************************************/
43 :
44 11460 : OGRDataSource::OGRDataSource()
45 :
46 : {
47 11460 : m_poStyleTable = NULL;
48 11460 : m_nRefCount = 0;
49 11460 : m_poDriver = NULL;
50 11460 : m_hMutex = NULL;
51 11460 : }
52 :
53 : /************************************************************************/
54 : /* ~OGRDataSource() */
55 : /************************************************************************/
56 :
57 11460 : OGRDataSource::~OGRDataSource()
58 :
59 : {
60 11460 : if ( m_poStyleTable )
61 : {
62 3 : delete m_poStyleTable;
63 3 : m_poStyleTable = NULL;
64 : }
65 :
66 11460 : if( m_hMutex != NULL )
67 614 : CPLDestroyMutex( m_hMutex );
68 11460 : }
69 :
70 : /************************************************************************/
71 : /* DestroyDataSource() */
72 : /************************************************************************/
73 :
74 348 : void OGRDataSource::DestroyDataSource( OGRDataSource *poDS )
75 :
76 : {
77 348 : delete poDS;
78 348 : }
79 :
80 : /************************************************************************/
81 : /* OGR_DS_Destroy() */
82 : /************************************************************************/
83 :
84 44 : void OGR_DS_Destroy( OGRDataSourceH hDS )
85 :
86 : {
87 44 : VALIDATE_POINTER0( hDS, "OGR_DS_Destroy" );
88 44 : delete (OGRDataSource *) hDS;
89 : }
90 :
91 : /************************************************************************/
92 : /* Release() */
93 : /************************************************************************/
94 :
95 0 : OGRErr OGRDataSource::Release()
96 :
97 : {
98 0 : return OGRSFDriverRegistrar::GetRegistrar()->ReleaseDataSource( this );
99 : }
100 :
101 : /************************************************************************/
102 : /* Reference() */
103 : /************************************************************************/
104 :
105 1061 : int OGRDataSource::Reference()
106 :
107 : {
108 1061 : return ++m_nRefCount;
109 : }
110 :
111 : /************************************************************************/
112 : /* OGR_DS_Reference() */
113 : /************************************************************************/
114 :
115 0 : int OGR_DS_Reference( OGRDataSourceH hDataSource )
116 :
117 : {
118 0 : VALIDATE_POINTER1( hDataSource, "OGR_DS_Reference", 0 );
119 :
120 0 : return ((OGRDataSource *) hDataSource)->Reference();
121 : }
122 :
123 : /************************************************************************/
124 : /* Dereference() */
125 : /************************************************************************/
126 :
127 42 : int OGRDataSource::Dereference()
128 :
129 : {
130 42 : return --m_nRefCount;
131 : }
132 :
133 : /************************************************************************/
134 : /* OGR_DS_Dereference() */
135 : /************************************************************************/
136 :
137 0 : int OGR_DS_Dereference( OGRDataSourceH hDataSource )
138 :
139 : {
140 0 : VALIDATE_POINTER1( hDataSource, "OGR_DS_Dereference", 0 );
141 :
142 0 : return ((OGRDataSource *) hDataSource)->Dereference();
143 : }
144 :
145 : /************************************************************************/
146 : /* GetRefCount() */
147 : /************************************************************************/
148 :
149 78 : int OGRDataSource::GetRefCount() const
150 :
151 : {
152 78 : return m_nRefCount;
153 : }
154 :
155 : /************************************************************************/
156 : /* OGR_DS_GetRefCount() */
157 : /************************************************************************/
158 :
159 4 : int OGR_DS_GetRefCount( OGRDataSourceH hDataSource )
160 :
161 : {
162 4 : VALIDATE_POINTER1( hDataSource, "OGR_DS_GetRefCount", 0 );
163 :
164 4 : return ((OGRDataSource *) hDataSource)->GetRefCount();
165 : }
166 :
167 : /************************************************************************/
168 : /* GetSummaryRefCount() */
169 : /************************************************************************/
170 :
171 13 : int OGRDataSource::GetSummaryRefCount() const
172 :
173 : {
174 13 : CPLMutexHolderD( (void **) &m_hMutex );
175 13 : int nSummaryCount = m_nRefCount;
176 : int iLayer;
177 13 : OGRDataSource *poUseThis = (OGRDataSource *) this;
178 :
179 26 : for( iLayer=0; iLayer < poUseThis->GetLayerCount(); iLayer++ )
180 13 : nSummaryCount += poUseThis->GetLayer( iLayer )->GetRefCount();
181 :
182 13 : return nSummaryCount;
183 : }
184 :
185 : /************************************************************************/
186 : /* OGR_DS_GetSummaryRefCount() */
187 : /************************************************************************/
188 :
189 0 : int OGR_DS_GetSummaryRefCount( OGRDataSourceH hDataSource )
190 :
191 : {
192 0 : VALIDATE_POINTER1( hDataSource, "OGR_DS_GetSummaryRefCount", 0 );
193 :
194 0 : return ((OGRDataSource *) hDataSource)->GetSummaryRefCount();
195 : }
196 :
197 : /************************************************************************/
198 : /* CreateLayer() */
199 : /************************************************************************/
200 :
201 0 : OGRLayer *OGRDataSource::CreateLayer( const char * pszName,
202 : OGRSpatialReference * poSpatialRef,
203 : OGRwkbGeometryType eGType,
204 : char **papszOptions )
205 :
206 : {
207 : (void) eGType;
208 : (void) poSpatialRef;
209 : (void) pszName;
210 : (void) papszOptions;
211 :
212 : CPLError( CE_Failure, CPLE_NotSupported,
213 0 : "CreateLayer() not supported by this data source." );
214 :
215 0 : return NULL;
216 : }
217 :
218 : /************************************************************************/
219 : /* OGR_DS_CreateLayer() */
220 : /************************************************************************/
221 :
222 1420 : OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
223 : const char * pszName,
224 : OGRSpatialReferenceH hSpatialRef,
225 : OGRwkbGeometryType eType,
226 : char ** papszOptions )
227 :
228 : {
229 1420 : VALIDATE_POINTER1( hDS, "OGR_DS_CreateLayer", NULL );
230 :
231 1420 : if (pszName == NULL)
232 : {
233 0 : CPLError ( CE_Failure, CPLE_ObjectNull, "Name was NULL in OGR_DS_CreateLayer");
234 0 : return 0;
235 : }
236 : return (OGRLayerH) ((OGRDataSource *)hDS)->CreateLayer(
237 1420 : pszName, (OGRSpatialReference *) hSpatialRef, eType, papszOptions );
238 : }
239 :
240 : /************************************************************************/
241 : /* CopyLayer() */
242 : /************************************************************************/
243 :
244 23 : OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
245 : const char *pszNewName,
246 : char **papszOptions )
247 :
248 : {
249 23 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
250 23 : OGRLayer *poDstLayer = NULL;
251 :
252 : /* -------------------------------------------------------------------- */
253 : /* Create the layer. */
254 : /* -------------------------------------------------------------------- */
255 23 : if( !TestCapability( ODsCCreateLayer ) )
256 : {
257 : CPLError( CE_Failure, CPLE_NotSupported,
258 0 : "This datasource does not support creation of layers." );
259 0 : return NULL;
260 : }
261 :
262 23 : CPLErrorReset();
263 23 : poDstLayer = CreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
264 46 : poSrcDefn->GetGeomType(), papszOptions );
265 :
266 23 : if( poDstLayer == NULL )
267 0 : return NULL;
268 :
269 : /* -------------------------------------------------------------------- */
270 : /* Add fields. Default to copy all field. */
271 : /* If only a subset of all fields requested, then output only */
272 : /* the selected fields, and in the order that they were */
273 : /* selected. */
274 : /* -------------------------------------------------------------------- */
275 : int iField;
276 :
277 51 : for( iField = 0; iField < poSrcDefn->GetFieldCount(); iField++ )
278 28 : poDstLayer->CreateField( poSrcDefn->GetFieldDefn(iField) );
279 :
280 : /* -------------------------------------------------------------------- */
281 : /* Check if the destination layer supports transactions and set a */
282 : /* default number of features in a single transaction. */
283 : /* -------------------------------------------------------------------- */
284 23 : int nGroupTransactions = 0;
285 23 : if( poDstLayer->TestCapability( OLCTransactions ) )
286 2 : nGroupTransactions = 128;
287 :
288 : /* -------------------------------------------------------------------- */
289 : /* Transfer features. */
290 : /* -------------------------------------------------------------------- */
291 : OGRFeature *poFeature;
292 :
293 23 : poSrcLayer->ResetReading();
294 :
295 23 : if( nGroupTransactions <= 0 )
296 : {
297 21 : while( TRUE )
298 : {
299 42 : OGRFeature *poDstFeature = NULL;
300 :
301 42 : poFeature = poSrcLayer->GetNextFeature();
302 :
303 42 : if( poFeature == NULL )
304 : break;
305 :
306 21 : CPLErrorReset();
307 21 : poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
308 :
309 21 : if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
310 : {
311 : CPLError( CE_Failure, CPLE_AppDefined,
312 : "Unable to translate feature %ld from layer %s.\n",
313 0 : poFeature->GetFID(), poSrcDefn->GetName() );
314 0 : OGRFeature::DestroyFeature( poFeature );
315 0 : return poDstLayer;
316 : }
317 :
318 21 : poDstFeature->SetFID( poFeature->GetFID() );
319 :
320 21 : OGRFeature::DestroyFeature( poFeature );
321 :
322 21 : CPLErrorReset();
323 21 : if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
324 : {
325 0 : OGRFeature::DestroyFeature( poDstFeature );
326 0 : return poDstLayer;
327 : }
328 :
329 21 : OGRFeature::DestroyFeature( poDstFeature );
330 : }
331 : }
332 : else
333 : {
334 2 : int i, bStopTransfer = FALSE, bStopTransaction = FALSE;
335 2 : int nFeatCount = 0; // Number of features in the temporary array
336 2 : int nFeaturesToAdd = 0;
337 : OGRFeature **papoDstFeature =
338 2 : (OGRFeature **)CPLCalloc(sizeof(OGRFeature *), nGroupTransactions);
339 6 : while( !bStopTransfer )
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 36 : 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 2 : CPLFree(papoDstFeature);
399 : }
400 23 : return poDstLayer;
401 : }
402 :
403 : /************************************************************************/
404 : /* OGR_DS_CopyLayer() */
405 : /************************************************************************/
406 :
407 2 : OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
408 : OGRLayerH hSrcLayer, const char *pszNewName,
409 : char **papszOptions )
410 :
411 : {
412 2 : VALIDATE_POINTER1( hDS, "OGR_DS_CopyLayer", NULL );
413 2 : VALIDATE_POINTER1( hSrcLayer, "OGR_DS_CopyLayer", NULL );
414 2 : VALIDATE_POINTER1( pszNewName, "OGR_DS_CopyLayer", NULL );
415 :
416 : return (OGRLayerH)
417 : ((OGRDataSource *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer,
418 2 : pszNewName, papszOptions );
419 : }
420 :
421 : /************************************************************************/
422 : /* DeleteLayer() */
423 : /************************************************************************/
424 :
425 0 : OGRErr OGRDataSource::DeleteLayer( int iLayer )
426 :
427 : {
428 : (void) iLayer;
429 : CPLError( CE_Failure, CPLE_NotSupported,
430 0 : "DeleteLayer() not supported by this data source." );
431 :
432 0 : return OGRERR_UNSUPPORTED_OPERATION;
433 : }
434 :
435 : /************************************************************************/
436 : /* OGR_DS_DeleteLayer() */
437 : /************************************************************************/
438 :
439 11 : OGRErr OGR_DS_DeleteLayer( OGRDataSourceH hDS, int iLayer )
440 :
441 : {
442 11 : VALIDATE_POINTER1( hDS, "OGR_DS_DeleteLayer", OGRERR_INVALID_HANDLE );
443 :
444 11 : return ((OGRDataSource *) hDS)->DeleteLayer( iLayer );
445 : }
446 :
447 : /************************************************************************/
448 : /* GetLayerByName() */
449 : /************************************************************************/
450 :
451 2537 : OGRLayer *OGRDataSource::GetLayerByName( const char *pszName )
452 :
453 : {
454 2537 : CPLMutexHolderD( &m_hMutex );
455 :
456 2537 : if ( ! pszName )
457 0 : return NULL;
458 :
459 : int i;
460 :
461 : /* first a case sensitive check */
462 259835 : for( i = 0; i < GetLayerCount(); i++ )
463 : {
464 259667 : OGRLayer *poLayer = GetLayer(i);
465 :
466 259667 : if( strcmp( pszName, poLayer->GetName() ) == 0 )
467 2369 : return poLayer;
468 : }
469 :
470 : /* then case insensitive */
471 898 : for( i = 0; i < GetLayerCount(); i++ )
472 : {
473 750 : OGRLayer *poLayer = GetLayer(i);
474 :
475 750 : if( EQUAL( pszName, poLayer->GetName() ) )
476 20 : return poLayer;
477 : }
478 :
479 148 : return NULL;
480 : }
481 :
482 : /************************************************************************/
483 : /* OGR_DS_GetLayerByName() */
484 : /************************************************************************/
485 :
486 1801 : OGRLayerH OGR_DS_GetLayerByName( OGRDataSourceH hDS, const char *pszName )
487 :
488 : {
489 1801 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayerByName", NULL );
490 :
491 1801 : return (OGRLayerH) ((OGRDataSource *) hDS)->GetLayerByName( pszName );
492 : }
493 :
494 : /************************************************************************/
495 : /* ProcessSQLCreateIndex() */
496 : /* */
497 : /* The correct syntax for creating an index in our dialect of */
498 : /* SQL is: */
499 : /* */
500 : /* CREATE INDEX ON <layername> USING <columnname> */
501 : /************************************************************************/
502 :
503 6 : OGRErr OGRDataSource::ProcessSQLCreateIndex( const char *pszSQLCommand )
504 :
505 : {
506 6 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Do some general syntax checking. */
510 : /* -------------------------------------------------------------------- */
511 30 : if( CSLCount(papszTokens) != 6
512 6 : || !EQUAL(papszTokens[0],"CREATE")
513 6 : || !EQUAL(papszTokens[1],"INDEX")
514 6 : || !EQUAL(papszTokens[2],"ON")
515 6 : || !EQUAL(papszTokens[4],"USING") )
516 : {
517 0 : CSLDestroy( papszTokens );
518 : CPLError( CE_Failure, CPLE_AppDefined,
519 : "Syntax error in CREATE INDEX command.\n"
520 : "Was '%s'\n"
521 : "Should be of form 'CREATE INDEX ON <table> USING <field>'",
522 0 : pszSQLCommand );
523 0 : return OGRERR_FAILURE;
524 : }
525 :
526 : /* -------------------------------------------------------------------- */
527 : /* Find the named layer. */
528 : /* -------------------------------------------------------------------- */
529 : int i;
530 6 : OGRLayer *poLayer = NULL;
531 :
532 : {
533 6 : CPLMutexHolderD( &m_hMutex );
534 :
535 6 : for( i = 0; i < GetLayerCount(); i++ )
536 : {
537 6 : poLayer = GetLayer(i);
538 :
539 6 : if( EQUAL(poLayer->GetName(),papszTokens[3]) )
540 6 : break;
541 : }
542 :
543 6 : if( i >= GetLayerCount() )
544 : {
545 : CPLError( CE_Failure, CPLE_AppDefined,
546 : "CREATE INDEX ON failed, no such layer as `%s'.",
547 0 : papszTokens[3] );
548 0 : CSLDestroy( papszTokens );
549 0 : return OGRERR_FAILURE;
550 0 : }
551 : }
552 :
553 : /* -------------------------------------------------------------------- */
554 : /* Does this layer even support attribute indexes? */
555 : /* -------------------------------------------------------------------- */
556 6 : if( poLayer->GetIndex() == NULL )
557 : {
558 : CPLError( CE_Failure, CPLE_AppDefined,
559 0 : "CREATE INDEX ON not supported by this driver." );
560 0 : CSLDestroy( papszTokens );
561 0 : return OGRERR_FAILURE;
562 : }
563 :
564 : /* -------------------------------------------------------------------- */
565 : /* Find the named field. */
566 : /* -------------------------------------------------------------------- */
567 9 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
568 : {
569 9 : if( EQUAL(papszTokens[5],
570 : poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
571 6 : break;
572 : }
573 :
574 6 : CSLDestroy( papszTokens );
575 :
576 6 : if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
577 : {
578 : CPLError( CE_Failure, CPLE_AppDefined,
579 : "`%s' failed, field not found.",
580 0 : pszSQLCommand );
581 0 : return OGRERR_FAILURE;
582 : }
583 :
584 : /* -------------------------------------------------------------------- */
585 : /* Attempt to create the index. */
586 : /* -------------------------------------------------------------------- */
587 : OGRErr eErr;
588 :
589 6 : eErr = poLayer->GetIndex()->CreateIndex( i );
590 6 : if( eErr == OGRERR_NONE )
591 6 : eErr = poLayer->GetIndex()->IndexAllFeatures( i );
592 : else
593 : {
594 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
595 : CPLError( CE_Failure, CPLE_AppDefined,
596 0 : "Cannot '%s'", pszSQLCommand);
597 : }
598 :
599 6 : return eErr;
600 : }
601 :
602 : /************************************************************************/
603 : /* ProcessSQLDropIndex() */
604 : /* */
605 : /* The correct syntax for droping one or more indexes in */
606 : /* the OGR SQL dialect is: */
607 : /* */
608 : /* DROP INDEX ON <layername> [USING <columnname>] */
609 : /************************************************************************/
610 :
611 2 : OGRErr OGRDataSource::ProcessSQLDropIndex( const char *pszSQLCommand )
612 :
613 : {
614 2 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Do some general syntax checking. */
618 : /* -------------------------------------------------------------------- */
619 10 : if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
620 2 : || !EQUAL(papszTokens[0],"DROP")
621 2 : || !EQUAL(papszTokens[1],"INDEX")
622 2 : || !EQUAL(papszTokens[2],"ON")
623 2 : || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4],"USING")) )
624 : {
625 0 : CSLDestroy( papszTokens );
626 : CPLError( CE_Failure, CPLE_AppDefined,
627 : "Syntax error in DROP INDEX command.\n"
628 : "Was '%s'\n"
629 : "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
630 0 : pszSQLCommand );
631 0 : return OGRERR_FAILURE;
632 : }
633 :
634 : /* -------------------------------------------------------------------- */
635 : /* Find the named layer. */
636 : /* -------------------------------------------------------------------- */
637 : int i;
638 2 : OGRLayer *poLayer=NULL;
639 :
640 : {
641 2 : CPLMutexHolderD( &m_hMutex );
642 :
643 2 : for( i = 0; i < GetLayerCount(); i++ )
644 : {
645 2 : poLayer = GetLayer(i);
646 :
647 2 : if( EQUAL(poLayer->GetName(),papszTokens[3]) )
648 2 : break;
649 : }
650 :
651 2 : if( i >= GetLayerCount() )
652 : {
653 : CPLError( CE_Failure, CPLE_AppDefined,
654 : "CREATE INDEX ON failed, no such layer as `%s'.",
655 0 : papszTokens[3] );
656 0 : CSLDestroy( papszTokens );
657 0 : return OGRERR_FAILURE;
658 0 : }
659 : }
660 :
661 : /* -------------------------------------------------------------------- */
662 : /* Does this layer even support attribute indexes? */
663 : /* -------------------------------------------------------------------- */
664 2 : if( poLayer->GetIndex() == NULL )
665 : {
666 : CPLError( CE_Failure, CPLE_AppDefined,
667 0 : "Indexes not supported by this driver." );
668 0 : CSLDestroy( papszTokens );
669 0 : return OGRERR_FAILURE;
670 : }
671 :
672 : /* -------------------------------------------------------------------- */
673 : /* If we weren't given a field name, drop all indexes. */
674 : /* -------------------------------------------------------------------- */
675 : OGRErr eErr;
676 :
677 2 : if( CSLCount(papszTokens) == 4 )
678 : {
679 0 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
680 : {
681 : OGRAttrIndex *poAttrIndex;
682 :
683 0 : poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
684 0 : if( poAttrIndex != NULL )
685 : {
686 0 : eErr = poLayer->GetIndex()->DropIndex( i );
687 0 : if( eErr != OGRERR_NONE )
688 0 : return eErr;
689 : }
690 : }
691 :
692 0 : CSLDestroy(papszTokens);
693 0 : return OGRERR_NONE;
694 : }
695 :
696 : /* -------------------------------------------------------------------- */
697 : /* Find the named field. */
698 : /* -------------------------------------------------------------------- */
699 3 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
700 : {
701 3 : if( EQUAL(papszTokens[5],
702 : poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
703 2 : break;
704 : }
705 :
706 2 : CSLDestroy( papszTokens );
707 :
708 2 : if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
709 : {
710 : CPLError( CE_Failure, CPLE_AppDefined,
711 : "`%s' failed, field not found.",
712 0 : pszSQLCommand );
713 0 : return OGRERR_FAILURE;
714 : }
715 :
716 : /* -------------------------------------------------------------------- */
717 : /* Attempt to drop the index. */
718 : /* -------------------------------------------------------------------- */
719 2 : eErr = poLayer->GetIndex()->DropIndex( i );
720 :
721 2 : return eErr;
722 : }
723 :
724 : /************************************************************************/
725 : /* ProcessSQLDropTable() */
726 : /* */
727 : /* The correct syntax for dropping a table (layer) in the OGR SQL */
728 : /* dialect is: */
729 : /* */
730 : /* DROP TABLE <layername> */
731 : /************************************************************************/
732 :
733 500 : OGRErr OGRDataSource::ProcessSQLDropTable( const char *pszSQLCommand )
734 :
735 : {
736 500 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
737 :
738 : /* -------------------------------------------------------------------- */
739 : /* Do some general syntax checking. */
740 : /* -------------------------------------------------------------------- */
741 1500 : if( CSLCount(papszTokens) != 3
742 500 : || !EQUAL(papszTokens[0],"DROP")
743 500 : || !EQUAL(papszTokens[1],"TABLE") )
744 : {
745 0 : CSLDestroy( papszTokens );
746 : CPLError( CE_Failure, CPLE_AppDefined,
747 : "Syntax error in DROP TABLE command.\n"
748 : "Was '%s'\n"
749 : "Should be of form 'DROP TABLE <table>'",
750 0 : pszSQLCommand );
751 0 : return OGRERR_FAILURE;
752 : }
753 :
754 : /* -------------------------------------------------------------------- */
755 : /* Find the named layer. */
756 : /* -------------------------------------------------------------------- */
757 : int i;
758 500 : OGRLayer *poLayer=NULL;
759 :
760 40199 : for( i = 0; i < GetLayerCount(); i++ )
761 : {
762 40199 : poLayer = GetLayer(i);
763 :
764 40199 : if( EQUAL(poLayer->GetName(),papszTokens[2]) )
765 500 : break;
766 : }
767 :
768 500 : if( i >= GetLayerCount() )
769 : {
770 : CPLError( CE_Failure, CPLE_AppDefined,
771 : "DROP TABLE failed, no such layer as `%s'.",
772 0 : papszTokens[2] );
773 0 : CSLDestroy( papszTokens );
774 0 : return OGRERR_FAILURE;
775 : }
776 :
777 500 : CSLDestroy( papszTokens );
778 :
779 : /* -------------------------------------------------------------------- */
780 : /* Delete it. */
781 : /* -------------------------------------------------------------------- */
782 :
783 500 : return DeleteLayer( i );
784 : }
785 :
786 : /************************************************************************/
787 : /* OGRDataSourceParseSQLType() */
788 : /************************************************************************/
789 :
790 : /* All arguments will be altered */
791 6 : static OGRFieldType OGRDataSourceParseSQLType(char* pszType, int& nWidth, int &nPrecision)
792 : {
793 6 : char* pszParenthesis = strchr(pszType, '(');
794 6 : if (pszParenthesis)
795 : {
796 4 : nWidth = atoi(pszParenthesis + 1);
797 4 : *pszParenthesis = '\0';
798 4 : char* pszComma = strchr(pszParenthesis + 1, ',');
799 4 : if (pszComma)
800 2 : nPrecision = atoi(pszComma + 1);
801 : }
802 :
803 6 : OGRFieldType eType = OFTString;
804 6 : if (EQUAL(pszType, "INTEGER"))
805 0 : eType = OFTInteger;
806 6 : else if (EQUAL(pszType, "INTEGER[]"))
807 0 : eType = OFTIntegerList;
808 8 : else if (EQUAL(pszType, "FLOAT") ||
809 : EQUAL(pszType, "NUMERIC") ||
810 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
811 : EQUAL(pszType, "REAL") /* unofficial alias */)
812 2 : eType = OFTReal;
813 4 : else if (EQUAL(pszType, "FLOAT[]") ||
814 : EQUAL(pszType, "NUMERIC[]") ||
815 : EQUAL(pszType, "DOUBLE[]") /* unofficial alias */ ||
816 : EQUAL(pszType, "REAL[]") /* unofficial alias */)
817 0 : eType = OFTRealList;
818 8 : else if (EQUAL(pszType, "CHARACTER") ||
819 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
820 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
821 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
822 4 : eType = OFTString;
823 0 : else if (EQUAL(pszType, "TEXT[]") ||
824 : EQUAL(pszType, "STRING[]") /* unofficial alias */||
825 : EQUAL(pszType, "VARCHAR[]") /* unofficial alias */)
826 0 : eType = OFTStringList;
827 0 : else if (EQUAL(pszType, "DATE"))
828 0 : eType = OFTDate;
829 0 : else if (EQUAL(pszType, "TIME"))
830 0 : eType = OFTTime;
831 0 : else if (EQUAL(pszType, "TIMESTAMP") ||
832 : EQUAL(pszType, "DATETIME") /* unofficial alias */ )
833 0 : eType = OFTDateTime;
834 : else
835 : {
836 : CPLError(CE_Warning, CPLE_NotSupported,
837 : "Unsupported column type '%s'. Defaulting to VARCHAR",
838 0 : pszType);
839 : }
840 6 : return eType;
841 : }
842 :
843 : /************************************************************************/
844 : /* ProcessSQLAlterTableAddColumn() */
845 : /* */
846 : /* The correct syntax for adding a column in the OGR SQL */
847 : /* dialect is: */
848 : /* */
849 : /* ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype>*/
850 : /************************************************************************/
851 :
852 2 : OGRErr OGRDataSource::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
853 :
854 : {
855 2 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
856 :
857 : /* -------------------------------------------------------------------- */
858 : /* Do some general syntax checking. */
859 : /* -------------------------------------------------------------------- */
860 2 : const char* pszLayerName = NULL;
861 2 : const char* pszColumnName = NULL;
862 2 : char* pszType = NULL;
863 2 : int iTypeIndex = 0;
864 2 : int nTokens = CSLCount(papszTokens);
865 :
866 11 : if( nTokens >= 7
867 2 : && EQUAL(papszTokens[0],"ALTER")
868 2 : && EQUAL(papszTokens[1],"TABLE")
869 2 : && EQUAL(papszTokens[3],"ADD")
870 2 : && EQUAL(papszTokens[4],"COLUMN"))
871 : {
872 1 : pszLayerName = papszTokens[2];
873 1 : pszColumnName = papszTokens[5];
874 1 : iTypeIndex = 6;
875 : }
876 5 : else if( nTokens >= 6
877 1 : && EQUAL(papszTokens[0],"ALTER")
878 1 : && EQUAL(papszTokens[1],"TABLE")
879 1 : && EQUAL(papszTokens[3],"ADD"))
880 : {
881 1 : pszLayerName = papszTokens[2];
882 1 : pszColumnName = papszTokens[4];
883 1 : iTypeIndex = 5;
884 : }
885 : else
886 : {
887 0 : CSLDestroy( papszTokens );
888 : CPLError( CE_Failure, CPLE_AppDefined,
889 : "Syntax error in ALTER TABLE ADD COLUMN command.\n"
890 : "Was '%s'\n"
891 : "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype>'",
892 0 : pszSQLCommand );
893 0 : return OGRERR_FAILURE;
894 : }
895 :
896 : /* -------------------------------------------------------------------- */
897 : /* Merge type components into a single string if there were split */
898 : /* with spaces */
899 : /* -------------------------------------------------------------------- */
900 2 : CPLString osType;
901 6 : for(int i=iTypeIndex;i<nTokens;i++)
902 : {
903 4 : osType += papszTokens[i];
904 4 : CPLFree(papszTokens[i]);
905 : }
906 2 : pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
907 2 : papszTokens[iTypeIndex + 1] = NULL;
908 :
909 : /* -------------------------------------------------------------------- */
910 : /* Find the named layer. */
911 : /* -------------------------------------------------------------------- */
912 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
913 2 : if( poLayer == NULL )
914 : {
915 : CPLError( CE_Failure, CPLE_AppDefined,
916 : "%s failed, no such layer as `%s'.",
917 : pszSQLCommand,
918 0 : pszLayerName );
919 0 : CSLDestroy( papszTokens );
920 0 : return OGRERR_FAILURE;
921 : }
922 :
923 : /* -------------------------------------------------------------------- */
924 : /* Add column. */
925 : /* -------------------------------------------------------------------- */
926 :
927 2 : int nWidth = 0, nPrecision = 0;
928 2 : OGRFieldType eType = OGRDataSourceParseSQLType(pszType, nWidth, nPrecision);
929 2 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
930 2 : oFieldDefn.SetWidth(nWidth);
931 2 : oFieldDefn.SetPrecision(nPrecision);
932 :
933 2 : CSLDestroy( papszTokens );
934 :
935 2 : return poLayer->CreateField( &oFieldDefn );
936 : }
937 :
938 : /************************************************************************/
939 : /* ProcessSQLAlterTableDropColumn() */
940 : /* */
941 : /* The correct syntax for droping a column in the OGR SQL */
942 : /* dialect is: */
943 : /* */
944 : /* ALTER TABLE <layername> DROP [COLUMN] <columnname> */
945 : /************************************************************************/
946 :
947 2 : OGRErr OGRDataSource::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
948 :
949 : {
950 2 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
951 :
952 : /* -------------------------------------------------------------------- */
953 : /* Do some general syntax checking. */
954 : /* -------------------------------------------------------------------- */
955 2 : const char* pszLayerName = NULL;
956 2 : const char* pszColumnName = NULL;
957 6 : if( CSLCount(papszTokens) == 6
958 1 : && EQUAL(papszTokens[0],"ALTER")
959 1 : && EQUAL(papszTokens[1],"TABLE")
960 1 : && EQUAL(papszTokens[3],"DROP")
961 1 : && EQUAL(papszTokens[4],"COLUMN"))
962 : {
963 1 : pszLayerName = papszTokens[2];
964 1 : pszColumnName = papszTokens[5];
965 : }
966 4 : else if( CSLCount(papszTokens) == 5
967 1 : && EQUAL(papszTokens[0],"ALTER")
968 1 : && EQUAL(papszTokens[1],"TABLE")
969 1 : && EQUAL(papszTokens[3],"DROP"))
970 : {
971 1 : pszLayerName = papszTokens[2];
972 1 : pszColumnName = papszTokens[4];
973 : }
974 : else
975 : {
976 0 : CSLDestroy( papszTokens );
977 : CPLError( CE_Failure, CPLE_AppDefined,
978 : "Syntax error in ALTER TABLE DROP COLUMN command.\n"
979 : "Was '%s'\n"
980 : "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] <columnname>'",
981 0 : pszSQLCommand );
982 0 : return OGRERR_FAILURE;
983 : }
984 :
985 : /* -------------------------------------------------------------------- */
986 : /* Find the named layer. */
987 : /* -------------------------------------------------------------------- */
988 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
989 2 : if( poLayer == NULL )
990 : {
991 : CPLError( CE_Failure, CPLE_AppDefined,
992 : "%s failed, no such layer as `%s'.",
993 : pszSQLCommand,
994 0 : pszLayerName );
995 0 : CSLDestroy( papszTokens );
996 0 : return OGRERR_FAILURE;
997 : }
998 :
999 : /* -------------------------------------------------------------------- */
1000 : /* Find the field. */
1001 : /* -------------------------------------------------------------------- */
1002 :
1003 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
1004 2 : if( nFieldIndex < 0 )
1005 : {
1006 : CPLError( CE_Failure, CPLE_AppDefined,
1007 : "%s failed, no such field as `%s'.",
1008 : pszSQLCommand,
1009 0 : pszColumnName );
1010 0 : CSLDestroy( papszTokens );
1011 0 : return OGRERR_FAILURE;
1012 : }
1013 :
1014 :
1015 : /* -------------------------------------------------------------------- */
1016 : /* Remove it. */
1017 : /* -------------------------------------------------------------------- */
1018 :
1019 2 : CSLDestroy( papszTokens );
1020 :
1021 2 : return poLayer->DeleteField( nFieldIndex );
1022 : }
1023 :
1024 : /************************************************************************/
1025 : /* ProcessSQLAlterTableRenameColumn() */
1026 : /* */
1027 : /* The correct syntax for renaming a column in the OGR SQL */
1028 : /* dialect is: */
1029 : /* */
1030 : /* ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
1031 : /************************************************************************/
1032 :
1033 2 : OGRErr OGRDataSource::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
1034 :
1035 : {
1036 2 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
1037 :
1038 : /* -------------------------------------------------------------------- */
1039 : /* Do some general syntax checking. */
1040 : /* -------------------------------------------------------------------- */
1041 2 : const char* pszLayerName = NULL;
1042 2 : const char* pszOldColName = NULL;
1043 2 : const char* pszNewColName = NULL;
1044 7 : if( CSLCount(papszTokens) == 8
1045 1 : && EQUAL(papszTokens[0],"ALTER")
1046 1 : && EQUAL(papszTokens[1],"TABLE")
1047 1 : && EQUAL(papszTokens[3],"RENAME")
1048 1 : && EQUAL(papszTokens[4],"COLUMN")
1049 1 : && EQUAL(papszTokens[6],"TO"))
1050 : {
1051 1 : pszLayerName = papszTokens[2];
1052 1 : pszOldColName = papszTokens[5];
1053 1 : pszNewColName = papszTokens[7];
1054 : }
1055 5 : else if( CSLCount(papszTokens) == 7
1056 1 : && EQUAL(papszTokens[0],"ALTER")
1057 1 : && EQUAL(papszTokens[1],"TABLE")
1058 1 : && EQUAL(papszTokens[3],"RENAME")
1059 1 : && EQUAL(papszTokens[5],"TO"))
1060 : {
1061 1 : pszLayerName = papszTokens[2];
1062 1 : pszOldColName = papszTokens[4];
1063 1 : pszNewColName = papszTokens[6];
1064 : }
1065 : else
1066 : {
1067 0 : CSLDestroy( papszTokens );
1068 : CPLError( CE_Failure, CPLE_AppDefined,
1069 : "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
1070 : "Was '%s'\n"
1071 : "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] <columnname> <columntype>'",
1072 0 : pszSQLCommand );
1073 0 : return OGRERR_FAILURE;
1074 : }
1075 :
1076 : /* -------------------------------------------------------------------- */
1077 : /* Find the named layer. */
1078 : /* -------------------------------------------------------------------- */
1079 2 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
1080 2 : if( poLayer == NULL )
1081 : {
1082 : CPLError( CE_Failure, CPLE_AppDefined,
1083 : "%s failed, no such layer as `%s'.",
1084 : pszSQLCommand,
1085 0 : pszLayerName );
1086 0 : CSLDestroy( papszTokens );
1087 0 : return OGRERR_FAILURE;
1088 : }
1089 :
1090 : /* -------------------------------------------------------------------- */
1091 : /* Find the field. */
1092 : /* -------------------------------------------------------------------- */
1093 :
1094 2 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
1095 2 : if( nFieldIndex < 0 )
1096 : {
1097 : CPLError( CE_Failure, CPLE_AppDefined,
1098 : "%s failed, no such field as `%s'.",
1099 : pszSQLCommand,
1100 0 : pszOldColName );
1101 0 : CSLDestroy( papszTokens );
1102 0 : return OGRERR_FAILURE;
1103 : }
1104 :
1105 : /* -------------------------------------------------------------------- */
1106 : /* Rename column. */
1107 : /* -------------------------------------------------------------------- */
1108 2 : OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
1109 2 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
1110 2 : oNewFieldDefn.SetName(pszNewColName);
1111 :
1112 2 : CSLDestroy( papszTokens );
1113 :
1114 2 : return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, ALTER_NAME_FLAG );
1115 : }
1116 :
1117 : /************************************************************************/
1118 : /* ProcessSQLAlterTableAlterColumn() */
1119 : /* */
1120 : /* The correct syntax for altering the type of a column in the */
1121 : /* OGR SQL dialect is: */
1122 : /* */
1123 : /* ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <newtype> */
1124 : /************************************************************************/
1125 :
1126 4 : OGRErr OGRDataSource::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
1127 :
1128 : {
1129 4 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
1130 :
1131 : /* -------------------------------------------------------------------- */
1132 : /* Do some general syntax checking. */
1133 : /* -------------------------------------------------------------------- */
1134 4 : const char* pszLayerName = NULL;
1135 4 : const char* pszColumnName = NULL;
1136 4 : char* pszType = NULL;
1137 4 : int iTypeIndex = 0;
1138 4 : int nTokens = CSLCount(papszTokens);
1139 :
1140 16 : if( nTokens >= 8
1141 2 : && EQUAL(papszTokens[0],"ALTER")
1142 2 : && EQUAL(papszTokens[1],"TABLE")
1143 2 : && EQUAL(papszTokens[3],"ALTER")
1144 2 : && EQUAL(papszTokens[4],"COLUMN")
1145 2 : && EQUAL(papszTokens[6],"TYPE"))
1146 : {
1147 2 : pszLayerName = papszTokens[2];
1148 2 : pszColumnName = papszTokens[5];
1149 2 : iTypeIndex = 7;
1150 : }
1151 12 : else if( nTokens >= 7
1152 2 : && EQUAL(papszTokens[0],"ALTER")
1153 2 : && EQUAL(papszTokens[1],"TABLE")
1154 2 : && EQUAL(papszTokens[3],"ALTER")
1155 2 : && EQUAL(papszTokens[5],"TYPE"))
1156 : {
1157 2 : pszLayerName = papszTokens[2];
1158 2 : pszColumnName = papszTokens[4];
1159 2 : iTypeIndex = 6;
1160 : }
1161 : else
1162 : {
1163 0 : CSLDestroy( papszTokens );
1164 : CPLError( CE_Failure, CPLE_AppDefined,
1165 : "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
1166 : "Was '%s'\n"
1167 : "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <columntype>'",
1168 0 : pszSQLCommand );
1169 0 : return OGRERR_FAILURE;
1170 : }
1171 :
1172 : /* -------------------------------------------------------------------- */
1173 : /* Merge type components into a single string if there were split */
1174 : /* with spaces */
1175 : /* -------------------------------------------------------------------- */
1176 4 : CPLString osType;
1177 8 : for(int i=iTypeIndex;i<nTokens;i++)
1178 : {
1179 4 : osType += papszTokens[i];
1180 4 : CPLFree(papszTokens[i]);
1181 : }
1182 4 : pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
1183 4 : papszTokens[iTypeIndex + 1] = NULL;
1184 :
1185 : /* -------------------------------------------------------------------- */
1186 : /* Find the named layer. */
1187 : /* -------------------------------------------------------------------- */
1188 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
1189 4 : if( poLayer == NULL )
1190 : {
1191 : CPLError( CE_Failure, CPLE_AppDefined,
1192 : "%s failed, no such layer as `%s'.",
1193 : pszSQLCommand,
1194 0 : pszLayerName );
1195 0 : CSLDestroy( papszTokens );
1196 0 : return OGRERR_FAILURE;
1197 : }
1198 :
1199 : /* -------------------------------------------------------------------- */
1200 : /* Find the field. */
1201 : /* -------------------------------------------------------------------- */
1202 :
1203 4 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
1204 4 : if( nFieldIndex < 0 )
1205 : {
1206 : CPLError( CE_Failure, CPLE_AppDefined,
1207 : "%s failed, no such field as `%s'.",
1208 : pszSQLCommand,
1209 0 : pszColumnName );
1210 0 : CSLDestroy( papszTokens );
1211 0 : return OGRERR_FAILURE;
1212 : }
1213 :
1214 : /* -------------------------------------------------------------------- */
1215 : /* Alter column. */
1216 : /* -------------------------------------------------------------------- */
1217 :
1218 4 : OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
1219 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
1220 :
1221 4 : int nWidth = 0, nPrecision = 0;
1222 4 : OGRFieldType eType = OGRDataSourceParseSQLType(pszType, nWidth, nPrecision);
1223 4 : oNewFieldDefn.SetType(eType);
1224 4 : oNewFieldDefn.SetWidth(nWidth);
1225 4 : oNewFieldDefn.SetPrecision(nPrecision);
1226 :
1227 4 : int nFlags = 0;
1228 4 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
1229 2 : nFlags |= ALTER_TYPE_FLAG;
1230 4 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
1231 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
1232 4 : nFlags |= ALTER_WIDTH_PRECISION_FLAG;
1233 :
1234 4 : CSLDestroy( papszTokens );
1235 :
1236 4 : if (nFlags == 0)
1237 0 : return OGRERR_NONE;
1238 : else
1239 4 : return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, nFlags );
1240 : }
1241 :
1242 : /************************************************************************/
1243 : /* ExecuteSQL() */
1244 : /************************************************************************/
1245 :
1246 820 : OGRLayer * OGRDataSource::ExecuteSQL( const char *pszStatement,
1247 : OGRGeometry *poSpatialFilter,
1248 : const char *pszDialect )
1249 :
1250 : {
1251 820 : swq_select *psSelectInfo = NULL;
1252 :
1253 : (void) pszDialect;
1254 :
1255 : swq_field_list sFieldList;
1256 820 : int nFIDIndex = 0;
1257 820 : OGRGenSQLResultsLayer *poResults = NULL;
1258 820 : char *pszWHERE = NULL;
1259 :
1260 820 : memset( &sFieldList, 0, sizeof(sFieldList) );
1261 :
1262 : /* -------------------------------------------------------------------- */
1263 : /* Handle CREATE INDEX statements specially. */
1264 : /* -------------------------------------------------------------------- */
1265 820 : if( EQUALN(pszStatement,"CREATE INDEX",12) )
1266 : {
1267 6 : ProcessSQLCreateIndex( pszStatement );
1268 6 : return NULL;
1269 : }
1270 :
1271 : /* -------------------------------------------------------------------- */
1272 : /* Handle DROP INDEX statements specially. */
1273 : /* -------------------------------------------------------------------- */
1274 814 : if( EQUALN(pszStatement,"DROP INDEX",10) )
1275 : {
1276 2 : ProcessSQLDropIndex( pszStatement );
1277 2 : return NULL;
1278 : }
1279 :
1280 : /* -------------------------------------------------------------------- */
1281 : /* Handle DROP TABLE statements specially. */
1282 : /* -------------------------------------------------------------------- */
1283 812 : if( EQUALN(pszStatement,"DROP TABLE",10) )
1284 : {
1285 500 : ProcessSQLDropTable( pszStatement );
1286 500 : return NULL;
1287 : }
1288 :
1289 : /* -------------------------------------------------------------------- */
1290 : /* Handle ALTER TABLE statements specially. */
1291 : /* -------------------------------------------------------------------- */
1292 312 : if( EQUALN(pszStatement,"ALTER TABLE",11) )
1293 : {
1294 10 : char **papszTokens = CSLTokenizeString( pszStatement );
1295 20 : if( CSLCount(papszTokens) >= 4 &&
1296 10 : EQUAL(papszTokens[3],"ADD") )
1297 : {
1298 2 : ProcessSQLAlterTableAddColumn( pszStatement );
1299 2 : CSLDestroy(papszTokens);
1300 2 : return NULL;
1301 : }
1302 16 : else if( CSLCount(papszTokens) >= 4 &&
1303 8 : EQUAL(papszTokens[3],"DROP") )
1304 : {
1305 2 : ProcessSQLAlterTableDropColumn( pszStatement );
1306 2 : CSLDestroy(papszTokens);
1307 2 : return NULL;
1308 : }
1309 12 : else if( CSLCount(papszTokens) >= 4 &&
1310 6 : EQUAL(papszTokens[3],"RENAME") )
1311 : {
1312 2 : ProcessSQLAlterTableRenameColumn( pszStatement );
1313 2 : CSLDestroy(papszTokens);
1314 2 : return NULL;
1315 : }
1316 8 : else if( CSLCount(papszTokens) >= 4 &&
1317 4 : EQUAL(papszTokens[3],"ALTER") )
1318 : {
1319 4 : ProcessSQLAlterTableAlterColumn( pszStatement );
1320 4 : CSLDestroy(papszTokens);
1321 4 : return NULL;
1322 : }
1323 : else
1324 : {
1325 : CPLError( CE_Failure, CPLE_AppDefined,
1326 : "Unsupported ALTER TABLE command : %s",
1327 0 : pszStatement );
1328 0 : CSLDestroy(papszTokens);
1329 0 : return NULL;
1330 : }
1331 : }
1332 :
1333 : /* -------------------------------------------------------------------- */
1334 : /* Preparse the SQL statement. */
1335 : /* -------------------------------------------------------------------- */
1336 302 : psSelectInfo = new swq_select();
1337 302 : if( psSelectInfo->preparse( pszStatement ) != CPLE_None )
1338 : {
1339 90 : delete psSelectInfo;
1340 90 : return NULL;
1341 : }
1342 :
1343 : /* -------------------------------------------------------------------- */
1344 : /* Validate that all the source tables are recognised, count */
1345 : /* fields. */
1346 : /* -------------------------------------------------------------------- */
1347 212 : int nFieldCount = 0, iTable, iField;
1348 : int iEDS;
1349 212 : int nExtraDSCount = 0;
1350 212 : OGRDataSource** papoExtraDS = NULL;
1351 212 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
1352 :
1353 440 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
1354 : {
1355 233 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
1356 : OGRLayer *poSrcLayer;
1357 233 : OGRDataSource *poTableDS = this;
1358 :
1359 233 : if( psTableDef->data_source != NULL )
1360 : {
1361 : poTableDS = (OGRDataSource *)
1362 5 : OGROpenShared( psTableDef->data_source, FALSE, NULL );
1363 5 : if( poTableDS == NULL )
1364 : {
1365 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
1366 : CPLError( CE_Failure, CPLE_AppDefined,
1367 : "Unable to open secondary datasource\n"
1368 : "`%s' required by JOIN.",
1369 0 : psTableDef->data_source );
1370 :
1371 0 : delete psSelectInfo;
1372 0 : goto end;
1373 : }
1374 :
1375 : /* Keep in an array to release at the end of this function */
1376 : papoExtraDS = (OGRDataSource** )CPLRealloc(papoExtraDS,
1377 5 : sizeof(OGRDataSource*) * (nExtraDSCount + 1));
1378 5 : papoExtraDS[nExtraDSCount++] = poTableDS;
1379 : }
1380 :
1381 233 : poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
1382 :
1383 233 : if( poSrcLayer == NULL )
1384 : {
1385 : CPLError( CE_Failure, CPLE_AppDefined,
1386 : "SELECT from table %s failed, no such table/featureclass.",
1387 5 : psTableDef->table_name );
1388 5 : delete psSelectInfo;
1389 5 : goto end;
1390 : }
1391 :
1392 228 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
1393 : }
1394 :
1395 : /* -------------------------------------------------------------------- */
1396 : /* Build the field list for all indicated tables. */
1397 : /* -------------------------------------------------------------------- */
1398 :
1399 207 : sFieldList.table_count = psSelectInfo->table_count;
1400 207 : sFieldList.table_defs = psSelectInfo->table_defs;
1401 :
1402 207 : sFieldList.count = 0;
1403 207 : sFieldList.names = (char **) CPLMalloc( sizeof(char *) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1404 : sFieldList.types = (swq_field_type *)
1405 207 : CPLMalloc( sizeof(swq_field_type) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1406 : sFieldList.table_ids = (int *)
1407 207 : CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1408 : sFieldList.ids = (int *)
1409 207 : CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1410 :
1411 434 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
1412 : {
1413 227 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
1414 227 : OGRDataSource *poTableDS = this;
1415 : OGRLayer *poSrcLayer;
1416 :
1417 227 : if( psTableDef->data_source != NULL )
1418 : {
1419 : poTableDS = (OGRDataSource *)
1420 5 : OGROpenShared( psTableDef->data_source, FALSE, NULL );
1421 5 : CPLAssert( poTableDS != NULL );
1422 5 : poTableDS->Dereference();
1423 : }
1424 :
1425 227 : poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
1426 :
1427 2526 : for( iField = 0;
1428 1263 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
1429 : iField++ )
1430 : {
1431 1036 : OGRFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
1432 1036 : int iOutField = sFieldList.count++;
1433 1036 : sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
1434 1036 : if( poFDefn->GetType() == OFTInteger )
1435 342 : sFieldList.types[iOutField] = SWQ_INTEGER;
1436 694 : else if( poFDefn->GetType() == OFTReal )
1437 190 : sFieldList.types[iOutField] = SWQ_FLOAT;
1438 504 : else if( poFDefn->GetType() == OFTString )
1439 468 : sFieldList.types[iOutField] = SWQ_STRING;
1440 : else
1441 36 : sFieldList.types[iOutField] = SWQ_OTHER;
1442 :
1443 1036 : sFieldList.table_ids[iOutField] = iTable;
1444 1036 : sFieldList.ids[iOutField] = iField;
1445 : }
1446 :
1447 227 : if( iTable == 0 )
1448 207 : nFIDIndex = poSrcLayer->GetLayerDefn()->GetFieldCount();
1449 : }
1450 :
1451 : /* -------------------------------------------------------------------- */
1452 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
1453 : /* -------------------------------------------------------------------- */
1454 207 : if( psSelectInfo->expand_wildcard( &sFieldList ) != CE_None )
1455 : {
1456 0 : delete psSelectInfo;
1457 0 : goto end;
1458 : }
1459 :
1460 1242 : for (iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
1461 : {
1462 1035 : sFieldList.names[sFieldList.count] = (char*) SpecialFieldNames[iField];
1463 1035 : sFieldList.types[sFieldList.count] = SpecialFieldTypes[iField];
1464 1035 : sFieldList.table_ids[sFieldList.count] = 0;
1465 1035 : sFieldList.ids[sFieldList.count] = nFIDIndex + iField;
1466 1035 : sFieldList.count++;
1467 : }
1468 :
1469 : /* -------------------------------------------------------------------- */
1470 : /* Finish the parse operation. */
1471 : /* -------------------------------------------------------------------- */
1472 207 : if( psSelectInfo->parse( &sFieldList, 0 ) != CE_None )
1473 : {
1474 24 : delete psSelectInfo;
1475 24 : goto end;
1476 : }
1477 :
1478 : /* -------------------------------------------------------------------- */
1479 : /* Extract the WHERE expression to use separately. */
1480 : /* -------------------------------------------------------------------- */
1481 183 : if( psSelectInfo->where_expr != NULL )
1482 : {
1483 156 : if (m_poDriver && (
1484 52 : EQUAL(m_poDriver->GetName(), "PostgreSQL") ||
1485 52 : EQUAL(m_poDriver->GetName(), "FileGDB" )) )
1486 0 : pszWHERE = psSelectInfo->where_expr->Unparse( &sFieldList, '"' );
1487 : else
1488 52 : pszWHERE = psSelectInfo->where_expr->Unparse( &sFieldList, '\'' );
1489 : //CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
1490 : }
1491 :
1492 : /* -------------------------------------------------------------------- */
1493 : /* Everything seems OK, try to instantiate a results layer. */
1494 : /* -------------------------------------------------------------------- */
1495 :
1496 : poResults = new OGRGenSQLResultsLayer( this, psSelectInfo,
1497 : poSpatialFilter,
1498 : pszWHERE,
1499 183 : pszDialect );
1500 :
1501 183 : CPLFree( pszWHERE );
1502 :
1503 : // Eventually, we should keep track of layers to cleanup.
1504 :
1505 : end:
1506 212 : CPLFree( sFieldList.names );
1507 212 : CPLFree( sFieldList.types );
1508 212 : CPLFree( sFieldList.table_ids );
1509 212 : CPLFree( sFieldList.ids );
1510 :
1511 : /* Release the datasets we have opened with OGROpenShared() */
1512 : /* It is safe to do that as the 'new OGRGenSQLResultsLayer' itself */
1513 : /* has taken a reference on them, which it will release in its */
1514 : /* destructor */
1515 217 : for(iEDS = 0; iEDS < nExtraDSCount; iEDS++)
1516 5 : poReg->ReleaseDataSource( papoExtraDS[iEDS] );
1517 212 : CPLFree(papoExtraDS);
1518 :
1519 212 : return poResults;
1520 : }
1521 :
1522 : /************************************************************************/
1523 : /* OGR_DS_ExecuteSQL() */
1524 : /************************************************************************/
1525 :
1526 1399 : OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS,
1527 : const char *pszStatement,
1528 : OGRGeometryH hSpatialFilter,
1529 : const char *pszDialect )
1530 :
1531 : {
1532 1399 : VALIDATE_POINTER1( hDS, "OGR_DS_ExecuteSQL", NULL );
1533 :
1534 : return (OGRLayerH)
1535 : ((OGRDataSource *)hDS)->ExecuteSQL( pszStatement,
1536 : (OGRGeometry *) hSpatialFilter,
1537 1399 : pszDialect );
1538 : }
1539 :
1540 : /************************************************************************/
1541 : /* ReleaseResultSet() */
1542 : /************************************************************************/
1543 :
1544 179 : void OGRDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
1545 :
1546 : {
1547 179 : delete poResultsSet;
1548 179 : }
1549 :
1550 : /************************************************************************/
1551 : /* OGR_DS_ReleaseResultSet() */
1552 : /************************************************************************/
1553 :
1554 344 : void OGR_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer )
1555 :
1556 : {
1557 344 : VALIDATE_POINTER0( hDS, "OGR_DS_ReleaseResultSet" );
1558 :
1559 344 : ((OGRDataSource *) hDS)->ReleaseResultSet( (OGRLayer *) hLayer );
1560 : }
1561 :
1562 : /************************************************************************/
1563 : /* OGR_DS_TestCapability() */
1564 : /************************************************************************/
1565 :
1566 47 : int OGR_DS_TestCapability( OGRDataSourceH hDS, const char *pszCap )
1567 :
1568 : {
1569 47 : VALIDATE_POINTER1( hDS, "OGR_DS_TestCapability", 0 );
1570 47 : VALIDATE_POINTER1( pszCap, "OGR_DS_TestCapability", 0 );
1571 :
1572 47 : return ((OGRDataSource *) hDS)->TestCapability( pszCap );
1573 : }
1574 :
1575 : /************************************************************************/
1576 : /* OGR_DS_GetLayerCount() */
1577 : /************************************************************************/
1578 :
1579 218 : int OGR_DS_GetLayerCount( OGRDataSourceH hDS )
1580 :
1581 : {
1582 218 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayerCount", 0 );
1583 :
1584 218 : return ((OGRDataSource *)hDS)->GetLayerCount();
1585 : }
1586 :
1587 : /************************************************************************/
1588 : /* OGR_DS_GetLayer() */
1589 : /************************************************************************/
1590 :
1591 2437 : OGRLayerH OGR_DS_GetLayer( OGRDataSourceH hDS, int iLayer )
1592 :
1593 : {
1594 2437 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayer", NULL );
1595 :
1596 2437 : return (OGRLayerH) ((OGRDataSource*)hDS)->GetLayer( iLayer );
1597 : }
1598 :
1599 : /************************************************************************/
1600 : /* OGR_DS_GetName() */
1601 : /************************************************************************/
1602 :
1603 29 : const char *OGR_DS_GetName( OGRDataSourceH hDS )
1604 :
1605 : {
1606 29 : VALIDATE_POINTER1( hDS, "OGR_DS_GetName", NULL );
1607 :
1608 29 : return ((OGRDataSource*)hDS)->GetName();
1609 : }
1610 :
1611 : /************************************************************************/
1612 : /* SyncToDisk() */
1613 : /************************************************************************/
1614 :
1615 0 : OGRErr OGRDataSource::SyncToDisk()
1616 :
1617 : {
1618 0 : CPLMutexHolderD( &m_hMutex );
1619 : int i;
1620 : OGRErr eErr;
1621 :
1622 0 : for( i = 0; i < GetLayerCount(); i++ )
1623 : {
1624 0 : OGRLayer *poLayer = GetLayer(i);
1625 :
1626 0 : if( poLayer )
1627 : {
1628 0 : eErr = poLayer->SyncToDisk();
1629 0 : if( eErr != OGRERR_NONE )
1630 0 : return eErr;
1631 : }
1632 : }
1633 :
1634 0 : return OGRERR_NONE;
1635 : }
1636 :
1637 : /************************************************************************/
1638 : /* OGR_DS_SyncToDisk() */
1639 : /************************************************************************/
1640 :
1641 0 : OGRErr OGR_DS_SyncToDisk( OGRDataSourceH hDS )
1642 :
1643 : {
1644 0 : VALIDATE_POINTER1( hDS, "OGR_DS_SyncToDisk", OGRERR_INVALID_HANDLE );
1645 :
1646 0 : return ((OGRDataSource *) hDS)->SyncToDisk();
1647 : }
1648 :
1649 : /************************************************************************/
1650 : /* GetDriver() */
1651 : /************************************************************************/
1652 :
1653 2701 : OGRSFDriver *OGRDataSource::GetDriver() const
1654 :
1655 : {
1656 2701 : return m_poDriver;
1657 : }
1658 :
1659 : /************************************************************************/
1660 : /* OGR_DS_GetDriver() */
1661 : /************************************************************************/
1662 :
1663 22 : OGRSFDriverH OGR_DS_GetDriver( OGRDataSourceH hDS )
1664 :
1665 : {
1666 22 : VALIDATE_POINTER1( hDS, "OGR_DS_GetDriver", NULL );
1667 :
1668 22 : return (OGRSFDriverH) ((OGRDataSource *) hDS)->GetDriver();
1669 : }
1670 :
1671 : /************************************************************************/
1672 : /* SetDriver() */
1673 : /************************************************************************/
1674 :
1675 358 : void OGRDataSource::SetDriver( OGRSFDriver *poDriver )
1676 :
1677 : {
1678 358 : m_poDriver = poDriver;
1679 358 : }
1680 :
1681 : /************************************************************************/
1682 : /* GetStyleTable() */
1683 : /************************************************************************/
1684 :
1685 62 : OGRStyleTable *OGRDataSource::GetStyleTable()
1686 : {
1687 62 : return m_poStyleTable;
1688 : }
1689 :
1690 : /************************************************************************/
1691 : /* SetStyleTableDirectly() */
1692 : /************************************************************************/
1693 :
1694 0 : void OGRDataSource::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
1695 : {
1696 0 : if ( m_poStyleTable )
1697 0 : delete m_poStyleTable;
1698 0 : m_poStyleTable = poStyleTable;
1699 0 : }
1700 :
1701 : /************************************************************************/
1702 : /* SetStyleTable() */
1703 : /************************************************************************/
1704 :
1705 62 : void OGRDataSource::SetStyleTable(OGRStyleTable *poStyleTable)
1706 : {
1707 62 : if ( m_poStyleTable )
1708 0 : delete m_poStyleTable;
1709 62 : if ( poStyleTable )
1710 0 : m_poStyleTable = poStyleTable->Clone();
1711 62 : }
1712 :
1713 : /************************************************************************/
1714 : /* OGR_DS_GetStyleTable() */
1715 : /************************************************************************/
1716 :
1717 0 : OGRStyleTableH OGR_DS_GetStyleTable( OGRDataSourceH hDS )
1718 :
1719 : {
1720 0 : VALIDATE_POINTER1( hDS, "OGR_DS_GetStyleTable", NULL );
1721 :
1722 0 : return (OGRStyleTableH) ((OGRDataSource *) hDS)->GetStyleTable( );
1723 : }
1724 :
1725 : /************************************************************************/
1726 : /* OGR_DS_SetStyleTableDirectly() */
1727 : /************************************************************************/
1728 :
1729 0 : void OGR_DS_SetStyleTableDirectly( OGRDataSourceH hDS,
1730 : OGRStyleTableH hStyleTable )
1731 :
1732 : {
1733 0 : VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTableDirectly" );
1734 :
1735 0 : ((OGRDataSource *) hDS)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
1736 : }
1737 :
1738 : /************************************************************************/
1739 : /* OGR_DS_SetStyleTable() */
1740 : /************************************************************************/
1741 :
1742 0 : void OGR_DS_SetStyleTable( OGRDataSourceH hDS, OGRStyleTableH hStyleTable )
1743 :
1744 : {
1745 0 : VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTable" );
1746 0 : VALIDATE_POINTER0( hStyleTable, "OGR_DS_SetStyleTable" );
1747 :
1748 0 : ((OGRDataSource *) hDS)->SetStyleTable( (OGRStyleTable *) hStyleTable);
1749 : }
|