LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/pgdump - ogrpgdumplayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 497 267 53.7 %
Date: 2013-03-30 Functions: 22 15 68.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrpgdumplayer.cpp 25366 2012-12-27 18:38:53Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRPGDumpLayer class
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Even Rouault
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_pgdump.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrpgdumplayer.cpp 25366 2012-12-27 18:38:53Z rouault $");
      35                 : 
      36                 : #define USE_COPY_UNSET -1
      37                 : 
      38                 : /* Flags for creating WKB format for PostGIS */
      39                 : #define WKBZOFFSET 0x80000000
      40                 : #define WKBMOFFSET 0x40000000
      41                 : #define WKBSRIDFLAG 0x20000000
      42                 : #define WKBBBOXFLAG 0x10000000
      43                 : 
      44                 : static CPLString OGRPGDumpEscapeStringList(
      45                 :                                        char** papszItems, int bForInsertOrUpdate);
      46                 : 
      47                 : /************************************************************************/
      48                 : /*                        OGRPGDumpLayer()                              */
      49                 : /************************************************************************/
      50                 : 
      51               3 : OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
      52                 :                                const char* pszSchemaName,
      53                 :                                const char* pszTableName,
      54                 :                                const char* pszGeomColumn,
      55                 :                                const char *pszFIDColumn,
      56                 :                                int         nCoordDimension,
      57                 :                                int         nSRSId,
      58                 :                                int         bWriteAsHexIn,
      59               3 :                                int         bCreateTable)
      60                 : {
      61               3 :     this->poDS = poDS;
      62               3 :     poFeatureDefn = new OGRFeatureDefn( pszTableName );
      63               3 :     poFeatureDefn->Reference();
      64               3 :     nFeatures = 0;
      65                 :     pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
      66                 :                                OGRPGDumpEscapeColumnName(pszSchemaName).c_str(),
      67               3 :                                OGRPGDumpEscapeColumnName(pszTableName).c_str() ));
      68               3 :     this->pszGeomColumn = (pszGeomColumn) ? CPLStrdup(pszGeomColumn) : NULL;
      69               3 :     this->pszFIDColumn = CPLStrdup(pszFIDColumn);
      70               3 :     this->nCoordDimension = nCoordDimension;
      71               3 :     this->nSRSId = nSRSId;
      72               3 :     this->bCreateTable = bCreateTable;
      73               3 :     bLaunderColumnNames = TRUE;
      74               3 :     bPreservePrecision = TRUE;
      75               3 :     bUseCopy = USE_COPY_UNSET;
      76               3 :     bFIDColumnInCopyFields = FALSE;
      77               3 :     bWriteAsHex = bWriteAsHexIn;
      78               3 :     bCopyActive = FALSE;
      79               3 :     papszOverrideColumnTypes = NULL;
      80               3 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                          ~OGRPGDumpLayer()                           */
      84                 : /************************************************************************/
      85                 : 
      86               3 : OGRPGDumpLayer::~OGRPGDumpLayer()
      87                 : {
      88               3 :     EndCopy();
      89                 : 
      90               3 :     poFeatureDefn->Release();
      91               3 :     CPLFree(pszSqlTableName);
      92               3 :     CPLFree(pszGeomColumn);
      93               3 :     CPLFree(pszFIDColumn);
      94               3 :     CSLDestroy(papszOverrideColumnTypes);
      95               3 : }
      96                 : 
      97                 : /************************************************************************/
      98                 : /*                           GetNextFeature()                           */
      99                 : /************************************************************************/
     100                 : 
     101               0 : OGRFeature *OGRPGDumpLayer::GetNextFeature()
     102                 : {
     103               0 :     CPLError(CE_Failure, CPLE_NotSupported, "PGDump driver is write only");
     104               0 :     return NULL;
     105                 : }
     106                 : 
     107                 : /************************************************************************/
     108                 : /*                           GetNextFeature()                           */
     109                 : /************************************************************************/
     110                 : 
     111               0 : int OGRPGDumpLayer::TestCapability( const char * pszCap )
     112                 : {
     113               0 :     if( EQUAL(pszCap,OLCSequentialWrite) ||
     114                 :         EQUAL(pszCap,OLCCreateField) )
     115               0 :         return TRUE;
     116                 :     else
     117               0 :         return FALSE;
     118                 : }
     119                 : 
     120                 : /************************************************************************/
     121                 : /*                           GeometryToHex()                            */
     122                 : /************************************************************************/
     123                 : 
     124              20 : char *OGRPGDumpLayer::GeometryToHex( OGRGeometry * poGeometry, int nSRSId )
     125                 : {
     126                 :     GByte       *pabyWKB;
     127                 :     char        *pszTextBuf;
     128                 :     char        *pszTextBufCurrent;
     129                 :     char        *pszHex;
     130                 : 
     131              20 :     int nWkbSize = poGeometry->WkbSize();
     132              20 :     pabyWKB = (GByte *) CPLMalloc(nWkbSize);
     133                 : 
     134              20 :     if( poGeometry->exportToWkb( wkbNDR, pabyWKB ) != OGRERR_NONE )
     135                 :     {
     136               0 :         CPLFree( pabyWKB );
     137               0 :         return CPLStrdup("");
     138                 :     }
     139                 : 
     140                 :     /* When converting to hex, each byte takes 2 hex characters.  In addition
     141                 :        we add in 8 characters to represent the SRID integer in hex, and
     142                 :        one for a null terminator */
     143                 : 
     144              20 :     int pszSize = nWkbSize*2 + 8 + 1;
     145              20 :     pszTextBuf = (char *) CPLMalloc(pszSize);
     146              20 :     pszTextBufCurrent = pszTextBuf;
     147                 : 
     148                 :     /* Convert the 1st byte, which is the endianess flag, to hex. */
     149              20 :     pszHex = CPLBinaryToHex( 1, pabyWKB );
     150              20 :     strcpy(pszTextBufCurrent, pszHex );
     151              20 :     CPLFree ( pszHex );
     152              20 :     pszTextBufCurrent += 2;
     153                 : 
     154                 :     /* Next, get the geom type which is bytes 2 through 5 */
     155                 :     GUInt32 geomType;
     156              20 :     memcpy( &geomType, pabyWKB+1, 4 );
     157                 : 
     158                 :     /* Now add the SRID flag if an SRID is provided */
     159              20 :     if (nSRSId > 0)
     160                 :     {
     161                 :         /* Change the flag to wkbNDR (little) endianess */
     162              10 :         GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
     163                 :         /* Apply the flag */
     164              10 :         geomType = geomType | nGSrsFlag;
     165                 :     }
     166                 : 
     167                 :     /* Now write the geom type which is 4 bytes */
     168              20 :     pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );
     169              20 :     strcpy(pszTextBufCurrent, pszHex );
     170              20 :     CPLFree ( pszHex );
     171              20 :     pszTextBufCurrent += 8;
     172                 : 
     173                 :     /* Now include SRID if provided */
     174              20 :     if (nSRSId > 0)
     175                 :     {
     176                 :         /* Force the srsid to wkbNDR (little) endianess */
     177              10 :         GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
     178              10 :         pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
     179              10 :         strcpy(pszTextBufCurrent, pszHex );
     180              10 :         CPLFree ( pszHex );
     181              10 :         pszTextBufCurrent += 8;
     182                 :     }
     183                 : 
     184                 :     /* Copy the rest of the data over - subtract
     185                 :        5 since we already copied 5 bytes above */
     186              20 :     pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );
     187              20 :     strcpy(pszTextBufCurrent, pszHex );
     188              20 :     CPLFree ( pszHex );
     189                 : 
     190              20 :     CPLFree( pabyWKB );
     191                 : 
     192              20 :     return pszTextBuf;
     193                 : }
     194                 : 
     195                 : /************************************************************************/
     196                 : /*                           GetNextFeature()                           */
     197                 : /************************************************************************/
     198                 : 
     199              30 : OGRErr OGRPGDumpLayer::CreateFeature( OGRFeature *poFeature )
     200                 : {
     201              30 :     if( NULL == poFeature )
     202                 :     {
     203                 :         CPLError( CE_Failure, CPLE_AppDefined,
     204               0 :                   "NULL pointer to OGRFeature passed to CreateFeature()." );
     205               0 :         return OGRERR_FAILURE;
     206                 :     }
     207                 : 
     208              30 :     nFeatures ++;
     209                 : 
     210                 :     // We avoid testing the config option too often. 
     211              30 :     if( bUseCopy == USE_COPY_UNSET )
     212               3 :         bUseCopy = CSLTestBoolean( CPLGetConfigOption( "PG_USE_COPY", "NO") );
     213                 : 
     214              30 :     if( !bUseCopy )
     215                 :     {
     216              10 :         return CreateFeatureViaInsert( poFeature );
     217                 :     }
     218                 :     else
     219                 :     {
     220              20 :         if ( !bCopyActive )
     221                 :         {
     222                 :             /* This is a heuristics. If the first feature to be copied has a */ 
     223                 :             /* FID set (and that a FID column has been identified), then we will */ 
     224                 :             /* try to copy FID values from features. Otherwise, we will not */ 
     225                 :             /* do and assume that the FID column is an autoincremented column. */ 
     226               2 :             StartCopy(poFeature->GetFID() != OGRNullFID); 
     227                 :         }
     228                 : 
     229              20 :         return CreateFeatureViaCopy( poFeature );
     230                 :     }
     231                 : }
     232                 : 
     233                 : /************************************************************************/
     234                 : /*                       CreateFeatureViaInsert()                       */
     235                 : /************************************************************************/
     236                 : 
     237              10 : OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
     238                 : 
     239                 : {
     240              10 :     CPLString           osCommand;
     241              10 :     int                 i = 0;
     242              10 :     int                 bNeedComma = FALSE;
     243              10 :     OGRErr              eErr = OGRERR_FAILURE;
     244              10 :     int bEmptyInsert = FALSE;
     245                 :     
     246              10 :     if( NULL == poFeature )
     247                 :     {
     248                 :         CPLError( CE_Failure, CPLE_AppDefined,
     249               0 :                   "NULL pointer to OGRFeature passed to CreateFeatureViaInsert()." );
     250               0 :         return eErr;
     251                 :     }
     252                 : 
     253                 : /* -------------------------------------------------------------------- */
     254                 : /*      Form the INSERT command.                                        */
     255                 : /* -------------------------------------------------------------------- */
     256              10 :     osCommand.Printf( "INSERT INTO %s (", pszSqlTableName );
     257                 : 
     258              10 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     259              10 :     if( poGeom != NULL && pszGeomColumn != NULL )
     260                 :     {
     261              10 :         osCommand = osCommand + OGRPGDumpEscapeColumnName(pszGeomColumn) + " ";
     262              10 :         bNeedComma = TRUE;
     263                 :     }
     264                 : 
     265              10 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     266                 :     {
     267               0 :         if( bNeedComma )
     268               0 :             osCommand += ", ";
     269                 :         
     270               0 :         osCommand = osCommand + OGRPGDumpEscapeColumnName(pszFIDColumn) + " ";
     271               0 :         bNeedComma = TRUE;
     272                 :     }
     273                 : 
     274              50 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     275                 :     {
     276              40 :         if( !poFeature->IsFieldSet( i ) )
     277              10 :             continue;
     278                 : 
     279              30 :         if( !bNeedComma )
     280               0 :             bNeedComma = TRUE;
     281                 :         else
     282              30 :             osCommand += ", ";
     283                 : 
     284                 :         osCommand = osCommand 
     285              30 :             + OGRPGDumpEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     286                 :     }
     287                 : 
     288              10 :     if (!bNeedComma)
     289               0 :         bEmptyInsert = TRUE;
     290                 : 
     291              10 :     osCommand += ") VALUES (";
     292                 : 
     293                 :     /* Set the geometry */
     294              10 :     bNeedComma = FALSE;
     295              10 :     if( poGeom != NULL && pszGeomColumn != NULL )
     296                 :     {
     297              10 :         char    *pszWKT = NULL;
     298                 : 
     299              10 :         poGeom->closeRings();
     300              10 :         poGeom->setCoordinateDimension( nCoordDimension );
     301                 : 
     302              10 :         if( bWriteAsHex )
     303                 :         {
     304              10 :             char* pszHex = GeometryToHex( poGeom, nSRSId );
     305              10 :             osCommand += "'";
     306              10 :             if (pszHex)
     307              10 :                 osCommand += pszHex;
     308              10 :             osCommand += "'";
     309              10 :             CPLFree(pszHex);
     310                 :         }
     311                 :         else
     312                 :         {
     313               0 :             poGeom->exportToWkt( &pszWKT );
     314                 : 
     315               0 :             if( pszWKT != NULL )
     316                 :             {
     317                 :                 osCommand +=
     318                 :                     CPLString().Printf(
     319               0 :                         "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );
     320               0 :                 OGRFree( pszWKT );
     321                 :             }
     322                 :             else
     323               0 :                 osCommand += "''";
     324                 :         }
     325                 : 
     326              10 :         bNeedComma = TRUE;
     327                 :     }
     328                 : 
     329                 :     /* Set the FID */
     330              10 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     331                 :     {
     332               0 :         if( bNeedComma )
     333               0 :             osCommand += ", ";
     334               0 :         osCommand += CPLString().Printf( "%ld ", poFeature->GetFID() );
     335               0 :         bNeedComma = TRUE;
     336                 :     }
     337                 : 
     338                 : 
     339              50 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     340                 :     {
     341              40 :         if( !poFeature->IsFieldSet( i ) )
     342              10 :             continue;
     343                 : 
     344              30 :         if( bNeedComma )
     345              30 :             osCommand += ", ";
     346                 :         else
     347               0 :             bNeedComma = TRUE;
     348                 : 
     349              30 :         AppendFieldValue(osCommand, poFeature, i);
     350                 :     }
     351                 : 
     352              10 :     osCommand += ")";
     353                 : 
     354              10 :     if (bEmptyInsert)
     355               0 :         osCommand.Printf( "INSERT INTO %s DEFAULT VALUES", pszSqlTableName );
     356                 : 
     357                 : /* -------------------------------------------------------------------- */
     358                 : /*      Execute the insert.                                             */
     359                 : /* -------------------------------------------------------------------- */
     360              10 :     poDS->Log(osCommand);
     361                 : 
     362              10 :     return OGRERR_NONE;
     363                 : }
     364                 : 
     365                 : 
     366                 : /************************************************************************/
     367                 : /*                        CreateFeatureViaCopy()                        */
     368                 : /************************************************************************/
     369                 : 
     370              20 : OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
     371                 : {
     372              20 :     CPLString            osCommand;
     373                 : 
     374                 :     /* First process geometry */
     375              20 :     OGRGeometry *poGeometry = (OGRGeometry *) poFeature->GetGeometryRef();
     376                 :     
     377              20 :     if (pszGeomColumn)
     378                 :     {
     379              10 :         char *pszGeom = NULL;
     380              10 :         if ( NULL != poGeometry /* && (bHasWkb || bHasPostGISGeometry || bHasPostGISGeography) */)
     381                 :         {
     382              10 :             poGeometry->closeRings();
     383              10 :             poGeometry->setCoordinateDimension( nCoordDimension );
     384                 :             
     385                 :             //CheckGeomTypeCompatibility(poGeometry);
     386                 :     
     387                 :             /*if (bHasWkb)
     388                 :                 pszGeom = GeometryToBYTEA( poGeometry );
     389                 :             else*/
     390              10 :                 pszGeom = GeometryToHex( poGeometry, nSRSId );
     391                 :         }
     392                 :     
     393              10 :         if ( pszGeom )
     394                 :         {
     395                 :             osCommand += pszGeom,
     396              10 :             CPLFree( pszGeom );
     397                 :         }
     398                 :         else
     399                 :         {
     400               0 :             osCommand = "\\N";
     401                 :         }
     402                 :     }
     403                 : 
     404                 :     /* Next process the field id column */
     405              20 :     int nFIDIndex = -1;
     406              20 :     if( bFIDColumnInCopyFields )
     407                 :     {
     408               0 :         if (osCommand.size() > 0)
     409               0 :             osCommand += "\t";
     410                 : 
     411               0 :         nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn ); 
     412                 : 
     413                 :         /* Set the FID */
     414               0 :         if( poFeature->GetFID() != OGRNullFID )
     415                 :         {
     416               0 :             osCommand += CPLString().Printf("%ld ", poFeature->GetFID());
     417                 :         }
     418                 :         else
     419                 :         {
     420               0 :             osCommand += "\\N" ;
     421                 :         }
     422                 :     }
     423                 : 
     424                 : 
     425                 :     /* Now process the remaining fields */
     426                 : 
     427              20 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     428              20 :     int bAddTab = osCommand.size() > 0; 
     429                 : 
     430             110 :     for( int i = 0; i < nFieldCount;  i++ )
     431                 :     {
     432              90 :         if (i == nFIDIndex)
     433               0 :             continue;
     434                 : 
     435              90 :         const char *pszStrValue = poFeature->GetFieldAsString(i);
     436              90 :         char *pszNeedToFree = NULL;
     437                 : 
     438              90 :         if (bAddTab)
     439              80 :             osCommand += "\t";
     440              90 :         bAddTab = TRUE; 
     441                 : 
     442              90 :         if( !poFeature->IsFieldSet( i ) )
     443                 :         {
     444              21 :             osCommand += "\\N" ;
     445                 : 
     446              21 :             continue;
     447                 :         }
     448                 : 
     449              69 :         int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
     450                 : 
     451                 :         // We need special formatting for integer list values.
     452              69 :         if( nOGRFieldType == OFTIntegerList )
     453                 :         {
     454               0 :             int nCount, nOff = 0, j;
     455               0 :             const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
     456                 : 
     457               0 :             pszNeedToFree = (char *) CPLMalloc(nCount * 13 + 10);
     458               0 :             strcpy( pszNeedToFree, "{" );
     459               0 :             for( j = 0; j < nCount; j++ )
     460                 :             {
     461               0 :                 if( j != 0 )
     462               0 :                     strcat( pszNeedToFree+nOff, "," );
     463                 : 
     464               0 :                 nOff += strlen(pszNeedToFree+nOff);
     465               0 :                 sprintf( pszNeedToFree+nOff, "%d", panItems[j] );
     466                 :             }
     467               0 :             strcat( pszNeedToFree+nOff, "}" );
     468               0 :             pszStrValue = pszNeedToFree;
     469                 :         }
     470                 : 
     471                 :         // We need special formatting for real list values.
     472              69 :         else if( nOGRFieldType == OFTRealList )
     473                 :         {
     474               0 :             int nCount, nOff = 0, j;
     475               0 :             const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);
     476                 : 
     477               0 :             pszNeedToFree = (char *) CPLMalloc(nCount * 40 + 10);
     478               0 :             strcpy( pszNeedToFree, "{" );
     479               0 :             for( j = 0; j < nCount; j++ )
     480                 :             {
     481               0 :                 if( j != 0 )
     482               0 :                     strcat( pszNeedToFree+nOff, "," );
     483                 : 
     484               0 :                 nOff += strlen(pszNeedToFree+nOff);
     485                 :                 //Check for special values. They need to be quoted.
     486               0 :                 if( CPLIsNan(padfItems[j]) )
     487               0 :                     sprintf( pszNeedToFree+nOff, "NaN" );
     488               0 :                 else if( CPLIsInf(padfItems[j]) )
     489               0 :                     sprintf( pszNeedToFree+nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
     490                 :                 else
     491               0 :                     sprintf( pszNeedToFree+nOff, "%.16g", padfItems[j] );
     492                 : 
     493                 :             }
     494               0 :             strcat( pszNeedToFree+nOff, "}" );
     495               0 :             pszStrValue = pszNeedToFree;
     496                 :         }
     497                 : 
     498                 : 
     499                 :         // We need special formatting for string list values.
     500              69 :         else if( nOGRFieldType == OFTStringList )
     501                 :         {
     502               0 :             CPLString osStr;
     503               0 :             char **papszItems = poFeature->GetFieldAsStringList(i);
     504                 : 
     505               0 :             pszStrValue = pszNeedToFree = CPLStrdup(OGRPGDumpEscapeStringList(papszItems, FALSE));
     506                 :         }
     507                 : 
     508                 :         // Binary formatting
     509              69 :         else if( nOGRFieldType == OFTBinary )
     510                 :         {
     511               0 :             int nLen = 0;
     512               0 :             GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
     513               0 :             char* pszBytea = GByteArrayToBYTEA( pabyData, nLen);
     514                 : 
     515               0 :             pszStrValue = pszNeedToFree = pszBytea;
     516                 :         }
     517                 : 
     518              69 :         else if( nOGRFieldType == OFTReal )
     519                 :         {
     520              20 :             char* pszComma = strchr((char*)pszStrValue, ',');
     521              20 :             if (pszComma)
     522               0 :                 *pszComma = '.';
     523                 :             //Check for special values. They need to be quoted.
     524              20 :             double dfVal = poFeature->GetFieldAsDouble(i);
     525              20 :             if( CPLIsNan(dfVal) )
     526               0 :                 pszStrValue = "NaN";
     527              20 :             else if( CPLIsInf(dfVal) )
     528               0 :                 pszStrValue = (dfVal > 0) ? "Infinity" : "-Infinity";
     529                 :         }
     530                 : 
     531              98 :         if( nOGRFieldType != OFTIntegerList &&
     532                 :             nOGRFieldType != OFTRealList &&
     533                 :             nOGRFieldType != OFTInteger &&
     534                 :             nOGRFieldType != OFTReal &&
     535                 :             nOGRFieldType != OFTBinary )
     536                 :         {
     537                 :             int         iChar;
     538                 : 
     539             189 :             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
     540                 :             {
     541             160 :                 if( poFeatureDefn->GetFieldDefn(i)->GetWidth() > 0
     542                 :                     && iChar == poFeatureDefn->GetFieldDefn(i)->GetWidth() )
     543                 :                 {
     544                 :                     CPLDebug( "PG",
     545                 :                               "Truncated %s field value, it was too long.",
     546               0 :                               poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     547               0 :                     break;
     548                 :                 }
     549                 : 
     550                 :                 /* Escape embedded \, \t, \n, \r since they will cause COPY
     551                 :                    to misinterpret a line of text and thus abort */
     552             640 :                 if( pszStrValue[iChar] == '\\' || 
     553             160 :                     pszStrValue[iChar] == '\t' || 
     554             160 :                     pszStrValue[iChar] == '\r' || 
     555             160 :                     pszStrValue[iChar] == '\n'   )
     556                 :                 {
     557               0 :                     osCommand += '\\';
     558                 :                 }
     559                 : 
     560             160 :                 osCommand += pszStrValue[iChar];
     561                 :             }
     562                 :         }
     563                 :         else
     564                 :         {
     565              40 :             osCommand += pszStrValue;
     566                 :         }
     567                 : 
     568              69 :         if( pszNeedToFree )
     569               0 :             CPLFree( pszNeedToFree );
     570                 :     }
     571                 : 
     572                 :     /* Add end of line marker */
     573                 :     //osCommand += "\n";
     574                 : 
     575                 : 
     576                 :     /* ------------------------------------------------------------ */
     577                 :     /*      Execute the copy.                                       */
     578                 :     /* ------------------------------------------------------------ */
     579                 : 
     580              20 :     OGRErr result = OGRERR_NONE;
     581                 : 
     582              20 :     poDS->Log(osCommand, FALSE);
     583                 : 
     584              20 :     return result;
     585                 : }
     586                 : 
     587                 : /************************************************************************/
     588                 : /*                             StartCopy()                              */
     589                 : /************************************************************************/
     590                 : 
     591               2 : OGRErr OGRPGDumpLayer::StartCopy(int bSetFID)
     592                 : 
     593                 : {
     594                 :     /* Tell the datasource we are now planning to copy data */
     595               2 :     poDS->StartCopy( this ); 
     596                 : 
     597               2 :     CPLString osFields = BuildCopyFields(bSetFID);
     598                 : 
     599               2 :     int size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
     600               2 :     char *pszCommand = (char *) CPLMalloc(size);
     601                 : 
     602                 :     sprintf( pszCommand,
     603                 :              "COPY %s (%s) FROM STDIN",
     604               2 :              pszSqlTableName, osFields.c_str() );
     605                 : 
     606               2 :     poDS->Log(pszCommand);
     607               2 :     bCopyActive = TRUE;
     608                 : 
     609               2 :     CPLFree( pszCommand );
     610                 : 
     611               2 :     return OGRERR_NONE;
     612                 : }
     613                 : 
     614                 : /************************************************************************/
     615                 : /*                              EndCopy()                               */
     616                 : /************************************************************************/
     617                 : 
     618               5 : OGRErr OGRPGDumpLayer::EndCopy()
     619                 : 
     620                 : {
     621               5 :     if( !bCopyActive )
     622               3 :         return OGRERR_NONE;
     623                 : 
     624               2 :     bCopyActive = FALSE;
     625                 : 
     626               2 :     poDS->Log("\\.", FALSE);
     627               2 :     poDS->Log("END");
     628                 : 
     629               2 :     bUseCopy = USE_COPY_UNSET;
     630                 : 
     631               2 :     return OGRERR_NONE;
     632                 : }
     633                 : 
     634                 : /************************************************************************/
     635                 : /*                          BuildCopyFields()                           */
     636                 : /************************************************************************/
     637                 : 
     638               2 : CPLString OGRPGDumpLayer::BuildCopyFields(int bSetFID)
     639                 : {
     640               2 :     int     i = 0;
     641               2 :     int     nFIDIndex = -1; 
     642               2 :     CPLString osFieldList;
     643                 : 
     644               2 :     if( pszGeomColumn != NULL )
     645                 :     {
     646               1 :         osFieldList = OGRPGDumpEscapeColumnName(pszGeomColumn);
     647                 :     }
     648                 : 
     649               2 :     bFIDColumnInCopyFields = (pszFIDColumn != NULL && bSetFID);
     650               2 :     if( bFIDColumnInCopyFields )
     651                 :     {
     652               0 :         if( osFieldList.size() > 0 )
     653               0 :             osFieldList += ", ";
     654                 : 
     655               0 :         nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn );
     656                 : 
     657               0 :         osFieldList += OGRPGDumpEscapeColumnName(pszFIDColumn); 
     658                 :     }
     659                 : 
     660              11 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     661                 :     {
     662               9 :         if (i == nFIDIndex)
     663               0 :             continue;
     664                 : 
     665               9 :         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     666                 : 
     667               9 :        if( osFieldList.size() > 0 )
     668               8 :             osFieldList += ", ";
     669                 : 
     670               9 :         osFieldList += OGRPGDumpEscapeColumnName(pszName);
     671                 :     }
     672                 : 
     673               0 :     return osFieldList;
     674                 : }
     675                 : 
     676                 : /************************************************************************/
     677                 : /*                       OGRPGDumpEscapeColumnName( )                   */
     678                 : /************************************************************************/
     679                 : 
     680              69 : CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName)
     681                 : {
     682              69 :     CPLString osStr;
     683                 : 
     684              69 :     osStr += "\"";
     685                 : 
     686                 :     char ch;
     687             564 :     for(int i=0; (ch = pszColumnName[i]) != '\0'; i++)
     688                 :     {
     689             495 :         if (ch == '"')
     690               0 :             osStr.append(1, ch);
     691             495 :         osStr.append(1, ch);
     692                 :     }
     693                 : 
     694              69 :     osStr += "\"";
     695                 : 
     696               0 :     return osStr;
     697                 : }
     698                 : 
     699                 : /************************************************************************/
     700                 : /*                             EscapeString( )                          */
     701                 : /************************************************************************/
     702                 : 
     703              13 : CPLString OGRPGDumpEscapeString(
     704                 :                                    const char* pszStrValue, int nMaxLength,
     705                 :                                    const char* pszFieldName)
     706                 : {
     707              13 :     CPLString osCommand;
     708                 : 
     709                 :     /* We need to quote and escape string fields. */
     710              13 :     osCommand += "'";
     711                 : 
     712              13 :     int nSrcLen = strlen(pszStrValue);
     713              13 :     if (nMaxLength > 0 && nSrcLen > nMaxLength)
     714                 :     {
     715                 :         CPLDebug( "PG",
     716                 :                   "Truncated %s field value, it was too long.",
     717               0 :                   pszFieldName );
     718               0 :         nSrcLen = nMaxLength;
     719                 :         
     720               0 :         while( nSrcLen > 0 && ((unsigned char *) pszStrValue)[nSrcLen-1] > 127 )
     721                 :         {
     722               0 :             CPLDebug( "PG", "Backup to start of multi-byte character." );
     723               0 :             nSrcLen--;
     724                 :         }
     725                 :     }
     726                 : 
     727              13 :     char* pszDestStr = (char*)CPLMalloc(2 * nSrcLen + 1);
     728                 : 
     729                 :     /* -------------------------------------------------------------------- */
     730                 :     /*  PQescapeStringConn was introduced in PostgreSQL security releases   */
     731                 :     /*  8.1.4, 8.0.8, 7.4.13, 7.3.15                                        */
     732                 :     /*  PG_HAS_PQESCAPESTRINGCONN is added by a test in 'configure'         */
     733                 :     /*  so it is not set by default when building OGR for Win32             */
     734                 :     /* -------------------------------------------------------------------- */
     735                 : #if defined(PG_HAS_PQESCAPESTRINGCONN)
     736                 :     int nError;
     737                 :     PQescapeStringConn (hPGConn, pszDestStr, pszStrValue, nSrcLen, &nError);
     738                 :     if (nError == 0)
     739                 :         osCommand += pszDestStr;
     740                 :     else
     741                 :         CPLError(CE_Warning, CPLE_AppDefined, 
     742                 :                  "PQescapeString(): %s\n"
     743                 :                  "  input: '%s'\n"
     744                 :                  "    got: '%s'\n",
     745                 :                  PQerrorMessage( hPGConn ),
     746                 :                  pszStrValue, pszDestStr );
     747                 : #else
     748                 :     //PQescapeString(pszDestStr, pszStrValue, nSrcLen);
     749                 :     
     750                 :     int i, j;
     751             108 :     for(i=0,j=0; i < nSrcLen; i++)
     752                 :     {
     753              95 :         if (pszStrValue[i] == '\'')
     754                 :         {
     755               0 :             pszDestStr[j++] = '\'';
     756               0 :             pszDestStr[j++] = '\'';
     757                 :         }
     758              95 :         else if (pszStrValue[i] == '\\')
     759                 :         {
     760               0 :             pszDestStr[j++] = '\\';
     761               0 :             pszDestStr[j++] = '\\';
     762                 :         }
     763                 :         else
     764              95 :             pszDestStr[j++] = pszStrValue[i];
     765                 :     }
     766              13 :     pszDestStr[j] = 0;
     767                 : 
     768              13 :     osCommand += pszDestStr;
     769                 : #endif
     770              13 :     CPLFree(pszDestStr);
     771                 : 
     772              13 :     osCommand += "'";
     773                 : 
     774               0 :     return osCommand;
     775                 : }
     776                 : 
     777                 : 
     778                 : /************************************************************************/
     779                 : /*                    OGRPGDumpEscapeStringList( )                      */
     780                 : /************************************************************************/
     781                 : 
     782               0 : static CPLString OGRPGDumpEscapeStringList(
     783                 :                                        char** papszItems, int bForInsertOrUpdate)
     784                 : {
     785               0 :     int bFirstItem = TRUE;
     786               0 :     CPLString osStr;
     787               0 :     if (bForInsertOrUpdate)
     788               0 :         osStr += "ARRAY[";
     789                 :     else
     790               0 :         osStr += "{";
     791               0 :     while(*papszItems)
     792                 :     {
     793               0 :         if (!bFirstItem)
     794                 :         {
     795               0 :             osStr += ',';
     796                 :         }
     797                 : 
     798               0 :         char* pszStr = *papszItems;
     799               0 :         if (*pszStr != '\0')
     800                 :         {
     801               0 :             if (bForInsertOrUpdate)
     802               0 :                 osStr += OGRPGDumpEscapeString(pszStr, -1, "");
     803                 :             else
     804                 :             {
     805               0 :                 osStr += '"';
     806                 : 
     807               0 :                 while(*pszStr)
     808                 :                 {
     809               0 :                     if (*pszStr == '"' )
     810               0 :                         osStr += "\\";
     811               0 :                     osStr += *pszStr;
     812               0 :                     pszStr++;
     813                 :                 }
     814                 : 
     815               0 :                 osStr += '"';
     816                 :             }
     817                 :         }
     818                 :         else
     819               0 :             osStr += "NULL";
     820                 : 
     821               0 :         bFirstItem = FALSE;
     822                 : 
     823               0 :         papszItems++;
     824                 :     }
     825               0 :     if (bForInsertOrUpdate)
     826               0 :         osStr += "]";
     827                 :     else
     828               0 :         osStr += "}";
     829               0 :     return osStr;
     830                 : }
     831                 : 
     832                 : /************************************************************************/
     833                 : /*                          AppendFieldValue()                          */
     834                 : /*                                                                      */
     835                 : /* Used by CreateFeatureViaInsert() and SetFeature() to format a        */
     836                 : /* non-empty field value                                                */
     837                 : /************************************************************************/
     838                 : 
     839              30 : void OGRPGDumpLayer::AppendFieldValue(CPLString& osCommand,
     840                 :                                        OGRFeature* poFeature, int i)
     841                 : {
     842              30 :     int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
     843                 : 
     844                 :     // We need special formatting for integer list values.
     845              30 :     if(  nOGRFieldType == OFTIntegerList )
     846                 :     {
     847               0 :         int nCount, nOff = 0, j;
     848               0 :         const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
     849               0 :         char *pszNeedToFree = NULL;
     850                 : 
     851               0 :         pszNeedToFree = (char *) CPLMalloc(nCount * 13 + 10);
     852               0 :         strcpy( pszNeedToFree, "'{" );
     853               0 :         for( j = 0; j < nCount; j++ )
     854                 :         {
     855               0 :             if( j != 0 )
     856               0 :                 strcat( pszNeedToFree+nOff, "," );
     857                 : 
     858               0 :             nOff += strlen(pszNeedToFree+nOff);
     859               0 :             sprintf( pszNeedToFree+nOff, "%d", panItems[j] );
     860                 :         }
     861               0 :         strcat( pszNeedToFree+nOff, "}'" );
     862                 : 
     863               0 :         osCommand += pszNeedToFree;
     864               0 :         CPLFree(pszNeedToFree);
     865                 : 
     866               0 :         return;
     867                 :     }
     868                 : 
     869                 :     // We need special formatting for real list values.
     870              30 :     else if( nOGRFieldType == OFTRealList )
     871                 :     {
     872               0 :         int nCount, nOff = 0, j;
     873               0 :         const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);
     874               0 :         char *pszNeedToFree = NULL;
     875                 : 
     876               0 :         pszNeedToFree = (char *) CPLMalloc(nCount * 40 + 10);
     877               0 :         strcpy( pszNeedToFree, "'{" );
     878               0 :         for( j = 0; j < nCount; j++ )
     879                 :         {
     880               0 :             if( j != 0 )
     881               0 :                 strcat( pszNeedToFree+nOff, "," );
     882                 : 
     883               0 :             nOff += strlen(pszNeedToFree+nOff);
     884                 :             //Check for special values. They need to be quoted.
     885               0 :             if( CPLIsNan(padfItems[j]) )
     886               0 :                 sprintf( pszNeedToFree+nOff, "NaN" );
     887               0 :             else if( CPLIsInf(padfItems[j]) )
     888               0 :                 sprintf( pszNeedToFree+nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
     889                 :             else
     890               0 :                 sprintf( pszNeedToFree+nOff, "%.16g", padfItems[j] );
     891                 : 
     892                 :         }
     893               0 :         strcat( pszNeedToFree+nOff, "}'" );
     894                 : 
     895               0 :         osCommand += pszNeedToFree;
     896               0 :         CPLFree(pszNeedToFree);
     897                 : 
     898               0 :         return;
     899                 :     }
     900                 : 
     901                 :     // We need special formatting for string list values.
     902              30 :     else if( nOGRFieldType == OFTStringList )
     903                 :     {
     904               0 :         char **papszItems = poFeature->GetFieldAsStringList(i);
     905                 : 
     906               0 :         osCommand += OGRPGDumpEscapeStringList(papszItems, TRUE);
     907                 : 
     908               0 :         return;
     909                 :     }
     910                 : 
     911                 :     // Binary formatting
     912              30 :     else if( nOGRFieldType == OFTBinary )
     913                 :     {
     914               0 :         osCommand += "'";
     915                 : 
     916               0 :         int nLen = 0;
     917               0 :         GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
     918               0 :         char* pszBytea = GByteArrayToBYTEA( pabyData, nLen);
     919                 : 
     920               0 :         osCommand += pszBytea;
     921                 : 
     922               0 :         CPLFree(pszBytea);
     923               0 :         osCommand += "'";
     924                 : 
     925               0 :         return;
     926                 :     }
     927                 : 
     928                 :     // Flag indicating NULL or not-a-date date value
     929                 :     // e.g. 0000-00-00 - there is no year 0
     930              30 :     OGRBoolean bIsDateNull = FALSE;
     931                 : 
     932              30 :     const char *pszStrValue = poFeature->GetFieldAsString(i);
     933                 : 
     934                 :     // Check if date is NULL: 0000-00-00
     935              30 :     if( nOGRFieldType == OFTDate )
     936                 :     {
     937               0 :         if( EQUALN( pszStrValue, "0000", 4 ) )
     938                 :         {
     939               0 :             pszStrValue = "NULL";
     940               0 :             bIsDateNull = TRUE;
     941                 :         }
     942                 :     }
     943              30 :     else if ( nOGRFieldType == OFTReal )
     944                 :     {
     945              10 :         char* pszComma = strchr((char*)pszStrValue, ',');
     946              10 :         if (pszComma)
     947               0 :             *pszComma = '.';
     948                 :         //Check for special values. They need to be quoted.
     949              10 :         double dfVal = poFeature->GetFieldAsDouble(i);
     950              10 :         if( CPLIsNan(dfVal) )
     951               0 :             pszStrValue = "'NaN'";
     952              10 :         else if( CPLIsInf(dfVal) )
     953               0 :             pszStrValue = (dfVal > 0) ? "'Infinity'" : "'-Infinity'";
     954                 :     }
     955                 : 
     956              40 :     if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTReal
     957                 :         && !bIsDateNull )
     958                 :     {
     959                 :         osCommand += OGRPGDumpEscapeString( pszStrValue,
     960                 :                                         poFeatureDefn->GetFieldDefn(i)->GetWidth(),
     961              10 :                                         poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     962                 :     }
     963                 :     else
     964                 :     {
     965              20 :         osCommand += pszStrValue;
     966                 :     }
     967                 : }
     968                 : 
     969                 : 
     970                 : /************************************************************************/
     971                 : /*                        GByteArrayToBYTEA()                           */
     972                 : /************************************************************************/
     973                 : 
     974               0 : char* OGRPGDumpLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
     975                 : {
     976                 :     char* pszTextBuf;
     977                 : 
     978               0 :     pszTextBuf = (char *) CPLMalloc(nLen*5+1);
     979                 : 
     980               0 :     int  iSrc, iDst=0;
     981                 : 
     982               0 :     for( iSrc = 0; iSrc < nLen; iSrc++ )
     983                 :     {
     984               0 :         if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126
     985               0 :             || pabyData[iSrc] == '\\' )
     986                 :         {
     987               0 :             sprintf( pszTextBuf+iDst, "\\\\%03o", pabyData[iSrc] );
     988               0 :             iDst += 5;
     989                 :         }
     990                 :         else
     991               0 :             pszTextBuf[iDst++] = pabyData[iSrc];
     992                 :     }
     993               0 :     pszTextBuf[iDst] = '\0';
     994                 : 
     995               0 :     return pszTextBuf;
     996                 : }
     997                 : 
     998                 : /************************************************************************/
     999                 : /*                        OGRPGTableLayerGetType()                      */
    1000                 : /************************************************************************/
    1001                 : 
    1002              13 : static CPLString OGRPGTableLayerGetType(OGRFieldDefn& oField,
    1003                 :                                         int bPreservePrecision,
    1004                 :                                         int bApproxOK)
    1005                 : {
    1006                 :     char                szFieldType[256];
    1007                 : 
    1008                 : /* -------------------------------------------------------------------- */
    1009                 : /*      Work out the PostgreSQL type.                                   */
    1010                 : /* -------------------------------------------------------------------- */
    1011              13 :     if( oField.GetType() == OFTInteger )
    1012                 :     {
    1013               3 :         if( oField.GetWidth() > 0 && bPreservePrecision )
    1014               0 :             sprintf( szFieldType, "NUMERIC(%d,0)", oField.GetWidth() );
    1015                 :         else
    1016               3 :             strcpy( szFieldType, "INTEGER" );
    1017                 :     }
    1018              10 :     else if( oField.GetType() == OFTReal )
    1019                 :     {
    1020               3 :         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
    1021                 :             && bPreservePrecision )
    1022                 :             sprintf( szFieldType, "NUMERIC(%d,%d)",
    1023               0 :                      oField.GetWidth(), oField.GetPrecision() );
    1024                 :         else
    1025               3 :             strcpy( szFieldType, "FLOAT8" );
    1026                 :     }
    1027               7 :     else if( oField.GetType() == OFTString )
    1028                 :     {
    1029               7 :         if (oField.GetWidth() > 0 &&  bPreservePrecision )
    1030               3 :             sprintf( szFieldType, "VARCHAR(%d)",  oField.GetWidth() );
    1031                 :         else
    1032               4 :             strcpy( szFieldType, "VARCHAR");
    1033                 :     }
    1034               0 :     else if( oField.GetType() == OFTIntegerList )
    1035                 :     {
    1036               0 :         strcpy( szFieldType, "INTEGER[]" );
    1037                 :     }
    1038               0 :     else if( oField.GetType() == OFTRealList )
    1039                 :     {
    1040               0 :         strcpy( szFieldType, "FLOAT8[]" );
    1041                 :     }
    1042               0 :     else if( oField.GetType() == OFTStringList )
    1043                 :     {
    1044               0 :         strcpy( szFieldType, "varchar[]" );
    1045                 :     }
    1046               0 :     else if( oField.GetType() == OFTDate )
    1047                 :     {
    1048               0 :         strcpy( szFieldType, "date" );
    1049                 :     }
    1050               0 :     else if( oField.GetType() == OFTTime )
    1051                 :     {
    1052               0 :         strcpy( szFieldType, "time" );
    1053                 :     }
    1054               0 :     else if( oField.GetType() == OFTDateTime )
    1055                 :     {
    1056               0 :         strcpy( szFieldType, "timestamp with time zone" );
    1057                 :     }
    1058               0 :     else if( oField.GetType() == OFTBinary )
    1059                 :     {
    1060               0 :         strcpy( szFieldType, "bytea" );
    1061                 :     }
    1062               0 :     else if( bApproxOK )
    1063                 :     {
    1064                 :         CPLError( CE_Warning, CPLE_NotSupported,
    1065                 :                   "Can't create field %s with type %s on PostgreSQL layers.  Creating as VARCHAR.",
    1066                 :                   oField.GetNameRef(),
    1067               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
    1068               0 :         strcpy( szFieldType, "VARCHAR" );
    1069                 :     }
    1070                 :     else
    1071                 :     {
    1072                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1073                 :                   "Can't create field %s with type %s on PostgreSQL layers.",
    1074                 :                   oField.GetNameRef(),
    1075               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
    1076               0 :         strcpy( szFieldType, "");
    1077                 :     }
    1078                 : 
    1079              13 :     return szFieldType;
    1080                 : }
    1081                 : 
    1082                 : /************************************************************************/
    1083                 : /*                           GetNextFeature()                           */
    1084                 : /************************************************************************/
    1085                 : 
    1086              13 : OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
    1087                 :                                      int bApproxOK )
    1088                 : {
    1089              13 :     if (nFeatures != 0)
    1090                 :     {
    1091                 :         CPLError(CE_Failure, CPLE_NotSupported,
    1092               0 :                  "Cannot create field after first feature has been written");
    1093               0 :         return OGRERR_FAILURE;
    1094                 :     }
    1095                 :     
    1096              13 :     CPLString           osCommand;
    1097              13 :     CPLString           osFieldType;
    1098              13 :     OGRFieldDefn        oField( poFieldIn );
    1099                 : 
    1100                 : /* -------------------------------------------------------------------- */
    1101                 : /*      Do we want to "launder" the column names into Postgres          */
    1102                 : /*      friendly format?                                                */
    1103                 : /* -------------------------------------------------------------------- */
    1104              13 :     if( bLaunderColumnNames )
    1105                 :     {
    1106              13 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
    1107                 : 
    1108              13 :         oField.SetName( pszSafeName );
    1109              13 :         CPLFree( pszSafeName );
    1110                 : 
    1111              13 :         if( EQUAL(oField.GetNameRef(),"oid") )
    1112                 :         {
    1113                 :             CPLError( CE_Warning, CPLE_AppDefined,
    1114               0 :                       "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." );
    1115               0 :             oField.SetName( "oid_" );
    1116                 :         }
    1117                 :     }
    1118                 : 
    1119              13 :     const char* pszOverrideType = CSLFetchNameValue(papszOverrideColumnTypes, oField.GetNameRef());
    1120              13 :     if( pszOverrideType != NULL )
    1121               0 :         osFieldType = pszOverrideType;
    1122                 :     else
    1123                 :     {
    1124              13 :         osFieldType = OGRPGTableLayerGetType(oField, bPreservePrecision, bApproxOK);
    1125              13 :         if (osFieldType.size() == 0)
    1126               0 :             return OGRERR_FAILURE;
    1127                 :     }
    1128                 : 
    1129                 : /* -------------------------------------------------------------------- */
    1130                 : /*      Create the new field.                                           */
    1131                 : /* -------------------------------------------------------------------- */
    1132                 :     osCommand.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
    1133                 :                       pszSqlTableName, OGRPGDumpEscapeColumnName(oField.GetNameRef()).c_str(),
    1134              13 :                       osFieldType.c_str() );
    1135              13 :     if (bCreateTable)
    1136              13 :         poDS->Log(osCommand);
    1137                 : 
    1138              13 :     poFeatureDefn->AddFieldDefn( &oField );
    1139                 :     
    1140              13 :     return OGRERR_NONE;
    1141                 : }
    1142                 : 
    1143                 : /************************************************************************/
    1144                 : /*                        SetOverrideColumnTypes()                      */
    1145                 : /************************************************************************/
    1146                 : 
    1147               3 : void OGRPGDumpLayer::SetOverrideColumnTypes( const char* pszOverrideColumnTypes )
    1148                 : {
    1149               3 :     if( pszOverrideColumnTypes == NULL )
    1150               3 :         return;
    1151                 : 
    1152               0 :     const char* pszIter = pszOverrideColumnTypes;
    1153               0 :     CPLString osCur;
    1154               0 :     while(*pszIter != '\0')
    1155                 :     {
    1156               0 :         if( *pszIter == '(' )
    1157                 :         {
    1158                 :             /* Ignore commas inside ( ) pair */
    1159               0 :             while(*pszIter != '\0')
    1160                 :             {
    1161               0 :                 if( *pszIter == ')' )
    1162                 :                 {
    1163               0 :                     osCur += *pszIter;
    1164               0 :                     pszIter ++;
    1165               0 :                     break;
    1166                 :                 }
    1167               0 :                 osCur += *pszIter;
    1168               0 :                 pszIter ++;
    1169                 :             }
    1170               0 :             if( *pszIter == '\0')
    1171               0 :                 break;
    1172                 :         }
    1173                 : 
    1174               0 :         if( *pszIter == ',' )
    1175                 :         {
    1176               0 :             papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
    1177               0 :             osCur = "";
    1178                 :         }
    1179                 :         else
    1180               0 :             osCur += *pszIter;
    1181               0 :         pszIter ++;
    1182                 :     }
    1183               0 :     if( osCur.size() )
    1184               0 :         papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
    1185                 : }

Generated by: LCOV version 1.7