#lang scheme/base
(require (planet bzlib/base)
(planet bzlib/template/iqs)
"base.ss"
(prefix-in s: srfi/19)
)
(define (make-place-holder-query converter s)
(define (helper lst)
(make-phq s (iqs-convert lst converter '())
(filter symbol? lst)))
(parameterize ((iqs-symbol-start #\?))
(helper (read-iqs (open-input-string s)))))
(define (default-converter args)
(let ((i 0))
(lambda (s)
(set! i (add1 i))
(format "$~a" i))))
(define (question-converter args)
(lambda (s) "?"))
(define (phq-map-values phq value
(mapper
(lambda (lst value)
(map (lambda (key)
(if-it (assoc key value)
(cdr it)
(error 'phq-map-values "missing key ~a" key)))
lst))))
(mapper (phq-args phq) value))
(define (sql-escape-string x)
(string-append "'"
(regexp-replace* #px"\\'" x "''")
"'"))
(define (data->string x)
(cond ((null? x) "NULL")
((number? x) (number->string x))
((s:date? x) (sql-escape-string (s:date->string x "~Y-~m-~d ~H:~M:~S~z")))
((date? x)
(data->string (s:make-date (date-second x)
(date-minute x)
(date-hour x)
(date-day x)
(date-month x)
(date-year x)
(date-time-zone-offset x))))
((bytes? x) (error 'data->string "bytes are not directly supported - please encode it into string according to your database's format, or use prepare statement"))
((string? x) (sql-escape-string x))
(else (error 'data->string "unsupported data type: ~a - please first convert to string" x))))
(define (map-value-converter args)
(let ((args args))
(lambda (s)
(begin0 (data->string (car args))
(set! args (cdr args))))))
(define (phq-merge-query phq value)
(let ((lst (read-iqs (open-input-string (phq-converted phq)))))
(if (not (= (length (filter symbol? lst)) (length value)))
(error 'php-merge-query "missing args in ~a" value)
(iqs-convert lst map-value-converter value))))
(provide/contract
(make-place-holder-query (-> (-> (listof any/c) (-> any/c any)) string? phq?))
(default-converter (-> (listof any/c) (-> any/c any)))
(question-converter (-> (listof any/c) (-> any/c any)))
(phq-map-values (->* (phq? (listof any/c))
((-> (listof any/c) (listof any/c) any))
any))
(phq-merge-query (-> phq? (listof any/c) string?))
(data->string (-> any/c any))
)