emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/emacsql 75ea77c9a0 149/427: Add an "as" operator, greatly


From: ELPA Syncer
Subject: [nongnu] elpa/emacsql 75ea77c9a0 149/427: Add an "as" operator, greatly simplifying :from.
Date: Tue, 13 Dec 2022 02:59:37 -0500 (EST)

branch: elpa/emacsql
commit 75ea77c9a0d1f5aede67a01dceeeaa3b077948fe
Author: Christopher Wellons <wellons@nullprogram.com>
Commit: Christopher Wellons <wellons@nullprogram.com>

    Add an "as" operator, greatly simplifying :from.
---
 README.md        |  11 ++++--
 emacsql-tests.el |   8 ++---
 emacsql.el       | 103 ++++++++++++++++++++++++-------------------------------
 3 files changed, 57 insertions(+), 65 deletions(-)

diff --git a/README.md b/README.md
index 8de9635404..6e85073a9a 100644
--- a/README.md
+++ b/README.md
@@ -103,13 +103,17 @@ so you'll need to enable it for each connection.
 
 ## Operators
 
-Emacsql currently supports the following expression operators, named
+Emacsql supports the following SQLite expression operators, named
 exactly like so in a structured Emacsql statement.
 
     *     /     %     +     -     <<    >>    &
     |     <     <=    >     >=    =     !=
     is    like  glob  and   or    in
 
+In addition, Emacsql has these operators.
+
+    quote   as    not
+
 The `<=` and `>=` operators accept 2 or 3 operands, transforming into
 a SQL `_ BETWEEN _ AND _` operator as appropriate.
 
@@ -180,6 +184,7 @@ column identifiers, optionally as expressions.
 
 ```el
 [:select [name (/ salary 52)] ...]
+[:select [(as name n) (as age a)] ...]
 ```
 
 #### :from `<table>`
@@ -189,9 +194,9 @@ Provides `FROM`.
 ```el
 [... :from employees]
 [... :from [employees accounts]]
-[... :from [employees (accounts a)]]
+[... :from [employees (as accounts a)]]
 [... :from (:select ...)]
-[... :from [((:select ...) s1) ((:select ...) s2)]]
+[... :from [(as (:select ...) s1) (as (:select ...) s2)]]
 ```
 
 #### :where `<expr>`
diff --git a/emacsql-tests.el b/emacsql-tests.el
index cb383f563f..763a014d0f 100644
--- a/emacsql-tests.el
+++ b/emacsql-tests.el
@@ -75,10 +75,10 @@
     ;; 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;")))
+    ([:select name :from [people (as accounts a)]] '()
+     "SELECT name FROM people, accounts AS a;")
+    ([:select p:name :from [(as (:select * :from people) p)]] '()
+     "SELECT p.name FROM (SELECT * FROM people) AS p;")))
 
 (ert-deftest emacsql-create-table ()
   (emacsql-tests-with-queries
diff --git a/emacsql.el b/emacsql.el
index 449544bba6..c79d90b70e 100644
--- a/emacsql.el
+++ b/emacsql.el
@@ -504,54 +504,56 @@ definitions for return from a `emacsql-defexpander'."
 (defun emacsql--expr (expr)
   "Expand EXPR recursively."
   (emacsql-with-vars ""
-    (if (atom expr)
-        (var expr :auto)
-      (cl-destructuring-bind (op . args) expr
-        (cl-flet ((recur (n) (combine (emacsql--expr (nth n args)))))
-          (cl-ecase op
-            ;; Trinary/binary
-            ((<= >=)
-             (cl-ecase (length args)
-               (2 (format "%s %s %s" (recur 0) op (recur 1)))
-               (3 (format "%s BETWEEN %s AND %s"
-                          (recur 1)
-                          (recur (if (eq op '>=) 2 0))
-                          (recur (if (eq op '>=) 0 2))))))
-            ;; Binary
-            ((< > = != like glob is and or * / % << >> + & |)
-             (if (= 2 (length args))
-                 (format "%s %s %s"
-                         (recur 0)
-                         (if (eq op '%) '%% (upcase (symbol-name op)))
-                         (recur 1))
-               (error "Wrong number of operands for %s" op)))
-            ;; Unary
-            ((not)
-             (if (= 1 (length args))
-                 (format "%s %s" (upcase (symbol-name op)) (recur 0))
-               (error "Wrong number of operands for %s" op)))
-            ;; Unary/Binary
-            ((-)
-             (cl-ecase (length args)
-               (1 (format "-(%s)" (recur 0)))
-               (2 (format "%s - %s" (recur 0) (recur 1)))))
-            ;; quote special case
-            ((quote)
-             (cl-ecase (length args)
-               (1 (var (nth 0 args) :value))))
-            ;; IN special case
-            ((in)
-             (cl-case (length args)
-               (1 (error "Wrong number of operands for %s" op))
-               (2 (format "%s IN %s" (recur 0) (var (nth 1 args) :vector)))
-               (otherwise
-                (format "%s IN %s" (recur 0) (subsql (cdr args))))))))))))
+    (cond
+     ((and (sequencep expr) (eq :select (elt expr 0))) (subsql expr))
+     ((atom expr) (var expr :auto))
+     ((cl-destructuring-bind (op . args) expr
+         (cl-flet ((recur (n) (combine (emacsql--expr (nth n args)))))
+           (cl-ecase op
+             ;; Trinary/binary
+             ((<= >=)
+              (cl-ecase (length args)
+                (2 (format "%s %s %s" (recur 0) op (recur 1)))
+                (3 (format "%s BETWEEN %s AND %s"
+                           (recur 1)
+                           (recur (if (eq op '>=) 2 0))
+                           (recur (if (eq op '>=) 0 2))))))
+             ;; Binary
+             ((< > = != like glob is and or * / % << >> + & | as)
+              (if (= 2 (length args))
+                  (format "%s %s %s"
+                          (recur 0)
+                          (if (eq op '%) '%% (upcase (symbol-name op)))
+                          (recur 1))
+                (error "Wrong number of operands for %s" op)))
+             ;; Unary
+             ((not)
+              (if (= 1 (length args))
+                  (format "%s %s" (upcase (symbol-name op)) (recur 0))
+                (error "Wrong number of operands for %s" op)))
+             ;; Unary/Binary
+             ((-)
+              (cl-ecase (length args)
+                (1 (format "-(%s)" (recur 0)))
+                (2 (format "%s - %s" (recur 0) (recur 1)))))
+             ;; quote special case
+             ((quote)
+              (cl-ecase (length args)
+                (1 (var (nth 0 args) :value))))
+             ;; IN special case
+             ((in)
+              (cl-case (length args)
+                (1 (error "Wrong number of operands for %s" op))
+                (2 (format "%s IN %s" (recur 0) (var (nth 1 args) :vector)))
+                (otherwise
+                 (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."
   (emacsql-with-vars ""
     (cl-etypecase idents
       (symbol (var idents :identifier))
+      (list (expr idents))
       (vector (mapconcat (lambda (e) (expr e)) idents ", ")))))
 
 (defun emacsql-init-font-lock ()
@@ -573,22 +575,7 @@ definitions for return from a `emacsql-defexpander'."
 (emacsql-defexpander :from (sources)
   "Expands to the FROM keyword."
   (emacsql-with-vars "FROM "
-    (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 ", ")))))
+    (idents sources)))
 
 (emacsql-defexpander :replace ()
   (list "REPLACE"))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]