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; }
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; }