@@ -1097,80 +1097,87 @@ findAlters
10971097 -> EntityDef
10981098 -- ^ The entity definition for the entity that we're working on.
10991099 -> Column
1100- -- ^ The column that we're searching for potential alterations for.
1100+ -- ^ The column that we're searching for potential alterations for, derived
1101+ -- from the Persistent EntityDef. That is: this is how we _want_ the column
1102+ -- to look, and not necessarily how it actually looks in the database right
1103+ -- now.
11011104 -> [Column ]
1105+ -- ^ The columns for this table, as they currently exist in the database.
11021106 -> ([AlterColumn ], [Column ])
1103- findAlters defs edef col @ ( Column name isNull sqltype def _gen _defConstraintName _maxLen ref) cols =
1104- case List. find (\ c -> cName c == name) cols of
1107+ findAlters defs edef newCol oldCols =
1108+ case List. find (\ c -> cName c == cName newCol) oldCols of
11051109 Nothing ->
1106- ([AddColumn col], cols )
1110+ ([AddColumn newCol] ++ refAdd (cReference newCol), oldCols )
11071111 Just
1108- ( Column _oldName isNull' sqltype' def' _gen' _defConstraintName' _maxLen' ref') ->
1112+ oldCol ->
11091113 let
11101114 refDrop Nothing = []
11111115 refDrop (Just ColumnReference {crConstraintName = cname}) =
11121116 [DropReference cname]
11131117
1114- refAdd Nothing = []
1115- refAdd (Just colRef) =
1116- case find ((== crTableName colRef) . getEntityDBName) defs of
1117- Just refdef
1118- | Just _oldName /= fmap fieldDB (getEntityIdField edef) ->
1119- [ AddReference
1120- (crTableName colRef)
1121- (crConstraintName colRef)
1122- (name NEL. :| [] )
1123- (NEL. toList $ Util. dbIdColumnsEsc escapeF refdef)
1124- (crFieldCascade colRef)
1125- ]
1126- Just _ -> []
1127- Nothing ->
1128- error $
1129- " could not find the entityDef for reftable["
1130- ++ show (crTableName colRef)
1131- ++ " ]"
11321118 modRef =
1133- if equivalentRef ref ref'
1119+ if equivalentRef (cReference oldCol) (cReference newCol)
11341120 then []
1135- else refDrop ref' ++ refAdd ref
1136- modNull = case (isNull, isNull' ) of
1121+ else refDrop (cReference oldCol) ++ refAdd (cReference newCol)
1122+ modNull = case (cNull newCol, cNull oldCol ) of
11371123 (True , False ) -> do
1138- guard $ Just name /= fmap fieldDB (getEntityIdField edef)
1139- pure (IsNull col )
1124+ guard $ Just (cName newCol) /= fmap fieldDB (getEntityIdField edef)
1125+ pure (IsNull newCol )
11401126 (False , True ) ->
11411127 let
1142- up = case def of
1128+ up = case cDefault newCol of
11431129 Nothing -> id
1144- Just s -> (:) (UpdateNullToValue col s)
1130+ Just s -> (:) (UpdateNullToValue newCol s)
11451131 in
1146- up [NotNull col ]
1132+ up [NotNull newCol ]
11471133 _ -> []
11481134 modType
1149- | sqlTypeEq sqltype sqltype' = []
1135+ | sqlTypeEq (cSqlType newCol) (cSqlType oldCol) = []
11501136 -- When converting from Persistent pre-2.0 databases, we
11511137 -- need to make sure that TIMESTAMP WITHOUT TIME ZONE is
11521138 -- treated as UTC.
1153- | sqltype == SqlDayTime && sqltype' == SqlOther " timestamp" =
1154- [ ChangeType col sqltype $
1139+ | cSqlType newCol == SqlDayTime && cSqlType oldCol == SqlOther " timestamp" =
1140+ [ ChangeType newCol (cSqlType newCol) $
11551141 T. concat
11561142 [ " USING "
1157- , escapeF name
1143+ , escapeF (cName newCol)
11581144 , " AT TIME ZONE 'UTC'"
11591145 ]
11601146 ]
1161- | otherwise = [ChangeType col sqltype " " ]
1147+ | otherwise = [ChangeType newCol (cSqlType newCol) " " ]
11621148 modDef =
1163- if def == def'
1164- || isJust (T. stripPrefix " nextval" =<< def' )
1149+ if cDefault newCol == cDefault oldCol
1150+ || isJust (T. stripPrefix " nextval" =<< cDefault oldCol )
11651151 then []
1166- else case def of
1167- Nothing -> [NoDefault col ]
1168- Just s -> [Default col s]
1152+ else case cDefault newCol of
1153+ Nothing -> [NoDefault newCol ]
1154+ Just s -> [Default newCol s]
11691155 dropSafe =
1170- if safeToRemove edef name
1171- then error " wtf" [Drop col (SafeToRemove True )]
1156+ if safeToRemove edef (cName newCol)
1157+ then error " wtf" [Drop newCol (SafeToRemove True )]
11721158 else []
11731159 in
11741160 ( modRef ++ modDef ++ modNull ++ modType ++ dropSafe
1175- , filter (\ c -> cName c /= name) cols
1161+ , filter (\ c -> cName c /= cName newCol) oldCols
11761162 )
1163+ where
1164+ refAdd Nothing = []
1165+ -- This check works around a bug where persistent will sometimes
1166+ -- generate an erroneous ForeignRef for ID fields.
1167+ -- See: https://github.com/yesodweb/persistent/issues/1615
1168+ refAdd _ | fmap fieldDB (getEntityIdField edef) == Just (cName newCol) = []
1169+ refAdd (Just colRef) =
1170+ case find ((== crTableName colRef) . getEntityDBName) defs of
1171+ Just refdef ->
1172+ [ AddReference
1173+ (crTableName colRef)
1174+ (crConstraintName colRef)
1175+ (cName newCol NEL. :| [] )
1176+ (NEL. toList $ Util. dbIdColumnsEsc escapeF refdef)
1177+ (crFieldCascade colRef)
1178+ ]
1179+ Nothing ->
1180+ error $
1181+ " could not find the entityDef for reftable["
1182+ ++ show (crTableName colRef)
1183+ ++ " ]"
0 commit comments