branch: elpa/emacsql commit 99a806938913afcfc30ea85f7b172659257c7d32 Author: Christopher Wellons <well...@nullprogram.com> Commit: Christopher Wellons <well...@nullprogram.com>
Add support for foreign keys. --- emacsql-tests.el | 4 ++++ emacsql.el | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/emacsql-tests.el b/emacsql-tests.el index 5277eb0629..8eb8113805 100644 --- a/emacsql-tests.el +++ b/emacsql-tests.el @@ -104,6 +104,10 @@ "CREATE TABLE foo (a, b, c, UNIQUE (a, b, c));") ([:create-table foo ([a b] :check (< a b)) ] '() "CREATE TABLE foo (a, b, CHECK (a < b));") + ([:create-table foo + ([a b c] :foreign ([a b] bar [aa bb] :on-delete :cascade))] '() + (concat "CREATE TABLE foo (a, b, c, FOREIGN KEY (a, b) " + "REFERENCES bar (aa, bb) ON DELETE CASCADE);")) ;; Drop table ([:drop-table $1] '(foo) "DROP TABLE foo;"))) diff --git a/emacsql.el b/emacsql.el index 60c65a1a3d..a1986e2e19 100644 --- a/emacsql.el +++ b/emacsql.el @@ -438,6 +438,26 @@ definitions for return from a `emacsql-defexpander'." collect (combine (emacsql--column-to-string column)) into parts finally (cl-return (mapconcat #'identity parts ", "))))) +(defun emacsql--foreign-key (spec) + (emacsql-with-vars "FOREIGN KEY " + (cl-destructuring-bind (child table parent . actions) (cl-coerce spec 'list) + (mapconcat + #'identity + (cons + (format "(%s) REFERENCES %s (%s)" (idents child) (var table :identifier) + (idents parent)) + (cl-loop for (key value) on actions by #'cddr collect + (cl-ecase key + (:on-update "ON UPDATE") + (:on-delete "ON DELETE")) + collect + (cl-ecase value + (:restrict "RESTRICT") + (:set-nil "SET NULL") + (:set-default "SET DEFAULT") + (:cascade "CASCADE")))) + " ")))) + (defun emacsql--schema-to-string (schema) (cl-etypecase schema (vector (emacsql--columns-to-string schema)) @@ -451,7 +471,8 @@ definitions for return from a `emacsql-defexpander'." (cl-ecase key (:primary (format "PRIMARY KEY (%s)" (idents value))) (:unique (format "UNIQUE (%s)" (idents value))) - (:check (format "CHECK (%s)" (expr value)))))) + (:check (format "CHECK (%s)" (expr value))) + (:foreign (combine (emacsql--foreign-key value)))))) ", "))))) (defun emacsql--vector (vector)