fukamachi / mito

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

"#<STANDARD-CLASS MITO.DAO.TABLE:DAO-CLASS> has no slot named MITO.CLASS.TABLE::PARENT-COLUMN-MAP" error #43

Open svetlyak40wt opened 5 years ago

svetlyak40wt commented 5 years ago

This error happens when you have a reference to another table in the class, having metclass = dao-table-mixin.

Here is a full example to reproduce this problem:

(defpackage #:mito-test
  (:use #:cl))
(in-package mito-test)

(defclass project ()
  ((name :col-type :text))
  (:metaclass mito:dao-table-class))

(defclass with-link-to-project-mixin ()
  ((project :col-type project))
  (:metaclass mito:dao-table-mixin))

(defclass action (with-link-to-project-mixin)
  ()
  (:metaclass mito:dao-table-class))

After these classes were defined, try:

MITO-TEST> (mito:save-dao (make-instance 'action))

This is a full stack trace from the Emacs:

;; #<STANDARD-CLASS MITO.DAO.TABLE:DAO-CLASS> has no slot named MITO.CLASS.TABLE::PARENT-COLUMN-MAP.
;;    [Condition of type SIMPLE-ERROR]

;; Restarts:
;;  0: [RETRY] Retry SLY mREPL evaluation request.
;;  1: [*ABORT] Return to SLY's top level.
;;  2: [ABORT-BREAK] Reset this thread
;;  3: [ABORT] Kill this thread

;; Backtrace:
;;  0: (#<CCL::STANDARD-KERNEL-METHOD SLOT-MISSING (T T T T)> #<STANDARD-CLASS STANDARD-CLASS> #<STANDARD-CLASS MITO.DAO.TABLE:DAO-CLASS> MITO.CLASS.TABLE::PARENT-COLUMN-MAP SLOT-VALUE NIL)
;;  1: (CCL::%SLOT-ID-REF-MISSING #<STANDARD-CLASS MITO.DAO.TABLE:DAO-CLASS> #<SLOT-ID for MITO.CLASS.TABLE::PARENT-COLUMN-MAP/1863 #x3020042934FD>)
;;  2: ((:INTERNAL MITO.CLASS.TABLE::REC MITO.CLASS.TABLE:FIND-PARENT-COLUMN))
;;  3: ((:INTERNAL MITO.CLASS.TABLE::REC MITO.CLASS.TABLE:FIND-PARENT-COLUMN))
;;  4: ((:INTERNAL MITO.CLASS.TABLE::REC MITO.CLASS.TABLE:FIND-PARENT-COLUMN))
;;  5: (MITO.CLASS.TABLE:FIND-PARENT-COLUMN #<MITO.DAO.TABLE:DAO-TABLE-CLASS ACTION2> #<DAO-TABLE-COLUMN-CLASS for instance slot PROJECT-ID #x30200716D12D>)
;;  6: (MITO.DAO::FOREIGN-VALUE #<ACTION2 #x30200739E03D> #<DAO-TABLE-COLUMN-CLASS for instance slot PROJECT-ID #x30200716D12D>)
;;  7: ((:INTERNAL MITO.DAO::MAKE-SET-CLAUSE) #<DAO-TABLE-COLUMN-CLASS for instance slot PROJECT-ID #x30200716D12D>)
;;  8: (CCL::MAP1 #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL MITO.DAO::MAKE-SET-CLAUSE) #x30200739D7BF> ((#<DAO-TABLE-COLUMN-CLASS for instance slot MITO.DAO.MIXIN::ID #x3020042C56FD> ..)))) :NCONC T)
;;  9: (MAPCAN #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL MITO.DAO::MAKE-SET-CLAUSE) #x30200739D7BF> (#<DAO-TABLE-COLUMN-CLASS for instance slot MITO.DAO.MIXIN::ID #x3020042C56FD> ..)))
;; 10: (MITO.DAO::MAKE-SET-CLAUSE #<ACTION2 #x30200739E03D>)
;; 11: (#<STANDARD-METHOD MITO.DAO:INSERT-DAO (MITO.DAO.TABLE:DAO-CLASS)> #<ACTION2 #x30200739E03D>)
;; 12: (CCL::%%STANDARD-COMBINED-METHOD-DCODE ((#<STANDARD-METHOD MITO.DAO:INSERT-DAO :BEFORE (MITO.DAO.MIXIN:RECORD-TIMESTAMPS-MIXIN)>) NIL ..) 17581893521117)
;; 13: (NIL #<Unknown Arguments>)
;; 14: (#<STANDARD-METHOD MITO.DAO:SAVE-DAO (MITO.DAO.TABLE:DAO-CLASS)> #<ACTION2 #x30200739E03D>)
;; 15: (CCL::CALL-CHECK-REGS MITO.DAO:SAVE-DAO #<ACTION2 #x30200739E03D>)
;; 16: (CCL::CHEAP-EVAL (MITO.DAO:SAVE-DAO (MAKE-INSTANCE 'ACTION2)))
svetlyak40wt commented 5 years ago

I'm still able to reproduce this issue on the latest Mito.

To reproduce issue

Create a qlfile with content

ql :all :latest

github mito fukamachi/mito

Run qlot to fetch all metadata

qlot install

Create a test lisp file test.lisp

;; (defpackage #:mito-test
;;   (:use #:cl))
;; (in-package mito-test)

(defclass project ()
  ((name :col-type :text))
  (:metaclass mito:dao-table-class))

(defclass with-link-to-project-mixin ()
  ((project :col-type project))
  (:metaclass mito:dao-table-mixin))

(defclass action (with-link-to-project-mixin)
  ()
  (:metaclass mito:dao-table-class))

(defun test-issue ()
  (mito:connect-toplevel :sqlite3
                         :database-name "db.sqlite")
  (mito:save-dao (make-instance 'action)))

Run test

qlot exec ros --eval '(ql:quickload :mito)' --load test.lisp --eval '(test-issue)'

Results for 2019-04-29

[art@lispbook:/tmp/check-mito]% qlot exec ros --eval '(ql:quickload :mito)' --load test.lisp --eval '(test-issue)'
To load "mito":
  Load 1 ASDF system:
    mito
; Loading "mito"
.....

debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {10005205B3}>:
  When attempting to read the slot's value (slot-value), the slot
  MITO.CLASS.TABLE::PARENT-COLUMN-MAP is missing from the object
  #<STANDARD-CLASS MITO.DAO.TABLE:DAO-CLASS>.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [CONTINUE] Ignore runtime option --eval "(ros:run '((:eval\"(ros:asdf)\")(:eval\"(ros:quicklisp)\")(:eval \"(ql:quickload :mito)\")(:load \"test.lisp\")(:eval \"(test-issue)\")(:quit)))".
  1: [ABORT   ] Skip rest of --eval and --load options.
  2:            Skip to toplevel READ/EVAL/PRINT loop.
  3: [EXIT    ] Exit SBCL (calling #'EXIT, killing the process).

((:METHOD SLOT-MISSING (T T T T)) #<unused argument> #<STANDARD-CLASS MITO.DAO.TABLE:DAO-CLASS> MITO.CLASS.TABLE::PARENT-COLUMN-MAP SLOT-VALUE NIL) [fast-method]
0]