int OGRSQLiteSelectLayer::TestCapability( const char * pszCap ) { if (EQUAL(pszCap,OLCFastSpatialFilter)) { if (osSQLCurrent != osSQLBase) return TRUE; size_t i = 0; OGRSQLiteLayer* poBaseLayer = GetBaseLayer(i); if (poBaseLayer == NULL) { CPLDebug("SQLITE", "Cannot find base layer"); return FALSE; } OGRPolygon oFakePoly; const char* pszWKT = "POLYGON((0 0,0 1,1 1,1 0,0 0))"; oFakePoly.importFromWkt((char**) &pszWKT); CPLString osSpatialWhere = poBaseLayer->GetSpatialWhere(&oFakePoly); return osSpatialWhere.size() != 0; } else return OGRSQLiteLayer::TestCapability( pszCap ); }
OGRwkbGeometryType OGRSQLiteViewLayer::GetGeomType() { if (poFeatureDefn) return poFeatureDefn->GetGeomType(); OGRSQLiteLayer* poUnderlyingLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(osUnderlyingTableName); if (poUnderlyingLayer) return poUnderlyingLayer->GetGeomType(); return wkbUnknown; }
OGRwkbGeometryType OGRSQLiteViewLayer::GetGeomType() { if (poFeatureDefn) return poFeatureDefn->GetGeomType(); OGRSQLiteLayer* poUnderlyingLayer = GetUnderlyingLayer(); if (poUnderlyingLayer) return poUnderlyingLayer->GetGeomType(); return wkbUnknown; }
CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn() { int rc; sqlite3 *hDB = poDS->GetDB(); sqlite3_stmt *hColStmt = NULL; const char *pszSQL; OGRSQLiteLayer* poUnderlyingLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(osUnderlyingTableName); if (poUnderlyingLayer == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find underlying layer %s for view %s", osUnderlyingTableName.c_str(), pszViewName); return CE_Failure; } if ( !poUnderlyingLayer->IsTableLayer() ) { CPLError(CE_Failure, CPLE_AppDefined, "Underlying layer %s for view %s is not a regular table", osUnderlyingTableName.c_str(), pszViewName); return CE_Failure; } const char* pszRealUnderlyingGeometryColumn = poUnderlyingLayer->GetGeometryColumn(); if ( pszRealUnderlyingGeometryColumn == NULL || !EQUAL(pszRealUnderlyingGeometryColumn, osUnderlyingGeometryColumn.c_str()) ) { CPLError(CE_Failure, CPLE_AppDefined, "Underlying layer %s for view %s has not expected geometry column name (%s instead of %s)", osUnderlyingTableName.c_str(), pszViewName, pszRealUnderlyingGeometryColumn ? pszRealUnderlyingGeometryColumn : "(null)", osUnderlyingGeometryColumn.c_str()); return CE_Failure; } poSRS = poUnderlyingLayer->GetSpatialRef(); if (poSRS) poSRS->Reference(); this->bHasSpatialIndex = poUnderlyingLayer->HasSpatialIndex(); /* -------------------------------------------------------------------- */ /* Get the column definitions for this table. */ /* -------------------------------------------------------------------- */ hColStmt = NULL; pszSQL = CPLSPrintf( "SELECT %s, * FROM '%s' LIMIT 1", pszFIDColumn, pszEscapedTableName ); rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to query table %s for column definitions : %s.", pszViewName, sqlite3_errmsg(hDB) ); return CE_Failure; } rc = sqlite3_step( hColStmt ); if ( rc != SQLITE_DONE && rc != SQLITE_ROW ) { CPLError( CE_Failure, CPLE_AppDefined, "In Initialize(): sqlite3_step(%s):\n %s", pszSQL, sqlite3_errmsg(hDB) ); sqlite3_finalize( hColStmt ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Collect the rest of the fields. */ /* -------------------------------------------------------------------- */ BuildFeatureDefn( pszViewName, hColStmt ); sqlite3_finalize( hColStmt ); /* -------------------------------------------------------------------- */ /* Set the geometry type if we know it. */ /* -------------------------------------------------------------------- */ poFeatureDefn->SetGeomType( poUnderlyingLayer->GetGeomType() ); return CE_None; }
OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn, CPLString osSQLIn, sqlite3_stmt *hStmtIn, int bUseStatementForGetNextFeature, int bEmptyLayer, int bAllowMultipleGeomFieldsIn ) { poBehaviour = new OGRSQLiteSelectLayerCommonBehaviour(poDSIn, this, osSQLIn, bEmptyLayer); poDS = poDSIn; this->bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn; std::set<CPLString> aosEmpty; BuildFeatureDefn( "SELECT", hStmtIn, aosEmpty, aosEmpty ); SetDescription( "SELECT" ); if( bUseStatementForGetNextFeature ) { hStmt = hStmtIn; bDoStep = FALSE; // Try to extract SRS from first geometry for( int iField = 0; !bEmptyLayer && iField < poFeatureDefn->GetGeomFieldCount(); iField ++) { OGRSQLiteGeomFieldDefn* poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(iField); if( wkbFlatten(poGeomFieldDefn->GetType()) != wkbUnknown ) continue; int nBytes; if( sqlite3_column_type( hStmt, poGeomFieldDefn->iCol ) == SQLITE_BLOB && (nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol )) > 39 ) { const GByte* pabyBlob = (const GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ); int eByteOrder = pabyBlob[1]; if( pabyBlob[0] == 0x00 && (eByteOrder == wkbNDR || eByteOrder == wkbXDR) && pabyBlob[38] == 0x7C ) { int nSRSId; memcpy(&nSRSId, pabyBlob + 2, 4); #ifdef CPL_LSB if( eByteOrder != wkbNDR) CPL_SWAP32PTR(&nSRSId); #else if( eByteOrder == wkbNDR) CPL_SWAP32PTR(&nSRSId); #endif CPLPushErrorHandler(CPLQuietErrorHandler); OGRSpatialReference* poSRS = poDS->FetchSRS( nSRSId ); CPLPopErrorHandler(); if( poSRS != NULL ) { poGeomFieldDefn->nSRSId = nSRSId; poGeomFieldDefn->SetSpatialRef(poSRS); } else CPLErrorReset(); } #ifdef SQLITE_HAS_COLUMN_METADATA else if( iField == 0 ) { const char* pszTableName = sqlite3_column_table_name( hStmt, poGeomFieldDefn->iCol ); if( pszTableName != NULL ) { OGRSQLiteLayer* poLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(pszTableName); if( poLayer != NULL && poLayer->GetLayerDefn()->GetGeomFieldCount() > 0) { OGRSQLiteGeomFieldDefn* poSrcGFldDefn = poLayer->myGetLayerDefn()->myGetGeomFieldDefn(0); poGeomFieldDefn->nSRSId = poSrcGFldDefn->nSRSId; poGeomFieldDefn->SetSpatialRef(poSrcGFldDefn->GetSpatialRef()); } } } #endif } } } else sqlite3_finalize( hStmtIn ); }
int OGRSQLiteSelectLayer::RebuildSQLWithSpatialClause() { osSQLCurrent = osSQLBase; if (m_poFilterGeom == NULL) { return TRUE; } size_t i = 0; OGRSQLiteLayer* poBaseLayer = GetBaseLayer(i); if (poBaseLayer == NULL) { CPLDebug("SQLITE", "Cannot find base layer"); return FALSE; } CPLString osSpatialWhere = poBaseLayer->GetSpatialWhere(m_poFilterGeom); if (osSpatialWhere.size() == 0) { CPLDebug("SQLITE", "Cannot get spatial where clause"); return FALSE; } while (i < osSQLBase.size() && osSQLBase[i] == ' ') i ++; if (i < osSQLBase.size() && EQUALN(osSQLBase.c_str() + i, "WHERE ", 6)) { osSQLCurrent = osSQLBase.substr(0, i + 6); osSQLCurrent += osSpatialWhere; osSQLCurrent += " AND ("; size_t nEndOfWhere = osSQLBase.ifind(" GROUP "); if (nEndOfWhere == std::string::npos) nEndOfWhere = osSQLBase.ifind(" ORDER "); if (nEndOfWhere == std::string::npos) nEndOfWhere = osSQLBase.ifind(" LIMIT "); if (nEndOfWhere == std::string::npos) { osSQLCurrent += osSQLBase.substr(i + 6); osSQLCurrent += ")"; } else { osSQLCurrent += osSQLBase.substr(i + 6, nEndOfWhere - (i + 6)); osSQLCurrent += ")"; osSQLCurrent += osSQLBase.substr(nEndOfWhere); } } else if (i < osSQLBase.size() && (EQUALN(osSQLBase.c_str() + i, "GROUP ", 6) || EQUALN(osSQLBase.c_str() + i, "ORDER ", 6) || EQUALN(osSQLBase.c_str() + i, "LIMIT ", 6))) { osSQLCurrent = osSQLBase.substr(0, i); osSQLCurrent += " WHERE "; osSQLCurrent += osSpatialWhere; osSQLCurrent += " "; osSQLCurrent += osSQLBase.substr(i); } else if (i == osSQLBase.size()) { osSQLCurrent = osSQLBase.substr(0, i); osSQLCurrent += " WHERE "; osSQLCurrent += osSpatialWhere; } else { CPLDebug("SQLITE", "SQL expression too complex for the driver to insert spatial filter in it"); return FALSE; } return TRUE; }
OGRSQLiteLayer* OGRSQLiteSelectLayer::GetBaseLayer(size_t& i) { char** papszTokens = CSLTokenizeString(osSQLBase.c_str()); int bCanInsertSpatialFilter = TRUE; int nCountSelect = 0, nCountFrom = 0, nCountWhere = 0; for(int iToken = 0; papszTokens[iToken] != NULL; iToken++) { if (EQUAL(papszTokens[iToken], "SELECT")) nCountSelect ++; else if (EQUAL(papszTokens[iToken], "FROM")) nCountFrom ++; else if (EQUAL(papszTokens[iToken], "WHERE")) nCountWhere ++; else if (EQUAL(papszTokens[iToken], "UNION") || EQUAL(papszTokens[iToken], "JOIN") || EQUAL(papszTokens[iToken], "INTERSECT") || EQUAL(papszTokens[iToken], "EXCEPT")) { bCanInsertSpatialFilter = FALSE; } } CSLDestroy(papszTokens); if (!(bCanInsertSpatialFilter && nCountSelect == 1 && nCountFrom == 1 && nCountWhere <= 1)) { CPLDebug("SQLITE", "SQL expression too complex to analyse"); return NULL; } size_t nFromPos = osSQLBase.ifind(" from "); if (nFromPos == std::string::npos) { return NULL; } int bInSingleQuotes = (osSQLBase[nFromPos + 6] == '\''); CPLString osBaseLayerName; for( i = nFromPos + 6 + (bInSingleQuotes ? 1 : 0); i < osSQLBase.size(); i++ ) { if (osSQLBase[i] == '\'' && i + 1 < osSQLBase.size() && osSQLBase[i + 1] == '\'' ) { osBaseLayerName += osSQLBase[i]; i++; } else if (osSQLBase[i] == '\'' && bInSingleQuotes) { i++; break; } else if (osSQLBase[i] == ' ' && !bInSingleQuotes) break; else osBaseLayerName += osSQLBase[i]; } OGRSQLiteLayer* poUnderlyingLayer = NULL; if( strchr(osBaseLayerName, '(') == NULL && osGeomColumn.size() != 0 ) { CPLString osNewUnderlyingTableName; osNewUnderlyingTableName.Printf("%s(%s)", osBaseLayerName.c_str(), osGeomColumn.c_str()); poUnderlyingLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(osNewUnderlyingTableName); } if( poUnderlyingLayer == NULL ) poUnderlyingLayer = (OGRSQLiteLayer*) poDS->GetLayerByName(osBaseLayerName); if( poUnderlyingLayer != NULL && poSRS != NULL && poUnderlyingLayer->GetSpatialRef() != NULL && poSRS != poUnderlyingLayer->GetSpatialRef() && !poSRS->IsSame(poUnderlyingLayer->GetSpatialRef()) ) { CPLDebug("SQLITE", "Result layer and base layer don't have the same SRS."); return NULL; } return poUnderlyingLayer; }
CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn() { int rc; sqlite3 *hDB = poDS->GetDB(); sqlite3_stmt *hColStmt = NULL; const char *pszSQL; OGRSQLiteLayer* poUnderlyingLayer = GetUnderlyingLayer(); if (poUnderlyingLayer == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find underlying layer %s for view %s", osUnderlyingTableName.c_str(), pszViewName); return CE_Failure; } if ( !poUnderlyingLayer->IsTableLayer() ) { CPLError(CE_Failure, CPLE_AppDefined, "Underlying layer %s for view %s is not a regular table", osUnderlyingTableName.c_str(), pszViewName); return CE_Failure; } int nUnderlyingLayerGeomFieldIndex = poUnderlyingLayer->GetLayerDefn()->GetGeomFieldIndex(osUnderlyingGeometryColumn); if ( nUnderlyingLayerGeomFieldIndex < 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Underlying layer %s for view %s has not expected geometry column name %s", osUnderlyingTableName.c_str(), pszViewName, osUnderlyingGeometryColumn.c_str()); return CE_Failure; } this->bHasSpatialIndex = poUnderlyingLayer->HasSpatialIndex(nUnderlyingLayerGeomFieldIndex); /* -------------------------------------------------------------------- */ /* Get the column definitions for this table. */ /* -------------------------------------------------------------------- */ hColStmt = NULL; pszSQL = CPLSPrintf( "SELECT \"%s\", * FROM '%s' LIMIT 1", OGRSQLiteEscapeName(pszFIDColumn).c_str(), pszEscapedTableName ); rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to query table %s for column definitions : %s.", pszViewName, sqlite3_errmsg(hDB) ); return CE_Failure; } rc = sqlite3_step( hColStmt ); if ( rc != SQLITE_DONE && rc != SQLITE_ROW ) { CPLError( CE_Failure, CPLE_AppDefined, "In Initialize(): sqlite3_step(%s):\n %s", pszSQL, sqlite3_errmsg(hDB) ); sqlite3_finalize( hColStmt ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Collect the rest of the fields. */ /* -------------------------------------------------------------------- */ std::set<CPLString> aosGeomCols; std::set<CPLString> aosIgnoredCols; aosGeomCols.insert(osGeomColumn); BuildFeatureDefn( pszViewName, hColStmt, aosGeomCols, aosIgnoredCols ); sqlite3_finalize( hColStmt ); /* -------------------------------------------------------------------- */ /* Set the properties of the geometry column. */ /* -------------------------------------------------------------------- */ if( poFeatureDefn->GetGeomFieldCount() != 0 ) { OGRSQLiteGeomFieldDefn* poSrcGeomFieldDefn = poUnderlyingLayer->myGetLayerDefn()->myGetGeomFieldDefn(nUnderlyingLayerGeomFieldIndex); OGRSQLiteGeomFieldDefn* poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(0); poGeomFieldDefn->SetType(poSrcGeomFieldDefn->GetType()); poGeomFieldDefn->SetSpatialRef(poSrcGeomFieldDefn->GetSpatialRef()); poGeomFieldDefn->nSRSId = poSrcGeomFieldDefn->nSRSId; if( eGeomFormat != OSGF_None ) poGeomFieldDefn->eGeomFormat = eGeomFormat; } return CE_None; }