branch: elpa/emacsql commit 364c3cacb6a41345337ac612c666e41a43353c1c Author: Christopher Wellons <well...@nullprogram.com> Commit: Christopher Wellons <well...@nullprogram.com>
More advanced :from sources, again. --- README.md | 2 ++ emacsql-tests.el | 10 ++++++++-- emacsql.el | 30 ++++++++++++++++++++---------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d936c94f92..65c61f7310 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,9 @@ Provides `FROM`. ```el [... :from employees] [... :from [employees accounts]] +[... :from [employees (accounts a)]] [... :from (:select ...)] +[... :from [((:select ...) s1) ((:select ...) s2)]] ``` #### :where `<expr>` diff --git a/emacsql-tests.el b/emacsql-tests.el index d659dcd804..ac622c12b9 100644 --- a/emacsql-tests.el +++ b/emacsql-tests.el @@ -69,7 +69,14 @@ ([:select * :from employees :where (< salary 50000)] '() "SELECT * FROM employees WHERE salary < 50000;") ([:select * :from people :where (in name $1)] '([FOO BAR]) - "SELECT * FROM people WHERE name IN ('FOO', 'BAR');"))) + "SELECT * FROM people WHERE name IN ('FOO', 'BAR');") + ;; Sub queries + ([:select name :from (:select * :from $1)] '(people) + "SELECT name FROM (SELECT * FROM people);") + ([:select name :from [people (accounts a)]] '() + "SELECT name FROM people, accounts a;") + ([:select p:name :from [((:select * :from people) p)]] '() + "SELECT p.name FROM (SELECT * FROM people) p;"))) (ert-deftest emacsql-create-table () (emacsql-tests-with-queries @@ -94,7 +101,6 @@ "CREATE TABLE foo (a, b, c, UNIQUE (a, b, c));") ([:create-table foo ([a b] :check (< a b)) ] '() "CREATE TABLE foo (a, b, CHECK (a < b));") - ([:drop-table $1] '(foo) "DROP TABLE foo;"))) diff --git a/emacsql.el b/emacsql.el index c38af94b21..af2d0d7aea 100644 --- a/emacsql.el +++ b/emacsql.el @@ -395,7 +395,8 @@ definitions for return from a `emacsql-defexpander'." (cl-flet* ((var (thing kind) (emacsql--vars-var thing kind)) (combine (expanded) (emacsql--vars-combine expanded)) (expr (thing) (combine (emacsql--expr thing))) - (idents (thing) (combine (emacsql--idents thing)))) + (idents (thing) (combine (emacsql--idents thing))) + (subsql (thing) (combine (emacsql-expand thing t)))) (cons (concat ,prefix (progn ,@body)) emacsql--vars)))) (defun emacsql--column-to-string (column) @@ -504,10 +505,7 @@ definitions for return from a `emacsql-defexpander'." (1 (error "Wrong number of operands for %s" op)) (2 (format "%s IN %s" (recur 0) (var (nth 1 args) :vector))) (otherwise - (let ((subsql (cl-coerce (cdr args) 'vector))) - (format "%s IN %s" - (recur 0) - (combine (emacsql-expand subsql :sub))))))))))))) + (format "%s IN %s" (recur 0) (subsql (cdr args)))))))))))) (defun emacsql--idents (idents) "Read in a vector of IDENTS identifiers, or just an single identifier." @@ -532,13 +530,25 @@ definitions for return from a `emacsql-defexpander'." "*" (idents arg)))) -(emacsql-defexpander :from (table) +(emacsql-defexpander :from (sources) "Expands to the FROM keyword." (emacsql-with-vars "FROM " - (cl-etypecase table - (vector (idents table)) - (symbol (var table :identifier)) - (list (combine (emacsql-expand table :subsql-p)))))) + (cl-etypecase sources + (symbol (var sources :identifier)) + (list (if (eq :select (car sources)) + (subsql sources) + (cl-destructuring-bind (table alias) sources + (concat (var table :identifier) " " (var alias :identifier))))) + (vector (mapconcat (lambda (source) + (cl-etypecase source + (symbol (var source :identifier)) + (list + (cl-destructuring-bind (table alias) source + (concat (if (symbolp table) + (var table :identifier) + (subsql table)) + " " (var alias :identifier)))))) + sources ", "))))) (emacsql-defexpander :replace () (list "REPLACE"))