Changeset 14204

Show
Ignore:
Timestamp:
04/05/08 12:00:20 (5 months ago)
Author:
rouault
Message:

Add the ability to specify a list of tables to be treated as layers with the 'tables=' connection string option (#1699)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/gdal/ogr/ogrsf_frmts/pg/drv_pg.html

    r11456 r14204  
    1919that would apply to it, apply to the name here.  The PG: prefix is used 
    2020to mark the name as a postgres connection string.<p> 
     21 
     22The set of tables to be scanned can be overridden by specifying 
     23<i>tables=[schema.]table[,[schema2.]table2,...]</i> within the connection string. 
     24If the parameter is found, the driver skips enumeration of the tables as 
     25described in the next paragraph.<p> 
    2126 
    2227If the <i>geometry_columns</i> table exists, then all listed tables and 
     
    129134<h3>Example</h3> 
    130135 
     136<ul> 
     137<li> 
    131138Simple translation of a shapefile into PostgreSQL.  The table 'abc' will 
    132139be created with the features from abc.shp and attributes from abc.dbf.  
     
    138145</pre> 
    139146 
     147<li> 
    140148<p> 
    141149This second example loads a political boundaries layer from VPF (via the 
     
    149157        -lco OVERWRITE=yes -nln polbndl_bnd 'polbndl@bnd(*)_line' 
    150158</pre> 
    151  
     159</li> 
     160 
     161<li> 
    152162<p> 
    153163In this example we merge tiger line data from two different directories of 
     
    161171     CompleteChain 
    162172</pre> 
    163  
     173</li> 
     174 
     175<li> 
    164176<p> 
    165177This example shows using ogrinfo to evaluate an SQL query statement  
     
    170182ogrinfo -ro PG:dbname=warmerda -sql "SELECT pop_1994 from canada where province_name = 'Alberta'" 
    171183</pre> 
    172  
     184</li> 
     185 
     186<li> 
    173187<p> 
    174188This example shows using ogrinfo to list PostgreSQL/PostGIS layers on a different host.<p> 
     
    177191ogrinfo -ro PG:'host=myserver.velocet.ca user=postgres dbname=warmerda' 
    178192</pre> 
     193</li> 
     194 
     195<li> 
     196<p> 
     197This example shows using ogrinfo to list only the layers specified by the <i>tables=</i> options.<p> 
     198 
     199<pre> 
     200ogrinfo -ro PG:'dbname=warmerda tables=table1,table2' 
     201</pre> 
     202</li> 
     203 
     204</ul> 
    179205 
    180206<h3>See Also</h3> 
  • trunk/gdal/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp

    r14198 r14204  
    182182    } 
    183183 
     184    pszName = CPLStrdup( pszNewName ); 
     185 
     186/* -------------------------------------------------------------------- */ 
     187/*      Determine if the connection string contains an optional         */ 
     188/*      TABLES portion. If so, parse it out. The expected               */ 
     189/*      connection string in this case will be, e.g.:                   */ 
     190/*                                                                      */ 
     191/*        'PG:dbname=warmerda user=warmerda tables=s1.t1,[s2.t2,...]    */ 
     192/*              - where sN is schema and tN is table name               */ 
     193/*      We must also strip this information from the connection         */ 
     194/*      string; PQconnectdb() does not like unknown directives          */ 
     195/* -------------------------------------------------------------------- */ 
     196    char              **papszTableNames=NULL; 
     197    char              **papszSchemaNames=NULL; 
     198 
     199    char             *pszTableStart; 
     200    pszTableStart = strstr(pszName, "tables="); 
     201    if (pszTableStart == NULL) 
     202        pszTableStart = strstr(pszName, "TABLES="); 
     203 
     204    if( pszTableStart != NULL ) 
     205    { 
     206        char          **papszTableList; 
     207        char           *pszTableSpec; 
     208        const char     *pszEnd = NULL; 
     209        int             i; 
     210 
     211        pszTableSpec = CPLStrdup( pszTableStart + 7 ); 
     212 
     213        for( i = 0; pszTableStart[i] != '\0'; i++ ) 
     214        { 
     215            if( pszTableStart[i] == ' ' ) 
     216            { 
     217                pszEnd = pszTableStart + i; 
     218                break; 
     219            } 
     220        } 
     221 
     222        if( pszEnd == NULL ) 
     223            pszEnd = pszName + strlen(pszName); 
     224 
     225        // Remove TABLES=xxxxx from pszName string 
     226        memmove( pszTableStart, pszEnd, strlen(pszEnd) + 1 ); 
     227 
     228        pszTableSpec[pszEnd - pszTableStart - 7] = '\0'; 
     229        papszTableList = CSLTokenizeString2( pszTableSpec, ",", 0 ); 
     230 
     231        for( i = 0; i < CSLCount(papszTableList); i++ ) 
     232        { 
     233            char      **papszQualifiedParts; 
     234 
     235            // Get schema and table name 
     236            papszQualifiedParts = CSLTokenizeString2( papszTableList[i], 
     237                                                      ".", 0 ); 
     238 
     239            if( CSLCount( papszQualifiedParts ) == 2 ) 
     240            { 
     241                papszSchemaNames = CSLAddString( papszSchemaNames,  
     242                                                papszQualifiedParts[0] ); 
     243                papszTableNames = CSLAddString( papszTableNames, 
     244                                                papszQualifiedParts[1] ); 
     245            } 
     246            else if( CSLCount( papszQualifiedParts ) == 1 ) 
     247            { 
     248                papszSchemaNames = CSLAddString( papszSchemaNames, "public"); 
     249                papszTableNames = CSLAddString( papszTableNames, 
     250                                                papszQualifiedParts[0] ); 
     251            } 
     252 
     253            CSLDestroy(papszQualifiedParts); 
     254        } 
     255 
     256        CSLDestroy(papszTableList); 
     257        CPLFree(pszTableSpec); 
     258    } 
     259 
    184260/* -------------------------------------------------------------------- */ 
    185261/*      Try to establish connection.                                    */ 
    186262/* -------------------------------------------------------------------- */ 
    187     hPGConn = PQconnectdb( pszNewName + (bUseBinaryCursor ? 4 : 3) ); 
     263    hPGConn = PQconnectdb( pszName + (bUseBinaryCursor ? 4 : 3) ); 
    188264    if( hPGConn == NULL || PQstatus(hPGConn) == CONNECTION_BAD ) 
    189265    { 
     266        CPLFree(pszName); 
     267        pszName = NULL; 
     268 
    190269        CPLError( CE_Failure, CPLE_AppDefined, 
    191270                  "PQconnectdb failed.\n%s", 
     
    195274        return FALSE; 
    196275    } 
    197  
    198     pszName = CPLStrdup( pszNewName ); 
    199276 
    200277    bDSUpdate = bUpdate; 
     
    404481 
    405482/* -------------------------------------------------------------------- */ 
    406 /*      Get a list of available tables.                                 */ 
    407 /* -------------------------------------------------------------------- */ 
    408     hResult = PQexec(hPGConn, "BEGIN"); 
    409  
    410     if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) 
    411     { 
    412         OGRPGClearResult( hResult ); 
    413  
    414         if ( bHavePostGIS ) 
    415             hResult = PQexec(hPGConn, 
    416                              "DECLARE mycursor CURSOR for " 
    417                              "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n, geometry_columns g " 
    418                              "WHERE (c.relkind in ('r','v') AND c.relname !~ '^pg' AND c.relnamespace=n.oid " 
    419                              "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema)" ); 
    420         else 
    421             hResult = PQexec(hPGConn, 
    422                              "DECLARE mycursor CURSOR for " 
    423                              "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n " 
    424                              "WHERE (c.relkind in ('r','v') AND c.relname !~ '^pg' AND c.relnamespace=n.oid)" ); 
    425     } 
    426  
    427     if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) 
    428     { 
    429         OGRPGClearResult( hResult ); 
    430         hResult = PQexec(hPGConn, "FETCH ALL in mycursor" ); 
    431     } 
    432  
    433     if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK ) 
    434     { 
    435         OGRPGClearResult( hResult ); 
    436  
    437         CPLError( CE_Failure, CPLE_AppDefined, 
    438                   "%s", PQerrorMessage(hPGConn) ); 
    439         return FALSE; 
    440     } 
    441  
    442 /* -------------------------------------------------------------------- */ 
    443 /*      Parse the returned table list                                   */ 
    444 /* -------------------------------------------------------------------- */ 
    445     char        **papszTableNames=NULL; 
    446     char        **papszSchemaNames=NULL; 
    447     int           iRecord; 
    448  
    449     for( iRecord = 0; iRecord < PQntuples(hResult); iRecord++ ) 
    450     { 
    451         const char *pszTable = PQgetvalue(hResult, iRecord, 0); 
    452  
    453         if( EQUAL(pszTable,"spatial_ref_sys") 
    454             || EQUAL(pszTable,"geometry_columns") ) 
    455             continue; 
    456  
    457         papszTableNames = CSLAddString(papszTableNames, 
    458                                        PQgetvalue(hResult, iRecord, 0)); 
    459         papszSchemaNames = CSLAddString(papszSchemaNames, 
    460                                        PQgetvalue(hResult, iRecord, 1)); 
    461  
    462     } 
    463  
    464 /* -------------------------------------------------------------------- */ 
    465 /*      Cleanup                                                         */ 
    466 /* -------------------------------------------------------------------- */ 
    467     OGRPGClearResult( hResult ); 
    468  
    469     hResult = PQexec(hPGConn, "CLOSE mycursor"); 
    470     OGRPGClearResult( hResult ); 
    471  
    472     hResult = PQexec(hPGConn, "COMMIT"); 
    473     OGRPGClearResult( hResult ); 
     483/*      Get a list of available tables if they have not been            */ 
     484/*      specified through the TABLES connection string param           */ 
     485/* -------------------------------------------------------------------- */ 
     486 
     487    if (papszTableNames == NULL) 
     488    { 
     489        hResult = PQexec(hPGConn, "BEGIN"); 
     490 
     491        if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) 
     492        { 
     493            OGRPGClearResult( hResult ); 
     494 
     495            if ( bHavePostGIS ) 
     496                hResult = PQexec(hPGConn, 
     497                                "DECLARE mycursor CURSOR for " 
     498                                "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n, geometry_columns g " 
     499                                "WHERE (c.relkind in ('r','v') AND c.relname !~ '^pg' AND c.relnamespace=n.oid " 
     500                                "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema)" ); 
     501            else 
     502                hResult = PQexec(hPGConn, 
     503                                "DECLARE mycursor CURSOR for " 
     504                                "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n " 
     505                                "WHERE (c.relkind in ('r','v') AND c.relname !~ '^pg' AND c.relnamespace=n.oid)" ); 
     506        } 
     507 
     508        if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) 
     509        { 
     510            OGRPGClearResult( hResult ); 
     511            hResult = PQexec(hPGConn, "FETCH ALL in mycursor" ); 
     512        } 
     513 
     514        if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK ) 
     515        { 
     516            OGRPGClearResult( hResult ); 
     517 
     518            CPLError( CE_Failure, CPLE_AppDefined, 
     519                    "%s", PQerrorMessage(hPGConn) ); 
     520            return FALSE; 
     521        } 
     522 
     523    /* -------------------------------------------------------------------- */ 
     524    /*      Parse the returned table list                                   */ 
     525    /* -------------------------------------------------------------------- */ 
     526        for( int iRecord = 0; iRecord < PQntuples(hResult); iRecord++ ) 
     527        { 
     528            const char *pszTable = PQgetvalue(hResult, iRecord, 0); 
     529 
     530            if( EQUAL(pszTable,"spatial_ref_sys") 
     531                || EQUAL(pszTable,"geometry_columns") ) 
     532                continue; 
     533 
     534            papszTableNames = CSLAddString(papszTableNames, 
     535                                        PQgetvalue(hResult, iRecord, 0)); 
     536            papszSchemaNames = CSLAddString(papszSchemaNames, 
     537                                        PQgetvalue(hResult, iRecord, 1)); 
     538 
     539        } 
     540 
     541    /* -------------------------------------------------------------------- */ 
     542    /*      Cleanup                                                         */ 
     543    /* -------------------------------------------------------------------- */ 
     544        OGRPGClearResult( hResult ); 
     545 
     546        hResult = PQexec(hPGConn, "CLOSE mycursor"); 
     547        OGRPGClearResult( hResult ); 
     548 
     549        hResult = PQexec(hPGConn, "COMMIT"); 
     550        OGRPGClearResult( hResult ); 
     551    } 
    474552 
    475553/* -------------------------------------------------------------------- */ 
    476554/*      Register the available tables.                                  */ 
    477555/* -------------------------------------------------------------------- */ 
    478     for( iRecord = 0; 
     556    for( int iRecord = 0; 
    479557         papszTableNames != NULL && papszTableNames[iRecord] != NULL; 
    480558         iRecord++ )