1 : /******************************************************************************
2 : * $Id: ogrdatasource.cpp 23782 2012-01-21 21:22:10Z 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 "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 23782 2012-01-21 21:22:10Z rouault $");
39 :
40 : /************************************************************************/
41 : /* ~OGRDataSource() */
42 : /************************************************************************/
43 :
44 27224 : OGRDataSource::OGRDataSource()
45 :
46 : {
47 27224 : m_poStyleTable = NULL;
48 27224 : m_nRefCount = 0;
49 27224 : m_poDriver = NULL;
50 27224 : m_hMutex = NULL;
51 27224 : }
52 :
53 : /************************************************************************/
54 : /* ~OGRDataSource() */
55 : /************************************************************************/
56 :
57 27224 : OGRDataSource::~OGRDataSource()
58 :
59 : {
60 27224 : if ( m_poStyleTable )
61 : {
62 6 : delete m_poStyleTable;
63 6 : m_poStyleTable = NULL;
64 : }
65 :
66 27224 : if( m_hMutex != NULL )
67 1422 : CPLDestroyMutex( m_hMutex );
68 27224 : }
69 :
70 : /************************************************************************/
71 : /* DestroyDataSource() */
72 : /************************************************************************/
73 :
74 1012 : void OGRDataSource::DestroyDataSource( OGRDataSource *poDS )
75 :
76 : {
77 1012 : delete poDS;
78 1012 : }
79 :
80 : /************************************************************************/
81 : /* OGR_DS_Destroy() */
82 : /************************************************************************/
83 :
84 88 : void OGR_DS_Destroy( OGRDataSourceH hDS )
85 :
86 : {
87 88 : VALIDATE_POINTER0( hDS, "OGR_DS_Destroy" );
88 88 : 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 2330 : int OGRDataSource::Reference()
106 :
107 : {
108 2330 : 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 96 : int OGRDataSource::Dereference()
128 :
129 : {
130 96 : 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 180 : int OGRDataSource::GetRefCount() const
150 :
151 : {
152 180 : return m_nRefCount;
153 : }
154 :
155 : /************************************************************************/
156 : /* OGR_DS_GetRefCount() */
157 : /************************************************************************/
158 :
159 8 : int OGR_DS_GetRefCount( OGRDataSourceH hDataSource )
160 :
161 : {
162 8 : VALIDATE_POINTER1( hDataSource, "OGR_DS_GetRefCount", 0 );
163 :
164 8 : return ((OGRDataSource *) hDataSource)->GetRefCount();
165 : }
166 :
167 : /************************************************************************/
168 : /* GetSummaryRefCount() */
169 : /************************************************************************/
170 :
171 32 : int OGRDataSource::GetSummaryRefCount() const
172 :
173 : {
174 32 : CPLMutexHolderD( (void **) &m_hMutex );
175 32 : int nSummaryCount = m_nRefCount;
176 : int iLayer;
177 32 : OGRDataSource *poUseThis = (OGRDataSource *) this;
178 :
179 64 : for( iLayer=0; iLayer < poUseThis->GetLayerCount(); iLayer++ )
180 32 : nSummaryCount += poUseThis->GetLayer( iLayer )->GetRefCount();
181 :
182 32 : 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 2892 : OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
223 : const char * pszName,
224 : OGRSpatialReferenceH hSpatialRef,
225 : OGRwkbGeometryType eType,
226 : char ** papszOptions )
227 :
228 : {
229 2892 : VALIDATE_POINTER1( hDS, "OGR_DS_CreateLayer", NULL );
230 :
231 2892 : 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 2892 : pszName, (OGRSpatialReference *) hSpatialRef, eType, papszOptions );
238 : }
239 :
240 : /************************************************************************/
241 : /* CopyLayer() */
242 : /************************************************************************/
243 :
244 70 : OGRLayer *OGRDataSource::CopyLayer( OGRLayer *poSrcLayer,
245 : const char *pszNewName,
246 : char **papszOptions )
247 :
248 : {
249 70 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
250 70 : OGRLayer *poDstLayer = NULL;
251 :
252 : /* -------------------------------------------------------------------- */
253 : /* Create the layer. */
254 : /* -------------------------------------------------------------------- */
255 70 : 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 70 : CPLErrorReset();
263 70 : poDstLayer = CreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
264 140 : poSrcDefn->GetGeomType(), papszOptions );
265 :
266 70 : 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 212 : for( iField = 0; iField < poSrcDefn->GetFieldCount(); iField++ )
278 142 : 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 70 : int nGroupTransactions = 0;
285 70 : if( poDstLayer->TestCapability( OLCTransactions ) )
286 4 : nGroupTransactions = 128;
287 :
288 : /* -------------------------------------------------------------------- */
289 : /* Transfer features. */
290 : /* -------------------------------------------------------------------- */
291 : OGRFeature *poFeature;
292 :
293 70 : poSrcLayer->ResetReading();
294 :
295 70 : if( nGroupTransactions <= 0 )
296 : {
297 84 : while( TRUE )
298 : {
299 150 : OGRFeature *poDstFeature = NULL;
300 :
301 150 : poFeature = poSrcLayer->GetNextFeature();
302 :
303 150 : if( poFeature == NULL )
304 : break;
305 :
306 84 : CPLErrorReset();
307 84 : poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
308 :
309 84 : 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 84 : poDstFeature->SetFID( poFeature->GetFID() );
319 :
320 84 : OGRFeature::DestroyFeature( poFeature );
321 :
322 84 : CPLErrorReset();
323 84 : if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
324 : {
325 0 : OGRFeature::DestroyFeature( poDstFeature );
326 0 : return poDstLayer;
327 : }
328 :
329 84 : OGRFeature::DestroyFeature( poDstFeature );
330 : }
331 : }
332 : else
333 : {
334 4 : int i, bStopTransfer = FALSE, bStopTransaction = FALSE;
335 4 : int nFeatCount = 0; // Number of features in the temporary array
336 4 : int nFeaturesToAdd = 0;
337 : OGRFeature **papoDstFeature =
338 4 : (OGRFeature **)CPLCalloc(sizeof(OGRFeature *), nGroupTransactions);
339 12 : while( !bStopTransfer )
340 : {
341 : /* -------------------------------------------------------------------- */
342 : /* Fill the array with features */
343 : /* -------------------------------------------------------------------- */
344 76 : for( nFeatCount = 0; nFeatCount < nGroupTransactions; nFeatCount++ )
345 : {
346 76 : poFeature = poSrcLayer->GetNextFeature();
347 :
348 76 : if( poFeature == NULL )
349 : {
350 4 : bStopTransfer = 1;
351 4 : break;
352 : }
353 :
354 72 : CPLErrorReset();
355 72 : papoDstFeature[nFeatCount] =
356 72 : OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
357 :
358 72 : 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 72 : papoDstFeature[nFeatCount]->SetFID( poFeature->GetFID() );
369 :
370 72 : OGRFeature::DestroyFeature( poFeature );
371 : }
372 4 : nFeaturesToAdd = nFeatCount;
373 :
374 4 : CPLErrorReset();
375 4 : bStopTransaction = FALSE;
376 12 : while( !bStopTransaction )
377 : {
378 4 : bStopTransaction = TRUE;
379 4 : poDstLayer->StartTransaction();
380 76 : for( i = 0; i < nFeaturesToAdd; i++ )
381 : {
382 72 : if( poDstLayer->CreateFeature( papoDstFeature[i] ) != OGRERR_NONE )
383 : {
384 0 : nFeaturesToAdd = i;
385 0 : bStopTransfer = TRUE;
386 0 : bStopTransaction = FALSE;
387 : }
388 : }
389 4 : if( bStopTransaction )
390 4 : poDstLayer->CommitTransaction();
391 : else
392 0 : poDstLayer->RollbackTransaction();
393 : }
394 :
395 76 : for( i = 0; i < nFeatCount; i++ )
396 72 : OGRFeature::DestroyFeature( papoDstFeature[i] );
397 : }
398 4 : CPLFree(papoDstFeature);
399 : }
400 70 : return poDstLayer;
401 : }
402 :
403 : /************************************************************************/
404 : /* OGR_DS_CopyLayer() */
405 : /************************************************************************/
406 :
407 4 : OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
408 : OGRLayerH hSrcLayer, const char *pszNewName,
409 : char **papszOptions )
410 :
411 : {
412 4 : VALIDATE_POINTER1( hDS, "OGR_DS_CopyLayer", NULL );
413 4 : VALIDATE_POINTER1( hSrcLayer, "OGR_DS_CopyLayer", NULL );
414 4 : VALIDATE_POINTER1( pszNewName, "OGR_DS_CopyLayer", NULL );
415 :
416 : return (OGRLayerH)
417 : ((OGRDataSource *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer,
418 4 : 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 22 : OGRErr OGR_DS_DeleteLayer( OGRDataSourceH hDS, int iLayer )
440 :
441 : {
442 22 : VALIDATE_POINTER1( hDS, "OGR_DS_DeleteLayer", OGRERR_INVALID_HANDLE );
443 :
444 22 : return ((OGRDataSource *) hDS)->DeleteLayer( iLayer );
445 : }
446 :
447 : /************************************************************************/
448 : /* GetLayerByName() */
449 : /************************************************************************/
450 :
451 5442 : OGRLayer *OGRDataSource::GetLayerByName( const char *pszName )
452 :
453 : {
454 5442 : CPLMutexHolderD( &m_hMutex );
455 :
456 5442 : if ( ! pszName )
457 0 : return NULL;
458 :
459 : int i;
460 :
461 : /* first a case sensitive check */
462 516662 : for( i = 0; i < GetLayerCount(); i++ )
463 : {
464 513776 : OGRLayer *poLayer = GetLayer(i);
465 :
466 513776 : if( strcmp( pszName, poLayer->GetName() ) == 0 )
467 2556 : return poLayer;
468 : }
469 :
470 : /* then case insensitive */
471 507358 : for( i = 0; i < GetLayerCount(); i++ )
472 : {
473 504516 : OGRLayer *poLayer = GetLayer(i);
474 :
475 504516 : if( EQUAL( pszName, poLayer->GetName() ) )
476 44 : return poLayer;
477 : }
478 :
479 2842 : return NULL;
480 : }
481 :
482 : /************************************************************************/
483 : /* OGR_DS_GetLayerByName() */
484 : /************************************************************************/
485 :
486 3716 : OGRLayerH OGR_DS_GetLayerByName( OGRDataSourceH hDS, const char *pszName )
487 :
488 : {
489 3716 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayerByName", NULL );
490 :
491 3716 : 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 16 : OGRErr OGRDataSource::ProcessSQLCreateIndex( const char *pszSQLCommand )
504 :
505 : {
506 16 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Do some general syntax checking. */
510 : /* -------------------------------------------------------------------- */
511 80 : if( CSLCount(papszTokens) != 6
512 16 : || !EQUAL(papszTokens[0],"CREATE")
513 16 : || !EQUAL(papszTokens[1],"INDEX")
514 16 : || !EQUAL(papszTokens[2],"ON")
515 16 : || !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 16 : OGRLayer *poLayer = NULL;
531 :
532 : {
533 16 : CPLMutexHolderD( &m_hMutex );
534 :
535 16 : for( i = 0; i < GetLayerCount(); i++ )
536 : {
537 16 : poLayer = GetLayer(i);
538 :
539 16 : if( EQUAL(poLayer->GetName(),papszTokens[3]) )
540 16 : break;
541 : }
542 :
543 16 : 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 16 : 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 24 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
568 : {
569 24 : if( EQUAL(papszTokens[5],
570 : poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
571 16 : break;
572 : }
573 :
574 16 : CSLDestroy( papszTokens );
575 :
576 16 : 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 16 : eErr = poLayer->GetIndex()->CreateIndex( i );
590 16 : if( eErr == OGRERR_NONE )
591 16 : 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 16 : 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 4 : OGRErr OGRDataSource::ProcessSQLDropIndex( const char *pszSQLCommand )
612 :
613 : {
614 4 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Do some general syntax checking. */
618 : /* -------------------------------------------------------------------- */
619 20 : if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
620 4 : || !EQUAL(papszTokens[0],"DROP")
621 4 : || !EQUAL(papszTokens[1],"INDEX")
622 4 : || !EQUAL(papszTokens[2],"ON")
623 4 : || (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 4 : OGRLayer *poLayer=NULL;
639 :
640 : {
641 4 : CPLMutexHolderD( &m_hMutex );
642 :
643 4 : for( i = 0; i < GetLayerCount(); i++ )
644 : {
645 4 : poLayer = GetLayer(i);
646 :
647 4 : if( EQUAL(poLayer->GetName(),papszTokens[3]) )
648 4 : break;
649 : }
650 :
651 4 : 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 4 : 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 4 : 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 6 : for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
700 : {
701 6 : if( EQUAL(papszTokens[5],
702 : poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
703 4 : break;
704 : }
705 :
706 4 : CSLDestroy( papszTokens );
707 :
708 4 : 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 4 : eErr = poLayer->GetIndex()->DropIndex( i );
720 :
721 4 : 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 1000 : OGRErr OGRDataSource::ProcessSQLDropTable( const char *pszSQLCommand )
734 :
735 : {
736 1000 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
737 :
738 : /* -------------------------------------------------------------------- */
739 : /* Do some general syntax checking. */
740 : /* -------------------------------------------------------------------- */
741 3000 : if( CSLCount(papszTokens) != 3
742 1000 : || !EQUAL(papszTokens[0],"DROP")
743 1000 : || !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 1000 : OGRLayer *poLayer=NULL;
759 :
760 80398 : for( i = 0; i < GetLayerCount(); i++ )
761 : {
762 80398 : poLayer = GetLayer(i);
763 :
764 80398 : if( EQUAL(poLayer->GetName(),papszTokens[2]) )
765 1000 : break;
766 : }
767 :
768 1000 : 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 1000 : CSLDestroy( papszTokens );
778 :
779 : /* -------------------------------------------------------------------- */
780 : /* Delete it. */
781 : /* -------------------------------------------------------------------- */
782 :
783 1000 : return DeleteLayer( i );
784 : }
785 :
786 : /************************************************************************/
787 : /* OGRDataSourceParseSQLType() */
788 : /************************************************************************/
789 :
790 : /* All arguments will be altered */
791 12 : static OGRFieldType OGRDataSourceParseSQLType(char* pszType, int& nWidth, int &nPrecision)
792 : {
793 12 : char* pszParenthesis = strchr(pszType, '(');
794 12 : if (pszParenthesis)
795 : {
796 8 : nWidth = atoi(pszParenthesis + 1);
797 8 : *pszParenthesis = '\0';
798 8 : char* pszComma = strchr(pszParenthesis + 1, ',');
799 8 : if (pszComma)
800 4 : nPrecision = atoi(pszComma + 1);
801 : }
802 :
803 12 : OGRFieldType eType = OFTString;
804 12 : if (EQUAL(pszType, "INTEGER"))
805 0 : eType = OFTInteger;
806 12 : else if (EQUAL(pszType, "INTEGER[]"))
807 0 : eType = OFTIntegerList;
808 16 : else if (EQUAL(pszType, "FLOAT") ||
809 : EQUAL(pszType, "NUMERIC") ||
810 : EQUAL(pszType, "DOUBLE") /* unofficial alias */ ||
811 : EQUAL(pszType, "REAL") /* unofficial alias */)
812 4 : eType = OFTReal;
813 8 : 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 16 : else if (EQUAL(pszType, "CHARACTER") ||
819 : EQUAL(pszType, "TEXT") /* unofficial alias */ ||
820 : EQUAL(pszType, "STRING") /* unofficial alias */ ||
821 : EQUAL(pszType, "VARCHAR") /* unofficial alias */)
822 8 : 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 12 : 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 4 : OGRErr OGRDataSource::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
853 :
854 : {
855 4 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
856 :
857 : /* -------------------------------------------------------------------- */
858 : /* Do some general syntax checking. */
859 : /* -------------------------------------------------------------------- */
860 4 : const char* pszLayerName = NULL;
861 4 : const char* pszColumnName = NULL;
862 4 : char* pszType = NULL;
863 4 : int iTypeIndex = 0;
864 4 : int nTokens = CSLCount(papszTokens);
865 :
866 22 : if( nTokens >= 7
867 4 : && EQUAL(papszTokens[0],"ALTER")
868 4 : && EQUAL(papszTokens[1],"TABLE")
869 4 : && EQUAL(papszTokens[3],"ADD")
870 4 : && EQUAL(papszTokens[4],"COLUMN"))
871 : {
872 2 : pszLayerName = papszTokens[2];
873 2 : pszColumnName = papszTokens[5];
874 2 : iTypeIndex = 6;
875 : }
876 10 : else if( nTokens >= 6
877 2 : && EQUAL(papszTokens[0],"ALTER")
878 2 : && EQUAL(papszTokens[1],"TABLE")
879 2 : && EQUAL(papszTokens[3],"ADD"))
880 : {
881 2 : pszLayerName = papszTokens[2];
882 2 : pszColumnName = papszTokens[4];
883 2 : 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 4 : CPLString osType;
901 12 : for(int i=iTypeIndex;i<nTokens;i++)
902 : {
903 8 : osType += papszTokens[i];
904 8 : CPLFree(papszTokens[i]);
905 : }
906 4 : pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
907 4 : papszTokens[iTypeIndex + 1] = NULL;
908 :
909 : /* -------------------------------------------------------------------- */
910 : /* Find the named layer. */
911 : /* -------------------------------------------------------------------- */
912 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
913 4 : 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 4 : int nWidth = 0, nPrecision = 0;
928 4 : OGRFieldType eType = OGRDataSourceParseSQLType(pszType, nWidth, nPrecision);
929 4 : OGRFieldDefn oFieldDefn(pszColumnName, eType);
930 4 : oFieldDefn.SetWidth(nWidth);
931 4 : oFieldDefn.SetPrecision(nPrecision);
932 :
933 4 : CSLDestroy( papszTokens );
934 :
935 4 : 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 4 : OGRErr OGRDataSource::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
948 :
949 : {
950 4 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
951 :
952 : /* -------------------------------------------------------------------- */
953 : /* Do some general syntax checking. */
954 : /* -------------------------------------------------------------------- */
955 4 : const char* pszLayerName = NULL;
956 4 : const char* pszColumnName = NULL;
957 12 : if( CSLCount(papszTokens) == 6
958 2 : && EQUAL(papszTokens[0],"ALTER")
959 2 : && EQUAL(papszTokens[1],"TABLE")
960 2 : && EQUAL(papszTokens[3],"DROP")
961 2 : && EQUAL(papszTokens[4],"COLUMN"))
962 : {
963 2 : pszLayerName = papszTokens[2];
964 2 : pszColumnName = papszTokens[5];
965 : }
966 8 : else if( CSLCount(papszTokens) == 5
967 2 : && EQUAL(papszTokens[0],"ALTER")
968 2 : && EQUAL(papszTokens[1],"TABLE")
969 2 : && EQUAL(papszTokens[3],"DROP"))
970 : {
971 2 : pszLayerName = papszTokens[2];
972 2 : 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 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
989 4 : 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 4 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
1004 4 : 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 4 : CSLDestroy( papszTokens );
1020 :
1021 4 : 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 4 : OGRErr OGRDataSource::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
1034 :
1035 : {
1036 4 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
1037 :
1038 : /* -------------------------------------------------------------------- */
1039 : /* Do some general syntax checking. */
1040 : /* -------------------------------------------------------------------- */
1041 4 : const char* pszLayerName = NULL;
1042 4 : const char* pszOldColName = NULL;
1043 4 : const char* pszNewColName = NULL;
1044 14 : if( CSLCount(papszTokens) == 8
1045 2 : && EQUAL(papszTokens[0],"ALTER")
1046 2 : && EQUAL(papszTokens[1],"TABLE")
1047 2 : && EQUAL(papszTokens[3],"RENAME")
1048 2 : && EQUAL(papszTokens[4],"COLUMN")
1049 2 : && EQUAL(papszTokens[6],"TO"))
1050 : {
1051 2 : pszLayerName = papszTokens[2];
1052 2 : pszOldColName = papszTokens[5];
1053 2 : pszNewColName = papszTokens[7];
1054 : }
1055 10 : else if( CSLCount(papszTokens) == 7
1056 2 : && EQUAL(papszTokens[0],"ALTER")
1057 2 : && EQUAL(papszTokens[1],"TABLE")
1058 2 : && EQUAL(papszTokens[3],"RENAME")
1059 2 : && EQUAL(papszTokens[5],"TO"))
1060 : {
1061 2 : pszLayerName = papszTokens[2];
1062 2 : pszOldColName = papszTokens[4];
1063 2 : 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> TO <newname>'",
1072 0 : pszSQLCommand );
1073 0 : return OGRERR_FAILURE;
1074 : }
1075 :
1076 : /* -------------------------------------------------------------------- */
1077 : /* Find the named layer. */
1078 : /* -------------------------------------------------------------------- */
1079 4 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
1080 4 : 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 4 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
1095 4 : 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 4 : OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
1109 4 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
1110 4 : oNewFieldDefn.SetName(pszNewColName);
1111 :
1112 4 : CSLDestroy( papszTokens );
1113 :
1114 4 : 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 8 : OGRErr OGRDataSource::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
1127 :
1128 : {
1129 8 : char **papszTokens = CSLTokenizeString( pszSQLCommand );
1130 :
1131 : /* -------------------------------------------------------------------- */
1132 : /* Do some general syntax checking. */
1133 : /* -------------------------------------------------------------------- */
1134 8 : const char* pszLayerName = NULL;
1135 8 : const char* pszColumnName = NULL;
1136 8 : char* pszType = NULL;
1137 8 : int iTypeIndex = 0;
1138 8 : int nTokens = CSLCount(papszTokens);
1139 :
1140 32 : if( nTokens >= 8
1141 4 : && EQUAL(papszTokens[0],"ALTER")
1142 4 : && EQUAL(papszTokens[1],"TABLE")
1143 4 : && EQUAL(papszTokens[3],"ALTER")
1144 4 : && EQUAL(papszTokens[4],"COLUMN")
1145 4 : && EQUAL(papszTokens[6],"TYPE"))
1146 : {
1147 4 : pszLayerName = papszTokens[2];
1148 4 : pszColumnName = papszTokens[5];
1149 4 : iTypeIndex = 7;
1150 : }
1151 24 : else if( nTokens >= 7
1152 4 : && EQUAL(papszTokens[0],"ALTER")
1153 4 : && EQUAL(papszTokens[1],"TABLE")
1154 4 : && EQUAL(papszTokens[3],"ALTER")
1155 4 : && EQUAL(papszTokens[5],"TYPE"))
1156 : {
1157 4 : pszLayerName = papszTokens[2];
1158 4 : pszColumnName = papszTokens[4];
1159 4 : 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 8 : CPLString osType;
1177 16 : for(int i=iTypeIndex;i<nTokens;i++)
1178 : {
1179 8 : osType += papszTokens[i];
1180 8 : CPLFree(papszTokens[i]);
1181 : }
1182 8 : pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
1183 8 : papszTokens[iTypeIndex + 1] = NULL;
1184 :
1185 : /* -------------------------------------------------------------------- */
1186 : /* Find the named layer. */
1187 : /* -------------------------------------------------------------------- */
1188 8 : OGRLayer *poLayer = GetLayerByName(pszLayerName);
1189 8 : 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 8 : int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
1204 8 : 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 8 : OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
1219 8 : OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
1220 :
1221 8 : int nWidth = 0, nPrecision = 0;
1222 8 : OGRFieldType eType = OGRDataSourceParseSQLType(pszType, nWidth, nPrecision);
1223 8 : oNewFieldDefn.SetType(eType);
1224 8 : oNewFieldDefn.SetWidth(nWidth);
1225 8 : oNewFieldDefn.SetPrecision(nPrecision);
1226 :
1227 8 : int nFlags = 0;
1228 8 : if (poOldFieldDefn->GetType() != oNewFieldDefn.GetType())
1229 4 : nFlags |= ALTER_TYPE_FLAG;
1230 8 : if (poOldFieldDefn->GetWidth() != oNewFieldDefn.GetWidth() ||
1231 : poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
1232 8 : nFlags |= ALTER_WIDTH_PRECISION_FLAG;
1233 :
1234 8 : CSLDestroy( papszTokens );
1235 :
1236 8 : if (nFlags == 0)
1237 0 : return OGRERR_NONE;
1238 : else
1239 8 : return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, nFlags );
1240 : }
1241 :
1242 : /************************************************************************/
1243 : /* ExecuteSQL() */
1244 : /************************************************************************/
1245 :
1246 1936 : OGRLayer * OGRDataSource::ExecuteSQL( const char *pszStatement,
1247 : OGRGeometry *poSpatialFilter,
1248 : const char *pszDialect )
1249 :
1250 : {
1251 1936 : swq_select *psSelectInfo = NULL;
1252 :
1253 : (void) pszDialect;
1254 :
1255 : swq_field_list sFieldList;
1256 1936 : int nFIDIndex = 0;
1257 1936 : OGRGenSQLResultsLayer *poResults = NULL;
1258 1936 : char *pszWHERE = NULL;
1259 :
1260 1936 : memset( &sFieldList, 0, sizeof(sFieldList) );
1261 :
1262 : /* -------------------------------------------------------------------- */
1263 : /* Handle CREATE INDEX statements specially. */
1264 : /* -------------------------------------------------------------------- */
1265 1936 : if( EQUALN(pszStatement,"CREATE INDEX",12) )
1266 : {
1267 16 : ProcessSQLCreateIndex( pszStatement );
1268 16 : return NULL;
1269 : }
1270 :
1271 : /* -------------------------------------------------------------------- */
1272 : /* Handle DROP INDEX statements specially. */
1273 : /* -------------------------------------------------------------------- */
1274 1920 : if( EQUALN(pszStatement,"DROP INDEX",10) )
1275 : {
1276 4 : ProcessSQLDropIndex( pszStatement );
1277 4 : return NULL;
1278 : }
1279 :
1280 : /* -------------------------------------------------------------------- */
1281 : /* Handle DROP TABLE statements specially. */
1282 : /* -------------------------------------------------------------------- */
1283 1916 : if( EQUALN(pszStatement,"DROP TABLE",10) )
1284 : {
1285 1000 : ProcessSQLDropTable( pszStatement );
1286 1000 : return NULL;
1287 : }
1288 :
1289 : /* -------------------------------------------------------------------- */
1290 : /* Handle ALTER TABLE statements specially. */
1291 : /* -------------------------------------------------------------------- */
1292 916 : if( EQUALN(pszStatement,"ALTER TABLE",11) )
1293 : {
1294 20 : char **papszTokens = CSLTokenizeString( pszStatement );
1295 40 : if( CSLCount(papszTokens) >= 4 &&
1296 20 : EQUAL(papszTokens[3],"ADD") )
1297 : {
1298 4 : ProcessSQLAlterTableAddColumn( pszStatement );
1299 4 : CSLDestroy(papszTokens);
1300 4 : return NULL;
1301 : }
1302 32 : else if( CSLCount(papszTokens) >= 4 &&
1303 16 : EQUAL(papszTokens[3],"DROP") )
1304 : {
1305 4 : ProcessSQLAlterTableDropColumn( pszStatement );
1306 4 : CSLDestroy(papszTokens);
1307 4 : return NULL;
1308 : }
1309 24 : else if( CSLCount(papszTokens) >= 4 &&
1310 12 : EQUAL(papszTokens[3],"RENAME") )
1311 : {
1312 4 : ProcessSQLAlterTableRenameColumn( pszStatement );
1313 4 : CSLDestroy(papszTokens);
1314 4 : return NULL;
1315 : }
1316 16 : else if( CSLCount(papszTokens) >= 4 &&
1317 8 : EQUAL(papszTokens[3],"ALTER") )
1318 : {
1319 8 : ProcessSQLAlterTableAlterColumn( pszStatement );
1320 8 : CSLDestroy(papszTokens);
1321 8 : 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 896 : psSelectInfo = new swq_select();
1337 896 : if( psSelectInfo->preparse( pszStatement ) != CPLE_None )
1338 : {
1339 188 : delete psSelectInfo;
1340 188 : return NULL;
1341 : }
1342 :
1343 : /* -------------------------------------------------------------------- */
1344 : /* Validate that all the source tables are recognised, count */
1345 : /* fields. */
1346 : /* -------------------------------------------------------------------- */
1347 708 : int nFieldCount = 0, iTable, iField;
1348 : int iEDS;
1349 708 : int nExtraDSCount = 0;
1350 708 : OGRDataSource** papoExtraDS = NULL;
1351 708 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
1352 :
1353 1452 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
1354 : {
1355 754 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
1356 : OGRLayer *poSrcLayer;
1357 754 : OGRDataSource *poTableDS = this;
1358 :
1359 754 : if( psTableDef->data_source != NULL )
1360 : {
1361 : poTableDS = (OGRDataSource *)
1362 10 : OGROpenShared( psTableDef->data_source, FALSE, NULL );
1363 10 : 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 10 : sizeof(OGRDataSource*) * (nExtraDSCount + 1));
1378 10 : papoExtraDS[nExtraDSCount++] = poTableDS;
1379 : }
1380 :
1381 754 : poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
1382 :
1383 754 : if( poSrcLayer == NULL )
1384 : {
1385 : CPLError( CE_Failure, CPLE_AppDefined,
1386 : "SELECT from table %s failed, no such table/featureclass.",
1387 10 : psTableDef->table_name );
1388 10 : delete psSelectInfo;
1389 10 : goto end;
1390 : }
1391 :
1392 744 : nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
1393 : }
1394 :
1395 : /* -------------------------------------------------------------------- */
1396 : /* Build the field list for all indicated tables. */
1397 : /* -------------------------------------------------------------------- */
1398 :
1399 698 : sFieldList.table_count = psSelectInfo->table_count;
1400 698 : sFieldList.table_defs = psSelectInfo->table_defs;
1401 :
1402 698 : sFieldList.count = 0;
1403 698 : sFieldList.names = (char **) CPLMalloc( sizeof(char *) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1404 : sFieldList.types = (swq_field_type *)
1405 698 : CPLMalloc( sizeof(swq_field_type) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1406 : sFieldList.table_ids = (int *)
1407 698 : CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1408 : sFieldList.ids = (int *)
1409 698 : CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
1410 :
1411 1440 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
1412 : {
1413 742 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
1414 742 : OGRDataSource *poTableDS = this;
1415 : OGRLayer *poSrcLayer;
1416 :
1417 742 : if( psTableDef->data_source != NULL )
1418 : {
1419 : poTableDS = (OGRDataSource *)
1420 10 : OGROpenShared( psTableDef->data_source, FALSE, NULL );
1421 10 : CPLAssert( poTableDS != NULL );
1422 10 : poTableDS->Dereference();
1423 : }
1424 :
1425 742 : poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
1426 :
1427 7528 : for( iField = 0;
1428 3764 : iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
1429 : iField++ )
1430 : {
1431 3022 : OGRFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
1432 3022 : int iOutField = sFieldList.count++;
1433 3022 : sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
1434 3022 : if( poFDefn->GetType() == OFTInteger )
1435 730 : sFieldList.types[iOutField] = SWQ_INTEGER;
1436 2292 : else if( poFDefn->GetType() == OFTReal )
1437 918 : sFieldList.types[iOutField] = SWQ_FLOAT;
1438 1374 : else if( poFDefn->GetType() == OFTString )
1439 1282 : sFieldList.types[iOutField] = SWQ_STRING;
1440 : else
1441 92 : sFieldList.types[iOutField] = SWQ_OTHER;
1442 :
1443 3022 : sFieldList.table_ids[iOutField] = iTable;
1444 3022 : sFieldList.ids[iOutField] = iField;
1445 : }
1446 :
1447 742 : if( iTable == 0 )
1448 698 : nFIDIndex = poSrcLayer->GetLayerDefn()->GetFieldCount();
1449 : }
1450 :
1451 : /* -------------------------------------------------------------------- */
1452 : /* Expand '*' in 'SELECT *' now before we add the pseudo fields */
1453 : /* -------------------------------------------------------------------- */
1454 698 : if( psSelectInfo->expand_wildcard( &sFieldList ) != CE_None )
1455 : {
1456 0 : delete psSelectInfo;
1457 0 : goto end;
1458 : }
1459 :
1460 4188 : for (iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
1461 : {
1462 3490 : sFieldList.names[sFieldList.count] = (char*) SpecialFieldNames[iField];
1463 3490 : sFieldList.types[sFieldList.count] = SpecialFieldTypes[iField];
1464 3490 : sFieldList.table_ids[sFieldList.count] = 0;
1465 3490 : sFieldList.ids[sFieldList.count] = nFIDIndex + iField;
1466 3490 : sFieldList.count++;
1467 : }
1468 :
1469 : /* -------------------------------------------------------------------- */
1470 : /* Finish the parse operation. */
1471 : /* -------------------------------------------------------------------- */
1472 698 : if( psSelectInfo->parse( &sFieldList, 0 ) != CE_None )
1473 : {
1474 48 : delete psSelectInfo;
1475 48 : goto end;
1476 : }
1477 :
1478 : /* -------------------------------------------------------------------- */
1479 : /* Extract the WHERE expression to use separately. */
1480 : /* -------------------------------------------------------------------- */
1481 650 : if( psSelectInfo->where_expr != NULL )
1482 : {
1483 1026 : if (m_poDriver && (
1484 342 : EQUAL(m_poDriver->GetName(), "PostgreSQL") ||
1485 342 : EQUAL(m_poDriver->GetName(), "FileGDB" )) )
1486 0 : pszWHERE = psSelectInfo->where_expr->Unparse( &sFieldList, '"' );
1487 : else
1488 342 : 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 650 : pszDialect );
1500 :
1501 650 : CPLFree( pszWHERE );
1502 :
1503 : // Eventually, we should keep track of layers to cleanup.
1504 :
1505 : end:
1506 708 : CPLFree( sFieldList.names );
1507 708 : CPLFree( sFieldList.types );
1508 708 : CPLFree( sFieldList.table_ids );
1509 708 : 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 718 : for(iEDS = 0; iEDS < nExtraDSCount; iEDS++)
1516 10 : poReg->ReleaseDataSource( papoExtraDS[iEDS] );
1517 708 : CPLFree(papoExtraDS);
1518 :
1519 708 : return poResults;
1520 : }
1521 :
1522 : /************************************************************************/
1523 : /* OGR_DS_ExecuteSQL() */
1524 : /************************************************************************/
1525 :
1526 3282 : OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS,
1527 : const char *pszStatement,
1528 : OGRGeometryH hSpatialFilter,
1529 : const char *pszDialect )
1530 :
1531 : {
1532 3282 : VALIDATE_POINTER1( hDS, "OGR_DS_ExecuteSQL", NULL );
1533 :
1534 : return (OGRLayerH)
1535 : ((OGRDataSource *)hDS)->ExecuteSQL( pszStatement,
1536 : (OGRGeometry *) hSpatialFilter,
1537 3282 : pszDialect );
1538 : }
1539 :
1540 : /************************************************************************/
1541 : /* ReleaseResultSet() */
1542 : /************************************************************************/
1543 :
1544 692 : void OGRDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
1545 :
1546 : {
1547 692 : delete poResultsSet;
1548 692 : }
1549 :
1550 : /************************************************************************/
1551 : /* OGR_DS_ReleaseResultSet() */
1552 : /************************************************************************/
1553 :
1554 1078 : void OGR_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer )
1555 :
1556 : {
1557 1078 : VALIDATE_POINTER0( hDS, "OGR_DS_ReleaseResultSet" );
1558 :
1559 1078 : ((OGRDataSource *) hDS)->ReleaseResultSet( (OGRLayer *) hLayer );
1560 : }
1561 :
1562 : /************************************************************************/
1563 : /* OGR_DS_TestCapability() */
1564 : /************************************************************************/
1565 :
1566 104 : int OGR_DS_TestCapability( OGRDataSourceH hDS, const char *pszCap )
1567 :
1568 : {
1569 104 : VALIDATE_POINTER1( hDS, "OGR_DS_TestCapability", 0 );
1570 104 : VALIDATE_POINTER1( pszCap, "OGR_DS_TestCapability", 0 );
1571 :
1572 104 : return ((OGRDataSource *) hDS)->TestCapability( pszCap );
1573 : }
1574 :
1575 : /************************************************************************/
1576 : /* OGR_DS_GetLayerCount() */
1577 : /************************************************************************/
1578 :
1579 462 : int OGR_DS_GetLayerCount( OGRDataSourceH hDS )
1580 :
1581 : {
1582 462 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayerCount", 0 );
1583 :
1584 462 : return ((OGRDataSource *)hDS)->GetLayerCount();
1585 : }
1586 :
1587 : /************************************************************************/
1588 : /* OGR_DS_GetLayer() */
1589 : /************************************************************************/
1590 :
1591 6181 : OGRLayerH OGR_DS_GetLayer( OGRDataSourceH hDS, int iLayer )
1592 :
1593 : {
1594 6181 : VALIDATE_POINTER1( hDS, "OGR_DS_GetLayer", NULL );
1595 :
1596 6181 : return (OGRLayerH) ((OGRDataSource*)hDS)->GetLayer( iLayer );
1597 : }
1598 :
1599 : /************************************************************************/
1600 : /* OGR_DS_GetName() */
1601 : /************************************************************************/
1602 :
1603 62 : const char *OGR_DS_GetName( OGRDataSourceH hDS )
1604 :
1605 : {
1606 62 : VALIDATE_POINTER1( hDS, "OGR_DS_GetName", NULL );
1607 :
1608 62 : 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 5988 : OGRSFDriver *OGRDataSource::GetDriver() const
1654 :
1655 : {
1656 5988 : return m_poDriver;
1657 : }
1658 :
1659 : /************************************************************************/
1660 : /* OGR_DS_GetDriver() */
1661 : /************************************************************************/
1662 :
1663 44 : OGRSFDriverH OGR_DS_GetDriver( OGRDataSourceH hDS )
1664 :
1665 : {
1666 44 : VALIDATE_POINTER1( hDS, "OGR_DS_GetDriver", NULL );
1667 :
1668 44 : return (OGRSFDriverH) ((OGRDataSource *) hDS)->GetDriver();
1669 : }
1670 :
1671 : /************************************************************************/
1672 : /* SetDriver() */
1673 : /************************************************************************/
1674 :
1675 778 : void OGRDataSource::SetDriver( OGRSFDriver *poDriver )
1676 :
1677 : {
1678 778 : m_poDriver = poDriver;
1679 778 : }
1680 :
1681 : /************************************************************************/
1682 : /* GetStyleTable() */
1683 : /************************************************************************/
1684 :
1685 142 : OGRStyleTable *OGRDataSource::GetStyleTable()
1686 : {
1687 142 : 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 142 : void OGRDataSource::SetStyleTable(OGRStyleTable *poStyleTable)
1706 : {
1707 142 : if ( m_poStyleTable )
1708 0 : delete m_poStyleTable;
1709 142 : if ( poStyleTable )
1710 0 : m_poStyleTable = poStyleTable->Clone();
1711 142 : }
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 : }
|