SQL Storage
The SqlStorage
interface encapsulates methods that modify the SQLite database embedded within a Durable Object. The SqlStorage
interface is accessible via the sql
property of DurableObjectStorage
class.
For example, using sql.exec()
, a user can create a table, then insert rows into the table.
Specifically for Durable Object classes with SQLite storage backend, KV operations which were previously asynchronous (for example, get
, put
, delete
, deleteAll
, list
) are synchronous, even though they return promises. These methods will have completed their operations before they return the promise.
exec(query: string , ...bindings: any[] )
: SqlStorageCursor
query
: string- The SQL query string to be executed.
query
can contain?
placeholders for parameter bindings. Multiple SQL statements, separated with a semicolon, can be executed in thequery
. With multiple SQL statements, any parameter bindings are applied to the last SQL statement in thequery
, and the returned cursor is only for the last SQL statement.
- The SQL query string to be executed.
bindings
: any[] Optional- Optional variable number of arguments that correspond to the
?
placeholders inquery
.
- Optional variable number of arguments that correspond to the
A cursor (SqlStorageCursor
) to iterate over query row results as objects. SqlStorageCursor
is a JavaScript Iterable ↗, which supports iteration using for (let row of cursor)
. SqlStorageCursor
is also a JavaScript Iterator ↗, which supports iteration using cursor.next()
.
SqlStorageCursor
supports the following methods:
next()
- Returns an object representing the next value of the cursor. The returned object has
done
andvalue
properties adhering to the JavaScript Iterator ↗.done
is set tofalse
when a next value is present, andvalue
is set to the next row object in the query result.done
is set totrue
when the entire cursor is consumed, and novalue
is set.
- Returns an object representing the next value of the cursor. The returned object has
toArray()
- Iterates through remaining cursor value(s) and returns an array of returned row objects.
one()
- Returns a row object if query result has exactly one row. If query result has zero rows or more than one row,
one()
throws an exception.
- Returns a row object if query result has exactly one row. If query result has zero rows or more than one row,
raw()
: Iterator- Returns an Iterator over the same query results, with each row as an array of column values (with no column names) rather than an object.
- Returned Iterator supports
next()
,toArray()
, andone()
methods above. - Returned cursor and
raw()
iterator iterate over the same query results and can be combined. For example:
SqlStorageCursor
had the following properties:
columnNames
: string[]- The column names of the query in the order they appear in each row array returned by the
raw
iterator.
- The column names of the query in the order they appear in each row array returned by the
rowsRead
: number- The number of rows read so far as part of this SQL
query
. This may increase as you iterate the cursor. The final value is used for SQL billing. rowsWritten
: number- The number of rows written so far as part of this SQL
query
. This may increase as you iterate the cursor. The final value is used for SQL billing.
Note that sql.exec()
cannot execute transaction-related statements like BEGIN TRANSACTION
or SAVEPOINT
. Instead, use the ctx.storage.transaction()
or ctx.storage.transactionSync()
APIs to start a transaction, and then execute SQL queries in your callback.
SQL API examples below use the following SQL schema:
Iterate over query results as row objects:
Convert query results to an array of row objects:
Convert query results to an array of row values arrays:
Get first row object of query results:
Check if query results have exactly one row:
Returned cursor behavior:
Returned cursor and raw()
iterator iterate over the same query results:
sql.exec().rowsRead()
:
databaseSize
: number
The current SQLite database size in bytes.
For Durable Objects classes with SQL storage, the following point-in-time-recovery (PITR) API methods are available to restore a Durable Object's embedded SQLite database to any point in time in the past 30 days. These methods apply to the entire SQLite database contents, including both the object's stored SQL data and stored key-value data using the key-value put()
API. The PITR API is not supported in local development because a durable log of data changes is not stored locally.
The PITR API represents points in times using 'bookmarks'. A bookmark is a mostly alphanumeric string like 0000007b-0000b26e-00001538-0c3e87bb37b3db5cc52eedb93cd3b96b
. Bookmarks are designed to be lexically comparable: a bookmark representing an earlier point in time compares less than one representing a later point, using regular string comparison.
ctx.storage.getCurrentBookmark()
: Promise<string>
- Returns a bookmark representing the current point in time in the object's history.
ctx.storage.getBookmarkForTime(timestamp: number | Date )
: Promise<string>
- Returns a bookmark representing approximately the given point in time, which must be within the last 30 days. If the timestamp is represented as a number, it is converted to a date as if using
new Date(timestamp)
.
ctx.storage.onNextSessionRestoreBookmark(bookmark: string )
: Promise<string>
- Configures the Durable Object so that the next time it restarts, it should restore its storage to exactly match what the storage contained at the given bookmark. After calling this, the application should typically invoke
ctx.abort()
to restart the Durable Object, thus completing the point-in-time recovery.
This method returns a special bookmark representing the point in time immediately before the recovery takes place (even though that point in time is still technically in the future). Thus, after the recovery completes, it can be undone by performing a second recovery to this bookmark.