?? ogrocilayer.cpp
字號:
/****************************************************************************** * $Id: ogrocilayer.cpp 10646 2007-01-18 02:38:10Z warmerdam $ * * Project: Oracle Spatial Driver * Purpose: Implementation of the OGROCILayer class. This is layer semantics * shared between table accessors and ExecuteSQL() result * pseudo-layers. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com> * * 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. ****************************************************************************/#include "ogr_oci.h"#include "cpl_conv.h"CPL_CVSID("$Id: ogrocilayer.cpp 10646 2007-01-18 02:38:10Z warmerdam $");/************************************************************************//* OGROCILayer() *//************************************************************************/OGROCILayer::OGROCILayer(){ poDS = NULL; poStatement = NULL; pszQueryStatement = NULL; pszGeomName = NULL; iGeomColumn = -1; pszFIDName = NULL; iFIDColumn = -1; hLastGeom = NULL; hLastGeomInd = NULL; iNextShapeId = 0;}/************************************************************************//* ~OGROCILayer() *//************************************************************************/OGROCILayer::~OGROCILayer(){ if( m_nFeaturesRead > 0 && poFeatureDefn != NULL ) { CPLDebug( "OCI", "%d features read on layer '%s'.", (int) m_nFeaturesRead, poFeatureDefn->GetName() ); } ResetReading(); CPLFree( pszGeomName ); pszGeomName = NULL; CPLFree( pszFIDName ); pszFIDName = NULL; CPLFree( pszQueryStatement ); pszQueryStatement = NULL; if( poFeatureDefn != NULL ) poFeatureDefn->Release();}/************************************************************************//* ResetReading() *//************************************************************************/void OGROCILayer::ResetReading(){ if( poStatement != NULL ) delete poStatement; poStatement = NULL; iNextShapeId = 0;}/************************************************************************//* GetNextFeature() *//* *//* By default we implement the full spatial and attribute query *//* semantics manually here. The table query class will *//* override this method and implement these inline, but the *//* simple SELECT statement evaluator (OGROCISelectLayer) will *//* depend us this code implementing additional spatial or *//* attribute query semantics. *//************************************************************************/OGRFeature *OGROCILayer::GetNextFeature(){ for( ; TRUE; ) { OGRFeature *poFeature; poFeature = GetNextRawFeature(); if( poFeature == NULL ) return NULL; if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) return poFeature; delete poFeature; }}/************************************************************************//* GetNextRawFeature() *//************************************************************************/OGRFeature *OGROCILayer::GetNextRawFeature(){/* -------------------------------------------------------------------- *//* Do we need to establish an initial query? *//* -------------------------------------------------------------------- */ if( iNextShapeId == 0 && poStatement == NULL ) { if( !ExecuteQuery(pszQueryStatement) ) return NULL; }/* -------------------------------------------------------------------- *//* Have we run out of query results, such that we have no *//* statement left? *//* -------------------------------------------------------------------- */ if( poStatement == NULL ) return NULL;/* -------------------------------------------------------------------- *//* Are we in some sort of error condition? *//* -------------------------------------------------------------------- */ hLastGeom = NULL; char **papszResult = poStatement->SimpleFetchRow(); if( papszResult == NULL ) { iNextShapeId = MAX(1,iNextShapeId); delete poStatement; poStatement = NULL; return NULL; }/* -------------------------------------------------------------------- *//* Create a feature from the current result. *//* -------------------------------------------------------------------- */ int iField; OGRFeature *poFeature = new OGRFeature( poFeatureDefn ); poFeature->SetFID( iNextShapeId ); iNextShapeId++; m_nFeaturesRead++; if( iFIDColumn != -1 && papszResult[iFIDColumn] != NULL ) poFeature->SetFID( atoi(papszResult[iFIDColumn]) ); for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ ) { if( papszResult[iField] != NULL ) poFeature->SetField( iField, papszResult[iField] ); }/* -------------------------------------------------------------------- *//* Translate geometry if we have it. *//* -------------------------------------------------------------------- */ if( iGeomColumn != -1 ) { poFeature->SetGeometryDirectly( TranslateGeometry() ); OGROCISession *poSession = poDS->GetSession(); if( poFeature->GetGeometryRef() != NULL && hLastGeom != NULL ) poSession->Failed( OCIObjectFree(poSession->hEnv, poSession->hError, (dvoid *) hLastGeom, (ub2)OCI_OBJECTFREE_FORCE) ); hLastGeom = NULL; hLastGeomInd = NULL; } nResultOffset++; return poFeature;}/************************************************************************//* ExecuteQuery() *//* *//* This is invoke when the first request for a feature is *//* made. It executes the query, and binds columns as needed. *//* The OGROCIStatement is used for most of the work. *//************************************************************************/int OGROCILayer::ExecuteQuery( const char *pszReqQuery ){ OGROCISession *poSession = poDS->GetSession(); CPLAssert( pszReqQuery != NULL ); CPLAssert( poStatement == NULL );/* -------------------------------------------------------------------- *//* Execute the query. *//* -------------------------------------------------------------------- */ poStatement = new OGROCIStatement( poSession ); if( poStatement->Execute( pszReqQuery ) != CE_None ) { delete poStatement; poStatement = NULL; return FALSE; } nResultOffset = 0;/* -------------------------------------------------------------------- *//* Do additional work binding the geometry column. *//* -------------------------------------------------------------------- */ if( iGeomColumn != -1 ) { OCIDefine *hGDefine = NULL; if( poSession->Failed( OCIDefineByPos(poStatement->GetStatement(), &hGDefine, poSession->hError, (ub4) iGeomColumn+1, (dvoid *)0, (sb4)0, SQLT_NTY, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT), "OCIDefineByPos(geometry)") ) return FALSE; if( poSession->Failed( OCIDefineObject(hGDefine, poSession->hError, poSession->hGeometryTDO, (dvoid **) &hLastGeom, (ub4 *)0, (dvoid **) &hLastGeomInd, (ub4 *)0 ), "OCIDefineObject") ) return FALSE; } return TRUE;}/************************************************************************//* TranslateGeometry() *//************************************************************************/OGRGeometry *OGROCILayer::TranslateGeometry(){ OGROCISession *poSession = poDS->GetSession();/* -------------------------------------------------------------------- *//* Is the geometry NULL? *//* -------------------------------------------------------------------- */ if( hLastGeom == NULL || hLastGeomInd == NULL || hLastGeomInd->_atomic == OCI_IND_NULL ) return NULL;/* -------------------------------------------------------------------- *//* Get the size of the sdo_elem_info and sdo_ordinates arrays. *//* -------------------------------------------------------------------- */ int nElemCount, nOrdCount; if( poSession->Failed( OCICollSize( poSession->hEnv, poSession->hError, (OCIColl *)(hLastGeom->sdo_elem_info), &nElemCount), "OCICollSize(sdo_elem_info)" ) ) return NULL; if( poSession->Failed( OCICollSize( poSession->hEnv, poSession->hError, (OCIColl *)(hLastGeom->sdo_ordinates), &nOrdCount), "OCICollSize(sdo_ordinates)" ) ) return NULL;/* -------------------------------------------------------------------- *//* Get the GType. *//* -------------------------------------------------------------------- */ int nGType; if( poSession->Failed( OCINumberToInt(poSession->hError, &(hLastGeom->sdo_gtype), (uword)sizeof(int), OCI_NUMBER_SIGNED, (dvoid *)&nGType), "OCINumberToInt(GType)" ) ) return NULL;/* -------------------------------------------------------------------- *//* Handle point data directly from built-in point info. *//* -------------------------------------------------------------------- */ if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_POINT) && hLastGeomInd->sdo_point._atomic == OCI_IND_NOTNULL && hLastGeomInd->sdo_point.x == OCI_IND_NOTNULL && hLastGeomInd->sdo_point.y == OCI_IND_NOTNULL ) { double dfX, dfY, dfZ = 0.0; OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.x), (uword)sizeof(double), (dvoid *)&dfX); OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.y), (uword)sizeof(double), (dvoid *)&dfY); if( hLastGeomInd->sdo_point.z == OCI_IND_NOTNULL ) OCINumberToReal(poSession->hError, &(hLastGeom->sdo_point.z), (uword)sizeof(double), (dvoid *)&dfZ); return new OGRPoint( dfX, dfY, dfZ ); }/* -------------------------------------------------------------------- *//* Establish the dimension. *//* -------------------------------------------------------------------- */ int nDimension = MAX(2,(nGType / 1000));/* -------------------------------------------------------------------- *//* If this is a sort of container geometry, create the *//* container now. *//* -------------------------------------------------------------------- */ OGRGeometryCollection *poCollection = NULL; OGRPolygon *poPolygon = NULL; if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_POLYGON) ) poPolygon = new OGRPolygon(); else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_COLLECTION) ) poCollection = new OGRGeometryCollection(); else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_MULTIPOINT) ) poCollection = new OGRMultiPoint(); else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_MULTILINESTRING) ) poCollection = new OGRMultiLineString(); else if( ORA_GTYPE_MATCH(nGType,ORA_GTYPE_MULTIPOLYGON) ) poCollection = new OGRMultiPolygon();/* ==================================================================== *//* Loop over the component elements. *//* ==================================================================== */ ub4 nNextStartOrdinal = 1; for( int iElement = 0; iElement < nElemCount; iElement += 3 ) { boolean bExists; OCINumber *hNumber; ub4 nInterpretation, nEType; int nStartOrdinal = nNextStartOrdinal;/* -------------------------------------------------------------------- *//* Get the details about element from the elem_info array. *//* -------------------------------------------------------------------- */ OCICollGetElem(poSession->hEnv, poSession->hError, (OCIColl *)(hLastGeom->sdo_elem_info), (sb4)(iElement+1), (boolean *)&bExists, (dvoid **)&hNumber, NULL ); OCINumberToInt(poSession->hError, hNumber, (uword)sizeof(ub4), OCI_NUMBER_UNSIGNED, (dvoid *) &nEType );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -