mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 10:33:33 +00:00
Back out fb4d12d2a2da, bug 701772, due to leaks.
This commit is contained in:
parent
817fccb725
commit
488e12717c
@ -71,13 +71,14 @@ CloneObjectStoreInfo(const nsAString& aKey,
|
||||
{
|
||||
ObjectStoreInfoHash* hash = static_cast<ObjectStoreInfoHash*>(aUserArg);
|
||||
|
||||
nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData));
|
||||
nsAutoPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData));
|
||||
|
||||
if (!hash->Put(aKey, newInfo)) {
|
||||
NS_WARNING("Out of memory?");
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
newInfo.forget();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
@ -91,23 +92,12 @@ DatabaseInfo::~DatabaseInfo()
|
||||
}
|
||||
}
|
||||
|
||||
ObjectStoreInfo::ObjectStoreInfo(ObjectStoreInfo& aOther)
|
||||
: name(aOther.name),
|
||||
id(aOther.id),
|
||||
keyPath(aOther.keyPath),
|
||||
indexes(aOther.indexes),
|
||||
nextAutoIncrementId(aOther.nextAutoIncrementId),
|
||||
comittedAutoIncrementId(aOther.comittedAutoIncrementId)
|
||||
{
|
||||
// Doesn't copy the refcount
|
||||
MOZ_COUNT_CTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
||||
IndexInfo::IndexInfo()
|
||||
: id(LL_MININT),
|
||||
unique(false),
|
||||
autoIncrement(false),
|
||||
multiEntry(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexInfo);
|
||||
@ -118,6 +108,7 @@ IndexInfo::IndexInfo(const IndexInfo& aOther)
|
||||
name(aOther.name),
|
||||
keyPath(aOther.keyPath),
|
||||
unique(aOther.unique),
|
||||
autoIncrement(aOther.autoIncrement),
|
||||
multiEntry(aOther.multiEntry)
|
||||
{
|
||||
MOZ_COUNT_CTOR(IndexInfo);
|
||||
@ -130,8 +121,19 @@ IndexInfo::~IndexInfo()
|
||||
|
||||
ObjectStoreInfo::ObjectStoreInfo()
|
||||
: id(0),
|
||||
nextAutoIncrementId(0),
|
||||
comittedAutoIncrementId(0)
|
||||
autoIncrement(false),
|
||||
databaseId(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ObjectStoreInfo);
|
||||
}
|
||||
|
||||
ObjectStoreInfo::ObjectStoreInfo(ObjectStoreInfo& aOther)
|
||||
: name(aOther.name),
|
||||
id(aOther.id),
|
||||
keyPath(aOther.keyPath),
|
||||
autoIncrement(aOther.autoIncrement),
|
||||
databaseId(aOther.databaseId),
|
||||
indexes(aOther.indexes)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ObjectStoreInfo);
|
||||
}
|
||||
@ -204,6 +206,11 @@ DatabaseInfo::Remove(nsIAtom* aId)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
DatabaseInfo* info = nsnull;
|
||||
|
||||
DebugOnly<bool> got = Get(aId, &info);
|
||||
NS_ASSERTION(got && info, "Don't know anything about this one!");
|
||||
|
||||
if (gDatabaseHash) {
|
||||
gDatabaseHash->Remove(aId);
|
||||
|
||||
@ -214,31 +221,6 @@ DatabaseInfo::Remove(nsIAtom* aId)
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
EnumerateDatabasesRemoveOrigin(nsISupports* aId,
|
||||
DatabaseInfo*& aDatabaseInfo,
|
||||
void* aUserArg)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
const nsACString* origin = static_cast<const nsACString*>(aUserArg);
|
||||
return aDatabaseInfo->origin.Equals(*origin) ?
|
||||
PL_DHASH_REMOVE :
|
||||
PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
DatabaseInfo::RemoveAllForOrigin(const nsACString& aOrigin)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (gDatabaseHash) {
|
||||
gDatabaseHash->Enumerate(EnumerateDatabasesRemoveOrigin,
|
||||
const_cast<nsACString*>(&aOrigin));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DatabaseInfo::GetObjectStoreNames(nsTArray<nsString>& aNames)
|
||||
{
|
||||
@ -259,16 +241,17 @@ DatabaseInfo::ContainsStoreName(const nsAString& aName)
|
||||
return objectStoreHash && objectStoreHash->Get(aName, nsnull);
|
||||
}
|
||||
|
||||
ObjectStoreInfo*
|
||||
DatabaseInfo::GetObjectStore(const nsAString& aName)
|
||||
bool
|
||||
DatabaseInfo::GetObjectStore(const nsAString& aName,
|
||||
ObjectStoreInfo** aInfo)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (objectStoreHash) {
|
||||
return objectStoreHash->GetWeak(aName);
|
||||
return objectStoreHash->Get(aName, aInfo);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -298,7 +281,7 @@ void
|
||||
DatabaseInfo::RemoveObjectStore(const nsAString& aName)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!");
|
||||
NS_ASSERTION(GetObjectStore(aName, nsnull), "Don't know about this one!");
|
||||
|
||||
if (objectStoreHash) {
|
||||
objectStoreHash->Remove(aName);
|
||||
|
@ -46,14 +46,14 @@
|
||||
#include "Key.h"
|
||||
#include "IDBObjectStore.h"
|
||||
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
struct ObjectStoreInfo;
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, ObjectStoreInfo>
|
||||
typedef nsClassHashtable<nsStringHashKey, ObjectStoreInfo>
|
||||
ObjectStoreInfoHash;
|
||||
|
||||
class IDBDatabase;
|
||||
@ -77,15 +77,14 @@ private:
|
||||
|
||||
static bool Put(DatabaseInfo* aInfo);
|
||||
|
||||
public:
|
||||
static void Remove(nsIAtom* aId);
|
||||
|
||||
static void RemoveAllForOrigin(const nsACString& aOrigin);
|
||||
|
||||
public:
|
||||
bool GetObjectStoreNames(nsTArray<nsString>& aNames);
|
||||
bool ContainsStoreName(const nsAString& aName);
|
||||
|
||||
ObjectStoreInfo* GetObjectStore(const nsAString& aName);
|
||||
bool GetObjectStore(const nsAString& aName,
|
||||
ObjectStoreInfo** aInfo);
|
||||
|
||||
bool PutObjectStore(ObjectStoreInfo* aInfo);
|
||||
|
||||
@ -94,9 +93,8 @@ public:
|
||||
already_AddRefed<DatabaseInfo> Clone();
|
||||
|
||||
nsString name;
|
||||
nsCString origin;
|
||||
PRUint64 version;
|
||||
nsCOMPtr<nsIAtom> id;
|
||||
nsIAtom* id;
|
||||
nsString filePath;
|
||||
PRInt64 nextObjectStoreId;
|
||||
PRInt64 nextIndexId;
|
||||
@ -115,13 +113,14 @@ struct IndexInfo
|
||||
~IndexInfo();
|
||||
#else
|
||||
IndexInfo()
|
||||
: id(LL_MININT), unique(false), multiEntry(false) { }
|
||||
: id(LL_MININT), unique(false), autoIncrement(false) { }
|
||||
#endif
|
||||
|
||||
PRInt64 id;
|
||||
nsString name;
|
||||
nsString keyPath;
|
||||
bool unique;
|
||||
bool autoIncrement;
|
||||
bool multiEntry;
|
||||
};
|
||||
|
||||
@ -129,39 +128,19 @@ struct ObjectStoreInfo
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ObjectStoreInfo();
|
||||
#else
|
||||
ObjectStoreInfo()
|
||||
: id(0), nextAutoIncrementId(0), comittedAutoIncrementId(0) { }
|
||||
#endif
|
||||
|
||||
ObjectStoreInfo(ObjectStoreInfo& aOther);
|
||||
|
||||
private:
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
~ObjectStoreInfo();
|
||||
#else
|
||||
~ObjectStoreInfo() {}
|
||||
ObjectStoreInfo()
|
||||
: id(0), autoIncrement(false), databaseId(0) { }
|
||||
#endif
|
||||
public:
|
||||
|
||||
// Constant members, can be gotten on any thread
|
||||
nsString name;
|
||||
PRInt64 id;
|
||||
nsString keyPath;
|
||||
|
||||
// Main-thread only members. This must *not* be touced on the database thread
|
||||
bool autoIncrement;
|
||||
nsIAtom* databaseId;
|
||||
nsTArray<IndexInfo> indexes;
|
||||
|
||||
// Database-thread members. After the ObjectStoreInfo has been initialized,
|
||||
// these can *only* be touced on the database thread.
|
||||
PRInt64 nextAutoIncrementId;
|
||||
PRInt64 comittedAutoIncrementId;
|
||||
|
||||
// This is threadsafe since the ObjectStoreInfos are created on the database
|
||||
// thread but then only used from the main thread. Ideal would be if we
|
||||
// could transfer ownership from the database thread to the main thread, but
|
||||
// we don't have that ability yet.
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ObjectStoreInfo)
|
||||
};
|
||||
|
||||
struct IndexUpdateInfo
|
||||
|
@ -124,24 +124,24 @@ NS_STACK_CLASS
|
||||
class AutoRemoveObjectStore
|
||||
{
|
||||
public:
|
||||
AutoRemoveObjectStore(DatabaseInfo* aInfo, const nsAString& aName)
|
||||
: mInfo(aInfo), mName(aName)
|
||||
AutoRemoveObjectStore(IDBDatabase* aDatabase, const nsAString& aName)
|
||||
: mDatabase(aDatabase), mName(aName)
|
||||
{ }
|
||||
|
||||
~AutoRemoveObjectStore()
|
||||
{
|
||||
if (mInfo) {
|
||||
mInfo->RemoveObjectStore(mName);
|
||||
if (mDatabase) {
|
||||
mDatabase->Info()->RemoveObjectStore(mName);
|
||||
}
|
||||
}
|
||||
|
||||
void forget()
|
||||
{
|
||||
mInfo = nsnull;
|
||||
mDatabase = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
DatabaseInfo* mInfo;
|
||||
IDBDatabase* mDatabase;
|
||||
nsString mName;
|
||||
};
|
||||
|
||||
@ -384,7 +384,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
DatabaseInfo* databaseInfo = transaction->DBInfo();
|
||||
DatabaseInfo* databaseInfo = Info();
|
||||
|
||||
nsString keyPath;
|
||||
keyPath.SetIsVoid(true);
|
||||
@ -446,24 +446,25 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo());
|
||||
nsAutoPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo());
|
||||
|
||||
newInfo->name = aName;
|
||||
newInfo->id = databaseInfo->nextObjectStoreId++;
|
||||
newInfo->keyPath = keyPath;
|
||||
newInfo->nextAutoIncrementId = autoIncrement ? 1 : 0;
|
||||
newInfo->comittedAutoIncrementId = newInfo->nextAutoIncrementId;
|
||||
newInfo->autoIncrement = autoIncrement;
|
||||
newInfo->databaseId = mDatabaseId;
|
||||
|
||||
if (!databaseInfo->PutObjectStore(newInfo)) {
|
||||
if (!Info()->PutObjectStore(newInfo)) {
|
||||
NS_WARNING("Put failed!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
ObjectStoreInfo* objectStoreInfo = newInfo.forget();
|
||||
|
||||
// Don't leave this in the hash if we fail below!
|
||||
AutoRemoveObjectStore autoRemove(databaseInfo, aName);
|
||||
AutoRemoveObjectStore autoRemove(this, aName);
|
||||
|
||||
nsRefPtr<IDBObjectStore> objectStore =
|
||||
transaction->GetOrCreateObjectStore(aName, newInfo);
|
||||
transaction->GetOrCreateObjectStore(aName, objectStoreInfo);
|
||||
NS_ENSURE_TRUE(objectStore, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsRefPtr<CreateObjectStoreHelper> helper =
|
||||
@ -490,9 +491,9 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName)
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
DatabaseInfo* info = transaction->DBInfo();
|
||||
ObjectStoreInfo* objectStoreInfo = info->GetObjectStore(aName);
|
||||
if (!objectStoreInfo) {
|
||||
DatabaseInfo* info = Info();
|
||||
ObjectStoreInfo* objectStoreInfo;
|
||||
if (!info->GetObjectStore(aName, &objectStoreInfo)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
@ -501,7 +502,9 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName)
|
||||
nsresult rv = helper->DispatchToTransactionPool();
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
transaction->RemoveObjectStore(aName);
|
||||
info->RemoveObjectStore(aName);
|
||||
|
||||
transaction->ReleaseCachedObjectStore(aName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -226,8 +226,9 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
|
||||
|
||||
bool hasResult;
|
||||
while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
|
||||
nsRefPtr<ObjectStoreInfo>* element =
|
||||
nsAutoPtr<ObjectStoreInfo>* element =
|
||||
aObjectStores.AppendElement(new ObjectStoreInfo());
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
ObjectStoreInfo* info = element->get();
|
||||
|
||||
@ -249,8 +250,8 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
info->nextAutoIncrementId = stmt->AsInt64(3);
|
||||
info->comittedAutoIncrementId = info->nextAutoIncrementId;
|
||||
info->autoIncrement = !!stmt->AsInt32(3);
|
||||
info->databaseId = aDatabaseId;
|
||||
|
||||
ObjectStoreInfoMap* mapEntry = infoMap.AppendElement();
|
||||
NS_ENSURE_TRUE(mapEntry, NS_ERROR_OUT_OF_MEMORY);
|
||||
@ -262,7 +263,8 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
|
||||
|
||||
// Load index information
|
||||
rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT object_store_id, id, name, key_path, unique_index, multientry "
|
||||
"SELECT object_store_id, id, name, key_path, unique_index, multientry, "
|
||||
"object_store_autoincrement "
|
||||
"FROM object_store_index"
|
||||
), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -296,6 +298,7 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
|
||||
|
||||
indexInfo->unique = !!stmt->AsInt32(4);
|
||||
indexInfo->multiEntry = !!stmt->AsInt32(5);
|
||||
indexInfo->autoIncrement = !!stmt->AsInt32(6);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -324,28 +327,35 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBFactory::SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
|
||||
PRUint64 aVersion,
|
||||
ObjectStoreInfoArray& aObjectStores)
|
||||
IDBFactory::UpdateDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
|
||||
PRUint64 aVersion,
|
||||
ObjectStoreInfoArray& aObjectStores)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aDatabaseInfo, "Null pointer!");
|
||||
|
||||
ObjectStoreInfoArray objectStores;
|
||||
objectStores.SwapElements(aObjectStores);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsTArray<nsString> existingNames;
|
||||
aDatabaseInfo->GetObjectStoreNames(existingNames);
|
||||
NS_ASSERTION(existingNames.IsEmpty(), "Should be an empty DatabaseInfo");
|
||||
if (!objectStores.SwapElements(aObjectStores)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoTArray<nsString, 10> existingNames;
|
||||
if (!aDatabaseInfo->GetObjectStoreNames(existingNames)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Remove all the old ones.
|
||||
for (PRUint32 index = 0; index < existingNames.Length(); index++) {
|
||||
aDatabaseInfo->RemoveObjectStore(existingNames[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
aDatabaseInfo->version = aVersion;
|
||||
|
||||
for (PRUint32 index = 0; index < objectStores.Length(); index++) {
|
||||
nsRefPtr<ObjectStoreInfo>& info = objectStores[index];
|
||||
nsAutoPtr<ObjectStoreInfo>& info = objectStores[index];
|
||||
NS_ASSERTION(info->databaseId == aDatabaseInfo->id, "Huh?!");
|
||||
|
||||
if (!aDatabaseInfo->PutObjectStore(info)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
|
@ -59,7 +59,7 @@ struct ObjectStoreInfo;
|
||||
|
||||
class IDBFactory : public nsIIDBFactory
|
||||
{
|
||||
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
||||
typedef nsTArray<nsAutoPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIDBFACTORY
|
||||
@ -90,9 +90,9 @@ public:
|
||||
ObjectStoreInfoArray& aObjectStores);
|
||||
|
||||
static nsresult
|
||||
SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
|
||||
PRUint64 aVersion,
|
||||
ObjectStoreInfoArray& aObjectStores);
|
||||
UpdateDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
|
||||
PRUint64 aVersion,
|
||||
ObjectStoreInfoArray& aObjectStores);
|
||||
|
||||
private:
|
||||
IDBFactory();
|
||||
|
@ -321,13 +321,15 @@ IDBIndex::Create(IDBObjectStore* aObjectStore,
|
||||
index->mKeyPath = aIndexInfo->keyPath;
|
||||
index->mUnique = aIndexInfo->unique;
|
||||
index->mMultiEntry = aIndexInfo->multiEntry;
|
||||
index->mAutoIncrement = aIndexInfo->autoIncrement;
|
||||
|
||||
return index.forget();
|
||||
}
|
||||
|
||||
IDBIndex::IDBIndex()
|
||||
: mId(LL_MININT),
|
||||
mUnique(false)
|
||||
mUnique(false),
|
||||
mAutoIncrement(false)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
}
|
||||
@ -691,12 +693,26 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
{
|
||||
NS_ASSERTION(mKeyRange, "Must have a key range here!");
|
||||
|
||||
nsCString keyColumn;
|
||||
nsCString indexTable;
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("unique_index_data");
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
keyColumn.AssignLiteral("ai_object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("index_data");
|
||||
keyColumn.AssignLiteral("object_data_key");
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
nsCString keyRangeClause;
|
||||
@ -704,10 +720,12 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
|
||||
NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
|
||||
indexTable +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
|
||||
keyRangeClause +
|
||||
NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" FROM ") + indexTable +
|
||||
NS_LITERAL_CSTRING(" WHERE ") + indexId +
|
||||
NS_LITERAL_CSTRING(" = :") + indexId + keyRangeClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT 1");
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
|
||||
@ -715,8 +733,7 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
|
||||
mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
rv = mKeyRange->BindToStatement(stmt);
|
||||
@ -746,12 +763,29 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
{
|
||||
NS_ASSERTION(mKeyRange, "Must have a key range here!");
|
||||
|
||||
nsCString indexTable;
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("unique_index_data");
|
||||
nsCString objectTable;
|
||||
nsCString joinTable;
|
||||
nsCString objectColumn;
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
objectTable.AssignLiteral("ai_object_data");
|
||||
objectColumn.AssignLiteral("ai_object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
joinTable.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
joinTable.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("index_data");
|
||||
objectTable.AssignLiteral("object_data");
|
||||
objectColumn.AssignLiteral("object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
joinTable.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
joinTable.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
nsCString keyRangeClause;
|
||||
@ -759,12 +793,15 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
|
||||
NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
|
||||
"INNER JOIN ") + indexTable +
|
||||
NS_LITERAL_CSTRING(" AS index_table ON object_data.id = ") +
|
||||
NS_LITERAL_CSTRING("index_table.object_data_id WHERE "
|
||||
"index_id = :index_id") +
|
||||
keyRangeClause +
|
||||
NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM ") + objectTable +
|
||||
NS_LITERAL_CSTRING(" INNER JOIN ") + joinTable +
|
||||
NS_LITERAL_CSTRING(" ON ") + objectTable +
|
||||
NS_LITERAL_CSTRING(".id = ") + joinTable +
|
||||
NS_LITERAL_CSTRING(".") + objectColumn +
|
||||
NS_LITERAL_CSTRING(" WHERE ") + indexId +
|
||||
NS_LITERAL_CSTRING(" = :") + indexId + keyRangeClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT 1");
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
|
||||
@ -772,8 +809,7 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
|
||||
mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
rv = mKeyRange->BindToStatement(stmt);
|
||||
@ -807,12 +843,26 @@ GetHelper::GetSuccessResult(JSContext* aCx,
|
||||
nsresult
|
||||
GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
{
|
||||
nsCString keyColumn;
|
||||
nsCString tableName;
|
||||
if (mIndex->IsUnique()) {
|
||||
tableName.AssignLiteral("unique_index_data");
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
keyColumn.AssignLiteral("ai_object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
tableName.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
tableName.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
tableName.AssignLiteral("index_data");
|
||||
keyColumn.AssignLiteral("object_data_key");
|
||||
if (mIndex->IsUnique()) {
|
||||
tableName.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
tableName.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
nsCString keyRangeClause;
|
||||
@ -826,18 +876,20 @@ GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
limitClause.AppendInt(mLimit);
|
||||
}
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
|
||||
tableName +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
|
||||
keyRangeClause + limitClause;
|
||||
NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" FROM ") + tableName +
|
||||
NS_LITERAL_CSTRING(" WHERE ") + indexId +
|
||||
NS_LITERAL_CSTRING(" = :") + indexId + keyRangeClause +
|
||||
limitClause;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
|
||||
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
|
||||
mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (mKeyRange) {
|
||||
@ -915,14 +967,33 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
|
||||
nsresult
|
||||
GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
{
|
||||
nsCString indexTable;
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("unique_index_data");
|
||||
nsCString dataTableName;
|
||||
nsCString objectDataId;
|
||||
nsCString indexTableName;
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
dataTableName.AssignLiteral("ai_object_data");
|
||||
objectDataId.AssignLiteral("ai_object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTableName.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
indexTableName.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("index_data");
|
||||
dataTableName.AssignLiteral("object_data");
|
||||
objectDataId.AssignLiteral("object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTableName.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
indexTableName.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
|
||||
|
||||
nsCString keyRangeClause;
|
||||
if (mKeyRange) {
|
||||
mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
|
||||
@ -934,20 +1005,21 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
|
||||
limitClause.AppendInt(mLimit);
|
||||
}
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
|
||||
"INNER JOIN ") + indexTable +
|
||||
NS_LITERAL_CSTRING(" AS index_table ON object_data.id = "
|
||||
"index_table.object_data_id "
|
||||
"WHERE index_id = :index_id") +
|
||||
keyRangeClause + limitClause;
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM ") + dataTableName +
|
||||
NS_LITERAL_CSTRING(" INNER JOIN ") + indexTableName +
|
||||
NS_LITERAL_CSTRING(" ON ") + dataTableName +
|
||||
NS_LITERAL_CSTRING(".id = ") + indexTableName +
|
||||
NS_LITERAL_CSTRING(".") + objectDataId +
|
||||
NS_LITERAL_CSTRING(" WHERE ") + indexId +
|
||||
NS_LITERAL_CSTRING(" = :") + indexId + keyRangeClause +
|
||||
limitClause;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
|
||||
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
|
||||
mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (mKeyRange) {
|
||||
@ -997,13 +1069,31 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
NS_ASSERTION(aConnection, "Passed a null connection!");
|
||||
|
||||
nsCString table;
|
||||
if (mIndex->IsUnique()) {
|
||||
table.AssignLiteral("unique_index_data");
|
||||
nsCString keyColumn;
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
keyColumn.AssignLiteral("ai_object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
table.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
table.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
table.AssignLiteral("index_data");
|
||||
keyColumn.AssignLiteral("object_data_key");
|
||||
if (mIndex->IsUnique()) {
|
||||
table.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
table.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(id, "id");
|
||||
NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
|
||||
NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(value, "value");
|
||||
|
||||
nsCString keyRangeClause;
|
||||
@ -1011,27 +1101,30 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
mKeyRange->GetBindingClause(value, keyRangeClause);
|
||||
}
|
||||
|
||||
nsCAutoString directionClause(" ORDER BY value ");
|
||||
nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value;
|
||||
switch (mDirection) {
|
||||
case nsIIDBCursor::NEXT:
|
||||
case nsIIDBCursor::NEXT_NO_DUPLICATE:
|
||||
directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
|
||||
directionClause += NS_LITERAL_CSTRING(" ASC, ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" ASC");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV:
|
||||
directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
|
||||
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" DESC");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV_NO_DUPLICATE:
|
||||
directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
|
||||
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" ASC");
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Unknown direction!");
|
||||
}
|
||||
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
|
||||
"FROM ") + table +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
|
||||
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" FROM ") + table +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :") + id +
|
||||
keyRangeClause + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT 1");
|
||||
|
||||
@ -1041,8 +1134,7 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
|
||||
mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (mKeyRange) {
|
||||
@ -1066,11 +1158,13 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now we need to make the query to get the next match.
|
||||
nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
|
||||
" FROM ") + table +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :id");
|
||||
nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT value, ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" FROM ") + table +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :") + id;
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(currentKey, "current_key");
|
||||
NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
|
||||
NS_NAMED_LITERAL_CSTRING(objectKey, "object_key");
|
||||
|
||||
switch (mDirection) {
|
||||
case nsIIDBCursor::NEXT:
|
||||
@ -1079,18 +1173,14 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Upper();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND value >= :current_key AND "
|
||||
"( value > :current_key OR "
|
||||
" object_data_key > :object_key )") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND value >= :current_key ") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
|
||||
currentKey + NS_LITERAL_CSTRING(" AND ( value > :") +
|
||||
currentKey + NS_LITERAL_CSTRING(" OR ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" > :") + objectKey +
|
||||
NS_LITERAL_CSTRING(" )") + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
|
||||
currentKey + NS_LITERAL_CSTRING(" LIMIT ");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::NEXT_NO_DUPLICATE:
|
||||
@ -1099,14 +1189,12 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Upper();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart + NS_LITERAL_CSTRING(" AND value > :current_key") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery =
|
||||
queryStart + NS_LITERAL_CSTRING(" AND value >= :current_key") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value > :") +
|
||||
currentKey + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") +
|
||||
currentKey + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV:
|
||||
@ -1116,18 +1204,14 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
mRangeKey = mKeyRange->Lower();
|
||||
}
|
||||
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND value <= :current_key AND "
|
||||
"( value < :current_key OR "
|
||||
" object_data_key < :object_key )") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND value <= :current_key ") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
|
||||
currentKey + NS_LITERAL_CSTRING(" AND ( value < :") +
|
||||
currentKey + NS_LITERAL_CSTRING(" OR ") + keyColumn +
|
||||
NS_LITERAL_CSTRING(" < :") + objectKey +
|
||||
NS_LITERAL_CSTRING(" ) ") + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
|
||||
currentKey + NS_LITERAL_CSTRING(" LIMIT ");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV_NO_DUPLICATE:
|
||||
@ -1136,16 +1220,12 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Lower();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND value < :current_key") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND value <= :current_key") +
|
||||
directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value < :") +
|
||||
currentKey + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") +
|
||||
currentKey + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT ");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1178,52 +1258,81 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
NS_ASSERTION(aConnection, "Passed a null connection!");
|
||||
|
||||
nsCString indexTable;
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("unique_index_data");
|
||||
nsCString objectTable;
|
||||
nsCString objectDataIdColumn;
|
||||
nsCString keyValueColumn;
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
objectTable.AssignLiteral("ai_object_data");
|
||||
objectDataIdColumn.AssignLiteral("ai_object_data_id");
|
||||
keyValueColumn.AssignLiteral("ai_object_data_id");
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("index_data");
|
||||
objectTable.AssignLiteral("object_data");
|
||||
objectDataIdColumn.AssignLiteral("object_data_id");
|
||||
keyValueColumn.AssignLiteral("object_data_key");
|
||||
if (mIndex->IsUnique()) {
|
||||
indexTable.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
indexTable.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(value, "index_table.value");
|
||||
nsCString value = indexTable + NS_LITERAL_CSTRING(".value");
|
||||
nsCString keyValue = indexTable + NS_LITERAL_CSTRING(".") + keyValueColumn;
|
||||
|
||||
nsCString keyRangeClause;
|
||||
if (mKeyRange) {
|
||||
mKeyRange->GetBindingClause(value, keyRangeClause);
|
||||
}
|
||||
|
||||
nsCAutoString directionClause(" ORDER BY index_table.value ");
|
||||
nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value;
|
||||
switch (mDirection) {
|
||||
case nsIIDBCursor::NEXT:
|
||||
case nsIIDBCursor::NEXT_NO_DUPLICATE:
|
||||
directionClause +=
|
||||
NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
|
||||
directionClause += NS_LITERAL_CSTRING(" ASC, ") + keyValue +
|
||||
NS_LITERAL_CSTRING(" ASC");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV:
|
||||
directionClause +=
|
||||
NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
|
||||
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyValue +
|
||||
NS_LITERAL_CSTRING(" DESC");
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV_NO_DUPLICATE:
|
||||
directionClause +=
|
||||
NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
|
||||
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyValue +
|
||||
NS_LITERAL_CSTRING(" ASC");
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Unknown direction!");
|
||||
}
|
||||
|
||||
nsCString firstQuery =
|
||||
NS_LITERAL_CSTRING("SELECT index_table.value, "
|
||||
"index_table.object_data_key, object_data.data, "
|
||||
"object_data.file_ids FROM ") +
|
||||
indexTable +
|
||||
NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
|
||||
"index_table.object_data_id = object_data.id "
|
||||
"WHERE index_table.index_id = :id") +
|
||||
keyRangeClause + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT 1");
|
||||
NS_NAMED_LITERAL_CSTRING(id, "id");
|
||||
NS_NAMED_LITERAL_CSTRING(dot, ".");
|
||||
NS_NAMED_LITERAL_CSTRING(commaspace, ", ");
|
||||
|
||||
nsCString data = objectTable + NS_LITERAL_CSTRING(".data");
|
||||
nsCString fileIds = objectTable + NS_LITERAL_CSTRING(".file_ids");
|
||||
|
||||
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + value + commaspace +
|
||||
keyValue + commaspace + data + commaspace + fileIds +
|
||||
NS_LITERAL_CSTRING(" FROM ") + indexTable +
|
||||
NS_LITERAL_CSTRING(" INNER JOIN ") + objectTable +
|
||||
NS_LITERAL_CSTRING(" ON ") + indexTable + dot +
|
||||
objectDataIdColumn + NS_LITERAL_CSTRING(" = ") +
|
||||
objectTable + dot + id +
|
||||
NS_LITERAL_CSTRING(" WHERE ") + indexTable +
|
||||
NS_LITERAL_CSTRING(".index_id = :") + id +
|
||||
keyRangeClause + directionClause +
|
||||
NS_LITERAL_CSTRING(" LIMIT 1");
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt =
|
||||
mTransaction->GetCachedStatement(firstQuery);
|
||||
@ -1231,7 +1340,7 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (mKeyRange) {
|
||||
@ -1259,17 +1368,29 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now we need to make the query to get the next match.
|
||||
nsCAutoString queryStart =
|
||||
NS_LITERAL_CSTRING("SELECT index_table.value, "
|
||||
"index_table.object_data_key, object_data.data, "
|
||||
"object_data.file_ids FROM ") +
|
||||
indexTable +
|
||||
NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
|
||||
"index_table.object_data_id = object_data.id "
|
||||
"WHERE index_table.index_id = :id");
|
||||
nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT ") + value +
|
||||
commaspace + keyValue + commaspace + data +
|
||||
commaspace + fileIds +
|
||||
NS_LITERAL_CSTRING(" FROM ") + indexTable +
|
||||
NS_LITERAL_CSTRING(" INNER JOIN ") + objectTable +
|
||||
NS_LITERAL_CSTRING(" ON ") + indexTable + dot +
|
||||
objectDataIdColumn + NS_LITERAL_CSTRING(" = ") +
|
||||
objectTable + dot + id +
|
||||
NS_LITERAL_CSTRING(" WHERE ") + indexTable +
|
||||
NS_LITERAL_CSTRING(".index_id = :") + id;
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(currentKey, "current_key");
|
||||
NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
|
||||
NS_NAMED_LITERAL_CSTRING(objectKey, "object_key");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(andStr, " AND ");
|
||||
NS_NAMED_LITERAL_CSTRING(orStr, " OR ");
|
||||
NS_NAMED_LITERAL_CSTRING(ge, " >= :");
|
||||
NS_NAMED_LITERAL_CSTRING(gt, " > :");
|
||||
NS_NAMED_LITERAL_CSTRING(le, " <= :");
|
||||
NS_NAMED_LITERAL_CSTRING(lt, " < :");
|
||||
NS_NAMED_LITERAL_CSTRING(openparen, " ( ");
|
||||
NS_NAMED_LITERAL_CSTRING(closeparen, " ) ");
|
||||
NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");
|
||||
|
||||
switch (mDirection) {
|
||||
@ -1279,16 +1400,11 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Upper();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
|
||||
"( index_table.value > :current_key OR "
|
||||
" index_table.object_data_key > :object_key ) ") +
|
||||
directionClause + limit;
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
|
||||
directionClause + limit;
|
||||
mContinueQuery = queryStart + andStr + value + ge + currentKey + andStr +
|
||||
openparen + value + gt + currentKey + orStr + keyValue +
|
||||
gt + objectKey + closeparen + directionClause + limit;
|
||||
mContinueToQuery = queryStart + andStr + value + ge + currentKey +
|
||||
directionClause + limit;
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::NEXT_NO_DUPLICATE:
|
||||
@ -1297,14 +1413,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Upper();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
|
||||
directionClause + limit;
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
|
||||
directionClause + limit;
|
||||
mContinueQuery = queryStart + andStr + value + gt + currentKey +
|
||||
directionClause + limit;
|
||||
mContinueToQuery = queryStart + andStr + value + ge + currentKey +
|
||||
directionClause + limit;
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV:
|
||||
@ -1313,16 +1425,11 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Lower();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
|
||||
"( index_table.value < :current_key OR "
|
||||
" index_table.object_data_key < :object_key ) ") +
|
||||
directionClause + limit;
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
|
||||
directionClause + limit;
|
||||
mContinueQuery = queryStart + andStr + value + le + currentKey + andStr +
|
||||
openparen + value + lt + currentKey + orStr + keyValue +
|
||||
lt + objectKey + closeparen + directionClause + limit;
|
||||
mContinueToQuery = queryStart + andStr + value + le + currentKey +
|
||||
directionClause + limit;
|
||||
break;
|
||||
|
||||
case nsIIDBCursor::PREV_NO_DUPLICATE:
|
||||
@ -1331,14 +1438,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
queryStart);
|
||||
mRangeKey = mKeyRange->Lower();
|
||||
}
|
||||
mContinueQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
|
||||
directionClause + limit;
|
||||
mContinueToQuery =
|
||||
queryStart +
|
||||
NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
|
||||
directionClause + limit;
|
||||
mContinueQuery = queryStart + andStr + value + lt + currentKey +
|
||||
directionClause +limit;
|
||||
mContinueToQuery = queryStart + andStr + value + le + currentKey +
|
||||
directionClause + limit;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1372,11 +1475,22 @@ nsresult
|
||||
CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
{
|
||||
nsCString table;
|
||||
if (mIndex->IsUnique()) {
|
||||
table.AssignLiteral("unique_index_data");
|
||||
|
||||
if (mIndex->IsAutoIncrement()) {
|
||||
if (mIndex->IsUnique()) {
|
||||
table.AssignLiteral("ai_unique_index_data");
|
||||
}
|
||||
else {
|
||||
table.AssignLiteral("ai_index_data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
table.AssignLiteral("index_data");
|
||||
if (mIndex->IsUnique()) {
|
||||
table.AssignLiteral("unique_index_data");
|
||||
}
|
||||
else {
|
||||
table.AssignLiteral("index_data");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
|
||||
@ -1395,8 +1509,10 @@ CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
}
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(id, "id");
|
||||
|
||||
nsCString query = NS_LITERAL_CSTRING("SELECT count(*) FROM ") + table +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :id") +
|
||||
NS_LITERAL_CSTRING(" WHERE index_id = :") + id +
|
||||
keyRangeClause;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
|
||||
@ -1404,7 +1520,7 @@ CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||
|
||||
mozStorageStatementScoper scoper(stmt);
|
||||
|
||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
|
||||
nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (mKeyRange) {
|
||||
|
@ -92,6 +92,11 @@ public:
|
||||
return mMultiEntry;
|
||||
}
|
||||
|
||||
bool IsAutoIncrement() const
|
||||
{
|
||||
return mAutoIncrement;
|
||||
}
|
||||
|
||||
const nsString& KeyPath() const
|
||||
{
|
||||
return mKeyPath;
|
||||
@ -111,6 +116,7 @@ private:
|
||||
nsString mKeyPath;
|
||||
bool mUnique;
|
||||
bool mMultiEntry;
|
||||
bool mAutoIncrement;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -72,8 +72,7 @@ public:
|
||||
|
||||
static already_AddRefed<IDBObjectStore>
|
||||
Create(IDBTransaction* aTransaction,
|
||||
ObjectStoreInfo* aInfo,
|
||||
nsIAtom* aDatabaseId);
|
||||
const ObjectStoreInfo* aInfo);
|
||||
|
||||
static bool
|
||||
IsValidKeyPath(JSContext* aCx, const nsAString& aKeyPath);
|
||||
@ -91,6 +90,7 @@ public:
|
||||
UpdateIndexes(IDBTransaction* aTransaction,
|
||||
PRInt64 aObjectStoreId,
|
||||
const Key& aObjectStoreKey,
|
||||
bool aAutoIncrement,
|
||||
bool aOverwrite,
|
||||
PRInt64 aObjectDataId,
|
||||
const nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
|
||||
@ -167,10 +167,8 @@ public:
|
||||
return mTransaction;
|
||||
}
|
||||
|
||||
ObjectStoreInfo* Info()
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
nsresult ModifyValueForNewKey(StructuredCloneWriteInfo& aCloneWriteInfo,
|
||||
Key& aKey);
|
||||
|
||||
protected:
|
||||
IDBObjectStore();
|
||||
@ -201,7 +199,6 @@ private:
|
||||
nsString mKeyPath;
|
||||
bool mAutoIncrement;
|
||||
nsCOMPtr<nsIAtom> mDatabaseId;
|
||||
nsRefPtr<ObjectStoreInfo> mInfo;
|
||||
PRUint32 mStructuredCloneVersion;
|
||||
|
||||
nsTArray<nsRefPtr<IDBIndex> > mCreatedIndexes;
|
||||
|
@ -121,8 +121,6 @@ IDBTransaction::Create(IDBDatabase* aDatabase,
|
||||
|
||||
transaction->mDatabase = aDatabase;
|
||||
transaction->mMode = aMode;
|
||||
|
||||
transaction->mDatabaseInfo = aDatabase->Info();
|
||||
|
||||
if (!transaction->mObjectStoreNames.AppendElements(aObjectStoreNames)) {
|
||||
NS_ERROR("Out of memory!");
|
||||
@ -213,13 +211,8 @@ IDBTransaction::OnRequestFinished()
|
||||
}
|
||||
|
||||
void
|
||||
IDBTransaction::RemoveObjectStore(const nsAString& aName)
|
||||
IDBTransaction::ReleaseCachedObjectStore(const nsAString& aName)
|
||||
{
|
||||
NS_ASSERTION(mMode == nsIIDBTransaction::VERSION_CHANGE,
|
||||
"Only remove object stores on VERSION_CHANGE transactions");
|
||||
|
||||
mDatabaseInfo->RemoveObjectStore(aName);
|
||||
|
||||
for (PRUint32 i = 0; i < mCreatedObjectStores.Length(); i++) {
|
||||
if (mCreatedObjectStores[i]->Name() == aName) {
|
||||
mCreatedObjectStores.RemoveElementAt(i);
|
||||
@ -244,8 +237,7 @@ IDBTransaction::CommitOrRollback()
|
||||
TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
|
||||
NS_ENSURE_STATE(pool);
|
||||
|
||||
nsRefPtr<CommitHelper> helper(new CommitHelper(this, mListener,
|
||||
mCreatedObjectStores));
|
||||
nsRefPtr<CommitHelper> helper(new CommitHelper(this, mListener));
|
||||
|
||||
mCachedStatements.Enumerate(DoomCachedStatements, helper);
|
||||
NS_ASSERTION(!mCachedStatements.Count(), "Statements left!");
|
||||
@ -371,6 +363,119 @@ IDBTransaction::GetOrCreateConnection(mozIStorageConnection** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
IDBTransaction::AddStatement(bool aCreate,
|
||||
bool aOverwrite,
|
||||
bool aAutoIncrement)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!aCreate) {
|
||||
NS_ASSERTION(aOverwrite, "Bad param combo!");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aAutoIncrement) {
|
||||
if (aCreate) {
|
||||
if (aOverwrite) {
|
||||
return GetCachedStatement(
|
||||
"INSERT OR FAIL INTO ai_object_data (object_store_id, id, data, "
|
||||
"file_ids) "
|
||||
"VALUES (:osid, :key_value, :data, :file_ids)"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"INSERT INTO ai_object_data (object_store_id, data, file_ids) "
|
||||
"VALUES (:osid, :data, :file_ids)"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"UPDATE ai_object_data "
|
||||
"SET data = :data, file_ids = :file_ids "
|
||||
"WHERE object_store_id = :osid "
|
||||
"AND id = :key_value"
|
||||
);
|
||||
}
|
||||
if (aCreate) {
|
||||
if (aOverwrite) {
|
||||
return GetCachedStatement(
|
||||
"INSERT OR FAIL INTO object_data (object_store_id, key_value, data, "
|
||||
"file_ids) "
|
||||
"VALUES (:osid, :key_value, :data, :file_ids)"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"INSERT INTO object_data (object_store_id, key_value, data, file_ids) "
|
||||
"VALUES (:osid, :key_value, :data, :file_ids)"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"UPDATE object_data "
|
||||
"SET data = :data, file_ids = :file_ids "
|
||||
"WHERE object_store_id = :osid "
|
||||
"AND key_value = :key_value"
|
||||
);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
IDBTransaction::IndexDataInsertStatement(bool aAutoIncrement,
|
||||
bool aUnique)
|
||||
{
|
||||
if (aAutoIncrement) {
|
||||
if (aUnique) {
|
||||
return GetCachedStatement(
|
||||
"INSERT INTO ai_unique_index_data "
|
||||
"(index_id, ai_object_data_id, value) "
|
||||
"VALUES (:index_id, :object_data_id, :value)"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"INSERT OR IGNORE INTO ai_index_data "
|
||||
"(index_id, ai_object_data_id, value) "
|
||||
"VALUES (:index_id, :object_data_id, :value)"
|
||||
);
|
||||
}
|
||||
if (aUnique) {
|
||||
return GetCachedStatement(
|
||||
"INSERT INTO unique_index_data "
|
||||
"(index_id, object_data_id, object_data_key, value) "
|
||||
"VALUES (:index_id, :object_data_id, :object_data_key, :value)"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"INSERT OR IGNORE INTO index_data ("
|
||||
"index_id, object_data_id, object_data_key, value) "
|
||||
"VALUES (:index_id, :object_data_id, :object_data_key, :value)"
|
||||
);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
IDBTransaction::IndexDataDeleteStatement(bool aAutoIncrement,
|
||||
bool aUnique)
|
||||
{
|
||||
if (aAutoIncrement) {
|
||||
if (aUnique) {
|
||||
return GetCachedStatement(
|
||||
"DELETE FROM ai_unique_index_data "
|
||||
"WHERE ai_object_data_id = :object_data_id"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"DELETE FROM ai_index_data "
|
||||
"WHERE ai_object_data_id = :object_data_id"
|
||||
);
|
||||
}
|
||||
if (aUnique) {
|
||||
return GetCachedStatement(
|
||||
"DELETE FROM unique_index_data "
|
||||
"WHERE object_data_id = :object_data_id"
|
||||
);
|
||||
}
|
||||
return GetCachedStatement(
|
||||
"DELETE FROM index_data "
|
||||
"WHERE object_data_id = :object_data_id"
|
||||
);
|
||||
}
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
IDBTransaction::GetCachedStatement(const nsACString& aQuery)
|
||||
{
|
||||
@ -452,9 +557,13 @@ IDBTransaction::GetOrCreateObjectStore(const nsAString& aName,
|
||||
}
|
||||
}
|
||||
|
||||
retval = IDBObjectStore::Create(this, aObjectStoreInfo, mDatabaseInfo->id);
|
||||
retval = IDBObjectStore::Create(this, aObjectStoreInfo);
|
||||
NS_ENSURE_TRUE(retval, nsnull);
|
||||
|
||||
mCreatedObjectStores.AppendElement(retval);
|
||||
if (!mCreatedObjectStores.AppendElement(retval)) {
|
||||
NS_WARNING("Out of memory!");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
@ -549,7 +658,12 @@ IDBTransaction::GetObjectStoreNames(nsIDOMDOMStringList** aObjectStores)
|
||||
nsTArray<nsString>* arrayOfNames;
|
||||
|
||||
if (mMode == IDBTransaction::VERSION_CHANGE) {
|
||||
mDatabaseInfo->GetObjectStoreNames(stackArray);
|
||||
DatabaseInfo* info = mDatabase->Info();
|
||||
|
||||
if (!info->GetObjectStoreNames(stackArray)) {
|
||||
NS_ERROR("Out of memory!");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
arrayOfNames = &stackArray;
|
||||
}
|
||||
@ -581,7 +695,7 @@ IDBTransaction::ObjectStore(const nsAString& aName,
|
||||
|
||||
if (mMode == nsIIDBTransaction::VERSION_CHANGE ||
|
||||
mObjectStoreNames.Contains(aName)) {
|
||||
info = mDatabaseInfo->GetObjectStore(aName);
|
||||
mDatabase->Info()->GetObjectStore(aName, &info);
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
@ -733,23 +847,15 @@ IDBTransaction::AfterProcessNextEvent(nsIThreadInternal* aThread,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CommitHelper::CommitHelper(
|
||||
IDBTransaction* aTransaction,
|
||||
IDBTransactionListener* aListener,
|
||||
const nsTArray<nsRefPtr<IDBObjectStore> >& aUpdatedObjectStores)
|
||||
CommitHelper::CommitHelper(IDBTransaction* aTransaction,
|
||||
IDBTransactionListener* aListener)
|
||||
: mTransaction(aTransaction),
|
||||
mListener(aListener),
|
||||
mAborted(!!aTransaction->mAborted)
|
||||
mAborted(!!aTransaction->mAborted),
|
||||
mHaveMetadata(false)
|
||||
{
|
||||
mConnection.swap(aTransaction->mConnection);
|
||||
mUpdateFileRefcountFunction.swap(aTransaction->mUpdateFileRefcountFunction);
|
||||
|
||||
for (PRUint32 i = 0; i < aUpdatedObjectStores.Length(); i++) {
|
||||
ObjectStoreInfo* info = aUpdatedObjectStores[i]->Info();
|
||||
if (info->comittedAutoIncrementId != info->nextAutoIncrementId) {
|
||||
mAutoIncrementObjectStores.AppendElement(aUpdatedObjectStores[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CommitHelper::~CommitHelper()
|
||||
@ -776,11 +882,19 @@ CommitHelper::Run()
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
if (mAborted) {
|
||||
if (mTransaction->Mode() == nsIIDBTransaction::VERSION_CHANGE) {
|
||||
// This will make the database take a snapshot of it's DatabaseInfo
|
||||
mTransaction->Database()->Close();
|
||||
// Then remove the info from the hash as it contains invalid data.
|
||||
DatabaseInfo::Remove(mTransaction->Database()->Id());
|
||||
if (mHaveMetadata) {
|
||||
NS_ASSERTION(mTransaction->Mode() == nsIIDBTransaction::VERSION_CHANGE,
|
||||
"Bad transaction type!");
|
||||
|
||||
DatabaseInfo* dbInfo = mTransaction->Database()->Info();
|
||||
|
||||
if (NS_FAILED(IDBFactory::UpdateDatabaseMetadata(dbInfo, mOldVersion,
|
||||
mOldObjectStores))) {
|
||||
NS_WARNING("Failed to update database metadata!");
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(mOldObjectStores.IsEmpty(), "Should have swapped!");
|
||||
}
|
||||
}
|
||||
|
||||
event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR),
|
||||
@ -824,17 +938,12 @@ CommitHelper::Run()
|
||||
mAborted = true;
|
||||
}
|
||||
|
||||
if (!mAborted && NS_FAILED(WriteAutoIncrementCounts())) {
|
||||
mAborted = true;
|
||||
}
|
||||
|
||||
if (!mAborted) {
|
||||
NS_NAMED_LITERAL_CSTRING(release, "COMMIT TRANSACTION");
|
||||
if (NS_SUCCEEDED(mConnection->ExecuteSimpleSQL(release))) {
|
||||
if (mUpdateFileRefcountFunction) {
|
||||
mUpdateFileRefcountFunction->UpdateFileInfos();
|
||||
}
|
||||
CommitAutoIncrementCounts();
|
||||
}
|
||||
else {
|
||||
mAborted = true;
|
||||
@ -842,11 +951,23 @@ CommitHelper::Run()
|
||||
}
|
||||
|
||||
if (mAborted) {
|
||||
RevertAutoIncrementCounts();
|
||||
NS_NAMED_LITERAL_CSTRING(rollback, "ROLLBACK TRANSACTION");
|
||||
if (NS_FAILED(mConnection->ExecuteSimpleSQL(rollback))) {
|
||||
NS_WARNING("Failed to rollback transaction!");
|
||||
}
|
||||
|
||||
if (mTransaction->Mode() == nsIIDBTransaction::VERSION_CHANGE) {
|
||||
nsresult rv =
|
||||
IDBFactory::LoadDatabaseInformation(mConnection,
|
||||
mTransaction->Database()->Id(),
|
||||
&mOldVersion, mOldObjectStores);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mHaveMetadata = true;
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Failed to get database information!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -870,55 +991,6 @@ CommitHelper::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CommitHelper::WriteAutoIncrementCounts()
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
nsresult rv;
|
||||
for (PRUint32 i = 0; i < mAutoIncrementObjectStores.Length(); i++) {
|
||||
ObjectStoreInfo* info = mAutoIncrementObjectStores[i]->Info();
|
||||
if (!stmt) {
|
||||
rv = mConnection->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"UPDATE object_store SET auto_increment = :ai "
|
||||
"WHERE id = :osid;"), getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
stmt->Reset();
|
||||
}
|
||||
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), info->id);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("ai"),
|
||||
info->nextAutoIncrementId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = stmt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CommitHelper::CommitAutoIncrementCounts()
|
||||
{
|
||||
for (PRUint32 i = 0; i < mAutoIncrementObjectStores.Length(); i++) {
|
||||
ObjectStoreInfo* info = mAutoIncrementObjectStores[i]->Info();
|
||||
info->comittedAutoIncrementId = info->nextAutoIncrementId;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommitHelper::RevertAutoIncrementCounts()
|
||||
{
|
||||
for (PRUint32 i = 0; i < mAutoIncrementObjectStores.Length(); i++) {
|
||||
ObjectStoreInfo* info = mAutoIncrementObjectStores[i]->Info();
|
||||
info->nextAutoIncrementId = info->comittedAutoIncrementId;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
UpdateRefcountFunction::Init()
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ public:
|
||||
void OnNewRequest();
|
||||
void OnRequestFinished();
|
||||
|
||||
void RemoveObjectStore(const nsAString& aName);
|
||||
void ReleaseCachedObjectStore(const nsAString& aName);
|
||||
|
||||
void SetTransactionListener(IDBTransactionListener* aListener);
|
||||
|
||||
@ -118,6 +118,19 @@ public:
|
||||
// Only meant to be called on mStorageThread!
|
||||
nsresult GetOrCreateConnection(mozIStorageConnection** aConnection);
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
AddStatement(bool aCreate,
|
||||
bool aOverwrite,
|
||||
bool aAutoIncrement);
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
IndexDataInsertStatement(bool aAutoIncrement,
|
||||
bool aUnique);
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
IndexDataDeleteStatement(bool aAutoIncrement,
|
||||
bool aUnique);
|
||||
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
GetCachedStatement(const nsACString& aQuery);
|
||||
|
||||
@ -125,7 +138,9 @@ public:
|
||||
already_AddRefed<mozIStorageStatement>
|
||||
GetCachedStatement(const char (&aQuery)[N])
|
||||
{
|
||||
return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
|
||||
nsCString query;
|
||||
query.AssignLiteral(aQuery);
|
||||
return GetCachedStatement(query);
|
||||
}
|
||||
|
||||
bool IsOpen() const;
|
||||
@ -152,11 +167,6 @@ public:
|
||||
return mDatabase;
|
||||
}
|
||||
|
||||
DatabaseInfo* DBInfo() const
|
||||
{
|
||||
return mDatabaseInfo;
|
||||
}
|
||||
|
||||
already_AddRefed<IDBObjectStore>
|
||||
GetOrCreateObjectStore(const nsAString& aName,
|
||||
ObjectStoreInfo* aObjectStoreInfo);
|
||||
@ -172,7 +182,6 @@ private:
|
||||
nsresult CommitOrRollback();
|
||||
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<DatabaseInfo> mDatabaseInfo;
|
||||
nsTArray<nsString> mObjectStoreNames;
|
||||
PRUint16 mReadyState;
|
||||
PRUint16 mMode;
|
||||
@ -215,8 +224,7 @@ public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
CommitHelper(IDBTransaction* aTransaction,
|
||||
IDBTransactionListener* aListener,
|
||||
const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
|
||||
IDBTransactionListener* aListener);
|
||||
~CommitHelper();
|
||||
|
||||
template<class T>
|
||||
@ -233,23 +241,17 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Writes new autoincrement counts to database
|
||||
nsresult WriteAutoIncrementCounts();
|
||||
|
||||
// Updates counts after a successful commit
|
||||
void CommitAutoIncrementCounts();
|
||||
|
||||
// Reverts counts when a transaction is aborted
|
||||
void RevertAutoIncrementCounts();
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
nsRefPtr<IDBTransactionListener> mListener;
|
||||
nsCOMPtr<mozIStorageConnection> mConnection;
|
||||
nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
|
||||
nsAutoTArray<nsCOMPtr<nsISupports>, 10> mDoomedObjects;
|
||||
nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
|
||||
|
||||
PRUint64 mOldVersion;
|
||||
nsTArray<nsAutoPtr<ObjectStoreInfo> > mOldObjectStores;
|
||||
|
||||
bool mAborted;
|
||||
bool mHaveMetadata;
|
||||
};
|
||||
|
||||
class UpdateRefcountFunction : public mozIStorageFunction
|
||||
|
@ -38,7 +38,6 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "DatabaseInfo.h"
|
||||
|
||||
#include "nsIFile.h"
|
||||
#include "nsIObserverService.h"
|
||||
@ -80,6 +79,9 @@
|
||||
// Preference that users can set to override DEFAULT_QUOTA_MB
|
||||
#define PREF_INDEXEDDB_QUOTA "dom.indexedDB.warningQuota"
|
||||
|
||||
// A bad TLS index number.
|
||||
#define BAD_TLS_INDEX (PRUintn)-1
|
||||
|
||||
USING_INDEXEDDB_NAMESPACE
|
||||
using namespace mozilla::services;
|
||||
using mozilla::Preferences;
|
||||
@ -1181,8 +1183,6 @@ IndexedDatabaseManager::ClearDatabasesForURI(nsIURI* aURI)
|
||||
for (PRUint32 index = 0; index < liveDatabases.Length(); index++) {
|
||||
liveDatabases[index]->Invalidate();
|
||||
}
|
||||
|
||||
DatabaseInfo::RemoveAllForOrigin(origin);
|
||||
|
||||
// After everything has been invalidated the helper should be dispatched to
|
||||
// the end of the event queue.
|
||||
|
@ -238,10 +238,12 @@ public:
|
||||
if (IsString()) {
|
||||
rv = aStatement->BindStringByName(aParamName, ToString());
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(IsInteger(), "Bad key!");
|
||||
else if (IsInteger()) {
|
||||
rv = aStatement->BindInt64ByName(aParamName, ToInteger());
|
||||
}
|
||||
else {
|
||||
NS_NOTREACHED("Bad key!");
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace {
|
||||
PR_STATIC_ASSERT(JS_STRUCTURED_CLONE_VERSION == 1);
|
||||
|
||||
// Major schema version. Bump for almost everything.
|
||||
const PRUint32 kMajorSchemaVersion = 11;
|
||||
const PRUint32 kMajorSchemaVersion = 10;
|
||||
|
||||
// Minor schema version. Should almost always be 0 (maybe bump on release
|
||||
// branches if we have to).
|
||||
@ -169,6 +169,38 @@ CreateFileTables(mozIStorageConnection* aDBConn)
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TRIGGER ai_object_data_insert_trigger "
|
||||
"AFTER INSERT ON ai_object_data "
|
||||
"FOR EACH ROW "
|
||||
"WHEN NEW.file_ids IS NOT NULL "
|
||||
"BEGIN "
|
||||
"SELECT update_refcount(NULL, NEW.file_ids); "
|
||||
"END;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TRIGGER ai_object_data_update_trigger "
|
||||
"AFTER UPDATE OF file_ids ON ai_object_data "
|
||||
"FOR EACH ROW "
|
||||
"WHEN OLD.file_ids IS NOT NULL OR NEW.file_ids IS NOT NULL "
|
||||
"BEGIN "
|
||||
"SELECT update_refcount(OLD.file_ids, NEW.file_ids); "
|
||||
"END;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TRIGGER ai_object_data_delete_trigger "
|
||||
"AFTER DELETE ON ai_object_data "
|
||||
"FOR EACH ROW WHEN OLD.file_ids IS NOT NULL "
|
||||
"BEGIN "
|
||||
"SELECT update_refcount(OLD.file_ids, NULL); "
|
||||
"END;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TRIGGER file_update_trigger "
|
||||
"AFTER UPDATE ON file "
|
||||
@ -225,15 +257,31 @@ CreateTables(mozIStorageConnection* aDBConn)
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Table `ai_object_data`
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE ai_object_data ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"object_store_id INTEGER NOT NULL, "
|
||||
"data BLOB NOT NULL, "
|
||||
"file_ids TEXT, "
|
||||
"UNIQUE (object_store_id, id), "
|
||||
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
|
||||
"CASCADE"
|
||||
");"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Table `index`
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE object_store_index ("
|
||||
"id INTEGER PRIMARY KEY, "
|
||||
"id INTEGER, "
|
||||
"object_store_id INTEGER NOT NULL, "
|
||||
"name TEXT NOT NULL, "
|
||||
"key_path TEXT NOT NULL, "
|
||||
"unique_index INTEGER NOT NULL, "
|
||||
"multientry INTEGER NOT NULL, "
|
||||
"multientry INTEGER NOT NULL DEFAULT 0, "
|
||||
"object_store_autoincrement INTERGER NOT NULL, "
|
||||
"PRIMARY KEY (id), "
|
||||
"UNIQUE (object_store_id, name), "
|
||||
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
|
||||
"CASCADE"
|
||||
@ -288,6 +336,53 @@ CreateTables(mozIStorageConnection* aDBConn)
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Table `ai_index_data`
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE ai_index_data ("
|
||||
"index_id INTEGER NOT NULL, "
|
||||
"value NOT NULL, "
|
||||
"ai_object_data_id INTEGER NOT NULL, "
|
||||
"PRIMARY KEY (index_id, value, ai_object_data_id), "
|
||||
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
|
||||
"CASCADE, "
|
||||
"FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
|
||||
"CASCADE"
|
||||
");"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Need this to make cascading deletes from ai_object_data and object_store
|
||||
// fast.
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE INDEX ai_index_data_ai_object_data_id_index "
|
||||
"ON ai_index_data (ai_object_data_id);"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Table `ai_unique_index_data`
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE ai_unique_index_data ("
|
||||
"index_id INTEGER NOT NULL, "
|
||||
"value NOT NULL, "
|
||||
"ai_object_data_id INTEGER NOT NULL, "
|
||||
"UNIQUE (index_id, value), "
|
||||
"PRIMARY KEY (index_id, value, ai_object_data_id), "
|
||||
"FOREIGN KEY (index_id) REFERENCES object_store_index(id) ON DELETE "
|
||||
"CASCADE, "
|
||||
"FOREIGN KEY (ai_object_data_id) REFERENCES ai_object_data(id) ON DELETE "
|
||||
"CASCADE"
|
||||
");"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Need this to make cascading deletes from ai_object_data and object_store
|
||||
// fast.
|
||||
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE INDEX ai_unique_index_data_ai_object_data_id_index "
|
||||
"ON ai_unique_index_data (ai_object_data_id);"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = CreateFileTables(aDBConn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -963,121 +1058,6 @@ UpgradeSchemaFrom9_0To10_0(mozIStorageConnection* aConnection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
UpgradeSchemaFrom10_0To11_0(mozIStorageConnection* aConnection)
|
||||
{
|
||||
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TEMPORARY TABLE temp_upgrade ("
|
||||
"id, "
|
||||
"object_store_id, "
|
||||
"name, "
|
||||
"key_path, "
|
||||
"unique_index, "
|
||||
"multientry"
|
||||
");"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO temp_upgrade "
|
||||
"SELECT id, object_store_id, name, key_path, "
|
||||
"unique_index, multientry "
|
||||
"FROM object_store_index;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DROP TABLE object_store_index;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE object_store_index ("
|
||||
"id INTEGER PRIMARY KEY, "
|
||||
"object_store_id INTEGER NOT NULL, "
|
||||
"name TEXT NOT NULL, "
|
||||
"key_path TEXT NOT NULL, "
|
||||
"unique_index INTEGER NOT NULL, "
|
||||
"multientry INTEGER NOT NULL, "
|
||||
"UNIQUE (object_store_id, name), "
|
||||
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
|
||||
"CASCADE"
|
||||
");"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO object_store_index "
|
||||
"SELECT id, object_store_id, name, key_path, "
|
||||
"unique_index, multientry "
|
||||
"FROM temp_upgrade;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DROP TABLE temp_upgrade;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO object_data (object_store_id, key_value, data, file_ids) "
|
||||
"SELECT object_store_id, id, data, file_ids "
|
||||
"FROM ai_object_data;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO index_data (index_id, value, object_data_key, object_data_id) "
|
||||
"SELECT ai_index_data.index_id, ai_index_data.value, ai_index_data.ai_object_data_id, object_data.id "
|
||||
"FROM ai_index_data "
|
||||
"INNER JOIN object_store_index ON "
|
||||
"object_store_index.id = ai_index_data.index_id "
|
||||
"INNER JOIN object_data ON "
|
||||
"object_data.object_store_id = object_store_index.object_store_id AND "
|
||||
"object_data.key_value = ai_index_data.ai_object_data_id;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"INSERT INTO unique_index_data (index_id, value, object_data_key, object_data_id) "
|
||||
"SELECT ai_unique_index_data.index_id, ai_unique_index_data.value, ai_unique_index_data.ai_object_data_id, object_data.id "
|
||||
"FROM ai_unique_index_data "
|
||||
"INNER JOIN object_store_index ON "
|
||||
"object_store_index.id = ai_unique_index_data.index_id "
|
||||
"INNER JOIN object_data ON "
|
||||
"object_data.object_store_id = object_store_index.object_store_id AND "
|
||||
"object_data.key_value = ai_unique_index_data.ai_object_data_id;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"UPDATE object_store "
|
||||
"SET auto_increment = (SELECT max(id) FROM ai_object_data) + 1 "
|
||||
"WHERE auto_increment;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DROP TABLE ai_unique_index_data;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DROP TABLE ai_index_data;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DROP TABLE ai_object_data;"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aConnection->SetSchemaVersion(MakeSchemaVersion(11, 0));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class VersionChangeEventsRunnable;
|
||||
|
||||
class SetVersionHelper : public AsyncConnectionHelper,
|
||||
@ -1383,7 +1363,7 @@ OpenDatabaseHelper::DoDatabaseWork()
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0; i < mObjectStores.Length(); i++) {
|
||||
nsRefPtr<ObjectStoreInfo>& objectStoreInfo = mObjectStores[i];
|
||||
nsAutoPtr<ObjectStoreInfo>& objectStoreInfo = mObjectStores[i];
|
||||
for (PRUint32 j = 0; j < objectStoreInfo->indexes.Length(); j++) {
|
||||
IndexInfo& indexInfo = objectStoreInfo->indexes[j];
|
||||
mLastIndexId = NS_MAX(indexInfo.id, mLastIndexId);
|
||||
@ -1529,7 +1509,7 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
||||
}
|
||||
else {
|
||||
// This logic needs to change next time we change the schema!
|
||||
PR_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((11 << 4) + 0));
|
||||
PR_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((10 << 4) + 0));
|
||||
|
||||
while (schemaVersion != kSQLiteSchemaVersion) {
|
||||
if (schemaVersion == 4) {
|
||||
@ -1551,9 +1531,6 @@ OpenDatabaseHelper::CreateDatabaseConnection(
|
||||
else if (schemaVersion == MakeSchemaVersion(9, 0)) {
|
||||
rv = UpgradeSchemaFrom9_0To10_0(connection);
|
||||
}
|
||||
else if (schemaVersion == MakeSchemaVersion(10, 0)) {
|
||||
rv = UpgradeSchemaFrom10_0To11_0(connection);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("Unable to open IndexedDB database, no upgrade path is "
|
||||
"available!");
|
||||
@ -1704,8 +1681,6 @@ OpenDatabaseHelper::Run()
|
||||
// Destroy the database now (we should have the only ref).
|
||||
mDatabase = nsnull;
|
||||
|
||||
DatabaseInfo::Remove(mDatabaseId);
|
||||
|
||||
IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
|
||||
NS_ASSERTION(mgr, "This should never fail!");
|
||||
|
||||
@ -1774,14 +1749,18 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||
|
||||
PRUint32 objectStoreCount = mObjectStores.Length();
|
||||
for (PRUint32 index = 0; index < objectStoreCount; index++) {
|
||||
nsRefPtr<ObjectStoreInfo>& info = mObjectStores[index];
|
||||
nsAutoPtr<ObjectStoreInfo>& info = mObjectStores[index];
|
||||
NS_ASSERTION(info->databaseId == mDatabaseId, "Huh?!");
|
||||
|
||||
ObjectStoreInfo* otherInfo = dbInfo->GetObjectStore(info->name);
|
||||
NS_ASSERTION(otherInfo, "ObjectStore not known!");
|
||||
ObjectStoreInfo* otherInfo;
|
||||
NS_ASSERTION(dbInfo->GetObjectStore(info->name, &otherInfo),
|
||||
"ObjectStore not known!");
|
||||
|
||||
NS_ASSERTION(info->name == otherInfo->name &&
|
||||
info->id == otherInfo->id &&
|
||||
info->keyPath == otherInfo->keyPath,
|
||||
info->keyPath == otherInfo->keyPath &&
|
||||
info->autoIncrement == otherInfo->autoIncrement &&
|
||||
info->databaseId == otherInfo->databaseId,
|
||||
"Metadata mismatch!");
|
||||
NS_ASSERTION(dbInfo->ContainsStoreName(info->name),
|
||||
"Object store names out of date!");
|
||||
@ -1800,6 +1779,8 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||
"Bad index keyPath!");
|
||||
NS_ASSERTION(indexInfo.unique == otherIndexInfo.unique,
|
||||
"Bad index unique value!");
|
||||
NS_ASSERTION(indexInfo.autoIncrement == otherIndexInfo.autoIncrement,
|
||||
"Bad index autoIncrement value!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1810,7 +1791,6 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||
nsRefPtr<DatabaseInfo> newInfo(new DatabaseInfo());
|
||||
|
||||
newInfo->name = mName;
|
||||
newInfo->origin = mASCIIOrigin;
|
||||
newInfo->id = mDatabaseId;
|
||||
newInfo->filePath = mDatabaseFilePath;
|
||||
|
||||
@ -1821,8 +1801,8 @@ OpenDatabaseHelper::EnsureSuccessResult()
|
||||
|
||||
newInfo.swap(dbInfo);
|
||||
|
||||
nsresult rv = IDBFactory::SetDatabaseMetadata(dbInfo, mCurrentVersion,
|
||||
mObjectStores);
|
||||
nsresult rv = IDBFactory::UpdateDatabaseMetadata(dbInfo, mCurrentVersion,
|
||||
mObjectStores);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
NS_ASSERTION(mObjectStores.IsEmpty(), "Should have swapped!");
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
mASCIIOrigin(aASCIIOrigin), mRequestedVersion(aRequestedVersion),
|
||||
mForDeletion(aForDeletion), mDatabaseId(nsnull), mCurrentVersion(0),
|
||||
mLastObjectStoreId(0), mLastIndexId(0), mState(eCreated),
|
||||
mResultCode(NS_OK), mLoadDBMetadata(false)
|
||||
mResultCode(NS_OK)
|
||||
{
|
||||
NS_ASSERTION(!aForDeletion || !aRequestedVersion,
|
||||
"Can't be for deletion and request a version!");
|
||||
@ -132,7 +132,7 @@ private:
|
||||
nsCOMPtr<nsIAtom> mDatabaseId;
|
||||
|
||||
// Out-params.
|
||||
nsTArray<nsRefPtr<ObjectStoreInfo> > mObjectStores;
|
||||
nsTArray<nsAutoPtr<ObjectStoreInfo> > mObjectStores;
|
||||
PRUint64 mCurrentVersion;
|
||||
nsString mDatabaseFilePath;
|
||||
PRInt64 mLastObjectStoreId;
|
||||
@ -153,9 +153,6 @@ private:
|
||||
nsresult mResultCode;
|
||||
|
||||
nsRefPtr<FileManager> mFileManager;
|
||||
|
||||
nsRefPtr<DatabaseInfo> mDBInfo;
|
||||
bool mLoadDBMetadata;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
@ -50,7 +50,7 @@ interface nsIDOMDOMStringList;
|
||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(e93c5ca4-89da-4eb4-b839-271ba4f65a27)]
|
||||
[scriptable, builtinclass, uuid(adc6a1e2-9fd7-4d28-a7f9-9c653313124b)]
|
||||
interface nsIIDBObjectStore : nsISupports
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
@ -61,8 +61,6 @@ interface nsIIDBObjectStore : nsISupports
|
||||
|
||||
readonly attribute nsIIDBTransaction transaction;
|
||||
|
||||
readonly attribute boolean autoIncrement;
|
||||
|
||||
// Success fires IDBTransactionEvent, result == value for key
|
||||
[implicit_jscontext]
|
||||
nsIIDBRequest
|
||||
|
@ -57,7 +57,6 @@ TEST_FILES = \
|
||||
test_add_twice_failure.html \
|
||||
test_advance.html \
|
||||
test_autoIncrement_indexes.html \
|
||||
test_autoIncrement.html \
|
||||
test_bfcache.html \
|
||||
test_clear.html \
|
||||
test_cmp.html \
|
||||
|
@ -88,13 +88,15 @@
|
||||
event = yield;
|
||||
|
||||
is(event.type, "abort", "Got a transaction abort event");
|
||||
is(db.version, 1, "Correct version");
|
||||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
|
||||
//todo(db.version, 1, "Correct version");
|
||||
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
|
||||
|
||||
event = yield;
|
||||
is(event.type, "error", "Got request error event");
|
||||
is(event.target.errorCode, IDBDatabaseException.ABORT_ERR, "Right error code");
|
||||
|
||||
db.close();
|
||||
|
||||
let request = mozIndexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
|
@ -47,11 +47,6 @@ function continueToNextStep()
|
||||
});
|
||||
}
|
||||
|
||||
function continueToNextStepSync()
|
||||
{
|
||||
testGenerator.next();
|
||||
}
|
||||
|
||||
function errorHandler(event)
|
||||
{
|
||||
ok(false, "indexedDB error, code " + event.target.errorCode);
|
||||
@ -80,7 +75,6 @@ ExpectError.prototype = {
|
||||
is(event.type, "error", "Got an error event");
|
||||
is(this._code, event.target.errorCode, "Expected error was thrown.");
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
grabEventAndContinueHandler(event);
|
||||
}
|
||||
};
|
||||
|
@ -82,8 +82,6 @@
|
||||
|
||||
let expected = expectedResult(method, keypath, explicit, autoincrement, existing);
|
||||
|
||||
let valueJSON = JSON.stringify(value);
|
||||
|
||||
ok(true, "making call" + test);
|
||||
|
||||
// Make function call for throwing functions
|
||||
@ -96,16 +94,13 @@
|
||||
ok(true, "did throw" + test);
|
||||
ok(ex instanceof IDBDatabaseException, "Got a IDBDatabaseException" + test);
|
||||
is(ex.code, IDBDatabaseException.DATA_ERR, "expect a DATA_ERR" + test);
|
||||
is(JSON.stringify(value), valueJSON, "call didn't modify value" + test);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make non-throwing function call
|
||||
let req = store[method].apply(store, args);
|
||||
is(JSON.stringify(value), valueJSON, "call didn't modify value" + test);
|
||||
|
||||
req.onsuccess = req.onerror = grabEventAndContinueHandler;
|
||||
req.onsuccess = req.onerror = grabEventAndContinueHandler
|
||||
let e = yield;
|
||||
|
||||
// Figure out what key we used
|
||||
@ -128,7 +123,16 @@
|
||||
}
|
||||
|
||||
is(e.type, "success", "write should succeed" + test);
|
||||
is(e.target.result, key, "write should return correct key" + test);
|
||||
if (autoincrement && speccedNoKey) {
|
||||
todo_is(e.target.result, key, "(fix ai) write should return correct key" + test);
|
||||
key = e.target.result;
|
||||
if (keypath) {
|
||||
value.id = key;
|
||||
}
|
||||
}
|
||||
else {
|
||||
is(e.target.result, key, "write should return correct key" + test);
|
||||
}
|
||||
|
||||
store.get(key).onsuccess = grabEventAndContinueHandler;
|
||||
e = yield;
|
||||
|
@ -1,384 +0,0 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Property Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function genCheck(key, value, test, options) {
|
||||
return function(event) {
|
||||
is(event.target.result, key, "correct returned key in " + test);
|
||||
if (options && options.store) {
|
||||
is(event.target.source, options.store, "correct store in " + test);
|
||||
}
|
||||
if (options && options.trans) {
|
||||
is(event.target.transaction, options.trans, "correct transaction in " + test);
|
||||
}
|
||||
|
||||
event.target.source.get(key).onsuccess = function(event) {
|
||||
is(JSON.stringify(event.target.result), JSON.stringify(value),
|
||||
"correct stored value in " + test);
|
||||
continueToNextStepSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const dbname = window.location.pathname;
|
||||
const RW = IDBTransaction.READ_WRITE
|
||||
let c1 = 1;
|
||||
let c2 = 1;
|
||||
|
||||
let openRequest = mozIndexedDB.open(dbname, 1);
|
||||
openRequest.onerror = errorHandler;
|
||||
openRequest.onupgradeneeded = grabEventAndContinueHandler;
|
||||
openRequest.onsuccess = unexpectedSuccessHandler;
|
||||
let event = yield;
|
||||
let db = event.target.result;
|
||||
let trans = event.target.transaction;
|
||||
|
||||
// Create test stores
|
||||
let store1 = db.createObjectStore("store1", { autoIncrement: true });
|
||||
let store2 = db.createObjectStore("store2", { autoIncrement: true, keyPath: "id" });
|
||||
let store3 = db.createObjectStore("store3", { autoIncrement: false });
|
||||
is(store1.autoIncrement, true, "store1 .autoIncrement");
|
||||
is(store2.autoIncrement, true, "store2 .autoIncrement");
|
||||
is(store3.autoIncrement, false, "store3 .autoIncrement");
|
||||
|
||||
store1.createIndex("unique1", "unique", { unique: true });
|
||||
store2.createIndex("unique1", "unique", { unique: true });
|
||||
|
||||
// Test simple inserts
|
||||
let test = " for test simple insert"
|
||||
store1.add({ foo: "value1" }).onsuccess =
|
||||
genCheck(c1++, { foo: "value1" }, "first" + test);
|
||||
store1.add({ foo: "value2" }).onsuccess =
|
||||
genCheck(c1++, { foo: "value2" }, "second" + test);
|
||||
|
||||
yield;
|
||||
yield;
|
||||
|
||||
store2.put({ bar: "value1" }).onsuccess =
|
||||
genCheck(c2, { bar: "value1", id: c2 }, "first in store2" + test,
|
||||
{ store: store2 });
|
||||
c2++;
|
||||
store1.put({ foo: "value3" }).onsuccess =
|
||||
genCheck(c1++, { foo: "value3" }, "third" + test,
|
||||
{ store: store1 });
|
||||
|
||||
yield;
|
||||
yield;
|
||||
|
||||
store2.get(IDBKeyRange.lowerBound(c2)).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
is(event.target.result, undefined, "no such value" + test);
|
||||
|
||||
// Close version_change transaction
|
||||
openRequest.onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
is(event.target, openRequest, "succeeded to open" + test);
|
||||
is(event.type, "success", "succeeded to open" + test);
|
||||
|
||||
// Test inserting explicit keys
|
||||
test = " for test explicit keys";
|
||||
trans = db.transaction("store1", RW);
|
||||
trans.objectStore("store1").add({ explicit: 1 }, 100).onsuccess =
|
||||
genCheck(100, { explicit: 1 }, "first" + test);
|
||||
c1 = 101;
|
||||
trans = db.transaction("store1", RW);
|
||||
trans.objectStore("store1").add({ explicit: 2 }).onsuccess =
|
||||
genCheck(c1++, { explicit: 2 }, "second" + test);
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction("store1", RW);
|
||||
trans.objectStore("store1").add({ explicit: 3 }, 200).onsuccess =
|
||||
genCheck(200, { explicit: 3 }, "third" + test);
|
||||
c1 = 201;
|
||||
trans.objectStore("store1").add({ explicit: 4 }).onsuccess =
|
||||
genCheck(c1++, { explicit: 4 }, "fourth" + test);
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction("store1", RW);
|
||||
trans.objectStore("store1").add({ explicit: 5 }, 150).onsuccess =
|
||||
genCheck(150, { explicit: 5 }, "fifth" + test);
|
||||
yield;
|
||||
trans.objectStore("store1").add({ explicit: 6 }).onsuccess =
|
||||
genCheck(c1++, { explicit: 6 }, "sixth" + test);
|
||||
yield;
|
||||
|
||||
trans = db.transaction("store1", RW);
|
||||
trans.objectStore("store1").add({ explicit: 7 }, "key").onsuccess =
|
||||
genCheck("key", { explicit: 7 }, "seventh" + test);
|
||||
yield;
|
||||
trans.objectStore("store1").add({ explicit: 8 }).onsuccess =
|
||||
genCheck(c1++, { explicit: 8 }, "eighth" + test);
|
||||
yield;
|
||||
|
||||
trans = db.transaction("store1", RW);
|
||||
trans.objectStore("store1").add({ explicit: 9 }, -100000).onsuccess =
|
||||
genCheck(-100000, { explicit: 9 }, "ninth" + test);
|
||||
yield;
|
||||
trans.objectStore("store1").add({ explicit: 10 }).onsuccess =
|
||||
genCheck(c1++, { explicit: 10 }, "tenth" + test);
|
||||
yield;
|
||||
|
||||
|
||||
trans = db.transaction("store2", RW);
|
||||
trans.objectStore("store2").add({ explicit2: 1, id: 300 }).onsuccess =
|
||||
genCheck(300, { explicit2: 1, id: 300 }, "first store2" + test);
|
||||
c2 = 301;
|
||||
trans = db.transaction("store2", RW);
|
||||
trans.objectStore("store2").add({ explicit2: 2 }).onsuccess =
|
||||
genCheck(c2, { explicit2: 2, id: c2 }, "second store2" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction("store2", RW);
|
||||
trans.objectStore("store2").add({ explicit2: 3, id: 400 }).onsuccess =
|
||||
genCheck(400, { explicit2: 3, id: 400 }, "third store2" + test);
|
||||
c2 = 401;
|
||||
trans.objectStore("store2").add({ explicit2: 4 }).onsuccess =
|
||||
genCheck(c2, { explicit2: 4, id: c2 }, "fourth store2" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction("store2", RW);
|
||||
trans.objectStore("store2").add({ explicit: 5, id: 150 }).onsuccess =
|
||||
genCheck(150, { explicit: 5, id: 150 }, "fifth store2" + test);
|
||||
yield;
|
||||
trans.objectStore("store2").add({ explicit: 6 }).onsuccess =
|
||||
genCheck(c2, { explicit: 6, id: c2 }, "sixth store2" + test);
|
||||
c2++;
|
||||
yield;
|
||||
|
||||
trans = db.transaction("store2", RW);
|
||||
trans.objectStore("store2").add({ explicit: 7, id: "key" }).onsuccess =
|
||||
genCheck("key", { explicit: 7, id: "key" }, "seventh store2" + test);
|
||||
yield;
|
||||
trans.objectStore("store2").add({ explicit: 8 }).onsuccess =
|
||||
genCheck(c2, { explicit: 8, id: c2 }, "eighth store2" + test);
|
||||
c2++;
|
||||
yield;
|
||||
|
||||
trans = db.transaction("store2", RW);
|
||||
trans.objectStore("store2").add({ explicit: 9, id: -100000 }).onsuccess =
|
||||
genCheck(-100000, { explicit: 9, id: -100000 }, "ninth store2" + test);
|
||||
yield;
|
||||
trans.objectStore("store2").add({ explicit: 10 }).onsuccess =
|
||||
genCheck(c2, { explicit: 10, id: c2 }, "tenth store2" + test);
|
||||
c2++;
|
||||
yield;
|
||||
|
||||
|
||||
// Test separate transactions doesn't generate overlapping numbers
|
||||
test = " for test non-overlapping counts";
|
||||
trans = db.transaction("store1", RW);
|
||||
trans2 = db.transaction("store1", RW);
|
||||
trans2.objectStore("store1").put({ over: 2 }).onsuccess =
|
||||
genCheck(c1 + 1, { over: 2 }, "first" + test,
|
||||
{ trans: trans2 });
|
||||
trans.objectStore("store1").put({ over: 1 }).onsuccess =
|
||||
genCheck(c1, { over: 1 }, "second" + test,
|
||||
{ trans: trans });
|
||||
c1 += 2;
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction("store2", RW);
|
||||
trans2 = db.transaction("store2", RW);
|
||||
trans2.objectStore("store2").put({ over: 2 }).onsuccess =
|
||||
genCheck(c2 + 1, { over: 2, id: c2 + 1 }, "third" + test,
|
||||
{ trans: trans2 });
|
||||
trans.objectStore("store2").put({ over: 1 }).onsuccess =
|
||||
genCheck(c2, { over: 1, id: c2 }, "fourth" + test,
|
||||
{ trans: trans });
|
||||
c2 += 2;
|
||||
yield; yield;
|
||||
|
||||
// Test that error inserts doesn't increase generator
|
||||
test = " for test error inserts";
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ unique: 1 }, -1);
|
||||
trans.objectStore("store2").add({ unique: 1, id: "unique" });
|
||||
|
||||
trans.objectStore("store1").add({ error: 1, unique: 1 }).onerror =
|
||||
new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
|
||||
trans.objectStore("store1").add({ error: 2 }).onsuccess =
|
||||
genCheck(c1++, { error: 2 }, "first" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store2").add({ error: 3, unique: 1 }).onerror =
|
||||
new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
|
||||
trans.objectStore("store2").add({ error: 4 }).onsuccess =
|
||||
genCheck(c2, { error: 4, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").add({ error: 5, unique: 1 }, 100000).onerror =
|
||||
new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
|
||||
trans.objectStore("store1").add({ error: 6 }).onsuccess =
|
||||
genCheck(c1++, { error: 6 }, "third" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store2").add({ error: 7, unique: 1, id: 100000 }).onerror =
|
||||
new ExpectError(IDBDatabaseException.CONSTRAINT_ERR);
|
||||
trans.objectStore("store2").add({ error: 8 }).onsuccess =
|
||||
genCheck(c2, { error: 8, id: c2 }, "fourth" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
// Test that aborts doesn't increase generator
|
||||
test = " for test aborted transaction";
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ abort: 1 }).onsuccess =
|
||||
genCheck(c1, { abort: 1 }, "first" + test);
|
||||
trans.objectStore("store2").put({ abort: 2 }).onsuccess =
|
||||
genCheck(c2, { abort: 2, id: c2 }, "second" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").add({ abort: 3 }, 500).onsuccess =
|
||||
genCheck(500, { abort: 3 }, "third" + test);
|
||||
trans.objectStore("store2").put({ abort: 4, id: 600 }).onsuccess =
|
||||
genCheck(600, { abort: 4, id: 600 }, "fourth" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").add({ abort: 5 }).onsuccess =
|
||||
genCheck(501, { abort: 5 }, "fifth" + test);
|
||||
trans.objectStore("store2").put({ abort: 6 }).onsuccess =
|
||||
genCheck(601, { abort: 6, id: 601 }, "sixth" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.abort();
|
||||
trans.onabort = grabEventAndContinueHandler;
|
||||
event = yield
|
||||
is(event.type, "abort", "transaction aborted");
|
||||
is(event.target, trans, "correct transaction aborted");
|
||||
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ abort: 1 }).onsuccess =
|
||||
genCheck(c1++, { abort: 1 }, "re-first" + test);
|
||||
trans.objectStore("store2").put({ abort: 2 }).onsuccess =
|
||||
genCheck(c2, { abort: 2, id: c2 }, "re-second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
// Test that delete doesn't decrease generator
|
||||
test = " for test delete items"
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ delete: 1 }).onsuccess =
|
||||
genCheck(c1++, { delete: 1 }, "first" + test);
|
||||
trans.objectStore("store2").put({ delete: 2 }).onsuccess =
|
||||
genCheck(c2, { delete: 2, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").delete(c1 - 1).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
trans.objectStore("store2").delete(c2 - 1).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").add({ delete: 3 }).onsuccess =
|
||||
genCheck(c1++, { delete: 3 }, "first" + test);
|
||||
trans.objectStore("store2").put({ delete: 4 }).onsuccess =
|
||||
genCheck(c2, { delete: 4, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").delete(c1 - 1).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
trans.objectStore("store2").delete(c2 - 1).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ delete: 5 }).onsuccess =
|
||||
genCheck(c1++, { delete: 5 }, "first" + test);
|
||||
trans.objectStore("store2").put({ delete: 6 }).onsuccess =
|
||||
genCheck(c2, { delete: 6, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
// Test that clears doesn't decrease generator
|
||||
test = " for test clear stores";
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ clear: 1 }).onsuccess =
|
||||
genCheck(c1++, { clear: 1 }, "first" + test);
|
||||
trans.objectStore("store2").put({ clear: 2 }).onsuccess =
|
||||
genCheck(c2, { clear: 2, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").clear().onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
trans.objectStore("store2").clear().onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").add({ clear: 3 }).onsuccess =
|
||||
genCheck(c1++, { clear: 3 }, "third" + test);
|
||||
trans.objectStore("store2").put({ clear: 4 }).onsuccess =
|
||||
genCheck(c2, { clear: 4, id: c2 }, "forth" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").clear().onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
trans.objectStore("store2").clear().onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
yield; yield;
|
||||
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").add({ clear: 5 }).onsuccess =
|
||||
genCheck(c1++, { clear: 5 }, "fifth" + test);
|
||||
trans.objectStore("store2").put({ clear: 6 }).onsuccess =
|
||||
genCheck(c2, { clear: 6, id: c2 }, "sixth" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
|
||||
// Test that close/reopen doesn't decrease generator
|
||||
test = " for test clear stores";
|
||||
trans = db.transaction(["store1", "store2"], RW);
|
||||
trans.objectStore("store1").clear().onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
trans.objectStore("store2").clear().onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
yield; yield;
|
||||
db.close();
|
||||
|
||||
SpecialPowers.gc();
|
||||
|
||||
openRequest = mozIndexedDB.open(dbname, 2);
|
||||
openRequest.onerror = errorHandler;
|
||||
openRequest.onupgradeneeded = grabEventAndContinueHandler;
|
||||
openRequest.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield;
|
||||
db = event.target.result;
|
||||
trans = event.target.transaction;
|
||||
|
||||
trans.objectStore("store1").add({ reopen: 1 }).onsuccess =
|
||||
genCheck(c1++, { reopen: 1 }, "first" + test);
|
||||
trans.objectStore("store2").put({ reopen: 2 }).onsuccess =
|
||||
genCheck(c2, { reopen: 2, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
openRequest.onsuccess = grabEventAndContinueHandler;
|
||||
yield;
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
@ -31,7 +31,8 @@
|
||||
objectStore.add(data).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1, "Added entry");
|
||||
let key = event.target.result;
|
||||
ok(key, "Added entry");
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
||||
event = yield;
|
||||
@ -44,17 +45,17 @@
|
||||
first.get("foo").onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is (event.target.result.id, 1, "Entry in first");
|
||||
is (event.target.result.id, key, "Entry in first");
|
||||
|
||||
second.get("foo").onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is (event.target.result.id, 1, "Entry in second");
|
||||
is (event.target.result.id, key, "Entry in second");
|
||||
|
||||
third.get("foo").onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is (event.target.result.id, 1, "Entry in third");
|
||||
is (event.target.result.id, key, "Entry in third");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
|
@ -21,7 +21,7 @@ function testSteps()
|
||||
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onsuccess = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
@ -43,28 +43,13 @@ function testSteps()
|
||||
is(event.type, "abort", "Got transaction abort event");
|
||||
is(event.target, transaction, "Right target");
|
||||
|
||||
is(db.version, 1, "Correct version");
|
||||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
|
||||
todo(db.version, 1, "Correct version");
|
||||
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
|
||||
|
||||
event = yield;
|
||||
is(event.type, "error", "Got request error event");
|
||||
is(event.target, request, "Right target");
|
||||
|
||||
request = mozIndexedDB.open(name, 1, description);
|
||||
request.onerror = grabEventAndContinueHandler;
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
let db2 = event.target.result;
|
||||
|
||||
isnot(db, db2, "Should give a different db instance");
|
||||
is(db2.version, 1, "Correct version");
|
||||
is(db2.objectStoreNames.length, 0, "Correct objectStoreNames length");
|
||||
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
yield;
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user