Path: blob/trunk/third_party/closure/goog/db/index.js
2868 views
// Copyright 2011 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Wrapper for an IndexedDB index.16*17*/181920goog.provide('goog.db.Index');2122goog.require('goog.async.Deferred');23goog.require('goog.db.Cursor');24goog.require('goog.db.Error');25goog.require('goog.db.KeyRange');26goog.require('goog.debug');27282930/**31* Creates an IDBIndex wrapper object. Indexes are associated with object32* stores and provide methods for looking up objects based on their non-key33* properties. Should not be created directly, access through the object store34* it belongs to.35* @see goog.db.ObjectStore#getIndex36*37* @param {!IDBIndex} index Underlying IDBIndex object.38* @constructor39* @final40*/41goog.db.Index = function(index) {42/**43* Underlying IndexedDB index object.44*45* @type {!IDBIndex}46* @private47*/48this.index_ = index;49};505152/**53* @return {string} Name of the index.54*/55goog.db.Index.prototype.getName = function() {56return this.index_.name;57};585960/**61* @return {*} Key path of the index.62*/63goog.db.Index.prototype.getKeyPath = function() {64return this.index_.keyPath;65};666768/**69* @return {boolean} True if the index enforces that there is only one object70* for each unique value it indexes on.71*/72goog.db.Index.prototype.isUnique = function() {73return this.index_.unique;74};757677/**78* Helper function for get and getKey.79*80* @param {string} fn Function name to call on the index to get the request.81* @param {string} msg Message to give to the error.82* @param {IDBKeyType} key The key to look up in the index.83* @return {!goog.async.Deferred} The resulting deferred object.84* @private85*/86goog.db.Index.prototype.get_ = function(fn, msg, key) {87var d = new goog.async.Deferred();88var request;89try {90request = this.index_[fn](key);91} catch (err) {92msg += ' with key ' + goog.debug.deepExpose(key);93d.errback(goog.db.Error.fromException(err, msg));94return d;95}96request.onsuccess = function(ev) { d.callback(ev.target.result); };97request.onerror = function(ev) {98msg += ' with key ' + goog.debug.deepExpose(key);99d.errback(goog.db.Error.fromRequest(ev.target, msg));100};101return d;102};103104105/**106* Fetches a single object from the object store. Even if there are multiple107* objects that match the given key, this method will get only one of them.108*109* @param {IDBKeyType} key Key to look up in the index.110* @return {!goog.async.Deferred} The deferred object for the given record.111*/112goog.db.Index.prototype.get = function(key) {113return this.get_('get', 'getting from index ' + this.getName(), key);114};115116117/**118* Looks up a single object from the object store and gives back the key that119* it's listed under in the object store. Even if there are multiple records120* that match the given key, this method returns the first.121*122* @param {IDBKeyType} key Key to look up in the index.123* @return {!goog.async.Deferred} The deferred key for the record that matches124* the key.125*/126goog.db.Index.prototype.getKey = function(key) {127return this.get_('getKey', 'getting key from index ' + this.getName(), key);128};129130131/**132* Helper function for getAll and getAllKeys.133*134* @param {string} fn Function name to call on the index to get the request.135* @param {string} msg Message to give to the error.136* @param {IDBKeyType=} opt_key Key to look up in the index.137* @return {!goog.async.Deferred} The resulting deferred array of objects.138* @private139*/140goog.db.Index.prototype.getAll_ = function(fn, msg, opt_key) {141// This is the most common use of IDBKeyRange. If more specific uses of142// cursors are needed then a full wrapper should be created.143var IDBKeyRange = goog.global.IDBKeyRange || goog.global.webkitIDBKeyRange;144var d = new goog.async.Deferred();145var request;146try {147if (opt_key) {148request = this.index_[fn](IDBKeyRange.only(opt_key));149} else {150request = this.index_[fn]();151}152} catch (err) {153if (opt_key) {154msg += ' for key ' + goog.debug.deepExpose(opt_key);155}156d.errback(goog.db.Error.fromException(err, msg));157return d;158}159var result = [];160request.onsuccess = function(ev) {161var cursor = ev.target.result;162if (cursor) {163result.push(cursor.value);164cursor['continue']();165} else {166d.callback(result);167}168};169request.onerror = function(ev) {170if (opt_key) {171msg += ' for key ' + goog.debug.deepExpose(opt_key);172}173d.errback(goog.db.Error.fromRequest(ev.target, msg));174};175return d;176};177178179/**180* Gets all indexed objects. If the key is provided, gets all indexed objects181* that match the key instead.182*183* @param {IDBKeyType=} opt_key Key to look up in the index.184* @return {!goog.async.Deferred} A deferred array of objects that match the185* key.186*/187goog.db.Index.prototype.getAll = function(opt_key) {188return this.getAll_(189'openCursor', 'getting all from index ' + this.getName(), opt_key);190};191192193/**194* Gets the keys to look up all the indexed objects. If the key is provided,195* gets all records for objects that match the key instead.196*197* @param {IDBKeyType=} opt_key Key to look up in the index.198* @return {!goog.async.Deferred} A deferred array of keys for objects that199* match the key.200*/201goog.db.Index.prototype.getAllKeys = function(opt_key) {202return this.getAll_(203'openKeyCursor', 'getting all keys from index ' + this.getName(),204opt_key);205};206207208/**209* Opens a cursor over the specified key range. Returns a cursor object which is210* able to iterate over the given range.211*212* Example usage:213*214* <code>215* var cursor = index.openCursor(goog.db.KeyRange.bound('a', 'c'));216*217* var key = goog.events.listen(218* cursor, goog.db.Cursor.EventType.NEW_DATA,219* function() {220* // Do something with data.221* cursor.next();222* });223*224* goog.events.listenOnce(225* cursor, goog.db.Cursor.EventType.COMPLETE,226* function() {227* // Clean up listener, and perform a finishing operation on the data.228* goog.events.unlistenByKey(key);229* });230* </code>231*232* @param {!goog.db.KeyRange=} opt_range The key range. If undefined iterates233* over the whole object store.234* @param {!goog.db.Cursor.Direction=} opt_direction The direction. If undefined235* moves in a forward direction with duplicates.236* @return {!goog.db.Cursor} The cursor.237* @throws {goog.db.Error} If there was a problem opening the cursor.238*/239goog.db.Index.prototype.openCursor = function(opt_range, opt_direction) {240return goog.db.Cursor.openCursor(this.index_, opt_range, opt_direction);241};242243244