[indexeddb] Compound Key support for Primary Keys and Indexes

We looked at the spec to see what it would take to be able to support multi-column keys on primary keys & indexes and we found some inconsistencies that need to be addressed.  Below is our proposal/assumptions on how to constrain the problem and what needs to be updated in the spec to support this:

. Cursors are automatically sorted in ascending order but they can be retrieved in descending order depending on the value passed to the IDBObjectStore.createIndex.  In other words, all of the attributes that make up the index or the primary key will share the same direction.  The default direction will match the single index case.

. KeyRanges will act on the first element of the compound key (i.e. the first column).

. IDBObjectStore.get and IDBIndex.get will be able to take in an array value.  Each value in the array will be mapped against the compound key defined in the IDBObjectStore and the record will be queried using all of the compound key values specified in the array.  If using an IDBKeyRange, the range will only be able to act on the first element of the compound key.  Because the current type of the get method parameter is an any, this will automatically support both single and array values.  For example,

---When retrieving the record of a single key index they do this: 
     var request = index.get("Israel Hilerio"); 
     request.onsuccess = function (evt) { var record = this.result; }

---When retrieving the record of a compound key index they will query like this: 
     var request = index.get(["PM","IE"]);
     request.onsuccess = function (evt) { var record = this.result; };

. IDBIndex.getKey will be able to take in an array value.  Each value in the array will be mapped against the compound key defined in the IDBObjectStore and the record will be queried using all of the compound key values specified in the array.  The result will be an array of values that can be accessed using the property order of the compound key.  Because the current type of the get method parameter is an any and the type of the IDBRequest.result is an any, this will automatically support both single and array values.  For example,

---When retrieving the primaryKey of a single key record they do this: 
     var request = index.getKey("Israel Hilerio"); 
     request.onsuccess = function (evt) { var primaryKey = this.result; }

---When retrieving the primaryKey of a compound key record they will query like this: 
     var request = index.getKey(["PM","IE"]);
     request.onsuccess = function (evt) { var firstKey = this.result[0]; var secondKey = this.result[1] };

---This will also support an indexed property that doesn't contain any arrays but the primary key of the record is an array.  Notice that passing a string into getKey will return an array as the result.
     var request = index.getKey("Israel Hilerio");
     request.onsuccess = function (evt) { var firstKey = this.result[0]; var secondKey = this.result[1] };

. IDBCursor.key and IDBCursor.primaryKey won't have to change signature since they are already any attributes.  The current definition should allow them to return an array if the key or primaryKey is a compound key.  For example,

---When retrieving the value of a single key they do this: 
     var myKey = cursor.key; 

---When retrieving the value of a compound key they will do this: 
     var myFirstKey = cursor.key[0]; 
     var mySecondKey = cursor.key[1];

. The autoInc property will only apply to the first element on the compound key.  This will be consistent with our proposed KeyRange suggestion.

. We should change the signature of IDBObjectStore.keyPath to be DOMStringList instead of DOMString.  This will make it more intuitive that it supports arrays.

Let me know what you think.

Israel

Received on Saturday, 27 August 2011 00:01:40 UTC