📄 ogr_gensql.cpp
字号:
/****************************************************************************** * $Id: ogr_gensql.cpp,v 1.14 2005/02/02 20:00:29 fwarmerdam Exp $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements OGRGenSQLResultsLayer. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log: ogr_gensql.cpp,v $ * Revision 1.14 2005/02/02 20:00:29 fwarmerdam * added SetNextByIndex support * * Revision 1.13 2003/03/20 19:13:21 warmerda * Added ClearFilters() method to cleanup spatial or attribute filters on the * target layer, and any joined layers. Used in destructor and after all * features have been read from source layer. * * Revision 1.12 2003/03/20 17:43:43 warmerda * fixed bug when secondary schema larger than primary schema * * Revision 1.11 2003/03/19 20:31:18 warmerda * add support for tables from external datasources * * Revision 1.10 2003/03/05 05:10:17 warmerda * implement join support * * Revision 1.9 2002/10/25 15:00:41 warmerda * Fixed int/long type mismatch. * * Revision 1.8 2002/08/12 16:40:56 dron * stricmp() function replaced by EQUALN() macro * * Revision 1.7 2002/08/12 15:06:01 warmerda * fix DISTINCT not working with FID (from Bruce) * * * Revision 1.6 2002/04/29 19:35:50 warmerda * fixes for selecting FID * * Revision 1.5 2002/04/29 18:13:36 warmerda * Fix serious bug with datasets with sparse FID sets. * * Revision 1.4 2002/04/25 21:03:07 warmerda * avoid strcasecmp * * Revision 1.3 2002/04/25 16:07:55 warmerda * fleshed out DISTINCT support * * Revision 1.2 2002/04/25 03:42:04 warmerda * fixed spatial filter support on SQL results * * Revision 1.1 2002/04/25 02:24:37 warmerda * New * */#include "ogr_p.h"#include "ogr_gensql.h"#include "cpl_string.h"CPL_C_START#include "swq.h"CPL_C_ENDCPL_CVSID("$Id: ogr_gensql.cpp,v 1.14 2005/02/02 20:00:29 fwarmerdam Exp $");/************************************************************************//* OGRGenSQLResultsLayer() *//************************************************************************/OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( OGRDataSource *poSrcDS, void *pSelectInfo, OGRGeometry *poSpatFilter ){ swq_select *psSelectInfo = (swq_select *) pSelectInfo; this->poSrcDS = poSrcDS; this->pSelectInfo = pSelectInfo; poDefn = NULL; poSummaryFeature = NULL; panFIDIndex = NULL; nIndexSize = 0; nNextIndexFID = 0; nExtraDSCount = 0; papoExtraDS = NULL; if( poSpatFilter != NULL ) this->poSpatialFilter = poSpatFilter->clone(); else this->poSpatialFilter = NULL;/* -------------------------------------------------------------------- *//* Identify all the layers involved in the SELECT. *//* -------------------------------------------------------------------- */ int iTable; papoTableLayers = (OGRLayer **) CPLCalloc( sizeof(OGRLayer *), psSelectInfo->table_count ); for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ ) { swq_table_def *psTableDef = psSelectInfo->table_defs + iTable; OGRDataSource *poTableDS = poSrcDS; if( psTableDef->data_source != NULL ) { OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar(); poTableDS = poReg->OpenShared( psTableDef->data_source, FALSE, NULL ); if( poTableDS == NULL ) { if( strlen(CPLGetLastErrorMsg()) == 0 ) CPLError( CE_Failure, CPLE_AppDefined, "Unable to open secondary datasource\n" "`%s' required by JOIN.", psTableDef->data_source ); return; } papoExtraDS = (OGRDataSource **) CPLRealloc( papoExtraDS, sizeof(void*) * ++nExtraDSCount ); papoExtraDS[nExtraDSCount-1] = poTableDS; } papoTableLayers[iTable] = poTableDS->GetLayerByName( psTableDef->table_name ); CPLAssert( papoTableLayers[iTable] != NULL ); if( papoTableLayers[iTable] == NULL ) return; } poSrcLayer = papoTableLayers[0];/* -------------------------------------------------------------------- *//* Prepare a feature definition based on the query. *//* -------------------------------------------------------------------- */ OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn(); poDefn = new OGRFeatureDefn( psSelectInfo->table_defs[0].table_alias ); for( int iField = 0; iField < psSelectInfo->result_columns; iField++ ) { swq_col_def *psColDef = psSelectInfo->column_defs + iField; OGRFieldDefn oFDefn( psColDef->field_name, OFTInteger ); OGRFieldDefn *poSrcFDefn = NULL; OGRFeatureDefn *poLayerDefn = papoTableLayers[psColDef->table_index]->GetLayerDefn(); if( psColDef->field_index > -1 && psColDef->field_index < poLayerDefn->GetFieldCount() ) poSrcFDefn = poLayerDefn->GetFieldDefn(psColDef->field_index); if( psColDef->col_func_name != NULL ) { oFDefn.SetName( CPLSPrintf( "%s_%s",psColDef->col_func_name, psColDef->field_name) ); } if( psColDef->col_func == SWQCF_COUNT ) oFDefn.SetType( OFTInteger ); else if( poSrcFDefn != NULL ) { oFDefn.SetType( poSrcFDefn->GetType() ); oFDefn.SetWidth( poSrcFDefn->GetWidth() ); oFDefn.SetPrecision( poSrcFDefn->GetPrecision() ); } poDefn->AddFieldDefn( &oFDefn ); } poDefn->SetGeomType( poSrcLayer->GetLayerDefn()->GetGeomType() ); iFIDFieldIndex = poSrcDefn->GetFieldCount();/* -------------------------------------------------------------------- *//* If an ORDER BY is in effect, apply it now. *//* -------------------------------------------------------------------- */ if( psSelectInfo->order_specs > 0 && psSelectInfo->query_mode == SWQM_RECORDSET ) CreateOrderByIndex(); ResetReading();}/************************************************************************//* ~OGRGenSQLResultsLayer() *//************************************************************************/OGRGenSQLResultsLayer::~OGRGenSQLResultsLayer(){ if( m_nFeaturesRead > 0 && poDefn != NULL ) { CPLDebug( "GenSQL", "%d features read on layer '%s'.", (int) m_nFeaturesRead, poDefn->GetName() ); } ClearFilters();/* -------------------------------------------------------------------- *//* Free various datastructures. *//* -------------------------------------------------------------------- */ CPLFree( papoTableLayers ); papoTableLayers = NULL; if( panFIDIndex != NULL ) CPLFree( panFIDIndex ); if( poSummaryFeature ) delete poSummaryFeature; if( pSelectInfo != NULL ) swq_select_free( (swq_select *) pSelectInfo ); if( poDefn != NULL ) delete poDefn;/* -------------------------------------------------------------------- *//* Release any additional datasources being used in joins. *//* -------------------------------------------------------------------- */ OGRSFDriverRegistrar *poReg=OGRSFDriverRegistrar::GetRegistrar(); for( int iEDS = 0; iEDS < nExtraDSCount; iEDS++ ) poReg->ReleaseDataSource( papoExtraDS[iEDS] ); CPLFree( papoExtraDS );}/************************************************************************//* ClearFilters() *//* *//* Clear up all filters currently in place on the target layer, *//* and joined layers. We try not to leave them installed *//* except when actively fetching features. *//************************************************************************/void OGRGenSQLResultsLayer::ClearFilters(){/* -------------------------------------------------------------------- *//* Clear any filters installed on the target layer. *//* -------------------------------------------------------------------- */ if( poSrcLayer != NULL ) { poSrcLayer->SetAttributeFilter( "" ); poSrcLayer->SetSpatialFilter( NULL ); }/* -------------------------------------------------------------------- *//* Clear any attribute filter installed on the joined layers. *//* -------------------------------------------------------------------- */ swq_select *psSelectInfo = (swq_select *) pSelectInfo; int iJoin; if( psSelectInfo != NULL ) { for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ ) { swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin; OGRLayer *poJoinLayer = papoTableLayers[psJoinInfo->secondary_table]; poJoinLayer->SetAttributeFilter( "" ); } }}/************************************************************************//* ResetReading() *//************************************************************************/void OGRGenSQLResultsLayer::ResetReading() { swq_select *psSelectInfo = (swq_select *) pSelectInfo; if( psSelectInfo->query_mode == SWQM_RECORDSET ) { poSrcLayer->SetAttributeFilter( psSelectInfo->whole_where_clause ); poSrcLayer->SetSpatialFilter( poSpatialFilter ); poSrcLayer->ResetReading(); } nNextIndexFID = 0;}/************************************************************************//* SetNextByIndex() *//* *//* If we already have an FID list, we can easily resposition *//* ourselves in it. *//************************************************************************/OGRErr OGRGenSQLResultsLayer::SetNextByIndex( long nIndex ){ swq_select *psSelectInfo = (swq_select *) pSelectInfo; if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD || psSelectInfo->query_mode == SWQM_DISTINCT_LIST || panFIDIndex != NULL ) { nNextIndexFID = nIndex; return OGRERR_NONE; } else { return poSrcLayer->SetNextByIndex( nIndex ); }}/************************************************************************//* GetExtent() *//************************************************************************/OGRErr OGRGenSQLResultsLayer::GetExtent( OGREnvelope *psExtent, int bForce )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -