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; } } } CPLString osName(pszName); if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) ) { char* pszTmp = OGRPGCommonLaunderName(pszName); osName = pszTmp; CPLFree(pszTmp); } OGRCARTODBTableLayer* poLayer = new OGRCARTODBTableLayer(this, osName); int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE); int bCartoDBify = CSLFetchBoolean(papszOptions, "CARTODBFY", CSLFetchBoolean(papszOptions, "CARTODBIFY", TRUE)); poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) ); poLayer->SetDeferedCreation(eGType, poSpatialRef, bGeomNullable, bCartoDBify); papoLayers = (OGRCARTODBTableLayer**) CPLRealloc( papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*)); papoLayers[nLayers ++] = poLayer; return poLayer; }
OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn, CPL_UNUSED int bApproxOK ) { GetLayerDefn(); if (!poDS->IsReadWrite()) { CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode"); return OGRERR_FAILURE; } OGRFieldDefn oField(poFieldIn); if( bLaunderColumnNames ) { char* pszName = OGRPGCommonLaunderName(oField.GetNameRef()); oField.SetName(pszName); CPLFree(pszName); } /* -------------------------------------------------------------------- */ /* Create the new field. */ /* -------------------------------------------------------------------- */ if( !bDeferedCreation ) { CPLString osSQL; osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s", OGRCARTODBEscapeIdentifier(osName).c_str(), OGRCARTODBEscapeIdentifier(oField.GetNameRef()).c_str(), OGRPGCommonLayerGetType(oField, FALSE, TRUE).c_str() ); if( !oField.IsNullable() ) osSQL += " NOT NULL"; if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() ) { osSQL += " DEFAULT "; osSQL += OGRPGCommonLayerGetPGDefault(&oField); } json_object* poObj = poDS->RunSQL(osSQL); if( poObj == NULL ) return OGRERR_FAILURE; json_object_put(poObj); } poFeatureDefn->AddFieldDefn( &oField ); return OGRERR_NONE; }
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; }
OGRLayer *OGRCARTODataSource::ICreateLayer( const char *pszNameIn, 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(pszNameIn,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.", pszNameIn ); return NULL; } } } CPLString osName(pszNameIn); if( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) ) { char* pszTmp = OGRPGCommonLaunderName(pszNameIn); osName = pszTmp; CPLFree(pszTmp); } OGRCARTOTableLayer* poLayer = new OGRCARTOTableLayer(this, osName); const bool bGeomNullable = CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true); int nSRID = (poSpatialRef && eGType != wkbNone) ? FetchSRSId( poSpatialRef ) : 0; bool bCartoify = CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBFY", CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBIFY", true)); if( bCartoify ) { 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"); } bCartoify = false; } } poLayer->SetLaunderFlag( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) ); poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable, bCartoify); papoLayers = (OGRCARTOTableLayer**) CPLRealloc( papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*)); papoLayers[nLayers ++] = poLayer; return poLayer; }