LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/pgdump - ogrpgdumplayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 411
Code covered: 55.0 % Executed lines: 226

       1                 : /******************************************************************************
       2                 :  * $Id: ogrpgdumplayer.cpp 19705 2010-05-14 19:42:02Z 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 19705 2010-05-14 19:42:02Z 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                 : OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
      52                 :                                const char* pszSchemaName,
      53                 :                                const char* pszLayerName,
      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( pszLayerName );

      63               3 :     poFeatureDefn->Reference();

      64               3 :     nFeatures = 0;

      65               3 :     pszSqlTableName = CPLStrdup(CPLSPrintf("\"%s\".\"%s\"", pszSchemaName, pszLayerName));

      66               3 :     this->pszGeomColumn = (pszGeomColumn) ? CPLStrdup(pszGeomColumn) : NULL;

      67               3 :     this->pszFIDColumn = CPLStrdup(pszFIDColumn);

      68               3 :     this->nCoordDimension = nCoordDimension;

      69               3 :     this->nSRSId = nSRSId;

      70               3 :     this->bCreateTable = bCreateTable;

      71               3 :     bLaunderColumnNames = TRUE;

      72               3 :     bPreservePrecision = TRUE;

      73               3 :     bUseCopy = USE_COPY_UNSET;

      74               3 :     bWriteAsHex = bWriteAsHexIn;

      75               3 :     bCopyActive = FALSE;

      76               3 : }

      77                 : 
      78                 : /************************************************************************/
      79                 : /*                          ~OGRPGDumpLayer()                           */
      80                 : /************************************************************************/
      81                 : 
      82               3 : OGRPGDumpLayer::~OGRPGDumpLayer()

      83                 : {
      84               3 :     EndCopy();

      85                 : 
      86               3 :     poFeatureDefn->Release();

      87               3 :     CPLFree(pszSqlTableName);

      88               3 :     CPLFree(pszGeomColumn);

      89               3 :     CPLFree(pszFIDColumn);

      90               3 : }

      91                 : 
      92                 : /************************************************************************/
      93                 : /*                           GetNextFeature()                           */
      94                 : /************************************************************************/
      95                 : 
      96               0 : OGRFeature *OGRPGDumpLayer::GetNextFeature()

      97                 : {
      98               0 :     CPLError(CE_Failure, CPLE_NotSupported, "PGDump driver is write only");

      99               0 :     return NULL;

     100                 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                           GetNextFeature()                           */
     104                 : /************************************************************************/
     105                 : 
     106               0 : int OGRPGDumpLayer::TestCapability( const char * pszCap )

     107                 : {
     108               0 :     if( EQUAL(pszCap,OLCSequentialWrite) ||

     109                 :         EQUAL(pszCap,OLCCreateField) )
     110               0 :         return TRUE;

     111                 :     else
     112               0 :         return FALSE;

     113                 : }
     114                 : 
     115                 : /************************************************************************/
     116                 : /*                           GeometryToHex()                            */
     117                 : /************************************************************************/
     118                 : 
     119              20 : char *OGRPGDumpLayer::GeometryToHex( OGRGeometry * poGeometry, int nSRSId )

     120                 : {
     121                 :     GByte       *pabyWKB;
     122                 :     char        *pszTextBuf;
     123                 :     char        *pszTextBufCurrent;
     124                 :     char        *pszHex;
     125                 : 
     126              20 :     int nWkbSize = poGeometry->WkbSize();

     127              20 :     pabyWKB = (GByte *) CPLMalloc(nWkbSize);

     128                 : 
     129              20 :     if( poGeometry->exportToWkb( wkbNDR, pabyWKB ) != OGRERR_NONE )

     130                 :     {
     131               0 :         CPLFree( pabyWKB );

     132               0 :         return CPLStrdup("");

     133                 :     }
     134                 : 
     135                 :     /* When converting to hex, each byte takes 2 hex characters.  In addition
     136                 :        we add in 8 characters to represent the SRID integer in hex, and
     137                 :        one for a null terminator */
     138                 : 
     139              20 :     int pszSize = nWkbSize*2 + 8 + 1;

     140              20 :     pszTextBuf = (char *) CPLMalloc(pszSize);

     141              20 :     pszTextBufCurrent = pszTextBuf;

     142                 : 
     143                 :     /* Convert the 1st byte, which is the endianess flag, to hex. */
     144              20 :     pszHex = CPLBinaryToHex( 1, pabyWKB );

     145              20 :     strcpy(pszTextBufCurrent, pszHex );

     146              20 :     CPLFree ( pszHex );

     147              20 :     pszTextBufCurrent += 2;

     148                 : 
     149                 :     /* Next, get the geom type which is bytes 2 through 5 */
     150                 :     GUInt32 geomType;
     151              20 :     memcpy( &geomType, pabyWKB+1, 4 );

     152                 : 
     153                 :     /* Now add the SRID flag if an SRID is provided */
     154              20 :     if (nSRSId != -1)

     155                 :     {
     156                 :         /* Change the flag to wkbNDR (little) endianess */
     157              10 :         GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );

     158                 :         /* Apply the flag */
     159              10 :         geomType = geomType | nGSrsFlag;

     160                 :     }
     161                 : 
     162                 :     /* Now write the geom type which is 4 bytes */
     163              20 :     pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );

     164              20 :     strcpy(pszTextBufCurrent, pszHex );

     165              20 :     CPLFree ( pszHex );

     166              20 :     pszTextBufCurrent += 8;

     167                 : 
     168                 :     /* Now include SRID if provided */
     169              20 :     if (nSRSId != -1)

     170                 :     {
     171                 :         /* Force the srsid to wkbNDR (little) endianess */
     172              10 :         GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );

     173              10 :         pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );

     174              10 :         strcpy(pszTextBufCurrent, pszHex );

     175              10 :         CPLFree ( pszHex );

     176              10 :         pszTextBufCurrent += 8;

     177                 :     }
     178                 : 
     179                 :     /* Copy the rest of the data over - subtract
     180                 :        5 since we already copied 5 bytes above */
     181              20 :     pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );

     182              20 :     strcpy(pszTextBufCurrent, pszHex );

     183              20 :     CPLFree ( pszHex );

     184                 : 
     185              20 :     CPLFree( pabyWKB );

     186                 : 
     187              20 :     return pszTextBuf;

     188                 : }
     189                 : 
     190                 : /************************************************************************/
     191                 : /*                           GetNextFeature()                           */
     192                 : /************************************************************************/
     193                 : 
     194              30 : OGRErr OGRPGDumpLayer::CreateFeature( OGRFeature *poFeature )

     195                 : {
     196              30 :     if( NULL == poFeature )

     197                 :     {
     198                 :         CPLError( CE_Failure, CPLE_AppDefined,
     199               0 :                   "NULL pointer to OGRFeature passed to CreateFeature()." );

     200               0 :         return OGRERR_FAILURE;

     201                 :     }
     202                 : 
     203              30 :     nFeatures ++;

     204                 : 
     205                 :     // We avoid testing the config option too often. 
     206              30 :     if( bUseCopy == USE_COPY_UNSET )

     207               3 :         bUseCopy = CSLTestBoolean( CPLGetConfigOption( "PG_USE_COPY", "NO") );

     208                 : 
     209              30 :     if( !bUseCopy )

     210                 :     {
     211              10 :         return CreateFeatureViaInsert( poFeature );

     212                 :     }
     213                 :     else
     214                 :     {
     215              20 :         if ( !bCopyActive )

     216               2 :             StartCopy();

     217                 : 
     218              20 :         return CreateFeatureViaCopy( poFeature );

     219                 :     }
     220                 : }
     221                 : 
     222                 : /************************************************************************/
     223                 : /*                       CreateFeatureViaInsert()                       */
     224                 : /************************************************************************/
     225                 : 
     226              10 : OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )

     227                 : 
     228                 : {
     229              10 :     CPLString           osCommand;

     230              10 :     int                 i = 0;

     231              10 :     int                 bNeedComma = FALSE;

     232              10 :     OGRErr              eErr = OGRERR_FAILURE;

     233                 :     
     234              10 :     if( NULL == poFeature )

     235                 :     {
     236                 :         CPLError( CE_Failure, CPLE_AppDefined,
     237               0 :                   "NULL pointer to OGRFeature passed to CreateFeatureViaInsert()." );

     238               0 :         return eErr;

     239                 :     }
     240                 : 
     241                 : /* -------------------------------------------------------------------- */
     242                 : /*      Form the INSERT command.                                        */
     243                 : /* -------------------------------------------------------------------- */
     244              10 :     osCommand.Printf( "INSERT INTO %s (", pszSqlTableName );

     245                 : 
     246              10 :     if( poFeature->GetGeometryRef() != NULL )

     247                 :     {
     248              10 :         osCommand = osCommand + "\"" + pszGeomColumn + "\" ";

     249              10 :         bNeedComma = TRUE;

     250                 :     }
     251                 : 
     252              10 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )

     253                 :     {
     254               0 :         if( bNeedComma )

     255               0 :             osCommand += ", ";

     256                 :         
     257               0 :         osCommand = osCommand + "\"" + pszFIDColumn + "\" ";

     258               0 :         bNeedComma = TRUE;

     259                 :     }
     260                 : 
     261              50 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )

     262                 :     {
     263              40 :         if( !poFeature->IsFieldSet( i ) )

     264              10 :             continue;

     265                 : 
     266              30 :         if( !bNeedComma )

     267               0 :             bNeedComma = TRUE;

     268                 :         else
     269              30 :             osCommand += ", ";

     270                 : 
     271                 :         osCommand = osCommand 
     272              30 :             + "\"" + poFeatureDefn->GetFieldDefn(i)->GetNameRef() + "\"";

     273                 :     }
     274                 : 
     275              10 :     osCommand += ") VALUES (";

     276                 : 
     277                 :     /* Set the geometry */
     278              10 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();

     279              10 :     bNeedComma = poGeom != NULL;

     280              10 :     if(  poGeom != NULL)

     281                 :     {
     282              10 :         char    *pszWKT = NULL;

     283                 : 
     284              10 :         poGeom->closeRings();

     285              10 :         poGeom->setCoordinateDimension( nCoordDimension );

     286                 : 
     287              10 :         if( bWriteAsHex )

     288                 :         {
     289              10 :             char* pszHex = GeometryToHex( poGeom, nSRSId );

     290              10 :             osCommand += "'";

     291              10 :             if (pszHex)

     292              10 :                 osCommand += pszHex;

     293              10 :             osCommand += "'";

     294              10 :             CPLFree(pszHex);

     295                 :         }
     296                 :         else
     297                 :         {
     298               0 :             poGeom->exportToWkt( &pszWKT );

     299                 : 
     300               0 :             if( pszWKT != NULL )

     301                 :             {
     302                 :                 osCommand +=
     303                 :                     CPLString().Printf(
     304               0 :                         "GeomFromEWKT('SRID=%d;%s'::TEXT) ", nSRSId, pszWKT );

     305               0 :                 OGRFree( pszWKT );

     306                 :             }
     307                 :             else
     308               0 :                 osCommand += "''";

     309                 :         }
     310                 :     }
     311                 : 
     312                 :     /* Set the FID */
     313              10 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )

     314                 :     {
     315               0 :         if( bNeedComma )

     316               0 :             osCommand += ", ";

     317               0 :         osCommand += CPLString().Printf( "%ld ", poFeature->GetFID() );

     318               0 :         bNeedComma = TRUE;

     319                 :     }
     320                 : 
     321                 : 
     322              50 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )

     323                 :     {
     324              40 :         if( !poFeature->IsFieldSet( i ) )

     325              10 :             continue;

     326                 : 
     327              30 :         if( bNeedComma )

     328              30 :             osCommand += ", ";

     329                 :         else
     330               0 :             bNeedComma = TRUE;

     331                 : 
     332              30 :         AppendFieldValue(osCommand, poFeature, i);

     333                 :     }
     334                 : 
     335              10 :     osCommand += ")";

     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Execute the insert.                                             */
     339                 : /* -------------------------------------------------------------------- */
     340              10 :     poDS->Log(osCommand);

     341                 : 
     342              10 :     return OGRERR_NONE;

     343                 : }
     344                 : 
     345                 : 
     346                 : /************************************************************************/
     347                 : /*                        CreateFeatureViaCopy()                        */
     348                 : /************************************************************************/
     349                 : 
     350              20 : OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )

     351                 : {
     352              20 :     CPLString            osCommand;

     353                 : 
     354                 :     /* First process geometry */
     355              20 :     OGRGeometry *poGeometry = (OGRGeometry *) poFeature->GetGeometryRef();

     356                 :     
     357              20 :     if (pszGeomColumn)

     358                 :     {
     359              10 :         char *pszGeom = NULL;

     360              10 :         if ( NULL != poGeometry /* && (bHasWkb || bHasPostGISGeometry || bHasPostGISGeography) */)

     361                 :         {
     362              10 :             poGeometry->closeRings();

     363              10 :             poGeometry->setCoordinateDimension( nCoordDimension );

     364                 :             
     365                 :             //CheckGeomTypeCompatibility(poGeometry);
     366                 :     
     367                 :             /*if (bHasWkb)
     368                 :                 pszGeom = GeometryToBYTEA( poGeometry );
     369                 :             else*/
     370              10 :                 pszGeom = GeometryToHex( poGeometry, nSRSId );

     371                 :         }
     372                 :     
     373              10 :         if ( pszGeom )

     374                 :         {
     375                 :             osCommand += pszGeom,
     376              10 :             CPLFree( pszGeom );

     377                 :         }
     378                 :         else
     379                 :         {
     380               0 :             osCommand = "\\N";

     381                 :         }
     382                 :     }
     383                 : 
     384                 :     /* Next process the field id column */
     385              20 :     if( /*bHasFid &&*/ poFeatureDefn->GetFieldIndex( pszFIDColumn ) != -1 )

     386                 :     {
     387               0 :         if (osCommand.size() > 0)

     388               0 :             osCommand += "\t";

     389                 :             
     390                 :         /* Set the FID */
     391               0 :         if( poFeature->GetFID() != OGRNullFID )

     392                 :         {
     393               0 :             osCommand += CPLString().Printf("%ld ", poFeature->GetFID());

     394                 :         }
     395                 :         else
     396                 :         {
     397               0 :             osCommand += "\\N" ;

     398                 :         }
     399                 :     }
     400                 : 
     401                 : 
     402                 :     /* Now process the remaining fields */
     403                 : 
     404              20 :     int nFieldCount = poFeatureDefn->GetFieldCount();

     405             100 :     for( int i = 0; i < nFieldCount;  i++ )

     406                 :     {
     407              80 :         const char *pszStrValue = poFeature->GetFieldAsString(i);

     408              80 :         char *pszNeedToFree = NULL;

     409                 : 
     410              80 :         if (osCommand.size() > 0)

     411              70 :             osCommand += "\t";

     412                 :             
     413              80 :         if( !poFeature->IsFieldSet( i ) )

     414                 :         {
     415              20 :             osCommand += "\\N" ;

     416                 : 
     417              20 :             continue;

     418                 :         }
     419                 : 
     420              60 :         int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();

     421                 : 
     422                 :         // We need special formatting for integer list values.
     423              60 :         if( nOGRFieldType == OFTIntegerList )

     424                 :         {
     425               0 :             int nCount, nOff = 0, j;

     426               0 :             const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);

     427                 : 
     428               0 :             pszNeedToFree = (char *) CPLMalloc(nCount * 13 + 10);

     429               0 :             strcpy( pszNeedToFree, "{" );

     430               0 :             for( j = 0; j < nCount; j++ )

     431                 :             {
     432               0 :                 if( j != 0 )

     433               0 :                     strcat( pszNeedToFree+nOff, "," );

     434                 : 
     435               0 :                 nOff += strlen(pszNeedToFree+nOff);

     436               0 :                 sprintf( pszNeedToFree+nOff, "%d", panItems[j] );

     437                 :             }
     438               0 :             strcat( pszNeedToFree+nOff, "}" );

     439               0 :             pszStrValue = pszNeedToFree;

     440                 :         }
     441                 : 
     442                 :         // We need special formatting for real list values.
     443              60 :         else if( nOGRFieldType == OFTRealList )

     444                 :         {
     445               0 :             int nCount, nOff = 0, j;

     446               0 :             const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);

     447                 : 
     448               0 :             pszNeedToFree = (char *) CPLMalloc(nCount * 40 + 10);

     449               0 :             strcpy( pszNeedToFree, "{" );

     450               0 :             for( j = 0; j < nCount; j++ )

     451                 :             {
     452               0 :                 if( j != 0 )

     453               0 :                     strcat( pszNeedToFree+nOff, "," );

     454                 : 
     455               0 :                 nOff += strlen(pszNeedToFree+nOff);

     456               0 :                 sprintf( pszNeedToFree+nOff, "%.16g", padfItems[j] );

     457                 :             }
     458               0 :             strcat( pszNeedToFree+nOff, "}" );

     459               0 :             pszStrValue = pszNeedToFree;

     460                 :         }
     461                 : 
     462                 : 
     463                 :         // We need special formatting for string list values.
     464              60 :         else if( nOGRFieldType == OFTStringList )

     465                 :         {
     466               0 :             CPLString osStr;

     467               0 :             char **papszItems = poFeature->GetFieldAsStringList(i);

     468                 : 
     469               0 :             pszStrValue = pszNeedToFree = CPLStrdup(OGRPGDumpEscapeStringList(papszItems, FALSE));

     470                 :         }
     471                 : 
     472                 :         // Binary formatting
     473              60 :         else if( nOGRFieldType == OFTBinary )

     474                 :         {
     475               0 :             int nLen = 0;

     476               0 :             GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );

     477               0 :             char* pszBytea = GByteArrayToBYTEA( pabyData, nLen);

     478                 : 
     479               0 :             pszStrValue = pszNeedToFree = pszBytea;

     480                 :         }
     481                 : 
     482              80 :         if( nOGRFieldType != OFTIntegerList &&

     483                 :             nOGRFieldType != OFTRealList &&
     484                 :             nOGRFieldType != OFTInteger &&
     485                 :             nOGRFieldType != OFTReal &&
     486                 :             nOGRFieldType != OFTBinary )
     487                 :         {
     488                 :             int         iChar;
     489                 : 
     490             180 :             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )

     491                 :             {
     492             160 :                 if( poFeatureDefn->GetFieldDefn(i)->GetWidth() > 0

     493                 :                     && iChar == poFeatureDefn->GetFieldDefn(i)->GetWidth() )
     494                 :                 {
     495                 :                     CPLDebug( "PG",
     496                 :                               "Truncated %s field value, it was too long.",
     497               0 :                               poFeatureDefn->GetFieldDefn(i)->GetNameRef() );

     498               0 :                     break;

     499                 :                 }
     500                 : 
     501                 :                 /* Escape embedded \, \t, \n, \r since they will cause COPY
     502                 :                    to misinterpret a line of text and thus abort */
     503             160 :                 if( pszStrValue[iChar] == '\\' || 

     504                 :                     pszStrValue[iChar] == '\t' || 
     505                 :                     pszStrValue[iChar] == '\r' || 
     506                 :                     pszStrValue[iChar] == '\n'   )
     507                 :                 {
     508               0 :                     osCommand += '\\';

     509                 :                 }
     510                 : 
     511             160 :                 osCommand += pszStrValue[iChar];

     512                 :             }
     513                 :         }
     514                 :         else
     515                 :         {
     516              40 :             osCommand += pszStrValue;

     517                 :         }
     518                 : 
     519              60 :         if( pszNeedToFree )

     520               0 :             CPLFree( pszNeedToFree );

     521                 :     }
     522                 : 
     523                 :     /* Add end of line marker */
     524                 :     //osCommand += "\n";
     525                 : 
     526                 : 
     527                 :     /* ------------------------------------------------------------ */
     528                 :     /*      Execute the copy.                                       */
     529                 :     /* ------------------------------------------------------------ */
     530                 : 
     531              20 :     OGRErr result = OGRERR_NONE;

     532                 : 
     533              20 :     poDS->Log(osCommand, FALSE);

     534                 : 
     535              20 :     return result;

     536                 : }
     537                 : 
     538                 : /************************************************************************/
     539                 : /*                             StartCopy()                              */
     540                 : /************************************************************************/
     541                 : 
     542               2 : OGRErr OGRPGDumpLayer::StartCopy()

     543                 : 
     544                 : {
     545                 :     /* Tell the datasource we are now planning to copy data */
     546               2 :     poDS->StartCopy( this ); 

     547                 : 
     548               2 :     CPLString osFields = BuildCopyFields();

     549                 : 
     550               2 :     int size = strlen(osFields) +  strlen(pszSqlTableName) + 100;

     551               2 :     char *pszCommand = (char *) CPLMalloc(size);

     552                 : 
     553                 :     sprintf( pszCommand,
     554                 :              "COPY %s (%s) FROM STDIN",
     555               2 :              pszSqlTableName, osFields.c_str() );

     556                 : 
     557               2 :     poDS->Log(pszCommand);

     558               2 :     bCopyActive = TRUE;

     559                 : 
     560               2 :     CPLFree( pszCommand );

     561                 : 
     562               2 :     return OGRERR_NONE;

     563                 : }
     564                 : 
     565                 : /************************************************************************/
     566                 : /*                              EndCopy()                               */
     567                 : /************************************************************************/
     568                 : 
     569               5 : OGRErr OGRPGDumpLayer::EndCopy()

     570                 : 
     571                 : {
     572               5 :     if( !bCopyActive )

     573               3 :         return OGRERR_NONE;

     574                 : 
     575               2 :     bCopyActive = FALSE;

     576                 : 
     577               2 :     poDS->Log("\\.", FALSE);

     578               2 :     poDS->Log("END");

     579                 : 
     580               2 :     bUseCopy = USE_COPY_UNSET;

     581                 : 
     582               2 :     return OGRERR_NONE;

     583                 : }
     584                 : 
     585                 : /************************************************************************/
     586                 : /*                          BuildCopyFields()                           */
     587                 : /************************************************************************/
     588                 : 
     589               2 : CPLString OGRPGDumpLayer::BuildCopyFields()

     590                 : {
     591               2 :     int     i = 0;

     592               2 :     CPLString osFieldList;

     593                 : 
     594               2 :     if( /*bHasFid &&*/ poFeatureDefn->GetFieldIndex( pszFIDColumn ) != -1 )

     595                 :     {
     596               0 :         osFieldList += "\"";

     597               0 :         osFieldList += pszFIDColumn;

     598               0 :         osFieldList += "\"";

     599                 :     }
     600                 : 
     601               2 :     if( pszGeomColumn )

     602                 :     {
     603               1 :         if( strlen(osFieldList) > 0 )

     604               0 :             osFieldList += ", ";

     605                 : 
     606               1 :         osFieldList += "\"";

     607               1 :         osFieldList += pszGeomColumn;

     608               1 :         osFieldList += "\"";

     609                 :     }
     610                 : 
     611              10 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )

     612                 :     {
     613               8 :         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();

     614                 : 
     615               8 :         if( strlen(osFieldList) > 0 )

     616               7 :             osFieldList += ", ";

     617                 : 
     618               8 :         osFieldList += "\"";

     619               8 :         osFieldList += pszName;

     620               8 :         osFieldList += "\"" ;

     621                 :     }
     622                 : 
     623               0 :     return osFieldList;

     624                 : }
     625                 : 
     626                 : /************************************************************************/
     627                 : /*                             EscapeString( )                          */
     628                 : /************************************************************************/
     629                 : 
     630                 : static CPLString OGRPGDumpEscapeString(
     631                 :                                    const char* pszStrValue, int nMaxLength,
     632              10 :                                    const char* pszFieldName)

     633                 : {
     634              10 :     CPLString osCommand;

     635                 : 
     636                 :     /* We need to quote and escape string fields. */
     637              10 :     osCommand += "'";

     638                 : 
     639              10 :     int nSrcLen = strlen(pszStrValue);

     640              10 :     if (nMaxLength > 0 && nSrcLen > nMaxLength)

     641                 :     {
     642                 :         CPLDebug( "PG",
     643                 :                   "Truncated %s field value, it was too long.",
     644               0 :                   pszFieldName );

     645               0 :         nSrcLen = nMaxLength;

     646                 :         
     647               0 :         while( nSrcLen > 0 && ((unsigned char *) pszStrValue)[nSrcLen-1] > 127 )

     648                 :         {
     649               0 :             CPLDebug( "PG", "Backup to start of multi-byte character." );

     650               0 :             nSrcLen--;

     651                 :         }
     652                 :     }
     653                 : 
     654              10 :     char* pszDestStr = (char*)CPLMalloc(2 * nSrcLen + 1);

     655                 : 
     656                 :     /* -------------------------------------------------------------------- */
     657                 :     /*  PQescapeStringConn was introduced in PostgreSQL security releases   */
     658                 :     /*  8.1.4, 8.0.8, 7.4.13, 7.3.15                                        */
     659                 :     /*  PG_HAS_PQESCAPESTRINGCONN is added by a test in 'configure'         */
     660                 :     /*  so it is not set by default when building OGR for Win32             */
     661                 :     /* -------------------------------------------------------------------- */
     662                 : #if defined(PG_HAS_PQESCAPESTRINGCONN)
     663                 :     int nError;
     664                 :     PQescapeStringConn (hPGConn, pszDestStr, pszStrValue, nSrcLen, &nError);
     665                 :     if (nError == 0)
     666                 :         osCommand += pszDestStr;
     667                 :     else
     668                 :         CPLError(CE_Warning, CPLE_AppDefined, 
     669                 :                  "PQescapeString(): %s\n"
     670                 :                  "  input: '%s'\n"
     671                 :                  "    got: '%s'\n",
     672                 :                  PQerrorMessage( hPGConn ),
     673                 :                  pszStrValue, pszDestStr );
     674                 : #else
     675                 :     //PQescapeString(pszDestStr, pszStrValue, nSrcLen);
     676                 :     
     677                 :     int i, j;
     678              90 :     for(i=0,j=0; i < nSrcLen; i++)

     679                 :     {
     680              80 :         if (pszStrValue[i] == '\'')

     681                 :         {
     682               0 :             pszDestStr[j++] = '\'';

     683               0 :             pszDestStr[j++] = '\'';

     684                 :         }
     685              80 :         else if (pszStrValue[i] == '\\')

     686                 :         {
     687               0 :             pszDestStr[j++] = '\\';

     688               0 :             pszDestStr[j++] = '\\';

     689                 :         }
     690                 :         else
     691              80 :             pszDestStr[j++] = pszStrValue[i];

     692                 :     }
     693              10 :     pszDestStr[j] = 0;

     694                 : 
     695              10 :     osCommand += pszDestStr;

     696                 : #endif
     697              10 :     CPLFree(pszDestStr);

     698                 : 
     699              10 :     osCommand += "'";

     700                 : 
     701               0 :     return osCommand;

     702                 : }
     703                 : 
     704                 : 
     705                 : /************************************************************************/
     706                 : /*                    OGRPGDumpEscapeStringList( )                      */
     707                 : /************************************************************************/
     708                 : 
     709                 : static CPLString OGRPGDumpEscapeStringList(
     710               0 :                                        char** papszItems, int bForInsertOrUpdate)

     711                 : {
     712               0 :     int bFirstItem = TRUE;

     713               0 :     CPLString osStr;

     714               0 :     if (bForInsertOrUpdate)

     715               0 :         osStr += "ARRAY[";

     716                 :     else
     717               0 :         osStr += "{";

     718               0 :     while(*papszItems)

     719                 :     {
     720               0 :         if (!bFirstItem)

     721                 :         {
     722               0 :             osStr += ',';

     723                 :         }
     724                 : 
     725               0 :         char* pszStr = *papszItems;

     726               0 :         if (*pszStr != '\0')

     727                 :         {
     728               0 :             if (bForInsertOrUpdate)

     729               0 :                 osStr += OGRPGDumpEscapeString(pszStr, -1, "");

     730                 :             else
     731                 :             {
     732               0 :                 osStr += '"';

     733                 : 
     734               0 :                 while(*pszStr)

     735                 :                 {
     736               0 :                     if (*pszStr == '"' )

     737               0 :                         osStr += "\\";

     738               0 :                     osStr += *pszStr;

     739               0 :                     pszStr++;

     740                 :                 }
     741                 : 
     742               0 :                 osStr += '"';

     743                 :             }
     744                 :         }
     745                 :         else
     746               0 :             osStr += "NULL";

     747                 : 
     748               0 :         bFirstItem = FALSE;

     749                 : 
     750               0 :         papszItems++;

     751                 :     }
     752               0 :     if (bForInsertOrUpdate)

     753               0 :         osStr += "]";

     754                 :     else
     755               0 :         osStr += "}";

     756               0 :     return osStr;

     757                 : }
     758                 : 
     759                 : /************************************************************************/
     760                 : /*                          AppendFieldValue()                          */
     761                 : /*                                                                      */
     762                 : /* Used by CreateFeatureViaInsert() and SetFeature() to format a        */
     763                 : /* non-empty field value                                                */
     764                 : /************************************************************************/
     765                 : 
     766                 : void OGRPGDumpLayer::AppendFieldValue(CPLString& osCommand,
     767              30 :                                        OGRFeature* poFeature, int i)

     768                 : {
     769              30 :     int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();

     770                 : 
     771                 :     // We need special formatting for integer list values.
     772              30 :     if(  nOGRFieldType == OFTIntegerList )

     773                 :     {
     774               0 :         int nCount, nOff = 0, j;

     775               0 :         const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);

     776               0 :         char *pszNeedToFree = NULL;

     777                 : 
     778               0 :         pszNeedToFree = (char *) CPLMalloc(nCount * 13 + 10);

     779               0 :         strcpy( pszNeedToFree, "'{" );

     780               0 :         for( j = 0; j < nCount; j++ )

     781                 :         {
     782               0 :             if( j != 0 )

     783               0 :                 strcat( pszNeedToFree+nOff, "," );

     784                 : 
     785               0 :             nOff += strlen(pszNeedToFree+nOff);

     786               0 :             sprintf( pszNeedToFree+nOff, "%d", panItems[j] );

     787                 :         }
     788               0 :         strcat( pszNeedToFree+nOff, "}'" );

     789                 : 
     790               0 :         osCommand += pszNeedToFree;

     791               0 :         CPLFree(pszNeedToFree);

     792                 : 
     793               0 :         return;

     794                 :     }
     795                 : 
     796                 :     // We need special formatting for real list values.
     797              30 :     else if( nOGRFieldType == OFTRealList )

     798                 :     {
     799               0 :         int nCount, nOff = 0, j;

     800               0 :         const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);

     801               0 :         char *pszNeedToFree = NULL;

     802                 : 
     803               0 :         pszNeedToFree = (char *) CPLMalloc(nCount * 40 + 10);

     804               0 :         strcpy( pszNeedToFree, "'{" );

     805               0 :         for( j = 0; j < nCount; j++ )

     806                 :         {
     807               0 :             if( j != 0 )

     808               0 :                 strcat( pszNeedToFree+nOff, "," );

     809                 : 
     810               0 :             nOff += strlen(pszNeedToFree+nOff);

     811               0 :             sprintf( pszNeedToFree+nOff, "%.16g", padfItems[j] );

     812                 :         }
     813               0 :         strcat( pszNeedToFree+nOff, "}'" );

     814                 : 
     815               0 :         osCommand += pszNeedToFree;

     816               0 :         CPLFree(pszNeedToFree);

     817                 : 
     818               0 :         return;

     819                 :     }
     820                 : 
     821                 :     // We need special formatting for string list values.
     822              30 :     else if( nOGRFieldType == OFTStringList )

     823                 :     {
     824               0 :         char **papszItems = poFeature->GetFieldAsStringList(i);

     825                 : 
     826               0 :         osCommand += OGRPGDumpEscapeStringList(papszItems, TRUE);

     827                 : 
     828               0 :         return;

     829                 :     }
     830                 : 
     831                 :     // Binary formatting
     832              30 :     else if( nOGRFieldType == OFTBinary )

     833                 :     {
     834               0 :         osCommand += "'";

     835                 : 
     836               0 :         int nLen = 0;

     837               0 :         GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );

     838               0 :         char* pszBytea = GByteArrayToBYTEA( pabyData, nLen);

     839                 : 
     840               0 :         osCommand += pszBytea;

     841                 : 
     842               0 :         CPLFree(pszBytea);

     843               0 :         osCommand += "'";

     844                 : 
     845               0 :         return;

     846                 :     }
     847                 : 
     848                 :     // Flag indicating NULL or not-a-date date value
     849                 :     // e.g. 0000-00-00 - there is no year 0
     850              30 :     OGRBoolean bIsDateNull = FALSE;

     851                 : 
     852              30 :     const char *pszStrValue = poFeature->GetFieldAsString(i);

     853                 : 
     854                 :     // Check if date is NULL: 0000-00-00
     855              30 :     if( nOGRFieldType == OFTDate )

     856                 :     {
     857               0 :         if( EQUALN( pszStrValue, "0000", 4 ) )

     858                 :         {
     859               0 :             pszStrValue = "NULL";

     860               0 :             bIsDateNull = TRUE;

     861                 :         }
     862                 :     }
     863                 : 
     864              40 :     if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTReal

     865                 :         && !bIsDateNull )
     866                 :     {
     867                 :         osCommand += OGRPGDumpEscapeString( pszStrValue,
     868                 :                                         poFeatureDefn->GetFieldDefn(i)->GetWidth(),
     869              10 :                                         poFeatureDefn->GetFieldDefn(i)->GetNameRef() );

     870                 :     }
     871                 :     else
     872                 :     {
     873              20 :         osCommand += pszStrValue;

     874                 :     }
     875                 : }
     876                 : 
     877                 : 
     878                 : /************************************************************************/
     879                 : /*                        GByteArrayToBYTEA()                           */
     880                 : /************************************************************************/
     881                 : 
     882               0 : char* OGRPGDumpLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)

     883                 : {
     884                 :     char* pszTextBuf;
     885                 : 
     886               0 :     pszTextBuf = (char *) CPLMalloc(nLen*5+1);

     887                 : 
     888               0 :     int  iSrc, iDst=0;

     889                 : 
     890               0 :     for( iSrc = 0; iSrc < nLen; iSrc++ )

     891                 :     {
     892               0 :         if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126

     893                 :             || pabyData[iSrc] == '\\' )
     894                 :         {
     895               0 :             sprintf( pszTextBuf+iDst, "\\\\%03o", pabyData[iSrc] );

     896               0 :             iDst += 5;

     897                 :         }
     898                 :         else
     899               0 :             pszTextBuf[iDst++] = pabyData[iSrc];

     900                 :     }
     901               0 :     pszTextBuf[iDst] = '\0';

     902                 : 
     903               0 :     return pszTextBuf;

     904                 : }
     905                 : 
     906                 : /************************************************************************/
     907                 : /*                           GetNextFeature()                           */
     908                 : /************************************************************************/
     909                 : 
     910                 : OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
     911              12 :                                      int bApproxOK )

     912                 : {
     913              12 :     if (nFeatures != 0)

     914                 :     {
     915                 :         CPLError(CE_Failure, CPLE_NotSupported,
     916               0 :                  "Cannot create field after first feature has been written");

     917               0 :         return OGRERR_FAILURE;

     918                 :     }
     919                 :     
     920              12 :     CPLString           osCommand;

     921                 :     char                szFieldType[256];
     922              12 :     OGRFieldDefn        oField( poFieldIn );

     923                 : 
     924                 : /* -------------------------------------------------------------------- */
     925                 : /*      Do we want to "launder" the column names into Postgres          */
     926                 : /*      friendly format?                                                */
     927                 : /* -------------------------------------------------------------------- */
     928              12 :     if( bLaunderColumnNames )

     929                 :     {
     930              12 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );

     931                 : 
     932              12 :         oField.SetName( pszSafeName );

     933              12 :         CPLFree( pszSafeName );

     934                 : 
     935              12 :         if( EQUAL(oField.GetNameRef(),"oid") )

     936                 :         {
     937                 :             CPLError( CE_Warning, CPLE_AppDefined,
     938               0 :                       "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." );

     939               0 :             oField.SetName( "oid_" );

     940                 :         }
     941                 :     }
     942                 : 
     943                 : /* -------------------------------------------------------------------- */
     944                 : /*      Work out the PostgreSQL type.                                   */
     945                 : /* -------------------------------------------------------------------- */
     946              12 :     if( oField.GetType() == OFTInteger )

     947                 :     {
     948               3 :         if( oField.GetWidth() > 0 && bPreservePrecision )

     949               0 :             sprintf( szFieldType, "NUMERIC(%d,0)", oField.GetWidth() );

     950                 :         else
     951               3 :             strcpy( szFieldType, "INTEGER" );

     952                 :     }
     953               9 :     else if( oField.GetType() == OFTReal )

     954                 :     {
     955               3 :         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0

     956                 :             && bPreservePrecision )
     957                 :             sprintf( szFieldType, "NUMERIC(%d,%d)",
     958               0 :                      oField.GetWidth(), oField.GetPrecision() );

     959                 :         else
     960               3 :             strcpy( szFieldType, "FLOAT8" );

     961                 :     }
     962               6 :     else if( oField.GetType() == OFTString )

     963                 :     {
     964               6 :         if( oField.GetWidth() == 0 || !bPreservePrecision )

     965               3 :             strcpy( szFieldType, "VARCHAR" );

     966                 :         else
     967               3 :             sprintf( szFieldType, "CHAR(%d)", oField.GetWidth() );

     968                 :     }
     969               0 :     else if( oField.GetType() == OFTIntegerList )

     970                 :     {
     971               0 :         strcpy( szFieldType, "INTEGER[]" );

     972                 :     }
     973               0 :     else if( oField.GetType() == OFTRealList )

     974                 :     {
     975               0 :         strcpy( szFieldType, "FLOAT8[]" );

     976                 :     }
     977               0 :     else if( oField.GetType() == OFTStringList )

     978                 :     {
     979               0 :         strcpy( szFieldType, "varchar[]" );

     980                 :     }
     981               0 :     else if( oField.GetType() == OFTDate )

     982                 :     {
     983               0 :         strcpy( szFieldType, "date" );

     984                 :     }
     985               0 :     else if( oField.GetType() == OFTTime )

     986                 :     {
     987               0 :         strcpy( szFieldType, "time" );

     988                 :     }
     989               0 :     else if( oField.GetType() == OFTDateTime )

     990                 :     {
     991               0 :         strcpy( szFieldType, "timestamp with time zone" );

     992                 :     }
     993               0 :     else if( oField.GetType() == OFTBinary )

     994                 :     {
     995               0 :         strcpy( szFieldType, "bytea" );

     996                 :     }
     997               0 :     else if( bApproxOK )

     998                 :     {
     999                 :         CPLError( CE_Warning, CPLE_NotSupported,
    1000                 :                   "Can't create field %s with type %s on PostgreSQL layers.  Creating as VARCHAR.",
    1001                 :                   oField.GetNameRef(),
    1002               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );

    1003               0 :         strcpy( szFieldType, "VARCHAR" );

    1004                 :     }
    1005                 :     else
    1006                 :     {
    1007                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1008                 :                   "Can't create field %s with type %s on PostgreSQL layers.",
    1009                 :                   oField.GetNameRef(),
    1010               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );

    1011                 : 
    1012              12 :         return OGRERR_FAILURE;

    1013                 :     }
    1014                 : 
    1015                 : /* -------------------------------------------------------------------- */
    1016                 : /*      Create the new field.                                           */
    1017                 : /* -------------------------------------------------------------------- */
    1018                 :     osCommand.Printf( "ALTER TABLE %s ADD COLUMN \"%s\" %s",
    1019              12 :                       pszSqlTableName, oField.GetNameRef(), szFieldType );

    1020              12 :     if (bCreateTable)

    1021              12 :         poDS->Log(osCommand);

    1022                 : 
    1023              12 :     poFeatureDefn->AddFieldDefn( &oField );

    1024                 :     
    1025              12 :     return OGRERR_NONE;

    1026                 : }

Generated by: LTP GCOV extension version 1.5