123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- // Copyright 2011 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview Wrapper for an IndexedDB index.
- *
- */
- goog.provide('goog.db.Index');
- goog.require('goog.async.Deferred');
- goog.require('goog.db.Cursor');
- goog.require('goog.db.Error');
- goog.require('goog.db.KeyRange');
- goog.require('goog.debug');
- /**
- * Creates an IDBIndex wrapper object. Indexes are associated with object
- * stores and provide methods for looking up objects based on their non-key
- * properties. Should not be created directly, access through the object store
- * it belongs to.
- * @see goog.db.ObjectStore#getIndex
- *
- * @param {!IDBIndex} index Underlying IDBIndex object.
- * @constructor
- * @final
- */
- goog.db.Index = function(index) {
- /**
- * Underlying IndexedDB index object.
- *
- * @type {!IDBIndex}
- * @private
- */
- this.index_ = index;
- };
- /**
- * @return {string} Name of the index.
- */
- goog.db.Index.prototype.getName = function() {
- return this.index_.name;
- };
- /**
- * @return {*} Key path of the index.
- */
- goog.db.Index.prototype.getKeyPath = function() {
- return this.index_.keyPath;
- };
- /**
- * @return {boolean} True if the index enforces that there is only one object
- * for each unique value it indexes on.
- */
- goog.db.Index.prototype.isUnique = function() {
- return this.index_.unique;
- };
- /**
- * Helper function for get and getKey.
- *
- * @param {string} fn Function name to call on the index to get the request.
- * @param {string} msg Message to give to the error.
- * @param {IDBKeyType} key The key to look up in the index.
- * @return {!goog.async.Deferred} The resulting deferred object.
- * @private
- */
- goog.db.Index.prototype.get_ = function(fn, msg, key) {
- var d = new goog.async.Deferred();
- var request;
- try {
- request = this.index_[fn](key);
- } catch (err) {
- msg += ' with key ' + goog.debug.deepExpose(key);
- d.errback(goog.db.Error.fromException(err, msg));
- return d;
- }
- request.onsuccess = function(ev) { d.callback(ev.target.result); };
- request.onerror = function(ev) {
- msg += ' with key ' + goog.debug.deepExpose(key);
- d.errback(goog.db.Error.fromRequest(ev.target, msg));
- };
- return d;
- };
- /**
- * Fetches a single object from the object store. Even if there are multiple
- * objects that match the given key, this method will get only one of them.
- *
- * @param {IDBKeyType} key Key to look up in the index.
- * @return {!goog.async.Deferred} The deferred object for the given record.
- */
- goog.db.Index.prototype.get = function(key) {
- return this.get_('get', 'getting from index ' + this.getName(), key);
- };
- /**
- * Looks up a single object from the object store and gives back the key that
- * it's listed under in the object store. Even if there are multiple records
- * that match the given key, this method returns the first.
- *
- * @param {IDBKeyType} key Key to look up in the index.
- * @return {!goog.async.Deferred} The deferred key for the record that matches
- * the key.
- */
- goog.db.Index.prototype.getKey = function(key) {
- return this.get_('getKey', 'getting key from index ' + this.getName(), key);
- };
- /**
- * Helper function for getAll and getAllKeys.
- *
- * @param {string} fn Function name to call on the index to get the request.
- * @param {string} msg Message to give to the error.
- * @param {IDBKeyType=} opt_key Key to look up in the index.
- * @return {!goog.async.Deferred} The resulting deferred array of objects.
- * @private
- */
- goog.db.Index.prototype.getAll_ = function(fn, msg, opt_key) {
- // This is the most common use of IDBKeyRange. If more specific uses of
- // cursors are needed then a full wrapper should be created.
- var IDBKeyRange = goog.global.IDBKeyRange || goog.global.webkitIDBKeyRange;
- var d = new goog.async.Deferred();
- var request;
- try {
- if (opt_key) {
- request = this.index_[fn](IDBKeyRange.only(opt_key));
- } else {
- request = this.index_[fn]();
- }
- } catch (err) {
- if (opt_key) {
- msg += ' for key ' + goog.debug.deepExpose(opt_key);
- }
- d.errback(goog.db.Error.fromException(err, msg));
- return d;
- }
- var result = [];
- request.onsuccess = function(ev) {
- var cursor = ev.target.result;
- if (cursor) {
- if (fn == 'openKeyCursor') {
- // openKeyCursor returns a cursor with undefined key/value. See
- // https://w3c.github.io/IndexedDB/#dom-idbobjectstore-openkeycursor.
- result.push(cursor.primaryKey);
- } else {
- result.push(cursor.value);
- }
- cursor['continue']();
- } else {
- d.callback(result);
- }
- };
- request.onerror = function(ev) {
- if (opt_key) {
- msg += ' for key ' + goog.debug.deepExpose(opt_key);
- }
- d.errback(goog.db.Error.fromRequest(ev.target, msg));
- };
- return d;
- };
- /**
- * Gets all indexed objects. If the key is provided, gets all indexed objects
- * that match the key instead.
- *
- * @param {IDBKeyType=} opt_key Key to look up in the index.
- * @return {!goog.async.Deferred} A deferred array of objects that match the
- * key.
- */
- goog.db.Index.prototype.getAll = function(opt_key) {
- return this.getAll_(
- 'openCursor', 'getting all from index ' + this.getName(), opt_key);
- };
- /**
- * Gets the keys to look up all the indexed objects. If the key is provided,
- * gets all records for objects that match the key instead.
- *
- * @param {IDBKeyType=} opt_key Key to look up in the index.
- * @return {!goog.async.Deferred} A deferred array of keys for objects that
- * match the key.
- */
- goog.db.Index.prototype.getAllKeys = function(opt_key) {
- return this.getAll_(
- 'openKeyCursor', 'getting all keys from index ' + this.getName(),
- opt_key);
- };
- /**
- * Opens a cursor over the specified key range. Returns a cursor object which is
- * able to iterate over the given range.
- *
- * Example usage:
- *
- * <code>
- * var cursor = index.openCursor(goog.db.KeyRange.bound('a', 'c'));
- *
- * var key = goog.events.listen(
- * cursor, goog.db.Cursor.EventType.NEW_DATA,
- * function() {
- * // Do something with data.
- * cursor.next();
- * });
- *
- * goog.events.listenOnce(
- * cursor, goog.db.Cursor.EventType.COMPLETE,
- * function() {
- * // Clean up listener, and perform a finishing operation on the data.
- * goog.events.unlistenByKey(key);
- * });
- * </code>
- *
- * @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates
- * over the whole object store.
- * @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined
- * moves in a forward direction with duplicates.
- * @return {!goog.db.Cursor} The cursor.
- * @throws {goog.db.Error} If there was a problem opening the cursor.
- */
- goog.db.Index.prototype.openCursor = function(opt_range, opt_direction) {
- return goog.db.Cursor.openCursor(this.index_, opt_range, opt_direction);
- };
|