LispCookbook / LispCookbook/cl-cookbook

Database Access and Persistence: How to handle deletion of joins?

Open
#178 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
1.1k
Forks
158
Avg merge
6d 3h
Merged PRs (30d)
2

Description

I am currently learning CLSQL and wonder what is the best way to handle deletions of joins. As an example, assume a user account is to be deleted in some random application and we want to delete all the data connected to it. I see the description on mito does not say anything about this and bridging this gap could be a very interesting improvement.

Assume the account has a one-to-many relationship to users within an account and messages within an account. The account implementation should not be aware of the details of message and users (as other data records can be there or added).

It seems that the object system is not useful here because decorating the deletion of account objects does not combine. (?) For instance if “message” code says (defmethod database-package:delete :before ((a account)) (delete-all-messages-related-to account)) and the “user” code (defmethod database-package:delete :before ((a account)) (delete-all-users-related-to account)) then we get only one of the effects. It also makes it hard or impossible to correctly order that additional behaviour.

A natural approach seems to use hooks

;;;
;;; Event Hooks
;;;

(defun make-hook ()
  "Create a fesh new hook holding callbacks."
  nil)

(defmacro hook-add (hook keyword callback &key after before)
  "Add or replace a CALLBACK identified by KEYWORD to CALLBACK."
  `(access:set-plist-val!
    (list :callback ,callback
          :after ,after
          :before ,before)
    ,keyword ,hook))

(defmacro hook-rem (hook keyword)
  "Remove the CALLBACK identified by KEYWORD from CALLBACK.

It is a no-op if KEYWORD is not bound in CALLBACK."
  `(access:rem-plist-val! ,keyword ,hook))


(defun hook-run/order (hook)
  "Sort hooks in the right order before executing them."
  (loop
    :for (callback-name callback-spec . rest) :on hook :by #'cddr
    :when (or (getf callback-spec :after) (getf callback-spec :before))
    :do (error "hook-run/order: Real ordering not implemented.")
    :collect (getf callback-spec :callback)))

(defun hook-run (hook)
  "Run the given HOOK."
  (loop :for callback :in (hook-run/order hook)
        :do (funcall callback)))

It is then easy to define a hook account-delete-hook (or maybe before/after hooks for that event) and just extend the deletion account method to run that hook. If this is a good approach, it could be worth mentioning it in the paragraph about object deletions.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the mito description and the paragraph about object deletions referenced in the issue. Determine whether the proposed hook approach is appropriate for related-record deletion and what guidance should be added. Done means the documentation clearly explains the recommended deletion behavior and ordering considerations.

Written by the indexing model from the issue text.

Assessment

Domain
databases, documentation
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.