about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--dump/sql.scm51
1 files changed, 48 insertions, 3 deletions
diff --git a/dump/sql.scm b/dump/sql.scm
index 576d6cd..74f3139 100644
--- a/dump/sql.scm
+++ b/dump/sql.scm
@@ -1,19 +1,64 @@
 ;;; Database helpers
 ;;;
-;;; These functions should have been a part of guile-dbi. Never too
-;;; late to contribute upstream!
+;;; Most of these functions should have been a part of
+;;; guile-dbi. Never too late to contribute upstream!
 
 (define-module (dump sql)
+  #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
   #:use-module (dbi dbi)
-  #:export (call-with-database
+  #:export (select-query
+            call-with-database
             sql-exec
             sql-fold
             sql-map
             sql-for-each
             sql-find))
 
+;; A half-baked macro to make SQL SELECT queries a bit more
+;; S-expression friendly
+(define-syntax select-query
+  (lambda (x)
+    (syntax-case x ()
+      ((_ fields tables raw-forms ...)
+       #`(string-append "SELECT "
+                        #,(syntax-case #'fields (distinct)
+                            ((distinct _ ...)
+                             "DISTINCT ")
+                            (_ ""))
+                        #,(string-join (filter-map (match-lambda
+                                                     ('distinct #f)
+                                                     ((table column)
+                                                      (format #f "~a.~a" table column))
+                                                     ((table column alias)
+                                                      (format #f "~a.~a AS ~a" table column alias))
+                                                     (field-spec
+                                                      (error "Invalid field specification" field-spec)))
+                                                   (syntax->datum #'fields))
+                                       ", ")
+                        " FROM "
+                        #,(string-join (map (match-lambda
+                                              ((join table condition)
+                                               (format #f "~a ~a ~a"
+                                                       (case join
+                                                         ((join) "JOIN")
+                                                         ((left-join) "LEFT JOIN")
+                                                         ((inner-join) "INNER JOIN")
+                                                         (else (error "Invalid join operator" join)))
+                                                       table condition))
+                                              ((? symbol? table)
+                                               (symbol->string table))
+                                              (table-spec
+                                               (error "Invalid table specification" table-spec)))
+                                            (syntax->datum #'tables))
+                                       " ")
+                        #,(syntax-case #'(raw-forms ...) ()
+                            (() "")
+                            (_ " "))
+                        raw-forms ...))
+      (_ (error "Invalid SQL select query" (syntax->datum x))))))
+
 (define (call-with-database backend connection-string proc)
   (let ((db #f))
     (dynamic-wind (lambda ()