1 : /******************************************************************************
2 : * $Id: ogrfeaturequery.cpp 16787 2009-04-17 13:51:40Z dmorissette $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of simple SQL WHERE style attributes queries
6 : * for OGRFeatures.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include <assert.h>
32 : #include "ogr_feature.h"
33 : #include "ogr_p.h"
34 : #include "ogr_attrind.h"
35 :
36 : CPL_CVSID("$Id: ogrfeaturequery.cpp 16787 2009-04-17 13:51:40Z dmorissette $");
37 :
38 : /************************************************************************/
39 : /* Support for special attributes (feature query and selection) */
40 : /************************************************************************/
41 :
42 : const char* SpecialFieldNames[SPECIAL_FIELD_COUNT]
43 : = {"FID", "OGR_GEOMETRY", "OGR_STYLE", "OGR_GEOM_WKT", "OGR_GEOM_AREA"};
44 : const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT]
45 : = {SWQ_INTEGER, SWQ_STRING, SWQ_STRING, SWQ_STRING, SWQ_FLOAT};
46 :
47 : /************************************************************************/
48 : /* OGRFeatureQuery() */
49 : /************************************************************************/
50 :
51 60 : OGRFeatureQuery::OGRFeatureQuery()
52 :
53 : {
54 60 : poTargetDefn = NULL;
55 60 : pSWQExpr = NULL;
56 60 : }
57 :
58 : /************************************************************************/
59 : /* ~OGRFeatureQuery() */
60 : /************************************************************************/
61 :
62 60 : OGRFeatureQuery::~OGRFeatureQuery()
63 :
64 : {
65 60 : if( pSWQExpr != NULL )
66 60 : swq_expr_free( (swq_expr *) pSWQExpr );
67 60 : }
68 :
69 : /************************************************************************/
70 : /* Parse */
71 : /************************************************************************/
72 :
73 126 : OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
74 : const char * pszExpression )
75 :
76 : {
77 : /* -------------------------------------------------------------------- */
78 : /* Clear any existing expression. */
79 : /* -------------------------------------------------------------------- */
80 126 : if( pSWQExpr != NULL )
81 66 : swq_expr_free( (swq_expr *) pSWQExpr );
82 :
83 : /* -------------------------------------------------------------------- */
84 : /* Build list of fields. */
85 : /* -------------------------------------------------------------------- */
86 : char **papszFieldNames;
87 : swq_field_type *paeFieldTypes;
88 : int iField;
89 126 : int nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT;
90 :
91 : papszFieldNames = (char **)
92 126 : CPLMalloc(sizeof(char *) * nFieldCount );
93 : paeFieldTypes = (swq_field_type *)
94 126 : CPLMalloc(sizeof(swq_field_type) * nFieldCount );
95 :
96 542 : for( iField = 0; iField < poDefn->GetFieldCount(); iField++ )
97 : {
98 416 : OGRFieldDefn *poField = poDefn->GetFieldDefn( iField );
99 :
100 416 : papszFieldNames[iField] = (char *) poField->GetNameRef();
101 :
102 416 : switch( poField->GetType() )
103 : {
104 : case OFTInteger:
105 93 : paeFieldTypes[iField] = SWQ_INTEGER;
106 93 : break;
107 :
108 : case OFTReal:
109 114 : paeFieldTypes[iField] = SWQ_FLOAT;
110 114 : break;
111 :
112 : case OFTString:
113 197 : paeFieldTypes[iField] = SWQ_STRING;
114 197 : break;
115 :
116 : default:
117 12 : paeFieldTypes[iField] = SWQ_OTHER;
118 : break;
119 : }
120 : }
121 :
122 126 : iField = 0;
123 882 : while (iField < SPECIAL_FIELD_COUNT)
124 : {
125 630 : papszFieldNames[poDefn->GetFieldCount() + iField] = (char *) SpecialFieldNames[iField];
126 630 : paeFieldTypes[poDefn->GetFieldCount() + iField] = SpecialFieldTypes[iField];
127 630 : ++iField;
128 : }
129 :
130 : /* -------------------------------------------------------------------- */
131 : /* Try to parse. */
132 : /* -------------------------------------------------------------------- */
133 : const char *pszError;
134 126 : OGRErr eErr = OGRERR_NONE;
135 :
136 126 : poTargetDefn = poDefn;
137 : pszError = swq_expr_compile( pszExpression, nFieldCount,
138 : papszFieldNames, paeFieldTypes,
139 126 : (swq_expr **) &pSWQExpr );
140 126 : if( pszError != NULL )
141 : {
142 : CPLError( CE_Failure, CPLE_AppDefined,
143 0 : "%s", pszError );
144 0 : eErr = OGRERR_CORRUPT_DATA;
145 0 : pSWQExpr = NULL;
146 : }
147 :
148 126 : CPLFree( papszFieldNames );
149 126 : CPLFree( paeFieldTypes );
150 :
151 :
152 126 : return eErr;
153 : }
154 :
155 : /************************************************************************/
156 : /* OGRFeatureQueryEvaluator() */
157 : /************************************************************************/
158 :
159 1032 : static int OGRFeatureQueryEvaluator( swq_field_op *op, OGRFeature *poFeature )
160 :
161 : {
162 : OGRField sField;
163 : OGRField *psField;
164 :
165 1032 : int iSpecialField = op->field_index - poFeature->GetDefnRef()->GetFieldCount();
166 1032 : if( iSpecialField >= 0 )
167 : {
168 35 : if ( iSpecialField < SPECIAL_FIELD_COUNT )
169 : {
170 35 : switch ( SpecialFieldTypes[iSpecialField] )
171 : {
172 : case SWQ_INTEGER:
173 20 : sField.Integer = poFeature->GetFieldAsInteger(op->field_index);
174 20 : break;
175 :
176 : case SWQ_FLOAT:
177 3 : sField.Real = poFeature->GetFieldAsDouble(op->field_index);
178 3 : break;
179 :
180 : case SWQ_STRING:
181 : sField.String = (char*)
182 12 : poFeature->GetFieldAsString( op->field_index );
183 : break;
184 :
185 : default:
186 : CPLAssert( FALSE );
187 : break;
188 : }
189 : }
190 : else
191 : {
192 0 : CPLDebug( "OGRFeatureQuery", "Illegal special field index.");
193 0 : return FALSE;
194 : }
195 35 : psField = &sField;
196 : }
197 : else
198 997 : psField = poFeature->GetRawFieldRef( op->field_index );
199 :
200 1032 : switch( op->field_type )
201 : {
202 : case SWQ_INTEGER:
203 392 : switch( op->operation )
204 : {
205 : case SWQ_EQ:
206 328 : return psField->Integer == op->int_value;
207 : case SWQ_NE:
208 0 : return psField->Integer != op->int_value;
209 : case SWQ_LT:
210 50 : return psField->Integer < op->int_value;
211 : case SWQ_GT:
212 14 : return psField->Integer > op->int_value;
213 : case SWQ_LE:
214 0 : return psField->Integer <= op->int_value;
215 : case SWQ_GE:
216 0 : return psField->Integer >= op->int_value;
217 : case SWQ_ISNULL:
218 0 : return !poFeature->IsFieldSet( op->field_index );
219 :
220 : case SWQ_IN:
221 : {
222 : const char *pszSrc;
223 :
224 0 : pszSrc = op->string_value;
225 0 : while( *pszSrc != '\0' )
226 : {
227 0 : if( atoi(pszSrc) == psField->Integer )
228 0 : return TRUE;
229 0 : pszSrc += strlen(pszSrc) + 1;
230 : }
231 :
232 0 : return FALSE;
233 : }
234 :
235 : default:
236 : CPLDebug( "OGRFeatureQuery",
237 : "Illegal operation (%d) on integer field.",
238 0 : op->operation );
239 0 : return FALSE;
240 : }
241 :
242 : case SWQ_FLOAT:
243 333 : switch( op->operation )
244 : {
245 : case SWQ_EQ:
246 95 : return psField->Real == op->float_value;
247 : case SWQ_NE:
248 0 : return psField->Real != op->float_value;
249 : case SWQ_LT:
250 87 : return psField->Real < op->float_value;
251 : case SWQ_GT:
252 121 : return psField->Real > op->float_value;
253 : case SWQ_LE:
254 0 : return psField->Real <= op->float_value;
255 : case SWQ_GE:
256 0 : return psField->Real >= op->float_value;
257 : case SWQ_ISNULL:
258 0 : return !poFeature->IsFieldSet( op->field_index );
259 : case SWQ_IN:
260 : {
261 : const char *pszSrc;
262 :
263 30 : pszSrc = op->string_value;
264 111 : while( *pszSrc != '\0' )
265 : {
266 57 : if( atof(pszSrc) == psField->Real )
267 6 : return TRUE;
268 51 : pszSrc += strlen(pszSrc) + 1;
269 : }
270 :
271 24 : return FALSE;
272 : }
273 :
274 : default:
275 : CPLDebug( "OGRFeatureQuery",
276 : "Illegal operation (%d) on float field.",
277 0 : op->operation );
278 0 : return FALSE;
279 : }
280 :
281 : case SWQ_STRING:
282 307 : switch( op->operation )
283 : {
284 : case SWQ_EQ:
285 276 : if (psField->Set.nMarker1 == OGRUnsetMarker
286 : && psField->Set.nMarker2 == OGRUnsetMarker )
287 : {
288 0 : return (op->string_value[0] == '\0');
289 : }
290 : else
291 : {
292 276 : return EQUAL(psField->String,op->string_value);
293 : }
294 : case SWQ_NE:
295 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
296 : && psField->Set.nMarker2 == OGRUnsetMarker )
297 : {
298 0 : return (op->string_value[0] != '\0');
299 : }
300 : else
301 : {
302 0 : return !EQUAL(psField->String,op->string_value);
303 : }
304 :
305 : case SWQ_LT:
306 2 : if (psField->Set.nMarker1 == OGRUnsetMarker
307 : && psField->Set.nMarker2 == OGRUnsetMarker )
308 : {
309 0 : return (op->string_value[0] != '\0');
310 : }
311 : else
312 : {
313 2 : return strcmp(psField->String,op->string_value) < 0;
314 : }
315 : case SWQ_GT:
316 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
317 : && psField->Set.nMarker2 == OGRUnsetMarker )
318 : {
319 0 : return (op->string_value[0] != '\0');
320 : }
321 : else
322 : {
323 0 : return strcmp(psField->String,op->string_value) > 0;
324 : }
325 : case SWQ_LE:
326 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
327 : && psField->Set.nMarker2 == OGRUnsetMarker )
328 : {
329 0 : return (op->string_value[0] != '\0');
330 : }
331 : else
332 : {
333 0 : return strcmp(psField->String,op->string_value) <= 0;
334 : }
335 : case SWQ_GE:
336 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
337 : && psField->Set.nMarker2 == OGRUnsetMarker )
338 : {
339 0 : return (op->string_value[0] != '\0');
340 : }
341 : else
342 : {
343 0 : return strcmp(psField->String,op->string_value) >= 0;
344 : }
345 :
346 : case SWQ_ISNULL:
347 0 : return !poFeature->IsFieldSet( op->field_index );
348 :
349 : case SWQ_LIKE:
350 12 : if (psField->Set.nMarker1 != OGRUnsetMarker
351 : || psField->Set.nMarker2 != OGRUnsetMarker )
352 12 : return swq_test_like(psField->String, op->string_value);
353 : else
354 0 : return FALSE;
355 :
356 : case SWQ_IN:
357 : {
358 : const char *pszSrc;
359 :
360 17 : if( !poFeature->IsFieldSet(op->field_index) )
361 0 : return FALSE;
362 :
363 17 : pszSrc = op->string_value;
364 65 : while( *pszSrc != '\0' )
365 : {
366 33 : if( EQUAL(pszSrc,psField->String) )
367 2 : return TRUE;
368 31 : pszSrc += strlen(pszSrc) + 1;
369 : }
370 :
371 15 : return FALSE;
372 : }
373 :
374 : default:
375 : CPLDebug( "OGRFeatureQuery",
376 : "Illegal operation (%d) on string field.",
377 0 : op->operation );
378 0 : return FALSE;
379 : }
380 :
381 : case SWQ_OTHER:
382 0 : switch( op->operation )
383 : {
384 : case SWQ_ISNULL:
385 0 : return !poFeature->IsFieldSet( op->field_index );
386 :
387 : default:
388 : CPLDebug( "OGRFeatureQuery",
389 : "Illegal operation (%d) on list or binary field.",
390 0 : op->operation );
391 0 : return FALSE;
392 : }
393 :
394 : default:
395 0 : assert( FALSE );
396 : return FALSE;
397 : }
398 : }
399 :
400 : /************************************************************************/
401 : /* Evaluate() */
402 : /************************************************************************/
403 :
404 1008 : int OGRFeatureQuery::Evaluate( OGRFeature *poFeature )
405 :
406 : {
407 1008 : if( pSWQExpr == NULL )
408 0 : return FALSE;
409 :
410 : return swq_expr_evaluate( (swq_expr *) pSWQExpr,
411 : (swq_op_evaluator) OGRFeatureQueryEvaluator,
412 1008 : (void *) poFeature );
413 : }
414 :
415 : /************************************************************************/
416 : /* EvaluateAgainstIndices() */
417 : /* */
418 : /* Attempt to return a list of FIDs matching the given */
419 : /* attribute query conditions utilizing attribute indices. */
420 : /* Returns NULL if the result cannot be computed from the */
421 : /* available indices, or an "OGRNullFID" terminated list of */
422 : /* FIDs if it can. */
423 : /* */
424 : /* For now we only support equality tests on a single indexed */
425 : /* attribute field. Eventually we should make this support */
426 : /* multi-part queries with ranges. */
427 : /************************************************************************/
428 :
429 95 : long *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
430 : OGRErr *peErr )
431 :
432 : {
433 95 : swq_expr *psExpr = (swq_expr *) pSWQExpr;
434 : OGRAttrIndex *poIndex;
435 :
436 95 : if( peErr != NULL )
437 0 : *peErr = OGRERR_NONE;
438 :
439 : /* -------------------------------------------------------------------- */
440 : /* Does the expression meet our requirements? Do we have an */
441 : /* index on the targetted field? */
442 : /* -------------------------------------------------------------------- */
443 95 : if( psExpr == NULL || psExpr->operation != SWQ_EQ
444 : || poLayer->GetIndex() == NULL )
445 22 : return NULL;
446 :
447 73 : poIndex = poLayer->GetIndex()->GetFieldIndex( psExpr->field_index );
448 73 : if( poIndex == NULL )
449 63 : return NULL;
450 :
451 : /* -------------------------------------------------------------------- */
452 : /* OK, we have an index, now we need to query it. */
453 : /* -------------------------------------------------------------------- */
454 : OGRField sValue;
455 : OGRFieldDefn *poFieldDefn;
456 :
457 10 : poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(psExpr->field_index);
458 :
459 10 : switch( poFieldDefn->GetType() )
460 : {
461 : case OFTInteger:
462 2 : sValue.Integer = psExpr->int_value;
463 2 : break;
464 :
465 : case OFTReal:
466 7 : sValue.Real = psExpr->float_value;
467 7 : break;
468 :
469 : case OFTString:
470 1 : sValue.String = psExpr->string_value;
471 1 : break;
472 :
473 : default:
474 : CPLAssert( FALSE );
475 0 : return NULL;
476 : }
477 :
478 10 : return poIndex->GetAllMatches( &sValue );
479 : }
480 :
481 : /************************************************************************/
482 : /* OGRFieldCollector() */
483 : /* */
484 : /* Helper function for recursing through tree to satisfy */
485 : /* GetUsedFields(). */
486 : /************************************************************************/
487 :
488 0 : char **OGRFeatureQuery::FieldCollector( void *pBareOp,
489 : char **papszList )
490 :
491 : {
492 0 : swq_field_op *op = (swq_field_op *) pBareOp;
493 :
494 : /* -------------------------------------------------------------------- */
495 : /* References to tables other than the primarily are currently */
496 : /* unsupported. Error out. */
497 : /* -------------------------------------------------------------------- */
498 0 : if( op->table_index != 0 )
499 : {
500 0 : CSLDestroy( papszList );
501 0 : return NULL;
502 : }
503 :
504 : /* -------------------------------------------------------------------- */
505 : /* Add the field name into our list if it is not already there. */
506 : /* -------------------------------------------------------------------- */
507 : const char *pszFieldName;
508 :
509 0 : if( op->field_index >= poTargetDefn->GetFieldCount()
510 : && op->field_index < poTargetDefn->GetFieldCount() + SPECIAL_FIELD_COUNT)
511 0 : pszFieldName = SpecialFieldNames[op->field_index];
512 0 : else if( op->field_index >= 0
513 : && op->field_index < poTargetDefn->GetFieldCount() )
514 : pszFieldName =
515 0 : poTargetDefn->GetFieldDefn(op->field_index)->GetNameRef();
516 : else
517 : {
518 0 : CSLDestroy( papszList );
519 0 : return NULL;
520 : }
521 :
522 0 : if( CSLFindString( papszList, pszFieldName ) == -1 )
523 0 : papszList = CSLAddString( papszList, pszFieldName );
524 :
525 : /* -------------------------------------------------------------------- */
526 : /* Add in fields from subexpressions. */
527 : /* -------------------------------------------------------------------- */
528 0 : if( op->first_sub_expr != NULL )
529 0 : papszList = FieldCollector( op->first_sub_expr, papszList );
530 0 : if( op->second_sub_expr != NULL )
531 0 : papszList = FieldCollector( op->second_sub_expr, papszList );
532 :
533 0 : return papszList;
534 : }
535 :
536 : /************************************************************************/
537 : /* GetUsedFields() */
538 : /************************************************************************/
539 :
540 : /**
541 : * Returns lists of fields in expression.
542 : *
543 : * All attribute fields are used in the expression of this feature
544 : * query are returned as a StringList of field names. This function would
545 : * primarily be used within drivers to recognise special case conditions
546 : * depending only on attribute fields that can be very efficiently
547 : * fetched.
548 : *
549 : * NOTE: If any fields in the expression are from tables other than the
550 : * primary table then NULL is returned indicating an error. In succesful
551 : * use, no non-empty expression should return an empty list.
552 : *
553 : * @return list of field names. Free list with CSLDestroy() when no longer
554 : * required.
555 : */
556 :
557 0 : char **OGRFeatureQuery::GetUsedFields( )
558 :
559 : {
560 0 : if( pSWQExpr == NULL )
561 0 : return NULL;
562 :
563 :
564 0 : return FieldCollector( pSWQExpr, NULL );
565 : }
566 :
567 :
568 :
|