LCOV - code coverage report
Current view: directory - ogr - ogrfeaturequery.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 235 194 82.6 %
Date: 2012-12-26 Functions: 16 14 87.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrfeaturequery.cpp 24849 2012-08-25 12:22:05Z 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 "swq.h"
      33                 : #include "ogr_feature.h"
      34                 : #include "ogr_p.h"
      35                 : #include "ogr_attrind.h"
      36                 : 
      37                 : CPL_CVSID("$Id: ogrfeaturequery.cpp 24849 2012-08-25 12:22:05Z rouault $");
      38                 : 
      39                 : /************************************************************************/
      40                 : /*     Support for special attributes (feature query and selection)     */
      41                 : /************************************************************************/
      42                 : 
      43                 : const char* SpecialFieldNames[SPECIAL_FIELD_COUNT] 
      44                 : = {"FID", "OGR_GEOMETRY", "OGR_STYLE", "OGR_GEOM_WKT", "OGR_GEOM_AREA"};
      45                 : const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT] 
      46                 : = {SWQ_INTEGER, SWQ_STRING, SWQ_STRING, SWQ_STRING, SWQ_FLOAT};
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                          OGRFeatureQuery()                           */
      50                 : /************************************************************************/
      51                 : 
      52             446 : OGRFeatureQuery::OGRFeatureQuery()
      53                 : 
      54                 : {
      55             446 :     poTargetDefn = NULL;
      56             446 :     pSWQExpr = NULL;
      57             446 : }
      58                 : 
      59                 : /************************************************************************/
      60                 : /*                          ~OGRFeatureQuery()                          */
      61                 : /************************************************************************/
      62                 : 
      63             446 : OGRFeatureQuery::~OGRFeatureQuery()
      64                 : 
      65                 : {
      66             446 :     delete (swq_expr_node *) pSWQExpr;
      67             446 : }
      68                 : 
      69                 : /************************************************************************/
      70                 : /*                                Parse                                 */
      71                 : /************************************************************************/
      72                 : 
      73             849 : OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn, 
      74                 :                                  const char * pszExpression )
      75                 : 
      76                 : {
      77                 : /* -------------------------------------------------------------------- */
      78                 : /*      Clear any existing expression.                                  */
      79                 : /* -------------------------------------------------------------------- */
      80             849 :     if( pSWQExpr != NULL )
      81                 :     {
      82             403 :         delete (swq_expr_node *) pSWQExpr;
      83             403 :         pSWQExpr = NULL;
      84                 :     }
      85                 : 
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Build list of fields.                                           */
      88                 : /* -------------------------------------------------------------------- */
      89                 :     char        **papszFieldNames;
      90                 :     swq_field_type *paeFieldTypes;
      91                 :     int         iField;
      92             849 :     int         nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT;
      93                 : 
      94                 :     papszFieldNames = (char **) 
      95             849 :         CPLMalloc(sizeof(char *) * nFieldCount );
      96                 :     paeFieldTypes = (swq_field_type *) 
      97             849 :         CPLMalloc(sizeof(swq_field_type) * nFieldCount );
      98                 : 
      99            5751 :     for( iField = 0; iField < poDefn->GetFieldCount(); iField++ )
     100                 :     {
     101            4902 :         OGRFieldDefn    *poField = poDefn->GetFieldDefn( iField );
     102                 : 
     103            4902 :         papszFieldNames[iField] = (char *) poField->GetNameRef();
     104                 : 
     105            4902 :         switch( poField->GetType() )
     106                 :         {
     107                 :           case OFTInteger:
     108            1290 :             paeFieldTypes[iField] = SWQ_INTEGER;
     109            1290 :             break;
     110                 : 
     111                 :           case OFTReal:
     112             885 :             paeFieldTypes[iField] = SWQ_FLOAT;
     113             885 :             break;
     114                 : 
     115                 :           case OFTString:
     116            1967 :             paeFieldTypes[iField] = SWQ_STRING;
     117            1967 :             break;
     118                 : 
     119                 :           case OFTDate:
     120                 :           case OFTTime:
     121                 :           case OFTDateTime:
     122             597 :             paeFieldTypes[iField] = SWQ_TIMESTAMP;
     123             597 :             break;
     124                 : 
     125                 :           default:
     126             163 :             paeFieldTypes[iField] = SWQ_OTHER;
     127                 :             break;
     128                 :         }
     129                 :     }
     130                 : 
     131             849 :     iField = 0;
     132            5943 :     while (iField < SPECIAL_FIELD_COUNT)
     133                 :     {
     134            4245 :         papszFieldNames[poDefn->GetFieldCount() + iField] = (char *) SpecialFieldNames[iField];
     135            4245 :         paeFieldTypes[poDefn->GetFieldCount() + iField] = SpecialFieldTypes[iField];
     136            4245 :         ++iField;
     137                 :     }
     138                 : 
     139                 : /* -------------------------------------------------------------------- */
     140                 : /*      Try to parse.                                                   */
     141                 : /* -------------------------------------------------------------------- */
     142             849 :     OGRErr      eErr = OGRERR_NONE;
     143                 :     CPLErr      eCPLErr;
     144                 : 
     145             849 :     poTargetDefn = poDefn;
     146                 :     eCPLErr = swq_expr_compile( pszExpression, nFieldCount,
     147                 :                                 papszFieldNames, paeFieldTypes, 
     148             849 :                                 (swq_expr_node **) &pSWQExpr );
     149             849 :     if( eCPLErr != CE_None )
     150                 :     {
     151               0 :         eErr = OGRERR_CORRUPT_DATA;
     152               0 :         pSWQExpr = NULL;
     153                 :     }
     154                 : 
     155             849 :     CPLFree( papszFieldNames );
     156             849 :     CPLFree( paeFieldTypes );
     157                 : 
     158                 : 
     159             849 :     return eErr;
     160                 : }
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                         OGRFeatureFetcher()                          */
     164                 : /************************************************************************/
     165                 : 
     166          458549 : static swq_expr_node *OGRFeatureFetcher( swq_expr_node *op, void *pFeatureIn )
     167                 : 
     168                 : {
     169          458549 :     OGRFeature *poFeature = (OGRFeature *) pFeatureIn;
     170          458549 :     swq_expr_node *poRetNode = NULL;
     171                 : 
     172          458549 :     switch( op->field_type )
     173                 :     {
     174                 :       case SWQ_INTEGER:
     175                 :       case SWQ_BOOLEAN:
     176                 :         poRetNode = new swq_expr_node( 
     177           80189 :             poFeature->GetFieldAsInteger(op->field_index) );
     178           80189 :         break;
     179                 : 
     180                 :       case SWQ_FLOAT:
     181                 :         poRetNode = new swq_expr_node( 
     182            2735 :             poFeature->GetFieldAsDouble(op->field_index) );
     183            2735 :         break;
     184                 :         
     185                 :       default:
     186                 :         poRetNode = new swq_expr_node( 
     187          375625 :             poFeature->GetFieldAsString(op->field_index) );
     188                 :         break;
     189                 :     }
     190                 : 
     191          458549 :     poRetNode->is_null = !(poFeature->IsFieldSet(op->field_index));
     192                 : 
     193          458549 :     return poRetNode;
     194                 : }
     195                 : 
     196                 : /************************************************************************/
     197                 : /*                              Evaluate()                              */
     198                 : /************************************************************************/
     199                 : 
     200          594175 : int OGRFeatureQuery::Evaluate( OGRFeature *poFeature )
     201                 : 
     202                 : {
     203          594175 :     if( pSWQExpr == NULL )
     204               0 :         return FALSE;
     205                 : 
     206                 :     swq_expr_node *poResult;
     207                 : 
     208                 :     poResult = ((swq_expr_node *) pSWQExpr)->Evaluate( OGRFeatureFetcher,
     209          594175 :                                                        (void *) poFeature );
     210                 : 
     211          594175 :     if( poResult == NULL )
     212               0 :         return FALSE;
     213                 : 
     214          594175 :     CPLAssert( poResult->field_type == SWQ_BOOLEAN );
     215                 : 
     216          594175 :     int bLogicalResult = poResult->int_value;
     217                 : 
     218          594175 :     delete poResult;
     219                 : 
     220          594175 :     return bLogicalResult;
     221                 : }
     222                 : 
     223                 : /************************************************************************/
     224                 : /*                            CanUseIndex()                             */
     225                 : /************************************************************************/
     226                 : 
     227              67 : int OGRFeatureQuery::CanUseIndex( OGRLayer *poLayer )
     228                 : {
     229              67 :     swq_expr_node *psExpr = (swq_expr_node *) pSWQExpr;
     230                 : 
     231                 : /* -------------------------------------------------------------------- */
     232                 : /*      Do we have an index on the targetted layer?                     */
     233                 : /* -------------------------------------------------------------------- */
     234              67 :     if ( poLayer->GetIndex() == FALSE )
     235               0 :         return FALSE;
     236                 : 
     237              67 :     return CanUseIndex( psExpr, poLayer );
     238                 : }
     239                 : 
     240              67 : int OGRFeatureQuery::CanUseIndex( swq_expr_node *psExpr,
     241                 :                                   OGRLayer *poLayer )
     242                 : {
     243                 :     OGRAttrIndex *poIndex;
     244                 : 
     245                 : /* -------------------------------------------------------------------- */
     246                 : /*      Does the expression meet our requirements?                      */
     247                 : /* -------------------------------------------------------------------- */
     248              67 :     if( psExpr == NULL ||
     249                 :         psExpr->eNodeType != SNT_OPERATION )
     250               0 :         return FALSE;
     251                 : 
     252              67 :     if ((psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
     253                 :          psExpr->nSubExprCount == 2)
     254                 :     {
     255                 :         return CanUseIndex( psExpr->papoSubExpr[0], poLayer ) &&
     256               0 :                CanUseIndex( psExpr->papoSubExpr[1], poLayer );
     257                 :     }
     258                 : 
     259              67 :     if( !(psExpr->nOperation == SWQ_EQ || psExpr->nOperation == SWQ_IN)
     260                 :         || psExpr->nSubExprCount < 2 )
     261               1 :         return FALSE;
     262                 : 
     263              66 :     swq_expr_node *poColumn = psExpr->papoSubExpr[0];
     264              66 :     swq_expr_node *poValue = psExpr->papoSubExpr[1];
     265                 :     
     266              66 :     if( poColumn->eNodeType != SNT_COLUMN
     267                 :         || poValue->eNodeType != SNT_CONSTANT )
     268               0 :         return FALSE;
     269                 : 
     270              66 :     poIndex = poLayer->GetIndex()->GetFieldIndex( poColumn->field_index );
     271              66 :     if( poIndex == NULL )
     272              66 :         return FALSE;
     273                 : 
     274                 : /* -------------------------------------------------------------------- */
     275                 : /*      OK, we have an index                                            */
     276                 : /* -------------------------------------------------------------------- */
     277               0 :     return TRUE;
     278                 : }
     279                 : 
     280                 : /************************************************************************/
     281                 : /*                       EvaluateAgainstIndices()                       */
     282                 : /*                                                                      */
     283                 : /*      Attempt to return a list of FIDs matching the given             */
     284                 : /*      attribute query conditions utilizing attribute indices.         */
     285                 : /*      Returns NULL if the result cannot be computed from the          */
     286                 : /*      available indices, or an "OGRNullFID" terminated list of        */
     287                 : /*      FIDs if it can.                                                 */
     288                 : /*                                                                      */
     289                 : /*      For now we only support equality tests on a single indexed      */
     290                 : /*      attribute field.  Eventually we should make this support        */
     291                 : /*      multi-part queries with ranges.                                 */
     292                 : /************************************************************************/
     293                 : 
     294              10 : static int CompareLong(const void *a, const void *b)
     295                 : {
     296              10 :   return (*(const long *)a) - (*(const long *)b);
     297                 : }
     298                 : 
     299             432 : long *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer, 
     300                 :                                                OGRErr *peErr )
     301                 : 
     302                 : {
     303             432 :     swq_expr_node *psExpr = (swq_expr_node *) pSWQExpr;
     304                 : 
     305             432 :     if( peErr != NULL )
     306               0 :         *peErr = OGRERR_NONE;
     307                 : 
     308                 : /* -------------------------------------------------------------------- */
     309                 : /*      Do we have an index on the targetted layer?                     */
     310                 : /* -------------------------------------------------------------------- */
     311             432 :     if ( poLayer->GetIndex() == NULL )
     312              32 :         return NULL;
     313                 : 
     314             400 :     int nFIDCount = 0;
     315             400 :     return EvaluateAgainstIndices(psExpr, poLayer, nFIDCount);
     316                 : }
     317                 : 
     318                 : /* The input arrays must be sorted ! */
     319                 : static
     320               1 : long* OGRORLongArray(long panFIDList1[], int nFIDCount1,
     321                 :                      long panFIDList2[], int nFIDCount2, int& nFIDCount)
     322                 : {
     323               1 :     int nMaxCount = nFIDCount1 + nFIDCount2;
     324               1 :     long* panFIDList = (long*) CPLMalloc((nMaxCount+1) * sizeof(long));
     325               1 :     nFIDCount = 0;
     326                 : 
     327               1 :     int i1 = 0, i2 =0;
     328               6 :     for(;i1<nFIDCount1 || i2<nFIDCount2;)
     329                 :     {
     330               6 :         if (i1 < nFIDCount1 && i2 < nFIDCount2)
     331                 :         {
     332               2 :             long nVal1 = panFIDList1[i1];
     333               2 :             long nVal2 = panFIDList2[i2];
     334               2 :             if (nVal1 < nVal2)
     335                 :             {
     336               2 :                 if (i1+1 < nFIDCount1 && panFIDList1[i1+1] <= nVal2)
     337                 :                 {
     338               1 :                     panFIDList[nFIDCount ++] = nVal1;
     339               1 :                     i1 ++;
     340                 :                 }
     341                 :                 else
     342                 :                 {
     343               0 :                     panFIDList[nFIDCount ++] = nVal1;
     344               0 :                     panFIDList[nFIDCount ++] = nVal2;
     345               0 :                     i1 ++;
     346               0 :                     i2 ++;
     347                 :                 }
     348                 :             }
     349               1 :             else if (nVal1 == nVal2)
     350                 :             {
     351               1 :                 panFIDList[nFIDCount ++] = nVal1;
     352               1 :                 i1 ++;
     353               1 :                 i2 ++;
     354                 :             }
     355                 :             else
     356                 :             {
     357               0 :                 if (i2+1 < nFIDCount2 && panFIDList2[i2+1] <= nVal1)
     358                 :                 {
     359               0 :                     panFIDList[nFIDCount ++] = nVal2;
     360               0 :                     i2 ++;
     361                 :                 }
     362                 :                 else
     363                 :                 {
     364               0 :                     panFIDList[nFIDCount ++] = nVal2;
     365               0 :                     panFIDList[nFIDCount ++] = nVal1;
     366               0 :                     i1 ++;
     367               0 :                     i2 ++;
     368                 :                 }
     369                 :             }
     370                 :         }
     371               2 :         else if (i1 < nFIDCount1)
     372                 :         {
     373               0 :             long nVal1 = panFIDList1[i1];
     374               0 :             panFIDList[nFIDCount ++] = nVal1;
     375               0 :             i1 ++;
     376                 :         }
     377               2 :         else if (i2 < nFIDCount2)
     378                 :         {
     379               2 :             long nVal2 = panFIDList2[i2];
     380               2 :             panFIDList[nFIDCount ++] = nVal2;
     381               2 :             i2 ++;
     382                 :         }
     383                 :     }
     384                 : 
     385               1 :     panFIDList[nFIDCount] = OGRNullFID;
     386                 : 
     387               1 :     return panFIDList;
     388                 : }
     389                 : 
     390                 : /* The input arrays must be sorted ! */
     391                 : static
     392               2 : long* OGRANDLongArray(long panFIDList1[], int nFIDCount1,
     393                 :                       long panFIDList2[], int nFIDCount2, int& nFIDCount)
     394                 : {
     395               2 :     int nMaxCount = MAX(nFIDCount1, nFIDCount2);
     396               2 :     long* panFIDList = (long*) CPLMalloc((nMaxCount+1) * sizeof(long));
     397               2 :     nFIDCount = 0;
     398                 : 
     399               2 :     int i1 = 0, i2 =0;
     400               8 :     for(;i1<nFIDCount1 && i2<nFIDCount2;)
     401                 :     {
     402               4 :         long nVal1 = panFIDList1[i1];
     403               4 :         long nVal2 = panFIDList2[i2];
     404               4 :         if (nVal1 < nVal2)
     405                 :         {
     406               3 :             if (i1+1 < nFIDCount1 && panFIDList1[i1+1] <= nVal2)
     407                 :             {
     408               1 :                 i1 ++;
     409                 :             }
     410                 :             else
     411                 :             {
     412               1 :                 i1 ++;
     413               1 :                 i2 ++;
     414                 :             }
     415                 :         }
     416               2 :         else if (nVal1 == nVal2)
     417                 :         {
     418               2 :             panFIDList[nFIDCount ++] = nVal1;
     419               2 :             i1 ++;
     420               2 :             i2 ++;
     421                 :         }
     422                 :         else
     423                 :         {
     424               0 :             if (i2+1 < nFIDCount2 && panFIDList2[i2+1] <= nVal1)
     425                 :             {
     426               0 :                 i2 ++;
     427                 :             }
     428                 :             else
     429                 :             {
     430               0 :                 i1 ++;
     431               0 :                 i2 ++;
     432                 :             }
     433                 :         }
     434                 :     }
     435                 : 
     436               2 :     panFIDList[nFIDCount] = OGRNullFID;
     437                 : 
     438               2 :     return panFIDList;
     439                 : }
     440                 : 
     441             514 : long *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
     442                 :                                                OGRLayer *poLayer,
     443                 :                                                int& nFIDCount )
     444                 : {
     445                 :     OGRAttrIndex *poIndex;
     446                 : 
     447                 : /* -------------------------------------------------------------------- */
     448                 : /*      Does the expression meet our requirements?                      */
     449                 : /* -------------------------------------------------------------------- */
     450             514 :     if( psExpr == NULL ||
     451                 :         psExpr->eNodeType != SNT_OPERATION )
     452               0 :         return NULL;
     453                 : 
     454             514 :     if ((psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
     455                 :          psExpr->nSubExprCount == 2)
     456                 :     {
     457             111 :         int nFIDCount1 = 0, nFIDCount2 = 0;
     458             111 :         long* panFIDList1 = EvaluateAgainstIndices( psExpr->papoSubExpr[0], poLayer, nFIDCount1 );
     459                 :         long* panFIDList2 = panFIDList1 == NULL ? NULL :
     460             111 :                             EvaluateAgainstIndices( psExpr->papoSubExpr[1], poLayer, nFIDCount2 );
     461             111 :         long* panFIDList = NULL;
     462             111 :         if (panFIDList1 != NULL && panFIDList2 != NULL)
     463                 :         {
     464               3 :             if (psExpr->nOperation == SWQ_OR )
     465                 :                 panFIDList = OGRORLongArray(panFIDList1, nFIDCount1,
     466               1 :                                             panFIDList2, nFIDCount2, nFIDCount);
     467               2 :             else if (psExpr->nOperation == SWQ_AND )
     468                 :                 panFIDList = OGRANDLongArray(panFIDList1, nFIDCount1,
     469               2 :                                             panFIDList2, nFIDCount2, nFIDCount);
     470                 : 
     471                 :         }
     472             111 :         CPLFree(panFIDList1);
     473             111 :         CPLFree(panFIDList2);
     474             111 :         return panFIDList;
     475                 :     }
     476                 : 
     477             403 :     if( !(psExpr->nOperation == SWQ_EQ || psExpr->nOperation == SWQ_IN)
     478                 :         || psExpr->nSubExprCount < 2 )
     479              39 :         return NULL;
     480                 : 
     481             364 :     swq_expr_node *poColumn = psExpr->papoSubExpr[0];
     482             364 :     swq_expr_node *poValue = psExpr->papoSubExpr[1];
     483                 :     
     484             364 :     if( poColumn->eNodeType != SNT_COLUMN
     485                 :         || poValue->eNodeType != SNT_CONSTANT )
     486              33 :         return NULL;
     487                 : 
     488             331 :     poIndex = poLayer->GetIndex()->GetFieldIndex( poColumn->field_index );
     489             331 :     if( poIndex == NULL )
     490             301 :         return NULL;
     491                 : 
     492                 : /* -------------------------------------------------------------------- */
     493                 : /*      OK, we have an index, now we need to query it.                  */
     494                 : /* -------------------------------------------------------------------- */
     495                 :     OGRField sValue;
     496                 :     OGRFieldDefn *poFieldDefn;
     497                 : 
     498              30 :     poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(poColumn->field_index);
     499                 : 
     500                 : /* -------------------------------------------------------------------- */
     501                 : /*      Handle the case of an IN operation.                             */
     502                 : /* -------------------------------------------------------------------- */
     503              30 :     if (psExpr->nOperation == SWQ_IN)
     504                 :     {
     505                 :         int nLength;
     506              10 :         long *panFIDs = NULL;
     507                 :         int iIN;
     508                 : 
     509              20 :         for( iIN = 1; iIN < psExpr->nSubExprCount; iIN++ )
     510                 :         {
     511              10 :             switch( poFieldDefn->GetType() )
     512                 :             {
     513                 :               case OFTInteger:
     514               5 :                 if (psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT)
     515               3 :                     sValue.Integer = (int) psExpr->papoSubExpr[iIN]->float_value;
     516                 :                 else
     517               2 :                     sValue.Integer = psExpr->papoSubExpr[iIN]->int_value;
     518               5 :                 break;
     519                 : 
     520                 :               case OFTReal:
     521               5 :                 sValue.Real = psExpr->papoSubExpr[iIN]->float_value;
     522               5 :                 break;
     523                 : 
     524                 :               case OFTString:
     525               0 :                 sValue.String = psExpr->papoSubExpr[iIN]->string_value;
     526               0 :                 break;
     527                 : 
     528                 :               default:
     529               0 :                 CPLAssert( FALSE );
     530               0 :                 return NULL;
     531                 :             }
     532                 : 
     533              10 :             panFIDs = poIndex->GetAllMatches( &sValue, panFIDs, &nFIDCount, &nLength );
     534                 :         }
     535                 : 
     536              10 :         if (nFIDCount > 1)
     537                 :         {
     538                 :             /* the returned FIDs are expected to be in sorted order */
     539               0 :             qsort(panFIDs, nFIDCount, sizeof(long), CompareLong);
     540                 :         }
     541              10 :         return panFIDs;
     542                 :     }
     543                 : 
     544                 : /* -------------------------------------------------------------------- */
     545                 : /*      Handle equality test.                                           */
     546                 : /* -------------------------------------------------------------------- */
     547              20 :     switch( poFieldDefn->GetType() )
     548                 :     {
     549                 :       case OFTInteger:
     550              14 :         if (poValue->field_type == SWQ_FLOAT)
     551               1 :             sValue.Integer = (int) poValue->float_value;
     552                 :         else
     553              13 :             sValue.Integer = poValue->int_value;
     554              14 :         break;
     555                 :         
     556                 :       case OFTReal:
     557               2 :         sValue.Real = poValue->float_value;
     558               2 :         break;
     559                 :         
     560                 :       case OFTString:
     561               4 :         sValue.String = poValue->string_value;
     562               4 :         break;
     563                 : 
     564                 :       default:
     565               0 :         CPLAssert( FALSE );
     566               0 :         return NULL;
     567                 :     }
     568                 : 
     569              20 :     int nLength = 0;
     570              20 :     long *panFIDs = poIndex->GetAllMatches( &sValue, NULL, &nFIDCount, &nLength );
     571              20 :     if (nFIDCount > 1)
     572                 :     {
     573                 :         /* the returned FIDs are expected to be in sorted order */
     574               6 :         qsort(panFIDs, nFIDCount, sizeof(long), CompareLong);
     575                 :     }
     576              20 :     return panFIDs;
     577                 : }
     578                 : 
     579                 : /************************************************************************/
     580                 : /*                         OGRFieldCollector()                          */
     581                 : /*                                                                      */
     582                 : /*      Helper function for recursing through tree to satisfy           */
     583                 : /*      GetUsedFields().                                                */
     584                 : /************************************************************************/
     585                 : 
     586              50 : char **OGRFeatureQuery::FieldCollector( void *pBareOp, 
     587                 :                                         char **papszList )
     588                 : 
     589                 : {
     590              50 :     swq_expr_node *op = (swq_expr_node *) pBareOp;
     591                 : 
     592                 : /* -------------------------------------------------------------------- */
     593                 : /*      References to tables other than the primarily are currently     */
     594                 : /*      unsupported. Error out.                                         */
     595                 : /* -------------------------------------------------------------------- */
     596              50 :     if( op->eNodeType == SNT_COLUMN )
     597                 :     {
     598              14 :         if( op->table_index != 0 )
     599                 :         {
     600               0 :             CSLDestroy( papszList );
     601               0 :             return NULL;
     602                 :         }
     603                 : 
     604                 : /* -------------------------------------------------------------------- */
     605                 : /*      Add the field name into our list if it is not already there.    */
     606                 : /* -------------------------------------------------------------------- */
     607                 :         const char *pszFieldName;
     608                 : 
     609              14 :         if( op->field_index >= poTargetDefn->GetFieldCount()
     610                 :             && op->field_index < poTargetDefn->GetFieldCount() + SPECIAL_FIELD_COUNT)
     611               3 :             pszFieldName = SpecialFieldNames[op->field_index - poTargetDefn->GetFieldCount()];
     612              11 :         else if( op->field_index >= 0
     613                 :                  && op->field_index < poTargetDefn->GetFieldCount() )
     614                 :             pszFieldName = 
     615              11 :                 poTargetDefn->GetFieldDefn(op->field_index)->GetNameRef();
     616                 :         else
     617                 :         {
     618               0 :             CSLDestroy( papszList );
     619               0 :             return NULL;
     620                 :         }
     621                 :         
     622              14 :         if( CSLFindString( papszList, pszFieldName ) == -1 )
     623              13 :             papszList = CSLAddString( papszList, pszFieldName );
     624                 :     }
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*      Add in fields from subexpressions.                              */
     628                 : /* -------------------------------------------------------------------- */
     629              50 :     if( op->eNodeType == SNT_OPERATION )
     630                 :     {
     631              58 :         for( int iSubExpr = 0; iSubExpr < op->nSubExprCount; iSubExpr++ )
     632                 :         {
     633              38 :             papszList = FieldCollector( op->papoSubExpr[iSubExpr], papszList );
     634                 :         }
     635                 :     }
     636                 : 
     637              50 :     return papszList;
     638                 : }
     639                 : 
     640                 : /************************************************************************/
     641                 : /*                           GetUsedFields()                            */
     642                 : /************************************************************************/
     643                 : 
     644                 : /**
     645                 :  * Returns lists of fields in expression.
     646                 :  *
     647                 :  * All attribute fields are used in the expression of this feature
     648                 :  * query are returned as a StringList of field names.  This function would
     649                 :  * primarily be used within drivers to recognise special case conditions
     650                 :  * depending only on attribute fields that can be very efficiently 
     651                 :  * fetched. 
     652                 :  *
     653                 :  * NOTE: If any fields in the expression are from tables other than the
     654                 :  * primary table then NULL is returned indicating an error.  In succesful
     655                 :  * use, no non-empty expression should return an empty list.
     656                 :  *
     657                 :  * @return list of field names.  Free list with CSLDestroy() when no longer
     658                 :  * required.
     659                 :  */
     660                 : 
     661              12 : char **OGRFeatureQuery::GetUsedFields( )
     662                 : 
     663                 : {
     664              12 :     if( pSWQExpr == NULL )
     665               0 :         return NULL;
     666                 : 
     667                 :     
     668              12 :     return FieldCollector( pSWQExpr, NULL );
     669                 : }
     670                 : 
     671                 : 
     672                 : 

Generated by: LCOV version 1.7