Changeset 66820 in webkit


Ignore:
Timestamp:
Sep 6, 2010 3:33:31 AM (14 years ago)
Author:
jorlow@chromium.org
Message:

2010-08-26 Jeremy Orlow <jorlow@chromium.org>

Reviewed by Steve Block.

Add index insertion support to IndexedDB.
https://bugs.webkit.org/show_bug.cgi?id=44695

  • storage/indexeddb/objectstore-basics-expected.txt:
  • storage/indexeddb/script-tests/objectstore-basics.js: (createSuccess): (addIndexSuccess): (getSuccess):

2010-08-26 Jeremy Orlow <jorlow@chromium.org>

Reviewed by Steve Block.

Add index insertion support to IndexedDB.
https://bugs.webkit.org/show_bug.cgi?id=44695

Whenever you insert an item into an ObjectStore, it should use all
indexes' key paths to insert corresponding entries into each index.
Also data should be deleted out of the index when it goes away.

Not much testing yet since there's no way to directly observe indexes.
More will be in next patch.

  • storage/IDBDatabaseBackendImpl.cpp: (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
  • storage/IDBFactoryBackendImpl.cpp: (WebCore::createTables):
  • storage/IDBIndex.idl:
  • storage/IDBIndexBackendImpl.cpp: (WebCore::whereClause): (WebCore::bindWhereClause): (WebCore::IDBIndexBackendImpl::addingKeyAllowed):
  • storage/IDBIndexBackendImpl.h: (WebCore::IDBIndexBackendImpl::id):
  • storage/IDBKey.cpp: (WebCore::IDBKey::whereSyntax): (WebCore::IDBKey::bind): (WebCore::IDBKey::bindWithNulls):
  • storage/IDBKey.h:
  • storage/IDBObjectStore.idl:
  • storage/IDBObjectStoreBackendImpl.cpp: (WebCore::whereClause): (WebCore::bindWhereClause): (WebCore::IDBObjectStoreBackendImpl::get): (WebCore::fetchKeyFromKeyPath): (WebCore::putObjectStoreData): (WebCore::putIndexData): (WebCore::IDBObjectStoreBackendImpl::put): (WebCore::IDBObjectStoreBackendImpl::remove): (WebCore::IDBObjectStoreBackendImpl::createIndex): (WebCore::doDelete): (WebCore::IDBObjectStoreBackendImpl::removeIndex): (WebCore::IDBObjectStoreBackendImpl::openCursor):
  • storage/IDBObjectStoreBackendImpl.h:

2010-08-26 Jeremy Orlow <jorlow@chromium.org>

Reviewed by Steve Block.

Add index insertion support to IndexedDB.
https://bugs.webkit.org/show_bug.cgi?id=44695

Add asserts on the [] operator.

  • public/WebVector.h: (WebKit::WebVector::operator[]):
Location:
trunk
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r66817 r66820  
     12010-08-26  Jeremy Orlow  <jorlow@chromium.org>
     2
     3        Reviewed by Steve Block.
     4
     5        Add index insertion support to IndexedDB.
     6        https://bugs.webkit.org/show_bug.cgi?id=44695
     7
     8        * storage/indexeddb/objectstore-basics-expected.txt:
     9        * storage/indexeddb/script-tests/objectstore-basics.js:
     10        (createSuccess):
     11        (addIndexSuccess):
     12        (getSuccess):
     13
    1142010-09-06  Philippe Normand  <pnormand@igalia.com>
    215
  • trunk/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt

    r64214 r66820  
    5151PASS storeNames.contains('storeName') is true
    5252PASS storeNames.length is 1
    53 store.add('value', 'key')
     53event.result.createIndex('indexName', 'x')
     54PASS 'onsuccess' in result is true
     55PASS 'onerror' in result is true
     56PASS 'abort' in result is true
     57PASS 'readyState' in result is true
     58An event should fire shortly...
     59
     60addIndexSuccess():
     61Success event fired:
     62PASS 'result' in event is true
     63PASS 'code' in event is false
     64PASS 'message' in event is false
     65PASS 'source' in event is true
     66PASS event.source != null is true
     67PASS 'onsuccess' in event.target is true
     68PASS 'onerror' in event.target is true
     69PASS 'abort' in event.target is true
     70PASS 'readyState' in event.target is true
     71PASS event.target.readyState is event.target.DONE
     72
     73PASS event.source.indexNames.contains('indexName') is true
     74event.source.add({x: 'value'}, 'key')
    5475PASS 'onsuccess' in result is true
    5576PASS 'onerror' in result is true
     
    93114PASS event.target.readyState is event.target.DONE
    94115
    95 PASS event.result is "value"
     116PASS event.result.x is "value"
    96117store = event.source
    97118store.remove('key')
     
    119140
    120141TEST COMPLETE
     142
  • trunk/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js

    r65667 r66820  
    3636    shouldBe("storeNames.contains('storeName')", "true");
    3737    shouldBe("storeNames.length", "1");
    38     // FIXME: test store.indexNames, as well as all object store's methods.
     38    // FIXME: test all of object store's methods.
    3939
    40     result = evalAndLog("store.add('value', 'key')");
     40    result = evalAndLog("event.result.createIndex('indexName', 'x')");
     41    verifyResult(result);
     42    result.onsuccess = addIndexSuccess;
     43    result.onerror = unexpectedErrorCallback;
     44}
     45
     46function addIndexSuccess()
     47{
     48    debug("addIndexSuccess():");
     49    verifySuccessEvent(event);
     50    shouldBeTrue("event.source.indexNames.contains('indexName')");
     51
     52    result = evalAndLog("event.source.add({x: 'value'}, 'key')");
    4153    verifyResult(result);
    4254    result.onsuccess = addSuccess;
     
    6173    debug("getSuccess():");
    6274    verifySuccessEvent(event);
    63     shouldBeEqualToString("event.result", "value");
     75    shouldBeEqualToString("event.result.x", "value");
    6476    var store = evalAndLog("store = event.source");
    6577
  • trunk/WebCore/ChangeLog

    r66818 r66820  
     12010-08-26  Jeremy Orlow  <jorlow@chromium.org>
     2
     3        Reviewed by Steve Block.
     4
     5        Add index insertion support to IndexedDB.
     6        https://bugs.webkit.org/show_bug.cgi?id=44695
     7
     8        Whenever you insert an item into an ObjectStore, it should use all
     9        indexes' key paths to insert corresponding entries into each index.
     10        Also data should be deleted out of the index when it goes away.
     11
     12        Not much testing yet since there's no way to directly observe indexes.
     13        More will be in next patch.
     14
     15        * storage/IDBDatabaseBackendImpl.cpp:
     16        (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
     17        * storage/IDBFactoryBackendImpl.cpp:
     18        (WebCore::createTables):
     19        * storage/IDBIndex.idl:
     20        * storage/IDBIndexBackendImpl.cpp:
     21        (WebCore::whereClause):
     22        (WebCore::bindWhereClause):
     23        (WebCore::IDBIndexBackendImpl::addingKeyAllowed):
     24        * storage/IDBIndexBackendImpl.h:
     25        (WebCore::IDBIndexBackendImpl::id):
     26        * storage/IDBKey.cpp:
     27        (WebCore::IDBKey::whereSyntax):
     28        (WebCore::IDBKey::bind):
     29        (WebCore::IDBKey::bindWithNulls):
     30        * storage/IDBKey.h:
     31        * storage/IDBObjectStore.idl:
     32        * storage/IDBObjectStoreBackendImpl.cpp:
     33        (WebCore::whereClause):
     34        (WebCore::bindWhereClause):
     35        (WebCore::IDBObjectStoreBackendImpl::get):
     36        (WebCore::fetchKeyFromKeyPath):
     37        (WebCore::putObjectStoreData):
     38        (WebCore::putIndexData):
     39        (WebCore::IDBObjectStoreBackendImpl::put):
     40        (WebCore::IDBObjectStoreBackendImpl::remove):
     41        (WebCore::IDBObjectStoreBackendImpl::createIndex):
     42        (WebCore::doDelete):
     43        (WebCore::IDBObjectStoreBackendImpl::removeIndex):
     44        (WebCore::IDBObjectStoreBackendImpl::openCursor):
     45        * storage/IDBObjectStoreBackendImpl.h:
     46
    1472010-09-06  Anton Muhin  <antonm@chromium.org>
    248
  • trunk/WebCore/storage/IDBDatabaseBackendImpl.cpp

    r66216 r66820  
    178178    doDelete(sqliteDatabase(), "DELETE FROM ObjectStores WHERE id = ?", objectStore->id());
    179179    doDelete(sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id());
     180    doDelete(sqliteDatabase(), "DELETE FROM IndexData WHERE indexId IN (SELECT id FROM Indexes WHERE objectStoreId = ?)", objectStore->id());
    180181    doDelete(sqliteDatabase(), "DELETE FROM Indexes WHERE objectStoreId = ?", objectStore->id());
    181     // FIXME: Delete index data as well.
    182182    transaction.commit();
    183183
  • trunk/WebCore/storage/IDBFactoryBackendImpl.cpp

    r65902 r66820  
    8484
    8585        "DROP TABLE IF EXISTS ObjectStores",
    86         "CREATE TABLE IF NOT EXISTS ObjectStores (id INTEGER PRIMARY KEY, name TEXT NOT NULL, keyPath TEXT, doAutoIncrement INTEGER NOT NULL)",
     86        "CREATE TABLE IF NOT EXISTS ObjectStores (id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE, keyPath TEXT, doAutoIncrement INTEGER NOT NULL)",
    8787        "DROP INDEX IF EXISTS ObjectStores_name",
    8888        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStores_name ON ObjectStores(name)",
    8989
    9090        "DROP TABLE IF EXISTS Indexes",
    91         "CREATE TABLE IF NOT EXISTS Indexes (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), name TEXT NOT NULL, keyPath TEXT, isUnique INTEGER NOT NULL)",
     91        "CREATE TABLE IF NOT EXISTS Indexes (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), name TEXT NOT NULL UNIQUE, keyPath TEXT, isUnique INTEGER NOT NULL)",
    9292        "DROP INDEX IF EXISTS Indexes_composit",
    9393        "CREATE UNIQUE INDEX IF NOT EXISTS Indexes_composit ON Indexes(objectStoreId, name)",
    9494
    9595        "DROP TABLE IF EXISTS ObjectStoreData",
    96         "CREATE TABLE IF NOT EXISTS ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, value TEXT NOT NULL)",
     96        "CREATE TABLE IF NOT EXISTS ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT UNIQUE, keyDate INTEGER UNIQUE, keyNumber INTEGER UNIQUE, value TEXT NOT NULL)",
    9797        "DROP INDEX IF EXISTS ObjectStoreData_composit",
    98         "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)"
     98        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)",
     99
     100        "DROP TABLE IF EXISTS IndexData",
     101        "CREATE TABLE IF NOT EXISTS IndexData (id INTEGER PRIMARY KEY, indexId INTEGER NOT NULL REFERENCES Indexs(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, objectStoreDataId INTEGER NOT NULL UNIQUE REFERENCES ObjectStoreData(id))",
     102        "DROP INDEX IF EXISTS IndexData_composit",
     103        "CREATE UNIQUE INDEX IF NOT EXISTS IndexData_composit ON IndexData(keyString, keyDate, keyNumber, indexId)",
     104        "DROP INDEX IF EXISTS IndexData_objectStoreDataId",
     105        "CREATE UNIQUE INDEX IF NOT EXISTS IndexData_objectStoreDataId ON IndexData(objectStoreDataId)",
     106        "DROP INDEX IF EXISTS IndexData_indexId",
     107        "CREATE UNIQUE INDEX IF NOT EXISTS IndexData_indexId ON IndexData(indexId)"
    99108        };
    100109
  • trunk/WebCore/storage/IDBIndex.idl

    r64358 r66820  
    2929        Conditional=INDEXED_DATABASE
    3030    ] IDBIndex {
    31         // FIXME: Complete this file.
    32 
    3331        readonly attribute DOMString name;
     32        // FIXME: Add "storeName".
    3433        readonly attribute DOMString keyPath;
    3534        readonly attribute boolean unique;
     35
     36        // FIXME: Implement.
     37        //IDBRequest openObjectCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) raises (DOMException);
     38        //IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) raises (DOMException);
     39        //IDBRequest getObject(in IDBKey key) raises (DOMException);
     40        //IDBRequest get(in IDBKey key) raises (DOMException);
    3641    };
    3742
  • trunk/WebCore/storage/IDBIndexBackendImpl.cpp

    r65667 r66820  
    3131#include "IDBDatabaseBackendImpl.h"
    3232#include "IDBObjectStoreBackendImpl.h"
    33 #include "SQLiteDatabase.h"
     33#include "SQLiteStatement.h"
    3434
    3535namespace WebCore {
     
    4848}
    4949
     50static String whereClause(IDBKey* key)
     51{
     52    return "WHERE indexId = ?  AND  " + key->whereSyntax();
     53}
     54
     55static void bindWhereClause(SQLiteStatement& query, int64_t id, IDBKey* key)
     56{
     57    query.bindInt64(1, id);
     58    key->bind(query, 2);
     59}
     60
     61bool IDBIndexBackendImpl::addingKeyAllowed(IDBKey* key)
     62{
     63    if (!m_unique)
     64        return true;
     65
     66    SQLiteStatement query(sqliteDatabase(), "SELECT id FROM IndexData " + whereClause(key));
     67    bool ok = query.prepare() == SQLResultOk;
     68    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     69    bindWhereClause(query, m_id, key);
     70    bool existingValue = query.step() == SQLResultRow;
     71
     72    return !existingValue;
     73}
     74
    5075SQLiteDatabase& IDBIndexBackendImpl::sqliteDatabase() const
    5176{
  • trunk/WebCore/storage/IDBIndexBackendImpl.h

    r65667 r66820  
    3333namespace WebCore {
    3434
     35class IDBKey;
    3536class IDBObjectStoreBackendImpl;
    3637class SQLiteDatabase;
     
    4344    }
    4445    virtual ~IDBIndexBackendImpl();
     46
     47    int64_t id() { return m_id; }
     48    bool addingKeyAllowed(IDBKey*);
    4549
    4650    // Implements IDBIndexBackendInterface.
  • trunk/WebCore/storage/IDBKey.cpp

    r66473 r66820  
    2929#if ENABLE(INDEXED_DATABASE)
    3030
     31#include "SQLiteStatement.h"
    3132#include "SerializedScriptValue.h"
    3233
     
    7374}
    7475
     76String IDBKey::whereSyntax() const
     77{
     78    switch (m_type) {
     79    case IDBKey::StringType:
     80        return "keyString = ?";
     81    case IDBKey::NumberType:
     82        return "keyNumber = ?";
     83    // FIXME: Implement date.
     84    case IDBKey::NullType:
     85        return "keyString IS NULL  AND  keyDate IS NULL  AND  keyNumber IS NULL";
     86    }
     87
     88    ASSERT_NOT_REACHED();
     89    return "";
     90}
     91
     92// Returns the number of items bound.
     93int IDBKey::bind(SQLiteStatement& query, int column) const
     94{
     95    switch (m_type) {
     96    case IDBKey::StringType:
     97        query.bindText(column, m_string);
     98        return 1;
     99    case IDBKey::NumberType:
     100        query.bindInt(column, m_number);
     101        return 1;
     102    case IDBKey::NullType:
     103        return 0;
     104    }
     105
     106    ASSERT_NOT_REACHED();
     107    return 0;
     108}
     109
     110void IDBKey::bindWithNulls(SQLiteStatement& query, int baseColumn) const
     111{
     112    switch (m_type) {
     113    case IDBKey::StringType:
     114        query.bindText(baseColumn + 0, m_string);
     115        query.bindNull(baseColumn + 1);
     116        query.bindNull(baseColumn + 2);
     117        break;
     118    case IDBKey::NumberType:
     119        query.bindNull(baseColumn + 0);
     120        query.bindNull(baseColumn + 1);
     121        query.bindInt(baseColumn + 2, m_number);
     122        break;
     123    case IDBKey::NullType:
     124        query.bindNull(baseColumn + 0);
     125        query.bindNull(baseColumn + 1);
     126        query.bindNull(baseColumn + 2);
     127        break;
     128    default:
     129        ASSERT_NOT_REACHED();
     130    }
     131}
     132
    75133} // namespace WebCore
    76134
  • trunk/WebCore/storage/IDBKey.h

    r66473 r66820  
    3333
    3434namespace WebCore {
     35
     36class SQLiteStatement;
    3537
    3638// FIXME: Add dates.
     
    7375
    7476    bool isEqual(IDBKey* other);
     77    String whereSyntax() const;
     78    int bind(SQLiteStatement& query, int column) const;
     79    void bindWithNulls(SQLiteStatement& query, int baseColumn) const;
    7580
    7681private:
  • trunk/WebCore/storage/IDBObjectStore.idl

    r64828 r66820  
    2929        Conditional=INDEXED_DATABASE
    3030    ] IDBObjectStore {
     31        // FIXME: Many of these should raise on certain errors.
    3132        [CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key);       
    32         // FIXME: Come to concensus re getAll.
    33         // FIXME: SerializedScriptValue raises an exception if you pass in something that can't be serialized.
    34         //        We need to instead "raise" this error via an error callback.
    3533        [CallWith=ScriptExecutionContext] IDBRequest add(in SerializedScriptValue value, in [Optional] IDBKey key);
    3634        [CallWith=ScriptExecutionContext] IDBRequest put(in SerializedScriptValue value, in [Optional] IDBKey key);
  • trunk/WebCore/storage/IDBObjectStoreBackendImpl.cpp

    r66474 r66820  
    3939#include "SQLiteDatabase.h"
    4040#include "SQLiteStatement.h"
     41#include "SQLiteTransaction.h"
    4142
    4243#if ENABLE(INDEXED_DATABASE)
     
    6667}
    6768
    68 static String whereClause(IDBKey::Type type)
    69 {
    70     switch (type) {
    71     case IDBKey::StringType:
    72         return "WHERE objectStoreId = ?  AND  keyString = ?";
    73     case IDBKey::NumberType:
    74         return "WHERE objectStoreId = ?  AND  keyNumber = ?";
    75     // FIXME: Implement date.
    76     case IDBKey::NullType:
    77         return "WHERE objectStoreId = ?  AND  keyString IS NULL  AND  keyDate IS NULL  AND  keyNumber IS NULL";
    78     }
    79 
    80     ASSERT_NOT_REACHED();
    81     return "";
    82 }
    83 
    84 // Returns number of items bound.
    85 static int bindKey(SQLiteStatement& query, int column, IDBKey* key)
    86 {
    87     switch (key->type()) {
    88     case IDBKey::StringType:
    89         query.bindText(column, key->string());
    90         return 1;
    91     case IDBKey::NumberType:
    92         query.bindInt(column, key->number());
    93         return 1;
    94     // FIXME: Implement date.
    95     case IDBKey::NullType:
    96         return 0;
    97     }
    98 
    99     ASSERT_NOT_REACHED();
    100     return 0;
     69static String whereClause(IDBKey* key)
     70{
     71    return "WHERE objectStoreId = ?  AND  " + key->whereSyntax();
    10172}
    10273
     
    10475{
    10576    query.bindInt64(1, id);
    106     bindKey(query, 2, key);
     77    key->bind(query, 2);
    10778}
    10879
    10980void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
    11081{
    111     SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key->type()));
     82    SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key.get()));
    11283    bool ok = query.prepare() == SQLResultOk;
    11384    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     
    12596    callbacks->onSuccess(SerializedScriptValue::createFromWire(query.getColumnText(3)));
    12697    ASSERT(query.step() != SQLResultRow);
     98}
     99
     100static PassRefPtr<IDBKey> fetchKeyFromKeyPath(SerializedScriptValue* value, const String& keyPath)
     101{
     102    Vector<RefPtr<SerializedScriptValue> > values;
     103    values.append(value);
     104    Vector<RefPtr<IDBKey> > keys;
     105    IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, keyPath, keys);
     106    if (keys.isEmpty())
     107        return 0;
     108    ASSERT(keys.size() == 1);
     109    return keys[0].release();
     110}
     111
     112static void putObjectStoreData(SQLiteDatabase& db, IDBKey* key, SerializedScriptValue* value, int64_t objectStoreId, int64_t* dataRowId)
     113{
     114    String sql = *dataRowId != -1 ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
     115                                  : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
     116    SQLiteStatement query(db, sql);
     117    bool ok = query.prepare() == SQLResultOk;
     118    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     119    key->bindWithNulls(query, 1);
     120    query.bindText(4, value->toWireString());
     121    if (*dataRowId != -1)
     122        query.bindInt(5, *dataRowId);
     123    else
     124        query.bindInt64(5, objectStoreId);
     125
     126    ok = query.step() == SQLResultDone;
     127    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     128
     129    if (*dataRowId == -1)
     130        *dataRowId = db.lastInsertRowID();
     131}
     132
     133static void putIndexData(SQLiteDatabase& db, IDBKey* key, int64_t indexId, int64_t objectStoreDataId)
     134{
     135    SQLiteStatement deleteQuery(db, "DELETE FROM IndexData WHERE objectStoreDataId = ?");
     136    bool ok = deleteQuery.prepare() == SQLResultOk;
     137    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     138    deleteQuery.bindInt64(1, objectStoreDataId);
     139    ok = deleteQuery.step() == SQLResultDone;
     140    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     141
     142    SQLiteStatement putQuery(db, "INSERT INTO IndexData (keyString, keyDate, keyNumber, indexId, objectStoreDataId) VALUES (?, ?, ?, ?, ?)");
     143    ok = putQuery.prepare() == SQLResultOk;
     144    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     145    key->bindWithNulls(putQuery, 1);
     146    putQuery.bindInt64(4, indexId);
     147    putQuery.bindInt64(5, objectStoreDataId);
     148
     149    ok = putQuery.step() == SQLResultDone;
     150    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
    127151}
    128152
     
    137161            return;
    138162        }
    139         Vector<RefPtr<SerializedScriptValue> > values;
    140         values.append(value);
    141         Vector<RefPtr<IDBKey> > idbKeys;
    142         IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, m_keyPath, idbKeys);
    143         if (idbKeys.isEmpty()) {
    144             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "An invalid keyPath was supplied for an objectStore."));
     163        key = fetchKeyFromKeyPath(value.get(), m_keyPath);
     164        if (!key) {
     165            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from the keyPath."));
    145166            return;
    146167        }
    147         key = idbKeys[0];
    148     }
    149 
    150     if (!key) {
     168    } else if (!key) {
    151169        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied."));
    152170        return;
    153171    }
    154172
    155     SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key->type()));
     173    Vector<RefPtr<IDBKey> > indexKeys;
     174    for (IndexMap::iterator it = m_indexes.begin(); it != m_indexes.end(); ++it) {
     175        RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath());
     176        if (!key) {
     177            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath."));
     178            return;
     179        }
     180        if (!it->second->addingKeyAllowed(key.get())) {
     181            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
     182            return;
     183        }
     184        indexKeys.append(key.release());
     185    }
     186
     187    SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key.get()));
    156188    bool ok = getQuery.prepare() == SQLResultOk;
    157189    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
    158190
    159191    bindWhereClause(getQuery, m_id, key.get());
    160     bool existingValue = getQuery.step() == SQLResultRow;
    161     if (addOnly && existingValue) {
     192    bool isExistingValue = getQuery.step() == SQLResultRow;
     193    if (addOnly && isExistingValue) {
    162194        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
    163195        return;
    164196    }
    165197
    166     String sql = existingValue ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
    167                                : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
    168     SQLiteStatement putQuery(sqliteDatabase(), sql);
    169     ok = putQuery.prepare() == SQLResultOk;
    170     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
    171     switch (key->type()) {
    172     case IDBKey::StringType:
    173         putQuery.bindText(1, key->string());
    174         putQuery.bindNull(2);
    175         putQuery.bindNull(3);
    176         break;
    177     // FIXME: Implement date.
    178     case IDBKey::NumberType:
    179         putQuery.bindNull(1);
    180         putQuery.bindNull(2);
    181         putQuery.bindInt(3, key->number());
    182         break;
    183     case IDBKey::NullType:
    184         putQuery.bindNull(1);
    185         putQuery.bindNull(2);
    186         putQuery.bindNull(3);
    187         break;
    188     default:
    189         ASSERT_NOT_REACHED();
    190     }
    191     putQuery.bindText(4, value->toWireString());
    192     if (existingValue)
    193         putQuery.bindInt(5, getQuery.getColumnInt(0));
    194     else
    195         putQuery.bindInt64(5, m_id);
    196 
    197     ok = putQuery.step() == SQLResultDone;
    198     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     198    // Before this point, don't do any mutation.  After this point, don't error out.
     199
     200    int64_t dataRowId = isExistingValue ? getQuery.getColumnInt(0) : -1;
     201    putObjectStoreData(sqliteDatabase(), key.get(), value.get(), m_id, &dataRowId);
     202
     203    int i = 0;
     204    for (IndexMap::iterator it = m_indexes.begin(); it != m_indexes.end(); ++it, ++i)
     205        putIndexData(sqliteDatabase(), indexKeys[i].get(), it->second->id(), dataRowId);
    199206
    200207    callbacks->onSuccess(key.get());
     
    203210void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
    204211{
    205     SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key->type()));
     212    SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key.get()));
    206213    bool ok = query.prepare() == SQLResultOk;
    207214    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
     
    234241    int64_t id = sqliteDatabase().lastInsertRowID();
    235242
    236     RefPtr<IDBIndexBackendInterface> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
     243    RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
    237244    ASSERT(index->name() == name);
    238245    m_indexes.set(name, index);
    239     callbacks->onSuccess(index.release());
     246    callbacks->onSuccess(index.get());
    240247}
    241248
     
    245252}
    246253
     254static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
     255{
     256    SQLiteStatement deleteQuery(db, sql);
     257    bool ok = deleteQuery.prepare() == SQLResultOk;
     258    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     259    deleteQuery.bindInt64(1, id);
     260    ok = deleteQuery.step() == SQLResultDone;
     261    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     262}
     263
    247264void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks)
    248265{
    249     if (!m_indexes.contains(name)) {
     266    RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
     267    if (!index) {
    250268        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Index name does not exist."));
    251269        return;
    252270    }
    253271
    254     SQLiteStatement deleteQuery(sqliteDatabase(), "DELETE FROM Indexes WHERE name = ? AND objectStoreId = ?");
    255     bool ok = deleteQuery.prepare() == SQLResultOk;
    256     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
    257     deleteQuery.bindText(1, name);
    258     deleteQuery.bindInt64(2, m_id);
    259     ok = deleteQuery.step() == SQLResultDone;
    260     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
    261 
    262     // FIXME: Delete index data as well.
     272    SQLiteTransaction transaction(sqliteDatabase());
     273    transaction.begin();
     274    doDelete(sqliteDatabase(), "DELETE FROM Indexes WHERE id = ?", index->id());
     275    doDelete(sqliteDatabase(), "DELETE FROM IndexData WHERE indexId = ?", index->id());
     276    transaction.commit();
    263277
    264278    m_indexes.remove(name);
     
    338352    int currentColumn = 1;
    339353    if (range->flags() & IDBKeyRange::LEFT_BOUND || range->flags() == IDBKeyRange::SINGLE)
    340         currentColumn += bindKey(*query, currentColumn, range->left().get());
     354        currentColumn += range->left()->bind(*query, currentColumn);
    341355    if (range->flags() & IDBKeyRange::RIGHT_BOUND || range->flags() == IDBKeyRange::SINGLE)
    342         currentColumn += bindKey(*query, currentColumn, range->right().get());
     356        currentColumn += range->right()->bind(*query, currentColumn);
    343357    query->bindInt64(currentColumn, m_id);
    344358
  • trunk/WebCore/storage/IDBObjectStoreBackendImpl.h

    r65902 r66820  
    3636
    3737class IDBDatabaseBackendImpl;
     38class IDBIndexBackendImpl;
    3839class SQLiteDatabase;
    3940
     
    7677    bool m_autoIncrement;
    7778
    78     typedef HashMap<String, RefPtr<IDBIndexBackendInterface> > IndexMap;
     79    typedef HashMap<String, RefPtr<IDBIndexBackendImpl> > IndexMap;
    7980    IndexMap m_indexes;
    8081};
  • trunk/WebKit/chromium/ChangeLog

    r66818 r66820  
     12010-08-26  Jeremy Orlow  <jorlow@chromium.org>
     2
     3        Reviewed by Steve Block.
     4
     5        Add index insertion support to IndexedDB.
     6        https://bugs.webkit.org/show_bug.cgi?id=44695
     7
     8        Add asserts on the [] operator.
     9
     10        * public/WebVector.h:
     11        (WebKit::WebVector::operator[]):
     12
    1132010-09-06  Anton Muhin  <antonm@chromium.org>
    214
  • trunk/WebKit/chromium/public/WebVector.h

    r52255 r66820  
    116116    bool isEmpty() const { return !m_size; }
    117117
    118     T& operator[](size_t i) { return m_ptr[i]; }
    119     const T& operator[](size_t i) const { return m_ptr[i]; }
     118    T& operator[](size_t i)
     119    {
     120        WEBKIT_ASSERT(i < m_size);
     121        return m_ptr[i];
     122    }
     123    const T& operator[](size_t i) const
     124    {
     125        WEBKIT_ASSERT(i < m_size);
     126        return m_ptr[i];
     127    }
    120128
    121129    T* data() { return m_ptr; }
Note: See TracChangeset for help on using the changeset viewer.