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