Bug 701772: Manage autoIncrement for objectStores ourselves in order to simplify the code, make ai-keys unique per objectStore and not per database, and allow ai-objectStores to contain non-integer keys. r=bent

This commit is contained in:
Jonas Sicking 2011-12-16 16:40:47 -08:00
Родитель a3df325117
Коммит 0173a656f9
23 изменённых файлов: 1169 добавлений и 1231 удалений

Просмотреть файл

@ -71,14 +71,13 @@ CloneObjectStoreInfo(const nsAString& aKey,
{
ObjectStoreInfoHash* hash = static_cast<ObjectStoreInfoHash*>(aUserArg);
nsAutoPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData));
nsRefPtr<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;
}
@ -92,12 +91,23 @@ 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);
@ -108,7 +118,6 @@ IndexInfo::IndexInfo(const IndexInfo& aOther)
name(aOther.name),
keyPath(aOther.keyPath),
unique(aOther.unique),
autoIncrement(aOther.autoIncrement),
multiEntry(aOther.multiEntry)
{
MOZ_COUNT_CTOR(IndexInfo);
@ -121,19 +130,8 @@ IndexInfo::~IndexInfo()
ObjectStoreInfo::ObjectStoreInfo()
: id(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)
nextAutoIncrementId(0),
comittedAutoIncrementId(0)
{
MOZ_COUNT_CTOR(ObjectStoreInfo);
}
@ -206,11 +204,6 @@ 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);
@ -221,6 +214,31 @@ 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)
{
@ -241,17 +259,16 @@ DatabaseInfo::ContainsStoreName(const nsAString& aName)
return objectStoreHash && objectStoreHash->Get(aName, nsnull);
}
bool
DatabaseInfo::GetObjectStore(const nsAString& aName,
ObjectStoreInfo** aInfo)
ObjectStoreInfo*
DatabaseInfo::GetObjectStore(const nsAString& aName)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (objectStoreHash) {
return objectStoreHash->Get(aName, aInfo);
return objectStoreHash->GetWeak(aName);
}
return false;
return nsnull;
}
bool
@ -281,7 +298,7 @@ void
DatabaseInfo::RemoveObjectStore(const nsAString& aName)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(GetObjectStore(aName, nsnull), "Don't know about this one!");
NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!");
if (objectStoreHash) {
objectStoreHash->Remove(aName);

Просмотреть файл

@ -46,14 +46,14 @@
#include "Key.h"
#include "IDBObjectStore.h"
#include "nsClassHashtable.h"
#include "nsRefPtrHashtable.h"
#include "nsHashKeys.h"
BEGIN_INDEXEDDB_NAMESPACE
struct ObjectStoreInfo;
typedef nsClassHashtable<nsStringHashKey, ObjectStoreInfo>
typedef nsRefPtrHashtable<nsStringHashKey, ObjectStoreInfo>
ObjectStoreInfoHash;
class IDBDatabase;
@ -77,14 +77,15 @@ private:
static bool Put(DatabaseInfo* aInfo);
public:
static void Remove(nsIAtom* aId);
public:
static void RemoveAllForOrigin(const nsACString& aOrigin);
bool GetObjectStoreNames(nsTArray<nsString>& aNames);
bool ContainsStoreName(const nsAString& aName);
bool GetObjectStore(const nsAString& aName,
ObjectStoreInfo** aInfo);
ObjectStoreInfo* GetObjectStore(const nsAString& aName);
bool PutObjectStore(ObjectStoreInfo* aInfo);
@ -93,8 +94,9 @@ public:
already_AddRefed<DatabaseInfo> Clone();
nsString name;
nsCString origin;
PRUint64 version;
nsIAtom* id;
nsCOMPtr<nsIAtom> id;
nsString filePath;
PRInt64 nextObjectStoreId;
PRInt64 nextIndexId;
@ -113,14 +115,13 @@ struct IndexInfo
~IndexInfo();
#else
IndexInfo()
: id(LL_MININT), unique(false), autoIncrement(false) { }
: id(LL_MININT), unique(false), multiEntry(false) { }
#endif
PRInt64 id;
nsString name;
nsString keyPath;
bool unique;
bool autoIncrement;
bool multiEntry;
};
@ -128,19 +129,39 @@ struct ObjectStoreInfo
{
#ifdef NS_BUILD_REFCNT_LOGGING
ObjectStoreInfo();
ObjectStoreInfo(ObjectStoreInfo& aOther);
~ObjectStoreInfo();
#else
ObjectStoreInfo()
: id(0), autoIncrement(false), databaseId(0) { }
: id(0), nextAutoIncrementId(0), comittedAutoIncrementId(0) { }
#endif
ObjectStoreInfo(ObjectStoreInfo& aOther);
private:
#ifdef NS_BUILD_REFCNT_LOGGING
~ObjectStoreInfo();
#else
~ObjectStoreInfo() {}
#endif
public:
// Constant members, can be gotten on any thread
nsString name;
PRInt64 id;
nsString keyPath;
bool autoIncrement;
nsIAtom* databaseId;
// Main-thread only members. This must *not* be touced on the database thread
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(IDBDatabase* aDatabase, const nsAString& aName)
: mDatabase(aDatabase), mName(aName)
AutoRemoveObjectStore(DatabaseInfo* aInfo, const nsAString& aName)
: mInfo(aInfo), mName(aName)
{ }
~AutoRemoveObjectStore()
{
if (mDatabase) {
mDatabase->Info()->RemoveObjectStore(mName);
if (mInfo) {
mInfo->RemoveObjectStore(mName);
}
}
void forget()
{
mDatabase = nsnull;
mInfo = nsnull;
}
private:
IDBDatabase* mDatabase;
DatabaseInfo* mInfo;
nsString mName;
};
@ -384,7 +384,7 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
DatabaseInfo* databaseInfo = Info();
DatabaseInfo* databaseInfo = transaction->DBInfo();
nsString keyPath;
keyPath.SetIsVoid(true);
@ -446,25 +446,24 @@ IDBDatabase::CreateObjectStore(const nsAString& aName,
}
}
nsAutoPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo());
nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo());
newInfo->name = aName;
newInfo->id = databaseInfo->nextObjectStoreId++;
newInfo->keyPath = keyPath;
newInfo->autoIncrement = autoIncrement;
newInfo->databaseId = mDatabaseId;
newInfo->nextAutoIncrementId = autoIncrement ? 1 : 0;
newInfo->comittedAutoIncrementId = newInfo->nextAutoIncrementId;
if (!Info()->PutObjectStore(newInfo)) {
if (!databaseInfo->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(this, aName);
AutoRemoveObjectStore autoRemove(databaseInfo, aName);
nsRefPtr<IDBObjectStore> objectStore =
transaction->GetOrCreateObjectStore(aName, objectStoreInfo);
transaction->GetOrCreateObjectStore(aName, newInfo);
NS_ENSURE_TRUE(objectStore, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsRefPtr<CreateObjectStoreHelper> helper =
@ -491,9 +490,9 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName)
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
DatabaseInfo* info = Info();
ObjectStoreInfo* objectStoreInfo;
if (!info->GetObjectStore(aName, &objectStoreInfo)) {
DatabaseInfo* info = transaction->DBInfo();
ObjectStoreInfo* objectStoreInfo = info->GetObjectStore(aName);
if (!objectStoreInfo) {
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
}
@ -502,9 +501,7 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName)
nsresult rv = helper->DispatchToTransactionPool();
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
info->RemoveObjectStore(aName);
transaction->ReleaseCachedObjectStore(aName);
transaction->RemoveObjectStore(aName);
return NS_OK;
}

Просмотреть файл

@ -226,9 +226,8 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
bool hasResult;
while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) {
nsAutoPtr<ObjectStoreInfo>* element =
nsRefPtr<ObjectStoreInfo>* element =
aObjectStores.AppendElement(new ObjectStoreInfo());
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
ObjectStoreInfo* info = element->get();
@ -250,8 +249,8 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
NS_ENSURE_SUCCESS(rv, rv);
}
info->autoIncrement = !!stmt->AsInt32(3);
info->databaseId = aDatabaseId;
info->nextAutoIncrementId = stmt->AsInt64(3);
info->comittedAutoIncrementId = info->nextAutoIncrementId;
ObjectStoreInfoMap* mapEntry = infoMap.AppendElement();
NS_ENSURE_TRUE(mapEntry, NS_ERROR_OUT_OF_MEMORY);
@ -263,8 +262,7 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
// Load index information
rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT object_store_id, id, name, key_path, unique_index, multientry, "
"object_store_autoincrement "
"SELECT object_store_id, id, name, key_path, unique_index, multientry "
"FROM object_store_index"
), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
@ -298,7 +296,6 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
indexInfo->unique = !!stmt->AsInt32(4);
indexInfo->multiEntry = !!stmt->AsInt32(5);
indexInfo->autoIncrement = !!stmt->AsInt32(6);
}
NS_ENSURE_SUCCESS(rv, rv);
@ -327,42 +324,33 @@ IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection,
// static
nsresult
IDBFactory::UpdateDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
PRUint64 aVersion,
ObjectStoreInfoArray& aObjectStores)
IDBFactory::SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
PRUint64 aVersion,
ObjectStoreInfoArray& aObjectStores)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(aDatabaseInfo, "Null pointer!");
ObjectStoreInfoArray objectStores;
if (!objectStores.SwapElements(aObjectStores)) {
NS_WARNING("Out of memory!");
return NS_ERROR_OUT_OF_MEMORY;
}
objectStores.SwapElements(aObjectStores);
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]);
#ifdef DEBUG
{
nsTArray<nsString> existingNames;
aDatabaseInfo->GetObjectStoreNames(existingNames);
NS_ASSERTION(existingNames.IsEmpty(), "Should be an empty DatabaseInfo");
}
#endif
aDatabaseInfo->version = aVersion;
for (PRUint32 index = 0; index < objectStores.Length(); index++) {
nsAutoPtr<ObjectStoreInfo>& info = objectStores[index];
NS_ASSERTION(info->databaseId == aDatabaseInfo->id, "Huh?!");
nsRefPtr<ObjectStoreInfo>& info = objectStores[index];
if (!aDatabaseInfo->PutObjectStore(info)) {
NS_WARNING("Out of memory!");
return NS_ERROR_OUT_OF_MEMORY;
}
info.forget();
}
return NS_OK;

Просмотреть файл

@ -59,7 +59,7 @@ struct ObjectStoreInfo;
class IDBFactory : public nsIIDBFactory
{
typedef nsTArray<nsAutoPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
typedef nsTArray<nsRefPtr<ObjectStoreInfo> > ObjectStoreInfoArray;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIIDBFACTORY
@ -90,9 +90,9 @@ public:
ObjectStoreInfoArray& aObjectStores);
static nsresult
UpdateDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
PRUint64 aVersion,
ObjectStoreInfoArray& aObjectStores);
SetDatabaseMetadata(DatabaseInfo* aDatabaseInfo,
PRUint64 aVersion,
ObjectStoreInfoArray& aObjectStores);
private:
IDBFactory();

Просмотреть файл

@ -321,15 +321,13 @@ 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),
mAutoIncrement(false)
mUnique(false)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
}
@ -693,26 +691,12 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
{
NS_ASSERTION(mKeyRange, "Must have a key range here!");
nsCString keyColumn;
nsCString indexTable;
if (mIndex->IsAutoIncrement()) {
keyColumn.AssignLiteral("ai_object_data_id");
if (mIndex->IsUnique()) {
indexTable.AssignLiteral("ai_unique_index_data");
}
else {
indexTable.AssignLiteral("ai_index_data");
}
if (mIndex->IsUnique()) {
indexTable.AssignLiteral("unique_index_data");
}
else {
keyColumn.AssignLiteral("object_data_key");
if (mIndex->IsUnique()) {
indexTable.AssignLiteral("unique_index_data");
}
else {
indexTable.AssignLiteral("index_data");
}
indexTable.AssignLiteral("index_data");
}
nsCString keyRangeClause;
@ -720,12 +704,10 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
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 +
nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
indexTable +
NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
keyRangeClause +
NS_LITERAL_CSTRING(" LIMIT 1");
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
@ -733,7 +715,8 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = mKeyRange->BindToStatement(stmt);
@ -763,29 +746,12 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
{
NS_ASSERTION(mKeyRange, "Must have a key range here!");
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");
}
nsCString indexTable;
if (mIndex->IsUnique()) {
indexTable.AssignLiteral("unique_index_data");
}
else {
objectTable.AssignLiteral("object_data");
objectColumn.AssignLiteral("object_data_id");
if (mIndex->IsUnique()) {
joinTable.AssignLiteral("unique_index_data");
}
else {
joinTable.AssignLiteral("index_data");
}
indexTable.AssignLiteral("index_data");
}
nsCString keyRangeClause;
@ -793,15 +759,12 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
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 +
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_LITERAL_CSTRING(" LIMIT 1");
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
@ -809,7 +772,8 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = mKeyRange->BindToStatement(stmt);
@ -843,26 +807,12 @@ GetHelper::GetSuccessResult(JSContext* aCx,
nsresult
GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
{
nsCString keyColumn;
nsCString tableName;
if (mIndex->IsAutoIncrement()) {
keyColumn.AssignLiteral("ai_object_data_id");
if (mIndex->IsUnique()) {
tableName.AssignLiteral("ai_unique_index_data");
}
else {
tableName.AssignLiteral("ai_index_data");
}
if (mIndex->IsUnique()) {
tableName.AssignLiteral("unique_index_data");
}
else {
keyColumn.AssignLiteral("object_data_key");
if (mIndex->IsUnique()) {
tableName.AssignLiteral("unique_index_data");
}
else {
tableName.AssignLiteral("index_data");
}
tableName.AssignLiteral("index_data");
}
nsCString keyRangeClause;
@ -876,20 +826,18 @@ GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
limitClause.AppendInt(mLimit);
}
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;
nsCString query = NS_LITERAL_CSTRING("SELECT object_data_key FROM ") +
tableName +
NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
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(indexId, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKeyRange) {
@ -967,33 +915,14 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
nsresult
GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
{
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");
}
nsCString indexTable;
if (mIndex->IsUnique()) {
indexTable.AssignLiteral("unique_index_data");
}
else {
dataTableName.AssignLiteral("object_data");
objectDataId.AssignLiteral("object_data_id");
if (mIndex->IsUnique()) {
indexTableName.AssignLiteral("unique_index_data");
}
else {
indexTableName.AssignLiteral("index_data");
}
indexTable.AssignLiteral("index_data");
}
NS_NAMED_LITERAL_CSTRING(indexId, "index_id");
nsCString keyRangeClause;
if (mKeyRange) {
mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("value"), keyRangeClause);
@ -1005,21 +934,20 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
limitClause.AppendInt(mLimit);
}
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;
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;
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKeyRange) {
@ -1069,31 +997,13 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_ASSERTION(aConnection, "Passed a null connection!");
nsCString table;
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");
}
if (mIndex->IsUnique()) {
table.AssignLiteral("unique_index_data");
}
else {
keyColumn.AssignLiteral("object_data_key");
if (mIndex->IsUnique()) {
table.AssignLiteral("unique_index_data");
}
else {
table.AssignLiteral("index_data");
}
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;
@ -1101,30 +1011,27 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
mKeyRange->GetBindingClause(value, keyRangeClause);
}
nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value;
nsCAutoString directionClause(" ORDER BY value ");
switch (mDirection) {
case nsIIDBCursor::NEXT:
case nsIIDBCursor::NEXT_NO_DUPLICATE:
directionClause += NS_LITERAL_CSTRING(" ASC, ") + keyColumn +
NS_LITERAL_CSTRING(" ASC");
directionClause += NS_LITERAL_CSTRING("ASC, object_data_key ASC");
break;
case nsIIDBCursor::PREV:
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyColumn +
NS_LITERAL_CSTRING(" DESC");
directionClause += NS_LITERAL_CSTRING("DESC, object_data_key DESC");
break;
case nsIIDBCursor::PREV_NO_DUPLICATE:
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyColumn +
NS_LITERAL_CSTRING(" ASC");
directionClause += NS_LITERAL_CSTRING("DESC, object_data_key ASC");
break;
default:
NS_NOTREACHED("Unknown direction!");
}
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, ") + keyColumn +
NS_LITERAL_CSTRING(" FROM ") + table +
NS_LITERAL_CSTRING(" WHERE index_id = :") + id +
nsCString firstQuery = NS_LITERAL_CSTRING("SELECT value, object_data_key "
"FROM ") + table +
NS_LITERAL_CSTRING(" WHERE index_id = :index_id") +
keyRangeClause + directionClause +
NS_LITERAL_CSTRING(" LIMIT 1");
@ -1134,7 +1041,8 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKeyRange) {
@ -1158,13 +1066,11 @@ 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, ") + keyColumn +
NS_LITERAL_CSTRING(" FROM ") + table +
NS_LITERAL_CSTRING(" WHERE index_id = :") + id;
nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT value, object_data_key"
" 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:
@ -1173,14 +1079,18 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Upper();
}
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 ");
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 ");
break;
case nsIIDBCursor::NEXT_NO_DUPLICATE:
@ -1189,12 +1099,14 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Upper();
}
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 ");
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 ");
break;
case nsIIDBCursor::PREV:
@ -1204,14 +1116,18 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
mRangeKey = mKeyRange->Lower();
}
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 ");
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 ");
break;
case nsIIDBCursor::PREV_NO_DUPLICATE:
@ -1220,12 +1136,16 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Lower();
}
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 ");
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 ");
break;
default:
@ -1258,81 +1178,52 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_ASSERTION(aConnection, "Passed a null connection!");
nsCString indexTable;
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");
}
if (mIndex->IsUnique()) {
indexTable.AssignLiteral("unique_index_data");
}
else {
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");
}
indexTable.AssignLiteral("index_data");
}
nsCString value = indexTable + NS_LITERAL_CSTRING(".value");
nsCString keyValue = indexTable + NS_LITERAL_CSTRING(".") + keyValueColumn;
NS_NAMED_LITERAL_CSTRING(value, "index_table.value");
nsCString keyRangeClause;
if (mKeyRange) {
mKeyRange->GetBindingClause(value, keyRangeClause);
}
nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value;
nsCAutoString directionClause(" ORDER BY index_table.value ");
switch (mDirection) {
case nsIIDBCursor::NEXT:
case nsIIDBCursor::NEXT_NO_DUPLICATE:
directionClause += NS_LITERAL_CSTRING(" ASC, ") + keyValue +
NS_LITERAL_CSTRING(" ASC");
directionClause +=
NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
break;
case nsIIDBCursor::PREV:
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyValue +
NS_LITERAL_CSTRING(" DESC");
directionClause +=
NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
break;
case nsIIDBCursor::PREV_NO_DUPLICATE:
directionClause += NS_LITERAL_CSTRING(" DESC, ") + keyValue +
NS_LITERAL_CSTRING(" ASC");
directionClause +=
NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
break;
default:
NS_NOTREACHED("Unknown direction!");
}
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");
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");
nsCOMPtr<mozIStorageStatement> stmt =
mTransaction->GetCachedStatement(firstQuery);
@ -1340,7 +1231,7 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKeyRange) {
@ -1368,29 +1259,17 @@ 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 ") + 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;
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");
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) {
@ -1400,11 +1279,16 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Upper();
}
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;
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;
break;
case nsIIDBCursor::NEXT_NO_DUPLICATE:
@ -1413,10 +1297,14 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Upper();
}
mContinueQuery = queryStart + andStr + value + gt + currentKey +
directionClause + limit;
mContinueToQuery = queryStart + andStr + value + ge + currentKey +
directionClause + limit;
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;
break;
case nsIIDBCursor::PREV:
@ -1425,11 +1313,16 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Lower();
}
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;
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;
break;
case nsIIDBCursor::PREV_NO_DUPLICATE:
@ -1438,10 +1331,14 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
queryStart);
mRangeKey = mKeyRange->Lower();
}
mContinueQuery = queryStart + andStr + value + lt + currentKey +
directionClause +limit;
mContinueToQuery = queryStart + andStr + value + le + currentKey +
directionClause + limit;
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;
break;
default:
@ -1475,22 +1372,11 @@ nsresult
CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
nsCString table;
if (mIndex->IsAutoIncrement()) {
if (mIndex->IsUnique()) {
table.AssignLiteral("ai_unique_index_data");
}
else {
table.AssignLiteral("ai_index_data");
}
if (mIndex->IsUnique()) {
table.AssignLiteral("unique_index_data");
}
else {
if (mIndex->IsUnique()) {
table.AssignLiteral("unique_index_data");
}
else {
table.AssignLiteral("index_data");
}
table.AssignLiteral("index_data");
}
NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
@ -1509,10 +1395,8 @@ 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);
@ -1520,7 +1404,7 @@ CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (mKeyRange) {

Просмотреть файл

@ -92,11 +92,6 @@ public:
return mMultiEntry;
}
bool IsAutoIncrement() const
{
return mAutoIncrement;
}
const nsString& KeyPath() const
{
return mKeyPath;
@ -116,7 +111,6 @@ private:
nsString mKeyPath;
bool mUnique;
bool mMultiEntry;
bool mAutoIncrement;
};
END_INDEXEDDB_NAMESPACE

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -72,7 +72,8 @@ public:
static already_AddRefed<IDBObjectStore>
Create(IDBTransaction* aTransaction,
const ObjectStoreInfo* aInfo);
ObjectStoreInfo* aInfo,
nsIAtom* aDatabaseId);
static bool
IsValidKeyPath(JSContext* aCx, const nsAString& aKeyPath);
@ -90,7 +91,6 @@ public:
UpdateIndexes(IDBTransaction* aTransaction,
PRInt64 aObjectStoreId,
const Key& aObjectStoreKey,
bool aAutoIncrement,
bool aOverwrite,
PRInt64 aObjectDataId,
const nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
@ -167,8 +167,10 @@ public:
return mTransaction;
}
nsresult ModifyValueForNewKey(StructuredCloneWriteInfo& aCloneWriteInfo,
Key& aKey);
ObjectStoreInfo* Info()
{
return mInfo;
}
protected:
IDBObjectStore();
@ -199,6 +201,7 @@ private:
nsString mKeyPath;
bool mAutoIncrement;
nsCOMPtr<nsIAtom> mDatabaseId;
nsRefPtr<ObjectStoreInfo> mInfo;
PRUint32 mStructuredCloneVersion;
nsTArray<nsRefPtr<IDBIndex> > mCreatedIndexes;

Просмотреть файл

@ -121,6 +121,8 @@ IDBTransaction::Create(IDBDatabase* aDatabase,
transaction->mDatabase = aDatabase;
transaction->mMode = aMode;
transaction->mDatabaseInfo = aDatabase->Info();
if (!transaction->mObjectStoreNames.AppendElements(aObjectStoreNames)) {
NS_ERROR("Out of memory!");
@ -211,8 +213,13 @@ IDBTransaction::OnRequestFinished()
}
void
IDBTransaction::ReleaseCachedObjectStore(const nsAString& aName)
IDBTransaction::RemoveObjectStore(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);
@ -237,7 +244,8 @@ IDBTransaction::CommitOrRollback()
TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
NS_ENSURE_STATE(pool);
nsRefPtr<CommitHelper> helper(new CommitHelper(this, mListener));
nsRefPtr<CommitHelper> helper(new CommitHelper(this, mListener,
mCreatedObjectStores));
mCachedStatements.Enumerate(DoomCachedStatements, helper);
NS_ASSERTION(!mCachedStatements.Count(), "Statements left!");
@ -363,119 +371,6 @@ 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)
{
@ -557,13 +452,9 @@ IDBTransaction::GetOrCreateObjectStore(const nsAString& aName,
}
}
retval = IDBObjectStore::Create(this, aObjectStoreInfo);
NS_ENSURE_TRUE(retval, nsnull);
retval = IDBObjectStore::Create(this, aObjectStoreInfo, mDatabaseInfo->id);
if (!mCreatedObjectStores.AppendElement(retval)) {
NS_WARNING("Out of memory!");
return nsnull;
}
mCreatedObjectStores.AppendElement(retval);
return retval.forget();
}
@ -658,12 +549,7 @@ IDBTransaction::GetObjectStoreNames(nsIDOMDOMStringList** aObjectStores)
nsTArray<nsString>* arrayOfNames;
if (mMode == IDBTransaction::VERSION_CHANGE) {
DatabaseInfo* info = mDatabase->Info();
if (!info->GetObjectStoreNames(stackArray)) {
NS_ERROR("Out of memory!");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
mDatabaseInfo->GetObjectStoreNames(stackArray);
arrayOfNames = &stackArray;
}
@ -695,7 +581,7 @@ IDBTransaction::ObjectStore(const nsAString& aName,
if (mMode == nsIIDBTransaction::VERSION_CHANGE ||
mObjectStoreNames.Contains(aName)) {
mDatabase->Info()->GetObjectStore(aName, &info);
info = mDatabaseInfo->GetObjectStore(aName);
}
if (!info) {
@ -847,15 +733,23 @@ IDBTransaction::AfterProcessNextEvent(nsIThreadInternal* aThread,
return NS_OK;
}
CommitHelper::CommitHelper(IDBTransaction* aTransaction,
IDBTransactionListener* aListener)
CommitHelper::CommitHelper(
IDBTransaction* aTransaction,
IDBTransactionListener* aListener,
const nsTArray<nsRefPtr<IDBObjectStore> >& aUpdatedObjectStores)
: mTransaction(aTransaction),
mListener(aListener),
mAborted(!!aTransaction->mAborted),
mHaveMetadata(false)
mAborted(!!aTransaction->mAborted)
{
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()
@ -882,19 +776,11 @@ CommitHelper::Run()
nsCOMPtr<nsIDOMEvent> event;
if (mAborted) {
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!");
}
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());
}
event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR),
@ -938,12 +824,17 @@ 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;
@ -951,23 +842,11 @@ 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!");
}
}
}
}
@ -991,6 +870,55 @@ 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 ReleaseCachedObjectStore(const nsAString& aName);
void RemoveObjectStore(const nsAString& aName);
void SetTransactionListener(IDBTransactionListener* aListener);
@ -118,19 +118,6 @@ 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);
@ -138,9 +125,7 @@ public:
already_AddRefed<mozIStorageStatement>
GetCachedStatement(const char (&aQuery)[N])
{
nsCString query;
query.AssignLiteral(aQuery);
return GetCachedStatement(query);
return GetCachedStatement(NS_LITERAL_CSTRING(aQuery));
}
bool IsOpen() const;
@ -167,6 +152,11 @@ public:
return mDatabase;
}
DatabaseInfo* DBInfo() const
{
return mDatabaseInfo;
}
already_AddRefed<IDBObjectStore>
GetOrCreateObjectStore(const nsAString& aName,
ObjectStoreInfo* aObjectStoreInfo);
@ -182,6 +172,7 @@ private:
nsresult CommitOrRollback();
nsRefPtr<IDBDatabase> mDatabase;
nsRefPtr<DatabaseInfo> mDatabaseInfo;
nsTArray<nsString> mObjectStoreNames;
PRUint16 mReadyState;
PRUint16 mMode;
@ -224,7 +215,8 @@ public:
NS_DECL_NSIRUNNABLE
CommitHelper(IDBTransaction* aTransaction,
IDBTransactionListener* aListener);
IDBTransactionListener* aListener,
const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
~CommitHelper();
template<class T>
@ -241,17 +233,23 @@ 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;
PRUint64 mOldVersion;
nsTArray<nsAutoPtr<ObjectStoreInfo> > mOldObjectStores;
nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
bool mAborted;
bool mHaveMetadata;
};
class UpdateRefcountFunction : public mozIStorageFunction

Просмотреть файл

@ -38,6 +38,7 @@
* ***** END LICENSE BLOCK ***** */
#include "IndexedDatabaseManager.h"
#include "DatabaseInfo.h"
#include "nsIFile.h"
#include "nsIObserverService.h"
@ -79,9 +80,6 @@
// 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;
@ -1183,6 +1181,8 @@ 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,11 +238,9 @@ public:
if (IsString()) {
rv = aStatement->BindStringByName(aParamName, ToString());
}
else if (IsInteger()) {
rv = aStatement->BindInt64ByName(aParamName, ToInteger());
}
else {
NS_NOTREACHED("Bad key!");
NS_ASSERTION(IsInteger(), "Bad key!");
rv = aStatement->BindInt64ByName(aParamName, ToInteger());
}
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 = 10;
const PRUint32 kMajorSchemaVersion = 11;
// Minor schema version. Should almost always be 0 (maybe bump on release
// branches if we have to).
@ -169,38 +169,6 @@ 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 "
@ -257,31 +225,15 @@ 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, "
"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 DEFAULT 0, "
"object_store_autoincrement INTERGER NOT NULL, "
"PRIMARY KEY (id), "
"multientry INTEGER NOT NULL, "
"UNIQUE (object_store_id, name), "
"FOREIGN KEY (object_store_id) REFERENCES object_store(id) ON DELETE "
"CASCADE"
@ -336,53 +288,6 @@ 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);
@ -1058,6 +963,121 @@ 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,
@ -1363,7 +1383,7 @@ OpenDatabaseHelper::DoDatabaseWork()
}
for (PRUint32 i = 0; i < mObjectStores.Length(); i++) {
nsAutoPtr<ObjectStoreInfo>& objectStoreInfo = mObjectStores[i];
nsRefPtr<ObjectStoreInfo>& objectStoreInfo = mObjectStores[i];
for (PRUint32 j = 0; j < objectStoreInfo->indexes.Length(); j++) {
IndexInfo& indexInfo = objectStoreInfo->indexes[j];
mLastIndexId = NS_MAX(indexInfo.id, mLastIndexId);
@ -1509,7 +1529,7 @@ OpenDatabaseHelper::CreateDatabaseConnection(
}
else {
// This logic needs to change next time we change the schema!
PR_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((10 << 4) + 0));
PR_STATIC_ASSERT(kSQLiteSchemaVersion == PRInt32((11 << 4) + 0));
while (schemaVersion != kSQLiteSchemaVersion) {
if (schemaVersion == 4) {
@ -1531,6 +1551,9 @@ 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!");
@ -1681,6 +1704,8 @@ 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!");
@ -1749,18 +1774,14 @@ OpenDatabaseHelper::EnsureSuccessResult()
PRUint32 objectStoreCount = mObjectStores.Length();
for (PRUint32 index = 0; index < objectStoreCount; index++) {
nsAutoPtr<ObjectStoreInfo>& info = mObjectStores[index];
NS_ASSERTION(info->databaseId == mDatabaseId, "Huh?!");
nsRefPtr<ObjectStoreInfo>& info = mObjectStores[index];
ObjectStoreInfo* otherInfo;
NS_ASSERTION(dbInfo->GetObjectStore(info->name, &otherInfo),
"ObjectStore not known!");
ObjectStoreInfo* otherInfo = dbInfo->GetObjectStore(info->name);
NS_ASSERTION(otherInfo, "ObjectStore not known!");
NS_ASSERTION(info->name == otherInfo->name &&
info->id == otherInfo->id &&
info->keyPath == otherInfo->keyPath &&
info->autoIncrement == otherInfo->autoIncrement &&
info->databaseId == otherInfo->databaseId,
info->keyPath == otherInfo->keyPath,
"Metadata mismatch!");
NS_ASSERTION(dbInfo->ContainsStoreName(info->name),
"Object store names out of date!");
@ -1779,8 +1800,6 @@ 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!");
}
}
}
@ -1791,6 +1810,7 @@ OpenDatabaseHelper::EnsureSuccessResult()
nsRefPtr<DatabaseInfo> newInfo(new DatabaseInfo());
newInfo->name = mName;
newInfo->origin = mASCIIOrigin;
newInfo->id = mDatabaseId;
newInfo->filePath = mDatabaseFilePath;
@ -1801,8 +1821,8 @@ OpenDatabaseHelper::EnsureSuccessResult()
newInfo.swap(dbInfo);
nsresult rv = IDBFactory::UpdateDatabaseMetadata(dbInfo, mCurrentVersion,
mObjectStores);
nsresult rv = IDBFactory::SetDatabaseMetadata(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)
mResultCode(NS_OK), mLoadDBMetadata(false)
{
NS_ASSERTION(!aForDeletion || !aRequestedVersion,
"Can't be for deletion and request a version!");
@ -132,7 +132,7 @@ private:
nsCOMPtr<nsIAtom> mDatabaseId;
// Out-params.
nsTArray<nsAutoPtr<ObjectStoreInfo> > mObjectStores;
nsTArray<nsRefPtr<ObjectStoreInfo> > mObjectStores;
PRUint64 mCurrentVersion;
nsString mDatabaseFilePath;
PRInt64 mLastObjectStoreId;
@ -153,6 +153,9 @@ 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(adc6a1e2-9fd7-4d28-a7f9-9c653313124b)]
[scriptable, builtinclass, uuid(e93c5ca4-89da-4eb4-b839-271ba4f65a27)]
interface nsIIDBObjectStore : nsISupports
{
readonly attribute DOMString name;
@ -61,6 +61,8 @@ interface nsIIDBObjectStore : nsISupports
readonly attribute nsIIDBTransaction transaction;
readonly attribute boolean autoIncrement;
// Success fires IDBTransactionEvent, result == value for key
[implicit_jscontext]
nsIIDBRequest

Просмотреть файл

@ -57,6 +57,7 @@ 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,15 +88,13 @@
event = yield;
is(event.type, "abort", "Got a transaction abort event");
//todo(db.version, 1, "Correct version");
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
is(db.version, 1, "Correct version");
is(db.objectStoreNames.length, 1, "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,6 +47,11 @@ function continueToNextStep()
});
}
function continueToNextStepSync()
{
testGenerator.next();
}
function errorHandler(event)
{
ok(false, "indexedDB error, code " + event.target.errorCode);
@ -75,6 +80,7 @@ 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,6 +82,8 @@
let expected = expectedResult(method, keypath, explicit, autoincrement, existing);
let valueJSON = JSON.stringify(value);
ok(true, "making call" + test);
// Make function call for throwing functions
@ -94,13 +96,16 @@
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);
req.onsuccess = req.onerror = grabEventAndContinueHandler
is(JSON.stringify(value), valueJSON, "call didn't modify value" + test);
req.onsuccess = req.onerror = grabEventAndContinueHandler;
let e = yield;
// Figure out what key we used
@ -123,16 +128,7 @@
}
is(e.type, "success", "write should succeed" + 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);
}
is(e.target.result, key, "write should return correct key" + test);
store.get(key).onsuccess = grabEventAndContinueHandler;
e = yield;

Просмотреть файл

@ -0,0 +1,384 @@
<!--
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,8 +31,7 @@
objectStore.add(data).onsuccess = grabEventAndContinueHandler;
event = yield;
let key = event.target.result;
ok(key, "Added entry");
is(event.target.result, 1, "Added entry");
request.onsuccess = grabEventAndContinueHandler;
event = yield;
@ -45,17 +44,17 @@
first.get("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is (event.target.result.id, key, "Entry in first");
is (event.target.result.id, 1, "Entry in first");
second.get("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is (event.target.result.id, key, "Entry in second");
is (event.target.result.id, 1, "Entry in second");
third.get("foo").onsuccess = grabEventAndContinueHandler;
event = yield;
is (event.target.result.id, key, "Entry in third");
is (event.target.result.id, 1, "Entry in third");
finishTest();
yield;

Просмотреть файл

@ -21,7 +21,7 @@ function testSteps()
let request = mozIndexedDB.open(name, 1, description);
request.onerror = grabEventAndContinueHandler;
request.onsuccess = errorHandler;
request.onsuccess = unexpectedSuccessHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;
@ -43,13 +43,28 @@ function testSteps()
is(event.type, "abort", "Got transaction abort event");
is(event.target, transaction, "Right target");
todo(db.version, 1, "Correct version");
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
is(db.version, 1, "Correct version");
is(db.objectStoreNames.length, 1, "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;
}