Reopening an objectstore with version change on Safari Mobile (iOS8.1)/Safari Desktop

150 Views Asked by At

TL;DR I want to open a database, get some information from it, close it and then reopen it with upgrade parameters based off of the information I get from it (version, number of objectstores, etc.)

I am having some troubles with my indexeddb plugin that I wrote closing an object store and then reopening it with a version change.

But first some background on what exactly I'm doing. Due to this issue, I was forced to do a terribly ugly structure for my database. Basically, I found that as you insert more records, it gets slower to insert. Since I have a very large set of data that needs to be saved, it turned out to be much much quicker to save each chunk of data into a separate Objectstore. At first I was creating a new database for each objectstore. This worked out quite well, but as I grew to understand indexedDB more I realized that this was not the best way to do it. I switched my plugin from using multiple databases to one database with multiple objectstores. However, this is where my problems started.

Since I am unable to know how many chunks of data I will need, and one objectstore for each chunk of data, I first get from the server the total count of records that will be inserted and then divide that by the size of each chunk. That way I know how many objectstores I will need. However, since I am going to need to sync this data, those objectstores may already exist or they may not.

Because of this, I get the number of objectstores that already exist, and if that amount is less than the number of the parts I add more.

In order to get that number of object stores, I need to open the database first, then open it again with the updated schema information. However, when I try to do that, it always hits my abort function in my onupgradeneeded. However, if I just run that create function from page load rather than opening the db first, it seems to update the database schema just fine (That doesn't really help me though, as I need to know how many tables I have and the current db version before I can update anything.

This works fine in chrome, firefox and chrome on android, but not on iOS or Safari. Looks like some sort of WebKit issue but I've been digging through their bugtracker and haven't found anything that looks quite like this.

I think that it is not properly closing the previous database connection so it cannot open a new one but I could be wrong here. Has anyone run into this before, or have any thoughts on how I can work around it?

If it helps, this is some of my code:

$.ajax({
        type: 'POST',
        url: "website/myURL.json",
        success: function(data){
            partCount = data;
            console.log("Got " + partCount + " parts.");

            $().database.get(timeTable,{"success":function(obj){
                tables = obj;
                if(tables.length < partCount){//Build new tables
                    var newTables = [];
                    var version = ($().database.version() + 1);

                    for(var i=tables.length; i<partCount; i++){
                        newTables.push({name:"table_"+i});
                    }
                    $().database.close();
                    $().database.open("database", 
                        {   version: version,
                            tables: newTables,
                            success: function(){
                                callbackFunction();
                            }
                        }
                    );
                }
                else{
                    callbackFunction();
                }
            }});

Open Function from plugin:

    function open(options){
        var opts = $.extend({
            version: settings.version,
            name: settings.name,
            keyPath: settings.keyPath
        },options);

        _dbExists = true;
        _logging = opts.logging;

        database.indexedDB = {};
        database.indexedDB.db = null;

        var request;
        if(opts.version === null || opts.version === ""){
            request = indexedDB.open(opts.name);
        }
        else{
            request = indexedDB.open(opts.name, opts.version);
        }

        request.onupgradeneeded = function(e) {
            var db = request.result;
            db.onabort = function (es) {
                console.log("DB action aborted.");
                opts.abort(es);
            };

            if(opts.tables){
                for(var j=0; j<opts.tables.length; j++){
                    table = opts.tables[j];

                    if(db.objectStoreNames.contains(table.name)){
                        db.deleteObjectStore(table.name);
                    }
                    //Create object store for each table.
                    var key = (table.hasOwnProperty("keyPath") && table.keyPath != null) ? table.keyPath : opts.keyPath; 
                    var objectStore = db.createObjectStore(table.name, {keyPath: key});
                    if(table.indices){
                        for(var i=0; i<table.indices.length; i++){
                            //Add indecies to table.
                            objectStore.createIndex(table.indices[i].name, table.indices[i].keyPath, table.indices[i].param);
                        }
                    }
                }
            }
            if(_logging) console.log("Upgrading database.");
        };

        request.onsuccess = function(e){
            database.indexedDB.db = request.result;
            _version = parseInt(request.result.version);
            console.log("DB opened");
            if(opts.success != null){
                opts.success(e);
            }
        };

        request.onerror = function(e) {
            console.log(e);
            if(opts.error != null){
                opts.error(e);
            }
        };
    }
0

There are 0 best solutions below