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

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

[nongnu] elpa/emacsql 109664b88b 060/427: Memoize emacsql-expand.


From: ELPA Syncer
Subject: [nongnu] elpa/emacsql 109664b88b 060/427: Memoize emacsql-expand.
Date: Tue, 13 Dec 2022 02:59:28 -0500 (EST)

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

    Memoize emacsql-expand.
---
 emacsql.el | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/emacsql.el b/emacsql.el
index fb7e700120..e2c646d578 100644
--- a/emacsql.el
+++ b/emacsql.el
@@ -289,6 +289,9 @@ Each row must be a sequence of values to store into TABLE.
 (defvar emacsql-expanders ()
   "Alist of all expansion functions.")
 
+(defvar emacsql-expander-cache (make-hash-table :test 'equal)
+  "Cache used to memoize `emacsql-expand'.")
+
 (defun emacsql-add-expander (keyword arity function)
   "Register FUNCTION for KEYWORD as a SQL expander.
 FUNCTION should accept the keyword's arguments and should return
@@ -296,6 +299,7 @@ a list of (<string> [arg-pos] ...).
 
 See also `emacsql-with-errors'."
   (prog1 keyword
+    (clrhash emacsql-expander-cache)
     (push (list keyword arity function) emacsql-expanders)))
 
 (defmacro emacsql-defexpander (keyword args &rest body)
@@ -305,16 +309,22 @@ See also `emacsql-with-errors'."
 
 (defun emacsql-expand (sql)
   "Expand SQL into a SQL-consumable string, with variables."
-  (cl-loop with items = (cl-coerce sql 'list)
-           while (not (null items))
-           for keyword = (pop items)
-           for (arity expander) = (cdr (assoc keyword emacsql-expanders))
-           when expander
-           collect (apply expander (cl-subseq items 0 arity)) into parts
-           else do (error "Unrecognized keyword %s" keyword)
-           do (setf items (cl-subseq items arity))
-           finally (cl-return (cons (concat (mapconcat #'car parts " ") ";")
-                                 (apply #'nconc (mapcar #'cdr parts))))))
+  (let* ((cache emacsql-expander-cache)
+         (cached (and cache (gethash sql cache))))
+    (or cached
+        (cl-loop with items = (cl-coerce sql 'list)
+                 while (not (null items))
+                 for keyword = (pop items)
+                 for (arity expander) = (cdr (assoc keyword emacsql-expanders))
+                 when expander
+                 collect (apply expander (cl-subseq items 0 arity)) into parts
+                 else do (error "Unrecognized keyword %s" keyword)
+                 do (setf items (cl-subseq items arity))
+                 finally
+                 (let ((string (concat (mapconcat #'car parts " ") ";"))
+                       (vars (apply #'nconc (mapcar #'cdr parts))))
+                   (cl-return (setf (gethash sql cache)
+                                    (cons string vars))))))))
 
 (defun emacsql-format (expansion &rest args)
   "Fill in the variables EXPANSION with ARGS."



reply via email to

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