|
This isn't the first time, I think it started occurring since the QL 2026-01 upgrade, not sure… I work on an existing app with an existing DB fine, I add a model field, I want to run the migrations and get: My new field: (publication-date
:accessor publication-date
:initarg :publication-date
:initform nil
:type (or null number)
:col-type (or :null :timestamp))WDYT? might be similar to #186
(defun migrate-all ()
"Migrate the tables after we changed the class definitions."
;; We'd rather use a "with-connexion" style to drop the connection afterwards.
;; Use mito:*auto-migration-mode* to nil to delete migration intermediate tables used with sqlite3.
(unless mito:*connection*
(error "Please connect to the DB."))
(ensure-tables-exist)
(mapcar #'mito:migrate-table (mito-admin::tables)))On Quicklisp 2026-01. |
Replies: 2 comments 2 replies
|
more SQL: in the last one, there's a dubious
-- |
|
Confirmed the bug. Here's what's going on. Root causeThe bug is in Here's what happens with your column:
So you end up with: INSERT INTO book (..., publication_date)
SELECT ..., () FROM book303
-- ^^^ should be NULLReproduction(ql:quickload :mito :silent t)
(defclass book ()
((title :col-type (:varchar 128)
:initarg :title))
(:metaclass mito:dao-table-class))
;; Create a temporary SQLite DB and table
(mito:connect-toplevel :sqlite3 :database-name "/tmp/repro-194.db")
(mapc #'mito:execute-sql (mito:table-definition 'book))
;; Add a nullable column with :initform nil
(defclass book ()
((title :col-type (:varchar 128)
:initarg :title)
(publication-date :col-type (or :null :timestamp)
:initarg :publication-date
:initform nil))
(:metaclass mito:dao-table-class))
;; Shows the bad SQL with ()
(mito:migration-expressions 'book)
;; Fails with: DB Error: near ")": syntax error
(mito:migrate-table 'book)
(mito:disconnect-toplevel)
(delete-file "/tmp/repro-194.db")FixIn the first ;; current code
((c2mop:slot-definition-initfunction slot)
(list
(cons (car new-column)
(convert-for-driver-type ...))))
;; fix
((c2mop:slot-definition-initfunction slot)
(let ((value (convert-for-driver-type
:sqlite3
(table-column-type slot)
(dao-table-column-deflate
slot
(funcall (c2mop:slot-definition-initfunction slot))))))
(when value
(list (cons (car new-column) value)))))This only affects the SQLite3 migration path. The non-SQLite path (line 193) already gets this right since it only sets a default when |
Confirmed the bug. Here's what's going on.
Root cause
The bug is in
migration-expressions-between-for-sqlite3insrc/migration/table.lisp(lines 119-127). When you add a new column that has an:initform, the SQLite migration builds anINSERT INTO ... SELECTto copy rows from the old table into the new one, plugging in a default value for the new column.Here's what happens with your column:
:initform nilcreates an initfunction, so(c2mop:slot-definition-initfunction slot)is non-nil and the firstcondbranch firesnildao-table-column-deflateandconvert-for-driver-typeboth passnilthrough unchangednilgets stored as(cons "publication_date" nil),…