From 3744ffb62fb16179734b981b9c54a79a3b3ba5b8 Mon Sep 17 00:00:00 2001 From: Fumiaki Kinoshita Date: Thu, 7 Dec 2023 23:05:11 +0900 Subject: [PATCH] persistent-mysql: treat tinyint as SqlOther "tinyint", not SqlBool (#1526) * persistent-mysql: treat tinyint as SqlOther "tinyint", not SqlBool * persistent-mysql/test/MyInit: connect to 127.0.0.1 rather than localhost sometimes localhost doesn't work on Mac * persistent-mysql: test: add TINYINT and TINYINT(4) fields --- persistent-mysql/ChangeLog.md | 5 +++++ persistent-mysql/Database/Persist/MySQL.hs | 14 +++++++------- persistent-mysql/test/MyInit.hs | 2 +- persistent-mysql/test/main.hs | 8 +++++++- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/persistent-mysql/ChangeLog.md b/persistent-mysql/ChangeLog.md index 1a8cfae56..45e7e6d20 100644 --- a/persistent-mysql/ChangeLog.md +++ b/persistent-mysql/ChangeLog.md @@ -1,5 +1,10 @@ # Changelog for persistent-mysql +## 2.13.1.5 + +* [#1526](https://github.com/yesodweb/persistent/pull/1526) + * Parse `tinyint` column as `SqlOther "tinyint"` rather than `SqlBool`, fixing breakage in legitimate non-Boolean uses of `tinyint` on MySQL 8.0 + ## 2.13.1.4 * [#1459](https://github.com/yesodweb/persistent/pull/1459) diff --git a/persistent-mysql/Database/Persist/MySQL.hs b/persistent-mysql/Database/Persist/MySQL.hs index 76e01a81a..73f0a1ded 100644 --- a/persistent-mysql/Database/Persist/MySQL.hs +++ b/persistent-mysql/Database/Persist/MySQL.hs @@ -827,14 +827,16 @@ data ColumnInfo = ColumnInfo -- @INFORMATION_SCHEMA@ tables. parseColumnType :: Text -> ColumnInfo -> ExceptT String IO (SqlType, Maybe Integer) -- Ints --- The display width is deprecated and being removed in MySQL 8.X. To be --- consistent with earlier versions, which do report it, accept either +-- The display width is deprecated and being removed in MySQL 8.X +-- with [an exception of tinyint(1) which is used for boolean values](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-19.html#mysqld-8-0-19-deprecation-removal). +-- To be consistent with earlier versions, which do report it, accept either -- the bare type in `ciColumnType ci`, or the type adorned with the expected -- value for the display width (ie the defaults for int and bigint, or the -- value explicitly set in `showSqlType` for SqlBool). -- parseColumnType "tinyint" ci - | ciColumnType ci == "tinyint" || ciColumnType ci == "tinyint(1)" = return (SqlBool, Nothing) + | ciColumnType ci == "tinyint(1)" = return (SqlBool, Nothing) + | otherwise = return (SqlOther "tinyint", Nothing) parseColumnType "int" ci | ciColumnType ci == "int" || ciColumnType ci == "int(11)" = return (SqlInt32, Nothing) parseColumnType "bigint" ci @@ -1023,10 +1025,8 @@ showSqlType :: SqlType -> String showSqlType SqlBlob Nothing _ = "BLOB" showSqlType SqlBlob (Just i) _ = "VARBINARY(" ++ show i ++ ")" --- "tinyint(1)" has been used historically here. In MySQL 8, the display width --- is deprecated, and in the future it may need to be removed here. However, --- "(1)" is not the default in older MySQL versions, so for them omitting it --- would alter the exact form of the column type in the information_schema. +-- While integer widths are deprecated in MySQL 8.0, "tinyint(1)" remains as an exception. +-- cf. https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-19.html#mysqld-8-0-19-deprecation-removal showSqlType SqlBool _ _ = "TINYINT(1)" showSqlType SqlDay _ _ = "DATE" showSqlType SqlDayTime _ _ = "DATETIME" diff --git a/persistent-mysql/test/MyInit.hs b/persistent-mysql/test/MyInit.hs index ddd50c83f..311aebc4b 100644 --- a/persistent-mysql/test/MyInit.hs +++ b/persistent-mysql/test/MyInit.hs @@ -137,7 +137,7 @@ runConn f = do } _ <- if not travis then withMySQLPool baseConnectInfo - { connectHost = "localhost" + { connectHost = "127.0.0.1" , connectUser = "test" , connectPassword = "test" , connectDatabase = "test" diff --git a/persistent-mysql/test/main.hs b/persistent-mysql/test/main.hs index cd0a21804..f5c95b0c4 100644 --- a/persistent-mysql/test/main.hs +++ b/persistent-mysql/test/main.hs @@ -18,6 +18,7 @@ import MyInit import qualified Data.ByteString as BS import Data.Fixed +import Data.Int (Int8) import Data.IntMap (IntMap) import qualified Data.Text as T import Data.Time (Day, TimeOfDay, UTCTime(..), timeOfDayToTime, timeToTimeOfDay) @@ -90,6 +91,8 @@ DataTypeTable no-json -- off for older servers by defining OLD_MYSQL. timeFrac TimeOfDay sqltype=TIME(6) utcFrac UTCTime sqltype=DATETIME(6) + tinyint Int8 sqltype=TINYINT + tinyint4 Int8 sqltype=TINYINT(4) |] instance Arbitrary (DataTypeTableGeneric backend) where @@ -110,7 +113,8 @@ instance Arbitrary (DataTypeTableGeneric backend) where <*> (truncateUTCTime =<< arbitrary) -- utc <*> (truncateTimeOfDay =<< arbitrary) -- timeFrac <*> (truncateUTCTime =<< arbitrary) -- utcFrac - + <*> arbitrary -- tinyint + <*> choose (-8, 7) -- tinyint4 setup :: (HasCallStack, MonadUnliftIO m) => Migration -> ReaderT SqlBackend m () setup migration = do printMigration migration @@ -169,6 +173,8 @@ main = do , TestFn "utc" (roundUTCTime . dataTypeTableUtc) , TestFn "timeFrac" (dataTypeTableTimeFrac) , TestFn "utcFrac" (dataTypeTableUtcFrac) + , TestFn "tinyint" dataTypeTableTinyint + , TestFn "tinyint4" dataTypeTableTinyint4 ] [ ("pico", dataTypeTablePico) ] dataTypeTableDouble