Esempio n. 1
0
int OGRCARTODBDataSource::Open( const char * pszFilename, int bUpdateIn)

{
    bReadWrite = bUpdateIn;

    pszName = CPLStrdup( pszFilename );
    pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
    char* pchSpace = strchr(pszAccount, ' ');
    if( pchSpace )
        *pchSpace = '\0';

    osAPIKey = CPLGetConfigOption("CARTODB_API_KEY", "");

    CPLString osTables = OGRCARTODBGetOptionValue(pszFilename, "tables");

    bUseHTTPS = CSLTestBoolean(CPLGetConfigOption("CARTODB_HTTPS", "YES"));

    if (osTables.size() != 0)
    {
        char** papszTables = CSLTokenizeString2(osTables, ",", 0);
        for(int i=0;papszTables && papszTables[i];i++)
        {
            papoLayers = (OGRLayer**) CPLRealloc(
                papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
            papoLayers[nLayers ++] = new OGRCARTODBTableLayer(this, papszTables[i]);
        }
        CSLDestroy(papszTables);
        return TRUE;
    }
    
    if( osAPIKey.size() == 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "When not specifying tables option, CARTODB_API_KEY must be defined");
        return FALSE;
    }

    json_object* poObj = RunSQL("SELECT CDB_UserTables()");
    if( poObj == NULL )
        return FALSE;
    json_object* poRows = json_object_object_get(poObj, "rows");
    if( poRows == NULL || json_object_get_type(poRows) != json_type_array)
    {
        json_object_put(poObj);
        return FALSE;
    }
    for(int i=0; i < json_object_array_length(poRows); i++)
    {
        json_object* poTableNameObj = json_object_array_get_idx(poRows, i);
        if( poTableNameObj != NULL &&
            json_object_get_type(poTableNameObj) == json_type_object )
        {
            json_object* poVal = json_object_object_get(poTableNameObj, "cdb_usertables");
            if( poVal != NULL &&
                json_object_get_type(poVal) == json_type_string )
            {
                papoLayers = (OGRLayer**) CPLRealloc(
                    papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
                papoLayers[nLayers ++] = new OGRCARTODBTableLayer(
                            this, json_object_get_string(poVal));
            }
        }
    }
    json_object_put(poObj);

    return TRUE;
}
int OGRCARTODBDataSource::Open( const char * pszFilename,
                                char** papszOpenOptions,
                                int bUpdateIn )

{
    bReadWrite = bUpdateIn;
    bBatchInsert = CSLTestBoolean(CSLFetchNameValueDef(papszOpenOptions, "BATCH_INSERT", "YES"));

    pszName = CPLStrdup( pszFilename );
    if( CSLFetchNameValue(papszOpenOptions, "ACCOUNT") )
        pszAccount = CPLStrdup(CSLFetchNameValue(papszOpenOptions, "ACCOUNT"));
    else
    {
        pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
        char* pchSpace = strchr(pszAccount, ' ');
        if( pchSpace )
            *pchSpace = '\0';
        if( pszAccount[0] == 0 )
        {
            CPLError(CE_Failure, CPLE_AppDefined, "Missing account name");
            return FALSE;
        }
    }

    osAPIKey = CSLFetchNameValueDef(papszOpenOptions, "API_KEY",
                                    CPLGetConfigOption("CARTODB_API_KEY", ""));

    CPLString osTables = OGRCARTODBGetOptionValue(pszFilename, "tables");
    
    /*if( osTables.size() == 0 && osAPIKey.size() == 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "When not specifying tables option, CARTODB_API_KEY must be defined");
        return FALSE;
    }*/

    bUseHTTPS = CSLTestBoolean(CPLGetConfigOption("CARTODB_HTTPS", "YES"));

    OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
    if( poSchemaLayer )
    {
        OGRFeature* poFeat = poSchemaLayer->GetNextFeature();
        if( poFeat )
        {
            if( poFeat->GetFieldCount() == 1 )
            {
                osCurrentSchema = poFeat->GetFieldAsString(0);
            }
            delete poFeat;
        }
        ReleaseResultSet(poSchemaLayer);
    }
    if( osCurrentSchema.size() == 0 )
        return FALSE;

    if( osAPIKey.size() && bUpdateIn )
    {
        ExecuteSQLInternal(
                "DROP FUNCTION IF EXISTS ogr_table_metadata(TEXT,TEXT); "
                "CREATE OR REPLACE FUNCTION ogr_table_metadata(schema_name TEXT, table_name TEXT) RETURNS TABLE "
                "(attname TEXT, typname TEXT, attlen INT, format_type TEXT, "
                "attnum INT, attnotnull BOOLEAN, indisprimary BOOLEAN, "
                "defaultexpr TEXT, dim INT, srid INT, geomtyp TEXT, srtext TEXT) AS $$ "
                "SELECT a.attname::text, t.typname::text, a.attlen::int, "
                        "format_type(a.atttypid,a.atttypmod)::text, "
                        "a.attnum::int, "
                        "a.attnotnull::boolean, "
                        "i.indisprimary::boolean, "
                        "pg_get_expr(def.adbin, c.oid)::text AS defaultexpr, "
                        "(CASE WHEN t.typname = 'geometry' THEN postgis_typmod_dims(a.atttypmod) ELSE NULL END)::int dim, "
                        "(CASE WHEN t.typname = 'geometry' THEN postgis_typmod_srid(a.atttypmod) ELSE NULL END)::int srid, "
                        "(CASE WHEN t.typname = 'geometry' THEN postgis_typmod_type(a.atttypmod) ELSE NULL END)::text geomtyp, "
                        "srtext "
                "FROM pg_class c "
                "JOIN pg_attribute a ON a.attnum > 0 AND "
                                        "a.attrelid = c.oid AND c.relname = $2 "
                                        "AND c.relname IN (SELECT CDB_UserTables())"
                "JOIN pg_type t ON a.atttypid = t.oid "
                "JOIN pg_namespace n ON c.relnamespace=n.oid AND n.nspname = $1 "
                "LEFT JOIN pg_index i ON c.oid = i.indrelid AND "
                                        "i.indisprimary = 't' AND a.attnum = ANY(i.indkey) "
                "LEFT JOIN pg_attrdef def ON def.adrelid = c.oid AND "
                                            "def.adnum = a.attnum "
                "LEFT JOIN spatial_ref_sys srs ON srs.srid = postgis_typmod_srid(a.atttypmod) "
                "ORDER BY a.attnum "
                "$$ LANGUAGE SQL");
    }
    
    if (osTables.size() != 0)
    {
        char** papszTables = CSLTokenizeString2(osTables, ",", 0);
        for(int i=0;papszTables && papszTables[i];i++)
        {
            papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
                papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
            papoLayers[nLayers ++] = new OGRCARTODBTableLayer(this, papszTables[i]);
        }
        CSLDestroy(papszTables);
        return TRUE;
    }

    OGRLayer* poTableListLayer = ExecuteSQLInternal("SELECT CDB_UserTables()");
    if( poTableListLayer )
    {
        OGRFeature* poFeat;
        while( (poFeat = poTableListLayer->GetNextFeature()) != NULL )
        {
            if( poFeat->GetFieldCount() == 1 )
            {
                papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
                    papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
                papoLayers[nLayers ++] = new OGRCARTODBTableLayer(
                            this, poFeat->GetFieldAsString(0));
            }
            delete poFeat;
        }
        ReleaseResultSet(poTableListLayer);
    }
    else if( osCurrentSchema == "public" )
        return FALSE;

    /* There's currently a bug with CDB_UserTables() on multi-user accounts */
    if( nLayers == 0 && osCurrentSchema != "public" )
    {
        CPLString osSQL;
        osSQL.Printf("SELECT c.relname FROM pg_class c, pg_namespace n "
                     "WHERE c.relkind in ('r', 'v') AND c.relname !~ '^pg_' AND c.relnamespace=n.oid AND n.nspname = '%s'",
                     OGRCARTODBEscapeLiteral(osCurrentSchema).c_str());
        poTableListLayer = ExecuteSQLInternal(osSQL);
        if( poTableListLayer )
        {
            OGRFeature* poFeat;
            while( (poFeat = poTableListLayer->GetNextFeature()) != NULL )
            {
                if( poFeat->GetFieldCount() == 1 )
                {
                    papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
                        papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
                    papoLayers[nLayers ++] = new OGRCARTODBTableLayer(
                                this, poFeat->GetFieldAsString(0));
                }
                delete poFeat;
            }
            ReleaseResultSet(poTableListLayer);
        }
        else
            return FALSE;
    }

    return TRUE;
}