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

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

[nongnu] elpa/emacsql 8951084b40 143/427: Add variable escaping.


From: ELPA Syncer
Subject: [nongnu] elpa/emacsql 8951084b40 143/427: Add variable escaping.
Date: Tue, 13 Dec 2022 02:59:36 -0500 (EST)

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

    Add variable escaping.
---
 README.md        |  5 ++++-
 emacsql-tests.el | 12 +++++++++---
 emacsql.el       | 26 +++++++++++++++-----------
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/README.md b/README.md
index f680060849..d9e4b8e9ca 100644
--- a/README.md
+++ b/README.md
@@ -121,7 +121,7 @@ Inside expressions, Emacsql cannot tell the difference 
between symbol
 literals and column references. If you're talking about the symbol
 itself, just quote it as you would in normal Elisp. Note that this
 does not "escape" `$n` variables: it just means the argument gets
-quoted.
+quoted. Use `$$` for escaping variables.
 
 ```el
 [... :where (= category 'hiking)]
@@ -304,6 +304,9 @@ statement in the `emacsql` function, 1-indexed.
 
     (emacsql db [:select * :from $1 :where (> salary $2)] 'employees 50000)
 
+To get a literal symbol that looks like one of these variables, escape
+it with an extra dollar sign (i.e. `$$1` becomes `$1`).
+
 ## Limitations
 
 Emacsql is *not* intended to play well with other programs accessing
diff --git a/emacsql-tests.el b/emacsql-tests.el
index 18a36194ce..b4edd8c2bb 100644
--- a/emacsql-tests.el
+++ b/emacsql-tests.el
@@ -48,7 +48,9 @@
   (should (eq (emacsql-var '$) 0))
   (should (eq (emacsql-var '$1) 0))
   (should (eq (emacsql-var '$5) 4))
-  (should (eq (emacsql-var '$10) 9)))
+  (should (eq (emacsql-var '$10) 9))
+  (should (eq (emacsql-var '$a) nil))
+  (should (eq (emacsql-var '$$10) '$10)))
 
 (defun emacsql-tests-query (query args result)
   "Check that QUERY outputs RESULT for ARGS."
@@ -150,12 +152,16 @@
     ([:limit [$1 $2]] '(4 30)
      "LIMIT 4, 30;")))
 
-(ert-deftest emacsql-expr ()
+(ert-deftest emacsql-quoting ()
   (emacsql-tests-with-queries
     ([:where (= name 'foo)] '()
      "WHERE name = 'foo';")
     ([:where (= name '$1)] '(qux)
-     "WHERE name = 'qux';")))
+     "WHERE name = 'qux';")
+    ([:where (= name '$$1)] '()
+     "WHERE name = '$1';")
+    ([:values [a $$1]] '()
+     "VALUES ('a', '$1');")))
 
 (ert-deftest emacsql-system ()
   "A short test that fully interacts with SQLite."
diff --git a/emacsql.el b/emacsql.el
index 9292a0b730..e995f8bce4 100644
--- a/emacsql.el
+++ b/emacsql.el
@@ -361,13 +361,15 @@ a list of (<string> [arg-pos] ...)."
 
 (defun emacsql-var (var)
   "Return the index number of VAR, or nil if VAR is not a variable.
-A variable is a symbol that looks like $1, $2, $3, etc. A $ means $1."
+A variable is a symbol that looks like $1, $2, $3, etc. A $ means
+$1. These are escaped with a double $$, in which case the proper
+symbol is returned."
   (when (symbolp var)
     (let ((name (symbol-name var)))
-      (when (eql (aref name 0) ?$)
-        (if (> (length name) 1)
-            (1- (read (substring name 1)))
-          0)))))
+      (cond
+       ((string-match-p "^\\$[0-9]+" name) (1- (read (substring name 1))))
+       ((string-match-p "^\\$$" name) 0)
+       ((string-match-p "^\\$\\$[0-9]+" name) (intern (substring name 1)))))))
 
 (defun emacsql-escape-format (thing &optional kind)
   "Escape THING for use as a `format' spec, pre-escaping for KIND.
@@ -384,12 +386,14 @@ KIND should be :value or :identifier."
 
 (defun emacsql--vars-var (thing kind)
   "Only use within `emacsql-with-vars'!"
-  (if (emacsql-var thing)
-      (prog1 "%s" (push (cons (emacsql-var thing) kind) emacsql--vars))
-    (cl-ecase kind
-      ((:identifier :value :vector) (emacsql-escape-format thing kind))
-      (:auto (emacsql-escape-format
-              thing (if (symbolp thing) :identifier :value))))))
+  (let ((var (emacsql-var thing)))
+    (when (and var (symbolp var)) (setf thing var))
+    (if (numberp var)
+        (prog1 "%s" (push (cons var kind) emacsql--vars))
+      (cl-ecase kind
+        ((:identifier :value :vector) (emacsql-escape-format thing kind))
+        (:auto (emacsql-escape-format
+                thing (if (symbolp thing) :identifier :value)))))))
 
 (defun emacsql--vars-combine (expanded)
   "Only use within `emacsql-with-vars'!"



reply via email to

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