1 : /******************************************************************************
2 : * $Id: ogr_gensql.cpp 19722 2010-05-15 11:35:37Z rouault $
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 19722 2010-05-15 11:35:37Z rouault $");
35 :
36 : /************************************************************************/
37 : /* OGRGenSQLResultsLayer() */
38 : /************************************************************************/
39 :
40 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
41 : void *pSelectInfo,
42 63 : OGRGeometry *poSpatFilter )
43 :
44 : {
45 63 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
46 :
47 63 : this->poSrcDS = poSrcDS;
48 63 : this->pSelectInfo = pSelectInfo;
49 63 : poDefn = NULL;
50 63 : poSummaryFeature = NULL;
51 63 : panFIDIndex = NULL;
52 63 : nIndexSize = 0;
53 63 : nNextIndexFID = 0;
54 63 : nExtraDSCount = 0;
55 63 : papoExtraDS = NULL;
56 :
57 : /* -------------------------------------------------------------------- */
58 : /* Identify all the layers involved in the SELECT. */
59 : /* -------------------------------------------------------------------- */
60 : int iTable;
61 :
62 : papoTableLayers = (OGRLayer **)
63 63 : CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count );
64 :
65 140 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
66 : {
67 77 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
68 77 : OGRDataSource *poTableDS = poSrcDS;
69 :
70 77 : 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 : papoTableLayers[iTable] =
93 77 : poTableDS->GetLayerByName( psTableDef->table_name );
94 :
95 77 : CPLAssert( papoTableLayers[iTable] != NULL );
96 :
97 77 : if( papoTableLayers[iTable] == NULL )
98 0 : return;
99 : }
100 :
101 63 : poSrcLayer = papoTableLayers[0];
102 :
103 : /* -------------------------------------------------------------------- */
104 : /* Now that we have poSrcLayer, we can install a spatial filter */
105 : /* if there is one. */
106 : /* -------------------------------------------------------------------- */
107 63 : if( poSpatFilter != NULL )
108 0 : SetSpatialFilter( poSpatFilter );
109 :
110 : /* -------------------------------------------------------------------- */
111 : /* Prepare a feature definition based on the query. */
112 : /* -------------------------------------------------------------------- */
113 63 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
114 :
115 63 : poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
116 63 : poDefn->Reference();
117 :
118 63 : iFIDFieldIndex = poSrcDefn->GetFieldCount();
119 :
120 235 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
121 : {
122 172 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
123 172 : OGRFieldDefn oFDefn( psColDef->field_name, OFTInteger );
124 172 : OGRFieldDefn *poSrcFDefn = NULL;
125 : OGRFeatureDefn *poLayerDefn =
126 172 : papoTableLayers[psColDef->table_index]->GetLayerDefn();
127 :
128 172 : if( psColDef->field_index > -1
129 : && psColDef->field_index < poLayerDefn->GetFieldCount() )
130 162 : poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
131 :
132 172 : if( psColDef->field_alias != NULL )
133 : {
134 0 : oFDefn.SetName(psColDef->field_alias);
135 : }
136 172 : 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 172 : if( psColDef->col_func == SWQCF_COUNT )
143 1 : oFDefn.SetType( OFTInteger );
144 171 : else if( poSrcFDefn != NULL )
145 : {
146 162 : oFDefn.SetType( poSrcFDefn->GetType() );
147 162 : oFDefn.SetWidth( poSrcFDefn->GetWidth() );
148 162 : 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 172 : switch (psColDef->target_type)
168 : {
169 : case SWQ_OTHER:
170 170 : 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 172 : if (psColDef->field_length > 0)
193 : {
194 2 : oFDefn.SetWidth( psColDef->field_length );
195 : }
196 :
197 172 : if (psColDef->field_precision >= 0)
198 : {
199 1 : oFDefn.SetPrecision( psColDef->field_precision );
200 : }
201 :
202 172 : poDefn->AddFieldDefn( &oFDefn );
203 : }
204 :
205 63 : poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() );
206 :
207 : /* -------------------------------------------------------------------- */
208 : /* If an ORDER BY is in effect, apply it now. */
209 : /* -------------------------------------------------------------------- */
210 63 : if( psSelectInfo->order_specs > 0
211 : && psSelectInfo->query_mode == SWQM_RECORDSET )
212 10 : CreateOrderByIndex();
213 :
214 63 : ResetReading();
215 0 : }
216 :
217 : /************************************************************************/
218 : /* ~OGRGenSQLResultsLayer() */
219 : /************************************************************************/
220 :
221 63 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
222 :
223 : {
224 63 : if( m_nFeaturesRead > 0 && poDefn != NULL )
225 : {
226 : CPLDebug( "GenSQL", "%d features read on layer '%s'.",
227 : (int) m_nFeaturesRead,
228 47 : poDefn->GetName() );
229 : }
230 :
231 63 : ClearFilters();
232 :
233 : /* -------------------------------------------------------------------- */
234 : /* Free various datastructures. */
235 : /* -------------------------------------------------------------------- */
236 63 : CPLFree( papoTableLayers );
237 63 : papoTableLayers = NULL;
238 :
239 63 : if( panFIDIndex != NULL )
240 10 : CPLFree( panFIDIndex );
241 :
242 63 : if( poSummaryFeature )
243 11 : delete poSummaryFeature;
244 :
245 63 : if( pSelectInfo != NULL )
246 63 : swq_select_free( (swq_select *) pSelectInfo );
247 :
248 63 : if( poDefn != NULL )
249 : {
250 63 : poDefn->Release();
251 : }
252 :
253 : /* -------------------------------------------------------------------- */
254 : /* Release any additional datasources being used in joins. */
255 : /* -------------------------------------------------------------------- */
256 63 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
257 :
258 67 : for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ )
259 4 : poReg->ReleaseDataSource( papoExtraDS[iEDS] );
260 :
261 63 : CPLFree( papoExtraDS );
262 63 : }
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 73 : void OGRGenSQLResultsLayer::ClearFilters()
273 :
274 : {
275 : /* -------------------------------------------------------------------- */
276 : /* Clear any filters installed on the target layer. */
277 : /* -------------------------------------------------------------------- */
278 73 : if( poSrcLayer != NULL )
279 : {
280 73 : poSrcLayer->SetAttributeFilter( "" );
281 73 : poSrcLayer->SetSpatialFilter( NULL );
282 : }
283 :
284 : /* -------------------------------------------------------------------- */
285 : /* Clear any attribute filter installed on the joined layers. */
286 : /* -------------------------------------------------------------------- */
287 73 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
288 : int iJoin;
289 :
290 73 : if( psSelectInfo != NULL )
291 : {
292 87 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
293 : {
294 14 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
295 : OGRLayer *poJoinLayer =
296 14 : papoTableLayers[psJoinInfo->secondary_table];
297 :
298 14 : poJoinLayer->SetAttributeFilter( "" );
299 : }
300 : }
301 73 : }
302 :
303 : /************************************************************************/
304 : /* ResetReading() */
305 : /************************************************************************/
306 :
307 88 : void OGRGenSQLResultsLayer::ResetReading()
308 :
309 : {
310 88 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
311 :
312 88 : if( psSelectInfo->query_mode == SWQM_RECORDSET )
313 : {
314 77 : poSrcLayer->SetAttributeFilter( psSelectInfo->whole_where_clause );
315 :
316 77 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
317 :
318 77 : poSrcLayer->ResetReading();
319 : }
320 :
321 88 : nNextIndexFID = 0;
322 88 : }
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 : OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent,
354 2 : int bForce )
355 :
356 : {
357 2 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
358 :
359 2 : if( psSelectInfo->query_mode == SWQM_RECORDSET )
360 2 : return poSrcLayer->GetExtent( psExtent, bForce );
361 : else
362 0 : return OGRERR_FAILURE;
363 : }
364 :
365 : /************************************************************************/
366 : /* GetSpatialRef() */
367 : /************************************************************************/
368 :
369 15 : OGRSpatialReference *OGRGenSQLResultsLayer::GetSpatialRef()
370 :
371 : {
372 15 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
373 :
374 15 : if( psSelectInfo->query_mode != SWQM_RECORDSET )
375 0 : return NULL;
376 : else
377 15 : return poSrcLayer->GetSpatialRef();
378 : }
379 :
380 : /************************************************************************/
381 : /* GetFeatureCount() */
382 : /************************************************************************/
383 :
384 13 : int OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
385 :
386 : {
387 13 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
388 :
389 13 : 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 11 : else if( psSelectInfo->query_mode != SWQM_RECORDSET )
402 0 : return 1;
403 11 : else if( m_poAttrQuery == NULL )
404 11 : 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 22 : if( psSelectInfo->result_columns == 1
474 : && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
475 : && !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 200 : while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
489 : {
490 360 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
491 : {
492 180 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
493 :
494 : pszError = swq_select_summarize( psSelectInfo, iField,
495 : poSrcFeature->GetFieldAsString(
496 180 : psColDef->field_index ) );
497 :
498 180 : 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 180 : 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 161 : OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
563 :
564 : {
565 161 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
566 : OGRFeature *poDstFeat;
567 :
568 161 : if( poSrcFeat == NULL )
569 0 : return NULL;
570 :
571 161 : m_nFeaturesRead++;
572 :
573 : /* -------------------------------------------------------------------- */
574 : /* Create destination feature. */
575 : /* -------------------------------------------------------------------- */
576 161 : poDstFeat = new OGRFeature( poDefn );
577 :
578 161 : poDstFeat->SetFID( poSrcFeat->GetFID() );
579 :
580 161 : poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
581 :
582 161 : poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
583 :
584 : /* -------------------------------------------------------------------- */
585 : /* Copy fields from primary record to the destination feature. */
586 : /* -------------------------------------------------------------------- */
587 762 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
588 : {
589 601 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
590 :
591 601 : if( psColDef->table_index != 0 )
592 179 : continue;
593 :
594 441 : 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 403 : 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 401 : poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
631 : }
632 : }
633 : }
634 :
635 : /* -------------------------------------------------------------------- */
636 : /* Copy values from any joined tables. */
637 : /* -------------------------------------------------------------------- */
638 : int iJoin;
639 :
640 224 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
641 : {
642 63 : CPLString osFilter;
643 :
644 63 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
645 63 : OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
646 :
647 : // if source key is null, we can't do join.
648 63 : if( !poSrcFeat->IsFieldSet( psJoinInfo->primary_field ) )
649 24 : continue;
650 :
651 : // Prepare attribute query to express fetching on the joined variable
652 : osFilter.Printf("%s = ",
653 : poJoinLayer->GetLayerDefn()->GetFieldDefn(
654 63 : psJoinInfo->secondary_field )->GetNameRef() );
655 :
656 : OGRField *psSrcField =
657 63 : poSrcFeat->GetRawFieldRef(psJoinInfo->primary_field);
658 :
659 63 : switch( poSrcLayer->GetLayerDefn()->GetFieldDefn(
660 : psJoinInfo->primary_field )->GetType() )
661 : {
662 : case OFTInteger:
663 12 : osFilter += CPLString().Printf("%d", psSrcField->Integer );
664 12 : break;
665 :
666 : case OFTReal:
667 44 : osFilter += CPLString().Printf("%.16g", psSrcField->Real );
668 44 : break;
669 :
670 : case OFTString:
671 : {
672 : char *pszEscaped = CPLEscapeString( psSrcField->String,
673 : strlen(psSrcField->String),
674 7 : CPLES_SQL );
675 7 : osFilter += "'";
676 7 : osFilter += pszEscaped;
677 7 : osFilter += "'";
678 7 : CPLFree( pszEscaped );
679 : }
680 7 : break;
681 :
682 : default:
683 0 : CPLAssert( FALSE );
684 : continue;
685 : }
686 :
687 63 : poJoinLayer->ResetReading();
688 63 : if( poJoinLayer->SetAttributeFilter( osFilter.c_str() ) != OGRERR_NONE )
689 : continue;
690 :
691 : // Fetch first joined feature.
692 : OGRFeature *poJoinFeature;
693 :
694 63 : poJoinFeature = poJoinLayer->GetNextFeature();
695 :
696 63 : if( poJoinFeature == NULL )
697 : continue;
698 :
699 : // Copy over selected field values.
700 220 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
701 : {
702 181 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
703 :
704 181 : if( psColDef->table_index == psJoinInfo->secondary_table )
705 : poDstFeat->SetField( iField,
706 : poJoinFeature->GetRawFieldRef(
707 97 : psColDef->field_index ) );
708 : }
709 :
710 39 : delete poJoinFeature;
711 : }
712 :
713 161 : return poDstFeat;
714 : }
715 :
716 : /************************************************************************/
717 : /* GetNextFeature() */
718 : /************************************************************************/
719 :
720 266 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
721 :
722 : {
723 266 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
724 :
725 : /* -------------------------------------------------------------------- */
726 : /* Handle summary sets. */
727 : /* -------------------------------------------------------------------- */
728 266 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
729 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
730 60 : return GetFeature( nNextIndexFID++ );
731 :
732 : /* -------------------------------------------------------------------- */
733 : /* Handle ordered sets. */
734 : /* -------------------------------------------------------------------- */
735 0 : while( TRUE )
736 : {
737 : OGRFeature *poFeature;
738 :
739 206 : if( panFIDIndex != NULL )
740 37 : poFeature = GetFeature( nNextIndexFID++ );
741 : else
742 : {
743 169 : OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
744 :
745 169 : if( poSrcFeat == NULL )
746 35 : return NULL;
747 :
748 134 : poFeature = TranslateFeature( poSrcFeat );
749 134 : delete poSrcFeat;
750 : }
751 :
752 171 : if( poFeature == NULL )
753 10 : return NULL;
754 :
755 161 : if( m_poAttrQuery == NULL
756 : || m_poAttrQuery->Evaluate( poFeature ) )
757 161 : return poFeature;
758 :
759 0 : delete poFeature;
760 : }
761 :
762 : return NULL;
763 : }
764 :
765 : /************************************************************************/
766 : /* GetFeature() */
767 : /************************************************************************/
768 :
769 97 : OGRFeature *OGRGenSQLResultsLayer::GetFeature( long nFID )
770 :
771 : {
772 97 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
773 :
774 : /* -------------------------------------------------------------------- */
775 : /* Handle request for summary record. */
776 : /* -------------------------------------------------------------------- */
777 97 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
778 : {
779 6 : if( !PrepareSummary() || nFID != 0 || poSummaryFeature == NULL )
780 3 : return NULL;
781 : else
782 3 : return poSummaryFeature->Clone();
783 : }
784 :
785 : /* -------------------------------------------------------------------- */
786 : /* Handle request for distinct list record. */
787 : /* -------------------------------------------------------------------- */
788 91 : if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
789 : {
790 54 : if( !PrepareSummary() )
791 0 : return NULL;
792 :
793 54 : swq_summary *psSummary = psSelectInfo->column_summary + 0;
794 :
795 54 : if( psSummary == NULL )
796 1 : return NULL;
797 :
798 53 : if( nFID < 0 || nFID >= psSummary->count )
799 6 : return NULL;
800 :
801 47 : poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
802 47 : poSummaryFeature->SetFID( nFID );
803 :
804 47 : return poSummaryFeature->Clone();
805 : }
806 :
807 : /* -------------------------------------------------------------------- */
808 : /* Are we running in sorted mode? If so, run the fid through */
809 : /* the index. */
810 : /* -------------------------------------------------------------------- */
811 37 : if( panFIDIndex != NULL )
812 : {
813 37 : if( nFID < 0 || nFID >= nIndexSize )
814 10 : return NULL;
815 : else
816 27 : nFID = panFIDIndex[nFID];
817 : }
818 :
819 : /* -------------------------------------------------------------------- */
820 : /* Handle request for random record. */
821 : /* -------------------------------------------------------------------- */
822 27 : OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
823 : OGRFeature *poResult;
824 :
825 27 : if( poSrcFeature == NULL )
826 0 : return NULL;
827 :
828 27 : poResult = TranslateFeature( poSrcFeature );
829 27 : poResult->SetFID( nFID );
830 :
831 27 : delete poSrcFeature;
832 :
833 27 : return poResult;
834 : }
835 :
836 : /************************************************************************/
837 : /* GetSpatialFilter() */
838 : /************************************************************************/
839 :
840 0 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
841 :
842 : {
843 0 : return NULL;
844 : }
845 :
846 : /************************************************************************/
847 : /* GetLayerDefn() */
848 : /************************************************************************/
849 :
850 117 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
851 :
852 : {
853 117 : return poDefn;
854 : }
855 :
856 : /************************************************************************/
857 : /* CreateOrderByIndex() */
858 : /* */
859 : /* This method is responsible for creating an index providing */
860 : /* ordered access to the features according to the supplied */
861 : /* ORDER BY clauses. */
862 : /* */
863 : /* This is accomplished by making one pass through all the */
864 : /* eligible source features, and capturing the order by fields */
865 : /* of all records in memory. A quick sort is then applied to */
866 : /* this in memory copy of the order-by fields to create the */
867 : /* required index. */
868 : /* */
869 : /* Keeping all the key values in memory will *not* scale up to */
870 : /* very large input datasets. */
871 : /************************************************************************/
872 :
873 10 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
874 :
875 : {
876 10 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
877 : OGRField *pasIndexFields;
878 10 : int i, nOrderItems = psSelectInfo->order_specs;
879 : long *panFIDList;
880 :
881 10 : if( nOrderItems == 0 )
882 0 : return;
883 :
884 10 : ResetReading();
885 :
886 : /* -------------------------------------------------------------------- */
887 : /* Allocate set of key values, and the output index. */
888 : /* -------------------------------------------------------------------- */
889 10 : nIndexSize = poSrcLayer->GetFeatureCount();
890 :
891 : pasIndexFields = (OGRField *)
892 10 : CPLCalloc(sizeof(OGRField), nOrderItems * nIndexSize);
893 10 : panFIDIndex = (long *) CPLCalloc(sizeof(long),nIndexSize);
894 10 : panFIDList = (long *) CPLCalloc(sizeof(long),nIndexSize);
895 :
896 37 : for( i = 0; i < nIndexSize; i++ )
897 27 : panFIDIndex[i] = i;
898 :
899 : /* -------------------------------------------------------------------- */
900 : /* Read in all the key values. */
901 : /* -------------------------------------------------------------------- */
902 : OGRFeature *poSrcFeat;
903 10 : int iFeature = 0;
904 :
905 47 : while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
906 : {
907 : int iKey;
908 :
909 54 : for( iKey = 0; iKey < nOrderItems; iKey++ )
910 : {
911 27 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
912 : OGRFieldDefn *poFDefn;
913 : OGRField *psSrcField, *psDstField;
914 :
915 27 : psDstField = pasIndexFields + iFeature * nOrderItems + iKey;
916 :
917 27 : if ( psKeyDef->field_index >= iFIDFieldIndex)
918 : {
919 0 : if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
920 : {
921 0 : switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
922 : {
923 : case SWQ_INTEGER:
924 0 : psDstField->Integer = poSrcFeat->GetFieldAsInteger(psKeyDef->field_index);
925 0 : break;
926 :
927 : case SWQ_FLOAT:
928 0 : psDstField->Real = poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
929 0 : break;
930 :
931 : default:
932 0 : psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
933 : break;
934 : }
935 : }
936 0 : continue;
937 : }
938 :
939 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
940 27 : psKeyDef->field_index );
941 :
942 27 : psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
943 :
944 27 : if( poFDefn->GetType() == OFTInteger
945 : || poFDefn->GetType() == OFTReal
946 : || poFDefn->GetType() == OFTDate
947 : || poFDefn->GetType() == OFTTime
948 : || poFDefn->GetType() == OFTDateTime)
949 27 : memcpy( psDstField, psSrcField, sizeof(OGRField) );
950 0 : else if( poFDefn->GetType() == OFTString )
951 : {
952 0 : if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
953 0 : psDstField->String = CPLStrdup( psSrcField->String );
954 : else
955 0 : memcpy( psDstField, psSrcField, sizeof(OGRField) );
956 : }
957 : }
958 :
959 27 : panFIDList[iFeature] = poSrcFeat->GetFID();
960 27 : delete poSrcFeat;
961 :
962 27 : iFeature++;
963 : }
964 :
965 10 : CPLAssert( nIndexSize == iFeature );
966 :
967 : /* -------------------------------------------------------------------- */
968 : /* Quick sort the records. */
969 : /* -------------------------------------------------------------------- */
970 10 : SortIndexSection( pasIndexFields, 0, nIndexSize );
971 :
972 : /* -------------------------------------------------------------------- */
973 : /* Rework the FID map to map to real FIDs. */
974 : /* -------------------------------------------------------------------- */
975 37 : for( i = 0; i < nIndexSize; i++ )
976 27 : panFIDIndex[i] = panFIDList[panFIDIndex[i]];
977 :
978 10 : CPLFree( panFIDList );
979 :
980 : /* -------------------------------------------------------------------- */
981 : /* Free the key field values. */
982 : /* -------------------------------------------------------------------- */
983 20 : for( int iKey = 0; iKey < nOrderItems; iKey++ )
984 : {
985 10 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
986 : OGRFieldDefn *poFDefn;
987 :
988 10 : if ( psKeyDef->field_index >= iFIDFieldIndex &&
989 : psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
990 : {
991 : /* warning: only special fields of type string should be deallocated */
992 0 : if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
993 : {
994 0 : for( i = 0; i < nIndexSize; i++ )
995 : {
996 0 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
997 0 : CPLFree( psField->String );
998 : }
999 : }
1000 0 : continue;
1001 : }
1002 :
1003 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1004 10 : psKeyDef->field_index );
1005 :
1006 10 : if( poFDefn->GetType() == OFTString )
1007 : {
1008 0 : for( i = 0; i < nIndexSize; i++ )
1009 : {
1010 0 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1011 :
1012 0 : if( psField->Set.nMarker1 != OGRUnsetMarker
1013 : || psField->Set.nMarker2 != OGRUnsetMarker )
1014 0 : CPLFree( psField->String );
1015 : }
1016 : }
1017 : }
1018 :
1019 10 : CPLFree( pasIndexFields );
1020 : }
1021 :
1022 : /************************************************************************/
1023 : /* SortIndexSection() */
1024 : /* */
1025 : /* Sort the records in a section of the index. */
1026 : /************************************************************************/
1027 :
1028 : void OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
1029 44 : int nStart, int nEntries )
1030 :
1031 : {
1032 44 : if( nEntries < 2 )
1033 27 : return;
1034 :
1035 17 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1036 17 : int nOrderItems = psSelectInfo->order_specs;
1037 :
1038 17 : int nFirstGroup = nEntries / 2;
1039 17 : int nFirstStart = nStart;
1040 17 : int nSecondGroup = nEntries - nFirstGroup;
1041 17 : int nSecondStart = nStart + nFirstGroup;
1042 17 : int iMerge = 0;
1043 : long *panMerged;
1044 :
1045 17 : SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup );
1046 17 : SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup );
1047 :
1048 17 : panMerged = (long *) CPLMalloc( sizeof(long) * nEntries );
1049 :
1050 76 : while( iMerge < nEntries )
1051 : {
1052 : int nResult;
1053 :
1054 42 : if( nFirstGroup == 0 )
1055 1 : nResult = -1;
1056 41 : else if( nSecondGroup == 0 )
1057 16 : nResult = 1;
1058 : else
1059 : nResult = Compare( pasIndexFields
1060 : + panFIDIndex[nFirstStart] * nOrderItems,
1061 : pasIndexFields
1062 25 : + panFIDIndex[nSecondStart] * nOrderItems );
1063 :
1064 42 : if( nResult < 0 )
1065 : {
1066 22 : panMerged[iMerge++] = panFIDIndex[nSecondStart++];
1067 22 : nSecondGroup--;
1068 : }
1069 : else
1070 : {
1071 20 : panMerged[iMerge++] = panFIDIndex[nFirstStart++];
1072 20 : nFirstGroup--;
1073 : }
1074 : }
1075 :
1076 : /* Copy the merge list back into the main index */
1077 :
1078 17 : memcpy( panFIDIndex + nStart, panMerged, sizeof(long) * nEntries );
1079 17 : CPLFree( panMerged );
1080 : }
1081 :
1082 : /************************************************************************/
1083 : /* Compare() */
1084 : /************************************************************************/
1085 :
1086 : int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
1087 25 : OGRField *pasSecondTuple )
1088 :
1089 : {
1090 25 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1091 25 : int nResult = 0, iKey;
1092 :
1093 50 : for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
1094 : {
1095 25 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1096 : OGRFieldDefn *poFDefn;
1097 :
1098 25 : if( psKeyDef->field_index >= iFIDFieldIndex )
1099 0 : poFDefn = NULL;
1100 : else
1101 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1102 25 : psKeyDef->field_index );
1103 :
1104 25 : if( (pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker
1105 : && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker)
1106 : || (pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
1107 : && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker) )
1108 0 : nResult = 0;
1109 25 : else if ( poFDefn == NULL )
1110 : {
1111 0 : switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
1112 : {
1113 : case SWQ_INTEGER:
1114 0 : if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
1115 0 : nResult = -1;
1116 0 : else if( pasFirstTuple[iKey].Integer > pasSecondTuple[iKey].Integer )
1117 0 : nResult = 1;
1118 0 : break;
1119 : case SWQ_FLOAT:
1120 0 : if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
1121 0 : nResult = -1;
1122 0 : else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
1123 0 : nResult = 1;
1124 0 : break;
1125 : case SWQ_STRING:
1126 : nResult = strcmp(pasFirstTuple[iKey].String,
1127 0 : pasSecondTuple[iKey].String);
1128 0 : break;
1129 :
1130 : default:
1131 0 : CPLAssert( FALSE );
1132 0 : nResult = 0;
1133 : }
1134 : }
1135 25 : else if( poFDefn->GetType() == OFTInteger )
1136 : {
1137 0 : if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
1138 0 : nResult = -1;
1139 0 : else if( pasFirstTuple[iKey].Integer
1140 : > pasSecondTuple[iKey].Integer )
1141 0 : nResult = 1;
1142 : }
1143 25 : else if( poFDefn->GetType() == OFTString )
1144 : nResult = strcmp(pasFirstTuple[iKey].String,
1145 0 : pasSecondTuple[iKey].String);
1146 25 : else if( poFDefn->GetType() == OFTReal )
1147 : {
1148 24 : if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
1149 4 : nResult = -1;
1150 20 : else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
1151 20 : nResult = 1;
1152 : }
1153 1 : else if( poFDefn->GetType() == OFTDate ||
1154 : poFDefn->GetType() == OFTTime ||
1155 : poFDefn->GetType() == OFTDateTime)
1156 : {
1157 : nResult = OGRCompareDate(&pasFirstTuple[iKey],
1158 1 : &pasSecondTuple[iKey]);
1159 : }
1160 :
1161 25 : if( psKeyDef->ascending_flag )
1162 24 : nResult *= -1;
1163 : }
1164 :
1165 25 : return nResult;
1166 : }
|