2
0
Fork 0
mirror of git://git.savannah.gnu.org/guix/data-service.git synced 2023-12-14 03:23:03 +01:00

Hack better NULL support on to (squee)

PQgetvalue used by squee returns null values as empty strings, which are
ambiguous for string fields. Therefore, use PQgetisnull to implement a
serialiser for squee which checks empty strings to see if they're actually a
NULL value, then returns '() in this case.

exec-query-with-null-handling can be used to access this behaviour.
This commit is contained in:
Christopher Baines 2019-09-04 12:52:12 +02:00
parent 902560d56b
commit 1441942200

View file

@ -16,12 +16,15 @@
;;; <http://www.gnu.org/licenses/>.
(define-module (guix-data-service database)
#:use-module (system foreign)
#:use-module (squee)
#:export (with-postgresql-connection
with-postgresql-transaction
with-advisory-session-lock
obtain-advisory-transaction-lock))
obtain-advisory-transaction-lock
exec-query-with-null-handling))
;; TODO This isn't exported for some reason
(define pg-conn-finish
@ -80,3 +83,36 @@
(exec-query conn
"SELECT pg_advisory_xact_lock($1)"
(list lock-number))))
(define squee/libpq
(@@ (squee) libpq))
(define squee/unwrap-result-ptr
(@@ (squee) unwrap-result-ptr))
(define %PQgetisnull
(pointer->procedure int
(dynamic-func "PQgetisnull" squee/libpq)
(list '* int int)))
(define (result-serializer-simple-list-with-null-handling result-ptr)
"Get a simple list of lists representing the result of the query"
(let ((rows-range (iota (result-num-rows result-ptr)))
(cols-range (iota (result-num-cols result-ptr))))
(map
(lambda (row-i)
(map
(lambda (col-i)
(let ((val (result-get-value result-ptr row-i col-i)))
(if (string-null? val)
(if (eq? 1 (%PQgetisnull
(squee/unwrap-result-ptr result-ptr) row-i col-i))
'()
val)
val)))
cols-range))
rows-range)))
(define* (exec-query-with-null-handling pg-conn command #:optional (params '()))
(exec-query pg-conn command params
#:serializer result-serializer-simple-list-with-null-handling))