Re: Bedlam wishlist? (was: New release - Library of code for SISC - Bedlam)
Igor Hjelmstrom Vinhas Ribeiro <[email protected]> Sat, 10 Apr 2010 16:34:00 -0300
| Newsgroups | gmane.comp.java.sisc.user |
|---|---|
| Message-ID | <[email protected]> |
Hi! Johannes, I didn't know about this improved driver - thank you for your email. I see that you implemented loading from csv - which is helpful but not enough for all my use-cases. So I would probably start by creating a slightly different version that loads from other sources... Do you want me to include your code in bedlam unchanged together with the patched PostgreSQL-JDBC-Driver (if that is the case please send me the entire code and let me know the license - GPL2/MIT/etc are all good enough for inclusion)? Or is there anything else that would need to be implemented before that? I will do my best to help - but just let me know if I understood your request correctly Best regards, Igor. On Thu, Apr 8, 2010 at 06:45, Johannes Bruegmann <[email protected]> wro= te: > Hello, > > may I =A0ask wether there =A0exists a "wishlist" =A0for bedlam? If so, ma= y I > ask for the following feature? > > There is a special PostgreSQL-JDBC-Driver at > > http://kato.iki.fi/sw/db/postgresql/jdbc/copy/ > > I use the JDBC3-Postresql 8.1+8.3 Version. > > It uses the COPY from/into feature =A0of PostgreSQL. Since INSERT can be > very slow for =A0large data, this is =A0a very efficient interface to copy > data into db =A0or from db. From what =A0i know, this driver only =A0exte= nds > the =A0jdbc-interface =A0and =A0does no further =A0 changes. =A0So it =A0= should be > compliant to the other stuff. > > I =A0have written some poor =A0man code for =A0that driver (maybe some pa= rts > are missing here, it is here just for illustration -- if wished, i can > distribute it in full for writing a nicer interface or the like). > > The READ-TABLE and COPY-SELECT functionality are a little bit limited, > because they depend =A0on procedures MAKE-CSV-READER and CSV->LIST which > are =A0taken =A0 =A0 from =A0Neil =A0 =A0Van =A0Dyke's =A0 cvs-scm =A0 = =A0 =A0(see here[tm]: > http://www.neilvandyke.org/csv-scheme/) utilities =A0(version at date of > writing was 0.5), but taken all =A0that into account COPY-SELECT (should > be called make-copy-select) often is =A0still =A0faster than using =A0nor= mal > JDBC-SELECT: > > (let* ((qrows "SELECT count(*)::INT FROM points") > =A0 =A0 =A0 =A0 (convrows (lambda (access-field) (access-field 1))) > =A0 =A0 =A0 =A0 (q "SELECT lcd, clid, tcd, stcd, junctionnumber as jno, r= nid, n1id, n2id, seg_lcd FROM points") > =A0 =A0 =A0 =A0 (conv (lambda (access-field) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (let ((lcd (access-field "lcd")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (clid (access-field "clid")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (tcd (access-field "tcd")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (stcd (access-field "stcd")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (jno (access-field "jno")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (rnid (access-field "rnid")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (n1id (access-field "n1id")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (n2id (access-field "n2id")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (seg-lcd (access-field "seg_l= cd"))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (list lcd clid tcd stcd jno rnid n1id= n2id seg-lcd)))) > =A0 =A0 =A0 =A0 (select-rows (jdbc/make-sql-select qrows convrows)) > =A0 =A0 =A0 =A0 (select-points1 (jdbc/make-sql-select q conv)) > =A0 =A0 =A0 =A0 (select-points2 (copy-select q conv))) > =A0 =A0(jdbc/with-connection (db-connect) > =A0 =A0 =A0(lambda (conn) > =A0 =A0 =A0 =A0(let ((rows (select-rows conn)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0(t1 (cadr (time (select-points1 conn)))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0(t2 (cadr (time (select-points2 conn))))) > =A0 =A0 =A0 =A0 =A0(display "Number of rows: ") (display (car rows)) (new= line) > =A0 =A0 =A0 =A0 =A0(display (format "JDBC-SELECT: ~a ms\nCOPY-SELECT: ~a = ms\n" (car t1) (car t2))))))) > > =3D=3D=3D> > > Number of rows: 28531 > JDBC-SELECT: 23966 ms > COPY-SELECT: 13352 ms > > The WRITE-TABLE stuff should be many times faster than INSERT. > > All this is only a suggestion, "wishes and hopes". Feel free to ignore > it silently. Or ask if there is something missing below. > > Thank you for the bedlam stuff. > > Regards, > Johannes Br=FCgmann > > -------------------------------------------------------------------------= ----- > Code: > > (define-java-classes > =A0<java.sql.connection> > =A0<java.sql.prepared-statement> > =A0<java.sql.result-set> > =A0<java.sql.driver-manager> > =A0<java.sql.types> > =A0<org.postgresql.copy.copy-manager>) > > ;;;@args : proc -> conn -> (proc conn) > ;;;taken from siscweb/jdbc > ;;;executes (proc conn) inside an transaction > (define (jdbc/call-with-transaction proc) > =A0(lambda (conn) > =A0 =A0(let ((jac (get-auto-commit conn))) > =A0 =A0 =A0(dynamic-wind > =A0 =A0 =A0 =A0 =A0(lambda () > =A0 =A0 =A0 =A0 =A0 =A0(set-auto-commit conn (->jboolean #f))) > =A0 =A0 =A0 =A0 =A0(lambda () > =A0 =A0 =A0 =A0 =A0 =A0(with/fc > =A0 =A0 =A0 =A0 =A0 =A0 (lambda (m e) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 (rollback conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 (throw m e)) > =A0 =A0 =A0 =A0 =A0 =A0 (lambda () > =A0 =A0 =A0 =A0 =A0 =A0 =A0 (let ((result (proc conn))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (commit conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 result)))) > =A0 =A0 =A0 =A0 =A0(lambda () > =A0 =A0 =A0 =A0 =A0 =A0(set-auto-commit conn jac)))))) > > ;;;@args : query input-port -> conn -> number-of-rows-affected > ;;;copy bulk data into a database object using @code{COPY} > ;;;the driver has to support that feature, for PostgreSQL there exists a = patched jar-file > ;;;if PostgreSQL server version < 8.2 this procedure returns @code{-1} ot= herwise the number of copied rows > (define (jdbc/copy-into-db query input-port) > =A0(lambda (conn) > =A0 =A0(let ((jinp (->jinput-stream input-port)) > =A0 =A0 =A0 =A0 =A0(jsql (->jstring query))) > =A0 =A0 =A0(let ((call-with-transaction > =A0 =A0 =A0 =A0 =A0 =A0 (jdbc/call-with-transaction (lambda (conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 (let* ((cm (java-new <org.postgresql.copy.copy-manager> conn)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0(num-of-rows-copied (copy-into-db cm jsql jinp))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 (->number num-of-rows-copied)))))) > =A0 =A0 =A0 =A0(call-with-transaction conn))))) > > ;;;@args : query output-port -> conn -> number-of-rows-copied > ;;;copy bulk data out of a database object using @code{COPY} > ;;;the driver has to support that feature, for PostgreSQL there exists a = patched jar-file > ;;;if PostgreSQL server version < 8.2 this procedure returns @code{-1} ot= herwise the number of copied rows > (define (jdbc/copy-from-db query output-port) > =A0(lambda (conn) > =A0 =A0(let ((joutp (->joutput-stream output-port)) > =A0 =A0 =A0 =A0 =A0(jsql (->jstring query))) > =A0 =A0 =A0(let ((call-with-transaction > =A0 =A0 =A0 =A0 =A0 =A0 (jdbc/call-with-transaction (lambda (conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 (let* ((cm (java-new <org.postgresql.copy.copy-manager> conn)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0(num-of-rows-copied (copy-from-db cm jsql joutp)= )) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 (->number num-of-rows-copied)))))) > =A0 =A0 =A0 =A0(call-with-transaction conn))))) > > ;;;@body > ;;;code token from @uref{http://sisc.cvs.sourceforge.net/sisc/contrib/pur= e-scheme/jdbc.scm} > (define (list-index/copy-select ls e) > =A0(cond [(null? ls) #f] > =A0 =A0 =A0 =A0[(equal? (car ls) e) 0] > =A0 =A0 =A0 =A0[else (+ 1 (list-index/copy-select (cdr ls) e))])) > > ;;;@args : delim qmark -> list-of-list-of-fields -> input-port > ;;;generates a @code{write-csv}-procedure which takes a list of list > ;;;of fields converts and concats them into a string, and displays > ;;;that string on an buffered-output-port. After the buffer is filled > ;;;with all lines it is opened for read and the input port is returned. > (define (make-write-csv delim qmark) > =A0(let ((write-csv-line (make-write-csv-line delim qmark))) > =A0 =A0(lambda (list-of-list-of-fields) > =A0 =A0 =A0(let ((dump-lines (lambda (output-port) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((char-output-por= t (open-character-output-port output-port))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(for-each (lambda = (fields) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0(let ((line (write-csv-line fields))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0(display line char-output-port) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0(newline char-output-port))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0list-of-list-of-fields) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(display "\\." cha= r-output-port) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(newline char-outp= ut-port) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(flush-output-port= char-output-port)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0output-port))) > =A0 =A0 =A0 =A0(let ((buffer (call-with-output-buffer dump-lines))) > =A0 =A0 =A0 =A0 =A0(let ((inp (open-input-buffer buffer))) > =A0 =A0 =A0 =A0 =A0 =A0inp)))))) > > ;;;args : table-expr list-of-list-of-fields -> connection -> num-of-rows-= affected > ;;;Writes @var{list-of-list-of-fiels} linewise into > ;;;@var{table-expr}. Upon successful completion the number of rows > ;;;written is returned (see @code{jdbc/copy-into-db}). > (define (write-table table-expr list-of-list-of-fields) > =A0(lambda (conn) > =A0 =A0(let ((query (string-append "COPY " table-expr " FROM STDIN WITH N= ULL AS 'SQL-NULL' CSV DELIMITER ';' QUOTE '\"'")) > =A0 =A0 =A0 =A0 =A0(write-csv (make-write-csv ";" "\""))) > =A0 =A0 =A0(let ((input-port (write-csv list-of-list-of-fields))) > =A0 =A0 =A0 =A0(let ((really-copy (jdbc/copy-into-db query input-port))) > =A0 =A0 =A0 =A0 =A0(really-copy conn)))))) > > (define (make-read-csv-row delim qmark) > =A0(lambda (inp) > =A0 =A0(make-csv-reader inp `((separator-chars . (,(car (string->list del= im)))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (quote-char . ,(car (= string->list qmark))))))) > > ;;;@args : delim qmark -> output-port -> list-of-list-of-fields > ;;;generates a @code{read-csv}-procedure which takes an > ;;;@code{buffered-output-port} as argument that receives the buffer of > ;;;the attached @code{buffered-output-port}, opens an > ;;;@code{buffered-input-port} upon that buffer, reads this buffer > ;;;linewise for csv-data, returns each line parsed into fields as list > ;;;of fields, and returns all lines as resulting list. > (define (make-read-csv delim qmark) > =A0(let ((read-csv-row (make-read-csv-row delim qmark))) > =A0 =A0(lambda (output-port) > =A0 =A0 =A0(let ((dump-fields (lambda (input-port) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (let ((char-input-por= t (open-character-input-port input-port))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (let ((next-row (= read-csv-row char-input-port))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (csv->list ne= xt-row))))) > =A0 =A0 =A0 =A0 =A0 =A0(buffer (get-output-buffer output-port))) > =A0 =A0 =A0 =A0 =A0(let ((vals-list (call-with-input-buffer buffer dump-f= ields))) > =A0 =A0 =A0 =A0 =A0 =A0vals-list))))) > > ;;;@args : table-expr conv -> connection -> list-of-list-of-fields > ;;;Reads @var{table-expr} and returns content as list of list of > ;;;fields, where each field has type string, where @var{conv} is: > ;;;@lisp > ;;; conv: col-spec -> col-value > ;;;@end lisp > ;;;code partially derived from @uref{http://sisc.cvs.sourceforge.net/sisc= /contrib/pure-scheme/jdbc.scm} > (define (read-table table-expr conv) > =A0(lambda (conn) > =A0 =A0(let* ((tre (posix-string->regexp "^[ ]*\([a-zA-Z0-9_]\+\).*")) > =A0 =A0 =A0 =A0 =A0 (tname (regexp-substitute/global #f tre table-expr 'p= re 1 'post)) > =A0 =A0 =A0 =A0 =A0 (fre (posix-string->regexp "^[ ]*[a-zA-Z0-9_]\+[ ]*[(= ]\([^)]\+\)[)]")) > =A0 =A0 =A0 =A0 =A0 (fnames (if (not (regexp-search fre table-expr)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "*" > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (regexp-substitute/global #f = fre table-expr 'pre 1 'post))) > =A0 =A0 =A0 =A0 =A0 (query-md (string-append "SELECT " fnames " FROM " tn= ame " LIMIT 1")) > =A0 =A0 =A0 =A0 =A0 (stmt (jdbc/prepare-statement conn query-md #f)) > =A0 =A0 =A0 =A0 =A0 (rs (execute-query stmt)) > =A0 =A0 =A0 =A0 =A0 (md (get-meta-data rs)) > =A0 =A0 =A0 =A0 =A0 (cc (->number (get-column-count md))) > =A0 =A0 =A0 =A0 =A0 (cn (map (lambda (i) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(->string (get-column-label md= (->jint i)))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(cdr (iota (+ cc 1)))))) > =A0 =A0 =A0(let ((types-conv (map (lambda (t) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (cdr (assoc (= ->number (get-column-type md (->jint (+ t 1)))) type-conversions/copy-selec= t))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (iota cc)))) > =A0 =A0 =A0 =A0(let ((access-row (lambda (row) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(lambda (field-id) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let* ((field-= pos (cond ((number? field-id) field-id) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0((string? field-id) (+ (list-index/copy-= select cn field-id) 1)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(else (error "columns are indexed by pos= itive non-zero integers and by field-name strings.")))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (= conv-record (list-ref types-conv (- field-pos 1)))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(if (or (n= ull? conv-record) (java-null? conv-record)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0'() > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(c= onv-record (list-ref row (- field-pos 1))))))))) > =A0 =A0 =A0 =A0 =A0(let ((query (string-append "COPY " table-expr " TO ST= DOUT WITH NULL AS 'NULL' CSV DELIMITER ';' QUOTE '\"'")) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(read-csv (make-read-csv ";" "\""))) > =A0 =A0 =A0 =A0 =A0 =A0(let ((output-port (open-output-buffer))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((really-copy (jdbc/copy-from-db query ou= tput-port))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(really-copy conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((rows (read-csv output-port)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(inc (lambda (x) (+ x 1)))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(map (lambda (row) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (conv (access-row row))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rows)))))))))) > > > ;;;@args : query conv -> connection -> list-of-list-of-fields > ;;;Reads @var{query} and returns content as list of list of > ;;;fields, where each field has type string, where @var{conv} is: > ;;;@lisp > ;;; conv: col-spec -> col-value > ;;;@end lisp > (define (copy-select query conv) > =A0(lambda (conn) > =A0 =A0(let ((tname (string-append "tmp_copy_select"))) > =A0 =A0 =A0(let ((call-with-transaction > =A0 =A0 =A0 =A0 =A0 =A0 (jdbc/call-with-transaction > =A0 =A0 =A0 =A0 =A0 =A0 =A0(lambda (conn) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((create-temp-table (string-append "C= REATE TEMP TABLE " tname " AS " query)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(drop-temp-table (string-appen= d "DROP TABLE " tname))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(dynamic-wind > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(lambda () > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((create-temp-tab= le/stmt (jdbc/prepare-statement conn create-temp-table #f))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(jdbc/execute-upda= te create-temp-table/stmt))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(lambda () > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let* ((really-read-ta= ble (read-table tname conv)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (rows (re= ally-read-table conn))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0rows)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(lambda () > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(let ((drop-temp-table= /stmt (jdbc/prepare-statement conn drop-temp-table #f))) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(jdbc/execute-upda= te drop-temp-table/stmt))))))))) > =A0 =A0 =A0 =A0(call-with-transaction conn))))) > > > -- > =A0 =A0 =A0 If =A0we confess our sins, he is faithful and just to forgive= us our sins > =A0 =A0 =A0 and to cleanse us from all unrighteousness. > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 1 John 1:9 (ESV) > ---------------------------------------------------------------------------= --- Download Intel® Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev