db: fix #:group contract, fix sqlite headers

This commit is contained in:
Ryan Culpepper 2011-09-03 14:52:06 -06:00
parent e6433084f3
commit 15e3640191
7 changed files with 129 additions and 84 deletions

View File

@ -71,3 +71,10 @@ Misc
- connection-pool-lease-evt
- when is it useful in practice?
- would make it easier to handle timeouts...
- on insert, return last inserted id
- postgresql: parse CommandComplete msg tag
- mysql: in ok-packet (what conditions, though?)
- sqlite3: sqlite3_last_insert_rowid(), use sqlite3_changes() to see if insert succeeded,
but still need to tell if stmt was even insert (parse sql?)
- odbc: ???

View File

@ -104,7 +104,9 @@
[query-exec
(->* (connection? statement?) () #:rest list? any)]
[query-rows
(->* (connection? statement?) () #:rest list? (listof vector?))]
(->* (connection? statement?)
(#:group (or/c (vectorof string?) (listof (vectorof string?))))
#:rest list? (listof vector?))]
[query-list
(->* (connection? statement?) () #:rest list? list?)]
[query-row

View File

@ -142,7 +142,7 @@
(let* ([sql (compose-statement 'query-rows c sql args 'rows)]
[result (query/rows c 'query-rows sql #f)]
[result
(cond [(pair? group-fields-list)
(cond [(not (null? group-fields-list))
(group-rows-result* 'query-rows result group-fields-list
(not (memq 'preserve-null-rows group-mode))
(memq 'list group-mode))]

View File

@ -37,14 +37,13 @@
(define/override (connected?) (and -db #t))
(define/public (query fsym stmt)
(let-values ([(stmt* info rows)
(let-values ([(stmt* result)
(call-with-lock fsym
(lambda ()
(check-valid-tx-status fsym)
(query1 fsym stmt)))])
(statement:after-exec stmt)
(cond [(pair? info) (rows-result info rows)]
[else (simple-result '())])))
result))
(define/private (query1 fsym stmt)
(let* ([stmt (cond [(string? stmt)
@ -64,12 +63,23 @@
(load-param fsym db stmt i param))
(let* ([info
(for/list ([i (in-range (sqlite3_column_count stmt))])
`((name ,(sqlite3_column_name stmt i))
(decltype ,(sqlite3_column_decltype stmt i))))]
`((name . ,(sqlite3_column_name stmt i))
(decltype . ,(sqlite3_column_decltype stmt i))))]
[rows (step* fsym db stmt)])
(HANDLE fsym (sqlite3_reset stmt))
(HANDLE fsym (sqlite3_clear_bindings stmt))
(values stmt info rows)))))
(values stmt
(cond [(pair? info)
(rows-result info rows)]
[else
(let ([changes (sqlite3_changes db)])
(cond [(and (positive? changes)
#f ;; Note: currently disabled
#| FIXME: statement was INSERT stmt |#)
(simple-result
(list (cons 'last-insert-rowid
(sqlite3_last_insert_rowid db))))]
[else (simple-result '())]))]))))))
(define/private (load-param fsym db stmt i param)
(HANDLE fsym
@ -203,7 +213,7 @@
(let ([db (get-db fsym)])
(when (get-tx-status db)
(error/already-in-tx fsym))
(let-values ([(stmt* _info _rows)
(let-values ([(stmt* _result)
(query1 fsym "BEGIN TRANSACTION")])
stmt*))))])
(statement:after-exec stmt)
@ -217,7 +227,7 @@
(unless (eq? mode 'rollback)
(check-valid-tx-status fsym))
(when (get-tx-status db)
(let-values ([(stmt* _info _rows)
(let-values ([(stmt* _result)
(case mode
((commit)
(query1 fsym "COMMIT TRANSACTION"))
@ -235,14 +245,11 @@
;; schema ignored, because sqlite doesn't support
(string-append "SELECT tbl_name from sqlite_master "
"WHERE type = 'table' or type = 'view'")])
(let-values ([(stmt rows)
(let-values ([(stmt result)
(call-with-lock fsym
(lambda ()
(let-values ([(stmt _info rows)
(query1 fsym stmt)])
(values stmt rows))))])
(lambda () (query1 fsym stmt)))])
(statement:after-exec stmt)
(for/list ([row (in-list rows)])
(for/list ([row (in-list (rows-result-rows result))])
(vector-ref row 0)))))
;; ----

View File

@ -140,6 +140,14 @@
(_fun _sqlite3_statement
-> _string))
(define-sqlite sqlite3_changes
(_fun _sqlite3_database
-> _int))
(define-sqlite sqlite3_last_insert_rowid
(_fun _sqlite3_database
-> _int))
;; ----------------------------------------
#|

View File

@ -26,17 +26,15 @@ native client library is required.}
@item{@bold{@as-index{@hyperlink["http://www.sqlite.org"]{SQLite}} version
3.} The SQLite native client library is required; see
@secref["sqlite3-native-libs"].}
@secref["sqlite3-requirements"].}
@item{@bold{@as-index{ODBC}.} An ODBC Driver Manager and appropriate
ODBC drivers are required; see @secref["odbc-native-libs"]. The
following additional database systems are known to work with this
library's ODBC support (see @secref["odbc-status"] for details):
@itemlist[
@item{@bold{@as-index{@hyperlink["http://www.oracle.com"]{Oracle}}}}
@item{@bold{@as-index{@hyperlink["http://www.ibm.com/software/data/db2/"]{DB2}}}}
@item{@bold{@as-index{@hyperlink["http://www.microsoft.com/sqlserver/"]{SQL Server}}}}
]}
ODBC drivers are required; see @secref["odbc-requirements"]. The
following database systems are known to work with this library via
ODBC (see @secref["odbc-status"] for details):
@bold{@as-index{@hyperlink["http://www.ibm.com/software/data/db2/"]{DB2}}},
@bold{@as-index{@hyperlink["http://www.oracle.com"]{Oracle}}}, and
@bold{@as-index{@hyperlink["http://www.microsoft.com/sqlserver/"]{SQL Server}}}.}
]
The query operations are functional in spirit: queries return results

View File

@ -4,25 +4,27 @@
scribble/struct
racket/sandbox
"config.rkt"
(for-label db))
(for-label db
setup/dirs))
@title[#:tag "notes"]{Notes}
This section describes miscellaneous issues.
This section discusses issues related to specific database systems.
@section[#:tag "connecting-to-server"]{Local Sockets for PostgreSQL and MySQL Servers}
PostgreSQL and MySQL servers are sometimes configured by default to
listen only on local sockets (also called ``unix domain
sockets''). This library provides support for communication over local
sockets, but only on Linux (x86 and x86-64) and Mac OS X. If local
socket communication is not available, the server must be reconfigured
to listen on a TCP port.
sockets on Linux (x86 and x86-64) and Mac OS X. If local socket
communication is not available, the server must be reconfigured to
listen on a TCP port.
The socket file for a PostgreSQL server is located in the directory
specified by the @tt{unix_socket_directory} variable in the
@tt{postgresql.conf} server configuration file. For example, on
Ubuntu 10.10 running PostgreSQL 8.4, the socket directory is
Ubuntu 11.04 running PostgreSQL 8.4, the socket directory is
@tt{/var/run/postgresql} and the socket file is
@tt{/var/run/postgresql/.s.PGSQL.5432}. Common socket paths may be
searched automatically using the @racket[postgresql-guess-socket-path]
@ -30,20 +32,19 @@ function.
The socket file for a MySQL server is located at the path specified by
the @tt{socket} variable in the @tt{my.cnf} configuration file. For
example, on Ubuntu 10.10 running MySQL 5.1, the socket is located at
example, on Ubuntu 11.04 running MySQL 5.1, the socket is located at
@tt{/var/run/mysqld/mysqld.sock}. Common socket paths for MySQL can be
searched using the @racket[mysql-guess-socket-path] function.
@section{Database Character Encodings}
@section{PostgreSQL Database Character Encoding}
In most cases, a PostgreSQL or MySQL database's character encoding is
irrelevant, since the connect function always requests translation to
Unicode (UTF-8) when creating a connection. If a PostgreSQL database's
character encoding is @tt{SQL_ASCII}, however, PostgreSQL will not
honor the connection encoding; it will instead send untranslated
octets, which will cause corrupt data or internal errors in the client
connection.
In most cases, a database's character encoding is irrelevant, since
the connect function always requests translation to Unicode (UTF-8)
when creating a connection. If a PostgreSQL database's character
encoding is @tt{SQL_ASCII}, however, PostgreSQL will not honor the
connection encoding; it will instead send untranslated octets, which
will cause corrupt data or internal errors in the client connection.
To convert a PostgreSQL database from @tt{SQL_ASCII} to something
sensible, @tt{pg_dump} the database, recode the dump file (using a
@ -51,31 +52,17 @@ utility such as @tt{iconv}), create a new database with the desired
encoding, and @tt{pg_restore} from the recoded dump file.
@section{Prepared Query Parameter Types}
Different database systems vary in their handling of query parameter
types. For example, consider the following parameterized SQL
statement:
@tt{SELECT 1 + ?;}
PostgreSQL reports an expected type of @tt{integer} for the parameter and
will not accept other types. MySQL and SQLite, in contrast, report no
useful parameter type information, and ODBC connections vary in
behavior based on the driver, the data source configuration, and the
connection parameters (see @secref["odbc-status"] for specific notes).
@section{PostgreSQL Authentication}
PostgreSQL supports a large variety of authentication mechanisms,
controlled by the @tt{pg_hba.conf} server configuration file. This
library currently supports only cleartext and md5-hashed passwords,
and it does not send cleartext passwords unless explicitly ordered to
(see @racket[postgresql-connect]). These correspond to the @tt{md5}
and @tt{password} authentication methods in the parlance of
PostgreSQL supports a large variety of
@hyperlink["http://www.postgresql.org/docs/8.4/static/auth-pg-hba-conf.html"]{authentication
mechanisms}, controlled by the @tt{pg_hba.conf} server configuration
file. This library currently supports only cleartext and md5-hashed
passwords, and it does not send cleartext passwords unless explicitly
ordered to (see @racket[postgresql-connect]). These correspond to the
@tt{md5} and @tt{password} authentication methods in the parlance of
@tt{pg_hba.conf}, respectively. On Linux, @tt{ident} authentication is
automatically supported for unix domain sockets (but not TCP). The
automatically supported for local sockets, but not TCP sockets. The
@tt{gss}, @tt{sspi}, @tt{krb5}, @tt{pam}, and @tt{ldap} methods are
not supported.
@ -89,36 +76,69 @@ plugins}. The only plugin currently supported by this library is
password authentication mechanism used since version 4.1.
@section[#:tag "sqlite3-native-libs"]{SQLite Native Library}
@section[#:tag "sqlite3-requirements"]{SQLite Requirements}
SQLite support requires the appropriate native library, specifically
@tt{libsqlite3.so.0} on Unix or @tt{sqlite3.dll} on Windows.
SQLite support requires the appropriate native library.
@itemlist[
@item{On Windows, the library is @tt{sqlite3.dll}. It can be obtained
from @hyperlink["http://www.sqlite.org/download.html"]{the SQLite
download page}; the DLL file should be extracted and placed into one
of the directories produced by
@racketblock[(begin (require setup/dirs) (get-lib-search-dirs))]}
@item{On Mac OS X, the library is @tt{libsqlite3.0.dylib}, which is
included (in @tt{/usr/lib}) in Mac OS X version 10.4 onwards.}
@item{On Linux, the library is @tt{libsqlite3.so.0}. It is included in
the @tt{libsqlite3-0} package in Debian/Ubuntu and in the @tt{sqlite}
package in Red Hat.}
]
@section[#:tag "odbc-native-libs"]{ODBC Native Libraries}
@section[#:tag "odbc-requirements"]{ODBC Requirements}
ODBC support requires the appropriate native library, specifically
@tt{libodbc.so.1} (from unixODBC; iODBC is not supported) on Unix or
@tt{odbc32.dll} on Windows. In addition, the appropriate ODBC Drivers
must be installed and any Data Sources configured.
ODBC requires the appropriate driver manager native library as well as
driver native libraries for each database system you want use ODBC to
connect to.
@itemlist[
@item{On Windows, the driver manager is @tt{odbc32.dll}, which is
included automatically with Windows.}
@item{On Mac OS X, the driver manager is @tt{libiodbc.2.dylib}
(@hyperlink["http://www.iodbc.org"]{iODBC}), which is included (in
@tt{/usr/lib}) in Mac OS X version 10.2 onwards.}
@item{On Linux, the driver manager is @tt{libodbc.so.1}
(@hyperlink["http://www.unixodbc.org"]{unixODBC}---iODBC is not
supported). It is available from the @tt{unixodbc} package in
Debian/Ubuntu and in the @tt{unixODBC} package in Red Hat.}
]
In addition, you must install the appropriate ODBC Drivers and
configure Data Sources. Refer to the ODBC documentation for the
specific database system for more information.
@section[#:tag "odbc-status"]{ODBC Support Status}
@section[#:tag "odbc-status"]{ODBC Status}
ODBC support is experimental. This library is compatible only with
ODBC 3.x Driver Managers. The behavior of ODBC connections can vary
widely depending on the driver in use and even the configuration of a
particular data source.
ODBC support is experimental. The behavior of ODBC connections can
vary widely depending on the driver in use and even the configuration
of a particular data source.
The following sections describe the configurations that this library
has been tested with. The platform @bold{win32} means Windows Vista on
a 32-bit processor and @bold{linux} means Ubuntu 11.04 and unixODBC on
both x86 (32-bit) and x86-64 processors, unless otherwise
specified. The iODBC Driver Manager is not supported.
has been tested with.
Reports of success or failure on other platforms or with other drivers
would be appreciated.
@;{
** There's no reason to actually use the following drivers. They're just
** useful for testing ODBC support.
@subsection{PostgreSQL ODBC Driver}
The PostgreSQL ODBC driver version 09.00.0300 has been tested on
@ -149,15 +169,18 @@ Furthermore, this driver interprets the declared types of columns
strictly, replacing nonconforming values in query results with
@tt{NULL}. All computed columns, even those with explicit @tt{CAST}s,
seem to be returned as @tt{text}.
}
@subsection{DB2 ODBC Driver}
The driver from IBM DB2 Express-C v9.7 has been tested on @bold{linux}
The driver from IBM DB2 Express-C v9.7 has been tested on Ubuntu 11.04
(32-bit only).
For a typical installation where the instance resides at
@tt{/home/db2inst1}, set the following option in the Driver
configuration: @tt{Driver = /home/db2inst1/sqllib/lib32/libdb2.so}.
configuration: @tt{Driver =
/home/db2inst1/sqllib/lib32/libdb2.so}. (The path would presumably be
different for a 64-bit installation.)
The DB2 driver does not seem to accept a separate argument for the
database to connect to; it must be the same as the Data Source name.
@ -165,7 +188,7 @@ database to connect to; it must be the same as the Data Source name.
@subsection{Oracle ODBC Driver}
The driver from Oracle Database 10g Release 2 Express Edition has been
tested on @bold{linux} (32-bit only).
tested on Ubuntu 11.04 (32-bit only).
It seems the @tt{ORACLE_HOME} and @tt{LD_LIBRARY_PATH} environment
variables must be set according to the @tt{oracle_env.{csh,sh}} script
@ -185,5 +208,5 @@ Maybe Oracle bug? See:
@subsection{SQL Server ODBC Driver}
Basic SQL Server support has been verified on @bold{win32}, but the
automated test suite has not yet been adapted and run.
Basic SQL Server support has been verified on Windows (32-bit only),
but the automated test suite has not yet been adapted and run.