OGRLayer * OGRMSSQLSpatialDataSource::CreateLayer( const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { char *pszTableName = NULL; char *pszSchemaName = NULL; const char *pszGeomType = NULL; const char *pszGeomColumn = NULL; int nCoordDimension = 3; /* determine the dimension */ if( eType == wkbFlatten(eType) ) nCoordDimension = 2; if( CSLFetchNameValue( papszOptions, "DIM") != NULL ) nCoordDimension = atoi(CSLFetchNameValue( papszOptions, "DIM")); /* MSSQL Schema handling: Extract schema name from input layer name or passed with -lco SCHEMA. Set layer name to "schema.table" or to "table" if schema is not specified */ const char* pszDotPos = strstr(pszLayerName,"."); if ( pszDotPos != NULL ) { int length = pszDotPos - pszLayerName; pszSchemaName = (char*)CPLMalloc(length+1); strncpy(pszSchemaName, pszLayerName, length); pszSchemaName[length] = '\0'; if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) pszTableName = LaunderName( pszDotPos + 1 ); //skip "." else pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "." } else { pszSchemaName = NULL; if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) pszTableName = LaunderName( pszLayerName ); //skip "." else pszTableName = CPLStrdup( pszLayerName ); //skip "." } if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL ) { CPLFree(pszSchemaName); pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" )); } if (pszSchemaName == NULL) pszSchemaName = CPLStrdup("dbo"); /* -------------------------------------------------------------------- */ /* Do we already have this layer? If so, should we blow it */ /* away? */ /* -------------------------------------------------------------------- */ int iLayer; for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszLayerName,papoLayers[iLayer]->GetTableName()) ) { if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") ) { if (!pszSchemaName) pszSchemaName = CPLStrdup(papoLayers[iLayer]->GetSchemaName()); DeleteLayer( iLayer ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, CreateLayer failed.\n" "Use the layer creation option OVERWRITE=YES to " "replace it.", pszLayerName ); CPLFree( pszSchemaName ); CPLFree( pszTableName ); return NULL; } } } /* -------------------------------------------------------------------- */ /* Handle the GEOM_TYPE option. */ /* -------------------------------------------------------------------- */ pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" ); if( !pszGeomType ) pszGeomType = "geometry"; if( !EQUAL(pszGeomType, "geometry") && !EQUAL(pszGeomType, "geography")) { CPLError( CE_Failure, CPLE_AppDefined, "FORMAT=%s not recognised or supported.", pszGeomType ); CPLFree( pszSchemaName ); CPLFree( pszTableName ); return NULL; } /* determine the geometry column name */ pszGeomColumn = CSLFetchNameValue( papszOptions, "GEOM_NAME"); if (!pszGeomColumn) pszGeomColumn = "ogr_geometry"; /* -------------------------------------------------------------------- */ /* Initialize the metadata tables */ /* -------------------------------------------------------------------- */ if (InitializeMetadataTables() != OGRERR_NONE) { CPLFree( pszSchemaName ); CPLFree( pszTableName ); return NULL; } /* -------------------------------------------------------------------- */ /* Try to get the SRS Id of this spatial reference system, */ /* adding to the srs table if needed. */ /* -------------------------------------------------------------------- */ int nSRSId = 0; if( CSLFetchNameValue( papszOptions, "SRID") != NULL ) nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID")); if( nSRSId == 0 && poSRS != NULL ) nSRSId = FetchSRSId( poSRS ); /* -------------------------------------------------------------------- */ /* Create a new table and create a new entry in the geometry, */ /* geometry_columns metadata table. */ /* -------------------------------------------------------------------- */ if( eType != wkbNone ) { const char *pszGeometryType = OGRToOGCGeomType(eType); CPLODBCStatement oStmt( &oSession ); oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' " "AND f_table_name = '%s'\n", pszSchemaName, pszTableName ); oStmt.Appendf("INSERT INTO [geometry_columns] ([f_table_catalog], [f_table_schema] ,[f_table_name], " "[f_geometry_column],[coord_dimension],[srid],[geometry_type]) VALUES ('%s', '%s', '%s', '%s', %d, %d, '%s')\n", pszCatalog, pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszGeometryType ); oStmt.Appendf("CREATE TABLE [%s].[%s] ([ogr_fid] [int] IDENTITY(1,1) NOT NULL, " "[%s] [%s] NULL, CONSTRAINT [PK_%s] PRIMARY KEY CLUSTERED ([ogr_fid] ASC))", pszSchemaName, pszTableName, pszGeomColumn, pszGeomType, pszTableName); oSession.BeginTransaction(); if( !oStmt.ExecuteSQL() ) { CPLError( CE_Failure, CPLE_AppDefined, "Error creating layer: %s", GetSession()->GetLastError() ); return NULL; } oSession.CommitTransaction(); } CPLFree( pszSchemaName ); CPLFree( pszTableName ); /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRMSSQLSpatialTableLayer *poLayer; poLayer = new OGRMSSQLSpatialTableLayer( this ); poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) ); poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE)); if (poLayer->Initialize("dbo", pszLayerName, pszGeomColumn, nCoordDimension, nSRSId, eType) == OGRERR_FAILURE) { return NULL; } /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRMSSQLSpatialTableLayer **) CPLRealloc( papoLayers, sizeof(OGRMSSQLSpatialTableLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; return poLayer; }
OGRErr OGRPGDumpLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn, CPL_UNUSED int bApproxOK ) { OGRwkbGeometryType eType = poGeomFieldIn->GetType(); if( eType == wkbNone ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot create geometry field of type wkbNone"); return OGRERR_FAILURE; } CPLString osCommand; OGRPGDumpGeomFieldDefn *poGeomField = new OGRPGDumpGeomFieldDefn( poGeomFieldIn ); /* -------------------------------------------------------------------- */ /* Do we want to "launder" the column names into Postgres */ /* friendly format? */ /* -------------------------------------------------------------------- */ if( bLaunderColumnNames ) { char *pszSafeName = poDS->LaunderName( poGeomField->GetNameRef() ); poGeomField->SetName( pszSafeName ); CPLFree( pszSafeName ); } OGRSpatialReference* poSRS = poGeomField->GetSpatialRef(); int nSRSId = nUnknownSRSId; if( nForcedSRSId != -2 ) nSRSId = nForcedSRSId; else if( poSRS != NULL ) { const char* pszAuthorityName = poSRS->GetAuthorityName(NULL); if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) ) { /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */ nSRSId = atoi( poSRS->GetAuthorityCode(NULL) ); } else { const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS"); if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984")) nSRSId = 4326; } } int nDimension = 3; if( wkbFlatten(eType) == eType ) nDimension = 2; poGeomField->nSRSId = nSRSId; poGeomField->nCoordDimension = nDimension; /* -------------------------------------------------------------------- */ /* Create the new field. */ /* -------------------------------------------------------------------- */ if (bCreateTable) { const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType()); osCommand.Printf( "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s',%d)", OGRPGDumpEscapeString(pszSchemaName).c_str(), OGRPGDumpEscapeString(poFeatureDefn->GetName()).c_str(), OGRPGDumpEscapeString(poGeomField->GetNameRef()).c_str(), nSRSId, pszGeometryType, nDimension ); poDS->Log(osCommand); if( bCreateSpatialIndexFlag ) { osCommand.Printf("CREATE INDEX %s ON %s USING GIST (%s)", OGRPGDumpEscapeColumnName( CPLSPrintf("%s_%s_geom_idx", GetName(), poGeomField->GetNameRef())).c_str(), pszSqlTableName, OGRPGDumpEscapeColumnName(poGeomField->GetNameRef()).c_str()); poDS->Log(osCommand); } } poFeatureDefn->AddGeomFieldDefn( poGeomField, FALSE ); return OGRERR_NONE; }
OGRLayer * OGRMySQLDataSource::CreateLayer( const char * pszLayerNameIn, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { MYSQL_RES *hResult=NULL; CPLString osCommand; const char *pszGeometryType; const char *pszGeomColumnName; const char *pszExpectedFIDName; char *pszLayerName; int nDimension = 3; // MySQL only supports 2d currently /* -------------------------------------------------------------------- */ /* Make sure there isn't an active transaction already. */ /* -------------------------------------------------------------------- */ InterruptLongResult(); if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) ) pszLayerName = LaunderName( pszLayerNameIn ); else pszLayerName = CPLStrdup( pszLayerNameIn ); if( wkbFlatten(eType) == eType ) nDimension = 2; CPLDebug("MYSQL","Creating layer %s.", pszLayerName); /* -------------------------------------------------------------------- */ /* Do we already have this layer? If so, should we blow it */ /* away? */ /* -------------------------------------------------------------------- */ int iLayer; for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) ) { if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") ) { DeleteLayer( iLayer ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, CreateLayer failed.\n" "Use the layer creation option OVERWRITE=YES to " "replace it.", pszLayerName ); CPLFree( pszLayerName ); return NULL; } } } pszGeomColumnName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" ); if (!pszGeomColumnName) pszGeomColumnName="SHAPE"; pszExpectedFIDName = CSLFetchNameValue( papszOptions, "MYSQL_FID" ); if (!pszExpectedFIDName) pszExpectedFIDName="OGR_FID"; CPLDebug("MYSQL","Geometry Column Name %s.", pszGeomColumnName); CPLDebug("MYSQL","FID Column Name %s.", pszExpectedFIDName); if( wkbFlatten(eType) == wkbNone ) { osCommand.Printf( "CREATE TABLE `%s` ( " " %s INT UNIQUE NOT NULL AUTO_INCREMENT )", pszLayerName, pszExpectedFIDName ); } else { osCommand.Printf( "CREATE TABLE `%s` ( " " %s INT UNIQUE NOT NULL AUTO_INCREMENT, " " %s GEOMETRY NOT NULL )", pszLayerName, pszExpectedFIDName, pszGeomColumnName ); } if( CSLFetchNameValue( papszOptions, "ENGINE" ) != NULL ) { osCommand += " ENGINE = "; osCommand += CSLFetchNameValue( papszOptions, "ENGINE" ); } if( !mysql_query(GetConn(), osCommand ) ) { if( mysql_field_count( GetConn() ) == 0 ) CPLDebug("MYSQL","Created table %s.", pszLayerName); else { ReportError( osCommand ); return NULL; } } else { ReportError( osCommand ); return NULL; } // make sure to attempt to free results of successful queries hResult = mysql_store_result( GetConn() ); if( hResult != NULL ) mysql_free_result( hResult ); hResult = NULL; // Calling this does no harm InitializeMetadataTables(); /* -------------------------------------------------------------------- */ /* Try to get the SRS Id of this spatial reference system, */ /* adding tot the srs table if needed. */ /* -------------------------------------------------------------------- */ int nSRSId = -1; if( poSRS != NULL ) nSRSId = FetchSRSId( poSRS ); /* -------------------------------------------------------------------- */ /* Sometimes there is an old crufty entry in the geometry_columns */ /* table if things were not properly cleaned up before. We make */ /* an effort to clean out such cruft. */ /* */ /* -------------------------------------------------------------------- */ osCommand.Printf( "DELETE FROM geometry_columns WHERE f_table_name = '%s'", pszLayerName ); if( mysql_query(GetConn(), osCommand ) ) { ReportError( osCommand ); return NULL; } // make sure to attempt to free results of successful queries hResult = mysql_store_result( GetConn() ); if( hResult != NULL ) mysql_free_result( hResult ); hResult = NULL; /* -------------------------------------------------------------------- */ /* Attempt to add this table to the geometry_columns table, if */ /* it is a spatial layer. */ /* -------------------------------------------------------------------- */ if( eType != wkbNone ) { int nCoordDimension; if( eType == wkbFlatten(eType) ) nCoordDimension = 2; else nCoordDimension = 3; pszGeometryType = OGRToOGCGeomType(eType); if( nSRSId == -1 ) osCommand.Printf( "INSERT INTO geometry_columns " " (F_TABLE_NAME, " " F_GEOMETRY_COLUMN, " " COORD_DIMENSION, " " TYPE) values " " ('%s', '%s', %d, '%s')", pszLayerName, pszGeomColumnName, nCoordDimension, pszGeometryType ); else osCommand.Printf( "INSERT INTO geometry_columns " " (F_TABLE_NAME, " " F_GEOMETRY_COLUMN, " " COORD_DIMENSION, " " SRID, " " TYPE) values " " ('%s', '%s', %d, %d, '%s')", pszLayerName, pszGeomColumnName, nCoordDimension, nSRSId, pszGeometryType ); if( mysql_query(GetConn(), osCommand ) ) { ReportError( osCommand ); return NULL; } // make sure to attempt to free results of successful queries hResult = mysql_store_result( GetConn() ); if( hResult != NULL ) mysql_free_result( hResult ); hResult = NULL; } /* -------------------------------------------------------------------- */ /* Create the spatial index. */ /* */ /* We're doing this before we add geometry and record to the table */ /* so this may not be exactly the best way to do it. */ /* -------------------------------------------------------------------- */ const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" ); if( eType != wkbNone && (pszSI == NULL || CSLTestBoolean(pszSI)) ) { osCommand.Printf( "ALTER TABLE `%s` ADD SPATIAL INDEX(`%s`) ", pszLayerName, pszGeomColumnName); if( mysql_query(GetConn(), osCommand ) ) { ReportError( osCommand ); return NULL; } // make sure to attempt to free results of successful queries hResult = mysql_store_result( GetConn() ); if( hResult != NULL ) mysql_free_result( hResult ); hResult = NULL; } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRMySQLTableLayer *poLayer; OGRErr eErr; poLayer = new OGRMySQLTableLayer( this, pszLayerName, TRUE, nSRSId ); eErr = poLayer->Initialize(pszLayerName); if (eErr == OGRERR_FAILURE) return NULL; poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) ); poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE)); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRMySQLLayer **) CPLRealloc( papoLayers, sizeof(OGRMySQLLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; CPLFree( pszLayerName ); return poLayer; }
OGRLayer *OGRCARTODBDataSource::ICreateLayer( const char *pszName, OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType, char ** papszOptions ) { if (!bReadWrite) { CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode"); return NULL; } /* -------------------------------------------------------------------- */ /* Do we already have this layer? If so, should we blow it */ /* away? */ /* -------------------------------------------------------------------- */ int iLayer; for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszName,papoLayers[iLayer]->GetName()) ) { if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") ) { DeleteLayer( iLayer ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, CreateLayer failed.\n" "Use the layer creation option OVERWRITE=YES to " "replace it.", pszName ); return NULL; } } } int nSRID = 0; if( poSpatialRef != NULL ) nSRID = FetchSRSId( poSpatialRef ); CPLString osGeomType; if( eGType != wkbNone ) { osGeomType = OGRToOGCGeomType(eGType); if( eGType & wkb25DBit ) osGeomType += "Z"; } CPLString osSQL; osSQL.Printf("CREATE TABLE %s ( %s SERIAL, ", OGRCARTODBEscapeIdentifier(pszName).c_str(), "cartodb_id"); if( osGeomType.size() > 0 ) { osSQL += CPLSPrintf("%s GEOMETRY(%s, %d), %s GEOMETRY(%s, %d),", "the_geom", osGeomType.c_str(), nSRID, "the_geom_webmercator", osGeomType.c_str(), 3857); } osSQL += CPLSPrintf("PRIMARY KEY (%s) )", "cartodb_id"); osSQL += ";"; osSQL += CPLSPrintf("DROP SEQUENCE IF EXISTS %s", OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq", pszName, "cartodb_id")).c_str()); osSQL += ";"; osSQL += CPLSPrintf("CREATE SEQUENCE %s START 1", OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq", pszName, "cartodb_id")).c_str()); osSQL += ";"; osSQL += CPLSPrintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT nextval('%s')", pszName, "cartodb_id", OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", pszName, "cartodb_id")).c_str()); json_object* poObj = RunSQL(osSQL); if( poObj == NULL ) return NULL; json_object_put(poObj); OGRCARTODBTableLayer* poLayer = new OGRCARTODBTableLayer(this, pszName); papoLayers = (OGRLayer**) CPLRealloc( papoLayers, (nLayers + 1) * sizeof(OGRLayer*)); papoLayers[nLayers ++] = poLayer; return poLayer; }
void OGRCloudantTableLayer::WriteMetadata() { if (pszSpatialDDoc == nullptr) OGRCloudantTableLayer::GetSpatialView(); if( pszSpatialDDoc == nullptr ) return; CPLString osURI; osURI = "/"; osURI += osEscapedName; osURI += "/"; osURI += pszSpatialDDoc; json_object* poDDocObj = poDS->GET(osURI); if (poDDocObj == nullptr) return; if ( !json_object_is_type(poDDocObj, json_type_object) ) { CPLError(CE_Failure, CPLE_AppDefined, "WriteMetadata() failed"); json_object_put(poDDocObj); return; } json_object* poError = CPL_json_object_object_get(poDDocObj, "error"); const char* pszError = json_object_get_string(poError); if (pszError && strcmp(pszError, "not_found") == 0) { json_object_put(poDDocObj); return; } if (poDS->IsError(poDDocObj, "WriteMetadata() failed")) { json_object_put(poDDocObj); return; } if (poSRS) { // epsg codes are supported in Cloudant const char * pszEpsg = nullptr; const char * pszAuthName = nullptr; char szSrid[100]; if (poSRS->IsProjected()) { pszAuthName = poSRS->GetAuthorityName("PROJCS"); if ((pszAuthName != nullptr) && (STARTS_WITH(pszAuthName, "EPSG"))) pszEpsg = poSRS->GetAuthorityCode("PROJCS"); } else { pszAuthName = poSRS->GetAuthorityName("GEOGCS"); if ((pszAuthName != nullptr) && (STARTS_WITH(pszAuthName, "EPSG"))) pszEpsg = poSRS->GetAuthorityCode("GEOGCS"); } if (pszEpsg != nullptr) { const char * pszUrn = "urn:ogc:def:crs:epsg::"; CPLStrlcpy(szSrid, pszUrn, sizeof(szSrid)); if (CPLStrlcpy(szSrid + sizeof(pszUrn), pszEpsg, sizeof(szSrid)) <= sizeof(szSrid)) { json_object_object_add(poDDocObj, "srsid", json_object_new_string(pszUrn)); } } } if (eGeomType != wkbNone) { json_object_object_add(poDDocObj, "geomtype", json_object_new_string(OGRToOGCGeomType(eGeomType))); if (wkbHasZ(poFeatureDefn->GetGeomType())) { json_object_object_add(poDDocObj, "is_25D", json_object_new_boolean(TRUE)); } } else { json_object_object_add(poDDocObj, "geomtype", json_object_new_string("NONE")); } json_object_object_add(poDDocObj, "geojson_documents", json_object_new_boolean(bGeoJSONDocument)); json_object* poFields = json_object_new_array(); json_object_object_add(poDDocObj, "fields", poFields); for(int i=COUCHDB_FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++) { json_object* poField = json_object_new_object(); json_object_array_add(poFields, poField); json_object_object_add(poField, "name", json_object_new_string(poFeatureDefn->GetFieldDefn(i)->GetNameRef())); const char* pszType = nullptr; switch (poFeatureDefn->GetFieldDefn(i)->GetType()) { case OFTInteger: pszType = "integer"; break; case OFTReal: pszType = "real"; break; case OFTString: pszType = "string"; break; case OFTIntegerList: pszType = "integerlist"; break; case OFTRealList: pszType = "reallist"; break; case OFTStringList: pszType = "stringlist"; break; default: pszType = "string"; break; } json_object_object_add(poField, "type", json_object_new_string(pszType)); } json_object* poAnswerObj = poDS->PUT(osURI, json_object_to_json_string(poDDocObj)); json_object_put(poDDocObj); json_object_put(poAnswerObj); }
OGRLayer * OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { CPLString osCommand; const char *pszGeomType = NULL; char *pszTableName = NULL; char *pszSchemaName = NULL; int nDimension = 3; int bHavePostGIS = TRUE; const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID"); CPLString osFIDColumnName, osFIDColumnNameEscaped; if (pszFIDColumnNameIn == NULL) osFIDColumnName = "ogc_fid"; else { if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) { char* pszLaunderedFid = OGRPGCommonLaunderName(pszFIDColumnNameIn, "PGDump"); osFIDColumnName = pszLaunderedFid; CPLFree(pszLaunderedFid); } else { osFIDColumnName = pszFIDColumnNameIn; } } osFIDColumnNameEscaped = OGRPGDumpEscapeColumnName(osFIDColumnName); if (strncmp(pszLayerName, "pg", 2) == 0) { CPLError(CE_Warning, CPLE_AppDefined, "The layer name should not begin by 'pg' as it is a reserved prefix"); } //bHavePostGIS = CSLFetchBoolean(papszOptions,"POSTGIS", TRUE); int bCreateTable = CSLFetchBoolean(papszOptions,"CREATE_TABLE", TRUE); int bCreateSchema = CSLFetchBoolean(papszOptions,"CREATE_SCHEMA", TRUE); const char* pszDropTable = CSLFetchNameValueDef(papszOptions,"DROP_TABLE", "IF_EXISTS"); if( wkbFlatten(eType) == eType ) nDimension = 2; if( CSLFetchNameValue( papszOptions, "DIM") != NULL ) nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM")); /* Should we turn layers with None geometry type as Unknown/GEOMETRY */ /* so they are still recorded in geometry_columns table ? (#4012) */ int bNoneAsUnknown = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "NONE_AS_UNKNOWN", "NO")); if (bNoneAsUnknown && eType == wkbNone) eType = wkbUnknown; else if (eType == wkbNone) bHavePostGIS = FALSE; int bExtractSchemaFromLayerName = CSLTestBoolean(CSLFetchNameValueDef( papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES")); /* Postgres Schema handling: Extract schema name from input layer name or passed with -lco SCHEMA. Set layer name to "schema.table" or to "table" if schema == current_schema() Usage without schema name is backwards compatible */ const char* pszDotPos = strstr(pszLayerName,"."); if ( pszDotPos != NULL && bExtractSchemaFromLayerName ) { int length = pszDotPos - pszLayerName; pszSchemaName = (char*)CPLMalloc(length+1); strncpy(pszSchemaName, pszLayerName, length); pszSchemaName[length] = '\0'; if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PGDump" ); //skip "." else pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "." } else { pszSchemaName = NULL; if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) pszTableName = OGRPGCommonLaunderName( pszLayerName, "PGDump" ); //skip "." else pszTableName = CPLStrdup( pszLayerName ); //skip "." } LogCommit(); /* -------------------------------------------------------------------- */ /* Set the default schema for the layers. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL ) { CPLFree(pszSchemaName); pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" )); if (bCreateSchema) { osCommand.Printf("CREATE SCHEMA \"%s\"", pszSchemaName); Log(osCommand); } } if ( pszSchemaName == NULL) { pszSchemaName = CPLStrdup("public"); } /* -------------------------------------------------------------------- */ /* Do we already have this layer? */ /* -------------------------------------------------------------------- */ int iLayer; for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) ) { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, CreateLayer failed.\n", pszLayerName ); CPLFree( pszTableName ); CPLFree( pszSchemaName ); return NULL; } } if (bCreateTable && (EQUAL(pszDropTable, "YES") || EQUAL(pszDropTable, "ON") || EQUAL(pszDropTable, "TRUE") || EQUAL(pszDropTable, "IF_EXISTS"))) { if (EQUAL(pszDropTable, "IF_EXISTS")) osCommand.Printf("DROP TABLE IF EXISTS \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName ); else osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName ); Log(osCommand); } /* -------------------------------------------------------------------- */ /* Handle the GEOM_TYPE option. */ /* -------------------------------------------------------------------- */ pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" ); if( pszGeomType == NULL ) { pszGeomType = "geometry"; } if( !EQUAL(pszGeomType,"geometry") && !EQUAL(pszGeomType, "geography")) { CPLError( CE_Failure, CPLE_AppDefined, "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or 'geography'.\n" "Creation of layer %s with GEOM_TYPE %s has failed.", pszLayerName, pszGeomType ); CPLFree( pszTableName ); CPLFree( pszSchemaName ); return NULL; } /* -------------------------------------------------------------------- */ /* Try to get the SRS Id of this spatial reference system, */ /* adding tot the srs table if needed. */ /* -------------------------------------------------------------------- */ int nUnknownSRSId = -1; const char* pszPostgisVersion = CSLFetchNameValue( papszOptions, "POSTGIS_VERSION" ); int bPostGIS2 = FALSE; if( pszPostgisVersion != NULL && atoi(pszPostgisVersion) >= 2 ) { bPostGIS2 = TRUE; nUnknownSRSId = 0; } int nSRSId = nUnknownSRSId; int nForcedSRSId = -2; if( CSLFetchNameValue( papszOptions, "SRID") != NULL ) { nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID")); nForcedSRSId = nSRSId; } else { if (poSRS) { const char* pszAuthorityName = poSRS->GetAuthorityName(NULL); if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) ) { /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */ nSRSId = atoi( poSRS->GetAuthorityCode(NULL) ); } else { const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS"); if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984")) nSRSId = 4326; } } } CPLString osEscapedTableNameSingleQuote = OGRPGDumpEscapeString(pszTableName); const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str(); const char *pszGeometryType = OGRToOGCGeomType(eType); const char *pszGFldName = NULL; if( bHavePostGIS && !EQUAL(pszGeomType, "geography")) { if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL ) pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME"); else pszGFldName = "wkb_geometry"; if( pszPostgisVersion == NULL || atoi(pszPostgisVersion) < 2 ) { /* Sometimes there is an old cruft entry in the geometry_columns * table if things were not properly cleaned up before. We make * an effort to clean out such cruft. * Note: PostGIS 2.0 defines geometry_columns as a view (no clean up is needed) */ osCommand.Printf( "DELETE FROM geometry_columns WHERE f_table_name = %s AND f_table_schema = '%s'", pszEscapedTableNameSingleQuote, pszSchemaName ); if (bCreateTable) Log(osCommand); } } LogStartTransaction(); /* -------------------------------------------------------------------- */ /* Create a basic table with the FID. Also include the */ /* geometry if this is not a PostGIS enabled table. */ /* -------------------------------------------------------------------- */ int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE); const char* pszSerialType = bFID64 ? "BIGSERIAL": "SERIAL"; CPLString osCreateTable; int bTemporary = CSLFetchBoolean( papszOptions, "TEMPORARY", FALSE ); if (bTemporary) { CPLFree(pszSchemaName); pszSchemaName = CPLStrdup("pg_temp_1"); osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName); } else osCreateTable.Printf("CREATE TABLE%s \"%s\".\"%s\"", CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) ? " UNLOGGED": "", pszSchemaName, pszTableName); if( !bHavePostGIS ) { if (eType == wkbNone) osCommand.Printf( "%s ( " " %s %s, " " CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() ); else osCommand.Printf( "%s ( " " %s %s, " " WKB_GEOMETRY %s, " " CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGeomType, pszTableName, osFIDColumnNameEscaped.c_str() ); } else if ( EQUAL(pszGeomType, "geography") ) { if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL ) pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME"); else pszGFldName = "the_geog"; if (nSRSId) osCommand.Printf( "%s ( %s %s, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName, osFIDColumnNameEscaped.c_str() ); else osCommand.Printf( "%s ( %s %s, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName, osFIDColumnNameEscaped.c_str() ); } else { osCommand.Printf( "%s ( %s %s, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() ); } if (bCreateTable) Log(osCommand); /* -------------------------------------------------------------------- */ /* Eventually we should be adding this table to a table of */ /* "geometric layers", capturing the WKT projection, and */ /* perhaps some other housekeeping. */ /* -------------------------------------------------------------------- */ if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography")) { osCommand.Printf( "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s',%d)", pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName, nSRSId, pszGeometryType, nDimension ); Log(osCommand); } const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" ); int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) ); if( bCreateTable && bHavePostGIS && bCreateSpatialIndex ) { /* -------------------------------------------------------------------- */ /* Create the spatial index. */ /* */ /* We're doing this before we add geometry and record to the table */ /* so this may not be exactly the best way to do it. */ /* -------------------------------------------------------------------- */ osCommand.Printf("CREATE INDEX \"%s_%s_geom_idx\" " "ON \"%s\".\"%s\" " "USING GIST (\"%s\")", pszTableName, pszGFldName, pszSchemaName, pszTableName, pszGFldName); Log(osCommand); } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRPGDumpLayer *poLayer; int bWriteAsHex = !CSLFetchBoolean(papszOptions,"WRITE_EWKT_GEOM",FALSE); poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszTableName, osFIDColumnName, bWriteAsHex, bCreateTable ); poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) ); poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE)); const char* pszOverrideColumnTypes = CSLFetchNameValue( papszOptions, "COLUMN_TYPES" ); poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes); poLayer->SetUnknownSRSId(nUnknownSRSId); poLayer->SetForcedSRSId(nForcedSRSId); poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex); poLayer->SetPostGIS2(bPostGIS2); if( bHavePostGIS ) { OGRGeomFieldDefn oTmp( pszGFldName, eType ); OGRPGDumpGeomFieldDefn *poGeomField = new OGRPGDumpGeomFieldDefn(&oTmp); poGeomField->nSRSId = nSRSId; poGeomField->nCoordDimension = nDimension; poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE); } /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRPGDumpLayer **) CPLRealloc( papoLayers, sizeof(OGRPGDumpLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; CPLFree( pszTableName ); CPLFree( pszSchemaName ); return poLayer; }
OGRErr OGRCARTODBTableLayer::RunDeferedCreationIfNecessary() { if( !bDeferedCreation ) return OGRERR_NONE; bDeferedCreation = FALSE; CPLString osSQL; osSQL.Printf("CREATE TABLE %s ( %s SERIAL,", OGRCARTODBEscapeIdentifier(osName).c_str(), osFIDColName.c_str()); int nSRID = 0; OGRwkbGeometryType eGType = GetGeomType(); if( eGType != wkbNone ) { CPLString osGeomType = OGRToOGCGeomType(eGType); if( wkbHasZ(eGType) ) osGeomType += "Z"; OGRCartoDBGeomFieldDefn *poFieldDefn = (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(0); nSRID = poFieldDefn->nSRID; osSQL += CPLSPrintf("%s GEOMETRY(%s, %d)%s, %s GEOMETRY(%s, %d),", "the_geom", osGeomType.c_str(), nSRID, (!poFieldDefn->IsNullable()) ? " NOT NULL" : "", "the_geom_webmercator", osGeomType.c_str(), 3857); } for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ ) { OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i); if( strcmp(poFieldDefn->GetNameRef(), osFIDColName) != 0 ) { osSQL += OGRCARTODBEscapeIdentifier(poFieldDefn->GetNameRef()); osSQL += " "; osSQL += OGRPGCommonLayerGetType(*poFieldDefn, FALSE, TRUE); if( !poFieldDefn->IsNullable() ) osSQL += " NOT NULL"; if( poFieldDefn->GetDefault() != NULL && !poFieldDefn->IsDefaultDriverSpecific() ) { osSQL += " DEFAULT "; osSQL += poFieldDefn->GetDefault(); } osSQL += ","; } } osSQL += CPLSPrintf("PRIMARY KEY (%s) )", osFIDColName.c_str()); CPLString osSeqName(OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str()))); osSQL += ";"; osSQL += CPLSPrintf("DROP SEQUENCE IF EXISTS %s CASCADE", osSeqName.c_str()); osSQL += ";"; osSQL += CPLSPrintf("CREATE SEQUENCE %s START 1", osSeqName.c_str()); osSQL += ";"; osSQL += CPLSPrintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT nextval('%s')", OGRCARTODBEscapeIdentifier(osName).c_str(), osFIDColName.c_str(), osSeqName.c_str()); json_object* poObj = poDS->RunSQL(osSQL); if( poObj == NULL ) return OGRERR_FAILURE; json_object_put(poObj); if( bCartoDBify ) { if( nSRID != 4326 ) { if( eGType != wkbNone ) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot register table in dashboard with " "cdb_cartodbfytable() since its SRS is not EPSG:4326"); } } else { if( poDS->GetCurrentSchema() == "public" ) osSQL.Printf("SELECT cdb_cartodbfytable('%s')", OGRCARTODBEscapeLiteral(osName).c_str()); else osSQL.Printf("SELECT cdb_cartodbfytable('%s', '%s')", OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(), OGRCARTODBEscapeLiteral(osName).c_str()); poObj = poDS->RunSQL(osSQL); if( poObj == NULL ) return OGRERR_FAILURE; json_object_put(poObj); } } return OGRERR_NONE; }
OGRLayer* OGRGeoPackageDataSource::CreateLayer( const char * pszLayerName, OGRSpatialReference * poSpatialRef, OGRwkbGeometryType eGType, char **papszOptions ) { int iLayer; OGRErr err; if( !m_bUpdate ) return NULL; /* Read GEOMETRY_COLUMN option */ const char* pszGeomColumnName = CSLFetchNameValue(papszOptions, "GEOMETRY_COLUMN"); if (pszGeomColumnName == NULL) pszGeomColumnName = "geom"; /* Read FID option */ const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID"); if (pszFIDColumnName == NULL) pszFIDColumnName = "fid"; if ( strspn(pszFIDColumnName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "The primary key (%s) name may not contain special characters or spaces", pszFIDColumnName); return NULL; } /* Avoiding gpkg prefixes is not an official requirement, but seems wise */ if (strncmp(pszLayerName, "gpkg", 4) == 0) { CPLError(CE_Failure, CPLE_AppDefined, "The layer name may not begin with 'gpkg' as it is a reserved geopackage prefix"); return NULL; } /* Pre-emptively try and avoid sqlite3 syntax errors due to */ /* illegal characters */ if ( strspn(pszLayerName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "The layer name may not contain special characters or spaces"); return NULL; } /* Check for any existing layers that already use this name */ for( iLayer = 0; iLayer < m_nLayers; iLayer++ ) { if( EQUAL(pszLayerName, m_papoLayers[iLayer]->GetName()) ) { const char *pszOverwrite = CSLFetchNameValue(papszOptions,"OVERWRITE"); if( pszOverwrite != NULL && CSLTestBoolean(pszOverwrite) ) { DeleteLayer( iLayer ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, CreateLayer failed.\n" "Use the layer creation option OVERWRITE=YES to " "replace it.", pszLayerName ); return NULL; } } } /* Read our SRS_ID from the OGRSpatialReference */ int nSRSId = UNDEFINED_SRID; if( poSpatialRef != NULL ) nSRSId = GetSrsId( poSpatialRef ); /* Requirement 25: The geometry_type_name value in a gpkg_geometry_columns */ /* row SHALL be one of the uppercase geometry type names specified in */ /* Geometry Types (Normative). */ const char *pszGeometryType = OGRToOGCGeomType(eGType); /* Create the table! */ char *pszSQL = NULL; if ( eGType != wkbNone ) { pszSQL = sqlite3_mprintf( "CREATE TABLE %s ( " "%s INTEGER PRIMARY KEY AUTOINCREMENT, " "%s %s )", pszLayerName, pszFIDColumnName, pszGeomColumnName, pszGeometryType); } else { pszSQL = sqlite3_mprintf( "CREATE TABLE %s ( " "%s INTEGER PRIMARY KEY AUTOINCREMENT )", pszLayerName, pszFIDColumnName); } err = SQLCommand(m_poDb, pszSQL); sqlite3_free(pszSQL); if ( OGRERR_NONE != err ) return NULL; /* Only spatial tables need to be registered in the metadata (hmmm) */ if ( eGType != wkbNone ) { /* Requirement 27: The z value in a gpkg_geometry_columns table row */ /* SHALL be one of 0 (none), 1 (mandatory), or 2 (optional) */ int bGeometryTypeHasZ = (wkb25DBit & eGType) != 0; /* Update gpkg_geometry_columns with the table info */ pszSQL = sqlite3_mprintf( "INSERT INTO gpkg_geometry_columns " "(table_name,column_name,geometry_type_name,srs_id,z,m)" " VALUES " "('%q','%q','%q',%d,%d,%d)", pszLayerName,pszGeomColumnName,pszGeometryType, nSRSId,bGeometryTypeHasZ,0); err = SQLCommand(m_poDb, pszSQL); sqlite3_free(pszSQL); if ( err != OGRERR_NONE ) return NULL; /* Update gpkg_contents with the table info */ pszSQL = sqlite3_mprintf( "INSERT INTO gpkg_contents " "(table_name,data_type,identifier,last_change,srs_id)" " VALUES " "('%q','features','%q',strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',CURRENT_TIMESTAMP),%d)", pszLayerName, pszLayerName, nSRSId); err = SQLCommand(m_poDb, pszSQL); sqlite3_free(pszSQL); if ( err != OGRERR_NONE ) return NULL; } /* This is where spatial index logic will go in the future */ const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" ); int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) ); if( eGType != wkbNone && bCreateSpatialIndex ) { /* This is where spatial index logic will go in the future */ } /* The database is now all set up, so create a blank layer and read in the */ /* info from the database. */ OGRGeoPackageLayer *poLayer = new OGRGeoPackageLayer(this, pszLayerName); if( OGRERR_NONE != poLayer->ReadTableDefinition() ) { delete poLayer; return NULL; } m_papoLayers = (OGRLayer**)CPLRealloc(m_papoLayers, sizeof(OGRGeoPackageLayer*) * (m_nLayers+1)); m_papoLayers[m_nLayers++] = poLayer; return poLayer; }
static int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer, int iGeomCol, const LayerDesc& oLayerDesc, const CPLString& osTableName, OGRSQLiteDataSource* poSQLiteDS, sqlite3* hDB, int bSpatialiteDB, const std::set<LayerDesc>& WHEN_SPATIALITE(oSetLayers), const std::set<CPLString>& WHEN_SPATIALITE(oSetSpatialIndex) ) { OGRGeomFieldDefn* poGeomField = poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol); CPLString osGeomColRaw; if( iGeomCol == 0 ) osGeomColRaw = OGR2SQLITE_GetNameForGeometryColumn(poLayer); else osGeomColRaw = poGeomField->GetNameRef(); const char* pszGeomColRaw = osGeomColRaw.c_str(); CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw)); const char* pszGeomColEscaped = osGeomColEscaped.c_str(); CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName)); const char* pszLayerNameEscaped = osLayerNameEscaped.c_str(); CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s", oLayerDesc.osLayerName.c_str(), pszGeomColRaw)); CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw)); /* Make sure that the SRS is injected in spatial_ref_sys */ OGRSpatialReference* poSRS = poGeomField->GetSpatialRef(); if( iGeomCol == 0 && poSRS == NULL ) poSRS = poLayer->GetSpatialRef(); int nSRSId = poSQLiteDS->GetUndefinedSRID(); if( poSRS != NULL ) nSRSId = poSQLiteDS->FetchSRSId(poSRS); CPLString osSQL; #ifdef HAVE_SPATIALITE bool bCreateSpatialIndex = false; #endif if( !bSpatialiteDB ) { osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_format, geometry_type, " "coord_dimension, srid) " "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)", pszLayerNameEscaped, pszGeomColEscaped, (int) wkbFlatten(poLayer->GetGeomType()), wkbHasZ( poLayer->GetGeomType() ) ? 3 : 2, nSRSId); } #ifdef HAVE_SPATIALITE else { /* We detect the need for creating a spatial index by 2 means : */ /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */ /* table in the SQL --> old/traditional way of requesting spatial indices */ /* with spatialite. */ std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin(); for(; oIter2 != oSetLayers.end(); ++oIter2) { const LayerDesc& oLayerDescIter = *oIter2; if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) ) { bCreateSpatialIndex = true; break; } } /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */ if( !bCreateSpatialIndex ) { std::set<CPLString>::const_iterator oIter3 = oSetSpatialIndex.begin(); for(; oIter3 != oSetSpatialIndex.end(); ++oIter3) { const CPLString& osNameIter = *oIter3; if( EQUAL(osNameIter, oLayerDesc.osLayerName) ) { bCreateSpatialIndex = true; break; } } } if( poSQLiteDS->HasSpatialite4Layout() ) { int nGeomType = poLayer->GetGeomType(); int nCoordDimension = 2; if( wkbHasZ((OGRwkbGeometryType)nGeomType) ) { nGeomType += 1000; nCoordDimension = 3; } osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES (Lower('%s'),Lower('%s'),%d ,%d ,%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, nGeomType, nCoordDimension, nSRSId, static_cast<int>(bCreateSpatialIndex) ); } else { const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType()); if (pszGeometryType[0] == '\0') pszGeometryType = "GEOMETRY"; osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES ('%s','%s','%s','%s',%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, pszGeometryType, wkbHasZ( poLayer->GetGeomType() ) ? "XYZ" : "XY", nSRSId, static_cast<int>(bCreateSpatialIndex) ); } } #endif // HAVE_SPATIALITE char* pszErrMsg = NULL; int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg ); if( pszErrMsg != NULL ) { CPLDebug("SQLITE", "%s -> %s", osSQL.c_str(), pszErrMsg); sqlite3_free(pszErrMsg); } #ifdef HAVE_SPATIALITE /* -------------------------------------------------------------------- */ /* Should we create a spatial index ?. */ /* -------------------------------------------------------------------- */ if( !bSpatialiteDB || !bCreateSpatialIndex ) return rc == SQLITE_OK; CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str()); /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */ #ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING " "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str(), nExtraDS, OGRSQLiteEscape(oLayerDesc.osLayerName).c_str()); rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); if( rc != SQLITE_OK ) { CPLDebug( "SQLITE", "Error occurred during spatial index creation : %s", sqlite3_errmsg(hDB)); } #else // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL ); osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" " "USING rtree(pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str()); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); sqlite3_stmt *hStmt = NULL; if( rc == SQLITE_OK ) { const char* pszInsertInto = CPLSPrintf( "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) " "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str()); rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL); } OGRFeature* poFeature; OGREnvelope sEnvelope; OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer); poLayer->ResetReading(); while( rc == SQLITE_OK && (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL && !poGeom->IsEmpty() ) { poGeom->getEnvelope(&sEnvelope); sqlite3_bind_int64(hStmt, 1, (sqlite3_int64) poFeature->GetFID() ); sqlite3_bind_double(hStmt, 2, sEnvelope.MinX); sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX); sqlite3_bind_double(hStmt, 4, sEnvelope.MinY); sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY); rc = sqlite3_step(hStmt); if( rc == SQLITE_OK || rc == SQLITE_DONE ) rc = sqlite3_reset(hStmt); } delete poFeature; } poLayer->SetIgnoredFields(NULL); sqlite3_finalize(hStmt); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL ); else { CPLDebug( "SQLITE", "Error occurred during spatial index creation : %s", sqlite3_errmsg(hDB)); rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL ); } #endif // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX #endif // HAVE_SPATIALITE return rc == SQLITE_OK; }
OGRLayer * OGRPGDumpDataSource::CreateLayer( const char * pszLayerNameIn, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions ) { CPLString osCommand; const char *pszGeomType = NULL; char *pszLayerName = NULL; const char *pszTableName = NULL; char *pszSchemaName = NULL; int nDimension = 3; const char *pszFIDColumn = "OGC_FID"; int bHavePostGIS = TRUE; if (pszLayerNameIn == NULL) return NULL; if (strncmp(pszLayerNameIn, "pg", 2) == 0) { CPLError(CE_Warning, CPLE_AppDefined, "The layer name should not begin by 'pg' as it is a reserved prefix"); } //bHavePostGIS = CSLFetchBoolean(papszOptions,"POSTGIS", TRUE); if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) { pszLayerName = LaunderName( pszLayerNameIn ); } else pszLayerName = CPLStrdup( pszLayerNameIn ); int bCreateTable = CSLFetchBoolean(papszOptions,"CREATE_TABLE", TRUE); if (eType == wkbNone) bHavePostGIS = FALSE; else if( wkbFlatten(eType) == eType ) nDimension = 2; if( CSLFetchNameValue( papszOptions, "DIM") != NULL ) nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM")); /* Postgres Schema handling: Extract schema name from input layer name or passed with -lco SCHEMA. Set layer name to "schema.table" or to "table" if schema == current_schema() Usage without schema name is backwards compatible */ pszTableName = strstr(pszLayerName,"."); if ( pszTableName != NULL ) { int length = pszTableName - pszLayerName; pszSchemaName = (char*)CPLMalloc(length+1); strncpy(pszSchemaName, pszLayerName, length); pszSchemaName[length] = '\0'; ++pszTableName; //skip "." } else { pszSchemaName = NULL; pszTableName = pszLayerName; } Commit(); /* -------------------------------------------------------------------- */ /* Set the default schema for the layers. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL ) { CPLFree(pszSchemaName); pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" )); osCommand.Printf("CREATE SCHEMA \"%s\"", pszSchemaName); Log(osCommand); } if ( pszSchemaName == NULL) { pszSchemaName = CPLStrdup("public"); } /* -------------------------------------------------------------------- */ /* Do we already have this layer? */ /* -------------------------------------------------------------------- */ int iLayer; for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) ) { CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, CreateLayer failed.\n", pszLayerName ); CPLFree( pszLayerName ); CPLFree( pszSchemaName ); return NULL; } } if (bCreateTable) { osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName ); Log(osCommand); } /* -------------------------------------------------------------------- */ /* Handle the GEOM_TYPE option. */ /* -------------------------------------------------------------------- */ pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" ); if( pszGeomType == NULL ) { pszGeomType = "geometry"; } if( !EQUAL(pszGeomType,"geometry") && !EQUAL(pszGeomType, "geography")) { CPLError( CE_Failure, CPLE_AppDefined, "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or 'geography'.\n" "Creation of layer %s with GEOM_TYPE %s has failed.", pszLayerName, pszGeomType ); CPLFree( pszLayerName ); CPLFree( pszSchemaName ); return NULL; } /* -------------------------------------------------------------------- */ /* Try to get the SRS Id of this spatial reference system, */ /* adding tot the srs table if needed. */ /* -------------------------------------------------------------------- */ int nSRSId = -1; if( CSLFetchNameValue( papszOptions, "SRID") != NULL ) nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID")); else { if (poSRS) { const char* pszAuthorityName = poSRS->GetAuthorityName(NULL); if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) ) { /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */ nSRSId = atoi( poSRS->GetAuthorityCode(NULL) ); } else { const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS"); if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984")) nSRSId = 4326; } } } const char *pszGeometryType = OGRToOGCGeomType(eType); const char *pszGFldName = NULL; if( bHavePostGIS && !EQUAL(pszGeomType, "geography")) { if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL ) pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME"); else pszGFldName = "wkb_geometry"; /* Sometimes there is an old cruft entry in the geometry_columns * table if things were not properly cleaned up before. We make * an effort to clean out such cruft. */ osCommand.Printf( "DELETE FROM geometry_columns WHERE f_table_name = '%s' AND f_table_schema = '%s'", pszTableName, pszSchemaName ); if (bCreateTable) Log(osCommand); } StartTransaction(); /* -------------------------------------------------------------------- */ /* Create a basic table with the FID. Also include the */ /* geometry if this is not a PostGIS enabled table. */ /* -------------------------------------------------------------------- */ CPLString osCreateTable; int bTemporary = CSLFetchNameValue( papszOptions, "TEMPORARY" ) != NULL && CSLTestBoolean(CSLFetchNameValue( papszOptions, "TEMPORARY" )); if (bTemporary) { CPLFree(pszSchemaName); pszSchemaName = CPLStrdup("pg_temp_1"); osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName); } else osCreateTable.Printf("CREATE TABLE \"%s\".\"%s\"", pszSchemaName, pszTableName); if( !bHavePostGIS ) { if (eType == wkbNone) osCommand.Printf( "%s ( " " %s SERIAL, " " CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), pszFIDColumn, pszTableName, pszFIDColumn ); else osCommand.Printf( "%s ( " " %s SERIAL, " " WKB_GEOMETRY %s, " " CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), pszFIDColumn, pszGeomType, pszTableName, pszFIDColumn ); } else if ( EQUAL(pszGeomType, "geography") ) { if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL ) pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME"); else pszGFldName = "the_geog"; if (nSRSId) osCommand.Printf( "%s ( %s SERIAL, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), pszFIDColumn, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName, pszFIDColumn ); else osCommand.Printf( "%s ( %s SERIAL, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), pszFIDColumn, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName, pszFIDColumn ); } else { osCommand.Printf( "%s ( %s SERIAL, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )", osCreateTable.c_str(), pszFIDColumn, pszTableName, pszFIDColumn ); } if (bCreateTable) Log(osCommand); /* -------------------------------------------------------------------- */ /* Eventually we should be adding this table to a table of */ /* "geometric layers", capturing the WKT projection, and */ /* perhaps some other housekeeping. */ /* -------------------------------------------------------------------- */ if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography")) { osCommand.Printf( "SELECT AddGeometryColumn('%s','%s','%s',%d,'%s',%d)", pszSchemaName, pszTableName, pszGFldName, nSRSId, pszGeometryType, nDimension ); Log(osCommand); } if( bCreateTable && bHavePostGIS ) { /* -------------------------------------------------------------------- */ /* Create the spatial index. */ /* */ /* We're doing this before we add geometry and record to the table */ /* so this may not be exactly the best way to do it. */ /* -------------------------------------------------------------------- */ const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" ); if( pszSI == NULL || CSLTestBoolean(pszSI) ) { osCommand.Printf("CREATE INDEX \"%s_geom_idx\" " "ON \"%s\".\"%s\" " "USING GIST (\"%s\")", pszTableName, pszSchemaName, pszTableName, pszGFldName); Log(osCommand); } } /* -------------------------------------------------------------------- */ /* Create the layer object. */ /* -------------------------------------------------------------------- */ OGRPGDumpLayer *poLayer; int bWriteAsHex = !CSLFetchBoolean(papszOptions,"WRITE_EWKT_GEOM",FALSE); poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszLayerName, pszGFldName, pszFIDColumn, nDimension, nSRSId, bWriteAsHex, bCreateTable ); poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) ); poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE)); /* -------------------------------------------------------------------- */ /* Add layer to data source layer list. */ /* -------------------------------------------------------------------- */ papoLayers = (OGRPGDumpLayer **) CPLRealloc( papoLayers, sizeof(OGRPGDumpLayer *) * (nLayers+1) ); papoLayers[nLayers++] = poLayer; CPLFree( pszLayerName ); CPLFree( pszSchemaName ); return poLayer; }
CPLXMLNode *GMLFeatureClass::SerializeToXML() { CPLXMLNode *psRoot; int iProperty; /* -------------------------------------------------------------------- */ /* Set feature class and core information. */ /* -------------------------------------------------------------------- */ psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" ); CPLCreateXMLElementAndValue( psRoot, "Name", GetName() ); CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() ); if( m_nGeometryPropertyCount > 1 ) { for(int i=0; i < m_nGeometryPropertyCount; i++) { GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[i]; CPLXMLNode *psPDefnNode; psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "GeomPropertyDefn" ); if( strlen(poGeomFDefn->GetName()) > 0 ) CPLCreateXMLElementAndValue( psPDefnNode, "Name", poGeomFDefn->GetName() ); if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 ) CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", poGeomFDefn->GetSrcElement() ); if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ ) { char szValue[128]; OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType(); CPLString osStr(OGRToOGCGeomType(eType)); if( wkbHasZ(eType) ) osStr += "Z"; CPLCreateXMLNode( psPDefnNode, CXT_Comment, osStr.c_str() ); sprintf( szValue, "%d", eType ); CPLCreateXMLElementAndValue( psPDefnNode, "Type", szValue ); } } } else if( m_nGeometryPropertyCount == 1 ) { GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[0]; if( strlen(poGeomFDefn->GetName()) > 0 ) CPLCreateXMLElementAndValue( psRoot, "GeometryName", poGeomFDefn->GetName() ); if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 ) CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", poGeomFDefn->GetSrcElement() ); if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ ) { char szValue[128]; OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType(); CPLString osStr(OGRToOGCGeomType(eType)); if( wkbHasZ(eType) ) osStr += "Z"; CPLCreateXMLNode( psRoot, CXT_Comment, osStr.c_str() ); sprintf( szValue, "%d", eType ); CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue ); } } else { CPLCreateXMLElementAndValue( psRoot, "GeometryType", "100" ); } const char* pszSRSName = GetSRSName(); if( pszSRSName ) { CPLCreateXMLElementAndValue( psRoot, "SRSName", pszSRSName ); } /* -------------------------------------------------------------------- */ /* Write out dataset specific information. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDSI; if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL ) { psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" ); if( m_nFeatureCount != -1 ) { char szValue[128]; sprintf( szValue, CPL_FRMT_GIB, m_nFeatureCount ); CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue ); } if( m_bHaveExtents && fabs(m_dfXMin) < 1e100 && fabs(m_dfXMax) < 1e100 && fabs(m_dfYMin) < 1e100 && fabs(m_dfYMax) < 1e100 ) { char szValue[128]; CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMin ); CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue ); CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMax ); CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue ); CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMin ); CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue ); CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMax ); CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue ); } if( m_pszExtraInfo ) CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo ); } /* -------------------------------------------------------------------- */ /* emit property information. */ /* -------------------------------------------------------------------- */ for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ ) { GMLPropertyDefn *poPDefn = GetProperty( iProperty ); CPLXMLNode *psPDefnNode; const char *pszTypeName = "Unknown"; psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" ); CPLCreateXMLElementAndValue( psPDefnNode, "Name", poPDefn->GetName() ); CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", poPDefn->GetSrcElement() ); switch( poPDefn->GetType() ) { case GMLPT_Untyped: pszTypeName = "Untyped"; break; case GMLPT_String: case GMLPT_Boolean: pszTypeName = "String"; break; case GMLPT_Integer: case GMLPT_Short: case GMLPT_Integer64: pszTypeName = "Integer"; break; case GMLPT_Real: case GMLPT_Float: pszTypeName = "Real"; break; case GMLPT_Complex: pszTypeName = "Complex"; break; case GMLPT_IntegerList: case GMLPT_Integer64List: pszTypeName = "IntegerList"; break; case GMLPT_RealList: pszTypeName = "RealList"; break; case GMLPT_StringList: case GMLPT_BooleanList: pszTypeName = "StringList"; break; /* should not happen in practise for now because this is not */ /* autodetected */ case GMLPT_FeatureProperty: pszTypeName = "FeatureProperty"; break; /* should not happen in practise for now because this is not */ /* autodetected */ case GMLPT_FeaturePropertyList: pszTypeName = "FeaturePropertyList"; break; } CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName ); if( poPDefn->GetType() == GMLPT_Boolean || poPDefn->GetType() == GMLPT_BooleanList ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Boolean" ); else if( poPDefn->GetType() == GMLPT_Short ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Short" ); else if( poPDefn->GetType() == GMLPT_Float ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Float" ); else if( poPDefn->GetType() == GMLPT_Integer64 || poPDefn->GetType() == GMLPT_Integer64List ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Integer64" ); if( EQUAL(pszTypeName,"String") ) { char szMaxLength[48]; sprintf(szMaxLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength ); } if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") ) { char szLength[48]; sprintf(szLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength ); } if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") ) { char szLength[48]; sprintf(szLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength ); char szPrecision[48]; sprintf(szPrecision, "%d", poPDefn->GetPrecision()); CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision ); } } return psRoot; }
OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS, const char *pszStatement, OGRGeometry *poSpatialFilter, const char *pszDialect ) { char* pszTmpDBName = (char*) CPLMalloc(256); sprintf(pszTmpDBName, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName); OGRSQLiteDataSource* poSQLiteDS = NULL; int nRet; int bSpatialiteDB = FALSE; CPLString osOldVal; const char* pszOldVal = CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", NULL); if( pszOldVal != NULL ) { osOldVal = pszOldVal; pszOldVal = osOldVal.c_str(); } /* -------------------------------------------------------------------- */ /* Create in-memory sqlite/spatialite DB */ /* -------------------------------------------------------------------- */ #ifdef HAVE_SPATIALITE /* -------------------------------------------------------------------- */ /* Creating an empty spatialite DB (with spatial_ref_sys populated */ /* has a non-neglectable cost. So at the first attempt, let's make */ /* one and cache it for later use. */ /* -------------------------------------------------------------------- */ #if 1 static vsi_l_offset nEmptyDBSize = 0; static GByte* pabyEmptyDB = NULL; { static void* hMutex = NULL; CPLMutexHolder oMutexHolder(&hMutex); static int bTried = FALSE; if( !bTried && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) ) { bTried = TRUE; char* pszCachedFilename = (char*) CPLMalloc(256); sprintf(pszCachedFilename, "/vsimem/ogr2sqlite/reference_%p.db",pszCachedFilename); char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES"); OGRSQLiteDataSource* poCachedDS = new OGRSQLiteDataSource(); nRet = poCachedDS->Create( pszCachedFilename, papszOptions ); CSLDestroy(papszOptions); papszOptions = NULL; delete poCachedDS; if( nRet ) /* Note: the reference file keeps the ownership of the data, so that */ /* it gets released with VSICleanupFileManager() */ pabyEmptyDB = VSIGetMemFileBuffer( pszCachedFilename, &nEmptyDBSize, FALSE ); CPLFree( pszCachedFilename ); } } /* The following configuration option is usefull mostly for debugging/testing */ if( pabyEmptyDB != NULL && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) ) { GByte* pabyEmptyDBClone = (GByte*)VSIMalloc(nEmptyDBSize); if( pabyEmptyDBClone == NULL ) { CPLFree(pszTmpDBName); return NULL; } memcpy(pabyEmptyDBClone, pabyEmptyDB, nEmptyDBSize); VSIFCloseL(VSIFileFromMemBuffer( pszTmpDBName, pabyEmptyDBClone, nEmptyDBSize, TRUE )); poSQLiteDS = new OGRSQLiteDataSource(); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO"); nRet = poSQLiteDS->Open( pszTmpDBName, TRUE ); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal); if( !nRet ) { /* should not happen really ! */ delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } bSpatialiteDB = TRUE; } #else /* No caching version */ poSQLiteDS = new OGRSQLiteDataSource(); char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES"); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO"); nRet = poSQLiteDS->Create( pszTmpDBName, papszOptions ); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal); CSLDestroy(papszOptions); papszOptions = NULL; if( nRet ) { bSpatialiteDB = TRUE; } #endif else { delete poSQLiteDS; poSQLiteDS = NULL; #else // HAVE_SPATIALITE if( TRUE ) { #endif // HAVE_SPATIALITE poSQLiteDS = new OGRSQLiteDataSource(); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO"); nRet = poSQLiteDS->Create( pszTmpDBName, NULL ); CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal); if( !nRet ) { delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } } /* -------------------------------------------------------------------- */ /* Attach the Virtual Table OGR2SQLITE module to it. */ /* -------------------------------------------------------------------- */ OGR2SQLITEModule* poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS); sqlite3* hDB = poSQLiteDS->GetDB(); /* -------------------------------------------------------------------- */ /* Analysze the statement to determine which tables will be used. */ /* -------------------------------------------------------------------- */ std::set<LayerDesc> oSetLayers; std::set<CPLString> oSetSpatialIndex; CPLString osModifiedSQL; OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex, osModifiedSQL); std::set<LayerDesc>::iterator oIter = oSetLayers.begin(); if( strcmp(pszStatement, osModifiedSQL.c_str()) != 0 ) CPLDebug("OGR", "Modified SQL: %s", osModifiedSQL.c_str()); pszStatement = osModifiedSQL.c_str(); /* do not use it anymore */ int bFoundOGRStyle = ( osModifiedSQL.ifind("OGR_STYLE") != std::string::npos ); /* -------------------------------------------------------------------- */ /* For each of those tables, create a Virtual Table. */ /* -------------------------------------------------------------------- */ for(; oIter != oSetLayers.end(); ++oIter) { const LayerDesc& oLayerDesc = *oIter; /*CPLDebug("OGR", "Layer desc : %s, %s, %s, %s", oLayerDesc.osOriginalStr.c_str(), oLayerDesc.osSubstitutedName.c_str(), oLayerDesc.osDSName.c_str(), oLayerDesc.osLayerName.c_str());*/ CPLString osSQL; OGRLayer* poLayer = NULL; CPLString osTableName; int nExtraDS; if( oLayerDesc.osDSName.size() == 0 ) { poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName); /* Might be a false positive (unlikely) */ if( poLayer == NULL ) continue; osTableName = oLayerDesc.osLayerName; nExtraDS = -1; osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)", OGRSQLiteEscapeName(osTableName).c_str(), nExtraDS, OGRSQLiteEscape(osTableName).c_str(), bFoundOGRStyle); } else { OGRDataSource* poOtherDS = (OGRDataSource* ) OGROpen(oLayerDesc.osDSName, FALSE, NULL); if( poOtherDS == NULL ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot open datasource '%s'", oLayerDesc.osDSName.c_str() ); delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName); if( poLayer == NULL ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find layer '%s' in '%s'", oLayerDesc.osLayerName.c_str(), oLayerDesc.osDSName.c_str() ); delete poOtherDS; delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } osTableName = oLayerDesc.osSubstitutedName; nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS); osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)", OGRSQLiteEscapeName(osTableName).c_str(), nExtraDS, OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(), bFoundOGRStyle); } char* pszErrMsg = NULL; int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg ); if( rc != SQLITE_OK ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot create virtual table for layer '%s' : %s", osTableName.c_str(), pszErrMsg); sqlite3_free(pszErrMsg); continue; } if( poLayer->GetGeomType() == wkbNone ) continue; CPLString osGeomColRaw(OGR2SQLITE_GetNameForGeometryColumn(poLayer)); const char* pszGeomColRaw = osGeomColRaw.c_str(); CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw)); const char* pszGeomColEscaped = osGeomColEscaped.c_str(); CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName)); const char* pszLayerNameEscaped = osLayerNameEscaped.c_str(); CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s", oLayerDesc.osLayerName.c_str(), pszGeomColRaw)); CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw)); /* Make sure that the SRS is injected in spatial_ref_sys */ OGRSpatialReference* poSRS = poLayer->GetSpatialRef(); int nSRSId = poSQLiteDS->GetUndefinedSRID(); if( poSRS != NULL ) nSRSId = poSQLiteDS->FetchSRSId(poSRS); int bCreateSpatialIndex = FALSE; if( !bSpatialiteDB ) { osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_format, geometry_type, " "coord_dimension, srid) " "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)", pszLayerNameEscaped, pszGeomColEscaped, (int) wkbFlatten(poLayer->GetGeomType()), ( poLayer->GetGeomType() & wkb25DBit ) ? 3 : 2, nSRSId); } #ifdef HAVE_SPATIALITE else { /* We detect the need for creating a spatial index by 2 means : */ /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */ /* table in the SQL --> old/traditionnal way of requesting spatial indices */ /* with spatialite. */ std::set<LayerDesc>::iterator oIter2 = oSetLayers.begin(); for(; oIter2 != oSetLayers.end(); ++oIter2) { const LayerDesc& oLayerDescIter = *oIter2; if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) ) { bCreateSpatialIndex = TRUE; break; } } /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */ if( !bCreateSpatialIndex ) { std::set<CPLString>::iterator oIter3 = oSetSpatialIndex.begin(); for(; oIter3 != oSetSpatialIndex.end(); ++oIter3) { const CPLString& osNameIter = *oIter3; if( EQUAL(osNameIter, oLayerDesc.osLayerName) ) { bCreateSpatialIndex = TRUE; break; } } } if( poSQLiteDS->HasSpatialite4Layout() ) { int nGeomType = poLayer->GetGeomType(); int nCoordDimension = 2; if( nGeomType & wkb25DBit ) { nGeomType += 1000; nCoordDimension = 3; } osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, geometry_type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES ('%s',Lower('%s'),%d ,%d ,%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, nGeomType, nCoordDimension, nSRSId, bCreateSpatialIndex ); } else { const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType()); if (pszGeometryType[0] == '\0') pszGeometryType = "GEOMETRY"; osSQL.Printf("INSERT INTO geometry_columns (f_table_name, " "f_geometry_column, type, coord_dimension, " "srid, spatial_index_enabled) " "VALUES ('%s','%s','%s','%s',%d, %d)", pszLayerNameEscaped, pszGeomColEscaped, pszGeometryType, ( poLayer->GetGeomType() & wkb25DBit ) ? "XYZ" : "XY", nSRSId, bCreateSpatialIndex ); } } #endif // HAVE_SPATIALITE sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); #ifdef HAVE_SPATIALITE /* -------------------------------------------------------------------- */ /* Should we create a spatial index ?. */ /* -------------------------------------------------------------------- */ if( !bSpatialiteDB || !bCreateSpatialIndex ) continue; CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str()); /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */ #ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING " "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str(), nExtraDS, OGRSQLiteEscape(oLayerDesc.osLayerName).c_str()); rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); if( rc != SQLITE_OK ) { CPLDebug("SQLITE", "Error occured during spatial index creation : %s", sqlite3_errmsg(hDB)); } #else // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL ); osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" " "USING rtree(pkid, xmin, xmax, ymin, ymax)", osIdxNameEscaped.c_str()); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL ); sqlite3_stmt *hStmt = NULL; if( rc == SQLITE_OK ) { const char* pszInsertInto = CPLSPrintf( "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) " "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str()); rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL); } OGRFeature* poFeature; OGREnvelope sEnvelope; OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer); poLayer->ResetReading(); while( rc == SQLITE_OK && (poFeature = poLayer->GetNextFeature()) != NULL ) { OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL && !poGeom->IsEmpty() ) { poGeom->getEnvelope(&sEnvelope); sqlite3_bind_int64(hStmt, 1, (sqlite3_int64) poFeature->GetFID() ); sqlite3_bind_double(hStmt, 2, sEnvelope.MinX); sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX); sqlite3_bind_double(hStmt, 4, sEnvelope.MinY); sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY); rc = sqlite3_step(hStmt); if( rc == SQLITE_OK || rc == SQLITE_DONE ) rc = sqlite3_reset(hStmt); } delete poFeature; } poLayer->SetIgnoredFields(NULL); sqlite3_finalize(hStmt); if( rc == SQLITE_OK ) rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL ); else { CPLDebug("SQLITE", "Error occured during spatial index creation : %s", sqlite3_errmsg(hDB)); rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL ); } #endif // ENABLE_VIRTUAL_OGR_SPATIAL_INDEX #endif // HAVE_SPATIALITE } /* -------------------------------------------------------------------- */ /* Reload, so that virtual tables are recognized */ /* -------------------------------------------------------------------- */ poSQLiteDS->ReloadLayers(); /* -------------------------------------------------------------------- */ /* Prepare the statement. */ /* -------------------------------------------------------------------- */ /* This will speed-up layer creation */ /* ORDER BY are costly to evaluate and are not necessary to establish */ /* the layer definition. */ int bUseStatementForGetNextFeature = TRUE; int bEmptyLayer = FALSE; sqlite3_stmt *hSQLStmt = NULL; int rc = sqlite3_prepare( hDB, pszStatement, strlen(pszStatement), &hSQLStmt, NULL ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "In ExecuteSQL(): sqlite3_prepare(%s):\n %s", pszStatement, sqlite3_errmsg(hDB) ); if( hSQLStmt != NULL ) { sqlite3_finalize( hSQLStmt ); } delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } /* -------------------------------------------------------------------- */ /* Do we get a resultset? */ /* -------------------------------------------------------------------- */ rc = sqlite3_step( hSQLStmt ); if( rc != SQLITE_ROW ) { if ( rc != SQLITE_DONE ) { CPLError( CE_Failure, CPLE_AppDefined, "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszStatement, sqlite3_errmsg(hDB) ); sqlite3_finalize( hSQLStmt ); delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } if( !EQUALN(pszStatement, "SELECT ", 7) ) { sqlite3_finalize( hSQLStmt ); delete poSQLiteDS; VSIUnlink(pszTmpDBName); CPLFree(pszTmpDBName); return NULL; } bUseStatementForGetNextFeature = FALSE; bEmptyLayer = TRUE; } /* -------------------------------------------------------------------- */ /* Create layer. */ /* -------------------------------------------------------------------- */ OGRSQLiteSelectLayer *poLayer = NULL; poLayer = new OGRSQLiteExecuteSQLLayer( pszTmpDBName, poSQLiteDS, pszStatement, hSQLStmt, bUseStatementForGetNextFeature, bEmptyLayer ); if( poSpatialFilter != NULL ) poLayer->SetSpatialFilter( poSpatialFilter ); return poLayer; } /************************************************************************/ /* OGRSQLiteGetReferencedLayers() */ /************************************************************************/ std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement) { /* -------------------------------------------------------------------- */ /* Analysze the statement to determine which tables will be used. */ /* -------------------------------------------------------------------- */ std::set<LayerDesc> oSetLayers; std::set<CPLString> oSetSpatialIndex; CPLString osModifiedSQL; OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers, oSetSpatialIndex, osModifiedSQL); return oSetLayers; }