[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"))
- [nongnu] elpa/emacsql 43ecb5a252 071/427: Tweak README names., (continued)
- [nongnu] elpa/emacsql 43ecb5a252 071/427: Tweak README names., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 58e31aa3a9 079/427: Add :update and :set expanders., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql c9aab20d47 082/427: Add in operator (special case operator)., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 25f9817064 094/427: Add work-in-progress note back., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 03295cba37 119/427: Add ORDER BY expanders., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql d1c0904564 120/427: Fix missing quotes., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 4718ff4e89 122/427: Simplify all the expanders with new local functions., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 54247e4b5e 127/427: Add another insertion unit test., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql aa9283ca0a 132/427: Allow sub-selects with :from., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql c236aa8437 144/427: Remove extra space., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 75ea77c9a0 149/427: Add an "as" operator, greatly simplifying :from.,
ELPA Syncer <=
- [nongnu] elpa/emacsql 213bb71b7a 152/427: Add :having expander., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 8123020ca7 153/427: Make and and or operators variadic., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 76bf0c34dc 038/427: Add rudimentary :where expander., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql afe64ca63a 040/427: Fix emacsql-add-expander example., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 72145a1627 045/427: Allow for multi-arity keyword expanders., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql f54142f1eb 062/427: Argument list checking in emacsql-format., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 86687b6ba3 067/427: Flesh out more README., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql a306de980a 070/427: Add :delete keyword., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql afa9aa5194 072/427: Add :into expander., ELPA Syncer, 2022/12/13
- [nongnu] elpa/emacsql 8f59fe6e80 073/427: Add a vector escape., ELPA Syncer, 2022/12/13