Skip to content

Commit 64d6b3f

Browse files
authored
Merge pull request yesodweb#781 from yesodweb/numericErrorMessage
Postgres: Improve error message when getting invalid scale/precision …
2 parents 682aa33 + 6c8bd8a commit 64d6b3f

3 files changed

Lines changed: 39 additions & 14 deletions

File tree

persistent-postgresql/ChangeLog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.8.1.1
2+
3+
* Added a more detailed error message when a `numeric` column's scale and precision can't be parsed. [#781](https://github.com/yesodweb/persistent/pull/781)
4+
15
## 2.8.1
26

37
* Implemented `connPutManySql` to utilize batched `putMany`. [#770](https://github.com/yesodweb/persistent/pull/770)

persistent-postgresql/Database/Persist/Postgresql.hs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -752,21 +752,21 @@ getAlters defs def (c1, u1) (c2, u2) =
752752
getColumn :: (Text -> IO Statement)
753753
-> DBName -> [PersistValue]
754754
-> IO (Either Text Column)
755-
getColumn getter tname [PersistText x, PersistText y, PersistText z, d, npre, nscl, maxlen] =
755+
getColumn getter tableName' [PersistText columnName, PersistText isNullable, PersistText typeName, defaultValue, numericPrecision, numericScale, maxlen] =
756756
case d' of
757757
Left s -> return $ Left s
758758
Right d'' ->
759759
let typeStr = case maxlen of
760-
PersistInt64 n -> T.concat [z, "(", T.pack (show n), ")"]
761-
_ -> z
760+
PersistInt64 n -> T.concat [typeName, "(", T.pack (show n), ")"]
761+
_ -> typeName
762762
in case getType typeStr of
763763
Left s -> return $ Left s
764764
Right t -> do
765-
let cname = DBName x
765+
let cname = DBName columnName
766766
ref <- getRef cname
767767
return $ Right Column
768768
{ cName = cname
769-
, cNull = y == "YES"
769+
, cNull = isNullable == "YES"
770770
, cSqlType = t
771771
, cDefault = fmap stripSuffixes d''
772772
, cDefaultConstraintName = Nothing
@@ -795,18 +795,18 @@ getColumn getter tname [PersistText x, PersistText y, PersistText z, d, npre, ns
795795
, "AND constraint_type='FOREIGN KEY' "
796796
, "AND constraint_name=?"
797797
]
798-
let ref = refName tname cname
798+
let ref = refName tableName' cname
799799
stmt <- getter sql
800800
with (stmtQuery stmt
801-
[ PersistText $ unDBName tname
801+
[ PersistText $ unDBName tableName'
802802
, PersistText $ unDBName ref
803803
]) (\src -> runConduit $ src .| do
804804
Just [PersistInt64 i] <- CL.head
805805
return $ if i == 0 then Nothing else Just (DBName "", ref))
806-
d' = case d of
806+
d' = case defaultValue of
807807
PersistNull -> Right Nothing
808808
PersistText t -> Right $ Just t
809-
_ -> Left $ T.pack $ "Invalid default column: " ++ show d
809+
_ -> Left $ T.pack $ "Invalid default column: " ++ show defaultValue
810810
getType "int4" = Right SqlInt32
811811
getType "int8" = Right SqlInt64
812812
getType "varchar" = Right SqlString
@@ -818,13 +818,34 @@ getColumn getter tname [PersistText x, PersistText y, PersistText z, d, npre, ns
818818
getType "float8" = Right SqlReal
819819
getType "bytea" = Right SqlBlob
820820
getType "time" = Right SqlTime
821-
getType "numeric" = getNumeric npre nscl
821+
getType "numeric" = getNumeric numericPrecision numericScale
822822
getType a = Right $ SqlOther a
823823

824824
getNumeric (PersistInt64 a) (PersistInt64 b) = Right $ SqlNumeric (fromIntegral a) (fromIntegral b)
825-
getNumeric a b = Left $ T.pack $ "Can not get numeric field precision, got: " ++ show a ++ " and " ++ show b ++ " as precision and scale"
826-
getColumn _ _ x =
827-
return $ Left $ T.pack $ "Invalid result from information_schema: " ++ show x
825+
getNumeric PersistNull PersistNull = Left $ T.concat
826+
[ "No precision and scale were specified for the column: "
827+
, columnName
828+
, " in table: "
829+
, unDBName tableName'
830+
, ". Postgres defaults to a maximum scale of 147,455 and precision of 16383,"
831+
, " which is probably not what you intended."
832+
, " Specify the values as numeric(total_digits, digits_after_decimal_place)."
833+
]
834+
getNumeric a b = Left $ T.concat
835+
[ "Can not get numeric field precision for the column: "
836+
, columnName
837+
, " in table: "
838+
, unDBName tableName'
839+
, ". Expected an integer for both precision and scale, "
840+
, "got: "
841+
, T.pack $ show a
842+
, " and "
843+
, T.pack $ show b
844+
, ", respectively."
845+
, " Specify the values as numeric(total_digits, digits_after_decimal_place)."
846+
]
847+
getColumn _ _ columnName =
848+
return $ Left $ T.pack $ "Invalid result from information_schema: " ++ show columnName
828849

829850
-- | Intelligent comparison of SQL types, to account for SqlInt32 vs SqlOther integer
830851
sqlTypeEq :: SqlType -> SqlType -> Bool

persistent-postgresql/persistent-postgresql.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: persistent-postgresql
2-
version: 2.8.1
2+
version: 2.8.1.1
33
license: MIT
44
license-file: LICENSE
55
author: Felipe Lessa, Michael Snoyman <michael@snoyman.com>

0 commit comments

Comments
 (0)