marijnh / Postmodern

A Common Lisp PostgreSQL programming interface
http://marijnhaverbeke.nl/postmodern
Other
392 stars 90 forks source link

Dao inheritance section #343

Closed kilianmh closed 2 months ago

kilianmh commented 2 months ago

Here is now some material for a section about dao-class inheritance. See #342 The code should work. If you want any changes/improvements i can assist.

Dao Class Inheritanc

The following dao class is related to ruby active record with the slots updated-at and created-at. Both slots are initialized automatically. Updated-at is automatically updated every time you use insert-dao whereas created-at will remain the same even if you change entry data. This code is written with the local-time library, but simple-time should also work:

(defun timestamp-to-postgre-time (timestamp)
  (local-time:format-timestring nil timestamp))

(defun update-time (old-time)
  (declare (ignore old-time))
  (local-time:format-timestring nil (now)))

(defclass active-record ()
  ((created-at :col-type timestamp
           :accessor created-at
           :description "The timestamp when the entry was created."
           :initform (local-time:now)
           :col-export timestamp-to-postgre-time)
   (updated-at :col-type timestamp
           :accessor updated-at
           :description "The timestamp when the entry was last updated."
           :initform (local-time:now)
           :col-export update-time))
  (:metaclass dao-class))

By using active-record as superclass, subclasses inherit the same convenient features:

(defclass user (active-record)
  ((user-id :col-type bigint
        :primary-key t
        :reader user-id
        :col-unique t
        :col-identity t)
   (name :col-type (or db-null string)
     :initarg :last-name
     :col-default :null
     :accessor last-name)
   (email :col-type string
      :col-unique t
      :initarg :email
      :accessor email))
  (:metaclass pomo:dao-class))

Next is an example for using inheritance with foreign-keys. For that we define a dao-class (which will not be created as table) whereas the only column is the primary key user-id from the user table:

(defclass user-id-foreign-key ()
  ((user-id :col-type integer
        :initarg :user-id
        :reader user-id
        :col-references ((user user-id))
        :col-primary-key t))
  (:metaclass pomo:dao-class))

Now we can add user-id-foreign-key as superclass in tables where we want to use user-id as foreign key:

(defclass user-credential (user-id-foreign-key active-record)
  ((password-hash :col-type string
          :initarg :password-hash
          :accessor password-hash)
   (salt :col-type integer
     :initarg :salt
     :accessor salt))
  (:metaclass pomo:dao-class))
sabracrolleton commented 2 months ago

Done