From 96d6cf3e4131973fd6583a5feb6e9554f3461cd3 Mon Sep 17 00:00:00 2001
From: Andrey Kiselev <dron@mns.spb.ru>
Date: Tue, 18 Nov 2008 17:58:29 +0300
Subject: [PATCH] Use the ALTER TABLE command when adding fields instead of the whole table rewriting.

---
 .../ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp |  172 ++------------------
 1 files changed, 12 insertions(+), 160 deletions(-)

diff --git a/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index 40502eb..967c8bd 100644
--- a/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -378,7 +378,6 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
                                          int bApproxOK )
 
 {
-    char                szFieldType[256];
     OGRFieldDefn        oField( poFieldIn );
 
     ResetReading();
@@ -396,96 +395,10 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     }
     
 /* -------------------------------------------------------------------- */
-/*      Work out the SQLite type.                                       */
-/* -------------------------------------------------------------------- */
-    if( oField.GetType() == OFTInteger )
-    {
-        strcpy( szFieldType, "INTEGER" );
-    }
-    else if( oField.GetType() == OFTReal )
-    {
-        strcpy( szFieldType, "FLOAT" );
-    }
-    else if( oField.GetType() == OFTBinary )
-    {
-        strcpy( szFieldType, "BLOB" );
-    }
-    else
-    {
-        strcpy( szFieldType, "VARCHAR" );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      How much space do we need for the list of fields.               */
-/* -------------------------------------------------------------------- */
-    int iField, nFieldListLen = 100;
-    char *pszOldFieldList, *pszNewFieldList;
-
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
-    {
-        nFieldListLen += 
-            strlen(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) + 50;
-    }
-
-    nFieldListLen += strlen( oField.GetNameRef() );
-
-    pszOldFieldList = (char *) CPLCalloc(1,nFieldListLen);
-    pszNewFieldList = (char *) CPLCalloc(1,nFieldListLen);
-
-/* -------------------------------------------------------------------- */
-/*      Build list of old fields, and the list of new fields.           */
+/*      Add the new field.                                              */
 /* -------------------------------------------------------------------- */
     const char *pszType;
-    sprintf( pszOldFieldList, "%s", "OGC_FID" );
-    sprintf( pszNewFieldList, "%s", "OGC_FID INTEGER PRIMARY KEY" );
-    
-    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
-
-    if( poFeatureDefn->GetGeomType() != wkbNone )
-    {
-        strcat( pszOldFieldList, "," );
-        strcat( pszNewFieldList, "," );
-
-        strcat( pszOldFieldList, osGeomColumn );
-        strcat( pszNewFieldList, osGeomColumn );
-
-        if( EQUAL(osGeomFormat,"WKB") )
-            strcat( pszNewFieldList, " BLOB" );
-        else
-            strcat( pszNewFieldList, " VARCHAR" );
-
-        iNextOrdinal++;
-    }
-
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
-    {
-        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
-
-        // we already added OGC_FID so don't do it again
-        if( EQUAL(poFldDefn->GetNameRef(),"OGC_FID") )
-            continue;
 
-        if( poFldDefn->GetType() == OFTInteger )
-            pszType = "INTEGER";
-        else if( poFldDefn->GetType() == OFTReal )
-            pszType = "FLOAT";
-        else if( poFldDefn->GetType() == OFTBinary )
-            pszType = "BLOB";
-        else
-            pszType = "VARCHAR";
-        
-        sprintf( pszOldFieldList+strlen(pszOldFieldList), 
-                 ", '%s'", poFldDefn->GetNameRef() );
-
-        sprintf( pszNewFieldList+strlen(pszNewFieldList), 
-                 ", '%s' %s", poFldDefn->GetNameRef(), pszType );
-
-        iNextOrdinal++;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Add the new field.                                              */
-/* -------------------------------------------------------------------- */
     if( oField.GetType() == OFTInteger )
         pszType = "INTEGER";
     else if( oField.GetType() == OFTReal )
@@ -495,83 +408,25 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     else
         pszType = "VARCHAR";
     
-    sprintf( pszNewFieldList+strlen(pszNewFieldList), 
-             ", '%s' %s", oField.GetNameRef(), pszType );
-
-/* ==================================================================== */
-/*      Backup, destroy, recreate and repopulate the table.  SQLite     */
-/*      has no ALTER TABLE so we have to do all this to add a           */
-/*      column.                                                         */
-/* ==================================================================== */
-
 /* -------------------------------------------------------------------- */
-/*      Do this all in a transaction.                                   */
+/*      Add a column to the table. Do this all in a transaction.        */
 /* -------------------------------------------------------------------- */
     poDS->SoftStartTransaction();
 
 /* -------------------------------------------------------------------- */
-/*      Make a backup of the table.                                     */
-/* -------------------------------------------------------------------- */
-    int rc;
-    char *pszErrMsg = NULL;
-    sqlite3 *hDB = poDS->GetDB();
-    
-    rc = sqlite3_exec( hDB, 
-                       CPLSPrintf( "CREATE TEMPORARY TABLE t1_back(%s)",
-                                   pszOldFieldList ),
-                       NULL, NULL, &pszErrMsg );
+    int         rc;
+    char        *pszErrMsg = NULL;
+    CPLString   osCommand;
 
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
-                           CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
-                                       pszOldFieldList, 
-                                       poFeatureDefn->GetName() ),
-                           NULL, NULL, &pszErrMsg );
+    osCommand.Printf( "ALTER TABLE '%s' ADD COLUMN '%s' %s",
+                      poFeatureDefn->GetName(),
+                      oField.GetNameRef(), pszType );
 
+#ifdef DEBUG
+    CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
+#endif
 
-/* -------------------------------------------------------------------- */
-/*      Drop the original table, and recreate with new field.           */
-/* -------------------------------------------------------------------- */
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
-                           CPLSPrintf( "DROP TABLE '%s'", 
-                                       poFeatureDefn->GetName() ),
-                           NULL, NULL, &pszErrMsg );
-
-    if( rc == SQLITE_OK )
-    {
-        const char *pszCmd = 
-            CPLSPrintf( "CREATE TABLE '%s' (%s)", 
-                        poFeatureDefn->GetName(),
-                        pszNewFieldList );
-        rc = sqlite3_exec( hDB, pszCmd, 
-                           NULL, NULL, &pszErrMsg );
-
-        CPLDebug( "OGR_SQLITE", "exec(%s)", pszCmd );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Copy backup field values into new table.                        */
-/* -------------------------------------------------------------------- */
-    
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
-                           CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
-                                       poFeatureDefn->GetName(),
-                                       pszOldFieldList ),
-                           NULL, NULL, &pszErrMsg );
-
-    CPLFree( pszOldFieldList );
-    CPLFree( pszNewFieldList );
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup backup table.                                           */
-/* -------------------------------------------------------------------- */
-    
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB, 
-                           CPLSPrintf( "DROP TABLE t1_back" ),
-                           NULL, NULL, &pszErrMsg );
+    rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
 
 /* -------------------------------------------------------------------- */
 /*      COMMIT on success or ROLLBACK on failuire.                      */
@@ -601,9 +456,6 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     poFeatureDefn->AddFieldDefn( &oField );
 
     iNewField = poFeatureDefn->GetFieldCount() - 1;
-    panFieldOrdinals = (int *) 
-        CPLRealloc(panFieldOrdinals, (iNewField+1) * sizeof(int) );
-    panFieldOrdinals[iNewField] = iNextOrdinal;
 
     return OGRERR_NONE;
 }
-- 
1.5.6.5


