Hi again,
Thanks for the fix and the new release, Marijn. I think I found another problem.
When I try to query with a prepared statement with the QUERY macro, and one of the arguments to the statement is the result of another QUERY macro (whether directly or from the result of a function), strange things crop up. In one instance, the inner QUERY was returning nil where it would return the expected integer otherwise. Here's an isolated case:
(postmodern:query "select cast ($1 as int)" (let ((foo (postmodern:query "select 12" :single))) (format t "result: ~S~%" foo) foo))
This gives me the expected message "result: 12", but also signals a condition, "Database error: Incorrect number of parameters given for prepared statement ."
Below is the complete macroexpansion of the above form (without LET and FORMAT).
(PROGN (CL-POSTGRES:PREPARE-QUERY POSTMODERN:*DATABASE* "" "select cast ($1 as int)") (CL-POSTGRES:EXEC-PREPARED POSTMODERN:*DATABASE* "" (MAPCAR 'S-SQL:SQL-IZE (LIST (CAR (CL-POSTGRES:EXEC-QUERY POSTMODERN:*DATABASE* "select 12" 'POSTMODERN::COLUMN-ROW-READER)))) 'CL-POSTGRES:LIST-ROW-READER))
The sequence of evaluation is PREPARE-QUERY, then EXEC-QUERY (for the inner "select 12"), then EXEC-PREPARED. I guessed that doing things with the database in-between PREPARE-QUERY and EXEC-PREPARED might be the problem, so I modified QUERY to evaluate prepared-statement arguments before PREPARE-QUERY. This allows the inner query to complete before the outer one actually starts.
diff -urNx '*~' postmodern-1.02/postmodern/query.lisp postmodern-1.02-modified/postmodern/query.lisp --- postmodern-1.02/postmodern/query.lisp 2007-07-25 04:10:42.000000000 -0700 +++ postmodern-1.02-modified/postmodern/query.lisp 2007-07-27 23:03:16.000000000 -0700 @@ -55,9 +55,10 @@ :else :collect arg))) (destructuring-bind (reader single-row) (cdr (assoc format *result-styles*)) (let ((base (if args - `(progn - (prepare-query *database* "" ,(real-query query)) - (exec-prepared *database* "" (mapcar 'sql-ize (list ,@args)) ',reader)) + (let ((arg-values (gensym))) + `(let ((,arg-values (mapcar 'sql-ize (list ,@args)))) + (prepare-query *database* "" ,(real-query query)) + (exec-prepared *database* "" ,arg-values ',reader))) `(exec-query *database* ,(real-query query) ',reader)))) (if single-row `(multiple-value-call 'car-of-first-value ,base)
Now my first example works, as does the result of one prepared-statement QUERY's being indirectly nested in another prepared-statement QUERY.