diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index f1c3010423e..43b39176c50 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -61,7 +61,7 @@ #include "IDBKeyRange.h" #include "LazyIdleThread.h" -#define DB_SCHEMA_VERSION 2 +#define DB_SCHEMA_VERSION 3 USING_INDEXEDDB_NAMESPACE @@ -165,10 +165,9 @@ CreateTables(mozIStorageConnection* aDBConn) // Table `ai_object_data` rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "CREATE TABLE ai_object_data (" - "id INTEGER, " + "id INTEGER PRIMARY KEY AUTOINCREMENT, " "object_store_id INTEGER NOT NULL, " "data TEXT NOT NULL, " - "PRIMARY KEY (id), " "FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE " "CASCADE" ");" diff --git a/dom/indexedDB/IDBObjectStore.cpp b/dom/indexedDB/IDBObjectStore.cpp index 1cb007a360c..6ddab0afc6c 100644 --- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -146,6 +146,25 @@ public: PRUint16 GetSuccessResult(nsIWritableVariant* aResult); }; +class ClearHelper : public AsyncConnectionHelper +{ +public: + ClearHelper(IDBTransaction* aTransaction, + IDBRequest* aRequest, + PRInt64 aObjectStoreID, + bool aAutoIncrement) + : AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID), + mAutoIncrement(aAutoIncrement) + { } + + PRUint16 DoDatabaseWork(mozIStorageConnection* aConnection); + +protected: + // In-params. + const PRInt64 mOSID; + const bool mAutoIncrement; +}; + class OpenCursorHelper : public AsyncConnectionHelper { public: @@ -920,7 +939,16 @@ IDBObjectStore::Add(const jsval &aValue, return NS_ERROR_OBJECT_IS_IMMUTABLE; } - jsval keyval = (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID; + jsval keyval; + if (aOptionalArgCount >= 1) { + keyval = aKey; + if (mAutoIncrement && JSVAL_IS_NULL(keyval)) { + return NS_ERROR_ILLEGAL_VALUE; + } + } + else { + keyval = JSVAL_VOID; + } nsString jsonValue; Key key; @@ -1032,6 +1060,32 @@ IDBObjectStore::Remove(nsIVariant* aKey, return NS_OK; } +NS_IMETHODIMP +IDBObjectStore::Clear(nsIIDBRequest** _retval) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (!mTransaction->TransactionIsOpen()) { + return NS_ERROR_UNEXPECTED; + } + + if (mMode != nsIIDBTransaction::READ_WRITE) { + return NS_ERROR_OBJECT_IS_IMMUTABLE; + } + + nsRefPtr request = + GenerateWriteRequest(mTransaction->ScriptContext(), mTransaction->Owner()); + NS_ENSURE_TRUE(request, NS_ERROR_FAILURE); + + nsRefPtr helper = + new ClearHelper(mTransaction, request, mId, !!mAutoIncrement); + nsresult rv = helper->DispatchToTransactionPool(); + NS_ENSURE_SUCCESS(rv, rv); + + request.forget(_retval); + return NS_OK; +} + NS_IMETHODIMP IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange, PRUint16 aDirection, @@ -1607,6 +1661,36 @@ RemoveHelper::GetSuccessResult(nsIWritableVariant* aResult) return OK; } +PRUint16 +ClearHelper::DoDatabaseWork(mozIStorageConnection* aConnection) +{ + NS_PRECONDITION(aConnection, "Passed a null connection!"); + + nsCString table; + if (mAutoIncrement) { + table.AssignLiteral("ai_object_data"); + } + else { + table.AssignLiteral("object_data"); + } + + nsCString query = NS_LITERAL_CSTRING("DELETE FROM ") + table + + NS_LITERAL_CSTRING(" WHERE object_store_id = :osid"); + + nsCOMPtr stmt = mTransaction->GetCachedStatement(query); + NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR); + + mozStorageStatementScoper scoper(stmt); + + nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mOSID); + NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + + rv = stmt->Execute(); + NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + + return OK; +} + PRUint16 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { diff --git a/dom/indexedDB/nsIIDBObjectStore.idl b/dom/indexedDB/nsIIDBObjectStore.idl index ecae8341c01..4b4fd9d65e7 100644 --- a/dom/indexedDB/nsIIDBObjectStore.idl +++ b/dom/indexedDB/nsIIDBObjectStore.idl @@ -89,6 +89,10 @@ interface nsIIDBObjectStore : nsISupports nsIIDBRequest remove(in nsIVariant key); + // Success fires IDBTransactionEvent, result == null + nsIIDBRequest + clear(); + // Success fires IDBTransactionEvent, result == IDBCursor or // IDBCursorPreloadedRequest if preload == true. result == null if no match. [optional_argc] diff --git a/dom/indexedDB/test/Makefile.in b/dom/indexedDB/test/Makefile.in index 41686e88b01..491802726ec 100644 --- a/dom/indexedDB/test/Makefile.in +++ b/dom/indexedDB/test/Makefile.in @@ -48,6 +48,7 @@ _TEST_FILES = \ helpers.js \ test_add_twice_failure.html \ test_bad_keypath.html \ + test_clear.html \ test_create_index.html \ test_create_objectStore.html \ test_cursors.html \ diff --git a/dom/indexedDB/test/helpers.js b/dom/indexedDB/test/helpers.js index 1b6f0e847fe..0c892d30133 100644 --- a/dom/indexedDB/test/helpers.js +++ b/dom/indexedDB/test/helpers.js @@ -23,6 +23,13 @@ function grabEventAndContinueHandler(event) testGenerator.send(event); } +function continueToNextStep() +{ + SimpleTest.executeSoon(function() { + testGenerator.next(); + }); +} + function errorHandler(event) { ok(false, "indexedDB error (" + event.code + "): " + event.message); diff --git a/dom/indexedDB/test/test_clear.html b/dom/indexedDB/test/test_clear.html new file mode 100644 index 00000000000..f5a1e393024 --- /dev/null +++ b/dom/indexedDB/test/test_clear.html @@ -0,0 +1,113 @@ + + + + Indexed Database Property Test + + + + + + + + + + + + +