long* OGRFeatureQuery::EvaluateAgainstIndices(OGRLayer *poLayer,
                                              OGRErr *peErr)

{
    swq_expr_node *psExpr = (swq_expr_node*) pSWQExpr;
    OGRAttrIndex  *poIndex;

    if (peErr != NULL)
        *peErr = OGRERR_NONE;

/* -------------------------------------------------------------------- */
/*      Does the expression meet our requirements?  Do we have an       */
/*      index on the targetted field?                                   */
/* -------------------------------------------------------------------- */
    if (psExpr == NULL
        || psExpr->eNodeType != SNT_OPERATION
        || !(psExpr->nOperation == SWQ_EQ || psExpr->nOperation == SWQ_IN)
        || poLayer->GetIndex() == NULL
        || psExpr->nSubExprCount < 2)
        return NULL;

    swq_expr_node *poColumn = psExpr->papoSubExpr[0];
    swq_expr_node *poValue  = psExpr->papoSubExpr[1];

    if (poColumn->eNodeType != SNT_COLUMN
        || poValue->eNodeType != SNT_CONSTANT)
        return NULL;

    poIndex = poLayer->GetIndex()->GetFieldIndex(poColumn->field_index);
    if (poIndex == NULL)
        return NULL;

/* -------------------------------------------------------------------- */
/*      OK, we have an index, now we need to query it.                  */
/* -------------------------------------------------------------------- */
    OGRField     sValue;
    OGRFieldDefn *poFieldDefn;

    poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(poColumn->field_index);

/* -------------------------------------------------------------------- */
/*      Handle the case of an IN operation.                             */
/* -------------------------------------------------------------------- */
    if (psExpr->nOperation == SWQ_IN)
    {
        int  nFIDCount = 0, nLength;
        long *panFIDs  = NULL;
        int  iIN;

        for (iIN = 1; iIN < psExpr->nSubExprCount; iIN++)
        {
            switch (poFieldDefn->GetType())
            {
            case OFTInteger:
                sValue.Integer = psExpr->papoSubExpr[iIN]->int_value;
                break;

            case OFTReal:
                sValue.Real = psExpr->papoSubExpr[iIN]->float_value;
                break;

            case OFTString:
                sValue.String = psExpr->papoSubExpr[iIN]->string_value;
                break;

            default:
                CPLAssert(FALSE);
                return NULL;
            }

            panFIDs = poIndex->GetAllMatches(&sValue, panFIDs, &nFIDCount, &nLength);
        }

        if (nFIDCount > 1)
        {
            /* the returned FIDs are expected to be in sorted order */
            qsort(panFIDs, nFIDCount, sizeof(long), CompareLong);
        }

        return panFIDs;
    }

/* -------------------------------------------------------------------- */
/*      Handle equality test.                                           */
/* -------------------------------------------------------------------- */
    switch (poFieldDefn->GetType())
    {
    case OFTInteger:
        sValue.Integer = poValue->int_value;
        break;

    case OFTReal:
        sValue.Real = poValue->float_value;
        break;

    case OFTString:
        sValue.String = poValue->string_value;
        break;

    default:
        CPLAssert(FALSE);
        return NULL;
    }

    int  nFIDCount = 0, nLength = 0;
    long *panFIDs  = poIndex->GetAllMatches(&sValue, NULL, &nFIDCount, &nLength);
    if (nFIDCount > 1)
    {
        /* the returned FIDs are expected to be in sorted order */
        qsort(panFIDs, nFIDCount, sizeof(long), CompareLong);
    }

    return panFIDs;
}
Exemplo n.º 2
0
long *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
                                               OGRLayer *poLayer,
                                               int& nFIDCount )
{
    OGRAttrIndex *poIndex;

/* -------------------------------------------------------------------- */
/*      Does the expression meet our requirements?                      */
/* -------------------------------------------------------------------- */
    if( psExpr == NULL ||
        psExpr->eNodeType != SNT_OPERATION )
        return NULL;

    if ((psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
         psExpr->nSubExprCount == 2)
    {
        int nFIDCount1 = 0, nFIDCount2 = 0;
        long* panFIDList1 = EvaluateAgainstIndices( psExpr->papoSubExpr[0], poLayer, nFIDCount1 );
        long* panFIDList2 = panFIDList1 == NULL ? NULL :
                            EvaluateAgainstIndices( psExpr->papoSubExpr[1], poLayer, nFIDCount2 );
        long* panFIDList = NULL;
        if (panFIDList1 != NULL && panFIDList2 != NULL)
        {
            if (psExpr->nOperation == SWQ_OR )
                panFIDList = OGRORLongArray(panFIDList1, nFIDCount1,
                                            panFIDList2, nFIDCount2, nFIDCount);
            else if (psExpr->nOperation == SWQ_AND )
                panFIDList = OGRANDLongArray(panFIDList1, nFIDCount1,
                                            panFIDList2, nFIDCount2, nFIDCount);

        }
        CPLFree(panFIDList1);
        CPLFree(panFIDList2);
        return panFIDList;
    }

    if( !(psExpr->nOperation == SWQ_EQ || psExpr->nOperation == SWQ_IN)
        || psExpr->nSubExprCount < 2 )
        return NULL;

    swq_expr_node *poColumn = psExpr->papoSubExpr[0];
    swq_expr_node *poValue = psExpr->papoSubExpr[1];
    
    if( poColumn->eNodeType != SNT_COLUMN
        || poValue->eNodeType != SNT_CONSTANT )
        return NULL;

    poIndex = poLayer->GetIndex()->GetFieldIndex( poColumn->field_index );
    if( poIndex == NULL )
        return NULL;

/* -------------------------------------------------------------------- */
/*      OK, we have an index, now we need to query it.                  */
/* -------------------------------------------------------------------- */
    OGRField sValue;
    OGRFieldDefn *poFieldDefn;

    poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(poColumn->field_index);

/* -------------------------------------------------------------------- */
/*      Handle the case of an IN operation.                             */
/* -------------------------------------------------------------------- */
    if (psExpr->nOperation == SWQ_IN)
    {
        int nLength;
        long *panFIDs = NULL;
        int iIN;

        for( iIN = 1; iIN < psExpr->nSubExprCount; iIN++ )
        {
            switch( poFieldDefn->GetType() )
            {
              case OFTInteger:
                if (psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT)
                    sValue.Integer = (int) psExpr->papoSubExpr[iIN]->float_value;
                else
                    sValue.Integer = psExpr->papoSubExpr[iIN]->int_value;
                break;

              case OFTReal:
                sValue.Real = psExpr->papoSubExpr[iIN]->float_value;
                break;

              case OFTString:
                sValue.String = psExpr->papoSubExpr[iIN]->string_value;
                break;

              default:
                CPLAssert( FALSE );
                return NULL;
            }

            panFIDs = poIndex->GetAllMatches( &sValue, panFIDs, &nFIDCount, &nLength );
        }

        if (nFIDCount > 1)
        {
            /* the returned FIDs are expected to be in sorted order */
            qsort(panFIDs, nFIDCount, sizeof(long), CompareLong);
        }
        return panFIDs;
    }

/* -------------------------------------------------------------------- */
/*      Handle equality test.                                           */
/* -------------------------------------------------------------------- */
    switch( poFieldDefn->GetType() )
    {
      case OFTInteger:
        if (poValue->field_type == SWQ_FLOAT)
            sValue.Integer = (int) poValue->float_value;
        else
            sValue.Integer = poValue->int_value;
        break;
        
      case OFTReal:
        sValue.Real = poValue->float_value;
        break;
        
      case OFTString:
        sValue.String = poValue->string_value;
        break;

      default:
        CPLAssert( FALSE );
        return NULL;
    }

    int nLength = 0;
    long *panFIDs = poIndex->GetAllMatches( &sValue, NULL, &nFIDCount, &nLength );
    if (nFIDCount > 1)
    {
        /* the returned FIDs are expected to be in sorted order */
        qsort(panFIDs, nFIDCount, sizeof(long), CompareLong);
    }
    return panFIDs;
}