fukamachi / mito

An ORM for Common Lisp with migrations, relationships and PostgreSQL support
292 stars 31 forks source link

Error when retrieving a View from the database #120

Open svetlyak40wt opened 1 year ago

svetlyak40wt commented 1 year ago

Here is my view definition:

(defclass top-item ()
  ((subject-type :initarg :subject-type
                 :col-type :text
                 :reader subject-type)
   (subject-id :initarg :subject-id
               :col-type :integer
               :reader subject-id)
   (rating :initarg :rating
           :col-type :integer
           :reader rating))
  (:as "select subject_type, subject_id, count(*) as rating from rating.vote group by subject_type, subject_id")
  (:metaclass mito:dao-table-view))

When I'm trying to do a select:

RATING/VOTE/API> (with-connection ()
                       (retrieve-dao 'top-item
                                 :subject-type "user"))

I'm getting this error:

There is no applicable method for the generic function
  #<STANDARD-GENERIC-FUNCTION (COMMON-LISP:SETF MITO.DAO.MIXIN:DAO-SYNCED) (1)>
when called with arguments
  (T #<TOP-ITEM {100E485A53}>).
   [Condition of type SB-PCL::NO-APPLICABLE-METHOD-ERROR]

Restarts:
 0: [RETRY] Retry calling the generic function.
 1: [RETRY] Retry SLY mREPL evaluation request.
 2: [*ABORT] Return to SLY's top level.
 3: [ABORT] abort thread (#<THREAD "sly-channel-1-mrepl-remote-1" RUNNING {10010C0003}>)

Backtrace:
 0: ((:METHOD NO-APPLICABLE-METHOD (T)) #<STANDARD-GENERIC-FUNCTION (COMMON-LISP:SETF MITO.DAO.MIXIN:DAO-SYNCED) (1)> T #<TOP-ITEM {10$
 1: (SB-PCL::CALL-NO-APPLICABLE-METHOD #<STANDARD-GENERIC-FUNCTION (COMMON-LISP:SETF MITO.DAO.MIXIN:DAO-SYNCED) (1)> (T #<TOP-ITEM {10$
 2: ((:METHOD MITO.DAO.MIXIN:MAKE-DAO-INSTANCE (MITO.CLASS.TABLE:TABLE-CLASS)) #<MITO.DAO.VIEW:DAO-TABLE-VIEW RATING/VOTE/MODEL::TOP-I$
 3: (SELECT-BY-SQL #<MITO.DAO.VIEW:DAO-TABLE-VIEW RATING/VOTE/MODEL::TOP-ITEM> #<SXQL-STATEMENT: SELECT * FROM #1=rating#1#.#1#top_ite$
 4: (RETRIEVE-DAO #<MITO.DAO.VIEW:DAO-TABLE-VIEW RATING/VOTE/MODEL::TOP-ITEM> :SUBJECT-TYPE "user")
 5: ((FLET "CONNECTED-FUNC3001"))
 6: (COMMON/DB::CALL-WITH-TRANSACTION #<FUNCTION (FLET "CONNECTED-FUNC3001") {5412086B}>)
 7: (COMMON/DB::CALL-WITH-CONNECTION #<FUNCTION (FLET "CONNECTED-FUNC3001") {5412086B}>)
 8: ((LAMBDA ()))

This is because for dao-table-class mito inserts dao-class to direct-superclasses:

(defmethod initialize-instance :around ((class dao-table-class) &rest initargs
                                                                &key direct-superclasses &allow-other-keys)
  (append-record-timestamp-mixin-to-direct-superclasses-if-needed initargs direct-superclasses)
  (unless (contains-class-or-subclasses 'dao-class direct-superclasses)
    (push (find-class 'dao-class) (getf initargs :direct-superclasses)))
  (append-auto-pk-class-to-direct-superclasses-if-needed initargs direct-superclasses)
  (apply #'call-next-method class initargs))

but for dao-table-view there is no such thing.

Right not this workaround works for me:

(defmethod initialize-instance :around ((class mito:dao-table-view) &rest initargs
                                        &key direct-superclasses &allow-other-keys)
  (unless (mito.util:contains-class-or-subclasses 'mito:dao-class direct-superclasses)
    (push (find-class 'mito:dao-class) (getf initargs :direct-superclasses)))
  (apply #'call-next-method class initargs))
vindarel commented 1 year ago

TIL about table views. They are not documented. A commit says they initially only worked with Postgres. https://github.com/fukamachi/mito/commit/81c3ccebe6ba71a84809316872f291c33d6f1ecd

svetlyak40wt commented 1 year ago

I was able to use the with abovermentioned hack and Postgres.