Reputation: 16274
My code is as follows (usually naming convention for the well-known objects):
var DBOpenRequest = window.indexedDB.open("messages", 6);
//...
DBOpenRequest.onupgradeneeded = function(event) {
console.log("Need to upgrade.");
var db = event.target.result;
console.log(db);
db.onerror = function(event) {
console.log("Error upgrading.");
};
// Create an objectStore for this database
var objectStore = db.createObjectStore("messages", { keyPath: "id", autoIncrement: true });
};
This ran fine for versions 3 and 4. When it came to version 5, I get the error:
Failed to execute 'createObjectStore' on 'IDBDatabase': An object store with the specified name already exists. at IDBOpenDBRequest.DBOpenRequest.onupgradeneeded
Isn't the createObjectStore
operating on a new version of the database which is empty? How do I fix the error?
I happened to log the db
object and the details are below:
I am curious why the version number is different in the summary line and when expanded.
Upvotes: 9
Views: 6745
Reputation: 143
The best way to upgrade the DB is checking if the store name is already there. In this example I'm using https://npmjs.com/idb
openDB('db-name', version, {
upgrade(db, oldVersion, newVersion, transaction) {
if(!db.objectStoreNames.contains('messages')) {
db.createObjectStore('messages', { keyPath: "id", autoIncrement: true })
}
}
})
If you need to check if an indexName already exist, you can get the objectStore and check for the indexNames property if it contains the indexName you need.
openDB('db-name', version, {
upgrade(db, oldVersion, newVersion, transaction) {
const storeName = transaction.objectStore('storeName')
if(!storeName.indexNames.contains('indexName')) {
storeName.createIndex('indexName', 'propertyName', { unique: false });
}
}
})
Using indexDB API with indexNames and objectStoreNames to check if something is either there or not makes my code way more reliable and easy to maintain, it is also briefly mentioned on Working with IndexDB Using database versioning
Upvotes: 8
Reputation: 8365
Isn't the createObjectStore operating on a new version of the database which is empty?
When you get upgradeneeded
the database is in whatever state you left it in before. Since you don't know what versions of your code a user will have visited, you need to look at the event's oldVersion
to find out what that was. The typical pattern is something like this:
var rq = indexedDB.open('db', 5);
rq.onupgradeneeded = function(e) {
var db = rq.result;
if (e.oldVersion < 1) {
// do initial schema creation
db.createObjectStore('users');
}
if (e.oldVersion < 2) {
// do 1->2 upgrade
var s = db.createObjectStore('better_users');
s.createIndex('some_index', ...);
db.deleteObjectStore('users'); // migrating data would be better
}
if (e.oldVersion < 3) {
// do 2->3 upgrade
rq.transaction.objectStore('better_users').createIndex('index2', ...);
}
if (e.oldVersion < 4) {
// do 3->4 upgrade
db.createObjectStore('messages', ...);
}
if (e.oldVersion < 5) {
// do 4->5 upgrade
// ...
}
}
I am curious why the version number is different in the summary line and when expanded.
That one is subtle... I believe at the point where the 5
was logged the database had started the upgrade. But because an exception was thrown in the upgradeneeded
handler the upgrade was aborted, and the version number was rolled back to 4
before the details were logged.
Upvotes: 27