3 Queries
The database package implements a high-level functional query API, unlike many other database libraries, which present a stateful, iteration-based interface to queries. When a query function is invoked, it either returns a result or, if the query caused an error, raises an exception. Different query functions impose different constraints on the query results and offer different mechanisms for processing the results.
SQL syntax errors, such as references to undefined tables, columns, or operations, etc
SQL runtime errors, such as integrity constraint violations
violations of a specialized query function’s expectations, such as using query-value with a query that returns multiple columns
supplying the wrong number or wrong types of parameters to a prepared query, executing a prepared query with the wrong connection, etc
changing communication settings, such as changing the connection’s character encoding
communication failures and internal errors in the library
Character encoding This library is designed to interact with database systems using the UTF-8 character encoding. The connection functions attempt to negotiate UTF-8 communication at the beginning of every connection, but some systems also allow the character encoding to be changed via SQL commands (eg, SET NAMES). If this happens, the client might be unable to reliably communicate with the database, and data might get corrupted in transmission. Avoid changing a connection’s character encoding. When possible, the connection will observe the change and automatically disconnect with an error.
Synchronization Connections are internally synchronized: it is
safe to perform concurrent queries on the same connection object from
different threads. Connections are not kill-safe: killing a thread
that is using a connection—
3.1 Statements
a string containing a single SQL statement, possibly with parameters
a prepared statement produced by prepare
a virtual statement produced by virtual-statement
a statement-binding value produced by bind-prepared-statement
an instance of a struct type that implements prop:statement
(statement? x) → boolean? |
x : any/c |
3.2 Simple queries
The simple query API consists of a set of functions specialized to various types of queries. For example, query-value is specialized to queries that return a recordset of exactly one column and exactly one row.
If a statement takes parameters, the parameter values are given as additional arguments immediately after the SQL statement. Only a statement given as a string, prepared statement, or virtual statement can be given “inline” parameters; if the statement is a statement-binding, no inline parameters are permitted.
The types of parameters and returned fields are described in SQL types and conversions.
(query-exec connection stmt arg ...) → void? |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: | |
> (query-exec c "insert into some_table values (1, 'a')") | |
> (query-exec pgc "delete from some_table where n = $1" 42) | |
(query-rows connection stmt arg ...) → (listof vector?) |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: |
> (query-rows pgc "select * from the_numbers where n = $1" 2) |
(#(2 "company")) |
> (query-rows c "select 17") |
(#(17)) |
(query-list connection stmt arg ...) → list? |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: |
> (query-list c "select n from the_numbers where n < 2") |
(0 1) |
> (query-list c "select 'hello'") |
("hello") |
(query-row connection stmt arg ...) → vector? |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: |
> (query-row myc "select * from the_numbers where n = ?" 2) |
#(2 "company") |
> (query-row c "select 17") |
#(17) |
(query-maybe-row connection stmt arg ...) → (or/c vector? #f) |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: |
> (query-maybe-row pgc "select * from the_numbers where n = $1" 100) |
> (query-maybe-row c "select 17") |
#(17) |
(query-value connection stmt arg ...) → any/c |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: |
> (query-value pgc "select timestamp 'epoch'") |
#(struct:sql-timestamp 1970 1 1 0 0 0 0 #f) |
> (query-value pgc "select s from the_numbers where n = $1" 3) |
"a crowd" |
(query-maybe-value connection stmt arg ...) → (or/c any/c #f) |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: |
> (query-value myc "select s from some_table where n = ?" 100) |
> (query-value c "select 17") |
17 |
(in-query connection stmt arg ...) → sequence? |
connection : connection? |
stmt : statement? |
arg : any/c |
Examples: | ||||
| ||||
(0 1) | ||||
| ||||
| ||||
An in-query application can provide better performance when it appears directly in a for clause. In addition, it may perform stricter checks on the number of columns returned by the query based on the number of variables in the clause’s left-hand side:
Example: | ||
| ||
in-query: query returned 2 columns (expected 1): "select * | ||
from the_numbers" |
3.3 General query support
A general query result is either a simple-result or a recordset.
(struct simple-result (info)) |
info : any/c |
The info field is usually an association list, but do not rely on its contents; it varies based on database system and may change in future versions of this library (even new minor versions).
The headers field is a list whose length is the number of columns in the result rows. Each header is usually an association list containing information about the column, but do not rely on its contents; it varies based on the database system and may change in future version of this library (even new minor versions).
(query connection stmt arg ...) → (or/c simple-result? recordset?) |
connection : connection? |
stmt : statement? |
arg : any/c |
(query-fold connection stmt fold-proc init) → alpha |
connection : connection? |
stmt : (or/c string? statement-binding?) |
fold-proc : (alpha field ... -> alpha) |
init : alpha |
This function is deprecated; use for/fold with in-query instead.
3.4 Prepared statements
A prepared statement is the result of a call to prepare.
The syntax of parameterized queries varies depending on the database system. For example:
PostgreSQL:
select * from the_numbers where num > $1;
MySQL, ODBC:
select * from the_numbers where num > ?;
SQLite:
supports both syntaxes (plus others)
Any server-side or native-library resources associated with a prepared statement are released when the prepared statement is garbage-collected or when the connection that owns it is closed; prepared statements do not need to be (and cannot be) explicitly closed.
(prepare connection stmt) → prepared-statement? |
connection : connection? |
stmt : (or/c string? virtual-statement?) |
(prepared-statement? x) → boolean? |
x : any/c |
(prepared-statement-parameter-types pst) |
→ (listof (list/c boolean? (or/c symbol? #f) any/c)) |
pst : prepared-statement? |
(list supported? type typeid)
The supported? field is #t if the type is supported by this library; the type field is a symbol corresponding to one of the tables in SQL type conversions, and the typeid field is a system-specific type identifier. The type description list format may be extended with additional information in future versions of this library.
(prepared-statement-result-types pst) |
→ (listof (list/c boolean? (or/c symbol? #f) any/c)) |
pst : prepared-statement? |
(bind-prepared-statement pst params) → statement-binding? |
pst : prepared-statement? |
params : (listof any/c) |
Example: | ||||||||
| ||||||||
("company" "a crowd") |
Most query functions perform the binding step implicitly, but there are functions such as query-fold that do not accept query parameters; bind-prepared-statement is neccessary to use a parameterized query with such functions.
(statement-binding? x) → boolean? |
x : any/c |
(virtual-statement gen) → virtual-statement? |
gen : (or/c string? (-> dbsystem? string?)) |
The gen argument must be either a SQL string or a function that accepts a databse system object and produces a SQL string. The function variant allows the SQL syntax to be dynamically customized for the database system in use.
Examples: | |||||||
| |||||||
> (query-list pgc pst 3) | |||||||
(1 2) | |||||||
> (query-list slc pst 3) | |||||||
(1 2) |
(virtual-statement? x) → boolean? |
x : any/c |
| ||
|
3.5 Transactions
The functions described in this section provide a consistent interface to transactions.
ODBC connections should use these functions exclusively instead of transaction-changing SQL statements such as START TRANSACTION and COMMIT. Using transaction-changing SQL may cause these functions to behave incorrectly and may cause additional problems in the ODBC driver.
PostgreSQL, MySQL, and SQLite connections are discouraged from using transaction-changing SQL statements, but the consequences are less dire. The functions below will behave correctly, but the syntax and behavior of the SQL statements is idiosyncratic. For example, in MySQL START TRANSACTION commits the current transaction, if one is active; in PostgreSQL COMMIT silently rolls back the current transaction if an error occurred in a previous statement.
All errors raised by checks performed by this library, such as parameter arity and type errors, leave the transaction open and unchanged (1).
All errors originating from PostgreSQL cause the transaction to become invalid (3).
Most errors originating from MySQL leave the transaction open and unchanged (1), but a few cause the transaction to become invalid (3). In the latter cases, the underlying behavior of MySQL is to roll back the transaction but leave it open (see the MySQL documentation). This library detects those cases and marks the transaction invalid instead.
Most errors originating from SQLite leave the transaction open and unchanged (1), but a few cause the transaction to become invalid (3). In the latter cases, the underlying behavior of SQLite is to roll back the transaction (see the SQLite documentation). This library detects those cases and marks the transaction invalid instead.
All errors originating from an ODBC driver cause the transaction to become invalid (3). The underlying behavior of ODBC drivers varies widely, and ODBC provides no mechanism to detect when an existing transaction has been rolled back, so this library intercepts all errors and marks the transaction invalid instead.
| |||||||||||||||
c : connection? | |||||||||||||||
|
If c is already in a transaction, an exception is raised.
(commit-transaction c) → void? |
c : connection? |
If no transaction is active, has no effect.
(rollback-transaction c) → void? |
c : connection? |
If no transaction is active, has no effect.
(in-transaction? c) → boolean? |
c : connection? |
(needs-rollback? c) → boolean? |
c : connection? |
| |||||||||||||||||||||
c : connection? | |||||||||||||||||||||
proc : (-> any) | |||||||||||||||||||||
|