1 : /******************************************************************************
2 : * $Id: ogr_gensql.cpp 17648 2009-09-17 15:11:18Z warmerdam $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRGenSQLResultsLayer.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
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 "ogr_p.h"
31 : #include "ogr_gensql.h"
32 : #include "cpl_string.h"
33 :
34 : CPL_CVSID("$Id: ogr_gensql.cpp 17648 2009-09-17 15:11:18Z warmerdam $");
35 :
36 : /************************************************************************/
37 : /* OGRGenSQLResultsLayer() */
38 : /************************************************************************/
39 :
40 49 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
41 : void *pSelectInfo,
42 49 : OGRGeometry *poSpatFilter )
43 :
44 : {
45 49 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
46 :
47 49 : this->poSrcDS = poSrcDS;
48 49 : this->pSelectInfo = pSelectInfo;
49 49 : poDefn = NULL;
50 49 : poSummaryFeature = NULL;
51 49 : panFIDIndex = NULL;
52 49 : nIndexSize = 0;
53 49 : nNextIndexFID = 0;
54 49 : nExtraDSCount = 0;
55 49 : papoExtraDS = NULL;
56 :
57 : /* -------------------------------------------------------------------- */
58 : /* Identify all the layers involved in the SELECT. */
59 : /* -------------------------------------------------------------------- */
60 : int iTable;
61 :
62 : papoTableLayers = (OGRLayer **)
63 49 : CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count );
64 :
65 111 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
66 : {
67 62 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
68 62 : OGRDataSource *poTableDS = poSrcDS;
69 :
70 62 : if( psTableDef->data_source != NULL )
71 : {
72 4 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
73 :
74 : poTableDS =
75 4 : poReg->OpenShared( psTableDef->data_source, FALSE, NULL );
76 4 : if( poTableDS == NULL )
77 : {
78 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
79 : CPLError( CE_Failure, CPLE_AppDefined,
80 : "Unable to open secondary datasource\n"
81 : "`%s' required by JOIN.",
82 0 : psTableDef->data_source );
83 0 : return;
84 : }
85 :
86 : papoExtraDS = (OGRDataSource **)
87 4 : CPLRealloc( papoExtraDS, sizeof(void*) * ++nExtraDSCount );
88 :
89 4 : papoExtraDS[nExtraDSCount-1] = poTableDS;
90 : }
91 :
92 62 : papoTableLayers[iTable] =
93 62 : poTableDS->GetLayerByName( psTableDef->table_name );
94 :
95 : CPLAssert( papoTableLayers[iTable] != NULL );
96 :
97 62 : if( papoTableLayers[iTable] == NULL )
98 0 : return;
99 : }
100 :
101 49 : poSrcLayer = papoTableLayers[0];
102 :
103 : /* -------------------------------------------------------------------- */
104 : /* Now that we have poSrcLayer, we can install a spatial filter */
105 : /* if there is one. */
106 : /* -------------------------------------------------------------------- */
107 49 : if( poSpatFilter != NULL )
108 0 : SetSpatialFilter( poSpatFilter );
109 :
110 : /* -------------------------------------------------------------------- */
111 : /* Prepare a feature definition based on the query. */
112 : /* -------------------------------------------------------------------- */
113 49 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
114 :
115 49 : poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
116 49 : poDefn->Reference();
117 :
118 49 : iFIDFieldIndex = poSrcDefn->GetFieldCount();
119 :
120 184 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
121 : {
122 135 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
123 135 : OGRFieldDefn oFDefn( psColDef->field_name, OFTInteger );
124 135 : OGRFieldDefn *poSrcFDefn = NULL;
125 : OGRFeatureDefn *poLayerDefn =
126 135 : papoTableLayers[psColDef->table_index]->GetLayerDefn();
127 :
128 135 : if( psColDef->field_index > -1
129 : && psColDef->field_index < poLayerDefn->GetFieldCount() )
130 125 : poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
131 :
132 135 : if( psColDef->field_alias != NULL )
133 : {
134 0 : oFDefn.SetName(psColDef->field_alias);
135 : }
136 135 : else if( psColDef->col_func_name != NULL )
137 : {
138 : oFDefn.SetName( CPLSPrintf( "%s_%s",psColDef->col_func_name,
139 3 : psColDef->field_name) );
140 : }
141 :
142 135 : if( psColDef->col_func == SWQCF_COUNT )
143 1 : oFDefn.SetType( OFTInteger );
144 134 : else if( poSrcFDefn != NULL )
145 : {
146 125 : oFDefn.SetType( poSrcFDefn->GetType() );
147 125 : oFDefn.SetWidth( poSrcFDefn->GetWidth() );
148 125 : oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
149 : }
150 9 : else if ( psColDef->field_index >= iFIDFieldIndex )
151 : {
152 9 : switch ( SpecialFieldTypes[psColDef->field_index-iFIDFieldIndex] )
153 : {
154 : case SWQ_INTEGER:
155 6 : oFDefn.SetType( OFTInteger );
156 6 : break;
157 : case SWQ_FLOAT:
158 1 : oFDefn.SetType( OFTReal );
159 1 : break;
160 : default:
161 2 : oFDefn.SetType( OFTString );
162 : break;
163 : }
164 : }
165 :
166 : /* setting up the target_type */
167 135 : switch (psColDef->target_type)
168 : {
169 : case SWQ_OTHER:
170 133 : break;
171 : case SWQ_INTEGER:
172 : case SWQ_BOOLEAN:
173 0 : oFDefn.SetType( OFTInteger );
174 0 : break;
175 : case SWQ_FLOAT:
176 1 : oFDefn.SetType( OFTReal );
177 1 : break;
178 : case SWQ_STRING:
179 1 : oFDefn.SetType( OFTString );
180 1 : break;
181 : case SWQ_TIMESTAMP:
182 0 : oFDefn.SetType( OFTDateTime );
183 0 : break;
184 : case SWQ_DATE:
185 0 : oFDefn.SetType( OFTDate );
186 0 : break;
187 : case SWQ_TIME:
188 0 : oFDefn.SetType( OFTTime );
189 : break;
190 : }
191 :
192 135 : if (psColDef->field_length > 0)
193 : {
194 2 : oFDefn.SetWidth( psColDef->field_length );
195 : }
196 :
197 135 : if (psColDef->field_precision >= 0)
198 : {
199 1 : oFDefn.SetPrecision( psColDef->field_precision );
200 : }
201 :
202 135 : poDefn->AddFieldDefn( &oFDefn );
203 : }
204 :
205 49 : poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() );
206 :
207 : /* -------------------------------------------------------------------- */
208 : /* If an ORDER BY is in effect, apply it now. */
209 : /* -------------------------------------------------------------------- */
210 49 : if( psSelectInfo->order_specs > 0
211 : && psSelectInfo->query_mode == SWQM_RECORDSET )
212 6 : CreateOrderByIndex();
213 :
214 49 : ResetReading();
215 0 : }
216 :
217 : /************************************************************************/
218 : /* ~OGRGenSQLResultsLayer() */
219 : /************************************************************************/
220 :
221 98 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
222 :
223 : {
224 49 : if( m_nFeaturesRead > 0 && poDefn != NULL )
225 : {
226 : CPLDebug( "GenSQL", "%d features read on layer '%s'.",
227 : (int) m_nFeaturesRead,
228 33 : poDefn->GetName() );
229 : }
230 :
231 49 : ClearFilters();
232 :
233 : /* -------------------------------------------------------------------- */
234 : /* Free various datastructures. */
235 : /* -------------------------------------------------------------------- */
236 49 : CPLFree( papoTableLayers );
237 49 : papoTableLayers = NULL;
238 :
239 49 : if( panFIDIndex != NULL )
240 6 : CPLFree( panFIDIndex );
241 :
242 49 : if( poSummaryFeature )
243 11 : delete poSummaryFeature;
244 :
245 49 : if( pSelectInfo != NULL )
246 49 : swq_select_free( (swq_select *) pSelectInfo );
247 :
248 49 : if( poDefn != NULL )
249 : {
250 49 : poDefn->Release();
251 : }
252 :
253 : /* -------------------------------------------------------------------- */
254 : /* Release any additional datasources being used in joins. */
255 : /* -------------------------------------------------------------------- */
256 49 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
257 :
258 53 : for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ )
259 4 : poReg->ReleaseDataSource( papoExtraDS[iEDS] );
260 :
261 49 : CPLFree( papoExtraDS );
262 98 : }
263 :
264 : /************************************************************************/
265 : /* ClearFilters() */
266 : /* */
267 : /* Clear up all filters currently in place on the target layer, */
268 : /* and joined layers. We try not to leave them installed */
269 : /* except when actively fetching features. */
270 : /************************************************************************/
271 :
272 59 : void OGRGenSQLResultsLayer::ClearFilters()
273 :
274 : {
275 : /* -------------------------------------------------------------------- */
276 : /* Clear any filters installed on the target layer. */
277 : /* -------------------------------------------------------------------- */
278 59 : if( poSrcLayer != NULL )
279 : {
280 59 : poSrcLayer->SetAttributeFilter( "" );
281 59 : poSrcLayer->SetSpatialFilter( NULL );
282 : }
283 :
284 : /* -------------------------------------------------------------------- */
285 : /* Clear any attribute filter installed on the joined layers. */
286 : /* -------------------------------------------------------------------- */
287 59 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
288 : int iJoin;
289 :
290 59 : if( psSelectInfo != NULL )
291 : {
292 72 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
293 : {
294 13 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
295 : OGRLayer *poJoinLayer =
296 13 : papoTableLayers[psJoinInfo->secondary_table];
297 :
298 13 : poJoinLayer->SetAttributeFilter( "" );
299 : }
300 : }
301 59 : }
302 :
303 : /************************************************************************/
304 : /* ResetReading() */
305 : /************************************************************************/
306 :
307 64 : void OGRGenSQLResultsLayer::ResetReading()
308 :
309 : {
310 64 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
311 :
312 64 : if( psSelectInfo->query_mode == SWQM_RECORDSET )
313 : {
314 53 : poSrcLayer->SetAttributeFilter( psSelectInfo->whole_where_clause );
315 :
316 53 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
317 :
318 53 : poSrcLayer->ResetReading();
319 : }
320 :
321 64 : nNextIndexFID = 0;
322 64 : }
323 :
324 : /************************************************************************/
325 : /* SetNextByIndex() */
326 : /* */
327 : /* If we already have an FID list, we can easily resposition */
328 : /* ourselves in it. */
329 : /************************************************************************/
330 :
331 0 : OGRErr OGRGenSQLResultsLayer::SetNextByIndex( long nIndex )
332 :
333 : {
334 0 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
335 :
336 0 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
337 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
338 : || panFIDIndex != NULL )
339 : {
340 0 : nNextIndexFID = nIndex;
341 0 : return OGRERR_NONE;
342 : }
343 : else
344 : {
345 0 : return poSrcLayer->SetNextByIndex( nIndex );
346 : }
347 : }
348 :
349 : /************************************************************************/
350 : /* GetExtent() */
351 : /************************************************************************/
352 :
353 1 : OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent,
354 : int bForce )
355 :
356 : {
357 1 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
358 :
359 1 : if( psSelectInfo->query_mode == SWQM_RECORDSET )
360 1 : return poSrcLayer->GetExtent( psExtent, bForce );
361 : else
362 0 : return OGRERR_FAILURE;
363 : }
364 :
365 : /************************************************************************/
366 : /* GetSpatialRef() */
367 : /************************************************************************/
368 :
369 7 : OGRSpatialReference *OGRGenSQLResultsLayer::GetSpatialRef()
370 :
371 : {
372 7 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
373 :
374 7 : if( psSelectInfo->query_mode != SWQM_RECORDSET )
375 0 : return NULL;
376 : else
377 7 : return poSrcLayer->GetSpatialRef();
378 : }
379 :
380 : /************************************************************************/
381 : /* GetFeatureCount() */
382 : /************************************************************************/
383 :
384 9 : int OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
385 :
386 : {
387 9 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
388 :
389 9 : if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
390 : {
391 2 : if( !PrepareSummary() )
392 0 : return 0;
393 :
394 2 : swq_summary *psSummary = psSelectInfo->column_summary + 0;
395 :
396 2 : if( psSummary == NULL )
397 0 : return 0;
398 :
399 2 : return psSummary->count;
400 : }
401 7 : else if( psSelectInfo->query_mode != SWQM_RECORDSET )
402 0 : return 1;
403 7 : else if( m_poAttrQuery == NULL )
404 7 : return poSrcLayer->GetFeatureCount( bForce );
405 : else
406 0 : return OGRLayer::GetFeatureCount( bForce );
407 : }
408 :
409 : /************************************************************************/
410 : /* TestCapability() */
411 : /************************************************************************/
412 :
413 0 : int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
414 :
415 : {
416 0 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
417 :
418 0 : if( EQUAL(pszCap,OLCFastSetNextByIndex) )
419 : {
420 0 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
421 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
422 : || panFIDIndex != NULL )
423 0 : return TRUE;
424 : else
425 0 : return poSrcLayer->TestCapability( pszCap );
426 : }
427 :
428 0 : if( psSelectInfo->query_mode == SWQM_RECORDSET
429 : && (EQUAL(pszCap,OLCFastFeatureCount)
430 : || EQUAL(pszCap,OLCRandomRead)
431 : || EQUAL(pszCap,OLCFastGetExtent)) )
432 0 : return poSrcLayer->TestCapability( pszCap );
433 :
434 0 : else if( psSelectInfo->query_mode != SWQM_RECORDSET )
435 : {
436 0 : if( EQUAL(pszCap,OLCFastFeatureCount) )
437 0 : return TRUE;
438 : }
439 :
440 0 : return FALSE;
441 : }
442 :
443 : /************************************************************************/
444 : /* PrepareSummary() */
445 : /************************************************************************/
446 :
447 62 : int OGRGenSQLResultsLayer::PrepareSummary()
448 :
449 : {
450 62 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
451 :
452 62 : if( poSummaryFeature != NULL )
453 51 : return TRUE;
454 :
455 11 : poSummaryFeature = new OGRFeature( poDefn );
456 11 : poSummaryFeature->SetFID( 0 );
457 :
458 : /* -------------------------------------------------------------------- */
459 : /* Ensure our query parameters are in place on the source */
460 : /* layer. And initialize reading. */
461 : /* -------------------------------------------------------------------- */
462 11 : poSrcLayer->SetAttributeFilter( psSelectInfo->whole_where_clause );
463 :
464 11 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
465 :
466 11 : poSrcLayer->ResetReading();
467 :
468 : /* -------------------------------------------------------------------- */
469 : /* We treat COUNT(*) (or COUNT of anything without distinct) as */
470 : /* a special case, and fill with GetFeatureCount(). */
471 : /* -------------------------------------------------------------------- */
472 :
473 23 : if( psSelectInfo->result_columns == 1
474 11 : && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
475 1 : && !psSelectInfo->column_defs[0].distinct_flag )
476 : {
477 1 : poSummaryFeature->SetField( 0, poSrcLayer->GetFeatureCount( TRUE ) );
478 1 : return TRUE;
479 : }
480 :
481 : /* -------------------------------------------------------------------- */
482 : /* Otherwise, process all source feature through the summary */
483 : /* building facilities of SWQ. */
484 : /* -------------------------------------------------------------------- */
485 : const char *pszError;
486 : OGRFeature *poSrcFeature;
487 :
488 203 : while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
489 : {
490 366 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
491 : {
492 183 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
493 :
494 : pszError = swq_select_summarize( psSelectInfo, iField,
495 : poSrcFeature->GetFieldAsString(
496 183 : psColDef->field_index ) );
497 :
498 183 : if( pszError != NULL )
499 : {
500 0 : delete poSummaryFeature;
501 0 : poSummaryFeature = NULL;
502 :
503 0 : CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
504 0 : return FALSE;
505 : }
506 : }
507 :
508 183 : delete poSrcFeature;
509 : }
510 :
511 10 : pszError = swq_select_finish_summarize( psSelectInfo );
512 10 : if( pszError != NULL )
513 : {
514 0 : delete poSummaryFeature;
515 0 : poSummaryFeature = NULL;
516 :
517 0 : CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
518 0 : return FALSE;
519 : }
520 :
521 : /* -------------------------------------------------------------------- */
522 : /* If we have run out of features on the source layer, clear */
523 : /* away the filters we have installed till a next run through */
524 : /* the features. */
525 : /* -------------------------------------------------------------------- */
526 10 : if( poSrcFeature == NULL )
527 10 : ClearFilters();
528 :
529 : /* -------------------------------------------------------------------- */
530 : /* Now apply the values to the summary feature. If we are in */
531 : /* DISTINCT_LIST mode we don't do this step. */
532 : /* -------------------------------------------------------------------- */
533 10 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
534 : && psSelectInfo->column_summary != NULL )
535 : {
536 2 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
537 : {
538 1 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
539 1 : swq_summary *psSummary = psSelectInfo->column_summary + iField;
540 :
541 1 : if( psColDef->col_func == SWQCF_AVG )
542 : poSummaryFeature->SetField( iField,
543 0 : psSummary->sum / psSummary->count );
544 1 : else if( psColDef->col_func == SWQCF_MIN )
545 0 : poSummaryFeature->SetField( iField, psSummary->min );
546 1 : else if( psColDef->col_func == SWQCF_MAX )
547 1 : poSummaryFeature->SetField( iField, psSummary->max );
548 0 : else if( psColDef->col_func == SWQCF_COUNT )
549 0 : poSummaryFeature->SetField( iField, psSummary->count );
550 0 : else if( psColDef->col_func == SWQCF_SUM )
551 0 : poSummaryFeature->SetField( iField, psSummary->sum );
552 : }
553 : }
554 :
555 10 : return TRUE;
556 : }
557 :
558 : /************************************************************************/
559 : /* TranslateFeature() */
560 : /************************************************************************/
561 :
562 119 : OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
563 :
564 : {
565 119 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
566 : OGRFeature *poDstFeat;
567 :
568 119 : if( poSrcFeat == NULL )
569 0 : return NULL;
570 :
571 119 : m_nFeaturesRead++;
572 :
573 : /* -------------------------------------------------------------------- */
574 : /* Create destination feature. */
575 : /* -------------------------------------------------------------------- */
576 119 : poDstFeat = new OGRFeature( poDefn );
577 :
578 119 : poDstFeat->SetFID( poSrcFeat->GetFID() );
579 :
580 119 : poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
581 :
582 119 : poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
583 :
584 : /* -------------------------------------------------------------------- */
585 : /* Copy fields from primary record to the destination feature. */
586 : /* -------------------------------------------------------------------- */
587 567 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
588 : {
589 448 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
590 :
591 448 : if( psColDef->table_index != 0 )
592 130 : continue;
593 :
594 337 : if ( psColDef->field_index >= iFIDFieldIndex &&
595 : psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
596 : {
597 19 : switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
598 : {
599 : case SWQ_INTEGER:
600 6 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
601 6 : break;
602 : case SWQ_FLOAT:
603 1 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
604 1 : break;
605 : default:
606 12 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
607 : }
608 : }
609 : else
610 : {
611 299 : switch (psColDef->target_type)
612 : {
613 : case SWQ_INTEGER:
614 0 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
615 0 : break;
616 :
617 : case SWQ_FLOAT:
618 2 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
619 2 : break;
620 :
621 : case SWQ_STRING:
622 : case SWQ_TIMESTAMP:
623 : case SWQ_DATE:
624 : case SWQ_TIME:
625 0 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
626 0 : break;
627 :
628 : default:
629 : poDstFeat->SetField( iField,
630 297 : poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
631 : }
632 : }
633 : }
634 :
635 : /* -------------------------------------------------------------------- */
636 : /* Copy values from any joined tables. */
637 : /* -------------------------------------------------------------------- */
638 : int iJoin;
639 :
640 175 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
641 : {
642 : char szFilter[512];
643 :
644 56 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
645 56 : OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
646 :
647 : // if source key is null, we can't do join.
648 56 : if( !poSrcFeat->IsFieldSet( psJoinInfo->primary_field ) )
649 0 : continue;
650 :
651 : // Prepare attribute query to express fetching on the joined variable
652 : sprintf( szFilter, "%s = ",
653 56 : poJoinLayer->GetLayerDefn()->GetFieldDefn(
654 112 : psJoinInfo->secondary_field )->GetNameRef() );
655 :
656 : OGRField *psSrcField =
657 56 : poSrcFeat->GetRawFieldRef(psJoinInfo->primary_field);
658 :
659 56 : switch( poSrcLayer->GetLayerDefn()->GetFieldDefn(
660 : psJoinInfo->primary_field )->GetType() )
661 : {
662 : case OFTInteger:
663 12 : sprintf( szFilter+strlen(szFilter), "%d", psSrcField->Integer );
664 12 : break;
665 :
666 : case OFTReal:
667 44 : sprintf( szFilter+strlen(szFilter), "%.16g", psSrcField->Real );
668 44 : break;
669 :
670 : case OFTString:
671 : {
672 : char *pszEscaped = CPLEscapeString( psSrcField->String,
673 : strlen(psSrcField->String),
674 0 : CPLES_SQL );
675 0 : if( strlen(pszEscaped) + strlen(szFilter) < sizeof(szFilter)-3 )
676 : sprintf( szFilter+strlen(szFilter), "\'%s\'",
677 0 : pszEscaped );
678 : else
679 : {
680 0 : strcat( szFilter, "' '" );
681 0 : CPLDebug( "GenSQL", "Skip long join field value." );
682 : }
683 0 : CPLFree( pszEscaped );
684 : }
685 0 : break;
686 :
687 : default:
688 : CPLAssert( FALSE );
689 0 : continue;
690 : }
691 :
692 56 : poJoinLayer->ResetReading();
693 56 : if( poJoinLayer->SetAttributeFilter( szFilter ) != OGRERR_NONE )
694 0 : continue;
695 :
696 : // Fetch first joined feature.
697 : OGRFeature *poJoinFeature;
698 :
699 56 : poJoinFeature = poJoinLayer->GetNextFeature();
700 :
701 56 : if( poJoinFeature == NULL )
702 24 : continue;
703 :
704 : // Copy over selected field values.
705 150 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
706 : {
707 118 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
708 :
709 118 : if( psColDef->table_index == psJoinInfo->secondary_table )
710 : poDstFeat->SetField( iField,
711 : poJoinFeature->GetRawFieldRef(
712 48 : psColDef->field_index ) );
713 : }
714 :
715 32 : delete poJoinFeature;
716 : }
717 :
718 119 : return poDstFeat;
719 : }
720 :
721 : /************************************************************************/
722 : /* GetNextFeature() */
723 : /************************************************************************/
724 :
725 210 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
726 :
727 : {
728 210 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
729 :
730 : /* -------------------------------------------------------------------- */
731 : /* Handle summary sets. */
732 : /* -------------------------------------------------------------------- */
733 210 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
734 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
735 60 : return GetFeature( nNextIndexFID++ );
736 :
737 : /* -------------------------------------------------------------------- */
738 : /* Handle ordered sets. */
739 : /* -------------------------------------------------------------------- */
740 0 : while( TRUE )
741 : {
742 : OGRFeature *poFeature;
743 :
744 150 : if( panFIDIndex != NULL )
745 25 : poFeature = GetFeature( nNextIndexFID++ );
746 : else
747 : {
748 125 : OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
749 :
750 125 : if( poSrcFeat == NULL )
751 25 : return NULL;
752 :
753 100 : poFeature = TranslateFeature( poSrcFeat );
754 100 : delete poSrcFeat;
755 : }
756 :
757 125 : if( poFeature == NULL )
758 6 : return NULL;
759 :
760 119 : if( m_poAttrQuery == NULL
761 : || m_poAttrQuery->Evaluate( poFeature ) )
762 119 : return poFeature;
763 :
764 0 : delete poFeature;
765 : }
766 :
767 : return NULL;
768 : }
769 :
770 : /************************************************************************/
771 : /* GetFeature() */
772 : /************************************************************************/
773 :
774 85 : OGRFeature *OGRGenSQLResultsLayer::GetFeature( long nFID )
775 :
776 : {
777 85 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
778 :
779 : /* -------------------------------------------------------------------- */
780 : /* Handle request for summary record. */
781 : /* -------------------------------------------------------------------- */
782 85 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
783 : {
784 6 : if( !PrepareSummary() || nFID != 0 || poSummaryFeature == NULL )
785 3 : return NULL;
786 : else
787 3 : return poSummaryFeature->Clone();
788 : }
789 :
790 : /* -------------------------------------------------------------------- */
791 : /* Handle request for distinct list record. */
792 : /* -------------------------------------------------------------------- */
793 79 : if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
794 : {
795 54 : if( !PrepareSummary() )
796 0 : return NULL;
797 :
798 54 : swq_summary *psSummary = psSelectInfo->column_summary + 0;
799 :
800 54 : if( psSummary == NULL )
801 1 : return NULL;
802 :
803 53 : if( nFID < 0 || nFID >= psSummary->count )
804 6 : return NULL;
805 :
806 47 : poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
807 47 : poSummaryFeature->SetFID( nFID );
808 :
809 47 : return poSummaryFeature->Clone();
810 : }
811 :
812 : /* -------------------------------------------------------------------- */
813 : /* Are we running in sorted mode? If so, run the fid through */
814 : /* the index. */
815 : /* -------------------------------------------------------------------- */
816 25 : if( panFIDIndex != NULL )
817 : {
818 25 : if( nFID < 0 || nFID >= nIndexSize )
819 6 : return NULL;
820 : else
821 19 : nFID = panFIDIndex[nFID];
822 : }
823 :
824 : /* -------------------------------------------------------------------- */
825 : /* Handle request for random record. */
826 : /* -------------------------------------------------------------------- */
827 19 : OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
828 : OGRFeature *poResult;
829 :
830 19 : if( poSrcFeature == NULL )
831 0 : return NULL;
832 :
833 19 : poResult = TranslateFeature( poSrcFeature );
834 19 : poResult->SetFID( nFID );
835 :
836 19 : delete poSrcFeature;
837 :
838 19 : return poResult;
839 : }
840 :
841 : /************************************************************************/
842 : /* GetSpatialFilter() */
843 : /************************************************************************/
844 :
845 0 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
846 :
847 : {
848 0 : return NULL;
849 : }
850 :
851 : /************************************************************************/
852 : /* GetLayerDefn() */
853 : /************************************************************************/
854 :
855 102 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
856 :
857 : {
858 102 : return poDefn;
859 : }
860 :
861 : /************************************************************************/
862 : /* CreateOrderByIndex() */
863 : /* */
864 : /* This method is responsible for creating an index providing */
865 : /* ordered access to the features according to the supplied */
866 : /* ORDER BY clauses. */
867 : /* */
868 : /* This is accomplished by making one pass through all the */
869 : /* eligible source features, and capturing the order by fields */
870 : /* of all records in memory. A quick sort is then applied to */
871 : /* this in memory copy of the order-by fields to create the */
872 : /* required index. */
873 : /* */
874 : /* Keeping all the key values in memory will *not* scale up to */
875 : /* very large input datasets. */
876 : /************************************************************************/
877 :
878 6 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
879 :
880 : {
881 6 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
882 : OGRField *pasIndexFields;
883 6 : int i, nOrderItems = psSelectInfo->order_specs;
884 : long *panFIDList;
885 :
886 6 : if( nOrderItems == 0 )
887 0 : return;
888 :
889 6 : ResetReading();
890 :
891 : /* -------------------------------------------------------------------- */
892 : /* Allocate set of key values, and the output index. */
893 : /* -------------------------------------------------------------------- */
894 6 : nIndexSize = poSrcLayer->GetFeatureCount();
895 :
896 : pasIndexFields = (OGRField *)
897 6 : CPLCalloc(sizeof(OGRField), nOrderItems * nIndexSize);
898 6 : panFIDIndex = (long *) CPLCalloc(sizeof(long),nIndexSize);
899 6 : panFIDList = (long *) CPLCalloc(sizeof(long),nIndexSize);
900 :
901 25 : for( i = 0; i < nIndexSize; i++ )
902 19 : panFIDIndex[i] = i;
903 :
904 : /* -------------------------------------------------------------------- */
905 : /* Read in all the key values. */
906 : /* -------------------------------------------------------------------- */
907 : OGRFeature *poSrcFeat;
908 6 : int iFeature = 0;
909 :
910 31 : while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
911 : {
912 : int iKey;
913 :
914 38 : for( iKey = 0; iKey < nOrderItems; iKey++ )
915 : {
916 19 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
917 : OGRFieldDefn *poFDefn;
918 : OGRField *psSrcField, *psDstField;
919 :
920 19 : psDstField = pasIndexFields + iFeature * nOrderItems + iKey;
921 :
922 19 : if ( psKeyDef->field_index >= iFIDFieldIndex)
923 : {
924 0 : if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
925 : {
926 0 : switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
927 : {
928 : case SWQ_INTEGER:
929 0 : psDstField->Integer = poSrcFeat->GetFieldAsInteger(psKeyDef->field_index);
930 0 : break;
931 :
932 : case SWQ_FLOAT:
933 0 : psDstField->Real = poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
934 0 : break;
935 :
936 : default:
937 0 : psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
938 : break;
939 : }
940 : }
941 0 : continue;
942 : }
943 :
944 19 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
945 38 : psKeyDef->field_index );
946 :
947 19 : psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
948 :
949 19 : if( poFDefn->GetType() == OFTInteger
950 : || poFDefn->GetType() == OFTReal
951 : || poFDefn->GetType() == OFTDate
952 : || poFDefn->GetType() == OFTTime
953 : || poFDefn->GetType() == OFTDateTime)
954 19 : memcpy( psDstField, psSrcField, sizeof(OGRField) );
955 0 : else if( poFDefn->GetType() == OFTString )
956 : {
957 0 : if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
958 0 : psDstField->String = CPLStrdup( psSrcField->String );
959 : else
960 0 : memcpy( psDstField, psSrcField, sizeof(OGRField) );
961 : }
962 : }
963 :
964 19 : panFIDList[iFeature] = poSrcFeat->GetFID();
965 19 : delete poSrcFeat;
966 :
967 19 : iFeature++;
968 : }
969 :
970 : CPLAssert( nIndexSize == iFeature );
971 :
972 : /* -------------------------------------------------------------------- */
973 : /* Quick sort the records. */
974 : /* -------------------------------------------------------------------- */
975 6 : SortIndexSection( pasIndexFields, 0, nIndexSize );
976 :
977 : /* -------------------------------------------------------------------- */
978 : /* Rework the FID map to map to real FIDs. */
979 : /* -------------------------------------------------------------------- */
980 25 : for( i = 0; i < nIndexSize; i++ )
981 19 : panFIDIndex[i] = panFIDList[panFIDIndex[i]];
982 :
983 6 : CPLFree( panFIDList );
984 :
985 : /* -------------------------------------------------------------------- */
986 : /* Free the key field values. */
987 : /* -------------------------------------------------------------------- */
988 12 : for( int iKey = 0; iKey < nOrderItems; iKey++ )
989 : {
990 6 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
991 : OGRFieldDefn *poFDefn;
992 :
993 6 : if ( psKeyDef->field_index >= iFIDFieldIndex &&
994 : psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
995 : {
996 : /* warning: only special fields of type string should be deallocated */
997 0 : if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
998 : {
999 0 : for( i = 0; i < nIndexSize; i++ )
1000 : {
1001 0 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1002 0 : CPLFree( psField->String );
1003 : }
1004 : }
1005 0 : continue;
1006 : }
1007 :
1008 6 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1009 12 : psKeyDef->field_index );
1010 :
1011 6 : if( poFDefn->GetType() == OFTString )
1012 : {
1013 0 : for( i = 0; i < nIndexSize; i++ )
1014 : {
1015 0 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1016 :
1017 0 : if( psField->Set.nMarker1 != OGRUnsetMarker
1018 : || psField->Set.nMarker2 != OGRUnsetMarker )
1019 0 : CPLFree( psField->String );
1020 : }
1021 : }
1022 : }
1023 :
1024 6 : CPLFree( pasIndexFields );
1025 : }
1026 :
1027 : /************************************************************************/
1028 : /* SortIndexSection() */
1029 : /* */
1030 : /* Sort the records in a section of the index. */
1031 : /************************************************************************/
1032 :
1033 32 : void OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
1034 : int nStart, int nEntries )
1035 :
1036 : {
1037 32 : if( nEntries < 2 )
1038 19 : return;
1039 :
1040 13 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1041 13 : int nOrderItems = psSelectInfo->order_specs;
1042 :
1043 13 : int nFirstGroup = nEntries / 2;
1044 13 : int nFirstStart = nStart;
1045 13 : int nSecondGroup = nEntries - nFirstGroup;
1046 13 : int nSecondStart = nStart + nFirstGroup;
1047 13 : int iMerge = 0;
1048 : long *panMerged;
1049 :
1050 13 : SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup );
1051 13 : SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup );
1052 :
1053 13 : panMerged = (long *) CPLMalloc( sizeof(long) * nEntries );
1054 :
1055 59 : while( iMerge < nEntries )
1056 : {
1057 : int nResult;
1058 :
1059 33 : if( nFirstGroup == 0 )
1060 1 : nResult = -1;
1061 32 : else if( nSecondGroup == 0 )
1062 12 : nResult = 1;
1063 : else
1064 : nResult = Compare( pasIndexFields
1065 20 : + panFIDIndex[nFirstStart] * nOrderItems,
1066 : pasIndexFields
1067 40 : + panFIDIndex[nSecondStart] * nOrderItems );
1068 :
1069 33 : if( nResult < 0 )
1070 : {
1071 17 : panMerged[iMerge++] = panFIDIndex[nSecondStart++];
1072 17 : nSecondGroup--;
1073 : }
1074 : else
1075 : {
1076 16 : panMerged[iMerge++] = panFIDIndex[nFirstStart++];
1077 16 : nFirstGroup--;
1078 : }
1079 : }
1080 :
1081 : /* Copy the merge list back into the main index */
1082 :
1083 13 : memcpy( panFIDIndex + nStart, panMerged, sizeof(long) * nEntries );
1084 13 : CPLFree( panMerged );
1085 : }
1086 :
1087 :
1088 : /************************************************************************/
1089 : /* OGRGenSQLCompareDate() */
1090 : /************************************************************************/
1091 :
1092 0 : static int OGRGenSQLCompareDate( OGRField *psFirstTuple,
1093 : OGRField *psSecondTuple )
1094 : {
1095 : /* FIXME? : We ignore TZFlag */
1096 :
1097 0 : if (psFirstTuple->Date.Year < psSecondTuple->Date.Year)
1098 0 : return -1;
1099 0 : else if (psFirstTuple->Date.Year > psSecondTuple->Date.Year)
1100 0 : return 1;
1101 :
1102 0 : if (psFirstTuple->Date.Month < psSecondTuple->Date.Month)
1103 0 : return -1;
1104 0 : else if (psFirstTuple->Date.Month > psSecondTuple->Date.Month)
1105 0 : return 1;
1106 :
1107 0 : if (psFirstTuple->Date.Day < psSecondTuple->Date.Day)
1108 0 : return -1;
1109 0 : else if (psFirstTuple->Date.Day > psSecondTuple->Date.Day)
1110 0 : return 1;
1111 :
1112 0 : if (psFirstTuple->Date.Hour < psSecondTuple->Date.Hour)
1113 0 : return -1;
1114 0 : else if (psFirstTuple->Date.Hour > psSecondTuple->Date.Hour)
1115 0 : return 1;
1116 :
1117 0 : if (psFirstTuple->Date.Minute < psSecondTuple->Date.Minute)
1118 0 : return -1;
1119 0 : else if (psFirstTuple->Date.Minute > psSecondTuple->Date.Minute)
1120 0 : return 1;
1121 :
1122 0 : if (psFirstTuple->Date.Second < psSecondTuple->Date.Second)
1123 0 : return -1;
1124 0 : else if (psFirstTuple->Date.Second > psSecondTuple->Date.Second)
1125 0 : return 1;
1126 :
1127 0 : return 0;
1128 : }
1129 :
1130 : /************************************************************************/
1131 : /* Compare() */
1132 : /************************************************************************/
1133 :
1134 20 : int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
1135 : OGRField *pasSecondTuple )
1136 :
1137 : {
1138 20 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1139 20 : int nResult = 0, iKey;
1140 :
1141 40 : for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
1142 : {
1143 20 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1144 : OGRFieldDefn *poFDefn;
1145 :
1146 20 : if( psKeyDef->field_index >= iFIDFieldIndex )
1147 0 : poFDefn = NULL;
1148 : else
1149 20 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1150 40 : psKeyDef->field_index );
1151 :
1152 40 : if( (pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker
1153 0 : && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker)
1154 20 : || (pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
1155 0 : && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker) )
1156 0 : nResult = 0;
1157 20 : else if ( poFDefn == NULL )
1158 : {
1159 0 : switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
1160 : {
1161 : case SWQ_INTEGER:
1162 0 : if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
1163 0 : nResult = -1;
1164 0 : else if( pasFirstTuple[iKey].Integer > pasSecondTuple[iKey].Integer )
1165 0 : nResult = 1;
1166 0 : break;
1167 : case SWQ_FLOAT:
1168 0 : if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
1169 0 : nResult = -1;
1170 0 : else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
1171 0 : nResult = 1;
1172 0 : break;
1173 : case SWQ_STRING:
1174 0 : nResult = strcmp(pasFirstTuple[iKey].String,
1175 0 : pasSecondTuple[iKey].String);
1176 0 : break;
1177 :
1178 : default:
1179 : CPLAssert( FALSE );
1180 0 : nResult = 0;
1181 : }
1182 : }
1183 20 : else if( poFDefn->GetType() == OFTInteger )
1184 : {
1185 0 : if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
1186 0 : nResult = -1;
1187 0 : else if( pasFirstTuple[iKey].Integer
1188 0 : > pasSecondTuple[iKey].Integer )
1189 0 : nResult = 1;
1190 : }
1191 20 : else if( poFDefn->GetType() == OFTString )
1192 0 : nResult = strcmp(pasFirstTuple[iKey].String,
1193 0 : pasSecondTuple[iKey].String);
1194 20 : else if( poFDefn->GetType() == OFTReal )
1195 : {
1196 20 : if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
1197 4 : nResult = -1;
1198 16 : else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
1199 16 : nResult = 1;
1200 : }
1201 0 : else if( poFDefn->GetType() == OFTDate ||
1202 : poFDefn->GetType() == OFTTime ||
1203 : poFDefn->GetType() == OFTDateTime)
1204 : {
1205 : nResult = OGRGenSQLCompareDate(&pasFirstTuple[iKey],
1206 0 : &pasSecondTuple[iKey]);
1207 : }
1208 :
1209 20 : if( psKeyDef->ascending_flag )
1210 20 : nResult *= -1;
1211 : }
1212 :
1213 20 : return nResult;
1214 : }
|