Changeset 91060 in webkit


Ignore:
Timestamp:
Jul 15, 2011 1:35:16 AM (13 years ago)
Author:
commit-queue@webkit.org
Message:

LocalStorage: Changed the value type of ItemTable from TEXT to BLOB
to avoid string truncation.
This patch will also convert the exsisting ItemTable and perform
the DATA MIGRATION job.
https://bugs.webkit.org/show_bug.cgi?id=58762

Patch by Jonathan Dong <Jonathan Dong> on 2011-07-15
Reviewed by Jeremy Orlow.

Tests: manual-tests/localstorage-value-truncation.html

  • manual-tests/localstorage-value-truncation.html: Added.

Demostrate the testcase shown in bug 58762.

  • platform/sql/SQLiteStatement.cpp:

(WebCore::SQLiteStatement::isColumnDeclearedAsBlob):
Test if the pre-defined type of column is BLOB.

  • platform/sql/SQLiteStatement.h:
  • storage/StorageAreaSync.cpp:

Change the localStorage value type from Text to BLOB to avoid the
value string truncation at \x00.
(WebCore::StorageAreaSync::openDatabase):
Change the database structure, use BLOB to replace the TEXT type of
value segment in ItemTable.
(WebCore::StorageAreaSync::migrateItemTableIfNeeded):
Migrate the ItemTable if the pre-defined type of value is TEXT.
(WebCore::StorageAreaSync::performImport):
Use getColumnBlobAsString() to import the BLOB value.
(WebCore::StorageAreaSync::sync):
Use bindBlob() to bind value string to the SQLiteStatement for the
database execution.

  • storage/StorageAreaSync.h:
Location:
trunk/Source/WebCore
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r91058 r91060  
     12011-07-15  Jonathan Dong  <jonathan.dong@torchmobile.com.cn>
     2
     3        LocalStorage: Changed the value type of ItemTable from TEXT to BLOB
     4        to avoid string truncation.
     5        This patch will also convert the exsisting ItemTable and perform
     6        the DATA MIGRATION job.
     7        https://bugs.webkit.org/show_bug.cgi?id=58762
     8
     9        Reviewed by Jeremy Orlow.
     10
     11        Tests: manual-tests/localstorage-value-truncation.html
     12
     13        * manual-tests/localstorage-value-truncation.html: Added.
     14        Demostrate the testcase shown in bug 58762.
     15        * platform/sql/SQLiteStatement.cpp:
     16        (WebCore::SQLiteStatement::isColumnDeclearedAsBlob):
     17        Test if the pre-defined type of column is BLOB.
     18        * platform/sql/SQLiteStatement.h:
     19        * storage/StorageAreaSync.cpp:
     20        Change the localStorage value type from Text to BLOB to avoid the
     21        value string truncation at \x00.
     22        (WebCore::StorageAreaSync::openDatabase):
     23        Change the database structure, use BLOB to replace the TEXT type of
     24        value segment in ItemTable.
     25        (WebCore::StorageAreaSync::migrateItemTableIfNeeded):
     26        Migrate the ItemTable if the pre-defined type of value is TEXT.
     27        (WebCore::StorageAreaSync::performImport):
     28        Use getColumnBlobAsString() to import the BLOB value.
     29        (WebCore::StorageAreaSync::sync):
     30        Use bindBlob() to bind value string to the SQLiteStatement for the
     31        database execution.
     32        * storage/StorageAreaSync.h:
     33
    1342011-07-15  Kentaro Hara  <haraken@google.com>
    235
  • trunk/Source/WebCore/platform/sql/SQLiteStatement.cpp

    r76448 r91060  
    288288}
    289289
     290bool SQLiteStatement::isColumnDeclaredAsBlob(int col)
     291{
     292    ASSERT(col >= 0);
     293    if (!m_statement) {
     294        if (prepare() != SQLITE_OK)
     295            return false;
     296    }
     297
     298    return equalIgnoringCase(String("BLOB"), String(reinterpret_cast<const UChar*>(sqlite3_column_decltype16(m_statement, col))));
     299}
     300
    290301String SQLiteStatement::getColumnName(int col)
    291302{
  • trunk/Source/WebCore/platform/sql/SQLiteStatement.h

    r76448 r91060  
    7575   
    7676    bool isColumnNull(int col);
     77    bool isColumnDeclaredAsBlob(int col);
    7778    String getColumnName(int col);
    7879    SQLValue getColumnValue(int col);
  • trunk/Source/WebCore/storage/StorageAreaSync.cpp

    r81037 r91060  
    3434#include "SQLiteFileSystem.h"
    3535#include "SQLiteStatement.h"
     36#include "SQLiteTransaction.h"
    3637#include "SecurityOrigin.h"
    3738#include "StorageAreaImpl.h"
     
    255256    }
    256257
    257     if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL)")) {
     258    migrateItemTableIfNeeded();
     259
     260    if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB NOT NULL ON CONFLICT FAIL)")) {
    258261        LOG_ERROR("Failed to create table ItemTable for local storage");
    259262        markImported();
     
    263266
    264267    StorageTracker::tracker().setOriginDetails(m_databaseIdentifier, databaseFilename);
     268}
     269
     270void StorageAreaSync::migrateItemTableIfNeeded()
     271{
     272    if (!m_database.tableExists("ItemTable"))
     273        return;
     274
     275    {
     276        SQLiteStatement query(m_database, "SELECT value FROM ItemTable LIMIT 1");
     277        // this query isn't ever executed.
     278        if (query.isColumnDeclaredAsBlob(0))
     279            return;
     280    }
     281
     282    // alter table for backward compliance, change the value type from TEXT to BLOB.
     283    static const char* commands[] = {
     284        "DROP TABLE IF EXISTS ItemTable2",
     285        "CREATE TABLE ItemTable2 (key TEXT UNIQUE ON CONFLICT REPLACE, value BLOB NOT NULL ON CONFLICT FAIL)",
     286        "INSERT INTO ItemTable2 SELECT * from ItemTable",
     287        "DROP TABLE ItemTable",
     288        "ALTER TABLE ItemTable2 RENAME TO ItemTable",
     289        0,
     290    };
     291
     292    SQLiteTransaction transaction(m_database, false);
     293    transaction.begin();
     294    for (size_t i = 0; commands[i]; ++i) {
     295        if (!m_database.executeCommand(commands[i])) {
     296            LOG_ERROR("Failed to migrate table ItemTable for local storage when executing: %s", commands[i]);
     297            transaction.rollback();
     298
     299            // finally it will try to keep a backup of ItemTable for the future restoration.
     300            // NOTICE: this will essentially DELETE the current database, but that's better
     301            // than continually hitting this case and never being able to use the local storage.
     302            // if this is ever hit, it's definitely a bug.
     303            ASSERT_NOT_REACHED();
     304            if (!m_database.executeCommand("ALTER TABLE ItemTable RENAME TO Backup_ItemTable"))
     305                LOG_ERROR("Failed to save ItemTable after migration job failed.");
     306
     307            return;
     308        }
     309    }
     310    transaction.commit();
    265311}
    266312
     
    287333    int result = query.step();
    288334    while (result == SQLResultRow) {
    289         itemMap.set(query.getColumnText(0), query.getColumnText(1));
     335        itemMap.set(query.getColumnText(0), query.getColumnBlobAsString(1));
    290336        result = query.step();
    291337    }
     
    393439        // If the second argument is non-null, we're doing an insert, so bind it as the value.
    394440        if (!it->second.isNull())
    395             query.bindText(2, it->second);
     441            query.bindBlob(2, it->second);
    396442
    397443        int result = query.step();
  • trunk/Source/WebCore/storage/StorageAreaSync.h

    r80892 r91060  
    103103        mutable bool m_importComplete;
    104104        void markImported();
     105        void migrateItemTableIfNeeded();
    105106    };
    106107
Note: See TracChangeset for help on using the changeset viewer.