aaronpowell / db.js

db.js is a wrapper for IndexedDB to make it easier to work against
http://aaronpowell.github.com/db.js/
MIT License
818 stars 142 forks source link

Index creation behavior (defaulting and keyPath) #149

Closed brettz9 closed 8 years ago

brettz9 commented 8 years ago

The use of defaulting to unique: false in the following code is puzzling to me:

var indexKey;
for (indexKey in table.indexes) {
    var index = table.indexes[indexKey];
    try {
        store.index(indexKey);
    } catch (err) {
        store.createIndex(indexKey, index.key || indexKey, Object.keys(index).length ? index : { unique: false });
    }
}

Is there any advantage to explicitly declaring unique: false here rather than just always using index (including if empty)? It appears from the spec that the default is false anyways...

Also, would it not be clearer to check for index.keyPath || indexKey instead of index.key || indexKey?

aaronpowell commented 8 years ago

Is there any advantage to explicitly declaring unique: false here rather than just always using index (including if empty)? It appears from the spec that the default is false anyways...

Yes, the default is false but unless it was to explicitly set undefined for the last argument index is always going to represent something and that something might not be valid.

Also, would it not be clearer to check for index.keyPath || indexKey instead of index.key || indexKey ?

Then the property it looks for would have to be called keyPath not key on the schema object (which then could be a breaking change).

brettz9 commented 8 years ago

Your existing Object.keys(index).length check:

store.createIndex(indexKey, index.key || indexKey, Object.keys(index).length ? index : { unique: false });

...will either:

  1. throw an error because index is not an object
  2. produce the same effect as {unique: false} if an empty object is supplied
  3. cause index to return itself due to index being an object with properties

I therefore see no difference with:

store.createIndex(indexKey, index.key || indexKey, index);

...except that your approach is longer and will throw (whether upon an explicitly empty index or where createIndex might throw with a bad index type supplied anyways).

If you think that is important to throw rather than supply a bad index, then why not just use the following check?

store.createIndex(indexKey, index.key || indexKey, index && typeof index === 'object' ? index : {unique: false});

(If you didn't mind null or undefined, you could also drop the index && portion.)

That would seem clearer as to your intent. Not a big deal, just trying to confirm it was not an oversight.

As far as keyPath, why not deprecate key in favor of keyPath?

aaronpowell commented 8 years ago

except that your approach is longer and will throw (whether upon an explicitly empty index or where createIndex might throw with a bad index type supplied anyways).

Could you create a test case that demonstrates how you'd hit this problem?

brettz9 commented 8 years ago

I'm not expecting that one would normally hit this problem without crafting a bad schema, but I'm just saying that if your purpose is to avoid, as you say, the "something" which "might not be valid", then your current approach isn't helping that much.

If a bad value is supplied as index to this portion:

Object.keys(index).length ? index : { unique: false }

...the following will occur with the Object.keys check:

Under your current code, an empty object will default to {unique:false} which is the expected default, though FWIW, {} would work just as well here.

Under your current code, a non-empty object will be passed on unaltered as expected (including, however, cases where bad or custom properties such as key are included on the object--which admittedly may not be an issue).

If your purpose is to circumvent all possible bad index values described in the list above, then the following code will do this more succinctly and will accurately avoid all of the bad value types above (and without throwing):

index && typeof index === 'object' ? index : {}
brettz9 commented 8 years ago

This was handled in one of the PRs, so closing. Thanks for all the merges!