Table of Contents
The SQL library performs automatic conversion between scheme and database types. Since the exact conversion table depends on the vendor, a mechanism is provided to add support for other vendors though vendor-specific modules.
Requires:
(import sql/jdbc)
Located in:
siscweb-sql.jar
This module provides functions to load drivers, obtain connections, and execute procedures within a transactional context.
procedure:
(jdbc/load-driver name) => #t/#fLoads the JDBC driver specified by
name. It is not necessary to use this function when obtaining a connection from a JDBC DataSource, or when using a plug-in, vendor-specific module. Returns a boolean representing the success of the operation.(jdbc/load-driver "org.hsqldb.jdbcDriver")
procedure:
(jdbc/get-connection datasource) => connectionObtains a connection from the specified JDBC
datasource.(import util/jndi) (jdbc/get-connection (jndi/lookup "java:/comp/env/jdbc/myDS"))
procedure:
(jdbc/open-connection url username password) => connectionOpens and returns a connection to the database specified by the
urlparameter, logging in with the givenusernameandpassword. Theurlis in the samejdbc:subprotocol:subnameformat as in the Java JDBC API.(jdbc/open-connection "jdbc:hsqldb:file:/tmp/my-db" "sa" "")
procedure:
(jdbc/get-vendor connection) => vendor-nameReturns the vendor name, in lowercase, of the database to which
connectionpoints.
procedure:
(jdbc/call-with-connection connection proc) => valueprocedure:(jdbc/call/conn connection procedure) => valueInvokes
procedurewith the givenconnection. When the procedure terminates or fails, the connection is automaticallyclose()ed. The passedproceduremust accept aconnectionas its only argument. The value returned will be that returned byprocedure.(jdbc/call/conn (jdbc/get-connection (jndi/lookup "java:/comp/env/jdbc/myDS")) (lambda (conn) (sql/execute conn "SELECT SYSDATE FROM DUAL")))
procedure:
(jdbc/call-with-transaction connection proc) => value
procedure:(jdbc/call/tran connection procedure) => valueInvokes
procedurewithin a transactional context. The transaction is committed ifprocedurereturns normally, and rolled back in case of failure or invocation of an escape continuation. The passedproceduremust acceptconnectionas its only argument. The value returned will be that returned byprocedure.(jdbc/call/conn (jdbc/get-connection (jndi/lookup "java:/comp/env/jdbc/myDS")) (lambda (conn) (jdbc/call/tran conn (lambda (conn) (sql/execute-update conn "UPDATE my_table SET my_field = 0")))))
Requires:
(import sql/query)
Located in:
siscweb-sql.jar
This module provides functions to execute queries and map through result sets.
jdbc/call/conn
context, intentional or not, the JDBC ResultSet and Statement
are closed only upon garbage collection. This can be a
particularly insidious problem when using pooled connections,
and will be fixed in the future.
procedure:
(sql/execute connection sql-query [value] ...) => number/resultsetExecutes
sql-querythrough the givenconnection.A number of optional
values can be specified; these will be bound in order to the placeholders in the query. Date, time and timestamps from srfi-19 can be used to bind to SQL DATE, TIME and TIMESTAMP types.Returns the number of rows updated in case of an INSERT/UPDATE/DELETE query statement, and a result set in case of a SELECT statement. Result sets are lazy lists in the sense of srfi-45. Each element of the list is a hashtable
(field-name => value). Multiple result sets are not supported.(sql/execute conn "SELECT * FROM my_table WHERE id = ?" 12345)
procedure:
(sql/execute-query connection sql-query [value] ...) => resultsetRuns
sql-queryand returns a result set.
procedure:
(sql/execute-update connection sql-query [value] ...) => numberRuns
sql-queryand returns the number of updated rows.
syntax:
(sql/map-row procedure ((variable field-name) ...) body) => list
syntax:(sql/for-each-row procedure ((variable field-name) ...) body) => undefinedThese two macros facilitate writing code that loops through a resultset. Like their correspectives
mapandfor-each, the former collects results into a list, while the latter is to be used for side-effects.For each row in the
resultset, a Schemevariableis bound to the value of the indicatedfield-namein the resultset, wherefield-nameis either a string or a symbol.In the case of
sql/map-row, the value returned by the last expression inbodyis collected into the returnedlist.(sql/for-each-row (sql/execute-query conn "SELECT id, name FROM person") ((id 'id) (name 'name)) (display (format "~a:~a\n" id name)))
SISCweb includes a number of vendor-specific modules that map Scheme data types onto SQL types and provide extra functionalities, usually in the area of BLOB handling.
Adding support for new vendors is described in the section called “Adding Support for Other Vendors”
Requires:
(import sql/hsqldb)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between HSQLDB and Scheme. Currently only numbers, strings, time types and Java objects are supported.
Requires:
(import sql/mssql)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between Microsoft SQL Server and Scheme. At this time bits, numbers, strings, and time types are supported.
Requires:
(import sql/oracle)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between Oracle and Scheme. At this time numbers, strings (but not CLOBs), and time types are supported. BLOBs are returned as such, but two functions are provided to use them as containers of Java objects.
procedure:
(oracle/read-blob blob) => |java.lang.Object|Deserializes a Java object from
blob.;; returns an alist (id => object) (sql/map-row (sql/execute-query "SELECT id, obj FROM my_table") ((id 'id) (blob 'obj)) `(,id . ,(oracle/read-blob blob)))
procedure:
(oracle/write-blob blob java-object) => undefinedSerializes
java-objectintoblob. Complex Scheme values can also be serialized byjava-wrapping them. The blob has to be first inserted using the Oracle EMPTY_BLOB() function, and then read back with a SELECT query.(sql/for-each-row (sql/execute-query "SELECT id, obj FROM my_table WHERE id = ?" 12345) ((blob 'obj)) (oracle/write-blob blob (java-wrap (lambda (x) (* x x)))))
Requires:
(import sql/postgresql)
Located in:
siscweb-sql.jar
Importing this module registers type conversions between PostgreSQL and Scheme. At this time bits, numbers, strings, time types and vectors are supported.
It is possible to add support for other database vendors. The existing modules (such as sql/hsqldb.scm) can be used as base and reference.
At this stage, supporting a new vendor is simply a matter of
defining an association list between SQL types and conversion
procedures. Each conversion procedure accepts the object as
read by the Java Statement.getObject(n)
method, a ResultSetMetaData object, and the column number.
The function should return a Scheme type. If that is not possible (such as it is the case with BLOBs), the function can return a raw Java type, as long as the module provides other functions to transform the Java type into a Scheme type.