// static nsresult IDBFactory::SetDatabaseMetadata(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"); } #endif aDatabaseInfo->version = aVersion; for (PRUint32 index = 0; index < objectStores.Length(); index++) { nsRefPtr<ObjectStoreInfo>& info = objectStores[index]; if (!aDatabaseInfo->PutObjectStore(info)) { NS_WARNING("Out of memory!"); return NS_ERROR_OUT_OF_MEMORY; } } return NS_OK; }
// static nsresult IDBFactory::UpdateDatabaseMetadata(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; } 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]); } aDatabaseInfo->version = aVersion; for (PRUint32 index = 0; index < objectStores.Length(); index++) { nsAutoPtr<ObjectStoreInfo>& info = objectStores[index]; NS_ASSERTION(info->databaseId == aDatabaseInfo->id, "Huh?!"); if (!aDatabaseInfo->PutObjectStore(info)) { NS_WARNING("Out of memory!"); return NS_ERROR_OUT_OF_MEMORY; } info.forget(); } return NS_OK; }
// static nsresult IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection, nsIAtom* aDatabaseId, PRUint64* aVersion, ObjectStoreInfoArray& aObjectStores) { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aConnection, "Null pointer!"); aObjectStores.Clear(); // Load object store names and ids. nsCOMPtr<mozIStorageStatement> stmt; nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT name, id, key_path, auto_increment " "FROM object_store" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); nsAutoTArray<ObjectStoreInfoMap, 20> infoMap; bool hasResult; while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { nsRefPtr<ObjectStoreInfo>* element = aObjectStores.AppendElement(new ObjectStoreInfo()); ObjectStoreInfo* info = element->get(); rv = stmt->GetString(0, info->name); NS_ENSURE_SUCCESS(rv, rv); info->id = stmt->AsInt64(1); PRInt32 columnType; nsresult rv = stmt->GetTypeOfIndex(2, &columnType); NS_ENSURE_SUCCESS(rv, rv); // NB: We don't have to handle the NULL case, since that is the default // for a new KeyPath. if (columnType != mozIStorageStatement::VALUE_TYPE_NULL) { NS_ASSERTION(columnType == mozIStorageStatement::VALUE_TYPE_TEXT, "Should be a string"); nsString keyPathSerialization; rv = stmt->GetString(2, keyPathSerialization); NS_ENSURE_SUCCESS(rv, rv); info->keyPath = KeyPath::DeserializeFromString(keyPathSerialization); } info->nextAutoIncrementId = stmt->AsInt64(3); info->comittedAutoIncrementId = info->nextAutoIncrementId; info->autoIncrement = !!info->nextAutoIncrementId; ObjectStoreInfoMap* mapEntry = infoMap.AppendElement(); NS_ENSURE_TRUE(mapEntry, NS_ERROR_OUT_OF_MEMORY); mapEntry->id = info->id; mapEntry->info = info; } NS_ENSURE_SUCCESS(rv, rv); // Load index information rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT object_store_id, id, name, key_path, unique_index, multientry " "FROM object_store_index" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { PRInt64 objectStoreId = stmt->AsInt64(0); ObjectStoreInfo* objectStoreInfo = nsnull; for (PRUint32 index = 0; index < infoMap.Length(); index++) { if (infoMap[index].id == objectStoreId) { objectStoreInfo = infoMap[index].info; break; } } if (!objectStoreInfo) { NS_ERROR("Index for nonexistant object store!"); return NS_ERROR_UNEXPECTED; } IndexInfo* indexInfo = objectStoreInfo->indexes.AppendElement(); NS_ENSURE_TRUE(indexInfo, NS_ERROR_OUT_OF_MEMORY); indexInfo->id = stmt->AsInt64(1); rv = stmt->GetString(2, indexInfo->name); NS_ENSURE_SUCCESS(rv, rv); nsString keyPathSerialization; rv = stmt->GetString(3, keyPathSerialization); NS_ENSURE_SUCCESS(rv, rv); // XXX bent wants to assert here indexInfo->keyPath = KeyPath::DeserializeFromString(keyPathSerialization); indexInfo->unique = !!stmt->AsInt32(4); indexInfo->multiEntry = !!stmt->AsInt32(5); } NS_ENSURE_SUCCESS(rv, rv); // Load version information. rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT version " "FROM database" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, rv); if (!hasResult) { NS_ERROR("Database has no version!"); return NS_ERROR_UNEXPECTED; } PRInt64 version = 0; rv = stmt->GetInt64(0, &version); *aVersion = NS_MAX<PRInt64>(version, 0); return rv; }
// static nsresult IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection, nsIAtom* aDatabaseId, PRUint64* aVersion, ObjectStoreInfoArray& aObjectStores) { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aConnection, "Null pointer!"); aObjectStores.Clear(); // Load object store names and ids. nsCOMPtr<mozIStorageStatement> stmt; nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT name, id, key_path, auto_increment " "FROM object_store" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); nsAutoTArray<ObjectStoreInfoMap, 20> infoMap; bool hasResult; while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { nsRefPtr<ObjectStoreInfo>* element = aObjectStores.AppendElement(new ObjectStoreInfo()); ObjectStoreInfo* info = element->get(); rv = stmt->GetString(0, info->name); NS_ENSURE_SUCCESS(rv, rv); info->id = stmt->AsInt64(1); PRInt32 columnType; nsresult rv = stmt->GetTypeOfIndex(2, &columnType); NS_ENSURE_SUCCESS(rv, rv); if (columnType == mozIStorageStatement::VALUE_TYPE_NULL) { info->keyPath.SetIsVoid(true); } else { NS_ASSERTION(columnType == mozIStorageStatement::VALUE_TYPE_TEXT, "Should be a string"); nsString keyPath; rv = stmt->GetString(2, keyPath); NS_ENSURE_SUCCESS(rv, rv); if (!keyPath.IsEmpty() && keyPath.First() == ',') { // We use a comma in the beginning to indicate that it's an array of // key paths. This is to be able to tell a string-keypath from an // array-keypath which contains only one item. nsCharSeparatedTokenizerTemplate<IgnoreWhitespace> tokenizer(keyPath, ','); tokenizer.nextToken(); while (tokenizer.hasMoreTokens()) { info->keyPathArray.AppendElement(tokenizer.nextToken()); } NS_ASSERTION(!info->keyPathArray.IsEmpty(), "Should have at least one keypath"); } else { info->keyPath = keyPath; } } info->nextAutoIncrementId = stmt->AsInt64(3); info->comittedAutoIncrementId = info->nextAutoIncrementId; info->autoIncrement = !!info->nextAutoIncrementId; ObjectStoreInfoMap* mapEntry = infoMap.AppendElement(); NS_ENSURE_TRUE(mapEntry, NS_ERROR_OUT_OF_MEMORY); mapEntry->id = info->id; mapEntry->info = info; } NS_ENSURE_SUCCESS(rv, rv); // Load index information rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT object_store_id, id, name, key_path, unique_index, multientry " "FROM object_store_index" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { PRInt64 objectStoreId = stmt->AsInt64(0); ObjectStoreInfo* objectStoreInfo = nsnull; for (PRUint32 index = 0; index < infoMap.Length(); index++) { if (infoMap[index].id == objectStoreId) { objectStoreInfo = infoMap[index].info; break; } } if (!objectStoreInfo) { NS_ERROR("Index for nonexistant object store!"); return NS_ERROR_UNEXPECTED; } IndexInfo* indexInfo = objectStoreInfo->indexes.AppendElement(); NS_ENSURE_TRUE(indexInfo, NS_ERROR_OUT_OF_MEMORY); indexInfo->id = stmt->AsInt64(1); rv = stmt->GetString(2, indexInfo->name); NS_ENSURE_SUCCESS(rv, rv); nsString keyPath; rv = stmt->GetString(3, keyPath); NS_ENSURE_SUCCESS(rv, rv); if (!keyPath.IsEmpty() && keyPath.First() == ',') { // We use a comma in the beginning to indicate that it's an array of // key paths. This is to be able to tell a string-keypath from an // array-keypath which contains only one item. nsCharSeparatedTokenizerTemplate<IgnoreWhitespace> tokenizer(keyPath, ','); tokenizer.nextToken(); while (tokenizer.hasMoreTokens()) { indexInfo->keyPathArray.AppendElement(tokenizer.nextToken()); } NS_ASSERTION(!indexInfo->keyPathArray.IsEmpty(), "Should have at least one keypath"); } else { indexInfo->keyPath = keyPath; } indexInfo->unique = !!stmt->AsInt32(4); indexInfo->multiEntry = !!stmt->AsInt32(5); } NS_ENSURE_SUCCESS(rv, rv); // Load version information. rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT version " "FROM database" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, rv); if (!hasResult) { NS_ERROR("Database has no version!"); return NS_ERROR_UNEXPECTED; } PRInt64 version = 0; rv = stmt->GetInt64(0, &version); *aVersion = NS_MAX<PRInt64>(version, 0); return rv; }
// static nsresult IDBFactory::LoadDatabaseInformation(mozIStorageConnection* aConnection, nsIAtom* aDatabaseId, PRUint64* aVersion, ObjectStoreInfoArray& aObjectStores) { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aConnection, "Null pointer!"); aObjectStores.Clear(); // Load object store names and ids. nsCOMPtr<mozIStorageStatement> stmt; nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT name, id, key_path, auto_increment " "FROM object_store" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); nsAutoTArray<ObjectStoreInfoMap, 20> infoMap; bool hasResult; while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { nsAutoPtr<ObjectStoreInfo>* element = aObjectStores.AppendElement(new ObjectStoreInfo()); NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY); ObjectStoreInfo* info = element->get(); rv = stmt->GetString(0, info->name); NS_ENSURE_SUCCESS(rv, rv); info->id = stmt->AsInt64(1); rv = stmt->GetString(2, info->keyPath); NS_ENSURE_SUCCESS(rv, rv); info->autoIncrement = !!stmt->AsInt32(3); info->databaseId = aDatabaseId; ObjectStoreInfoMap* mapEntry = infoMap.AppendElement(); NS_ENSURE_TRUE(mapEntry, NS_ERROR_OUT_OF_MEMORY); mapEntry->id = info->id; mapEntry->info = info; } NS_ENSURE_SUCCESS(rv, rv); // Load index information rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT object_store_id, id, name, key_path, unique_index, " "object_store_autoincrement " "FROM object_store_index" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { PRInt64 objectStoreId = stmt->AsInt64(0); ObjectStoreInfo* objectStoreInfo = nsnull; for (PRUint32 index = 0; index < infoMap.Length(); index++) { if (infoMap[index].id == objectStoreId) { objectStoreInfo = infoMap[index].info; break; } } if (!objectStoreInfo) { NS_ERROR("Index for nonexistant object store!"); return NS_ERROR_UNEXPECTED; } IndexInfo* indexInfo = objectStoreInfo->indexes.AppendElement(); NS_ENSURE_TRUE(indexInfo, NS_ERROR_OUT_OF_MEMORY); indexInfo->id = stmt->AsInt64(1); rv = stmt->GetString(2, indexInfo->name); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->GetString(3, indexInfo->keyPath); NS_ENSURE_SUCCESS(rv, rv); indexInfo->unique = !!stmt->AsInt32(4); indexInfo->autoIncrement = !!stmt->AsInt32(5); } NS_ENSURE_SUCCESS(rv, rv); // Load version information. rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT version " "FROM database" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, rv); if (!hasResult) { NS_ERROR("Database has no version!"); return NS_ERROR_UNEXPECTED; } PRInt64 version = 0; rv = stmt->GetInt64(0, &version); *aVersion = NS_MAX<PRInt64>(version, 0); return rv; }