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&#174; 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