Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid key path in IndexedDB: restrictions?

I'm trying to create a really simple IndexedDB with some JavaScript, but it fails in the on handler already. Apparently the browser (Chrome 57) is not able to parse the keyPath (in Basic Concepts) of my storage.

I'm following more or less these simple examples: MDN or Opera-Dev.

Suppose I want to store objects like this one in the DB:

{
    "1": 23, // the unique id
    "2": 'Name',
    "3": 'Description',
    "4": null,
    "5": null
}

Here is the code:

var sStoreNodes = 'nodes';
var sIdFieldNode = '1'; // the important part

// event is fired for creating the DB and upgrading the version
request.onupgradeneeded = function(event)
{
    var db = event.target.result;

    // Create an objectStore for nodes. Unique key should be the id of the node, on property 1. 
    // So ID will be the key!
    var objectStore =  db.createObjectStore(
        sStoreNodes,
        {
            // changing to a plain string works, if it is a valid identifier and not just a strigified number
            'keyPath'       : [ sIdFieldNode ],
            'autoIncrement' : false // really important here
        });
};

The error message reads like:

Uncaught DOMException: Failed to execute 'createObjectStore' on 'IDBDatabase': The keyPath option is not a valid key path. at IDBOpenDBRequest.CCapIndexedDB.request.onupgradeneeded

I can also try to leave out the key path, but I'm wondering why this happens and want can I do about it, if I really need to use a (complex) key path.

Regarding the spec:

I'm not sure, whether this can be applied here:

A value is said to be a valid key if it is one of the following ECMAScript [ECMA-262] types: Number primitive value, String primitive value, Date object, or Array object.

and what this actually means:

If the key path is a DOMString, the value [for getting the key path] will be a DOMString equal to the key path. If the key path is a sequence, the value will be a new Array, populated by appending Strings equal to each DOMString in the sequence.


Edit This works, if you don't use a stringified number, but a string instead, which is a valid identifier (beginning with a character [a-zA-Z]). So 'keyPath' : 'b' is OK. I guess this is because this value is used for creating paths like a.b.c.

like image 852
BairDev Avatar asked Apr 07 '17 09:04

BairDev


1 Answers

Here is the definition of a key path, from the spec:

A key path is a DOMString or sequence that defines how to extract a key from a value. A valid key path is one of:

  • An empty DOMString.
  • An identifier, which is a DOMString matching the IdentifierName production from the ECMAScript Language Specification [ECMA-262].
  • A DOMString consisting of two or more identifiers separated by periods (ASCII character code 46).
  • A non-empty sequence containing only DOMStrings conforming to the above requirements.

For a string containing an integer, clearly the first, third, and fourth options do not apply. For the second, we have to see what an IdentifierName is, which is a little complicated, but basically it has to start with a letter, underscore, or dollar sign. This means that a string containing just an integer is not a valid key path.

If you really do have an object where the primary key is in a field whose name is a string containing an integer, you can either rename the field or not use key paths (in which case you have to manually specify the key as the second argument to IDBObjectStore.add and IDBObjectStore.put).

You linked to the definition for a key, which defines the valid values that a key can have (like for an object {a: 1} where the key path is 'a' the key is 1, which is valid).

The other thing you linked to is about key paths like a.b.c referencing {a: {b: {c: 1}}}.

like image 125
dumbmatter Avatar answered Nov 16 '22 23:11

dumbmatter