?? ogr_gensql.cpp
字號:
return NULL;
if( nFID < 0 || nFID >= psSummary->count )
return NULL;
poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
poSummaryFeature->SetFID( nFID );
return poSummaryFeature->Clone();
}
/* -------------------------------------------------------------------- */
/* Are we running in sorted mode? If so, run the fid through */
/* the index. */
/* -------------------------------------------------------------------- */
if( panFIDIndex != NULL )
{
if( nFID < 0 || nFID >= nIndexSize )
return NULL;
else
nFID = panFIDIndex[nFID];
}
/* -------------------------------------------------------------------- */
/* Handle request for random record. */
/* -------------------------------------------------------------------- */
OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
OGRFeature *poResult;
if( poSrcFeature == NULL )
return NULL;
poResult = TranslateFeature( poSrcFeature );
poResult->SetFID( nFID );
delete poSrcFeature;
return poResult;
}
/************************************************************************/
/* GetSpatialFilter() */
/************************************************************************/
OGRGeometry *OGRGenSQLResultsLayer::GetSpatialFilter()
{
return NULL;
}
/************************************************************************/
/* GetLayerDefn() */
/************************************************************************/
OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
{
return poDefn;
}
/************************************************************************/
/* CreateOrderByIndex() */
/* */
/* This method is responsible for creating an index providing */
/* ordered access to the features according to the supplied */
/* ORDER BY clauses. */
/* */
/* This is accomplished by making one pass through all the */
/* eligible source features, and capturing the order by fields */
/* of all records in memory. A quick sort is then applied to */
/* this in memory copy of the order-by fields to create the */
/* required index. */
/* */
/* Keeping all the key values in memory will *not* scale up to */
/* very large input datasets. */
/************************************************************************/
void OGRGenSQLResultsLayer::CreateOrderByIndex()
{
swq_select *psSelectInfo = (swq_select *) pSelectInfo;
OGRField *pasIndexFields;
int i, nOrderItems = psSelectInfo->order_specs;
long *panFIDList;
if( nOrderItems == 0 )
return;
ResetReading();
/* -------------------------------------------------------------------- */
/* Allocate set of key values, and the output index. */
/* -------------------------------------------------------------------- */
nIndexSize = poSrcLayer->GetFeatureCount();
pasIndexFields = (OGRField *)
CPLCalloc(sizeof(OGRField), nOrderItems * nIndexSize);
panFIDIndex = (long *) CPLCalloc(sizeof(long),nIndexSize);
panFIDList = (long *) CPLCalloc(sizeof(long),nIndexSize);
for( i = 0; i < nIndexSize; i++ )
panFIDIndex[i] = i;
/* -------------------------------------------------------------------- */
/* Read in all the key values. */
/* -------------------------------------------------------------------- */
OGRFeature *poSrcFeat;
int iFeature = 0;
while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
{
int iKey;
for( iKey = 0; iKey < nOrderItems; iKey++ )
{
swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
OGRFieldDefn *poFDefn;
OGRField *psSrcField, *psDstField;
psDstField = pasIndexFields + iFeature * nOrderItems + iKey;
if ( psKeyDef->field_index >= iFIDFieldIndex)
{
if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
{
switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
{
case SWQ_INTEGER:
psDstField->Integer = poSrcFeat->GetFieldAsInteger(psKeyDef->field_index);
break;
default:
psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
break;
}
}
continue;
}
poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
psKeyDef->field_index );
psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
if( poFDefn->GetType() == OFTInteger
|| poFDefn->GetType() == OFTReal )
memcpy( psDstField, psSrcField, sizeof(OGRField) );
else if( poFDefn->GetType() == OFTString )
{
if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
psDstField->String = CPLStrdup( psSrcField->String );
else
memcpy( psDstField, psSrcField, sizeof(OGRField) );
}
}
panFIDList[iFeature] = poSrcFeat->GetFID();
delete poSrcFeat;
iFeature++;
}
CPLAssert( nIndexSize == iFeature );
/* -------------------------------------------------------------------- */
/* Quick sort the records. */
/* -------------------------------------------------------------------- */
SortIndexSection( pasIndexFields, 0, nIndexSize );
/* -------------------------------------------------------------------- */
/* Rework the FID map to map to real FIDs. */
/* -------------------------------------------------------------------- */
for( i = 0; i < nIndexSize; i++ )
panFIDIndex[i] = panFIDList[panFIDIndex[i]];
CPLFree( panFIDList );
/* -------------------------------------------------------------------- */
/* Free the key field values. */
/* -------------------------------------------------------------------- */
for( int iKey = 0; iKey < nOrderItems; iKey++ )
{
swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
OGRFieldDefn *poFDefn;
if ( psKeyDef->field_index >= iFIDFieldIndex &&
psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
{
/* warning: only special fields of type string should be deallocated */
if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
{
for( i = 0; i < nIndexSize; i++ )
{
OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
CPLFree( psField->String );
}
}
continue;
}
poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
psKeyDef->field_index );
if( poFDefn->GetType() == OFTString )
{
for( i = 0; i < nIndexSize; i++ )
{
OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
if( psField->Set.nMarker1 != OGRUnsetMarker
|| psField->Set.nMarker2 != OGRUnsetMarker )
CPLFree( psField->String );
}
}
}
CPLFree( pasIndexFields );
}
/************************************************************************/
/* SortIndexSection() */
/* */
/* Sort the records in a section of the index. */
/************************************************************************/
void OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
int nStart, int nEntries )
{
if( nEntries < 2 )
return;
swq_select *psSelectInfo = (swq_select *) pSelectInfo;
int nOrderItems = psSelectInfo->order_specs;
int nFirstGroup = nEntries / 2;
int nFirstStart = nStart;
int nSecondGroup = nEntries - nFirstGroup;
int nSecondStart = nStart + nFirstGroup;
int iMerge = 0;
long *panMerged;
SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup );
SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup );
panMerged = (long *) CPLMalloc( sizeof(long) * nEntries );
while( iMerge < nEntries )
{
int nResult;
if( nFirstGroup == 0 )
nResult = -1;
else if( nSecondGroup == 0 )
nResult = 1;
else
nResult = Compare( pasIndexFields
+ panFIDIndex[nFirstStart] * nOrderItems,
pasIndexFields
+ panFIDIndex[nSecondStart] * nOrderItems );
if( nResult < 0 )
{
panMerged[iMerge++] = panFIDIndex[nSecondStart++];
nSecondGroup--;
}
else
{
panMerged[iMerge++] = panFIDIndex[nFirstStart++];
nFirstGroup--;
}
}
/* Copy the merge list back into the main index */
memcpy( panFIDIndex + nStart, panMerged, sizeof(long) * nEntries );
CPLFree( panMerged );
}
/************************************************************************/
/* Compare() */
/************************************************************************/
int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
OGRField *pasSecondTuple )
{
swq_select *psSelectInfo = (swq_select *) pSelectInfo;
int nResult = 0, iKey;
for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
{
swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
OGRFieldDefn *poFDefn;
if( psKeyDef->field_index >= iFIDFieldIndex )
poFDefn = NULL;
else
poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
psKeyDef->field_index );
if( (pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker
&& pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker)
|| (pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
&& pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker) )
nResult = 0;
else if ( poFDefn == NULL )
{
switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
{
case SWQ_INTEGER:
if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
nResult = -1;
else if( pasFirstTuple[iKey].Integer > pasSecondTuple[iKey].Integer )
nResult = 1;
break;
case SWQ_STRING:
nResult = strcmp(pasFirstTuple[iKey].String,
pasSecondTuple[iKey].String);
break;
default:
CPLAssert( FALSE );
nResult = 0;
}
}
else if( poFDefn->GetType() == OFTInteger )
{
if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
nResult = -1;
else if( pasFirstTuple[iKey].Integer
> pasSecondTuple[iKey].Integer )
nResult = 1;
}
else if( poFDefn->GetType() == OFTString )
nResult = strcmp(pasFirstTuple[iKey].String,
pasSecondTuple[iKey].String);
else if( poFDefn->GetType() == OFTReal )
{
if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
nResult = -1;
else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
nResult = 1;
}
if( psKeyDef->ascending_flag )
nResult *= -1;
}
return nResult;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -