Skip to content

Commit

Permalink
Merge pull request #314 from sabracrolleton/master
Browse files Browse the repository at this point in the history
Expand ability to use lists in parameterized queries and s-sql
  • Loading branch information
sabracrolleton committed Nov 27, 2022
2 parents 8a52e13 + c9f704f commit 9f1af39
Show file tree
Hide file tree
Showing 23 changed files with 2,457 additions and 1,864 deletions.
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
# Changelog 1.33.7
Changes in cl-postgres and s-sql to allow use of plain proper lists in parameterized queries. Previously only vectors could be used. The following show examples using both vectors and lists in queries using both raw sql and s-sql.
```lisp
(query "select name from employee where id = any($1)"
#(1 3 4))
(query "select name from employee where id = any($1)"
'(1 3 4))
(let ((emp-ids #(1 2)))
(query "select name from employee where id = any($1)"
emp-ids))
(let ((emp-ids '(1 2)))
(query "select name from employee where id = any($1)"
emp-ids))
(query (:select 'name :from 'employee :where (:= 'id (:any* '$1)))
#(1 3) :column)
'("Jason" "Celia")
(query (:select 'name :from 'employee :where (:= 'id (:any* '$1)))
'(1 3) :column)
'("Jason" "Celia")
```

Plain proper lists can also now be used in s-sql queries using :in. Previously you needed to use :set
```lisp
(query (:select 'name :from 'employee :where (:in 'id (:set 1 3 4))))
'(("Jason") ("Celia") ("Linda"))
```
Now you can also provide a list.
```lisp
(let ((emp-ids '(1 2)))
(query (:select 'name :from 'employee :where (:in 'id emp-ids))))
(("Jason") ("Robert"))
```

# Changelog 1.33.6
Postmodern/cl-postgres now returns an empty array if Postgresql returns an empty array.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A Common Lisp PostgreSQL programming interface

---

Version 1.33.5
Version 1.33.7

Postmodern is a Common Lisp library for interacting with [PostgreSQL](http://www.postgresql.org) databases. It is under active development. Features are:

Expand Down
2 changes: 1 addition & 1 deletion cl-postgres.asd
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
:author "Marijn Haverbeke <marijnh@gmail.com>"
:maintainer "Sabra Crolleton <sabra.crolleton@gmail.com>"
:license "zlib"
:version "1.33.6"
:version "1.33.7"
:depends-on ("md5" "split-sequence" "ironclad" "cl-base64" "uax-15"
(:feature (:or :allegro :ccl :clisp :genera
:armedbear :cmucl :lispworks)
Expand Down
14 changes: 13 additions & 1 deletion cl-postgres/sql-string.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ You can define to-sql-string methods for your own datatypes if you want to be
able to pass them to exec-prepared. When a non-NIL second value is returned,
this may be T to indicate that the first value should simply be escaped as a
string, or a second string providing a type prefix for the value. (This is
used by S-SQL.)")
different from s-sql::to-s-sql-string only in the handling of cons lists.")
(:method ((arg string))
(values arg t))
(:method ((arg vector))
Expand All @@ -98,6 +98,18 @@ used by S-SQL.)")
(if escape (write-quoted string out) (write-string string out))))
(write-char #\} out))
t)))
(:method ((arg cons)) ;lists, but not nil
(if (alexandria:proper-list-p arg)
(values
(with-output-to-string (out)
(write-char #\{ out)
(loop :for sep := "" :then #\, :for x :in arg :do
(princ sep out)
(multiple-value-bind (string escape) (to-sql-string x)
(if escape (write-quoted string out) (write-string string out))))
(write-char #\} out))
t)
(error "Value ~S can not be converted to an SQL literal." arg)))
(:method ((arg array))
(values
(with-output-to-string (out)
Expand Down
35 changes: 32 additions & 3 deletions cl-postgres/tests/tests.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,36 @@ variables:~:{~% ~A: ~(~A~), ~:[defaults to \"~A\"~;~:*provided \"~A\"~]~}~%"
(is (eql d t))
(is (eql e 9/2)))))

(test sql-strings
(test to-sql-strings
(is (string= (to-sql-string :null) "NULL"))
(is (string= (to-sql-string t) "true"))
(is (string= (cl-postgres:to-sql-string '())
"false"))
(is (string= (cl-postgres:to-sql-string nil)
"false"))
(is (string= (cl-postgres:to-sql-string (list))
"false"))
(is (string= (to-sql-string 400) "400"))
(is (string= (to-sql-string 4.01) "4.01"))
(is (string= (to-sql-string "foo") "foo"))
(is (eq t (nth-value 1 (to-sql-string "bar"))))
(is (eq nil (nth-value 1 (to-sql-string 10)))))
(is (eq nil (nth-value 1 (to-sql-string 10))))
(is (string= (to-sql-string #("alpha" "beta"))
"{\"alpha\",\"beta\"}"))
(is (string= (to-sql-string '("alpha" "beta"))
"{\"alpha\",\"beta\"}"))
(signals error (cl-postgres:to-sql-string '(a . b)))
(signals error (cl-postgres:to-sql-string '(a b)))
(is (string= (cl-postgres:to-sql-string '(1 2))
"{1,2}"))
(is (string= (cl-postgres:to-sql-string '(1.3 -2.83))
"{1.3,-2.83}"))
(is (string= (cl-postgres:to-sql-string #(1.3 -2.83))
"{1.3,-2.83}"))
(is (string= (cl-postgres:to-sql-string 1/3)
"0.3333333333333333333333333333333333333"))
(is (string= (cl-postgres:to-sql-string #(#(1 2) #(1.3 -2.83)))
"{\"{1,2}\",\"{1.3,-2.83}\"}")))

(test date-query
(with-default-readtable
Expand Down Expand Up @@ -239,7 +262,13 @@ variables:~:{~% ~A: ~(~A~), ~:[defaults to \"~A\"~;~:*provided \"~A\"~]~}~%"
'((42 nil "foo"))))
(prepare-query connection "test4" "select $1")
(is (equal (exec-prepared connection "test4" '(42) 'list-row-reader)
'(("42"))))))
'(("42"))))
(exec-query connection "create table if not exists cl_postgres_employees (id integer, name text)")
(exec-query connection "insert into cl_postgres_employees (id,name) values (1,'Jason'),(2, 'Robert'),(3,'Celia'),(4,'Karen')")
(prepare-query connection "t15" "SELECT name FROM cl_postgres_employees WHERE (id = ANY($1))")
(is (equal (exec-prepared connection "t15" '((1 2 3)) 'list-row-reader)
'(("Jason") ("Robert") ("Celia"))))
(exec-query connection "drop table cl_postgres_employees")))

(test unprepare-query
(with-test-connection
Expand Down
Loading

0 comments on commit 9f1af39

Please sign in to comment.