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.
The steps for opening a database are defined in the following steps. The algorithm in these steps takes three required arguments: an origin, which requested the database to be opened, a database name, and a database version. The algorithm also takes two optional arguments, a request which represents a request used when opening the database is done by using an asynchronous API or a upgrade callback which represents the callback used when opening the database is done by using the synchronous API.
"versionchange"
transaction.
If several connections with the same origin, name and version are opened at the same time,
and that version is a higher version that the database's current version, then once any of
those connections can proceed to the next step in this algorithm it will immediately start
a "versionchange"
transaction. This prevents the other connections from proceeding until that
"versionchange"
transaction is finished.
This means that if two databases with the same name and origin, but with different versions, are being opened at the same time, the one with the highest version will attempt to be opened first. If it is able to successfully open, then the one with the lower version will receive an error.
0
as version, and with no object stores. Let db
be the new database.
DOMError
of type VersionError.
"versionchange"
transaction using connection,
version, request and upgrade callback.
"versionchange"
transaction in the previous step was aborted, or if
connection is closed, return a
DOMError
of type AbortError and abort these steps.
In either of these cases, ensure that connection is closed
by running the steps for closing a database connection before these steps are aborted.
When the user agent is to create a transaction it MUST run the following steps. This algorithm takes five parameters: A connection, a mode, a list of storeNames of object stores to be included in the scope of the transaction, a timeout for the transaction starting, and a callback parameter for synchronously created transactions.
DOMException
of type InvalidStateError.
DOMStringList
or Array
leave it as is. Otherwise,
interpret it as an Array
with one value, and that value is the stringified version of
storeNames. If any of the strings in storeNames identifies an object store which doesn't
exist, throw a DOMException
of type NotFoundError. If storeNames is an empty list
throw a DOMException
of type InvalidAccessError.
DOMException
of type InvalidStateError.
DOMException
of type TimeoutError should be thrown.
Because the asynchronous API always passes in a timeout of infinite, only the synchronous API will ever time out.
name
of the exception that was thrown as the error
parameter, abort this algorithm without taking any further steps, and re-throw the exception.
When taking the steps for committing a transaction the implementation MUST execute the following algorithm. This algorithm takes one parameter, the transaction to commit.
QuotaExceededError
or UnknownError
.
Event
interface and have its type
set to "complete"
.
The event does not bubble and is not cancelable. The
propagation path for the event is transaction's connection and
then transaction.
Note that even if an exception is thrown from one of the event handlers of this event, the transaction is still
committed since writing the database changes happens before the event takes places. Only after the transaction
has been successfully written is the "complete"
event fired.
When taking the steps for aborting a transaction the implementation MUST execute the following algorithm. This algorithm takes two parameters, the transaction to abort and an error name.
"versionchange"
transactions this includes changes to the set of object stores and indexes, as well
as the change to the version. Also run the steps for aborting a "versionchange"
transaction
which reverts changes to all IDBDatabase
and IDBObjectStore
instances.
null
, create a DOMError
object and set its name
to error. Set transaction's error
property to this newly created DOMError
.
undefined
and set the request's error
attribute to a DOMError
with a type of AbortError.
Event
interface and have its type
set to "error"
.
The event bubbles and is cancelable. The
propagation path for the event is transaction's connection,
then transaction and finally the request. There is no default action for the event.
This does not always result in any error
events being fired. For example if a transaction is aborted
due to an error while committing the transaction, or if it was the last remaining request
that failed.
Event
interface and have its type
set to "abort"
.
The event does bubble but is not cancelable.
The propagation path for the event is transaction's connection and
then transaction.
When taking the steps for asynchronously executing a request the implementation MUST run the following algorithm. The algorithm takes a source object and an operation to perform on a database.
These steps can be aborted at any point if the transaction the created request belongs to is aborted using the steps for aborting a transaction
DOMException
of type TransactionInactiveError.
Cursors override this step to reuse an existing IDBRequest. However they still put the IDBRequest at the end of the list of requests in transaction.
error
attribute of the request to undefined
.
Finally fire a success event at request.
undefined
and set the error
attribute on the request
to the a DOMError
with the same error type of the operation that failed.
Finally fire an error event at request.
When taking the steps for synchronously executing a request the implementation MUST run the following algorithm. The algorithm takes a source object and an operation to perform on a database.
DOMException
of type TransactionInactiveError.
DOMException
with the type
of error from the operation.
When taking the steps for extracting a key from a value using a key path, the implementation MUST run the following algorithm. The algorithm takes a key path named keyPath and a value named value and in some cases returns a key which may or may not be a valid key.
Array
, then let result be newly constructed empty
Array
. For each item in the keyPath Array
, perform the following
substeps:
This will only ever "recurse" one level since keyPath arrays can't ever be nested.
"versionchange"
transaction steps
The steps for running a "versionchange"
transaction are
as follows. This algorithm takes two required parameters: a connection object which is used
to update the database, and a new version to be set for the database.
The algorithm also takes two optional arguments: a request which represents a request
used when the asynchronous API is used, or a upgrade callback which
represents the callback used when the synchronous API is used.
IDBDatabase
and IDBDatabaseSync
objects, except connection, connected to the same database as connection.
Fire a versionchange
event at each object in openDatabases that is open. The event MUST NOT
be fired on objects which has the closePending
flag set. The event MUST use the
IDBVersionChangeEvent
interface and have the
oldVersion
property set to db's
version and have the newVersion
property set to version.
This event MUST NOT bubble or be cancelable. The propagation path for the event is just the IDBDatabase
object itself.
Firing this event might cause one or more of the other objects in openDatabases to be closed, in which case
the versionchange
event MUST NOT be fired at those objects if that hasn't yet been done.
If running asynchronously and any of the connections in openDatabases are still not closed,
queue up a blocked
event for the request. The event MUST use the
IDBVersionChangeEvent
interface and have the
oldVersion
property set to db's
version and have the newVersion
property set to version.
This event MUST NOT bubble or be cancelable. The propagation path for the event is just request.
If .close() is called immediately but a transaction associated with the connection
keeps running for a "long time", should we also fire a blocked
event?
If, while we're waiting here, someone calls open with a version number higher than version, we should probably let that upgrade run first and bail here if it was successful
"versionchange"
and connection used as connection.
The scope of the transaction includes every object store in connection. Set its
active flag to false. Let transaction represent this transaction.
result
property of request to connection.
transaction
property of request to transaction.
upgradeneeded
event targeted at request. The event MUST use the
IDBVersionChangeEvent
interface and have the
oldVersion
property set to old version
and have the newVersion
property set to version.
The readyState
on the request is set to "done"
.
AbortError
.
"versionchange"
transaction is aborted the IDBDatabase
instance which represents connection will remain unchanged.
I.e., it's name
, version
, and objectStoreNames
properties
will remain the value they were before the transaction was aborted.
The default attributes for the IDBDatabase are:
Attribute | Value |
---|---|
name |
the name provided to IDBFactory.open |
version |
0 (zero) |
objectStoresNames |
null |
transaction
property to null
. This MUST be done in the same task as the task firing the
complete
or abort
event, but after those events has been fired.
"versionchange"
transaction
The Steps for aborting a "versionchange"
transaction are as follows.
"versionchange"
transaction was started because the database was newly created,
revert IDBDatabase.version to version 0;
if the transaction was started in response to a version upgrade,
revert to the version it had before the transaction was started.
Note that the only time that the IDBDatabase.version property ever changes value
is during a "versionchange"
transaction.
"versionchange"
transaction was started because the database was newly created,
revert it to an empty list.
If the "versionchange"
transaction was started in response to a version upgrade,
revert to the list of object store names it had before the transaction was started.
Although you cannot access object stores by using the IDBTransaction.objectStore function after a transaction is aborted, the page may still have references to object store instances. In that case IDBObjectStore.indexNames can still be accessed.
The steps for closing a database connection are as follows. These steps take one argument, a connection object.
closePending
flag of connection to true.
Once the closePending
flag has ben set to true no new transactions can be
created using connection. All functions that
create transactions first check the closePending flag first and
throw an exception if it is true.
Once the connection is closed, this can unblock the steps for running a "versionchange"
transaction, and the steps for deleting a database, which both
wait for connections to a given database to be closed
before continuing.
The steps for deleting a database are as follows. The algorithm in these steps takes three arguments: the origin that requested the database to be deleted, a database name, and an optional request representing a request used when deleting the database from an asynchronous API.
IDBDatabase
and IDBDatabaseSync
objects connected to db.
Fire a versionchange
event at each object in openDatabases that is open. The event MUST NOT
be fired on objects which has the closePending
flag set. The event MUST use the
IDBVersionChangeEvent
interface and have the
oldVersion
property set to db's
version and have the newVersion
property set to null
.
This event MUST NOT bubble or be cancelable.
Firing this event might cause one or more of the other objects in openDatabases to be closed, in which case
the versionchange
event MUST NOT be fired at those objects if that hasn't yet been done.
If any of the connections in openDatabases are still not closed, and request was provided,
fire a blocked
event at request. The event MUST use the
IDBVersionChangeEvent
interface and have the
oldVersion
property set to db's
version and have the newVersion
property set to null
.
This event MUST NOT bubble or be cancelable.
Should we allow blocked
to be fired here too, if waiting takes "too long"?
To fire a success event at a request, the implementation MUST run the following steps:
Event
interface and have its type
set to "success"
.
The event does not bubble and is not cancelable. The
propagation path for the event is the transaction's connection,
then transaction and finally request.
AbortError
as error.
To fire an error event at a request, the implementation MUST run the following steps:
Event
interface and have its type
set to "error"
.
The event bubbles and is cancelable. The
propagation path for the event is the transaction's connection,
then transaction and finally request. The event's default action is to abort the
transaction by running the steps for aborting a transaction using transaction as transaction
and the name
of request's error
property as error. However the default action is
not taken if any of the event handlers threw an exception.
AbortError
as error. This is done even if the error event is not
canceled.
This means that if an error event is fired and any of the event handlers throw an exception, the error
property
on the transaction is set to an AbortError
rather than whatever DOMError
the error
property on the request was set to. Even if preventDefault
is never called.
The steps to assign a key to a value using a key path are as follows:
Object
object or an Array
object (see structured clone algorithm
[[!HTML5]]), then throw a DOMException
of type DataError
.
Object
or an Array
, and not a Date
, RegExp
, Blob
,
or other nonsupported type.
The intent is that these steps are only executed if evaluating the key path did not yield a value. In other words, before you run these steps, first evaluate the key path against value, and only if that does not yield a value (where 'undefined' does count as a value) do you generate a key and use these steps to modify value to contain the generated key.
The key path used here is always a DOMString
and never an Array
since it is not
possible to create a object store whose multiEntry flag is true and whose
key path is an Array
.
This section describes various operations done on the data in object stores and indexes in a database. These operations are run by the steps for asynchronously executing a request and the steps for synchronously executing a request.
The steps for storing a record into an object store are as follows. The algorithm run by these steps takes four parameters: an object store store, a value, an optional key, and a no-overwrite flag.
long
or a float
and this number is larger than, or equal to, the next key that store's
key generator would generate, change store's key generator such that the next
key it generates is the lowest integer larger than key.
ConstraintError
. Abort this algorithm without taking
any further steps.
Array
,
and if index key is not a valid key, take no further actions for this index.
Array
,
remove any elements from index key that are not valid keys and remove any duplicate
elements from index key such that only one instance of the duplicate value remains.
For example, the following value of index key [10, 20, null, 30, 20]
is converted to
[10, 20, 30]
.
After this step index key is or contains only valid keys.
Array
,
and if index already contains a record with key equal to index key,
and index has it's unique flag set to true, then this operation failed with a
ConstraintError
. Abort this algorithm without taking any further steps.
Array
,
and if index already contains a record with key equal to any of the
values in index key, and index has it's unique flag set to true, then this operation
failed with a ConstraintError
. Abort this algorithm without taking any further steps.
Array
,
then store a record in index containig index key as its key and key as its
value. The record is stored in index's list of records such
that the list is sorted primarily on the records keys, and secondarily on the records values, in ascending
order.
Array
,
then for each item in index key store a record in index containig
the items value as its key and key as its value. The records are stored in index's
list of records such that the list is sorted primarily on the records keys,
and secondarily on the records values, in ascending order.
Note that it is legal for the Array
to have length 0, in this case no records are added to
the index.
If any of the items in the Array
are themselves an Array
, then the inner
Array
is used as a key for that entry. In other words, Array
s are not recursively
"unpacked" to produce multiple rows. Only the outer-most Array
is.
The steps for retrieving a value from an object store are as follows. These steps MUST be run with two parameters - the record key and the object store.
undefined
.
The steps for retrieving a referenced value from an index are as follows. These steps MUST be run with two parameters - the record key and the index.
undefined
.
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.
undefined
.
The steps for deleting records from an object store are as follows. The algorithm run by these steps takes two parameters: an object store store and a key.
undefined
.
The steps for clearing an object store are as follows. The algorithm run by these steps takes one parameter: an object store store.
The steps for iterating a cursor are as follows. The algorithm run by these steps takes two parameters: a cursor and optional key to iterate to.
source is always an object store or an index.
records is always sorted in ascending key order. In the case of source being an index, records is secondarily sorted in ascending value order.
If direction is "next"
, let found record be the first record in records which
satisfy all of the following requirements:
If direction is "nextunique"
, let found record be the first record in records which
satisfy all of the following requirements:
If direction is "prev"
, let found record be the last record in records which
satisfy all of the following requirements:
If direction is "prevunique"
, let temp record be the last record in
records which satisfy all of the following requirements:
If temp record is defined, let found record be the first record in records whose key is equal to temp record's key.
undefined
.
If cursor implements IDBCursorWithValue or IDBCursorWithValueSync, then set
cursor's value to undefined
.
The result of this algorithm is null
. Abort these steps.
Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.
Set cursor's key to found record's key.
If cursor implements IDBCursorWithValue or IDBCursorWithValueSync, then set cursor's value to a structured clone of found record referenced value.
Once data has been successfully read, schedule a task which when run will set the cursor's value and fire a success event.