Copyright © 2010 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This document defines APIs for a database of records holding simple values and hierarchical objects. Each record consists of a key and some value. Moreover, the database maintains indexes over records it stores. An application developer directly uses an API to locate records either by their key or by using an index. A query language can be layered on this API. An indexed database can be implemented using a persistent B-tree data structure.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published by the Web Applications Working Group as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives). All feedback is welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This section is non-normative.
User agents need to store large numbers of objects locally in order to satisfy off-line data requirements of Web applications. [WEBSTORAGE] is useful for storing pairs of keys and their corresponding values. However, it does not provide in-order retrieval of keys, efficient searching over values, or storage of duplicate values for a key.
This specification provides a concrete API to perform advanced key-value data management that is at the heart of most sophisticated query processors. It does so by using transactional databases to store keys and their corresponding values (one or more per key), and providing a means of traversing keys in a deterministic order. This is often implemented through the use of persistent B-tree data structures that are considered efficient for insertion and deletion as well as in-order traversal of very large numbers of data records.
A script can efficiently find records in an object store that come closest to the required value provided the value is stored in either a primary or a secondary key. In the following example, the 'books' object store holds data about books which are stored by their 'isbn' attribute. Additionally, an index is maintained on the 'author' attribute of the objects stored in the object store. This index can be used to look up books for a given author. If an exact match is not found, the next matching author is located.
var db = indexedDB.open('books', 'Book store', false);
if (db.version !== '1.0') {
var olddb = indexedDB.open('books', 'Book store');
olddb.createObjectStore('books', 'isbn');
olddb.createIndex('BookAuthor', 'books', 'author', false);
olddb.setVersion("1.0");
}
// db.version === "1.0";
var index = db.openIndex('BookAuthor');
var matching = index.get('fred');
if (matching)
report(matching.isbn, matching.name, matching.author);
else
report(null);
The next example performs the exact same logic as above asynchronously.
function findFred() {
db.request.onsuccess = function() {
var index = db.request.result;
index.request.onsuccess = function() {
var matching = index.request.result;
if (matching)
report(matching.isbn, matching.name, matching.author);
else
report(null);
}
index.get('fred');
}
db.openIndex('BookAuthor');
}
indexedDB.request.onsuccess = function() {
var db = indexedDB.request.result;
if (db.version !== '1.0') {
indexedDB.request.onsuccess = function() {
var olddb = indexedDB.request.result;
olddb.request.onsuccess = function() {
olddb.request.onsuccess = function() {
olddb.request.onsuccess = function() {
findFred(db);
}
olddb.setVersion("1.0");
}
olddb.createIndex('BookAuthor', 'books', 'author', false);
}
olddb.createObjectStore('books', 'isbn');
}
indexedDB.open('books', 'Book store');
}
findFred(db);
};
indexedDB.open('books', 'Book store', false);
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words must, must not, required, should, should not, recommended, may, and optional in this specification are to be interpreted as described in [RFC2119].
This specification defines one class of products:
A user agent must behave as described in this specification in order to be considered conformant.
User agents may implement algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.
A conforming Indexed Database API user agent must also be a conforming implementation of the IDL fragments of this specification, as described in the “Web IDL” specification. [WEBIDL]
This specification relies on several other underlying specifications.
Function
,
origin, same origin, structured clone,
structured clone algorithm, task, task source,
and queue a task are defined by the HTML 5
specification [HTML5].
Worker
is defined by
the WebWorkers specification [WEBWORKERS].An indexed database is made of records holding simple values and hierarchical objects. Each record consists of a key and some value.
In order to efficiently retrieve records stored in an indexed
database, a user agent needs to organize each record by its key.
Conforming user agents must support the use of values
of IDL data types DOMString
and long
as well as the value null
as keys.
For purposes of comparison, a DOMString
key is always
evaluated higher than any long
key. Moreover,
null
always evaluates lower than any
DOMString
or long
key.
undefined
cannot be used as a key.
Values can be any data type supported by the structured clone algorithm
[HTML5]. This includes simple types such as DOMString
and Date
as well as Object
and Array
instances.
A database may choose to derive a key from the contents of
the value being stored. In such a case, only Object
instances may be stored as values. Only the direct enumerable
properties of a stored Object
instance can be
used to derive a key value.
An object store is a persistent storage that holds key-value pairs, also called records. An object store's records are sorted by keys so as to enable fast insertion and look up as well as ordered retrieval. Every object store has a name.
An object store must have a unique key generator, if it uses keys generated from a monotonically increasing sequence. Alternatively, if an application provides keys, they can either be identified as a part of the value being stored, also called in-line keys, or be identified separately, also called out-of-line keys. No two records in an object store may be identified by the same key. An object store must have a key path if it uses in-line keys. The key path must be the name of an enumerated property of all objects being stored in that object store.
Concurrent access to an object store may be isolated in one of three modes. Any number of readers may concurrently access an object store. A writer is not allowed if there is any reader concurrently accesing the object store, unless the reader is detached, i.e., looking at a snapshot view of the data that does not change once created.
The ObjectStore
interface is used to access the metadata
of an object store.
interface ObjectStore {
const unsigned short READ_WRITE = 0;
const unsigned short READ_ONLY = 1;
const unsigned short SNAPSHOT_READ = 2;
readonly attribute unsigned short mode;
readonly attribute DOMString name;
readonly attribute DOMString keyPath;
readonly attribute DOMStringList indexNames;
};
indexNames
of type DOMStringList, readonlykeyPath
of type DOMString, readonlynull
,
the application must provide a key value for each modification operation.
mode
of type unsigned short, readonlyname
of type DOMString, readonlyREAD_ONLY
of type unsigned shortREAD_WRITE
of type unsigned shortSNAPSHOT_READ
of type unsigned shortRecords in an object store can be retrieved by means of the record's key. However, that may not be always adequate to recall records. An index is used to lookup records in an object store other than through a record key.
An index is a specialized persistent store that holds key-value pairs such that each value is the key of objects in the referenced object store. An index may allow duplicate values for a key, unlike an object store, only if its unique flag is not set. Every index has a name.
If an index is auto-populated, then the user agent populates records using the values stored in the referenced object store. An auto-populated index must have a key path, which must be the name of an enumerated property of all objects being stored in the referenced object store. The auto-populated index record corresponding to an object store record must satisfy the following index maintenance conditions:
The Index
interface is used to access the metadata
of an index.
interface Index {
readonly attribute DOMString name;
readonly attribute DOMString storeName;
readonly attribute DOMString keyPath;
readonly attribute boolean unique;
};
keyPath
of type DOMString, readonlynull
,
this index is not auto-populated.
name
of type DOMString, readonlystoreName
of type DOMString, readonlyunique
of type boolean, readonlyEach origin has an associated set of databases. A database comprises:
The object stores and indexes of a database are also referred as its objects.
Each database has a valid name and a human readable description A valid name is any string including the empty string. Names must be compared in a case-sensitive manner.
Each database also has a current version.
The object store name and index name must be valid and unique within the database.
When a database is opened, that creates a connection. There may be multiple connections to a given database at any given time. A connection that is attempting to read a given piece of data in a database is called a reader and one that is attempting to write that piece of data is called a writer. There may be zero or one active transaction in a connection.
A Database
object represents a connection to a
database. There is no way to enumerate the
databases available for an origin from this API.
interface Database {
readonly attribute DOMString name;
readonly attribute DOMString description;
readonly attribute DOMString version;
readonly attribute DOMStringList objectStores;
readonly attribute DOMStringList indexes;
readonly attribute Transaction
currentTransaction;
};
currentTransaction
of type Transaction
, readonlyTransaction
object
corresponding to the transaction that is active in this
database connection.
description
of type DOMString, readonlyindexes
of type DOMStringList, readonlyname
of type DOMString, readonlyobjectStores
of type DOMStringList, readonlyversion
of type DOMString, readonlyAn individual record can be retrieved from an object store using either the record's key or the key applicable for some index that references that object store. Multiple records can be fetched using a key range. A key range is a continuous interval over some data type used for keys.
A key range may be left-bounded or right-bounded if there is a value that is, respectively, smaller than or larger than all its elements. A key range is said to be bounded if it is both left- and right-bounded and unbounded otherwise. A valid key range must be either half-bounded or bounded. A key range may be open, i.e., not including its endpoints or closed, i.e., including its endpoints. A key range may consist of a single value.
The KeyRange
interface is used to define a key range.
interface KeyRange {
const unsigned short SINGLE = 0;
const unsigned short LEFT_OPEN = 1;
const unsigned short RIGHT_OPEN = 2;
const unsigned short LEFT_BOUND = 4;
const unsigned short RIGHT_BOUND = 8;
readonly attribute any left;
readonly attribute any right;
readonly attribute unsigned short flags;
KeyRange
only (in any value);
KeyRange
leftBound (in any bound, in optional boolean open);
KeyRange
rightBound (in any bound, in optional boolean open);
KeyRange
bound (in any left, in any right, in optional boolean openLeft, in optional boolean openRight);
};
flags
of type unsigned short, readonlyleft
of type any, readonlyright
of type any, readonlybound
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
left | any | ✘ | ✘ | The left-bound value |
right | any | ✘ | ✘ | The right-bound value |
openLeft | boolean | ✘ | ✔ | Is the left-bound value included in the key range. |
openRight | boolean | ✘ | ✔ | Is the right-bound value included in the key range. |
KeyRange
leftBound
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
bound | any | ✘ | ✘ | The left bound value |
open | boolean | ✘ | ✔ | Is the left-bound value included in the key range. |
KeyRange
only
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
value | any | ✘ | ✘ | The only value |
KeyRange
rightBound
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
bound | any | ✘ | ✘ | The right bound value |
open | boolean | ✘ | ✔ | Is the right-bound value included in the key range. |
KeyRange
LEFT_BOUND
of type unsigned shortLEFT_OPEN
of type unsigned shortRIGHT_BOUND
of type unsigned shortRIGHT_OPEN
of type unsigned shortSINGLE
of type unsigned shortCursors are a transient mechanism used to iterate over multiple records in a database. The storage operations are performed on the underlying index or an object store.
A cursor comprises a range of records in either an index or an object store. A cursor maintains a position over this series, which moves in a direction that is either monotonically increasing or decreasing order of the record keys.
interface Cursor {
const unsigned short NEXT = 0;
const unsigned short NEXT_NO_DUPLICATE = 1;
const unsigned short PREV = 2;
const unsigned short PREV_NO_DUPLICATE = 3;
readonly attribute unsigned short direction;
};
direction
of type unsigned short, readonlyNEXT
of type unsigned shortNEXT_NO_DUPLICATE
of type unsigned shortPREV
of type unsigned shortPREV_NO_DUPLICATE
of type unsigned shortA transaction has a scope and a database. A transaction's scope is either static or dynamic. If the scope is static, it can cover either all the object stores and indexes in a database or it may include a subset of them.
A connection may have at most one transaction at any given time. Moreover, there may not be any overlap among the scopes of all open connections to a given database.
Transactions offer some protection from application and system failures. A transaction may be used to store multiple data records or to conditionally modify certain data records. A transaction represents an atomic and durable set of data access and mutation operations.
Transactions are expected to be short lived. Conforming user agents may terminate transactions that take too long to complete in order to free up storage resources that are locked by a long running transaction.
interface Transaction {
attribute boolean static;
attribute Database
db;
};
db
of type Database
static
of type booleantrue
, then this transaction is static
and false
otherwise.
The steps for opening a database are as follows. These steps must be run with an origin, a database name and description. All the steps must be run atomically:
The steps for storing a record into an object store are as follows. These steps must be run with four parameters: the object store, a value, an optional key, and an optional no-overwrite flag.
DATA_ERR
.
CONSTRAINT_ERR
.
Store a record in store containing key as its key and object as its value. If any indexes are auto-populated for store, then store a record in that index according to index maintenance conditions.
The steps for storing a record into an index are as follows. These steps must be run with four parameters: the index, a key, a value, and a no-overwrite flag.
CONSTRAINT_ERR
.
CONSTRAINT_ERR
.
CONSTRAINT_ERR
.
Store a record in index containing key as its key and value as its value.
The steps for retrieving a record from an object store are as follows. These steps must be run with two parameters - the record key and the object store.
NOT_FOUND_ERR
.
The steps for retrieving a record from an index are as follows. These steps must be run with two parameters - the record key and the index.
NOT_FOUND_ERR
.
The steps for retrieving a value from an index are as follows. These steps must be run with two parameters - the record key and the index.
NOT_FOUND_ERR
.
The steps for deleting a record from an object store are as follows. These steps must be run with two parameters: the key of the record to be deleted and the object store.
NOT_FOUND_ERR
.
The steps for deleting a record from an index are as follows. These steps must be run with two parameters: the key of the record to be deleted and the index.
NOT_FOUND_ERR
.
When the user agent is to create a transaction it must run the following steps. These steps must be run with two parameters - database and an optional list of names of database objects to be reserved.
NON_TRANSIENT_ERR
.
NON_TRANSIENT_ERR
and jump to the last step.
TIMEOUT_ERR
and jump to the last step.
Transaction
object
that represents that transaction. Let transaction be this object.
Database
object
to transaction.
DatabaseException
exception exception with the code code.
Worker
objects must implement the
EnvironmentSync
interface.
WorkerUtils implements EnvironmentSync
;
interface EnvironmentSync {
readonly attribute IndexedDatabase
indexedDB;
};
indexedDB
of type IndexedDatabase
, readonlyinterface IndexedDatabase {
DatabaseSync
open (in DOMString name, in DOMString description, in optional boolean modifyDatabase) raises (DatabaseException
);
};
open
The synchronous API for databases blocks the calling thread until a
DatabaseSync
object is ready to return.
When this method is invoked, the user agent must run the
following steps:
DatabaseException
exception with the code of that error and abort these steps.
DatabaseSync
object using result
and call it db.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name for the database |
description | DOMString | ✘ | ✘ | The description for the database |
modifyDatabase | boolean | ✘ | ✔ | This defaults to true |
Exception | Description | ||||
---|---|---|---|---|---|
DatabaseException |
|
DatabaseSync
A database connection can be used to manipulate the objects of that database. That is also the only means of obtaining a transaction for that database.
interface DatabaseSync : Database
{
ObjectStoreSync
createObjectStore ([Null=Empty] in DOMString name, [Null=Null] in DOMString keyPath, in optional boolean autoIncrement) raises (DatabaseException
);
ObjectStoreSync
openObjectStore (in DOMString name, in optional unsigned short mode) raises (DatabaseException
);
IndexSync
createIndex ([Null=Empty] in DOMString name, [Null=Empty] in DOMString storeName, in DOMString keyPath, in optional boolean unique) raises (DatabaseException
);
IndexSync
openIndex (in DOMString name) raises (DatabaseException
);
void removeObjectStore (in DOMString storeName) raises (DatabaseException
);
void removeIndex (in DOMString indexName) raises (DatabaseException
);
void setVersion ([Null=Null] in DOMString version);
TransactionSync
transaction (in optional DOMStringList storeNames, in optional unsigned int timeout) raises (DatabaseException
);
};
createIndex
This method creates a and returns a new index with the given name in the connected database.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of a new index |
storeName | DOMString | ✘ | ✘ | The name of an existing object store referenced by the new index |
keyPath | DOMString | ✘ | ✘ | The key path used by the new index |
unique | boolean | ✘ | ✔ | The unique flag for the new index |
Exception | Description | ||||
---|---|---|---|---|---|
DatabaseException |
|
IndexSync
createObjectStore
This method creates a and returns a new object store with the given name in the connected database.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of a new object store |
keyPath | DOMString | ✘ | ✘ | The key path of a new object store. If null path is specified, then the object store created will not have a key path and will use out-of-line keys. |
autoIncrement | boolean | ✘ | ✔ | Whether the object store created should have a key generator. |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
ObjectStoreSync
openIndex
This method opens the index with the given name in the connected database for the mode specified.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of an existing index |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
IndexSync
openObjectStore
This method opens the object store with the given name in the connected database for the mode specified.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of an existing object store |
mode | unsigned short | ✘ | ✔ | The mode used to access the object store |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
ObjectStoreSync
removeIndex
This method is used to destroy an index with the given name.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
indexName | DOMString | ✘ | ✘ | The name of an existing index |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
removeObjectStore
This method is used to destroy an object store with the given name as well as all indexes that are referencing that object store.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
storeName | DOMString | ✘ | ✘ | The name of an existing object store |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
setVersion
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
version | DOMString | ✘ | ✘ | The version to store in the database |
void
transaction
TransactionSync
object.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
storeNames | DOMStringList | ✘ | ✔ | The names of object stores and indexes in the scope of the new transaction |
timeout | unsigned int | ✘ | ✔ | The interval which this operation is allowed to take to reserve all the database objects identified in the new transaction's scope. The default is user agent specific |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
TransactionSync
In the following example, we set up an object store to use the key path id. This object store is also designed to use a key generator.
var db = indexedDB.open('AddressBook', 'Address Book');
if (db.version !== '1') {
var olddb = indexedDB.open('AddressBook', 'Address Book');
olddb.createObjectStore('Contact', 'id', true);
olddb.setVersion('1');
}
Using this database, we can store records in the Contact object store.
var store = db.openObjectStore('Contact');
var lincoln = {name: 'Lincoln', number: '7012'};
var contact = store.put(lincoln);
// contact.id === 1
A stored value can be retrieved using the same key used by the first put operation.
var contact = store.<>get(1);
// contact.name === 'Lincoln'
A second put operation will overwrite the record stored by the first put operation.
var abraham = {id: 1, name: 'Abraham', number: '2107'};
store.put(abraham);
Now when the object store is read with the same key, the result is different compared to the object read earlier.
var contact = store.get(1);
// contact.id === 1 && contact.name === 'Abraham';
Additionally, all the records of an object store matching a certain key range can be retrieved in key order.
var range = new KeyRange
.bound(2, 4);
var cursor = store.openCursor(range);
// each value is a contact and each key is the id for that
// contact whose id is between 2 and 4, both inclusive
cursor.continue();
interface ObjectStoreSync : ObjectStore
{
any put (in any value, in optional any key, in optional boolean noOverwrite) raises (DatabaseException
);
void delete (in any key) raises (DatabaseException
);
any get (in any key) raises (DatabaseException
);
CursorSync
openCursor (in optional KeyRange
range, in optional unsigned short direction) raises (DatabaseException
);
};
delete
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be removed |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
get
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be retrieved |
Exception | Description | ||||
---|---|---|---|---|---|
DatabaseException |
|
any
openCursor
null
, then the
range includes all the records.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
range |
| ✘ | ✔ | The key range to use as the cursor's range |
direction | unsigned short | ✘ | ✔ | The cursor's required direction |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
CursorSync
put
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
value | any | ✘ | ✘ | The value to be stored in the record |
key | any | ✘ | ✔ | The key used to identify the record |
noOverwrite | boolean | ✘ | ✔ | Whether to overwrite an existing record with the same key |
Exception | Description | ||||||
---|---|---|---|---|---|---|---|
DatabaseException |
|
any
An index can be created for retrieving records other than by using record keys. Continuing the earlier example, an auto-populated index could be maintained on the name property of objects in the Contact object store.
var db = indexedDB.open('AddressBook', 'Address Book');
if (db.version === '1') {
var olddb = indexedDB.open('AddressBook', 'Address Book');
olddb.createObjectStore('Contact', 'id', true);
olddb.createIndex('ContactName', 'Contact', 'name', false);
olddb.setVersion('2');
}
For example, the id of an object with the name property value 'Lincoln' can be retrieved using the ContactName index.
Additionally, all the records of an object store matching a certain range index keys can be retrieved in key order. When objects are retrieved from the Contact object store, they are arranged by the value of the id attribute. On the other hand, when objects are retrieved using the ContactName index, they are arranged by the value of the name property.
var range = new KeyRange
.bound('L', 'M');
var cursor = index.openCursor(range);
// each value is a contact and each key is the name for that
// contact whose name's first letter is either L or M
cursor.continue();
If, on the other hand, we only want the names but not the Contact objects for a given range, then we can use a different mechanism for that.
var range = new KeyRange
.bound('L', 'M');
var cursor = index.openObjectCursor(range);
// each value is a contact and each key is the name for that
// contact whose name's first letter is either L or M
cursor.continue();
interface IndexSync {
void openObjectCursor (in optional KeyRange
range, in optional unsigned short direction) raises (DatabaseException
);
void openCursor (in optional KeyRange
range, in optional unsigned short direction) raises (DatabaseException
);
any put (in any value, in optional any key, in optional boolean noOverwrite) raises (DatabaseException
);
any getObject (in any key) raises (DatabaseException
);
any get (in any key) raises (DatabaseException
);
void delete (in any key) raises (DatabaseException
);
};
delete
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be removed |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
get
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be retrieved |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
any
getObject
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be retrieved |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
any
openCursor
null
, then the
range includes all the records.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
range |
| ✘ | ✔ | The key range to use as the cursor's range |
direction | unsigned short | ✘ | ✔ | The cursor's required direction |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
openObjectCursor
null
, then the
range includes all the records.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
range |
| ✘ | ✔ | The key range to use as the cursor's range |
direction | unsigned short | ✘ | ✔ | The cursor's required direction |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
put
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
value | any | ✘ | ✘ | The value to be stored in the record |
key | any | ✘ | ✔ | The key used to identify the record |
noOverwrite | boolean | ✘ | ✔ | Whether to overwrite an existing record with the same key. This defaults
to false . |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
any
Using the synchronous API, an application can process all the records in the cursor's range. No two values provided by the user agent to callbacks processing data in this cursor can be identical.
By default, a cursor walks over objects starting at the first record and ending at the last record including all the duplicates encountered along the way. If the cursor callback returns true, then the iteration is stopped.
var objects = ...
var cursor = objects.openCursor();
// act on each object and continue the cursor to its end
cursor.continue();
To start at the last record and end in the first record, the cursor
should be created with the direction parameter PREV
.
To start at a certain key and end in the last record, i.e., for a lower-bounded cursor, while skipping duplicates, the cursor should be created with both the required start key and the direction parameter.
var objects = ...
var range = KeyRange
.leftBound(key);
objects.openCursor(range, Cursor
.NEXT_NO_DUPLICATE);
// act on each object and continue the cursor to its end
cursor.continue();
It is also possible to create a bounded cursor, i.e., with
application-specified starting and ending points, the
cursor should be created with both the required keys.
If the range is inclusive of both keys, then additional
flags are required. In the following example, all keys
with values in the inclusive range (start
,
end
) are returned with all their duplicates,
from the beginning of the range to its end.
var objects = ...
var range = KeyRange
.bound(start, end);
objects.openCursor(range);
// act on each object and continue the cursor to its end
cursor.continue();
interface CursorSync {
readonly attribute any key;
attribute any value setraises (DatabaseException
);
readonly attribute unsigned long long count;
bool continue (in optional any key);
void delete () raises (DatabaseException
);
};
count
of type unsigned long long, readonlykey
of type any, readonlyvalue
of type anyException | On Get | On Set | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
DatabaseException | ✘ | ✔ |
|
continue
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✔ | The next key to position this cursor at |
bool
delete
Delete the object at the cursor's position.
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
When an application creates a transaction synchronously, it blocks until the user agent is able to reserve the required database objects.
interface TransactionSync : Transaction
{
void abort () raises (DatabaseException
);
void commit () raises (DatabaseException
);
};
abort
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
commit
Exception | Description | ||||
---|---|---|---|---|---|
DatabaseException |
|
void
Once a transaction is aborted or committed, the active transaction on this database connection is removed. A new transaction can be created to perform operations atomically.
DatabaseException
Interfaceexception DatabaseException {
const unsigned short UNKNOWN_ERR = 0;
const unsigned short NON_TRANSIENT_ERR = 1;
const unsigned short NOT_FOUND_ERR = 2;
const unsigned short CONSTRAINT_ERR = 3;
const unsigned short DATA_ERR = 4;
const unsigned short NOT_ALLOWED_ERR = 5;
const unsigned short SERIAL_ERR = 11;
const unsigned short RECOVERABLE_ERR = 21;
const unsigned shrot TRANSIENT_ERR = 31;
const unsigned short TIMEOUT_ERR = 32;
const unsigned short DEADLOCK_ERR = 33;
attribute unsigned short code;
attribute DOMString message;
};
code
of type unsigned shortmessage
of type DOMStringCONSTRAINT_ERR
of type unsigned shortDATA_ERR
of type unsigned shortDEADLOCK_ERR
of type unsigned shortNON_TRANSIENT_ERR
of type unsigned shortNOT_ALLOWED_ERR
of type unsigned shortNOT_FOUND_ERR
of type unsigned shortRECOVERABLE_ERR
of type unsigned shortSERIAL_ERR
of type unsigned shortTIMEOUT_ERR
of type unsigned shortTRANSIENT_ERR
of type unsigned shrotUNKNOWN_ERR
of type unsigned short
The asynchronous API returns without blocking the calling thread.
This API can only be used in a Window
.
Asynchronous APIs are essentially the same as the synchronous ones
except that the result of an operation is not available when the
operation returns.
This section is non-normative.
Events are fired during asynchronous access as database objects are created and data is consumed from these objects. As requests are made to database objects, the user agent loads information about them into memory and when the required object handle is available, it alerts the application through the firing of events. The events are as follows:
Event name | Dispatched when... |
---|---|
success |
The database request has been completed and its results are available. |
error |
There was an error performing the database request. |
DBRequest
Interface
The DBRequest
interface provides means to access results of
asynchronous requests to databases and database
objects using event handler attributes [DOM-LEVEL-3-EVENTS].
In the following example, we open a database asynchronously. Various event handlers are registered for responding to various situations.
interface DBRequest {
void abort ();
const unsigned short INITIAL = 0;
const unsigned short LOADING = 1;
const unsigned short DONE = 2;
readonly attribute unsigned short readyState;
readonly attribute DatabaseError
error;
readonly attribute any result;
attribute Function onsuccess;
attribute Function onerror;
};
error
of type DatabaseError
, readonlyonerror
of type Functiononsuccess
of type FunctionreadyState
of type unsigned short, readonlyresult
of type any, readonlyabort
readyState
to INITIAL
. No
result
or
error
is set.void
DONE
of type unsigned shortresult
attribute.INITIAL
of type unsigned shortLOADING
of type unsigned shortDBRequest
implements EventTarget;
All instances of the
type are defined to also implement the EventTarget interface.DBRequest
When a request is made, the
readyState
changes to
LOADING
.
Once the result of the request is available, the
readyState
changes to DONE
,
place the result of the request in
result
,
and aueue a task to fire an event with the name success
,
with no namespace, which does not bubble, is not cancelable, and which uses
the Event
interface at each
Window
object.
If an exception occurs while performing the operation, the
readyState
changes to DONE
,
the error information is placed in a new DatabaseError
object at the
error
attribute, and queue a task to fire an event with the name
error
, with no namespace, which does not bubble, is
not cancelable, and which uses the Event
interface at each Window
object.
The task source for these tasks is the database access task source.
Window
objects must implement the
Environment
interface.
Window implements Environment
;
interface Environment {
readonly attribute IndexedDatabaseRequest
indexedDB;
};
indexedDB
of type IndexedDatabaseRequest
, readonly
Every interface for making asynchronous requests includes a
DBRequest
object that communicates back to the requesting
application through events.
This design means that only a single request can be active on any database
or object handle at a time. If a second request is
started, the user agent must abort any previous active request.
interface IndexedDatabaseRequest {
readonly attribute DBRequest
request;
void open (in DOMString name, in DOMString description, in optional boolean modifyDatabase) raises (DatabaseException
);
};
request
of type DBRequest
, readonlyopen
This method returns immediately and runs the
following steps in a different thread.
If an error occurs while the database connection
is being opened, then this object's request
error
is populated
with a new DatabaseError
object whose code is set
to UNKNOWN_ERR
.
error
with that code
and abort these steps.
DatabaseRequest
object for result
and call it db.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name for the database |
description | DOMString | ✘ | ✘ | The description for the database |
modifyDatabase | boolean | ✘ | ✔ | This defaults to true |
Exception | Description | ||
---|---|---|---|
DatabaseException |
|
void
interface DatabaseRequest : Database
{
readonly attribute DBRequest
request;
void createObjectStore ([Null=Empty] in DOMString name, [Null=Null] in DOMString keyPath, in optional boolean autoIncrement);
void openObjectStore (in DOMString name, in optional unsigned short mode);
void createIndex ([Null=Empty] in DOMString name, [Null=Empty] in DOMString storeName, in DOMString keyPath, in optional boolean unique);
void openIndex (in DOMString name);
void removeObjectStore (in DOMString storeName);
void removeIndex (in DOMString indexName);
void setVersion ([Null=Null] in DOMString version);
void transaction (in optional DOMStringList storeNames, in optional unsigned int timeout);
};
request
of type DBRequest
, readonlycreateIndex
This method returns immediately and creates a new index
with the given name and parameters in the
connected database. If an index
with the same name, compared in a case-sensitive manner, already exists
in the connected database, then this
object's request error
is populated with a new
DatabaseError
object whose code is set to
CONSTRAINT_ERR
. If the object store with the
given name does not exist in the connected
database then this object's request error
is populated with a new
DatabaseError
object whose code is set to
NOT_FOUND_ERR
. If the index is created, the
result
of this object's
request is set to a new
IndexRequest
for that index.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of a new index |
storeName | DOMString | ✘ | ✘ | The name of an existing object store referenced by the new index |
keyPath | DOMString | ✘ | ✘ | The key path used by the new index |
unique | boolean | ✘ | ✔ | The unique flag for the new index |
void
createObjectStore
This method returns immediately and creates a new object store
with the given name in the connected
database. If an object store with the same name, compared
in a case-sensitive manner, already exists in the
connected database, then this object's
request error
is populated with a new DatabaseError
object whose code is set to CONSTRAINT_ERR
. If the
object store is created, the
result
of this
object's request is set to a new ObjectStoreRequest
for that object store.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of a new object store |
keyPath | DOMString | ✘ | ✘ | The key path of a new object store. If null path is specified, then the object store created will not have a key path and will use out-of-line keys. |
autoIncrement | boolean | ✘ | ✔ | Whether the object store created should have a key generator. |
void
openIndex
This method returns immediately and opens the index with the
given name in the connected database.
If an index with the given
name does not exist in the connected database,
then this object's request error
is populated with a new
DatabaseError
object whose code is set to
NOT_FOUND_ERR
. If the index is opened,
the result
of this object's request is set to a new
IndexRequest
for that index.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of an existing index |
void
openObjectStore
This method returns immediately and opens the object store with
the given name in the connected database
for the mode specified. If an object store with the given
name does not exist in the connected database,
then this object's request error
is populated with a new
DatabaseError
object whose code is set to
NOT_FOUND_ERR
. If the object store is opened,
the result
of this
object's request is set to a new
ObjectStoreRequest
for that object store.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
name | DOMString | ✘ | ✘ | The name of an existing object store |
mode | unsigned short | ✘ | ✔ | The mode used to access the object store |
void
removeIndex
This method returns immediately and destroys the index
with the given name in the connected
database. If an index with the given name does not
exist in the connected database,
then this object's request error
is populated with a new
DatabaseError
object whose code is set to
NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
indexName | DOMString | ✘ | ✘ | The name of an existing index |
void
removeObjectStore
This method returns immediately and destroys the object store
with the given name in the connected
database as well as all indexes that are
referencing that object store. If an
object store with the given name does not exist in the
connected database,
then this object's request error
is populated with a new
DatabaseError
object whose code is set to
NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
storeName | DOMString | ✘ | ✘ | The name of an existing object store |
void
setVersion
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
version | DOMString | ✘ | ✘ | The version to store in the database |
void
transaction
result
of this object's request is set to a new
TransactionRequest
object. If reserving all the
database objects identified in the requested scope
takes longer than the specified timeout interval, then the
error
of
this object's request is set to the code
TIMEOUT_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
storeNames | DOMStringList | ✘ | ✔ | The names of object stores and indexes in the scope of the new transaction |
timeout | unsigned int | ✘ | ✔ | The interval which this operation is allowed to take to reserve all the database objects identified in the new transaction's scope. The default is user agent specific |
void
interface ObjectStoreRequest : ObjectStore
{
readonly attribute DBRequest
request;
void put (in any value, in optional any key, in optional boolean noOverwrite);
void delete (in any key);
void get (in any key);
void openCursor (in optional KeyRange
range, in optional unsigned short direction);
};
request
of type DBRequest
, readonlydelete
error
for this object's
request is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be removed |
void
get
result
of this object's request
is set to the retrieved value. If a record did not exist in this
object store for the key key parameter, then the
error
for this object's request is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be retrieved |
void
openCursor
null
, then the range includes all the records.
If there is even a single record that matches the key range, then
the result
of this object's request is set to the
CursorRequest
object for that cursor. If no
records match the key range, then the
error
of this object's request
is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
range |
| ✘ | ✔ | The key range to use as the cursor's range |
direction | unsigned short | ✘ | ✔ | The cursor's required direction |
void
put
result
of this object's request is set to the key for the stored record.
If the noOverwrite parameter was true and a record exists
in this object store for the key key parameter, then
the error
for this object's request is set to code
CONSTRAINT_ERR
. If this object store uses
out-of-line keys but does not use a key generator and the
key parameter was not passed, then the
error
for this object's
request is set to code DATA_ERR
. If the data being
stored could not be serialized by the internal structured cloning algorithm,
then the error
for this object's request is set to code
SERIAL_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
value | any | ✘ | ✘ | The value to be stored in the record |
key | any | ✘ | ✔ | The key used to identify the record |
noOverwrite | boolean | ✘ | ✔ | Whether to overwrite an existing record with the same key |
void
interface IndexRequest : Index
{
readonly attribute DBRequest
request;
void openObjectCursor (in optional KeyRange
range, in optional unsigned short direction);
void openCursor (in optional KeyRange
range, in optional unsigned short direction);
void put (in any value, in optional any key, in optional boolean noOverwrite);
void getObject (in any key);
void get (in any key);
void delete (in any key);
};
request
of type DBRequest
, readonlydelete
error
for this object's request is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be removed |
void
get
result
of this object's request
is set to the retrieved value. If a record did not exist in this
index for the key key parameter, then the
error
for this object's request is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be retrieved |
void
getObject
result
of this object's request
is set to the retrieved value. If a record did not exist in this
index for the key key parameter, then the
error
for this object's request is set to code NOT_FOUND_ERR
.
- Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✘ | Key identifying the record to be retrieved |
void
openCursor
null
, then the
range includes all the records.
If there is even a single record that matches the key range, then
the result
of this
object's request is set to the
CursorRequest
object for that cursor. If no
records match the key range, then the
error
of this object's request
is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
range |
| ✘ | ✔ | The key range to use as the cursor's range |
direction | unsigned short | ✘ | ✔ | The cursor's required direction |
void
openObjectCursor
null
, then the
range includes all the records.
If there is even a single record that matches the key range, then
the result
of this object's request is set to the
CursorRequest
object for that cursor. If no
records match the key range, then the
error
of this object's request
is set to code NOT_FOUND_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
range |
| ✘ | ✔ | The key range to use as the cursor's range |
direction | unsigned short | ✘ | ✔ | The cursor's required direction |
void
put
result
of this object's request is set to
the key for the stored record. If the noOverwrite parameter was
true
and a record exists in this index for the key
key parameter or this index is auto-populated or if no
record exists with key value parameter in the index's
referenced object store, then the error
of this object's request
is set to code CONSTRAINT_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
value | any | ✘ | ✘ | The value to be stored in the record |
key | any | ✘ | ✔ | The key used to identify the record |
noOverwrite | boolean | ✘ | ✔ | Whether to overwrite an existing record with the same key. This defaults
to false . |
void
interface CursorRequest : Cursor
{
readonly attribute DBRequest
request;
readonly attribute any key;
readonly attribute any value;
readonly attribute unsigned long long count;
void update (in any value);
void continue (in optional any key);
void delete ();
};
count
of type unsigned long long, readonlykey
of type any, readonlyrequest
of type DBRequest
, readonlyvalue
of type any, readonlycontinue
error
for this object's request is set to code
NOT_ALLOWED_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
key | any | ✘ | ✔ | The next key to position this cursor at |
void
delete
This method returns immediately and deletes the object at the
cursor's position. If the underlying
index or object store does not support updating the item
because it is open in the
READ_ONLY
or
SNAPSHOT_READ
mode, then the
error
for this object's request is set to code
NOT_ALLOWED_ERR
.
void
update
error
for this object's
request is set to code DATA_ERR
. If the underlying
index or object store does not support updating the item
because it is open in the READ_ONLY
or
SNAPSHOT_READ
mode, then the
error
for this
object's request is set to code NOT_ALLOWED_ERR
.
If the data being stored could not be serialized by the
internal structured cloning algorithm, then the
error
for this
object's request is set to code SERIAL_ERR
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
value | any | ✘ | ✘ |
void
interface TransactionRequest : Transaction
{
readonly attribute DBRequest
request;
void abort ();
void commit ();
};
request
of type DBRequest
, readonlyabort
error
for this object's request is set to code
NON_TRANSIENT_ERR
.
void
commit
error
for this object's request is set to code
NON_TRANSIENT_ERR
. If this transaction's
scope is dynamic, and the user agent cannot commit all the
changes due to conflicts with another transaction, then the
error
for this object's request is set to code
RECOVERABLE_ERR
.
void
The following are the event handlers (and their corresponding
event handler event types) that must be supported, as IDL
attributes, by objects implementing the DBRequest
interface:
Event handler | Event handler event type |
---|---|
onsuccess |
success |
onerror |
error |
DatabaseError
Interface
Errors in the asynchronous database API are reported using
callbacks that have a DatabaseError
object as one of their arguments.
interface DatabaseError {
attribute unsigned short code;
attribute DOMString message;
};
code
of type unsigned shortmessage
of type DOMStringA third-party host (or any object capable of getting content distributed to multiple sites) could use a unique identifier stored in its client-side database to track a user across multiple sessions, building a profile of the user's activities. In conjunction with a site that is aware of the user's real idobject (for example an e-commerce site that requires authenticated credentials), this could allow oppressive groups to target individuals with greater accuracy than in a world with purely anonymous Web usage.
There are a number of techniques that can be used to mitigate the risk of user tracking:
iframe
s.
User agents may automatically delete stored data after a period of time.
This can restrict the ability of a site to track a user, as the site would then only be able to track the user across multiple sessions when he authenticates with the site itself (e.g. by making a purchase or logging in to a service).
However, this also puts the user's data at risk.
User agents should present the database feature to the user in a way that associates them strongly with HTTP session cookies. [COOKIES]
This might encourage users to view such storage with healthy suspicion.
User agents may require the user to authorize access to databases before a site can use the feature.
User agents may record the origins of sites that contained content from third-party origins that caused data to be stored.
If this information is then used to present the view of data currently in persistent storage, it would allow the user to make informed decisions about which parts of the persistent storage to prune. Combined with a blacklist ("delete this data and prevent this domain from ever storing data again"), the user can restrict the use of persistent storage to sites that he trusts.
User agents may allow users to share their persistent storage domain blacklists.
This would allow communities to act together to protect their privacy.
While these suggestions prevent trivial use of this API for user tracking, they do not block it altogether. Within a single domain, a site can continue to track the user during a session, and can then pass all this information to the third party along with any identifying information (names, credit card numbers, addresses) obtained by the site. If a third party cooperates with multiple sites to obtain such information, a profile can still be created.
However, user tracking is to some extent possible even with no cooperation from the user agent whatsoever, for instance by using session identifiers in URLs, a technique already commonly used for innocuous purposes but easily repurposed for user tracking (even retroactively). This information can then be shared with other sites, using using visitors' IP addresses and other user-specific data (e.g. user-agent headers and configuration settings) to combine separate sessions into coherent user profiles.
User agents should treat persistently stored data as potentially sensitive; it's quite possible for e-mails, calendar appointments, health records, or other confidential documents to be stored in this mechanism.
To this end, user agents should ensure that when deleting data, it is promptly deleted from the underlying storage.