1 : /******************************************************************************
2 : * $Id: ogr_gensql.cpp 23531 2011-12-11 19:11:56Z 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 "swq.h"
31 : #include "ogr_p.h"
32 : #include "ogr_gensql.h"
33 : #include "cpl_string.h"
34 : #include <vector>
35 :
36 : CPL_CVSID("$Id: ogr_gensql.cpp 23531 2011-12-11 19:11:56Z rouault $");
37 :
38 :
39 : /************************************************************************/
40 : /* OGRGenSQLResultsLayerHasSpecialField() */
41 : /************************************************************************/
42 :
43 : static
44 5 : int OGRGenSQLResultsLayerHasSpecialField(swq_expr_node* expr,
45 : int nMinIndexForSpecialField)
46 : {
47 5 : if (expr->eNodeType == SNT_COLUMN)
48 : {
49 2 : if (expr->table_index == 0)
50 : {
51 2 : return expr->field_index >= nMinIndexForSpecialField;
52 : }
53 : }
54 3 : else if (expr->eNodeType == SNT_OPERATION)
55 : {
56 4 : for( int i = 0; i < expr->nSubExprCount; i++ )
57 : {
58 3 : if (OGRGenSQLResultsLayerHasSpecialField(expr->papoSubExpr[i],
59 : nMinIndexForSpecialField))
60 1 : return TRUE;
61 : }
62 : }
63 2 : return FALSE;
64 : }
65 :
66 : /************************************************************************/
67 : /* OGRGenSQLResultsLayer() */
68 : /************************************************************************/
69 :
70 183 : OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS,
71 : void *pSelectInfo,
72 : OGRGeometry *poSpatFilter,
73 : const char *pszWHERE,
74 183 : const char *pszDialect )
75 :
76 : {
77 183 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
78 :
79 183 : this->poSrcDS = poSrcDS;
80 183 : this->pSelectInfo = pSelectInfo;
81 183 : poDefn = NULL;
82 183 : poSummaryFeature = NULL;
83 183 : panFIDIndex = NULL;
84 183 : nIndexSize = 0;
85 183 : nNextIndexFID = 0;
86 183 : nExtraDSCount = 0;
87 183 : papoExtraDS = NULL;
88 :
89 : /* -------------------------------------------------------------------- */
90 : /* Identify all the layers involved in the SELECT. */
91 : /* -------------------------------------------------------------------- */
92 : int iTable;
93 :
94 : papoTableLayers = (OGRLayer **)
95 183 : CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count );
96 :
97 383 : for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
98 : {
99 200 : swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
100 200 : OGRDataSource *poTableDS = poSrcDS;
101 :
102 200 : if( psTableDef->data_source != NULL )
103 : {
104 5 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
105 :
106 : poTableDS =
107 5 : poReg->OpenShared( psTableDef->data_source, FALSE, NULL );
108 5 : if( poTableDS == NULL )
109 : {
110 0 : if( strlen(CPLGetLastErrorMsg()) == 0 )
111 : CPLError( CE_Failure, CPLE_AppDefined,
112 : "Unable to open secondary datasource\n"
113 : "`%s' required by JOIN.",
114 0 : psTableDef->data_source );
115 0 : return;
116 : }
117 :
118 : papoExtraDS = (OGRDataSource **)
119 5 : CPLRealloc( papoExtraDS, sizeof(void*) * ++nExtraDSCount );
120 :
121 5 : papoExtraDS[nExtraDSCount-1] = poTableDS;
122 : }
123 :
124 200 : papoTableLayers[iTable] =
125 200 : poTableDS->GetLayerByName( psTableDef->table_name );
126 :
127 200 : CPLAssert( papoTableLayers[iTable] != NULL );
128 :
129 200 : if( papoTableLayers[iTable] == NULL )
130 0 : return;
131 : }
132 :
133 183 : poSrcLayer = papoTableLayers[0];
134 :
135 : /* -------------------------------------------------------------------- */
136 : /* If the user has explicitely requested a OGRSQL dialect, then */
137 : /* we should avoid to forward the where clause to the source layer */
138 : /* when there is a risk it cannot understand it (#4022) */
139 : /* -------------------------------------------------------------------- */
140 183 : int bForwardWhereToSourceLayer = TRUE;
141 183 : if( pszWHERE )
142 : {
143 52 : if( psSelectInfo->where_expr && pszDialect != NULL &&
144 : EQUAL(pszDialect, "OGRSQL") )
145 : {
146 2 : int nMinIndexForSpecialField = poSrcLayer->GetLayerDefn()->GetFieldCount();
147 : bForwardWhereToSourceLayer = !OGRGenSQLResultsLayerHasSpecialField
148 2 : (psSelectInfo->where_expr, nMinIndexForSpecialField);
149 : }
150 52 : if (bForwardWhereToSourceLayer)
151 51 : this->pszWHERE = CPLStrdup(pszWHERE);
152 : else
153 1 : this->pszWHERE = NULL;
154 : }
155 : else
156 131 : this->pszWHERE = NULL;
157 :
158 : /* -------------------------------------------------------------------- */
159 : /* Now that we have poSrcLayer, we can install a spatial filter */
160 : /* if there is one. */
161 : /* -------------------------------------------------------------------- */
162 183 : if( poSpatFilter != NULL )
163 0 : SetSpatialFilter( poSpatFilter );
164 :
165 : /* -------------------------------------------------------------------- */
166 : /* Prepare a feature definition based on the query. */
167 : /* -------------------------------------------------------------------- */
168 183 : OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
169 :
170 183 : poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias );
171 183 : poDefn->Reference();
172 :
173 183 : iFIDFieldIndex = poSrcDefn->GetFieldCount();
174 :
175 1576 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
176 : {
177 1393 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
178 1393 : OGRFieldDefn oFDefn( "", OFTInteger );
179 1393 : OGRFieldDefn *poSrcFDefn = NULL;
180 1393 : OGRFeatureDefn *poLayerDefn = NULL;
181 :
182 1393 : if( psColDef->table_index != -1 )
183 : poLayerDefn =
184 1372 : papoTableLayers[psColDef->table_index]->GetLayerDefn();
185 :
186 1393 : if( psColDef->field_index > -1
187 : && poLayerDefn != NULL
188 : && psColDef->field_index < poLayerDefn->GetFieldCount() )
189 1287 : poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index);
190 :
191 1393 : if( strlen(psColDef->field_name) == 0 )
192 : {
193 16 : CPLFree( psColDef->field_name );
194 16 : psColDef->field_name = (char *) CPLMalloc(40);
195 16 : sprintf( psColDef->field_name, "FIELD_%d", iField+1 );
196 : }
197 :
198 1393 : if( psColDef->field_alias != NULL )
199 : {
200 5 : oFDefn.SetName(psColDef->field_alias);
201 : }
202 1388 : else if( psColDef->col_func != SWQCF_NONE )
203 : {
204 : const swq_operation *op = swq_op_registrar::GetOperator(
205 88 : (swq_op) psColDef->col_func );
206 :
207 : oFDefn.SetName( CPLSPrintf( "%s_%s",
208 : op->osName.c_str(),
209 88 : psColDef->field_name ) );
210 : }
211 : else
212 1300 : oFDefn.SetName( psColDef->field_name );
213 :
214 1393 : if( psColDef->col_func == SWQCF_COUNT )
215 83 : oFDefn.SetType( OFTInteger );
216 1310 : else if( poSrcFDefn != NULL )
217 : {
218 1279 : oFDefn.SetType( poSrcFDefn->GetType() );
219 1279 : if( psColDef->col_func != SWQCF_AVG )
220 : {
221 1278 : oFDefn.SetWidth( poSrcFDefn->GetWidth() );
222 1278 : oFDefn.SetPrecision( poSrcFDefn->GetPrecision() );
223 : }
224 : }
225 31 : else if ( psColDef->field_index >= iFIDFieldIndex )
226 : {
227 10 : switch ( SpecialFieldTypes[psColDef->field_index-iFIDFieldIndex] )
228 : {
229 : case SWQ_INTEGER:
230 5 : oFDefn.SetType( OFTInteger );
231 5 : break;
232 : case SWQ_FLOAT:
233 1 : oFDefn.SetType( OFTReal );
234 1 : break;
235 : default:
236 4 : oFDefn.SetType( OFTString );
237 : break;
238 : }
239 : }
240 : else
241 : {
242 21 : switch( psColDef->field_type )
243 : {
244 : case SWQ_INTEGER:
245 : case SWQ_BOOLEAN:
246 7 : oFDefn.SetType( OFTInteger );
247 7 : break;
248 :
249 : case SWQ_FLOAT:
250 5 : oFDefn.SetType( OFTReal );
251 5 : break;
252 :
253 : default:
254 9 : oFDefn.SetType( OFTString );
255 : break;
256 : }
257 : }
258 :
259 : /* setting up the target_type */
260 1393 : switch (psColDef->target_type)
261 : {
262 : case SWQ_OTHER:
263 1390 : break;
264 : case SWQ_INTEGER:
265 : case SWQ_BOOLEAN:
266 1 : oFDefn.SetType( OFTInteger );
267 1 : break;
268 : case SWQ_FLOAT:
269 1 : oFDefn.SetType( OFTReal );
270 1 : break;
271 : case SWQ_STRING:
272 1 : oFDefn.SetType( OFTString );
273 1 : break;
274 : case SWQ_TIMESTAMP:
275 0 : oFDefn.SetType( OFTDateTime );
276 0 : break;
277 : case SWQ_DATE:
278 0 : oFDefn.SetType( OFTDate );
279 0 : break;
280 : case SWQ_TIME:
281 0 : oFDefn.SetType( OFTTime );
282 0 : break;
283 :
284 : default:
285 0 : CPLAssert( FALSE );
286 0 : oFDefn.SetType( OFTString );
287 : break;
288 : }
289 :
290 1393 : if (psColDef->field_length > 0)
291 : {
292 2 : oFDefn.SetWidth( psColDef->field_length );
293 : }
294 :
295 1393 : if (psColDef->field_precision >= 0)
296 : {
297 1 : oFDefn.SetPrecision( psColDef->field_precision );
298 : }
299 :
300 1393 : poDefn->AddFieldDefn( &oFDefn );
301 : }
302 :
303 183 : poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() );
304 :
305 : /* -------------------------------------------------------------------- */
306 : /* If an ORDER BY is in effect, apply it now. */
307 : /* -------------------------------------------------------------------- */
308 183 : if( psSelectInfo->order_specs > 0
309 : && psSelectInfo->query_mode == SWQM_RECORDSET )
310 10 : CreateOrderByIndex();
311 :
312 183 : ResetReading();
313 :
314 183 : FindAndSetIgnoredFields();
315 :
316 183 : if( !bForwardWhereToSourceLayer )
317 1 : SetAttributeFilter( pszWHERE );
318 0 : }
319 :
320 : /************************************************************************/
321 : /* ~OGRGenSQLResultsLayer() */
322 : /************************************************************************/
323 :
324 183 : OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer()
325 :
326 : {
327 183 : if( m_nFeaturesRead > 0 && poDefn != NULL )
328 : {
329 : CPLDebug( "GenSQL", "%d features read on layer '%s'.",
330 : (int) m_nFeaturesRead,
331 70 : poDefn->GetName() );
332 : }
333 :
334 183 : ClearFilters();
335 :
336 : /* -------------------------------------------------------------------- */
337 : /* Free various datastructures. */
338 : /* -------------------------------------------------------------------- */
339 183 : CPLFree( papoTableLayers );
340 183 : papoTableLayers = NULL;
341 :
342 183 : CPLFree( panFIDIndex );
343 :
344 183 : delete poSummaryFeature;
345 183 : delete (swq_select *) pSelectInfo;
346 :
347 183 : if( poDefn != NULL )
348 : {
349 183 : poDefn->Release();
350 : }
351 :
352 : /* -------------------------------------------------------------------- */
353 : /* Release any additional datasources being used in joins. */
354 : /* -------------------------------------------------------------------- */
355 183 : OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar();
356 :
357 188 : for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ )
358 5 : poReg->ReleaseDataSource( papoExtraDS[iEDS] );
359 :
360 183 : CPLFree( papoExtraDS );
361 183 : CPLFree( pszWHERE );
362 183 : }
363 :
364 : /************************************************************************/
365 : /* ClearFilters() */
366 : /* */
367 : /* Clear up all filters currently in place on the target layer, */
368 : /* and joined layers. We try not to leave them installed */
369 : /* except when actively fetching features. */
370 : /************************************************************************/
371 :
372 207 : void OGRGenSQLResultsLayer::ClearFilters()
373 :
374 : {
375 : /* -------------------------------------------------------------------- */
376 : /* Clear any filters installed on the target layer. */
377 : /* -------------------------------------------------------------------- */
378 207 : if( poSrcLayer != NULL )
379 : {
380 207 : poSrcLayer->SetAttributeFilter( "" );
381 207 : poSrcLayer->SetSpatialFilter( NULL );
382 : }
383 :
384 : /* -------------------------------------------------------------------- */
385 : /* Clear any attribute filter installed on the joined layers. */
386 : /* -------------------------------------------------------------------- */
387 207 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
388 : int iJoin;
389 :
390 207 : if( psSelectInfo != NULL )
391 : {
392 224 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
393 : {
394 17 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
395 : OGRLayer *poJoinLayer =
396 17 : papoTableLayers[psJoinInfo->secondary_table];
397 :
398 17 : poJoinLayer->SetAttributeFilter( "" );
399 : }
400 : }
401 :
402 : /* -------------------------------------------------------------------- */
403 : /* Clear any ignored field lists installed on source layers */
404 : /* -------------------------------------------------------------------- */
405 207 : if( psSelectInfo != NULL )
406 : {
407 431 : for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
408 : {
409 224 : OGRLayer* poLayer = papoTableLayers[iTable];
410 224 : poLayer->SetIgnoredFields(NULL);
411 : }
412 : }
413 207 : }
414 :
415 : /************************************************************************/
416 : /* ResetReading() */
417 : /************************************************************************/
418 :
419 266 : void OGRGenSQLResultsLayer::ResetReading()
420 :
421 : {
422 266 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
423 :
424 266 : if( psSelectInfo->query_mode == SWQM_RECORDSET )
425 : {
426 170 : poSrcLayer->SetAttributeFilter( pszWHERE );
427 170 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
428 :
429 170 : poSrcLayer->ResetReading();
430 : }
431 :
432 266 : nNextIndexFID = 0;
433 266 : }
434 :
435 : /************************************************************************/
436 : /* SetNextByIndex() */
437 : /* */
438 : /* If we already have an FID list, we can easily resposition */
439 : /* ourselves in it. */
440 : /************************************************************************/
441 :
442 2 : OGRErr OGRGenSQLResultsLayer::SetNextByIndex( long nIndex )
443 :
444 : {
445 2 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
446 :
447 2 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
448 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
449 : || panFIDIndex != NULL )
450 : {
451 0 : nNextIndexFID = nIndex;
452 0 : return OGRERR_NONE;
453 : }
454 : else
455 : {
456 2 : return poSrcLayer->SetNextByIndex( nIndex );
457 : }
458 : }
459 :
460 : /************************************************************************/
461 : /* GetExtent() */
462 : /************************************************************************/
463 :
464 4 : OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent,
465 : int bForce )
466 :
467 : {
468 4 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
469 :
470 4 : if( psSelectInfo->query_mode == SWQM_RECORDSET )
471 4 : return poSrcLayer->GetExtent( psExtent, bForce );
472 : else
473 0 : return OGRERR_FAILURE;
474 : }
475 :
476 : /************************************************************************/
477 : /* GetSpatialRef() */
478 : /************************************************************************/
479 :
480 19 : OGRSpatialReference *OGRGenSQLResultsLayer::GetSpatialRef()
481 :
482 : {
483 19 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
484 :
485 19 : if( psSelectInfo->query_mode != SWQM_RECORDSET )
486 0 : return NULL;
487 : else
488 19 : return poSrcLayer->GetSpatialRef();
489 : }
490 :
491 : /************************************************************************/
492 : /* GetFeatureCount() */
493 : /************************************************************************/
494 :
495 49 : int OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
496 :
497 : {
498 49 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
499 :
500 49 : if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
501 : {
502 2 : if( !PrepareSummary() )
503 0 : return 0;
504 :
505 2 : swq_summary *psSummary = psSelectInfo->column_summary + 0;
506 :
507 2 : if( psSummary == NULL )
508 0 : return 0;
509 :
510 2 : return psSummary->count;
511 : }
512 47 : else if( psSelectInfo->query_mode != SWQM_RECORDSET )
513 0 : return 1;
514 47 : else if( m_poAttrQuery == NULL )
515 43 : return poSrcLayer->GetFeatureCount( bForce );
516 : else
517 4 : return OGRLayer::GetFeatureCount( bForce );
518 : }
519 :
520 : /************************************************************************/
521 : /* TestCapability() */
522 : /************************************************************************/
523 :
524 10 : int OGRGenSQLResultsLayer::TestCapability( const char *pszCap )
525 :
526 : {
527 10 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
528 :
529 10 : if( EQUAL(pszCap,OLCFastSetNextByIndex) )
530 : {
531 2 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
532 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
533 : || panFIDIndex != NULL )
534 0 : return TRUE;
535 : else
536 2 : return poSrcLayer->TestCapability( pszCap );
537 : }
538 :
539 8 : if( psSelectInfo->query_mode == SWQM_RECORDSET
540 : && (EQUAL(pszCap,OLCFastFeatureCount)
541 : || EQUAL(pszCap,OLCRandomRead)
542 : || EQUAL(pszCap,OLCFastGetExtent)) )
543 2 : return poSrcLayer->TestCapability( pszCap );
544 :
545 6 : else if( psSelectInfo->query_mode != SWQM_RECORDSET )
546 : {
547 0 : if( EQUAL(pszCap,OLCFastFeatureCount) )
548 0 : return TRUE;
549 : }
550 6 : return FALSE;
551 : }
552 :
553 : /************************************************************************/
554 : /* ContainGeomSpecialField() */
555 : /************************************************************************/
556 :
557 17 : int OGRGenSQLResultsLayer::ContainGeomSpecialField(swq_expr_node* expr)
558 : {
559 17 : if (expr->eNodeType == SNT_COLUMN)
560 : {
561 6 : if( expr->table_index != -1 && expr->field_index != -1 )
562 : {
563 6 : OGRLayer* poLayer = papoTableLayers[expr->table_index];
564 : int nSpecialFieldIdx = expr->field_index -
565 6 : poLayer->GetLayerDefn()->GetFieldCount();
566 : return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
567 : nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
568 6 : nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
569 : }
570 : }
571 11 : else if (expr->eNodeType == SNT_OPERATION)
572 : {
573 17 : for( int i = 0; i < expr->nSubExprCount; i++ )
574 : {
575 11 : if (ContainGeomSpecialField(expr->papoSubExpr[i]))
576 0 : return TRUE;
577 : }
578 : }
579 11 : return FALSE;
580 : }
581 :
582 : /************************************************************************/
583 : /* PrepareSummary() */
584 : /************************************************************************/
585 :
586 155 : int OGRGenSQLResultsLayer::PrepareSummary()
587 :
588 : {
589 155 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
590 :
591 155 : if( poSummaryFeature != NULL )
592 60 : return TRUE;
593 :
594 95 : poSummaryFeature = new OGRFeature( poDefn );
595 95 : poSummaryFeature->SetFID( 0 );
596 :
597 : /* -------------------------------------------------------------------- */
598 : /* Ensure our query parameters are in place on the source */
599 : /* layer. And initialize reading. */
600 : /* -------------------------------------------------------------------- */
601 95 : poSrcLayer->SetAttributeFilter(pszWHERE);
602 95 : poSrcLayer->SetSpatialFilter( m_poFilterGeom );
603 :
604 95 : poSrcLayer->ResetReading();
605 :
606 : /* -------------------------------------------------------------------- */
607 : /* Ignore geometry reading if no spatial filter in place and that */
608 : /* the where clause doesn't include OGR_GEOMETRY, OGR_GEOM_WKT or */
609 : /* OGR_GEOM_AREA special fields. */
610 : /* -------------------------------------------------------------------- */
611 95 : int bSaveIsGeomIgnored = poSrcLayer->GetLayerDefn()->IsGeometryIgnored();
612 190 : if ( m_poFilterGeom == NULL && ( psSelectInfo->where_expr == NULL ||
613 : !ContainGeomSpecialField(psSelectInfo->where_expr) ) )
614 : {
615 95 : poSrcLayer->GetLayerDefn()->SetGeometryIgnored(TRUE);
616 : }
617 :
618 : /* -------------------------------------------------------------------- */
619 : /* We treat COUNT(*) as a special case, and fill with */
620 : /* GetFeatureCount(). */
621 : /* -------------------------------------------------------------------- */
622 :
623 256 : if( psSelectInfo->result_columns == 1
624 90 : && psSelectInfo->column_defs[0].col_func == SWQCF_COUNT
625 71 : && psSelectInfo->column_defs[0].field_index < 0 )
626 : {
627 71 : poSummaryFeature->SetField( 0, poSrcLayer->GetFeatureCount( TRUE ) );
628 71 : poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
629 71 : return TRUE;
630 : }
631 :
632 : /* -------------------------------------------------------------------- */
633 : /* Otherwise, process all source feature through the summary */
634 : /* building facilities of SWQ. */
635 : /* -------------------------------------------------------------------- */
636 : const char *pszError;
637 : OGRFeature *poSrcFeature;
638 : int iField;
639 :
640 267 : while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
641 : {
642 475 : for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
643 : {
644 256 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
645 :
646 256 : if (psColDef->col_func == SWQCF_COUNT)
647 : {
648 : /* psColDef->field_index can be -1 in the case of a COUNT(*) */
649 52 : if (psColDef->field_index < 0)
650 22 : pszError = swq_select_summarize( psSelectInfo, iField, "" );
651 30 : else if (poSrcFeature->IsFieldSet(psColDef->field_index))
652 : pszError = swq_select_summarize( psSelectInfo, iField, poSrcFeature->GetFieldAsString(
653 18 : psColDef->field_index ) );
654 : else
655 12 : pszError = NULL;
656 : }
657 : else
658 : {
659 204 : const char* pszVal = NULL;
660 204 : if (poSrcFeature->IsFieldSet(psColDef->field_index))
661 : pszVal = poSrcFeature->GetFieldAsString(
662 188 : psColDef->field_index );
663 204 : pszError = swq_select_summarize( psSelectInfo, iField, pszVal );
664 : }
665 :
666 256 : if( pszError != NULL )
667 : {
668 0 : delete poSrcFeature;
669 0 : delete poSummaryFeature;
670 0 : poSummaryFeature = NULL;
671 :
672 0 : poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
673 :
674 0 : CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
675 0 : return FALSE;
676 : }
677 : }
678 :
679 219 : delete poSrcFeature;
680 : }
681 :
682 24 : poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
683 :
684 24 : pszError = swq_select_finish_summarize( psSelectInfo );
685 24 : if( pszError != NULL )
686 : {
687 0 : delete poSummaryFeature;
688 0 : poSummaryFeature = NULL;
689 :
690 0 : CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
691 0 : return FALSE;
692 : }
693 :
694 : /* -------------------------------------------------------------------- */
695 : /* If we have run out of features on the source layer, clear */
696 : /* away the filters we have installed till a next run through */
697 : /* the features. */
698 : /* -------------------------------------------------------------------- */
699 24 : if( poSrcFeature == NULL )
700 24 : ClearFilters();
701 :
702 : /* -------------------------------------------------------------------- */
703 : /* Now apply the values to the summary feature. If we are in */
704 : /* DISTINCT_LIST mode we don't do this step. */
705 : /* -------------------------------------------------------------------- */
706 24 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
707 : {
708 28 : for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
709 : {
710 18 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
711 18 : if (psSelectInfo->column_summary != NULL)
712 : {
713 14 : swq_summary *psSummary = psSelectInfo->column_summary + iField;
714 :
715 14 : if( psColDef->col_func == SWQCF_AVG )
716 : poSummaryFeature->SetField( iField,
717 0 : psSummary->sum / psSummary->count );
718 14 : else if( psColDef->col_func == SWQCF_MIN )
719 1 : poSummaryFeature->SetField( iField, psSummary->min );
720 13 : else if( psColDef->col_func == SWQCF_MAX )
721 1 : poSummaryFeature->SetField( iField, psSummary->max );
722 12 : else if( psColDef->col_func == SWQCF_COUNT )
723 12 : poSummaryFeature->SetField( iField, psSummary->count );
724 0 : else if( psColDef->col_func == SWQCF_SUM )
725 0 : poSummaryFeature->SetField( iField, psSummary->sum );
726 : }
727 4 : else if ( psColDef->col_func == SWQCF_COUNT )
728 0 : poSummaryFeature->SetField( iField, 0 );
729 : }
730 : }
731 :
732 24 : return TRUE;
733 : }
734 :
735 : /************************************************************************/
736 : /* OGRMultiFeatureFetcher() */
737 : /************************************************************************/
738 :
739 13 : static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
740 : void *pFeatureList )
741 :
742 : {
743 : std::vector<OGRFeature*> *papoFeatures =
744 13 : (std::vector<OGRFeature*> *) pFeatureList;
745 : OGRFeature *poFeature;
746 13 : swq_expr_node *poRetNode = NULL;
747 :
748 13 : CPLAssert( op->eNodeType == SNT_COLUMN );
749 :
750 : /* -------------------------------------------------------------------- */
751 : /* What feature are we using? The primary or one of the joined ones?*/
752 : /* -------------------------------------------------------------------- */
753 13 : if( op->table_index < 0 || op->table_index >= (int)papoFeatures->size() )
754 : {
755 : CPLError( CE_Failure, CPLE_AppDefined,
756 : "Request for unexpected table_index (%d) in field fetcher.",
757 0 : op->table_index );
758 0 : return NULL;
759 : }
760 :
761 13 : poFeature = (*papoFeatures)[op->table_index];
762 :
763 : /* -------------------------------------------------------------------- */
764 : /* Fetch the value. */
765 : /* -------------------------------------------------------------------- */
766 13 : switch( op->field_type )
767 : {
768 : case SWQ_INTEGER:
769 : case SWQ_BOOLEAN:
770 5 : if( poFeature == NULL
771 : || !poFeature->IsFieldSet(op->field_index) )
772 : {
773 0 : poRetNode = new swq_expr_node(0);
774 0 : poRetNode->is_null = TRUE;
775 : }
776 : else
777 : poRetNode = new swq_expr_node(
778 5 : poFeature->GetFieldAsInteger(op->field_index) );
779 5 : break;
780 :
781 : case SWQ_FLOAT:
782 2 : if( poFeature == NULL
783 : || !poFeature->IsFieldSet(op->field_index) )
784 : {
785 0 : poRetNode = new swq_expr_node( 0.0 );
786 0 : poRetNode->is_null = TRUE;
787 : }
788 : else
789 : poRetNode = new swq_expr_node(
790 2 : poFeature->GetFieldAsDouble(op->field_index) );
791 2 : break;
792 :
793 : default:
794 6 : if( poFeature == NULL
795 : || !poFeature->IsFieldSet(op->field_index) )
796 : {
797 0 : poRetNode = new swq_expr_node("");
798 0 : poRetNode->is_null = TRUE;
799 : }
800 : else
801 : poRetNode = new swq_expr_node(
802 6 : poFeature->GetFieldAsString(op->field_index) );
803 : break;
804 : }
805 :
806 13 : return poRetNode;
807 : }
808 :
809 : /************************************************************************/
810 : /* TranslateFeature() */
811 : /************************************************************************/
812 :
813 56824 : OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
814 :
815 : {
816 56824 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
817 : OGRFeature *poDstFeat;
818 56824 : std::vector<OGRFeature*> apoFeatures;
819 :
820 56824 : if( poSrcFeat == NULL )
821 0 : return NULL;
822 :
823 56824 : m_nFeaturesRead++;
824 :
825 56824 : apoFeatures.push_back( poSrcFeat );
826 :
827 : /* -------------------------------------------------------------------- */
828 : /* Fetch the corresponding features from any jointed tables. */
829 : /* -------------------------------------------------------------------- */
830 : int iJoin;
831 :
832 56824 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
833 : {
834 80 : CPLString osFilter;
835 :
836 80 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
837 80 : OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table];
838 :
839 : // if source key is null, we can't do join.
840 80 : if( !poSrcFeat->IsFieldSet( psJoinInfo->primary_field ) )
841 : {
842 0 : apoFeatures.push_back( NULL );
843 0 : continue;
844 : }
845 :
846 : OGRFieldDefn* poSecondaryFieldDefn =
847 80 : poJoinLayer->GetLayerDefn()->GetFieldDefn(
848 160 : psJoinInfo->secondary_field );
849 80 : OGRFieldType ePrimaryFieldType = poSrcLayer->GetLayerDefn()->
850 160 : GetFieldDefn(psJoinInfo->primary_field )->GetType();
851 80 : OGRFieldType eSecondaryFieldType = poSecondaryFieldDefn->GetType();
852 :
853 : // Prepare attribute query to express fetching on the joined variable
854 :
855 : // If joining a (primary) numeric column with a (secondary) string column
856 : // then add implicit casting of the secondary column to numeric. This behaviour
857 : // worked in GDAL < 1.8, and it is consistant with how sqlite behaves too. See #4321
858 : // For the reverse case, joining a string column with a numeric column, the
859 : // string constant will be cast to float by SWQAutoConvertStringToNumeric (#4259)
860 100 : if( eSecondaryFieldType == OFTString &&
861 : (ePrimaryFieldType == OFTInteger || ePrimaryFieldType == OFTReal) )
862 20 : osFilter.Printf("CAST(%s AS FLOAT) = ", poSecondaryFieldDefn->GetNameRef() );
863 : else
864 60 : osFilter.Printf("%s = ", poSecondaryFieldDefn->GetNameRef() );
865 :
866 : OGRField *psSrcField =
867 80 : poSrcFeat->GetRawFieldRef(psJoinInfo->primary_field);
868 :
869 80 : switch( ePrimaryFieldType )
870 : {
871 : case OFTInteger:
872 12 : osFilter += CPLString().Printf("%d", psSrcField->Integer );
873 12 : break;
874 :
875 : case OFTReal:
876 54 : osFilter += CPLString().Printf("%.16g", psSrcField->Real );
877 54 : break;
878 :
879 : case OFTString:
880 : {
881 : char *pszEscaped = CPLEscapeString( psSrcField->String,
882 : strlen(psSrcField->String),
883 14 : CPLES_SQL );
884 14 : osFilter += "'";
885 14 : osFilter += pszEscaped;
886 14 : osFilter += "'";
887 14 : CPLFree( pszEscaped );
888 : }
889 14 : break;
890 :
891 : default:
892 0 : CPLAssert( FALSE );
893 0 : continue;
894 : }
895 :
896 80 : OGRFeature *poJoinFeature = NULL;
897 :
898 80 : poJoinLayer->ResetReading();
899 80 : if( poJoinLayer->SetAttributeFilter( osFilter.c_str() ) == OGRERR_NONE )
900 80 : poJoinFeature = poJoinLayer->GetNextFeature();
901 :
902 80 : apoFeatures.push_back( poJoinFeature );
903 : }
904 :
905 : /* -------------------------------------------------------------------- */
906 : /* Create destination feature. */
907 : /* -------------------------------------------------------------------- */
908 56824 : poDstFeat = new OGRFeature( poDefn );
909 :
910 113648 : poDstFeat->SetFID( poSrcFeat->GetFID() );
911 :
912 56824 : poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
913 :
914 56824 : poDstFeat->SetStyleString( poSrcFeat->GetStyleString() );
915 :
916 : /* -------------------------------------------------------------------- */
917 : /* Evaluate fields that are complex expressions. */
918 : /* -------------------------------------------------------------------- */
919 397054 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
920 : {
921 340230 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
922 : swq_expr_node *poResult;
923 :
924 340230 : if( psColDef->field_index != -1 )
925 340168 : continue;
926 :
927 : poResult = psColDef->expr->Evaluate( OGRMultiFeatureFetcher,
928 62 : (void *) &apoFeatures );
929 :
930 62 : if( poResult == NULL )
931 : {
932 0 : delete poDstFeat;
933 0 : return NULL;
934 : }
935 :
936 62 : if( poResult->is_null )
937 : {
938 3 : delete poResult;
939 3 : continue;
940 : }
941 :
942 59 : switch( poResult->field_type )
943 : {
944 : case SWQ_INTEGER:
945 25 : poDstFeat->SetField( iField, poResult->int_value );
946 25 : break;
947 :
948 : case SWQ_FLOAT:
949 19 : poDstFeat->SetField( iField, poResult->float_value );
950 19 : break;
951 :
952 : default:
953 15 : poDstFeat->SetField( iField, poResult->string_value );
954 : break;
955 : }
956 :
957 59 : delete poResult;
958 : }
959 :
960 : /* -------------------------------------------------------------------- */
961 : /* Copy fields from primary record to the destination feature. */
962 : /* -------------------------------------------------------------------- */
963 397054 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
964 : {
965 340230 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
966 :
967 340230 : if( psColDef->table_index != 0 )
968 332 : continue;
969 :
970 339921 : if ( psColDef->field_index >= iFIDFieldIndex &&
971 : psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
972 : {
973 23 : switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
974 : {
975 : case SWQ_INTEGER:
976 4 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
977 4 : break;
978 : case SWQ_FLOAT:
979 1 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
980 1 : break;
981 : default:
982 18 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
983 : }
984 : }
985 : else
986 : {
987 339875 : switch (psColDef->target_type)
988 : {
989 : case SWQ_INTEGER:
990 0 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsInteger(psColDef->field_index) );
991 0 : break;
992 :
993 : case SWQ_FLOAT:
994 0 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsDouble(psColDef->field_index) );
995 0 : break;
996 :
997 : case SWQ_STRING:
998 : case SWQ_TIMESTAMP:
999 : case SWQ_DATE:
1000 : case SWQ_TIME:
1001 0 : poDstFeat->SetField( iField, poSrcFeat->GetFieldAsString(psColDef->field_index) );
1002 0 : break;
1003 :
1004 : default:
1005 : poDstFeat->SetField( iField,
1006 339875 : poSrcFeat->GetRawFieldRef( psColDef->field_index ) );
1007 : }
1008 : }
1009 : }
1010 :
1011 : /* -------------------------------------------------------------------- */
1012 : /* Copy values from any joined tables. */
1013 : /* -------------------------------------------------------------------- */
1014 56824 : for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
1015 : {
1016 80 : CPLString osFilter;
1017 :
1018 80 : swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
1019 80 : OGRFeature *poJoinFeature = apoFeatures[iJoin+1];
1020 :
1021 80 : if( poJoinFeature == NULL )
1022 27 : continue;
1023 :
1024 : // Copy over selected field values.
1025 374 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1026 : {
1027 321 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1028 :
1029 321 : if( psColDef->table_index == psJoinInfo->secondary_table )
1030 : poDstFeat->SetField( iField,
1031 : poJoinFeature->GetRawFieldRef(
1032 167 : psColDef->field_index ) );
1033 : }
1034 :
1035 53 : delete poJoinFeature;
1036 : }
1037 :
1038 56824 : return poDstFeat;
1039 : }
1040 :
1041 : /************************************************************************/
1042 : /* GetNextFeature() */
1043 : /************************************************************************/
1044 :
1045 47622 : OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
1046 :
1047 : {
1048 47622 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1049 :
1050 : /* -------------------------------------------------------------------- */
1051 : /* Handle summary sets. */
1052 : /* -------------------------------------------------------------------- */
1053 47622 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
1054 : || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
1055 153 : return GetFeature( nNextIndexFID++ );
1056 :
1057 : /* -------------------------------------------------------------------- */
1058 : /* Handle ordered sets. */
1059 : /* -------------------------------------------------------------------- */
1060 9434 : while( TRUE )
1061 : {
1062 : OGRFeature *poFeature;
1063 :
1064 56903 : if( panFIDIndex != NULL )
1065 37 : poFeature = GetFeature( nNextIndexFID++ );
1066 : else
1067 : {
1068 56866 : OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
1069 :
1070 56866 : if( poSrcFeat == NULL )
1071 71 : return NULL;
1072 :
1073 56795 : poFeature = TranslateFeature( poSrcFeat );
1074 56795 : delete poSrcFeat;
1075 : }
1076 :
1077 56832 : if( poFeature == NULL )
1078 10 : return NULL;
1079 :
1080 56822 : if( m_poAttrQuery == NULL
1081 : || m_poAttrQuery->Evaluate( poFeature ) )
1082 47388 : return poFeature;
1083 :
1084 9434 : delete poFeature;
1085 : }
1086 :
1087 : return NULL;
1088 : }
1089 :
1090 : /************************************************************************/
1091 : /* GetFeature() */
1092 : /************************************************************************/
1093 :
1094 192 : OGRFeature *OGRGenSQLResultsLayer::GetFeature( long nFID )
1095 :
1096 : {
1097 192 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1098 :
1099 : /* -------------------------------------------------------------------- */
1100 : /* Handle request for summary record. */
1101 : /* -------------------------------------------------------------------- */
1102 192 : if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
1103 : {
1104 87 : if( !PrepareSummary() || nFID != 0 || poSummaryFeature == NULL )
1105 5 : return NULL;
1106 : else
1107 82 : return poSummaryFeature->Clone();
1108 : }
1109 :
1110 : /* -------------------------------------------------------------------- */
1111 : /* Handle request for distinct list record. */
1112 : /* -------------------------------------------------------------------- */
1113 105 : if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
1114 : {
1115 66 : if( !PrepareSummary() )
1116 0 : return NULL;
1117 :
1118 66 : swq_summary *psSummary = psSelectInfo->column_summary + 0;
1119 :
1120 66 : if( psSummary == NULL )
1121 1 : return NULL;
1122 :
1123 65 : if( nFID < 0 || nFID >= psSummary->count )
1124 6 : return NULL;
1125 :
1126 59 : if( psSummary->distinct_list[nFID] != NULL )
1127 51 : poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
1128 : else
1129 8 : poSummaryFeature->UnsetField( 0 );
1130 59 : poSummaryFeature->SetFID( nFID );
1131 :
1132 59 : return poSummaryFeature->Clone();
1133 : }
1134 :
1135 : /* -------------------------------------------------------------------- */
1136 : /* Are we running in sorted mode? If so, run the fid through */
1137 : /* the index. */
1138 : /* -------------------------------------------------------------------- */
1139 39 : if( panFIDIndex != NULL )
1140 : {
1141 37 : if( nFID < 0 || nFID >= nIndexSize )
1142 10 : return NULL;
1143 : else
1144 27 : nFID = panFIDIndex[nFID];
1145 : }
1146 :
1147 : /* -------------------------------------------------------------------- */
1148 : /* Handle request for random record. */
1149 : /* -------------------------------------------------------------------- */
1150 29 : OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
1151 : OGRFeature *poResult;
1152 :
1153 29 : if( poSrcFeature == NULL )
1154 0 : return NULL;
1155 :
1156 29 : poResult = TranslateFeature( poSrcFeature );
1157 29 : poResult->SetFID( nFID );
1158 :
1159 29 : delete poSrcFeature;
1160 :
1161 29 : return poResult;
1162 : }
1163 :
1164 : /************************************************************************/
1165 : /* GetSpatialFilter() */
1166 : /************************************************************************/
1167 :
1168 2 : OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
1169 :
1170 : {
1171 2 : return NULL;
1172 : }
1173 :
1174 : /************************************************************************/
1175 : /* GetLayerDefn() */
1176 : /************************************************************************/
1177 :
1178 160 : OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
1179 :
1180 : {
1181 160 : return poDefn;
1182 : }
1183 :
1184 : /************************************************************************/
1185 : /* CreateOrderByIndex() */
1186 : /* */
1187 : /* This method is responsible for creating an index providing */
1188 : /* ordered access to the features according to the supplied */
1189 : /* ORDER BY clauses. */
1190 : /* */
1191 : /* This is accomplished by making one pass through all the */
1192 : /* eligible source features, and capturing the order by fields */
1193 : /* of all records in memory. A quick sort is then applied to */
1194 : /* this in memory copy of the order-by fields to create the */
1195 : /* required index. */
1196 : /* */
1197 : /* Keeping all the key values in memory will *not* scale up to */
1198 : /* very large input datasets. */
1199 : /************************************************************************/
1200 :
1201 10 : void OGRGenSQLResultsLayer::CreateOrderByIndex()
1202 :
1203 : {
1204 10 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1205 : OGRField *pasIndexFields;
1206 10 : int i, nOrderItems = psSelectInfo->order_specs;
1207 : long *panFIDList;
1208 :
1209 10 : if( nOrderItems == 0 )
1210 0 : return;
1211 :
1212 10 : ResetReading();
1213 :
1214 : /* -------------------------------------------------------------------- */
1215 : /* Allocate set of key values, and the output index. */
1216 : /* -------------------------------------------------------------------- */
1217 10 : nIndexSize = poSrcLayer->GetFeatureCount();
1218 :
1219 : pasIndexFields = (OGRField *)
1220 10 : CPLCalloc(sizeof(OGRField), nOrderItems * nIndexSize);
1221 10 : panFIDIndex = (long *) CPLCalloc(sizeof(long),nIndexSize);
1222 10 : panFIDList = (long *) CPLCalloc(sizeof(long),nIndexSize);
1223 :
1224 37 : for( i = 0; i < nIndexSize; i++ )
1225 27 : panFIDIndex[i] = i;
1226 :
1227 : /* -------------------------------------------------------------------- */
1228 : /* Read in all the key values. */
1229 : /* -------------------------------------------------------------------- */
1230 : OGRFeature *poSrcFeat;
1231 10 : int iFeature = 0;
1232 :
1233 47 : while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
1234 : {
1235 : int iKey;
1236 :
1237 54 : for( iKey = 0; iKey < nOrderItems; iKey++ )
1238 : {
1239 27 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1240 : OGRFieldDefn *poFDefn;
1241 : OGRField *psSrcField, *psDstField;
1242 :
1243 27 : psDstField = pasIndexFields + iFeature * nOrderItems + iKey;
1244 :
1245 27 : if ( psKeyDef->field_index >= iFIDFieldIndex)
1246 : {
1247 0 : if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
1248 : {
1249 0 : switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
1250 : {
1251 : case SWQ_INTEGER:
1252 0 : psDstField->Integer = poSrcFeat->GetFieldAsInteger(psKeyDef->field_index);
1253 0 : break;
1254 :
1255 : case SWQ_FLOAT:
1256 0 : psDstField->Real = poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
1257 0 : break;
1258 :
1259 : default:
1260 0 : psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
1261 : break;
1262 : }
1263 : }
1264 0 : continue;
1265 : }
1266 :
1267 27 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1268 54 : psKeyDef->field_index );
1269 :
1270 27 : psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
1271 :
1272 27 : if( poFDefn->GetType() == OFTInteger
1273 : || poFDefn->GetType() == OFTReal
1274 : || poFDefn->GetType() == OFTDate
1275 : || poFDefn->GetType() == OFTTime
1276 : || poFDefn->GetType() == OFTDateTime)
1277 27 : memcpy( psDstField, psSrcField, sizeof(OGRField) );
1278 0 : else if( poFDefn->GetType() == OFTString )
1279 : {
1280 0 : if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
1281 0 : psDstField->String = CPLStrdup( psSrcField->String );
1282 : else
1283 0 : memcpy( psDstField, psSrcField, sizeof(OGRField) );
1284 : }
1285 : }
1286 :
1287 27 : panFIDList[iFeature] = poSrcFeat->GetFID();
1288 27 : delete poSrcFeat;
1289 :
1290 27 : iFeature++;
1291 : }
1292 :
1293 10 : CPLAssert( nIndexSize == iFeature );
1294 :
1295 : /* -------------------------------------------------------------------- */
1296 : /* Quick sort the records. */
1297 : /* -------------------------------------------------------------------- */
1298 10 : SortIndexSection( pasIndexFields, 0, nIndexSize );
1299 :
1300 : /* -------------------------------------------------------------------- */
1301 : /* Rework the FID map to map to real FIDs. */
1302 : /* -------------------------------------------------------------------- */
1303 37 : for( i = 0; i < nIndexSize; i++ )
1304 27 : panFIDIndex[i] = panFIDList[panFIDIndex[i]];
1305 :
1306 10 : CPLFree( panFIDList );
1307 :
1308 : /* -------------------------------------------------------------------- */
1309 : /* Free the key field values. */
1310 : /* -------------------------------------------------------------------- */
1311 20 : for( int iKey = 0; iKey < nOrderItems; iKey++ )
1312 : {
1313 10 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1314 : OGRFieldDefn *poFDefn;
1315 :
1316 10 : if ( psKeyDef->field_index >= iFIDFieldIndex &&
1317 : psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
1318 : {
1319 : /* warning: only special fields of type string should be deallocated */
1320 0 : if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
1321 : {
1322 0 : for( i = 0; i < nIndexSize; i++ )
1323 : {
1324 0 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1325 0 : CPLFree( psField->String );
1326 : }
1327 : }
1328 0 : continue;
1329 : }
1330 :
1331 10 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1332 20 : psKeyDef->field_index );
1333 :
1334 10 : if( poFDefn->GetType() == OFTString )
1335 : {
1336 0 : for( i = 0; i < nIndexSize; i++ )
1337 : {
1338 0 : OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
1339 :
1340 0 : if( psField->Set.nMarker1 != OGRUnsetMarker
1341 : || psField->Set.nMarker2 != OGRUnsetMarker )
1342 0 : CPLFree( psField->String );
1343 : }
1344 : }
1345 : }
1346 :
1347 10 : CPLFree( pasIndexFields );
1348 : }
1349 :
1350 : /************************************************************************/
1351 : /* SortIndexSection() */
1352 : /* */
1353 : /* Sort the records in a section of the index. */
1354 : /************************************************************************/
1355 :
1356 44 : void OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
1357 : int nStart, int nEntries )
1358 :
1359 : {
1360 44 : if( nEntries < 2 )
1361 27 : return;
1362 :
1363 17 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1364 17 : int nOrderItems = psSelectInfo->order_specs;
1365 :
1366 17 : int nFirstGroup = nEntries / 2;
1367 17 : int nFirstStart = nStart;
1368 17 : int nSecondGroup = nEntries - nFirstGroup;
1369 17 : int nSecondStart = nStart + nFirstGroup;
1370 17 : int iMerge = 0;
1371 : long *panMerged;
1372 :
1373 17 : SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup );
1374 17 : SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup );
1375 :
1376 17 : panMerged = (long *) CPLMalloc( sizeof(long) * nEntries );
1377 :
1378 76 : while( iMerge < nEntries )
1379 : {
1380 : int nResult;
1381 :
1382 42 : if( nFirstGroup == 0 )
1383 1 : nResult = -1;
1384 41 : else if( nSecondGroup == 0 )
1385 16 : nResult = 1;
1386 : else
1387 : nResult = Compare( pasIndexFields
1388 25 : + panFIDIndex[nFirstStart] * nOrderItems,
1389 : pasIndexFields
1390 50 : + panFIDIndex[nSecondStart] * nOrderItems );
1391 :
1392 42 : if( nResult < 0 )
1393 : {
1394 22 : panMerged[iMerge++] = panFIDIndex[nSecondStart++];
1395 22 : nSecondGroup--;
1396 : }
1397 : else
1398 : {
1399 20 : panMerged[iMerge++] = panFIDIndex[nFirstStart++];
1400 20 : nFirstGroup--;
1401 : }
1402 : }
1403 :
1404 : /* Copy the merge list back into the main index */
1405 :
1406 17 : memcpy( panFIDIndex + nStart, panMerged, sizeof(long) * nEntries );
1407 17 : CPLFree( panMerged );
1408 : }
1409 :
1410 : /************************************************************************/
1411 : /* Compare() */
1412 : /************************************************************************/
1413 :
1414 25 : int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
1415 : OGRField *pasSecondTuple )
1416 :
1417 : {
1418 25 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1419 25 : int nResult = 0, iKey;
1420 :
1421 50 : for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
1422 : {
1423 25 : swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
1424 : OGRFieldDefn *poFDefn;
1425 :
1426 25 : if( psKeyDef->field_index >= iFIDFieldIndex )
1427 0 : poFDefn = NULL;
1428 : else
1429 25 : poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
1430 50 : psKeyDef->field_index );
1431 :
1432 50 : if( (pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker
1433 0 : && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker)
1434 25 : || (pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
1435 0 : && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker) )
1436 0 : nResult = 0;
1437 25 : else if ( poFDefn == NULL )
1438 : {
1439 0 : switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
1440 : {
1441 : case SWQ_INTEGER:
1442 0 : if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
1443 0 : nResult = -1;
1444 0 : else if( pasFirstTuple[iKey].Integer > pasSecondTuple[iKey].Integer )
1445 0 : nResult = 1;
1446 0 : break;
1447 : case SWQ_FLOAT:
1448 0 : if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
1449 0 : nResult = -1;
1450 0 : else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
1451 0 : nResult = 1;
1452 0 : break;
1453 : case SWQ_STRING:
1454 0 : nResult = strcmp(pasFirstTuple[iKey].String,
1455 0 : pasSecondTuple[iKey].String);
1456 0 : break;
1457 :
1458 : default:
1459 0 : CPLAssert( FALSE );
1460 0 : nResult = 0;
1461 : }
1462 : }
1463 25 : else if( poFDefn->GetType() == OFTInteger )
1464 : {
1465 0 : if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
1466 0 : nResult = -1;
1467 0 : else if( pasFirstTuple[iKey].Integer
1468 0 : > pasSecondTuple[iKey].Integer )
1469 0 : nResult = 1;
1470 : }
1471 25 : else if( poFDefn->GetType() == OFTString )
1472 0 : nResult = strcmp(pasFirstTuple[iKey].String,
1473 0 : pasSecondTuple[iKey].String);
1474 25 : else if( poFDefn->GetType() == OFTReal )
1475 : {
1476 24 : if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
1477 4 : nResult = -1;
1478 20 : else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
1479 20 : nResult = 1;
1480 : }
1481 1 : else if( poFDefn->GetType() == OFTDate ||
1482 : poFDefn->GetType() == OFTTime ||
1483 : poFDefn->GetType() == OFTDateTime)
1484 : {
1485 : nResult = OGRCompareDate(&pasFirstTuple[iKey],
1486 1 : &pasSecondTuple[iKey]);
1487 : }
1488 :
1489 25 : if( psKeyDef->ascending_flag )
1490 24 : nResult *= -1;
1491 : }
1492 :
1493 25 : return nResult;
1494 : }
1495 :
1496 :
1497 : /************************************************************************/
1498 : /* AddFieldDefnToSet() */
1499 : /************************************************************************/
1500 :
1501 2678 : void OGRGenSQLResultsLayer::AddFieldDefnToSet(int iTable, int iColumn,
1502 : CPLHashSet* hSet)
1503 : {
1504 2678 : if (iTable != -1 && iColumn != -1)
1505 : {
1506 1417 : OGRLayer* poLayer = papoTableLayers[iTable];
1507 1417 : if (iColumn < poLayer->GetLayerDefn()->GetFieldCount())
1508 : {
1509 : OGRFieldDefn* poFDefn =
1510 1401 : poLayer->GetLayerDefn()->GetFieldDefn(iColumn);
1511 1401 : CPLHashSetInsert(hSet, poFDefn);
1512 : }
1513 : }
1514 2678 : }
1515 :
1516 : /************************************************************************/
1517 : /* ExploreExprForIgnoredFields() */
1518 : /************************************************************************/
1519 :
1520 1424 : void OGRGenSQLResultsLayer::ExploreExprForIgnoredFields(swq_expr_node* expr,
1521 : CPLHashSet* hSet)
1522 : {
1523 1424 : if (expr->eNodeType == SNT_COLUMN)
1524 : {
1525 1230 : AddFieldDefnToSet(expr->table_index, expr->field_index, hSet);
1526 : }
1527 194 : else if (expr->eNodeType == SNT_OPERATION)
1528 : {
1529 273 : for( int i = 0; i < expr->nSubExprCount; i++ )
1530 184 : ExploreExprForIgnoredFields(expr->papoSubExpr[i], hSet);
1531 : }
1532 1424 : }
1533 :
1534 : /************************************************************************/
1535 : /* FindAndSetIgnoredFields() */
1536 : /************************************************************************/
1537 :
1538 183 : void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
1539 : {
1540 183 : swq_select *psSelectInfo = (swq_select *) pSelectInfo;
1541 : CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashPointer,
1542 : CPLHashSetEqualPointer,
1543 183 : NULL);
1544 :
1545 : /* -------------------------------------------------------------------- */
1546 : /* 1st phase : explore the whole select infos to determine which */
1547 : /* source fields are used */
1548 : /* -------------------------------------------------------------------- */
1549 1576 : for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
1550 : {
1551 1393 : swq_col_def *psColDef = psSelectInfo->column_defs + iField;
1552 1393 : AddFieldDefnToSet(psColDef->table_index, psColDef->field_index, hSet);
1553 1393 : if (psColDef->expr)
1554 1188 : ExploreExprForIgnoredFields(psColDef->expr, hSet);
1555 : }
1556 :
1557 183 : if (psSelectInfo->where_expr)
1558 52 : ExploreExprForIgnoredFields(psSelectInfo->where_expr, hSet);
1559 :
1560 200 : for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
1561 : {
1562 17 : swq_join_def *psJoinDef = psSelectInfo->join_defs + iJoin;
1563 17 : AddFieldDefnToSet(0, psJoinDef->primary_field, hSet);
1564 17 : AddFieldDefnToSet(psJoinDef->secondary_table, psJoinDef->secondary_field, hSet);
1565 : }
1566 :
1567 204 : for( int iOrder = 0; iOrder < psSelectInfo->order_specs; iOrder++ )
1568 : {
1569 21 : swq_order_def *psOrderDef = psSelectInfo->order_defs + iOrder;
1570 21 : AddFieldDefnToSet(psOrderDef->table_index, psOrderDef->field_index, hSet);
1571 : }
1572 :
1573 : /* -------------------------------------------------------------------- */
1574 : /* 2nd phase : now, we can exclude the unused fields */
1575 : /* -------------------------------------------------------------------- */
1576 383 : for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
1577 : {
1578 200 : OGRLayer* poLayer = papoTableLayers[iTable];
1579 200 : OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
1580 : int iSrcField;
1581 200 : char** papszIgnoredFields = NULL;
1582 1182 : for(iSrcField=0;iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
1583 : {
1584 982 : OGRFieldDefn* poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
1585 982 : if (CPLHashSetLookup(hSet,poFDefn) == NULL)
1586 : {
1587 700 : papszIgnoredFields = CSLAddString(papszIgnoredFields, poFDefn->GetNameRef());
1588 : //CPLDebug("OGR", "Adding %s to the list of ignored fields of layer %s",
1589 : // poFDefn->GetNameRef(), poLayer->GetName());
1590 : }
1591 : }
1592 200 : poLayer->SetIgnoredFields((const char**)papszIgnoredFields);
1593 200 : CSLDestroy(papszIgnoredFields);
1594 : }
1595 :
1596 183 : CPLHashSetDestroy(hSet);
1597 183 : }
|