void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName, sqlite3_stmt *hStmt ) { m_poFeatureDefn = new OGRSQLiteFeatureDefn( pszLayerName ); SetDescription( m_poFeatureDefn->GetName() ); m_poFeatureDefn->SetGeomType(wkbNone); m_poFeatureDefn->Reference(); int nRawColumns = sqlite3_column_count( hStmt ); panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns ); int iCol; for( iCol = 0; iCol < nRawColumns; iCol++ ) { OGRFieldDefn oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )), OFTString ); // In some cases, particularly when there is a real name for // the primary key/_rowid_ column we will end up getting the // primary key column appearing twice. Ignore any repeated names. if( m_poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 ) continue; if( EQUAL(oField.GetNameRef(), "FID") ) { CPLFree(m_pszFidColumn); m_pszFidColumn = CPLStrdup(oField.GetNameRef()); iFIDCol = iCol; } if( m_pszFidColumn != NULL && EQUAL(m_pszFidColumn, oField.GetNameRef())) continue; // The rowid is for internal use, not a real column. if( EQUAL(oField.GetNameRef(),"_rowid_") ) continue; // this will avoid the old geom field to appear when running something // like "select st_buffer(geom,5) as geom, * from my_layer" if( m_poFeatureDefn->GetGeomFieldCount() && EQUAL(oField.GetNameRef(), m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()) ) continue; int nColType = sqlite3_column_type( hStmt, iCol ); const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol); // Recognize a geometry column from trying to build the geometry // Useful for OGRSQLiteSelectLayer if( nColType == SQLITE_BLOB && m_poFeatureDefn->GetGeomFieldCount() == 0 ) { const int nBytes = sqlite3_column_bytes( hStmt, iCol ); if( nBytes > 4 ) { int iGpkgSize = sqlite3_column_bytes(hStmt, iCol); const GByte* pabyGpkg = (const GByte*)sqlite3_column_blob( hStmt, iCol ); GPkgHeader oHeader; OGRGeometry* poGeom = NULL; int nSRID; if( GPkgHeaderFromWKB(pabyGpkg, &oHeader) == OGRERR_NONE ) { OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown); /* Read the SRS */ OGRSpatialReference *poSRS = m_poDS->GetSpatialRef(oHeader.iSrsId); if ( poSRS ) { oGeomField.SetSpatialRef(poSRS); poSRS->Dereference(); } OGRwkbGeometryType eGeomType = wkbUnknown; if( pszDeclType != NULL ) { eGeomType = GPkgGeometryTypeToWKB(pszDeclType, (oHeader.iDims == 3)); if( eGeomType != wkbNone ) oGeomField.SetType( eGeomType ); } #ifdef SQLITE_HAS_COLUMN_METADATA const char* pszTableName = sqlite3_column_table_name( hStmt, iCol ); if( oGeomField.GetType() == wkbUnknown && pszTableName != NULL ) { OGRGeoPackageLayer* poLayer = (OGRGeoPackageLayer*) m_poDS->GetLayerByName(pszTableName); if( poLayer != NULL && poLayer->GetLayerDefn()->GetGeomFieldCount() > 0) { oGeomField.SetType( poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->GetType() ); } } #endif m_poFeatureDefn->AddGeomFieldDefn(&oGeomField); iGeomCol = iCol; continue; } // Try also spatialite geometry blobs else if( OGRSQLiteLayer::ImportSpatiaLiteGeometry( pabyGpkg, iGpkgSize, &poGeom, &nSRID ) == OGRERR_NONE ) { OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown); /* Read the SRS */ OGRSpatialReference *poSRS = m_poDS->GetSpatialRef(nSRID); if ( poSRS ) { oGeomField.SetSpatialRef(poSRS); poSRS->Dereference(); } delete poGeom; m_poFeatureDefn->AddGeomFieldDefn(&oGeomField); iGeomCol = iCol; continue; } } } switch( nColType ) { case SQLITE_INTEGER: if( CSLTestBoolean(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE")) ) oField.SetType( OFTInteger64 ); else { GIntBig nVal = sqlite3_column_int64(hStmt, iCol); if( (GIntBig)(int)nVal == nVal ) oField.SetType( OFTInteger ); else oField.SetType( OFTInteger64 ); } break; case SQLITE_FLOAT: oField.SetType( OFTReal ); break; case SQLITE_BLOB: oField.SetType( OFTBinary ); break; default: /* leave it as OFTString */; } if (pszDeclType != NULL) { OGRFieldSubType eSubType; int nMaxWidth; OGRFieldType eFieldType = GPkgFieldToOGR(pszDeclType, eSubType, nMaxWidth); if( (int)eFieldType <= OFTMaxType ) { oField.SetType(eFieldType); oField.SetSubType(eSubType); oField.SetWidth(nMaxWidth); } } m_poFeatureDefn->AddFieldDefn( &oField ); panFieldOrdinals[m_poFeatureDefn->GetFieldCount() - 1] = iCol; } }
OGRLayer* OGRVRTDataSource::InstanciateUnionLayer( CPLXMLNode *psLTree, const char *pszVRTDirectory, int bUpdate, int nRecLevel) { CPLXMLNode *psSubNode; if( !EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") ) return NULL; /* -------------------------------------------------------------------- */ /* Get layer name. */ /* -------------------------------------------------------------------- */ const char *pszLayerName = CPLGetXMLValue( psLTree, "name", NULL ); if( pszLayerName == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Missing name attribute on OGRVRTUnionLayer" ); return FALSE; } /* -------------------------------------------------------------------- */ /* Do we have a fixed geometry type? If not derive from the */ /* source layer. */ /* -------------------------------------------------------------------- */ const char* pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL ); int bGlobalGeomTypeSet = FALSE; OGRwkbGeometryType eGlobalGeomType = wkbUnknown; if( pszGType != NULL ) { int bError; bGlobalGeomTypeSet = TRUE; eGlobalGeomType = OGRVRTGetGeometryType(pszGType, &bError); if( bError ) { CPLError( CE_Failure, CPLE_AppDefined, "GeometryType %s not recognised.", pszGType ); return NULL; } } /* -------------------------------------------------------------------- */ /* Apply a spatial reference system if provided */ /* -------------------------------------------------------------------- */ const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL ); OGRSpatialReference* poGlobalSRS = NULL; int bGlobalSRSSet = FALSE; if( pszLayerSRS != NULL ) { bGlobalSRSSet = TRUE; if( !EQUAL(pszLayerSRS,"NULL") ) { OGRSpatialReference oSRS; if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE ) { CPLError( CE_Failure, CPLE_AppDefined, "Failed to import LayerSRS `%s'.", pszLayerSRS ); return FALSE; } poGlobalSRS = oSRS.Clone(); } } /* -------------------------------------------------------------------- */ /* Find field declarations. */ /* -------------------------------------------------------------------- */ OGRFieldDefn** papoFields = NULL; int nFields = 0; OGRUnionLayerGeomFieldDefn** papoGeomFields = NULL; int nGeomFields = 0; for( psSubNode=psLTree->psChild; psSubNode != NULL; psSubNode=psSubNode->psNext ) { if( psSubNode->eType != CXT_Element ) continue; if( psSubNode->eType == CXT_Element && EQUAL(psSubNode->pszValue,"Field") ) { /* -------------------------------------------------------------------- */ /* Field name. */ /* -------------------------------------------------------------------- */ const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL ); if( pszName == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to identify Field name." ); break; } OGRFieldDefn oFieldDefn( pszName, OFTString ); /* -------------------------------------------------------------------- */ /* Type */ /* -------------------------------------------------------------------- */ const char *pszArg = CPLGetXMLValue( psSubNode, "type", NULL ); if( pszArg != NULL ) { int iType; for( iType = 0; iType <= (int) OFTMaxType; iType++ ) { if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName( (OGRFieldType)iType)) ) { oFieldDefn.SetType( (OGRFieldType) iType ); break; } } if( iType > (int) OFTMaxType ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to identify Field type '%s'.", pszArg ); break; } } /* -------------------------------------------------------------------- */ /* Width and precision. */ /* -------------------------------------------------------------------- */ int nWidth = atoi(CPLGetXMLValue( psSubNode, "width", "0" )); if (nWidth < 0) { CPLError( CE_Failure, CPLE_IllegalArg, "Invalid width for field %s.", pszName ); break; } oFieldDefn.SetWidth(nWidth); int nPrecision = atoi(CPLGetXMLValue( psSubNode, "precision", "0" )); if (nPrecision < 0 || nPrecision > 1024) { CPLError( CE_Failure, CPLE_IllegalArg, "Invalid precision for field %s.", pszName ); break; } oFieldDefn.SetPrecision(nPrecision); papoFields = (OGRFieldDefn**) CPLRealloc(papoFields, sizeof(OGRFieldDefn*) * (nFields + 1)); papoFields[nFields] = new OGRFieldDefn(&oFieldDefn); nFields ++; } else if( psSubNode->eType == CXT_Element && EQUAL(psSubNode->pszValue,"GeometryField") ) { const char *pszName = CPLGetXMLValue( psSubNode, "name", NULL ); if( pszName == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to identify GeometryField name." ); break; } pszGType = CPLGetXMLValue( psSubNode, "GeometryType", NULL ); if( pszGType == NULL && nGeomFields == 0 ) pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL ); OGRwkbGeometryType eGeomType = wkbUnknown; int bGeomTypeSet = FALSE; if( pszGType != NULL ) { int bError; eGeomType = OGRVRTGetGeometryType(pszGType, &bError); bGeomTypeSet = TRUE; if( bError || eGeomType == wkbNone ) { CPLError( CE_Failure, CPLE_AppDefined, "GeometryType %s not recognised.", pszGType ); break; } } const char* pszSRS = CPLGetXMLValue( psSubNode, "SRS", NULL ); if( pszSRS == NULL && nGeomFields == 0 ) pszSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL ); OGRSpatialReference* poSRS = NULL; int bSRSSet = FALSE; if( pszSRS != NULL ) { bSRSSet = TRUE; if( !EQUAL(pszSRS,"NULL") ) { OGRSpatialReference oSRS; if( oSRS.SetFromUserInput( pszSRS ) != OGRERR_NONE ) { CPLError( CE_Failure, CPLE_AppDefined, "Failed to import SRS `%s'.", pszSRS ); break; } poSRS = oSRS.Clone(); } } OGRUnionLayerGeomFieldDefn* poFieldDefn = new OGRUnionLayerGeomFieldDefn(pszName, eGeomType); if( poSRS != NULL ) { poFieldDefn->SetSpatialRef(poSRS); poSRS->Dereference(); } poFieldDefn->bGeomTypeSet = bGeomTypeSet; poFieldDefn->bSRSSet = bSRSSet; const char* pszExtentXMin = CPLGetXMLValue( psSubNode, "ExtentXMin", NULL ); const char* pszExtentYMin = CPLGetXMLValue( psSubNode, "ExtentYMin", NULL ); const char* pszExtentXMax = CPLGetXMLValue( psSubNode, "ExtentXMax", NULL ); const char* pszExtentYMax = CPLGetXMLValue( psSubNode, "ExtentYMax", NULL ); if( pszExtentXMin != NULL && pszExtentYMin != NULL && pszExtentXMax != NULL && pszExtentYMax != NULL ) { poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin); poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin); poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax); poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax); } papoGeomFields = (OGRUnionLayerGeomFieldDefn**) CPLRealloc(papoGeomFields, sizeof(OGRUnionLayerGeomFieldDefn*) * (nGeomFields + 1)); papoGeomFields[nGeomFields] = poFieldDefn; nGeomFields ++; } } /* -------------------------------------------------------------------- */ /* Set Extent if provided */ /* -------------------------------------------------------------------- */ const char* pszExtentXMin = CPLGetXMLValue( psLTree, "ExtentXMin", NULL ); const char* pszExtentYMin = CPLGetXMLValue( psLTree, "ExtentYMin", NULL ); const char* pszExtentXMax = CPLGetXMLValue( psLTree, "ExtentXMax", NULL ); const char* pszExtentYMax = CPLGetXMLValue( psLTree, "ExtentYMax", NULL ); if( eGlobalGeomType != wkbNone && nGeomFields == 0 && (bGlobalGeomTypeSet || bGlobalSRSSet || (pszExtentXMin != NULL && pszExtentYMin != NULL && pszExtentXMax != NULL && pszExtentYMax != NULL)) ) { OGRUnionLayerGeomFieldDefn* poFieldDefn = new OGRUnionLayerGeomFieldDefn("", eGlobalGeomType); if( poGlobalSRS != NULL ) { poFieldDefn->SetSpatialRef(poGlobalSRS); poGlobalSRS->Dereference(); poGlobalSRS = NULL; } poFieldDefn->bGeomTypeSet = bGlobalGeomTypeSet; poFieldDefn->bSRSSet = bGlobalSRSSet; if( pszExtentXMin != NULL && pszExtentYMin != NULL && pszExtentXMax != NULL && pszExtentYMax != NULL ) { poFieldDefn->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin); poFieldDefn->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin); poFieldDefn->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax); poFieldDefn->sStaticEnvelope.MaxY = CPLAtof(pszExtentYMax); } papoGeomFields = (OGRUnionLayerGeomFieldDefn**) CPLRealloc(papoGeomFields, sizeof(OGRUnionLayerGeomFieldDefn*) * (nGeomFields + 1)); papoGeomFields[nGeomFields] = poFieldDefn; nGeomFields ++; } else { delete poGlobalSRS; poGlobalSRS = NULL; } /* -------------------------------------------------------------------- */ /* Find source layers */ /* -------------------------------------------------------------------- */ int nSrcLayers = 0; OGRLayer** papoSrcLayers = NULL; for( psSubNode=psLTree->psChild; psSubNode != NULL; psSubNode=psSubNode->psNext ) { if( psSubNode->eType != CXT_Element ) continue; OGRLayer* poSrcLayer = InstanciateLayer(psSubNode, pszVRTDirectory, bUpdate, nRecLevel + 1); if( poSrcLayer != NULL ) { papoSrcLayers = (OGRLayer**) CPLRealloc(papoSrcLayers, sizeof(OGRLayer*) * (nSrcLayers + 1)); papoSrcLayers[nSrcLayers] = poSrcLayer; nSrcLayers ++; } } if( nSrcLayers == 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot find source layers" ); int iField; for(iField = 0; iField < nFields; iField++) delete papoFields[iField]; CPLFree(papoFields); for(iField = 0; iField < nGeomFields; iField++) delete papoGeomFields[iField]; CPLFree(papoGeomFields); return NULL; } /* -------------------------------------------------------------------- */ /* Build the OGRUnionLayer. */ /* -------------------------------------------------------------------- */ OGRUnionLayer* poLayer = new OGRUnionLayer( pszLayerName, nSrcLayers, papoSrcLayers, TRUE ); /* -------------------------------------------------------------------- */ /* Set the source layer field name attribute. */ /* -------------------------------------------------------------------- */ const char* pszSourceLayerFieldName = CPLGetXMLValue( psLTree, "SourceLayerFieldName", NULL ); poLayer->SetSourceLayerFieldName(pszSourceLayerFieldName); /* -------------------------------------------------------------------- */ /* Set the PreserveSrcFID attribute. */ /* -------------------------------------------------------------------- */ int bPreserveSrcFID = FALSE; const char* pszPreserveFID = CPLGetXMLValue( psLTree, "PreserveSrcFID", NULL ); if( pszPreserveFID != NULL ) bPreserveSrcFID = CSLTestBoolean(pszPreserveFID); poLayer->SetPreserveSrcFID(bPreserveSrcFID); /* -------------------------------------------------------------------- */ /* Set fields */ /* -------------------------------------------------------------------- */ FieldUnionStrategy eFieldStrategy = FIELD_UNION_ALL_LAYERS; const char* pszFieldStrategy = CPLGetXMLValue( psLTree, "FieldStrategy", NULL ); if( pszFieldStrategy != NULL ) { if( EQUAL(pszFieldStrategy, "FirstLayer") ) eFieldStrategy = FIELD_FROM_FIRST_LAYER; else if( EQUAL(pszFieldStrategy, "Union") ) eFieldStrategy = FIELD_UNION_ALL_LAYERS; else if( EQUAL(pszFieldStrategy, "Intersection") ) eFieldStrategy = FIELD_INTERSECTION_ALL_LAYERS; else { CPLError( CE_Warning, CPLE_AppDefined, "Unhandled value for FieldStrategy `%s'.", pszFieldStrategy ); } } if( nFields != 0 || nGeomFields > 1 ) { if( pszFieldStrategy != NULL ) CPLError( CE_Warning, CPLE_AppDefined, "Ignoring FieldStrategy value, because explicit Field or GeometryField is provided") ; eFieldStrategy = FIELD_SPECIFIED; } poLayer->SetFields(eFieldStrategy, nFields, papoFields, (nGeomFields == 0 && eGlobalGeomType == wkbNone) ? -1 : nGeomFields, papoGeomFields); int iField; for(iField = 0; iField < nFields; iField++) delete papoFields[iField]; CPLFree(papoFields); for(iField = 0; iField < nGeomFields; iField++) delete papoGeomFields[iField]; CPLFree(papoGeomFields); /* -------------------------------------------------------------------- */ /* Set FeatureCount if provided */ /* -------------------------------------------------------------------- */ const char* pszFeatureCount = CPLGetXMLValue( psLTree, "FeatureCount", NULL ); if( pszFeatureCount != NULL ) { poLayer->SetFeatureCount(atoi(pszFeatureCount)); } return poLayer; }
void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName, sqlite3_stmt *hStmt ) { m_poFeatureDefn = new OGRSQLiteFeatureDefn( pszLayerName ); SetDescription( m_poFeatureDefn->GetName() ); m_poFeatureDefn->SetGeomType(wkbNone); m_poFeatureDefn->Reference(); int nRawColumns = sqlite3_column_count( hStmt ); panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns ); int iCol; for( iCol = 0; iCol < nRawColumns; iCol++ ) { OGRFieldDefn oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )), OFTString ); // In some cases, particularly when there is a real name for // the primary key/_rowid_ column we will end up getting the // primary key column appearing twice. Ignore any repeated names. if( m_poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 ) continue; if( EQUAL(oField.GetNameRef(), "FID") ) { CPLFree(m_pszFidColumn); m_pszFidColumn = CPLStrdup(oField.GetNameRef()); iFIDCol = iCol; } if( m_pszFidColumn != NULL && EQUAL(m_pszFidColumn, oField.GetNameRef())) continue; // The rowid is for internal use, not a real column. if( EQUAL(oField.GetNameRef(),"_rowid_") ) continue; int nColType = sqlite3_column_type( hStmt, iCol ); const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol); // Recognize a geometry column from trying to build the geometry // Usefull for OGRSQLiteSelectLayer if( nColType == SQLITE_BLOB && m_poFeatureDefn->GetGeomFieldCount() == 0 ) { const int nBytes = sqlite3_column_bytes( hStmt, iCol ); if( nBytes > 4 ) { const GByte* pabyGpkg = (const GByte*)sqlite3_column_blob( hStmt, iCol ); GPkgHeader oHeader; if( GPkgHeaderFromWKB(pabyGpkg, &oHeader) == OGRERR_NONE ) { OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown); /* Read the SRS */ OGRSpatialReference *poSRS = m_poDS->GetSpatialRef(oHeader.iSrsId); if ( poSRS ) { oGeomField.SetSpatialRef(poSRS); poSRS->Dereference(); } OGRwkbGeometryType eGeomType = wkbUnknown; if( pszDeclType != NULL ) { eGeomType = GPkgGeometryTypeToWKB(pszDeclType, (oHeader.iDims == 3)); if( eGeomType != wkbNone ) oGeomField.SetType( eGeomType ); } #ifdef SQLITE_HAS_COLUMN_METADATA const char* pszTableName = sqlite3_column_table_name( hStmt, iCol ); if( oGeomField.GetType() == wkbUnknown && pszTableName != NULL ) { OGRGeoPackageLayer* poLayer = (OGRGeoPackageLayer*) m_poDS->GetLayerByName(pszTableName); if( poLayer != NULL && poLayer->GetLayerDefn()->GetGeomFieldCount() > 0) { oGeomField.SetType( poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->GetType() ); } } #endif m_poFeatureDefn->AddGeomFieldDefn(&oGeomField); iGeomCol = iCol; continue; } } } switch( nColType ) { case SQLITE_INTEGER: oField.SetType( OFTInteger ); break; case SQLITE_FLOAT: oField.SetType( OFTReal ); break; case SQLITE_BLOB: oField.SetType( OFTBinary ); break; default: /* leave it as OFTString */; } if (pszDeclType != NULL) { OGRFieldType eFieldType = GPkgFieldToOGR(pszDeclType); if( (int)eFieldType <= OFTMaxType ) oField.SetType(eFieldType); } m_poFeatureDefn->AddFieldDefn( &oField ); panFieldOrdinals[m_poFeatureDefn->GetFieldCount() - 1] = iCol; } }