yesodweb / yesodweb/persistent

Persistent generates invalid migration sql for MySQL when using 'default'

Open
#975 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Haskell
Stars
486
Forks
306
PR merge metrics
No merged PRs in 30d

Description

Hi all,

In an example scaffolded mysql Yesod project, my models file contains:

User
...
    ~createdat UTCTime default=current_timestamp  
    ~updatedat UTCTime default=current_timestamp

I run:

stack exec -- yesod devel
...
Starting devel application
Migrating: ALTER TABLE `user` ADD COLUMN `createdat` DATETIME NOT NULL DEFAULT current_timestamp
22/Oct/2019:15:31:39 +0200 [Debug#SQL] ALTER TABLE `user` ADD COLUMN `createdat` DATETIME NOT NULL DEFAULT current_timestamp; []
Migrating: ALTER TABLE `user` ADD COLUMN `updatedat` DATETIME NOT NULL DEFAULT current_timestamp
...
Migrating: ALTER TABLE `user` ALTER COLUMN `createdat` SET DEFAULT current_timestamp
22/Oct/2019:15:31:41 +0200 [Debug#SQL] ALTER TABLE `user` ALTER COLUMN `createdat` SET DEFAULT current_timestamp; []
devel.hs: ConnectionError {errFunction = "query", errNumber = 1064, errMessage = "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'current_timestamp' at line 1"}
Unexpected: child process exited with ExitFailure 1
Trying again
...

The invalid SQL that is generated being:

ALTER TABLE `user` ALTER COLUMN `createdat` SET DEFAULT current_timestamp

Which seems to give the same MySQL error when I run it by pasting on the mysql command line client directly. I think the correct syntax should be:

ALTER TABLE user CHANGE `createdat` `createdat` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;

This runs without error directly on the mysql client.

I notice that the first migrations that add the columns (including with the default) works (It's there when I run describe user directly), and that this additional ALTER migration isn't needed. The project will not run because of it.

I also tried with default=NOW() inside the models file, instead of current_timestamp, and also with double quotes like "default=current_timestamp" just to be certain, but the result is no different.

I will have to keep an auxiliary file of SQL commands to set MySQL triggers, to be run, as a work-around in the mean time.

Is this a bug, or am I using Persistent wrong?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the scaffolded models file and the SQL emitted by stack exec -- yesod devel, comparing the working ADD COLUMN statements with the failing ALTER statement. Inspect Persistent's MySQL migration generation for default changes; done means the reproduced migration runs successfully without invalid or unnecessary SQL.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell, mysql
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.