Skip to content

Add openCursor(key, primaryKey) and continuePrimaryKey #14

Open

Description

@inexorabletash

https://www.w3.org/Bugs/Public/show_bug.cgi?id=20257

partial interface IDBIndex {
  IDBRequest openCursor(optional any query, optional IDBCursorDirection direction, IDBIndexOpenCursorOptions options);
  IDBRequest openKeyCursor(optional any query, optional IDBCursorDirection direction, IDBIndexOpenCursorOptions options);
}

dictionary IDBIndexOpenCursorOptions {
  any key;
  any primaryKey;
}

partial interface IDBCursor {
  void continuePrimaryKey(optional any key, optional any primaryKey);
}

If primaryKey is specified in options but key is not, throw.

  • cursor iteration operation
  • continuePrimaryKey()
  • IDBIndex.openCursor()
  • IDBIndex.openKeyCursor()

Activity

  1. inexorabletash commented on May 28, 2015

    @inexorabletash
    MemberAuthor

    Need to specify what happens if you call continuePrimaryKey() on a cursor where the source is an object store. Throw?

    I'm updating the experimental impl in Blink to throw InvalidAccessError in this case, pending further discussion.

  2. inexorabletash commented on Jun 5, 2015

    @inexorabletash
    MemberAuthor

    What should the behavior of continuePrimaryKey() be with "prevunique" iteration? Given this index:

    • r1 = key: 'a', primary key: 1
    • r2 = key: 'a', primary key: 2
    • r3 = key: 'b', primary key: 1

    If direction is "prevunique" and the cursor is at r3, continue('a') is specified to end up at r1 (the first record with matching key).

    Cases:

    • If direction is "prevunique" and the cursor is at r3, continue('a', 1) should end up at... ?
      • r1 is obvious
    • If direction is "prevunique" and the cursor is at r3, continue('a', 2) should end up at... ?
      • r2 seems to make the most sense here, but r1 would be consistent too.
    • If direction is "prevunique" and the cursor is at r3, continue('a', 3) should end up at... ?
      • to me, r2 seems sensible here, but my intuition may be wonky
  3. inexorabletash commented on Jun 6, 2015

    @inexorabletash
    MemberAuthor
  4. inexorabletash commented on Jun 6, 2015

    @inexorabletash
    MemberAuthor

    Initial work in a4e4d2b

  5. inexorabletash commented on Jun 11, 2015

    @inexorabletash
    MemberAuthor

    Another option is to throw if continuePrimaryKey() is used with "nextunique" or "prevunique" since the behavior is a bit odd.

  6. yathit commented on Jun 16, 2015

    @yathit

    @inexorabletash +1 throw InvalidAccessError

  7. inexorabletash commented on Jun 16, 2015

    @inexorabletash
    MemberAuthor

    @yathit do you mean for the object store source case, or for "nextunique" / "prevunique", or both?

  8. yathit commented on Jun 16, 2015

    @yathit

    @inexorabletash both cases.

  9. inexorabletash commented on Jun 17, 2015

    @inexorabletash
    MemberAuthor

    sgtm!

  10. inexorabletash commented on Jun 19, 2015

    @inexorabletash
    MemberAuthor

    In the openCursor() case, is the lower-bound of the key range implicitly the index key if primaryKey is specified (and thus it's an error if a open lower bound is specified), or should the range and starting position be decoupled and require both the key and primaryKey to be explicit specified e.g. openCursor(null, null, {key: x, primaryKey: y}) ?

  11. yathit commented on Jun 20, 2015

    @yathit

    Agree. IDBIndexOpenCursorOptions should be a complete cursor position.

    dictionary IDBIndexOpenCursorOptions {
      IDBKey key, // nullable, default to lower-bound
      IDBKey primaryKey; // nullable, default to first
    }
    

    Using openCursor becomes easier. Let the keyRange unchanged and open with different starting position, without requiring keyRange to be met with cursor position.

  12. inexorabletash commented on Feb 19, 2016

    @inexorabletash
    MemberAuthor

    Should we throw if primaryKey is specified but key is not? (I vote yes.)

    Should we define any special behavior if options are used on a unique index? (I vote no.)

  13. inexorabletash commented on Feb 19, 2016

    @inexorabletash
    MemberAuthor

    For posterity, here's how you'd write a fallback if these methods didn't exist:

      var options = {key: 2, primaryKey: 2};
    
      var req = idx.openCursor(null, 'next', options);
      req.onsuccess = function() {
        var cursor = req.result;
        if (!cursor) return;
    
        if (indexedDB.cmp(cursor.key, options.key) < 0 ||
          (indexedDB.cmp(cursor.key, options.key) === 0 &&
            indexedDB.cmp(cursor.primaryKey, options.primaryKey) < 0)) {
    
              // if you have continuePrimaryKey but not openCursor(..., options) for some reason
              if (cursor.continuePrimaryKey) {
                cursor.continuePrimaryKey(options.key, options.primaryKey);
                return;
              }
    
              // If index key is too low we can jump directly to that.
              if (indexedDB.cmp(cursor.key, options.key) < 0) {
                cursor.continue();
                return;
              }
    
              // Otherwise we're stuck iterating until we hit the right primary key.
              cursor.continue();
              return;
        }
    
        // The cursor is positioned at appropriate record - use it!
        cursor.continue();
      };
  14. pwnall commented on Mar 9, 2017

    @pwnall

    Should this issue be closed? I'm pretty sure Chrome, Firefox and Safari are shipping this.

  15. inexorabletash commented on Mar 9, 2017

    @inexorabletash
    MemberAuthor

    openCursor() with primaryKey specified is still a proposal - no-one implements that.

    Currently you need to open the cursor against key then maybe call continuePrimaryKey() to advance it to the right primaryKey on the first iteration.

  16. pwnall commented on Mar 9, 2017

    @pwnall

    Thanks for explaining! I missed that first part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions