branch: externals/triples commit 09a78f5b80af54032055df028a16a4eed45b7747 Author: Andrew Hyatt <ahy...@gmail.com> Commit: Andrew Hyatt <ahy...@gmail.com>
Add `triples-mode-subject', for renaming a subject. This method not only renames the subject, but also any objects that point to the subject. --- CHANGELOG.org | 1 + triples-test.el | 15 +++++++++++++++ triples.el | 26 ++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/CHANGELOG.org b/CHANGELOG.org index 90aebd5c20..66d4677898 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -3,6 +3,7 @@ TITLE: Changelog for the triples module for GNU Emacs. * 0.2 - Create a default database to encourage a shared triple database. Add information on why this is an interesting idea in the README. - Add support for backups of databases via =triples-backup=, and a simple way to have a sane and shared backups created with the new =triples-backups= module. +- Add =triples-move-subject= which will move both a subject as well as reference to it. * 0.1.2 - Bugfix release to remove backward compatibility with pre-Emacs 29 versions. * 0.1.1 diff --git a/triples-test.el b/triples-test.el index 44d92ab2da..3442a3b626 100644 --- a/triples-test.el +++ b/triples-test.el @@ -345,6 +345,21 @@ easily debug into it.") (sqlite-select db "SELECT COUNT(*) FROM triples WHERE subject = ? AND predicate = 'base/type' AND object = 'marker'" (list (triples-standardize-val "foo"))))))) +(ert-deftest triples-move-subject () + (triples-test-with-temp-db + (triples-add-schema db 'named '(name)) + (triples-add-schema db 'friend '(id)) + (triples-set-subject db 123 '(named :name "Ada Lovelace")) + (triples-set-subject db 456 '(named :name "Michael Faraday") + '(friend :id 123)) + (triples-set-subject db 987 '(named :name "To Be Deleted")) + (should-error (triples-move-subject db 123 987)) + (triples-delete-subject db 987) + (triples-move-subject db 123 987) + (should-not (triples-get-subject db 123)) + (should (equal "Ada Lovelace" (plist-get (triples-get-subject db 987) :named/name))) + (should (equal 987 (plist-get (triples-get-subject db 456) :friend/id))))) + (ert-deftest triples-readme () (triples-test-with-temp-db (triples-add-schema db 'person diff --git a/triples.el b/triples.el index ebc59982f0..7d688896d0 100644 --- a/triples.el +++ b/triples.el @@ -300,6 +300,32 @@ object, properties to retrieve or nil for *." (when properties `((= properties ,(intern (format "$s%d" (cl-incf n))))))))))) (seq-filter #'identity (list subject predicate object properties))))))) +(defun triples-move-subject (db old-subject new-subject) + "Replace all instance in DB of OLD-SUBJECT to NEW-SUBJECT. +Any references to OLD-SUBJECT as an object are also replaced. +This will throw an error if there is an existing subject +NEW-SUBJECT with at least one equal property (such as type +markers). But if there are no commonalities, the OLD-SUBJECT is +merged into NEW-SUBJECT." + (pcase triples-sqlite-interface + ('builtin + (condition-case err + (progn + (sqlite-transaction db) + (sqlite-execute db "UPDATE triples SET subject = ? WHERE subject = ?" + (list (triples-standardize-val new-subject) (triples-standardize-val old-subject))) + (sqlite-execute db "UPDATE triples SET object = ? WHERE object = ?" + (list (triples-standardize-val new-subject) (triples-standardize-val old-subject))) + (sqlite-commit db)) + (error (sqlite-rollback db) + (signal 'error err)))) + ('emacsql + (emacsql-with-transaction db + (emacsql db [:update triples :set (= subject $s1) :where (= subject $s2)] + new-subject old-subject) + (emacsql db [:update triples :set (= object $s1) :where (= object $s2)] + new-subject old-subject))))) + ;; Code after this point should not call sqlite or emacsql directly. If any more ;; calls are needed, put them in a defun, make it work for sqlite and emacsql, ;; and put them above.