branch: elpa/emacsql commit 109664b88b2920eb35bb5807e36dc342552e943d Author: Christopher Wellons <well...@nullprogram.com> Commit: Christopher Wellons <well...@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."