fukamachi / mito

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

underscores break slot names #117

Open einsiedlerspiel opened 1 year ago

einsiedlerspiel commented 1 year ago

I had trouble retrieving data via mito:select-dao and kept getting results with unbound slots, so i dug a bit deeper and found that mito currently can't retrieve data from tables where the slots of the table definition includes underscores.

(ql:quickload :mito)

(mito:connect-toplevel :mysql
                       :database-name "testDB"
                       :username username
                       :password passphrase
                       :host host)

(mito:deftable table1 ()
  ((entry_name :col-type (:varchar 100))))

(mito:deftable table2 ()
  ((entry-name :col-type (:varchar 100))))

(mapcar #'mito:ensure-table-exists '(table1 table2))

(mito:create-dao 'table1 :entry_name "entry1")
(mito:create-dao 'table2 :entry-name "entry2")

(setf table1-result (mito:select-dao 'table1))
(setf table2-result (mito:select-dao 'table2))

This works as expected with the table2, I can access the values of the returned object without problem:

(table2-entry-name (car table2-result))
;=> "entry2"

but with table1, it throws an error because the slot entry_name is unbound.

(table1-entry_name (car table1-result))
;=> ; Evaluation aborted on #<UNBOUND-SLOT ENTRY_NAME {10028CA253}>.
;     The slot COMMON-LISP-USER::ENTRY_NAME is unbound in the object
;     #<TABLE1 {1006110F73}>.

I've traced the problem back to retrieve-by-sql which produces the same output for both tables, i.e. at some point in that function the underscore in the slot name gets turned into a dash.

(mito:retrieve-by-sql (sxql:select :*
                        (sxql:from :table1)))
;=> ((:ID 1 :ENTRY-NAME "entry1" :CREATED-AT 3872237193 :UPDATED-AT 3872237193))

(mito:retrieve-by-sql (sxql:select :*
                        (sxql:from :table2)))
;=> ((:ID 1 :ENTRY-NAME "entry2" :CREATED-AT 3872237193 :UPDATED-AT 3872237193))

and sure enough retrieve-by-sql calls lispify which replaces all underscores with dashes

https://github.com/fukamachi/mito/blob/fcc8003b823925d8cd73fc77af1fcb6f0b70f6a7/src/core/util.lisp#L89-L93

So right now if you define a table with slot names that contain underscores it's impossible to retrieve data from that table/slot with mito functions, i don't think that's expected behavior.

As far as i can tell this behavior is a correlate to mito turning all dashes in slot names into underscores when creating table definitions. I think Mito should either check whether the user defined class uses underscores before changing them, or it should not allow to use underscores in the table definition in the first place and clearly document that it reverses the sql standard to only allow - where the former only allows _.