Client API
Connection Management
(connection? [v any/c]) → boolean?
Checks whether something is a database connection handle.
(uri->scheme+options [uri uri-reference?]) → (values symbol? list?)
Converts a URI into a connection specification as follows:
- The URI scheme becomes the first result.
- The URI host, if present, becomes a (host . ...) pair in the resulting list.
- The URI port, if present, becomes a (port . ...) pair in the resulting list.
- The URI path is converted to a platform specific path using the procedure make-pathname or make-absolute-pathname, depending on whether the URI path is absolute to begin with, and becomes a (path . ...) pair in the resulting list.
- The URI query is split at any occurence of & or ;, each resulting snippet is split into a key and value part at the first occurence of =, any remaining urlencoded characters in the key and value part are resolved, the key is converted into a symbol and the value is read using the standard Scheme reader. All key value pairs become parts of the resulting list.
(connect [spec (or/c (cons/c symbol? list?) uri-reference? string?)] #:autoload? [autoload? any/c #f] #:cache [cache integer? 64]) → connection?
Connects to a database. If autoload? is true, the driver symbol from the specification is prefixed with dbd- and passed to the procedure require. The driver is then looked up using the procedure select-driver and the driver is used to establish a database connection.
The cache parameter determines the size of a least-recently-used statement cache for the database connection. If the size is zero, caching is disabled and a finalizer is registered for prepared statements instead of adding them to a cache.
(disconnect [db connection?]) → void?
Closes a database connection. The statement cache of the connection is flushed before the underlying driver is instructed to terminate the connection. In addition, the underlying driver is instructed to clean up any left-over statements belonging to the connection, if this is possible.
(with-transaction [db connection?] [thunk (-> any)]) → any
Invokes thunk within the dynamic extent of a transaction on the given database and returns whatever thunk returns.
Statement Management
(statement? [v any/c]) → boolean?
Checks whether something is a statement handle.
(statement->sql [stmt statement?]) → string?
Extracts the SQL source code from a statement. In the resulting source code identifier placeholders have already been interpolated and query parameter placeholders have been replaced with driver specific substrings.
(prepare [db connection?] [sql string?] #:<syms> [syms (listof symbol?) '()]) → statement?
(prepare [db connection?] [sql string?] [sym symbol?] ...) → statement?
Prepares a statement or retrieves one from the cache. The query string may contain the following placeholders:
- ~~ is replaced by ~.
- ~s is replaced by the next symbol from syms, properly quoted.
- ~q or ~q: followed by a symbol are replaced by a driver specific query parameter placeholder.
(forget [stmt statement?]) → void?
Destroys a prepared statement.
(rows-fold [kons (-> row? any/c any/c)] [knil any/c] [stmt statement?] #:<args> [args list?]) → any/c
(rows-fold [kons (-> row? any/c any/c)] [knil any/c] [stmt statement?] [arg any/c] ...) → any/c
(rows-fold [kons (-> row? any/c any/c)] [knil any/c] [db database?] [sql string?] #:<syms> [syms (listof symbol?)] #:<args> [args list?]) → any/c
(rows-fold [kons (-> row? any/c any/c)] [knil any/c] [db database?] [sql string?] [sym/arg (or/c symbol? any/c)] ...) → any/c
Prepares a statement if necessary, binds query parameters and iterates over result rows.
The arguments can be positional or keyword arguments and, in case SQL source is given instead of an existing statement handle, symbols to be interpolated into the source may be intermixed with the other query arguments.
To avoid the necessity to use apply in higher level abstraction code, the lists of symbols and of keywords and arguments can also be specified explicitly using the special keyword arguments #:<syms> and #:<args>.
Returns the result of calling kons repeatedly on a row and its last return value or knil for the first call.
In case kons is identical to the procedure void, the underlying driver may decide to never actually call the procedure.
(:rows row (index idx) [stmt statement?] #:<args> [args list?])
(:rows row (index idx) [stmt statement?] [arg any/c] ...)
(:rows row [stmt statement?] #:<args> [args list?])
(:rows row [stmt statement?] [arg any/c] ...)
(:rows row (index idx) [db database?] [sql string?] #:<syms> [syms (listof symbol?)] #:<args> [args list?])
(:rows row (index idx) [db database?] [sql string?] [sym/arg (or/c symbol? any/c)] ...)
(:rows row [db database?] [sql string?] #:<syms> [syms (listof symbol?)] #:<args> [args list?])
(:rows row [db database?] [sql string?] [sym/arg (or/c symbol? any/c)] ...)
Prepares a statement if necessary, binds query parameters and iterates over result rows.
The arguments can be positional or keyword arguments and, in case SQL source is given instead of an existing statement handle, symbols to be interpolated into the source may be intermixed with the other query arguments.
To avoid the necessity to use apply in higher level abstraction code, the lists of symbols and of keywords and arguments can also be specified explicitly using the special keyword arguments #:<syms> and #:<args>.
Row Data Access
(row? [v any/c]) → boolean?
Checks whether something is a result row handle.
(row-length [row row?]) → integer?
Counts the number of columns in a result row.
(row-ref [row row?] [idx (or/c integer? symbol?)]) → any/c
Retrieves the value in a column of a result row. The column is referenced by zero based index or by symbolic name.
(row->list [row row?]) → list?
Converts a result row into a list of column values.
(row->alist [row row?]) → (listof (cons/c (or/c symbol? integer?) any/c))
Converts a result row into an association list mapping column names to values. Anonymous columns are assigned their index as their name.
(row->vector [row row?]) → vector?
Converts a result row into a vector of column values.
Persistent Records
(persistent-record-type? [v any/c]) → boolean?
Checks whether something is a persistent record type descriptor.
(make-persistent-record-type [type-name symbol?] [field-names (listof symbol?)] [key-names (listof symbol?)]) → persistent-record-type?
Creates a new persistent record type descriptor. type-name is used both as the record type tag and as the table identifier. field-names is a list of field names that are also used as column identifiers. key-names is a list of field names that uniquely identify the database row corresponding to any instance of the record type.
(persistent-record-constructor [prtd persistent-record-type?] [field-names (listof symbol?) ...]) → (-> [v any/c] ... record-instance?)
Obtains a constructor procedure from a persistent record type descriptor. The constructor initializes the given list of fields or all fields if the optional argument is not given. The list of fields must at least include all key fields.
All the fields initialized by the constructor are initially marked as modified.
(persistent-record-constructor/row [prtd persistent-record-type?]) → (-> [row row?] [field-names (listof symbol?) ...] record-instance?)
Obtains a constructor procedure from a persistent record type descriptor. The constructor converts a result row into an instance of the record type in which all fields are initialized.
The constructor can optionally be given a list of column indices or names to take from the result row. If this list is omitted, the constructor tries to extract all columns using the record type's field names.
None of the fields in the resulting record are initially marked as modified.
(persistent-record-constructor/key [prtd persistent-record-type?]) → (-> [db connection?] [key any/c] ... record-instance?)
Obtains a constructor procedure from a persistent record type descriptor. The constructor finds a row matching the given key in a database and converts it into an instance of the record type in which all fields are initialized.
None of the fields in the resulting record are initially marked as modified.
(persistent-record-predicate [prtd persistent-record-type?]) → (-> [v any/c] boolean?)
Obtains a record predicate from a persistent record type descriptor.
(persistent-record-syncer [prtd persistent-record-type?]) → (-> [pr record-instance?] [db connection?] void?)
Obtains a record synchronization procedure from a persistent record type descriptor.
Record synchronization works as follows:
- If any of the record's key fields are marked as modified, an INSERT statement is executed to store all the modified fields in the record type's table in the given database.
- If none of the record's key fields are marked as modified, an UPDATE statement is executed to store all the modified fields in the record type's table in the row matching all the key fields in the record.
- All unmodified fields of the record are updated to their corresponding values in the database using the results from a SELECT statement.
- The set of modified fields in the record is reset to null.
(persistent-record-accessor [prtd persistent-record-type?] [field-name symbol?]) → (-> [pr record-instance?] any/c)
Obtains a record field accessor from a persistent record type descriptor.
(persistent-record-modifier [prtd persistent-record-type?] [field-name symbol?]) → (-> [pr record-instance?] any/c void?)
Obtains a record field modifier from a persistent record type descriptor.
After setting the field in the record, the modifier adds the field to the record's set of modified fields.
(define-persistent-record-type <type-name> <constructor-spec> <key-spec> <constructor/row> <predicate> <syncer> <accessor-spec> ...)
Syntactic form to define a persistent record type. The definition essentially has this form:
(define <type-name> (make-persistent-record-type '<type-name> '(<field-name> ...) '(<key-name> ...)))
Where the field and key names are provided by other subforms:
<constructor-spec> := (<constructor> <constructor/row> <field-name> ...) <key-spec> := (<constructor/key> <key-name> ...)
Three constructors are defined for the record type:
(define <constructor> (persistent-record-constructor <type-name>)) (define <constructor/row> (persistent-record-constructor/row <type-name>)) (define <constructor/key> (persistent-record-constructor/key <type-name>))
A predicate is defined for the record type:
(define <predicate> (persistent-record-predicate <type-name>))
A synchronizer is defined for the record type:
(define <syncer> (persistent-record-syncer <type-name>))
Accessors and modifiers are defined according to the corresponding subforms:
<accessor-spec> := [<field-name> <accessor> <modifier>] | [<field-name> <accessor>]
Where a modifier becomes this:
(define <modifier> (persistent-record-modifier <type-name> '<field-name>))
And an accessor becomes this:
(define <accessor> (getter-with-setter (persistent-record-accessor <type-name> '<field-name>) <modifier>))
No setter is attached if no modifier has been defined.
(persistent-record-link-accessor [prtd-a persistent-record-type?] [key-names-a (listof symbol?)] [prtd-b persistent-record-type?] [key-names-b (listof symbol?) ...]) → (-> [pr-a record-instance?] [db connection?] record-instance?)
Given two persistent record type descriptors and lists of key fields for each of them, this procedure constructs an accessor that loads a record of the second type whose key fields match those of a given record of the first type.
The list of key fields for the second record type can be omitted and defaults to its natural unique key fields.
(persistent-record-link-modifier [prtd-a persistent-record-type?] [key-names-a (listof symbol?)] [prtd-b persistent-record-type?] [key-names-b (listof symbol?) ...]) → (-> [pr-a record-instance?] [pr-b record-instance?] void?)
Given two persistent record type descriptors and lists of key fields for each of them, this procedure constructs a modifier that changes the key fields in a record of the first type to match those of a given record of the second type.
The list of key fields for the second record type can be omitted and defaults to its natural unique key fields.
(define-persistent-record-link <accessor-spec> <from-key-spec> <to-key-spec>)
Defines a link accessors and optionally a modifier according to the accessor specification:
<accessor-spec> := (<accessor> <modifier> <from-type-name> <to-type-name>) | (<accessor> <from-type-name> <to-type-name>)
The modifier, if any, becomes this:
(define <modifier> (persistent-record-link-modifier <from-type-name> '(<from-key-name> ...) <to-type-name> '(<to-key-name> ...)))
The accessor, if any, becomes this:
(define <accessor> (getter-with-setter (persistent-record-link-accessor <from-type-name> '(<from-key-name> ...) <to-type-name> '(<to-key-name> ...)) <modifier>))
No setter is attached if no modifier has been defined. Also, the list of key names for the target record type is omitted if it wasn't specified by the key specification subforms:
<from-key-spec> := (from-key <from-key-name> ...) <to-key-spec> := (to-key <to-key-name> ...) |