1 : /******************************************************************************
2 : * $Id: ogrfeaturequery.cpp 19722 2010-05-15 11:35:37Z rouault $
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 19722 2010-05-15 11:35:37Z rouault $");
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 67 : OGRFeatureQuery::OGRFeatureQuery()
52 :
53 : {
54 67 : poTargetDefn = NULL;
55 67 : pSWQExpr = NULL;
56 67 : }
57 :
58 : /************************************************************************/
59 : /* ~OGRFeatureQuery() */
60 : /************************************************************************/
61 :
62 67 : OGRFeatureQuery::~OGRFeatureQuery()
63 :
64 : {
65 67 : if( pSWQExpr != NULL )
66 67 : swq_expr_free( (swq_expr *) pSWQExpr );
67 67 : }
68 :
69 : /************************************************************************/
70 : /* Parse */
71 : /************************************************************************/
72 :
73 : OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
74 140 : const char * pszExpression )
75 :
76 : {
77 : /* -------------------------------------------------------------------- */
78 : /* Clear any existing expression. */
79 : /* -------------------------------------------------------------------- */
80 140 : if( pSWQExpr != NULL )
81 73 : 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 140 : int nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT;
90 :
91 : papszFieldNames = (char **)
92 140 : CPLMalloc(sizeof(char *) * nFieldCount );
93 : paeFieldTypes = (swq_field_type *)
94 140 : CPLMalloc(sizeof(swq_field_type) * nFieldCount );
95 :
96 620 : for( iField = 0; iField < poDefn->GetFieldCount(); iField++ )
97 : {
98 480 : OGRFieldDefn *poField = poDefn->GetFieldDefn( iField );
99 :
100 480 : papszFieldNames[iField] = (char *) poField->GetNameRef();
101 :
102 480 : switch( poField->GetType() )
103 : {
104 : case OFTInteger:
105 93 : paeFieldTypes[iField] = SWQ_INTEGER;
106 93 : break;
107 :
108 : case OFTReal:
109 119 : paeFieldTypes[iField] = SWQ_FLOAT;
110 119 : break;
111 :
112 : case OFTString:
113 254 : paeFieldTypes[iField] = SWQ_STRING;
114 254 : break;
115 :
116 : case OFTDate:
117 : case OFTTime:
118 : case OFTDateTime:
119 14 : paeFieldTypes[iField] = SWQ_TIMESTAMP;
120 14 : break;
121 :
122 : default:
123 0 : paeFieldTypes[iField] = SWQ_OTHER;
124 : break;
125 : }
126 : }
127 :
128 140 : iField = 0;
129 980 : while (iField < SPECIAL_FIELD_COUNT)
130 : {
131 700 : papszFieldNames[poDefn->GetFieldCount() + iField] = (char *) SpecialFieldNames[iField];
132 700 : paeFieldTypes[poDefn->GetFieldCount() + iField] = SpecialFieldTypes[iField];
133 700 : ++iField;
134 : }
135 :
136 : /* -------------------------------------------------------------------- */
137 : /* Try to parse. */
138 : /* -------------------------------------------------------------------- */
139 : const char *pszError;
140 140 : OGRErr eErr = OGRERR_NONE;
141 :
142 140 : poTargetDefn = poDefn;
143 : pszError = swq_expr_compile( pszExpression, nFieldCount,
144 : papszFieldNames, paeFieldTypes,
145 140 : (swq_expr **) &pSWQExpr );
146 140 : if( pszError != NULL )
147 : {
148 : CPLError( CE_Failure, CPLE_AppDefined,
149 0 : "%s", pszError );
150 0 : eErr = OGRERR_CORRUPT_DATA;
151 0 : pSWQExpr = NULL;
152 : }
153 :
154 140 : CPLFree( papszFieldNames );
155 140 : CPLFree( paeFieldTypes );
156 :
157 :
158 140 : return eErr;
159 : }
160 :
161 : /************************************************************************/
162 : /* OGRFeatureQueryEvaluator() */
163 : /************************************************************************/
164 :
165 1152 : static int OGRFeatureQueryEvaluator( swq_field_op *op, OGRFeature *poFeature )
166 :
167 : {
168 : OGRField sField;
169 : OGRField *psField;
170 :
171 1152 : int iSpecialField = op->field_index - poFeature->GetDefnRef()->GetFieldCount();
172 1152 : if( iSpecialField >= 0 )
173 : {
174 35 : if ( iSpecialField < SPECIAL_FIELD_COUNT )
175 : {
176 35 : switch ( SpecialFieldTypes[iSpecialField] )
177 : {
178 : case SWQ_INTEGER:
179 20 : sField.Integer = poFeature->GetFieldAsInteger(op->field_index);
180 20 : break;
181 :
182 : case SWQ_FLOAT:
183 3 : sField.Real = poFeature->GetFieldAsDouble(op->field_index);
184 3 : break;
185 :
186 : case SWQ_STRING:
187 : sField.String = (char*)
188 12 : poFeature->GetFieldAsString( op->field_index );
189 12 : break;
190 :
191 : default:
192 0 : CPLAssert( FALSE );
193 : break;
194 : }
195 : }
196 : else
197 : {
198 0 : CPLDebug( "OGRFeatureQuery", "Illegal special field index.");
199 0 : return FALSE;
200 : }
201 35 : psField = &sField;
202 : }
203 : else
204 1117 : psField = poFeature->GetRawFieldRef( op->field_index );
205 :
206 1152 : switch( op->field_type )
207 : {
208 : case SWQ_INTEGER:
209 392 : switch( op->operation )
210 : {
211 : case SWQ_EQ:
212 328 : return psField->Integer == op->int_value;
213 : case SWQ_NE:
214 0 : return psField->Integer != op->int_value;
215 : case SWQ_LT:
216 50 : return psField->Integer < op->int_value;
217 : case SWQ_GT:
218 14 : return psField->Integer > op->int_value;
219 : case SWQ_LE:
220 0 : return psField->Integer <= op->int_value;
221 : case SWQ_GE:
222 0 : return psField->Integer >= op->int_value;
223 : case SWQ_ISNULL:
224 0 : return !poFeature->IsFieldSet( op->field_index );
225 :
226 : case SWQ_IN:
227 : {
228 : const char *pszSrc;
229 :
230 0 : pszSrc = op->string_value;
231 0 : while( *pszSrc != '\0' )
232 : {
233 0 : if( atoi(pszSrc) == psField->Integer )
234 0 : return TRUE;
235 0 : pszSrc += strlen(pszSrc) + 1;
236 : }
237 :
238 0 : return FALSE;
239 : }
240 :
241 : default:
242 : CPLDebug( "OGRFeatureQuery",
243 : "Illegal operation (%d) on integer field.",
244 0 : op->operation );
245 0 : return FALSE;
246 : }
247 :
248 : case SWQ_FLOAT:
249 372 : switch( op->operation )
250 : {
251 : case SWQ_EQ:
252 134 : return psField->Real == op->float_value;
253 : case SWQ_NE:
254 0 : return psField->Real != op->float_value;
255 : case SWQ_LT:
256 87 : return psField->Real < op->float_value;
257 : case SWQ_GT:
258 121 : return psField->Real > op->float_value;
259 : case SWQ_LE:
260 0 : return psField->Real <= op->float_value;
261 : case SWQ_GE:
262 0 : return psField->Real >= op->float_value;
263 : case SWQ_ISNULL:
264 0 : return !poFeature->IsFieldSet( op->field_index );
265 : case SWQ_IN:
266 : {
267 : const char *pszSrc;
268 :
269 30 : pszSrc = op->string_value;
270 111 : while( *pszSrc != '\0' )
271 : {
272 57 : if( atof(pszSrc) == psField->Real )
273 6 : return TRUE;
274 51 : pszSrc += strlen(pszSrc) + 1;
275 : }
276 :
277 24 : return FALSE;
278 : }
279 :
280 : default:
281 : CPLDebug( "OGRFeatureQuery",
282 : "Illegal operation (%d) on float field.",
283 0 : op->operation );
284 0 : return FALSE;
285 : }
286 :
287 : case SWQ_STRING:
288 337 : switch( op->operation )
289 : {
290 : case SWQ_EQ:
291 306 : if (psField->Set.nMarker1 == OGRUnsetMarker
292 : && psField->Set.nMarker2 == OGRUnsetMarker )
293 : {
294 0 : return (op->string_value[0] == '\0');
295 : }
296 : else
297 : {
298 306 : return EQUAL(psField->String,op->string_value);
299 : }
300 : case SWQ_NE:
301 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
302 : && psField->Set.nMarker2 == OGRUnsetMarker )
303 : {
304 0 : return (op->string_value[0] != '\0');
305 : }
306 : else
307 : {
308 0 : return !EQUAL(psField->String,op->string_value);
309 : }
310 :
311 : case SWQ_LT:
312 2 : if (psField->Set.nMarker1 == OGRUnsetMarker
313 : && psField->Set.nMarker2 == OGRUnsetMarker )
314 : {
315 0 : return (op->string_value[0] != '\0');
316 : }
317 : else
318 : {
319 2 : return strcmp(psField->String,op->string_value) < 0;
320 : }
321 : case SWQ_GT:
322 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
323 : && psField->Set.nMarker2 == OGRUnsetMarker )
324 : {
325 0 : return (op->string_value[0] != '\0');
326 : }
327 : else
328 : {
329 0 : return strcmp(psField->String,op->string_value) > 0;
330 : }
331 : case SWQ_LE:
332 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
333 : && psField->Set.nMarker2 == OGRUnsetMarker )
334 : {
335 0 : return (op->string_value[0] != '\0');
336 : }
337 : else
338 : {
339 0 : return strcmp(psField->String,op->string_value) <= 0;
340 : }
341 : case SWQ_GE:
342 0 : if (psField->Set.nMarker1 == OGRUnsetMarker
343 : && psField->Set.nMarker2 == OGRUnsetMarker )
344 : {
345 0 : return (op->string_value[0] != '\0');
346 : }
347 : else
348 : {
349 0 : return strcmp(psField->String,op->string_value) >= 0;
350 : }
351 :
352 : case SWQ_ISNULL:
353 0 : return !poFeature->IsFieldSet( op->field_index );
354 :
355 : case SWQ_LIKE:
356 12 : if (psField->Set.nMarker1 != OGRUnsetMarker
357 : || psField->Set.nMarker2 != OGRUnsetMarker )
358 12 : return swq_test_like(psField->String, op->string_value);
359 : else
360 0 : return FALSE;
361 :
362 : case SWQ_IN:
363 : {
364 : const char *pszSrc;
365 :
366 17 : if( !poFeature->IsFieldSet(op->field_index) )
367 0 : return FALSE;
368 :
369 17 : pszSrc = op->string_value;
370 65 : while( *pszSrc != '\0' )
371 : {
372 33 : if( EQUAL(pszSrc,psField->String) )
373 2 : return TRUE;
374 31 : pszSrc += strlen(pszSrc) + 1;
375 : }
376 :
377 15 : return FALSE;
378 : }
379 :
380 : default:
381 : CPLDebug( "OGRFeatureQuery",
382 : "Illegal operation (%d) on string field.",
383 0 : op->operation );
384 0 : return FALSE;
385 : }
386 :
387 : case SWQ_TIMESTAMP:
388 : {
389 : OGRField sField2;
390 : int bField1Valid = !(psField->Set.nMarker1 == OGRUnsetMarker
391 51 : && psField->Set.nMarker2 == OGRUnsetMarker );
392 : int bField2Valid = op->string_value[0] != '\0' &&
393 51 : OGRParseDate(op->string_value, &sField2, 0);
394 51 : int nRes = OGRCompareDate(psField, &sField2);
395 51 : switch( op->operation )
396 : {
397 : case SWQ_EQ:
398 : return (bField1Valid && bField2Valid && nRes == 0) ||
399 0 : (!bField1Valid && !bField2Valid);
400 : case SWQ_NE:
401 : return !((bField1Valid && bField2Valid && nRes == 0) ||
402 13 : (!bField1Valid && !bField2Valid));
403 :
404 : case SWQ_LT:
405 25 : return (bField1Valid && bField2Valid && nRes < 0);
406 : case SWQ_GT:
407 13 : return (bField1Valid && bField2Valid && nRes > 0);
408 : case SWQ_LE:
409 0 : return (bField1Valid && bField2Valid && nRes <= 0);
410 : case SWQ_GE:
411 0 : return (bField1Valid && bField2Valid && nRes >= 0);
412 : case SWQ_ISNULL:
413 0 : return !poFeature->IsFieldSet( op->field_index );
414 :
415 : default:
416 : CPLDebug( "OGRFeatureQuery",
417 : "Illegal operation (%d) on timestamp field.",
418 0 : op->operation );
419 0 : return FALSE;
420 : }
421 : }
422 :
423 : case SWQ_OTHER:
424 0 : switch( op->operation )
425 : {
426 : case SWQ_ISNULL:
427 0 : return !poFeature->IsFieldSet( op->field_index );
428 :
429 : default:
430 : CPLDebug( "OGRFeatureQuery",
431 : "Illegal operation (%d) on list or binary field.",
432 0 : op->operation );
433 0 : return FALSE;
434 : }
435 :
436 : default:
437 0 : assert( FALSE );
438 : return FALSE;
439 : }
440 : }
441 :
442 : /************************************************************************/
443 : /* Evaluate() */
444 : /************************************************************************/
445 :
446 1102 : int OGRFeatureQuery::Evaluate( OGRFeature *poFeature )
447 :
448 : {
449 1102 : if( pSWQExpr == NULL )
450 0 : return FALSE;
451 :
452 : return swq_expr_evaluate( (swq_expr *) pSWQExpr,
453 : (swq_op_evaluator) OGRFeatureQueryEvaluator,
454 1102 : (void *) poFeature );
455 : }
456 :
457 : /************************************************************************/
458 : /* EvaluateAgainstIndices() */
459 : /* */
460 : /* Attempt to return a list of FIDs matching the given */
461 : /* attribute query conditions utilizing attribute indices. */
462 : /* Returns NULL if the result cannot be computed from the */
463 : /* available indices, or an "OGRNullFID" terminated list of */
464 : /* FIDs if it can. */
465 : /* */
466 : /* For now we only support equality tests on a single indexed */
467 : /* attribute field. Eventually we should make this support */
468 : /* multi-part queries with ranges. */
469 : /************************************************************************/
470 :
471 : long *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
472 106 : OGRErr *peErr )
473 :
474 : {
475 106 : swq_expr *psExpr = (swq_expr *) pSWQExpr;
476 : OGRAttrIndex *poIndex;
477 :
478 106 : if( peErr != NULL )
479 0 : *peErr = OGRERR_NONE;
480 :
481 : /* -------------------------------------------------------------------- */
482 : /* Does the expression meet our requirements? Do we have an */
483 : /* index on the targetted field? */
484 : /* -------------------------------------------------------------------- */
485 106 : if( psExpr == NULL || psExpr->operation != SWQ_EQ
486 : || poLayer->GetIndex() == NULL )
487 22 : return NULL;
488 :
489 84 : poIndex = poLayer->GetIndex()->GetFieldIndex( psExpr->field_index );
490 84 : if( poIndex == NULL )
491 74 : return NULL;
492 :
493 : /* -------------------------------------------------------------------- */
494 : /* OK, we have an index, now we need to query it. */
495 : /* -------------------------------------------------------------------- */
496 : OGRField sValue;
497 : OGRFieldDefn *poFieldDefn;
498 :
499 10 : poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(psExpr->field_index);
500 :
501 10 : switch( poFieldDefn->GetType() )
502 : {
503 : case OFTInteger:
504 2 : sValue.Integer = psExpr->int_value;
505 2 : break;
506 :
507 : case OFTReal:
508 7 : sValue.Real = psExpr->float_value;
509 7 : break;
510 :
511 : case OFTString:
512 1 : sValue.String = psExpr->string_value;
513 1 : break;
514 :
515 : default:
516 0 : CPLAssert( FALSE );
517 0 : return NULL;
518 : }
519 :
520 10 : return poIndex->GetAllMatches( &sValue );
521 : }
522 :
523 : /************************************************************************/
524 : /* OGRFieldCollector() */
525 : /* */
526 : /* Helper function for recursing through tree to satisfy */
527 : /* GetUsedFields(). */
528 : /************************************************************************/
529 :
530 : char **OGRFeatureQuery::FieldCollector( void *pBareOp,
531 0 : char **papszList )
532 :
533 : {
534 0 : swq_field_op *op = (swq_field_op *) pBareOp;
535 :
536 : /* -------------------------------------------------------------------- */
537 : /* References to tables other than the primarily are currently */
538 : /* unsupported. Error out. */
539 : /* -------------------------------------------------------------------- */
540 0 : if( op->table_index != 0 )
541 : {
542 0 : CSLDestroy( papszList );
543 0 : return NULL;
544 : }
545 :
546 : /* -------------------------------------------------------------------- */
547 : /* Add the field name into our list if it is not already there. */
548 : /* -------------------------------------------------------------------- */
549 : const char *pszFieldName;
550 :
551 0 : if( op->field_index >= poTargetDefn->GetFieldCount()
552 : && op->field_index < poTargetDefn->GetFieldCount() + SPECIAL_FIELD_COUNT)
553 0 : pszFieldName = SpecialFieldNames[op->field_index];
554 0 : else if( op->field_index >= 0
555 : && op->field_index < poTargetDefn->GetFieldCount() )
556 : pszFieldName =
557 0 : poTargetDefn->GetFieldDefn(op->field_index)->GetNameRef();
558 : else
559 : {
560 0 : CSLDestroy( papszList );
561 0 : return NULL;
562 : }
563 :
564 0 : if( CSLFindString( papszList, pszFieldName ) == -1 )
565 0 : papszList = CSLAddString( papszList, pszFieldName );
566 :
567 : /* -------------------------------------------------------------------- */
568 : /* Add in fields from subexpressions. */
569 : /* -------------------------------------------------------------------- */
570 0 : if( op->first_sub_expr != NULL )
571 0 : papszList = FieldCollector( op->first_sub_expr, papszList );
572 0 : if( op->second_sub_expr != NULL )
573 0 : papszList = FieldCollector( op->second_sub_expr, papszList );
574 :
575 0 : return papszList;
576 : }
577 :
578 : /************************************************************************/
579 : /* GetUsedFields() */
580 : /************************************************************************/
581 :
582 : /**
583 : * Returns lists of fields in expression.
584 : *
585 : * All attribute fields are used in the expression of this feature
586 : * query are returned as a StringList of field names. This function would
587 : * primarily be used within drivers to recognise special case conditions
588 : * depending only on attribute fields that can be very efficiently
589 : * fetched.
590 : *
591 : * NOTE: If any fields in the expression are from tables other than the
592 : * primary table then NULL is returned indicating an error. In succesful
593 : * use, no non-empty expression should return an empty list.
594 : *
595 : * @return list of field names. Free list with CSLDestroy() when no longer
596 : * required.
597 : */
598 :
599 0 : char **OGRFeatureQuery::GetUsedFields( )
600 :
601 : {
602 0 : if( pSWQExpr == NULL )
603 0 : return NULL;
604 :
605 :
606 0 : return FieldCollector( pSWQExpr, NULL );
607 : }
608 :
609 :
610 :
|