LTP GCOV extension - code coverage report
Current view: directory - ogr - ogrfeaturequery.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 188
Code covered: 56.9 % Executed lines: 107

       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                 : 

Generated by: LTP GCOV extension version 1.5