From 448a93f6cf3990ce10c64e9ab428275c17a19fa9 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 16 Aug 2023 11:05:05 +0200 Subject: [PATCH 1/4] Fix inconsistent client list error (happened in prod). --- services/brig/src/Brig/Data/Client.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/brig/src/Brig/Data/Client.hs b/services/brig/src/Brig/Data/Client.hs index 4fc538024a..9d359fd9d7 100644 --- a/services/brig/src/Brig/Data/Client.hs +++ b/services/brig/src/Brig/Data/Client.hs @@ -387,7 +387,7 @@ updateClientCapabilitiesQuery :: PrepQuery W (Maybe (C.Set ClientCapability), Us updateClientCapabilitiesQuery = "UPDATE clients SET capabilities = ? WHERE user = ? AND client = ?" updateClientLastActiveQuery :: PrepQuery W (UTCTime, UserId, ClientId) () -updateClientLastActiveQuery = "UPDATE clients SET last_active = ? WHERE user = ? AND client = ?" +updateClientLastActiveQuery = "UPDATE clients SET last_active = ? WHERE user = ? AND client = ? IF EXISTS" selectClientIds :: PrepQuery R (Identity UserId) (Identity ClientId) selectClientIds = "SELECT client from clients where user = ?" From d7e17c77f47b796de857cc215b9d402910daa0fa Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 16 Aug 2023 11:06:19 +0200 Subject: [PATCH 2/4] Changelog. --- changelog.d/3-bug-fixes/wpb-3888 | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/3-bug-fixes/wpb-3888 diff --git a/changelog.d/3-bug-fixes/wpb-3888 b/changelog.d/3-bug-fixes/wpb-3888 new file mode 100644 index 0000000000..84317f5b35 --- /dev/null +++ b/changelog.d/3-bug-fixes/wpb-3888 @@ -0,0 +1 @@ +Make sure cassandra updates do not re-introduce removed content. \ No newline at end of file From 383c749786ebc3867c6710abe4f744b393dcacb6 Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 16 Aug 2023 11:16:21 +0200 Subject: [PATCH 3/4] Fix all occurrances of the issue. --- services/brig/src/Brig/API/OAuth.hs | 2 +- services/brig/src/Brig/Data/Client.hs | 4 +- services/brig/src/Brig/Data/Connection.hs | 4 +- services/brig/src/Brig/Data/MLS/KeyPackage.hs | 2 +- services/brig/src/Brig/Data/User.hs | 42 +++++++------- services/brig/src/Brig/Provider/DB.hs | 30 +++++----- services/brig/src/Brig/Unique.hs | 4 +- .../brig/test/integration/API/User/Auth.hs | 2 +- .../galley/src/Galley/Cassandra/Queries.hs | 56 +++++++++---------- services/gundeck/src/Gundeck/Push/Data.hs | 2 +- .../src/Spar/Sem/IdPConfigStore/Cassandra.hs | 4 +- tools/db/migrate-sso-feature-flag/src/Work.hs | 2 +- tools/db/repair-handles/src/Work.hs | 2 +- 13 files changed, 78 insertions(+), 78 deletions(-) diff --git a/services/brig/src/Brig/API/OAuth.hs b/services/brig/src/Brig/API/OAuth.hs index c7ff94be6a..2a2da982a5 100644 --- a/services/brig/src/Brig/API/OAuth.hs +++ b/services/brig/src/Brig/API/OAuth.hs @@ -313,7 +313,7 @@ updateOAuthClient' :: (MonadClient m) => OAuthClientId -> OAuthApplicationName - updateOAuthClient' cid name uri = retry x5 . write q $ params LocalQuorum (name, uri, cid) where q :: PrepQuery W (OAuthApplicationName, RedirectUrl, OAuthClientId) () - q = "UPDATE oauth_client SET name = ?, redirect_uri = ? WHERE id = ?" + q = "UPDATE oauth_client SET name = ?, redirect_uri = ? WHERE id = ? IF EXISTS" insertOAuthClient :: (MonadClient m) => OAuthClientId -> OAuthApplicationName -> RedirectUrl -> Password -> m () insertOAuthClient cid name uri pw = retry x5 . write q $ params LocalQuorum (cid, name, uri, pw) diff --git a/services/brig/src/Brig/Data/Client.hs b/services/brig/src/Brig/Data/Client.hs index 9d359fd9d7..2714fcb8d8 100644 --- a/services/brig/src/Brig/Data/Client.hs +++ b/services/brig/src/Brig/Data/Client.hs @@ -381,10 +381,10 @@ insertClient :: PrepQuery W (UserId, ClientId, UTCTimeMillis, ClientType, Maybe insertClient = "INSERT INTO clients (user, client, tstamp, type, label, class, cookie, lat, lon, model, capabilities) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" updateClientLabelQuery :: PrepQuery W (Maybe Text, UserId, ClientId) () -updateClientLabelQuery = "UPDATE clients SET label = ? WHERE user = ? AND client = ?" +updateClientLabelQuery = "UPDATE clients SET label = ? WHERE user = ? AND client = ? IF EXISTS" updateClientCapabilitiesQuery :: PrepQuery W (Maybe (C.Set ClientCapability), UserId, ClientId) () -updateClientCapabilitiesQuery = "UPDATE clients SET capabilities = ? WHERE user = ? AND client = ?" +updateClientCapabilitiesQuery = "UPDATE clients SET capabilities = ? WHERE user = ? AND client = ? IF EXISTS" updateClientLastActiveQuery :: PrepQuery W (UTCTime, UserId, ClientId) () updateClientLastActiveQuery = "UPDATE clients SET last_active = ? WHERE user = ? AND client = ? IF EXISTS" diff --git a/services/brig/src/Brig/Data/Connection.hs b/services/brig/src/Brig/Data/Connection.hs index f4d8b56e3e..0b04a85ffa 100644 --- a/services/brig/src/Brig/Data/Connection.hs +++ b/services/brig/src/Brig/Data/Connection.hs @@ -340,7 +340,7 @@ connectionInsert :: PrepQuery W (UserId, UserId, RelationWithHistory, UTCTimeMil connectionInsert = "INSERT INTO connection (left, right, status, last_update, conv) VALUES (?, ?, ?, ?, ?)" connectionUpdate :: PrepQuery W (RelationWithHistory, UTCTimeMillis, UserId, UserId) () -connectionUpdate = "UPDATE connection SET status = ?, last_update = ? WHERE left = ? AND right = ?" +connectionUpdate = "UPDATE connection SET status = ?, last_update = ? WHERE left = ? AND right = ? IF EXISTS" connectionSelect :: PrepQuery R (UserId, UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe ConvId) connectionSelect = "SELECT left, right, status, last_update, conv FROM connection WHERE left = ? AND right = ?" @@ -391,7 +391,7 @@ remoteConnectionSelectFrom :: PrepQuery R (UserId, Domain, UserId) (RelationWith remoteConnectionSelectFrom = "SELECT status, last_update, conv_domain, conv_id FROM connection_remote where left = ? AND right_domain = ? AND right_user = ?" remoteConnectionUpdate :: PrepQuery W (RelationWithHistory, UTCTimeMillis, UserId, Domain, UserId) () -remoteConnectionUpdate = "UPDATE connection_remote set status = ?, last_update = ? WHERE left = ? and right_domain = ? and right_user = ?" +remoteConnectionUpdate = "UPDATE connection_remote set status = ?, last_update = ? WHERE left = ? and right_domain = ? and right_user = ? IF EXISTS" remoteConnectionDelete :: PrepQuery W (UserId, Domain, UserId) () remoteConnectionDelete = "DELETE FROM connection_remote where left = ? AND right_domain = ? AND right_user = ?" diff --git a/services/brig/src/Brig/Data/MLS/KeyPackage.hs b/services/brig/src/Brig/Data/MLS/KeyPackage.hs index 2bdd3abaac..1fe84ae038 100644 --- a/services/brig/src/Brig/Data/MLS/KeyPackage.hs +++ b/services/brig/src/Brig/Data/MLS/KeyPackage.hs @@ -193,7 +193,7 @@ addKeyPackageRef ref nkpr = do (params LocalQuorum (nkprClientId nkpr, qUnqualified (nkprConversation nkpr), qDomain (nkprConversation nkpr), qDomain (nkprUserId nkpr), qUnqualified (nkprUserId nkpr), ref)) where q :: PrepQuery W (ClientId, ConvId, Domain, Domain, UserId, KeyPackageRef) x - q = "UPDATE mls_key_package_refs SET client = ?, conv = ?, conv_domain = ?, domain = ?, user = ? WHERE ref = ?" + q = "UPDATE mls_key_package_refs SET client = ?, conv = ?, conv_domain = ?, domain = ?, user = ? WHERE ref = ? IF EXISTS" -- | Update key package ref, used in Galley when commit reveals key package ref update for the sender. -- Nothing is changed if the previous key package ref is not found in the table. diff --git a/services/brig/src/Brig/Data/User.hs b/services/brig/src/Brig/Data/User.hs index 1891e135f4..41b21f1da6 100644 --- a/services/brig/src/Brig/Data/User.hs +++ b/services/brig/src/Brig/Data/User.hs @@ -336,7 +336,7 @@ updateFeatureConferenceCalling uid mbStatus = do pure mbStatus where update :: PrepQuery W (Maybe ApiFt.FeatureStatus, UserId) () - update = fromString "update user set feature_conference_calling = ? where id = ?" + update = fromString "update user set feature_conference_calling = ? where id = ? if exists" deleteEmail :: MonadClient m => UserId -> m () deleteEmail u = retry x5 $ write userEmailDelete (params LocalQuorum (Identity u)) @@ -622,64 +622,64 @@ userInsert = \VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" userDisplayNameUpdate :: PrepQuery W (Name, UserId) () -userDisplayNameUpdate = "UPDATE user SET name = ? WHERE id = ?" +userDisplayNameUpdate = "UPDATE user SET name = ? WHERE id = ? IF EXISTS" userPictUpdate :: PrepQuery W (Pict, UserId) () -userPictUpdate = "UPDATE user SET picture = ? WHERE id = ?" +userPictUpdate = "UPDATE user SET picture = ? WHERE id = ? IF EXISTS" userAssetsUpdate :: PrepQuery W ([Asset], UserId) () -userAssetsUpdate = "UPDATE user SET assets = ? WHERE id = ?" +userAssetsUpdate = "UPDATE user SET assets = ? WHERE id = ? IF EXISTS" userAccentIdUpdate :: PrepQuery W (ColourId, UserId) () -userAccentIdUpdate = "UPDATE user SET accent_id = ? WHERE id = ?" +userAccentIdUpdate = "UPDATE user SET accent_id = ? WHERE id = ? IF EXISTS" userEmailUpdate :: PrepQuery W (Email, UserId) () -userEmailUpdate = "UPDATE user SET email = ? WHERE id = ?" +userEmailUpdate = "UPDATE user SET email = ? WHERE id = ? IF EXISTS" userEmailUnvalidatedUpdate :: PrepQuery W (Email, UserId) () -userEmailUnvalidatedUpdate = "UPDATE user SET email_unvalidated = ? WHERE id = ?" +userEmailUnvalidatedUpdate = "UPDATE user SET email_unvalidated = ? WHERE id = ? IF EXISTS" userEmailUnvalidatedDelete :: PrepQuery W (Identity UserId) () -userEmailUnvalidatedDelete = "UPDATE user SET email_unvalidated = null WHERE id = ?" +userEmailUnvalidatedDelete = "UPDATE user SET email_unvalidated = null WHERE id = ? IF EXISTS" userPhoneUpdate :: PrepQuery W (Phone, UserId) () -userPhoneUpdate = "UPDATE user SET phone = ? WHERE id = ?" +userPhoneUpdate = "UPDATE user SET phone = ? WHERE id = ? IF EXISTS" userSSOIdUpdate :: PrepQuery W (Maybe UserSSOId, UserId) () -userSSOIdUpdate = "UPDATE user SET sso_id = ? WHERE id = ?" +userSSOIdUpdate = "UPDATE user SET sso_id = ? WHERE id = ? IF EXISTS" userManagedByUpdate :: PrepQuery W (ManagedBy, UserId) () -userManagedByUpdate = "UPDATE user SET managed_by = ? WHERE id = ?" +userManagedByUpdate = "UPDATE user SET managed_by = ? WHERE id = ? IF EXISTS" userHandleUpdate :: PrepQuery W (Handle, UserId) () -userHandleUpdate = "UPDATE user SET handle = ? WHERE id = ?" +userHandleUpdate = "UPDATE user SET handle = ? WHERE id = ? IF EXISTS" userSupportedProtocolUpdate :: PrepQuery W (Set BaseProtocolTag, UserId) () -userSupportedProtocolUpdate = "UPDATE user SET supported_protocols = ? WHERE id = ?" +userSupportedProtocolUpdate = "UPDATE user SET supported_protocols = ? WHERE id = ? IF EXISTS" userPasswordUpdate :: PrepQuery W (Password, UserId) () -userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ?" +userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ? IF EXISTS" userStatusUpdate :: PrepQuery W (AccountStatus, UserId) () -userStatusUpdate = "UPDATE user SET status = ? WHERE id = ?" +userStatusUpdate = "UPDATE user SET status = ? WHERE id = ? IF EXISTS" userDeactivatedUpdate :: PrepQuery W (Identity UserId) () -userDeactivatedUpdate = "UPDATE user SET activated = false WHERE id = ?" +userDeactivatedUpdate = "UPDATE user SET activated = false WHERE id = ? IF EXISTS" userActivatedUpdate :: PrepQuery W (Maybe Email, Maybe Phone, UserId) () -userActivatedUpdate = "UPDATE user SET activated = true, email = ?, phone = ? WHERE id = ?" +userActivatedUpdate = "UPDATE user SET activated = true, email = ?, phone = ? WHERE id = ? IF EXISTS" userLocaleUpdate :: PrepQuery W (Language, Maybe Country, UserId) () -userLocaleUpdate = "UPDATE user SET language = ?, country = ? WHERE id = ?" +userLocaleUpdate = "UPDATE user SET language = ?, country = ? WHERE id = ? IF EXISTS" userEmailDelete :: PrepQuery W (Identity UserId) () -userEmailDelete = "UPDATE user SET email = null WHERE id = ?" +userEmailDelete = "UPDATE user SET email = null WHERE id = ? IF EXISTS" userPhoneDelete :: PrepQuery W (Identity UserId) () -userPhoneDelete = "UPDATE user SET phone = null WHERE id = ?" +userPhoneDelete = "UPDATE user SET phone = null WHERE id = ? IF EXISTS" userRichInfoUpdate :: PrepQuery W (RichInfoAssocList, UserId) () -userRichInfoUpdate = "UPDATE rich_info SET json = ? WHERE user = ?" +userRichInfoUpdate = "UPDATE rich_info SET json = ? WHERE user = ? IF EXISTS" ------------------------------------------------------------------------------- -- Conversions diff --git a/services/brig/src/Brig/Provider/DB.hs b/services/brig/src/Brig/Provider/DB.hs index ab7f85df1b..a5d9fd3800 100644 --- a/services/brig/src/Brig/Provider/DB.hs +++ b/services/brig/src/Brig/Provider/DB.hs @@ -72,11 +72,11 @@ updateAccountProfile p name url descr = retry x5 . batch $ do for_ descr $ \x -> addPrepQuery cqlDescr (x, p) where cqlName :: PrepQuery W (Name, ProviderId) () - cqlName = "UPDATE provider SET name = ? WHERE id = ?" + cqlName = "UPDATE provider SET name = ? WHERE id = ? IF EXISTS" cqlUrl :: PrepQuery W (HttpsUrl, ProviderId) () - cqlUrl = "UPDATE provider SET url = ? WHERE id = ?" + cqlUrl = "UPDATE provider SET url = ? WHERE id = ? IF EXISTS" cqlDescr :: PrepQuery W (Text, ProviderId) () - cqlDescr = "UPDATE provider SET descr = ? WHERE id = ?" + cqlDescr = "UPDATE provider SET descr = ? WHERE id = ? IF EXISTS" -- | Lookup the raw account data of a (possibly unverified) provider. lookupAccountData :: @@ -136,7 +136,7 @@ updateAccountPassword pid pwd = do retry x5 $ write cql $ params LocalQuorum (p, pid) where cql :: PrepQuery W (Password, ProviderId) () - cql = "UPDATE provider SET password = ? where id = ?" + cql = "UPDATE provider SET password = ? where id = ? IF EXISTS" -------------------------------------------------------------------------------- -- Unique (Natural) Keys @@ -159,7 +159,7 @@ insertKey p old new = retry x5 . batch $ do cqlKeyDelete :: PrepQuery W (Identity Text) () cqlKeyDelete = "DELETE FROM provider_keys WHERE key = ?" cqlEmail :: PrepQuery W (Email, ProviderId) () - cqlEmail = "UPDATE provider SET email = ? WHERE id = ?" + cqlEmail = "UPDATE provider SET email = ? WHERE id = ? IF EXISTS" lookupKey :: MonadClient m => @@ -306,15 +306,15 @@ updateService pid sid svcName svcTags nameChange summary descr assets tagsChange for_ assets $ \x -> addPrepQuery cqlAssets (x, pid, sid) where cqlName :: PrepQuery W (Name, ProviderId, ServiceId) () - cqlName = "UPDATE service SET name = ? WHERE provider = ? AND id = ?" + cqlName = "UPDATE service SET name = ? WHERE provider = ? AND id = ? IF EXISTS" cqlSummary :: PrepQuery W (Text, ProviderId, ServiceId) () - cqlSummary = "UPDATE service SET summary = ? WHERE provider = ? AND id = ?" + cqlSummary = "UPDATE service SET summary = ? WHERE provider = ? AND id = ? IF EXISTS" cqlDescr :: PrepQuery W (Text, ProviderId, ServiceId) () - cqlDescr = "UPDATE service SET descr = ? WHERE provider = ? AND id = ?" + cqlDescr = "UPDATE service SET descr = ? WHERE provider = ? AND id = ? IF EXISTS" cqlAssets :: PrepQuery W ([Asset], ProviderId, ServiceId) () - cqlAssets = "UPDATE service SET assets = ? WHERE provider = ? AND id = ?" + cqlAssets = "UPDATE service SET assets = ? WHERE provider = ? AND id = ? IF EXISTS" cqlTags :: PrepQuery W (C.Set ServiceTag, ProviderId, ServiceId) () - cqlTags = "UPDATE service SET tags = ? WHERE provider = ? AND id = ?" + cqlTags = "UPDATE service SET tags = ? WHERE provider = ? AND id = ? IF EXISTS" -- NB: can take a significant amount of time if many teams were using the service deleteService :: @@ -437,15 +437,15 @@ updateServiceConn pid sid url tokens keys enabled = retry x5 . batch $ do where (pks, fps) = (fmap fst &&& fmap snd) (unzip . toList <$> keys) cqlBaseUrl :: PrepQuery W (HttpsUrl, ProviderId, ServiceId) () - cqlBaseUrl = "UPDATE service SET base_url = ? WHERE provider = ? AND id = ?" + cqlBaseUrl = "UPDATE service SET base_url = ? WHERE provider = ? AND id = ? IF EXISTS" cqlTokens :: PrepQuery W (List1 ServiceToken, ProviderId, ServiceId) () - cqlTokens = "UPDATE service SET auth_tokens = ? WHERE provider = ? AND id = ?" + cqlTokens = "UPDATE service SET auth_tokens = ? WHERE provider = ? AND id = ? IF EXISTS" cqlKeys :: PrepQuery W ([ServiceKey], ProviderId, ServiceId) () - cqlKeys = "UPDATE service SET pubkeys = ? WHERE provider = ? AND id = ?" + cqlKeys = "UPDATE service SET pubkeys = ? WHERE provider = ? AND id = ? IF EXISTS" cqlFps :: PrepQuery W ([Fingerprint Rsa], ProviderId, ServiceId) () - cqlFps = "UPDATE service SET fingerprints = ? WHERE provider = ? AND id = ?" + cqlFps = "UPDATE service SET fingerprints = ? WHERE provider = ? AND id = ? IF EXISTS" cqlEnabled :: PrepQuery W (Bool, ProviderId, ServiceId) () - cqlEnabled = "UPDATE service SET enabled = ? WHERE provider = ? AND id = ?" + cqlEnabled = "UPDATE service SET enabled = ? WHERE provider = ? AND id = ? IF EXISTS" -------------------------------------------------------------------------------- -- Service "Indexes" (tag and prefix); contain only enabled services diff --git a/services/brig/src/Brig/Unique.hs b/services/brig/src/Brig/Unique.hs index 88e325e8c4..81c24aed76 100644 --- a/services/brig/src/Brig/Unique.hs +++ b/services/brig/src/Brig/Unique.hs @@ -72,7 +72,7 @@ withClaim u v t io = do then liftIO $ timeout (fromIntegral ttl # Second) io else pure Nothing cql :: PrepQuery W (Int32, C.Set (Id a), Text) () - cql = "UPDATE unique_claims USING TTL ? SET claims = claims + ? WHERE value = ?" + cql = "UPDATE unique_claims USING TTL ? SET claims = claims + ? WHERE value = ? IF EXISTS" deleteClaim :: MonadClient m => @@ -91,7 +91,7 @@ deleteClaim u v t = do retry x5 $ write cql $ params LocalQuorum (ttl * 2, C.Set [u], v) where cql :: PrepQuery W (Int32, C.Set (Id a), Text) () - cql = "UPDATE unique_claims USING TTL ? SET claims = claims - ? WHERE value = ?" + cql = "UPDATE unique_claims USING TTL ? SET claims = claims - ? WHERE value = ? IF EXISTS" -- | Lookup the current claims on a value. lookupClaims :: MonadClient m => Text -> m [Id a] diff --git a/services/brig/test/integration/API/User/Auth.hs b/services/brig/test/integration/API/User/Auth.hs index 8979a1b941..be66d96677 100644 --- a/services/brig/test/integration/API/User/Auth.hs +++ b/services/brig/test/integration/API/User/Auth.hs @@ -212,7 +212,7 @@ testLoginWith6CharPassword brig db = do p <- liftIO $ mkSafePassword t retry x5 $ write userPasswordUpdate (params LocalQuorum (p, u)) userPasswordUpdate :: PrepQuery W (Password, UserId) () - userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ?" + userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ? IF EXISTS" -------------------------------------------------------------------------------- -- ZAuth test environment for generating arbitrary tokens. diff --git a/services/galley/src/Galley/Cassandra/Queries.hs b/services/galley/src/Galley/Cassandra/Queries.hs index e04507c944..d88de5ff07 100644 --- a/services/galley/src/Galley/Cassandra/Queries.hs +++ b/services/galley/src/Galley/Cassandra/Queries.hs @@ -177,7 +177,7 @@ listTeamAdmins :: PrepQuery R (Identity TeamId) (Identity UserId) listTeamAdmins = "select user from team_admin where team = ?" updatePermissions :: PrepQuery W (Permissions, TeamId, UserId) () -updatePermissions = "update team_member set perms = ? where team = ? and user = ?" +updatePermissions = "update team_member set perms = ? where team = ? and user = ? IF EXISTS" insertUserTeam :: PrepQuery W (UserId, TeamId) () insertUserTeam = "insert into user_team (user, team) values (?, ?)" @@ -186,25 +186,25 @@ deleteUserTeam :: PrepQuery W (UserId, TeamId) () deleteUserTeam = "delete from user_team where user = ? and team = ?" markTeamDeleted :: PrepQuery W (TeamStatus, TeamId) () -markTeamDeleted = "update team set status = ? where team = ?" +markTeamDeleted = "update team set status = ? where team = ? IF EXISTS" deleteTeam :: PrepQuery W (TeamStatus, TeamId) () -deleteTeam = "update team using timestamp 32503680000000000 set name = 'default', icon = 'default', status = ? where team = ? " +deleteTeam = "update team using timestamp 32503680000000000 set name = 'default', icon = 'default', status = ? where team = ? IF EXISTS" updateTeamName :: PrepQuery W (Text, TeamId) () -updateTeamName = "update team set name = ? where team = ?" +updateTeamName = "update team set name = ? where team = ? IF EXISTS" updateTeamIcon :: PrepQuery W (Text, TeamId) () -updateTeamIcon = "update team set icon = ? where team = ?" +updateTeamIcon = "update team set icon = ? where team = ? IF EXISTS" updateTeamIconKey :: PrepQuery W (Text, TeamId) () -updateTeamIconKey = "update team set icon_key = ? where team = ?" +updateTeamIconKey = "update team set icon_key = ? where team = ? IF EXISTS" updateTeamStatus :: PrepQuery W (TeamStatus, TeamId) () -updateTeamStatus = "update team set status = ? where team = ?" +updateTeamStatus = "update team set status = ? where team = ? IF EXISTS" updateTeamSplashScreen :: PrepQuery W (Text, TeamId) () -updateTeamSplashScreen = "update team set splash_screen = ? where team = ?" +updateTeamSplashScreen = "update team set splash_screen = ? where team = ? IF EXISTS" -- Conversations ------------------------------------------------------------ @@ -264,34 +264,34 @@ insertMLSSelfConv = <> ", ?, ?)" updateConvAccess :: PrepQuery W (C.Set Access, C.Set AccessRole, ConvId) () -updateConvAccess = "update conversation set access = ?, access_roles_v2 = ? where conv = ?" +updateConvAccess = "update conversation set access = ?, access_roles_v2 = ? where conv = ? IF EXISTS" updateConvReceiptMode :: PrepQuery W (ReceiptMode, ConvId) () -updateConvReceiptMode = "update conversation set receipt_mode = ? where conv = ?" +updateConvReceiptMode = "update conversation set receipt_mode = ? where conv = ? IF EXISTS" updateConvMessageTimer :: PrepQuery W (Maybe Milliseconds, ConvId) () -updateConvMessageTimer = "update conversation set message_timer = ? where conv = ?" +updateConvMessageTimer = "update conversation set message_timer = ? where conv = ? IF EXISTS" updateConvName :: PrepQuery W (Text, ConvId) () -updateConvName = "update conversation set name = ? where conv = ?" +updateConvName = "update conversation set name = ? where conv = ? IF EXISTS" updateConvType :: PrepQuery W (ConvType, ConvId) () -updateConvType = "update conversation set type = ? where conv = ?" +updateConvType = "update conversation set type = ? where conv = ? IF EXISTS" updateConvEpoch :: PrepQuery W (Epoch, ConvId) () -updateConvEpoch = "update conversation set epoch = ? where conv = ?" +updateConvEpoch = "update conversation set epoch = ? where conv = ? IF EXISTS" deleteConv :: PrepQuery W (Identity ConvId) () deleteConv = "delete from conversation using timestamp 32503680000000000 where conv = ?" markConvDeleted :: PrepQuery W (Identity ConvId) () -markConvDeleted = "update conversation set deleted = true where conv = ?" +markConvDeleted = "update conversation set deleted = true where conv = ? IF EXISTS" selectPublicGroupState :: PrepQuery R (Identity ConvId) (Identity (Maybe OpaquePublicGroupState)) selectPublicGroupState = "select public_group_state from conversation where conv = ?" updatePublicGroupState :: PrepQuery W (OpaquePublicGroupState, ConvId) () -updatePublicGroupState = "update conversation set public_group_state = ? where conv = ?" +updatePublicGroupState = "update conversation set public_group_state = ? where conv = ? IF EXISTS" -- Conversations accessible by code ----------------------------------------- @@ -349,16 +349,16 @@ removeMember :: PrepQuery W (ConvId, UserId) () removeMember = "delete from member where conv = ? and user = ?" updateOtrMemberMutedStatus :: PrepQuery W (MutedStatus, Maybe Text, ConvId, UserId) () -updateOtrMemberMutedStatus = "update member set otr_muted_status = ?, otr_muted_ref = ? where conv = ? and user = ?" +updateOtrMemberMutedStatus = "update member set otr_muted_status = ?, otr_muted_ref = ? where conv = ? and user = ? IF EXISTS" updateOtrMemberArchived :: PrepQuery W (Bool, Maybe Text, ConvId, UserId) () -updateOtrMemberArchived = "update member set otr_archived = ?, otr_archived_ref = ? where conv = ? and user = ?" +updateOtrMemberArchived = "update member set otr_archived = ?, otr_archived_ref = ? where conv = ? and user = ? IF EXISTS" updateMemberHidden :: PrepQuery W (Bool, Maybe Text, ConvId, UserId) () -updateMemberHidden = "update member set hidden = ?, hidden_ref = ? where conv = ? and user = ?" +updateMemberHidden = "update member set hidden = ?, hidden_ref = ? where conv = ? and user = ? IF EXISTS" updateMemberConvRoleName :: PrepQuery W (RoleName, ConvId, UserId) () -updateMemberConvRoleName = "update member set conversation_role = ? where conv = ? and user = ?" +updateMemberConvRoleName = "update member set conversation_role = ? where conv = ? and user = ? IF EXISTS" -- Federated conversations ----------------------------------------------------- -- @@ -379,7 +379,7 @@ selectRemoteMembers :: PrepQuery R (Identity ConvId) (Domain, UserId, RoleName) selectRemoteMembers = "select user_remote_domain, user_remote_id, conversation_role from member_remote_user where conv = ?" updateRemoteMemberConvRoleName :: PrepQuery W (RoleName, ConvId, Domain, UserId) () -updateRemoteMemberConvRoleName = "update member_remote_user set conversation_role = ? where conv = ? and user_remote_domain = ? and user_remote_id = ?" +updateRemoteMemberConvRoleName = "update member_remote_user set conversation_role = ? where conv = ? and user_remote_domain = ? and user_remote_id = ? IF EXISTS" -- Used when removing a federation domain, so that we can quickly list all of the affected remote users and conversations -- This returns local conversation IDs and remote users @@ -411,13 +411,13 @@ selectLocalMembersByDomain = "select conv_remote_id, user from user_remote_conv -- remote conversation status for local user updateRemoteOtrMemberMutedStatus :: PrepQuery W (MutedStatus, Maybe Text, Domain, ConvId, UserId) () -updateRemoteOtrMemberMutedStatus = "update user_remote_conv set otr_muted_status = ?, otr_muted_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ?" +updateRemoteOtrMemberMutedStatus = "update user_remote_conv set otr_muted_status = ?, otr_muted_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ? IF EXISTS" updateRemoteOtrMemberArchived :: PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) () -updateRemoteOtrMemberArchived = "update user_remote_conv set otr_archived = ?, otr_archived_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ?" +updateRemoteOtrMemberArchived = "update user_remote_conv set otr_archived = ?, otr_archived_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ? IF EXISTS" updateRemoteMemberHidden :: PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) () -updateRemoteMemberHidden = "update user_remote_conv set hidden = ?, hidden_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ?" +updateRemoteMemberHidden = "update user_remote_conv set hidden = ?, hidden_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ? IF EXISTS" selectRemoteMemberStatus :: PrepQuery R (Domain, ConvId, UserId) (Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool, Maybe Text) selectRemoteMemberStatus = "select otr_muted_status, otr_muted_ref, otr_archived, otr_archived_ref, hidden, hidden_ref from user_remote_conv where conv_remote_domain = ? and conv_remote_id = ? and user = ?" @@ -433,12 +433,12 @@ rmClients = "delete from clients where user = ?" addMemberClient :: ClientId -> QueryString W (Identity UserId) () addMemberClient c = let t = LT.fromStrict (client c) - in QueryString $ "update clients set clients = clients + {'" <> t <> "'} where user = ?" + in QueryString $ "update clients set clients = clients + {'" <> t <> "'} where user = ? IF EXISTS" rmMemberClient :: ClientId -> QueryString W (Identity UserId) () rmMemberClient c = let t = LT.fromStrict (client c) - in QueryString $ "update clients set clients = clients - {'" <> t <> "'} where user = ?" + in QueryString $ "update clients set clients = clients - {'" <> t <> "'} where user = ? IF EXISTS" -- MLS Clients -------------------------------------------------------------- @@ -553,7 +553,7 @@ selectSearchVisibility = updateSearchVisibility :: PrepQuery W (TeamSearchVisibility, TeamId) () updateSearchVisibility = - "update team set search_visibility = ? where team = ?" + "update team set search_visibility = ? where team = ? IF EXISTS" -- Custom Backend ----------------------------------------------------------- @@ -563,7 +563,7 @@ selectCustomBackend = updateCustomBackend :: PrepQuery W (HttpsUrl, HttpsUrl, Domain) () updateCustomBackend = - "update custom_backend set config_json_url = ?, webapp_welcome_url = ? where domain = ?" + "update custom_backend set config_json_url = ?, webapp_welcome_url = ? where domain = ? IF EXISTS" deleteCustomBackend :: PrepQuery W (Identity Domain) () deleteCustomBackend = diff --git a/services/gundeck/src/Gundeck/Push/Data.hs b/services/gundeck/src/Gundeck/Push/Data.hs index f00ddc1903..c3976ffc7c 100644 --- a/services/gundeck/src/Gundeck/Push/Data.hs +++ b/services/gundeck/src/Gundeck/Push/Data.hs @@ -52,7 +52,7 @@ updateArn :: MonadClient m => UserId -> Transport -> AppName -> Token -> Endpoin updateArn uid transport app token arn = retry x5 $ write q (params LocalQuorum (arn, uid, transport, app, token)) where q :: PrepQuery W (EndpointArn, UserId, Transport, AppName, Token) () - q = "update user_push set arn = ? where usr = ? and transport = ? and app = ? and ptoken = ?" + q = "update user_push set arn = ? where usr = ? and transport = ? and app = ? and ptoken = ? IF EXISTS" delete :: MonadClient m => UserId -> Transport -> AppName -> Token -> m () delete u t a p = retry x5 $ write q (params LocalQuorum (u, t, a, p)) diff --git a/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs b/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs index 2b3d347007..6ae8659117 100644 --- a/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs +++ b/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs @@ -356,7 +356,7 @@ setReplacedBy (Replaced old) (Replacing new) = do retry x5 . write ins $ params LocalQuorum (new, old) where ins :: PrepQuery W (SAML.IdPId, SAML.IdPId) () - ins = "UPDATE idp SET replaced_by = ? WHERE idp = ?" + ins = "UPDATE idp SET replaced_by = ? WHERE idp = ? IF EXISTS" -- | See also: 'setReplacedBy'. clearReplacedBy :: @@ -367,7 +367,7 @@ clearReplacedBy (Replaced old) = do retry x5 . write ins $ params LocalQuorum (Identity old) where ins :: PrepQuery W (Identity SAML.IdPId) () - ins = "UPDATE idp SET replaced_by = null WHERE idp = ?" + ins = "UPDATE idp SET replaced_by = null WHERE idp = ? IF EXISTS" -- | If the IdP is 'WireIdPAPIV1', it must be deleted globally, if it is 'WireIdPAPIV2', it -- must be deleted inside one team. 'V1' can be either in the old table without team index, diff --git a/tools/db/migrate-sso-feature-flag/src/Work.hs b/tools/db/migrate-sso-feature-flag/src/Work.hs index ff56a09447..275fec582d 100644 --- a/tools/db/migrate-sso-feature-flag/src/Work.hs +++ b/tools/db/migrate-sso-feature-flag/src/Work.hs @@ -68,4 +68,4 @@ writeSsoFlags = mapM_ (`setSSOTeamConfig` FeatureStatusEnabled) setSSOTeamConfig tid ssoTeamConfigStatus = do retry x5 $ write updateSSOTeamConfig (params LocalQuorum (ssoTeamConfigStatus, tid)) updateSSOTeamConfig :: PrepQuery W (FeatureStatus, TeamId) () - updateSSOTeamConfig = "update team_features set sso_status = ? where team_id = ?" + updateSSOTeamConfig = "update team_features set sso_status = ? where team_id = ? IF EXISTS" diff --git a/tools/db/repair-handles/src/Work.hs b/tools/db/repair-handles/src/Work.hs index 7b91c7c98c..2bfc866b7a 100644 --- a/tools/db/repair-handles/src/Work.hs +++ b/tools/db/repair-handles/src/Work.hs @@ -142,7 +142,7 @@ executeAction env = \case params LocalQuorum (handle, uid) where updateHandle :: PrepQuery W (Handle, UserId) () - updateHandle = "UPDATE user SET handle = ? WHERE id = ?" + updateHandle = "UPDATE user SET handle = ? WHERE id = ? IF EXISTS" removeHandle :: Env -> Handle -> IO () removeHandle Env {..} handle = From 44da604fdb2ee8b30e86ccd7b5d048bc0aa6872d Mon Sep 17 00:00:00 2001 From: Matthias Fischmann Date: Wed, 16 Aug 2023 11:46:54 +0200 Subject: [PATCH 4/4] Revert "Fix all occurrances of the issue." This reverts commit 383c749786ebc3867c6710abe4f744b393dcacb6. --- services/brig/src/Brig/API/OAuth.hs | 2 +- services/brig/src/Brig/Data/Client.hs | 4 +- services/brig/src/Brig/Data/Connection.hs | 4 +- services/brig/src/Brig/Data/MLS/KeyPackage.hs | 2 +- services/brig/src/Brig/Data/User.hs | 42 +++++++------- services/brig/src/Brig/Provider/DB.hs | 30 +++++----- services/brig/src/Brig/Unique.hs | 4 +- .../brig/test/integration/API/User/Auth.hs | 2 +- .../galley/src/Galley/Cassandra/Queries.hs | 56 +++++++++---------- services/gundeck/src/Gundeck/Push/Data.hs | 2 +- .../src/Spar/Sem/IdPConfigStore/Cassandra.hs | 4 +- tools/db/migrate-sso-feature-flag/src/Work.hs | 2 +- tools/db/repair-handles/src/Work.hs | 2 +- 13 files changed, 78 insertions(+), 78 deletions(-) diff --git a/services/brig/src/Brig/API/OAuth.hs b/services/brig/src/Brig/API/OAuth.hs index 2a2da982a5..c7ff94be6a 100644 --- a/services/brig/src/Brig/API/OAuth.hs +++ b/services/brig/src/Brig/API/OAuth.hs @@ -313,7 +313,7 @@ updateOAuthClient' :: (MonadClient m) => OAuthClientId -> OAuthApplicationName - updateOAuthClient' cid name uri = retry x5 . write q $ params LocalQuorum (name, uri, cid) where q :: PrepQuery W (OAuthApplicationName, RedirectUrl, OAuthClientId) () - q = "UPDATE oauth_client SET name = ?, redirect_uri = ? WHERE id = ? IF EXISTS" + q = "UPDATE oauth_client SET name = ?, redirect_uri = ? WHERE id = ?" insertOAuthClient :: (MonadClient m) => OAuthClientId -> OAuthApplicationName -> RedirectUrl -> Password -> m () insertOAuthClient cid name uri pw = retry x5 . write q $ params LocalQuorum (cid, name, uri, pw) diff --git a/services/brig/src/Brig/Data/Client.hs b/services/brig/src/Brig/Data/Client.hs index 2714fcb8d8..9d359fd9d7 100644 --- a/services/brig/src/Brig/Data/Client.hs +++ b/services/brig/src/Brig/Data/Client.hs @@ -381,10 +381,10 @@ insertClient :: PrepQuery W (UserId, ClientId, UTCTimeMillis, ClientType, Maybe insertClient = "INSERT INTO clients (user, client, tstamp, type, label, class, cookie, lat, lon, model, capabilities) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" updateClientLabelQuery :: PrepQuery W (Maybe Text, UserId, ClientId) () -updateClientLabelQuery = "UPDATE clients SET label = ? WHERE user = ? AND client = ? IF EXISTS" +updateClientLabelQuery = "UPDATE clients SET label = ? WHERE user = ? AND client = ?" updateClientCapabilitiesQuery :: PrepQuery W (Maybe (C.Set ClientCapability), UserId, ClientId) () -updateClientCapabilitiesQuery = "UPDATE clients SET capabilities = ? WHERE user = ? AND client = ? IF EXISTS" +updateClientCapabilitiesQuery = "UPDATE clients SET capabilities = ? WHERE user = ? AND client = ?" updateClientLastActiveQuery :: PrepQuery W (UTCTime, UserId, ClientId) () updateClientLastActiveQuery = "UPDATE clients SET last_active = ? WHERE user = ? AND client = ? IF EXISTS" diff --git a/services/brig/src/Brig/Data/Connection.hs b/services/brig/src/Brig/Data/Connection.hs index 0b04a85ffa..f4d8b56e3e 100644 --- a/services/brig/src/Brig/Data/Connection.hs +++ b/services/brig/src/Brig/Data/Connection.hs @@ -340,7 +340,7 @@ connectionInsert :: PrepQuery W (UserId, UserId, RelationWithHistory, UTCTimeMil connectionInsert = "INSERT INTO connection (left, right, status, last_update, conv) VALUES (?, ?, ?, ?, ?)" connectionUpdate :: PrepQuery W (RelationWithHistory, UTCTimeMillis, UserId, UserId) () -connectionUpdate = "UPDATE connection SET status = ?, last_update = ? WHERE left = ? AND right = ? IF EXISTS" +connectionUpdate = "UPDATE connection SET status = ?, last_update = ? WHERE left = ? AND right = ?" connectionSelect :: PrepQuery R (UserId, UserId) (UserId, UserId, RelationWithHistory, UTCTimeMillis, Maybe ConvId) connectionSelect = "SELECT left, right, status, last_update, conv FROM connection WHERE left = ? AND right = ?" @@ -391,7 +391,7 @@ remoteConnectionSelectFrom :: PrepQuery R (UserId, Domain, UserId) (RelationWith remoteConnectionSelectFrom = "SELECT status, last_update, conv_domain, conv_id FROM connection_remote where left = ? AND right_domain = ? AND right_user = ?" remoteConnectionUpdate :: PrepQuery W (RelationWithHistory, UTCTimeMillis, UserId, Domain, UserId) () -remoteConnectionUpdate = "UPDATE connection_remote set status = ?, last_update = ? WHERE left = ? and right_domain = ? and right_user = ? IF EXISTS" +remoteConnectionUpdate = "UPDATE connection_remote set status = ?, last_update = ? WHERE left = ? and right_domain = ? and right_user = ?" remoteConnectionDelete :: PrepQuery W (UserId, Domain, UserId) () remoteConnectionDelete = "DELETE FROM connection_remote where left = ? AND right_domain = ? AND right_user = ?" diff --git a/services/brig/src/Brig/Data/MLS/KeyPackage.hs b/services/brig/src/Brig/Data/MLS/KeyPackage.hs index 1fe84ae038..2bdd3abaac 100644 --- a/services/brig/src/Brig/Data/MLS/KeyPackage.hs +++ b/services/brig/src/Brig/Data/MLS/KeyPackage.hs @@ -193,7 +193,7 @@ addKeyPackageRef ref nkpr = do (params LocalQuorum (nkprClientId nkpr, qUnqualified (nkprConversation nkpr), qDomain (nkprConversation nkpr), qDomain (nkprUserId nkpr), qUnqualified (nkprUserId nkpr), ref)) where q :: PrepQuery W (ClientId, ConvId, Domain, Domain, UserId, KeyPackageRef) x - q = "UPDATE mls_key_package_refs SET client = ?, conv = ?, conv_domain = ?, domain = ?, user = ? WHERE ref = ? IF EXISTS" + q = "UPDATE mls_key_package_refs SET client = ?, conv = ?, conv_domain = ?, domain = ?, user = ? WHERE ref = ?" -- | Update key package ref, used in Galley when commit reveals key package ref update for the sender. -- Nothing is changed if the previous key package ref is not found in the table. diff --git a/services/brig/src/Brig/Data/User.hs b/services/brig/src/Brig/Data/User.hs index 41b21f1da6..1891e135f4 100644 --- a/services/brig/src/Brig/Data/User.hs +++ b/services/brig/src/Brig/Data/User.hs @@ -336,7 +336,7 @@ updateFeatureConferenceCalling uid mbStatus = do pure mbStatus where update :: PrepQuery W (Maybe ApiFt.FeatureStatus, UserId) () - update = fromString "update user set feature_conference_calling = ? where id = ? if exists" + update = fromString "update user set feature_conference_calling = ? where id = ?" deleteEmail :: MonadClient m => UserId -> m () deleteEmail u = retry x5 $ write userEmailDelete (params LocalQuorum (Identity u)) @@ -622,64 +622,64 @@ userInsert = \VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" userDisplayNameUpdate :: PrepQuery W (Name, UserId) () -userDisplayNameUpdate = "UPDATE user SET name = ? WHERE id = ? IF EXISTS" +userDisplayNameUpdate = "UPDATE user SET name = ? WHERE id = ?" userPictUpdate :: PrepQuery W (Pict, UserId) () -userPictUpdate = "UPDATE user SET picture = ? WHERE id = ? IF EXISTS" +userPictUpdate = "UPDATE user SET picture = ? WHERE id = ?" userAssetsUpdate :: PrepQuery W ([Asset], UserId) () -userAssetsUpdate = "UPDATE user SET assets = ? WHERE id = ? IF EXISTS" +userAssetsUpdate = "UPDATE user SET assets = ? WHERE id = ?" userAccentIdUpdate :: PrepQuery W (ColourId, UserId) () -userAccentIdUpdate = "UPDATE user SET accent_id = ? WHERE id = ? IF EXISTS" +userAccentIdUpdate = "UPDATE user SET accent_id = ? WHERE id = ?" userEmailUpdate :: PrepQuery W (Email, UserId) () -userEmailUpdate = "UPDATE user SET email = ? WHERE id = ? IF EXISTS" +userEmailUpdate = "UPDATE user SET email = ? WHERE id = ?" userEmailUnvalidatedUpdate :: PrepQuery W (Email, UserId) () -userEmailUnvalidatedUpdate = "UPDATE user SET email_unvalidated = ? WHERE id = ? IF EXISTS" +userEmailUnvalidatedUpdate = "UPDATE user SET email_unvalidated = ? WHERE id = ?" userEmailUnvalidatedDelete :: PrepQuery W (Identity UserId) () -userEmailUnvalidatedDelete = "UPDATE user SET email_unvalidated = null WHERE id = ? IF EXISTS" +userEmailUnvalidatedDelete = "UPDATE user SET email_unvalidated = null WHERE id = ?" userPhoneUpdate :: PrepQuery W (Phone, UserId) () -userPhoneUpdate = "UPDATE user SET phone = ? WHERE id = ? IF EXISTS" +userPhoneUpdate = "UPDATE user SET phone = ? WHERE id = ?" userSSOIdUpdate :: PrepQuery W (Maybe UserSSOId, UserId) () -userSSOIdUpdate = "UPDATE user SET sso_id = ? WHERE id = ? IF EXISTS" +userSSOIdUpdate = "UPDATE user SET sso_id = ? WHERE id = ?" userManagedByUpdate :: PrepQuery W (ManagedBy, UserId) () -userManagedByUpdate = "UPDATE user SET managed_by = ? WHERE id = ? IF EXISTS" +userManagedByUpdate = "UPDATE user SET managed_by = ? WHERE id = ?" userHandleUpdate :: PrepQuery W (Handle, UserId) () -userHandleUpdate = "UPDATE user SET handle = ? WHERE id = ? IF EXISTS" +userHandleUpdate = "UPDATE user SET handle = ? WHERE id = ?" userSupportedProtocolUpdate :: PrepQuery W (Set BaseProtocolTag, UserId) () -userSupportedProtocolUpdate = "UPDATE user SET supported_protocols = ? WHERE id = ? IF EXISTS" +userSupportedProtocolUpdate = "UPDATE user SET supported_protocols = ? WHERE id = ?" userPasswordUpdate :: PrepQuery W (Password, UserId) () -userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ? IF EXISTS" +userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ?" userStatusUpdate :: PrepQuery W (AccountStatus, UserId) () -userStatusUpdate = "UPDATE user SET status = ? WHERE id = ? IF EXISTS" +userStatusUpdate = "UPDATE user SET status = ? WHERE id = ?" userDeactivatedUpdate :: PrepQuery W (Identity UserId) () -userDeactivatedUpdate = "UPDATE user SET activated = false WHERE id = ? IF EXISTS" +userDeactivatedUpdate = "UPDATE user SET activated = false WHERE id = ?" userActivatedUpdate :: PrepQuery W (Maybe Email, Maybe Phone, UserId) () -userActivatedUpdate = "UPDATE user SET activated = true, email = ?, phone = ? WHERE id = ? IF EXISTS" +userActivatedUpdate = "UPDATE user SET activated = true, email = ?, phone = ? WHERE id = ?" userLocaleUpdate :: PrepQuery W (Language, Maybe Country, UserId) () -userLocaleUpdate = "UPDATE user SET language = ?, country = ? WHERE id = ? IF EXISTS" +userLocaleUpdate = "UPDATE user SET language = ?, country = ? WHERE id = ?" userEmailDelete :: PrepQuery W (Identity UserId) () -userEmailDelete = "UPDATE user SET email = null WHERE id = ? IF EXISTS" +userEmailDelete = "UPDATE user SET email = null WHERE id = ?" userPhoneDelete :: PrepQuery W (Identity UserId) () -userPhoneDelete = "UPDATE user SET phone = null WHERE id = ? IF EXISTS" +userPhoneDelete = "UPDATE user SET phone = null WHERE id = ?" userRichInfoUpdate :: PrepQuery W (RichInfoAssocList, UserId) () -userRichInfoUpdate = "UPDATE rich_info SET json = ? WHERE user = ? IF EXISTS" +userRichInfoUpdate = "UPDATE rich_info SET json = ? WHERE user = ?" ------------------------------------------------------------------------------- -- Conversions diff --git a/services/brig/src/Brig/Provider/DB.hs b/services/brig/src/Brig/Provider/DB.hs index a5d9fd3800..ab7f85df1b 100644 --- a/services/brig/src/Brig/Provider/DB.hs +++ b/services/brig/src/Brig/Provider/DB.hs @@ -72,11 +72,11 @@ updateAccountProfile p name url descr = retry x5 . batch $ do for_ descr $ \x -> addPrepQuery cqlDescr (x, p) where cqlName :: PrepQuery W (Name, ProviderId) () - cqlName = "UPDATE provider SET name = ? WHERE id = ? IF EXISTS" + cqlName = "UPDATE provider SET name = ? WHERE id = ?" cqlUrl :: PrepQuery W (HttpsUrl, ProviderId) () - cqlUrl = "UPDATE provider SET url = ? WHERE id = ? IF EXISTS" + cqlUrl = "UPDATE provider SET url = ? WHERE id = ?" cqlDescr :: PrepQuery W (Text, ProviderId) () - cqlDescr = "UPDATE provider SET descr = ? WHERE id = ? IF EXISTS" + cqlDescr = "UPDATE provider SET descr = ? WHERE id = ?" -- | Lookup the raw account data of a (possibly unverified) provider. lookupAccountData :: @@ -136,7 +136,7 @@ updateAccountPassword pid pwd = do retry x5 $ write cql $ params LocalQuorum (p, pid) where cql :: PrepQuery W (Password, ProviderId) () - cql = "UPDATE provider SET password = ? where id = ? IF EXISTS" + cql = "UPDATE provider SET password = ? where id = ?" -------------------------------------------------------------------------------- -- Unique (Natural) Keys @@ -159,7 +159,7 @@ insertKey p old new = retry x5 . batch $ do cqlKeyDelete :: PrepQuery W (Identity Text) () cqlKeyDelete = "DELETE FROM provider_keys WHERE key = ?" cqlEmail :: PrepQuery W (Email, ProviderId) () - cqlEmail = "UPDATE provider SET email = ? WHERE id = ? IF EXISTS" + cqlEmail = "UPDATE provider SET email = ? WHERE id = ?" lookupKey :: MonadClient m => @@ -306,15 +306,15 @@ updateService pid sid svcName svcTags nameChange summary descr assets tagsChange for_ assets $ \x -> addPrepQuery cqlAssets (x, pid, sid) where cqlName :: PrepQuery W (Name, ProviderId, ServiceId) () - cqlName = "UPDATE service SET name = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlName = "UPDATE service SET name = ? WHERE provider = ? AND id = ?" cqlSummary :: PrepQuery W (Text, ProviderId, ServiceId) () - cqlSummary = "UPDATE service SET summary = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlSummary = "UPDATE service SET summary = ? WHERE provider = ? AND id = ?" cqlDescr :: PrepQuery W (Text, ProviderId, ServiceId) () - cqlDescr = "UPDATE service SET descr = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlDescr = "UPDATE service SET descr = ? WHERE provider = ? AND id = ?" cqlAssets :: PrepQuery W ([Asset], ProviderId, ServiceId) () - cqlAssets = "UPDATE service SET assets = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlAssets = "UPDATE service SET assets = ? WHERE provider = ? AND id = ?" cqlTags :: PrepQuery W (C.Set ServiceTag, ProviderId, ServiceId) () - cqlTags = "UPDATE service SET tags = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlTags = "UPDATE service SET tags = ? WHERE provider = ? AND id = ?" -- NB: can take a significant amount of time if many teams were using the service deleteService :: @@ -437,15 +437,15 @@ updateServiceConn pid sid url tokens keys enabled = retry x5 . batch $ do where (pks, fps) = (fmap fst &&& fmap snd) (unzip . toList <$> keys) cqlBaseUrl :: PrepQuery W (HttpsUrl, ProviderId, ServiceId) () - cqlBaseUrl = "UPDATE service SET base_url = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlBaseUrl = "UPDATE service SET base_url = ? WHERE provider = ? AND id = ?" cqlTokens :: PrepQuery W (List1 ServiceToken, ProviderId, ServiceId) () - cqlTokens = "UPDATE service SET auth_tokens = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlTokens = "UPDATE service SET auth_tokens = ? WHERE provider = ? AND id = ?" cqlKeys :: PrepQuery W ([ServiceKey], ProviderId, ServiceId) () - cqlKeys = "UPDATE service SET pubkeys = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlKeys = "UPDATE service SET pubkeys = ? WHERE provider = ? AND id = ?" cqlFps :: PrepQuery W ([Fingerprint Rsa], ProviderId, ServiceId) () - cqlFps = "UPDATE service SET fingerprints = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlFps = "UPDATE service SET fingerprints = ? WHERE provider = ? AND id = ?" cqlEnabled :: PrepQuery W (Bool, ProviderId, ServiceId) () - cqlEnabled = "UPDATE service SET enabled = ? WHERE provider = ? AND id = ? IF EXISTS" + cqlEnabled = "UPDATE service SET enabled = ? WHERE provider = ? AND id = ?" -------------------------------------------------------------------------------- -- Service "Indexes" (tag and prefix); contain only enabled services diff --git a/services/brig/src/Brig/Unique.hs b/services/brig/src/Brig/Unique.hs index 81c24aed76..88e325e8c4 100644 --- a/services/brig/src/Brig/Unique.hs +++ b/services/brig/src/Brig/Unique.hs @@ -72,7 +72,7 @@ withClaim u v t io = do then liftIO $ timeout (fromIntegral ttl # Second) io else pure Nothing cql :: PrepQuery W (Int32, C.Set (Id a), Text) () - cql = "UPDATE unique_claims USING TTL ? SET claims = claims + ? WHERE value = ? IF EXISTS" + cql = "UPDATE unique_claims USING TTL ? SET claims = claims + ? WHERE value = ?" deleteClaim :: MonadClient m => @@ -91,7 +91,7 @@ deleteClaim u v t = do retry x5 $ write cql $ params LocalQuorum (ttl * 2, C.Set [u], v) where cql :: PrepQuery W (Int32, C.Set (Id a), Text) () - cql = "UPDATE unique_claims USING TTL ? SET claims = claims - ? WHERE value = ? IF EXISTS" + cql = "UPDATE unique_claims USING TTL ? SET claims = claims - ? WHERE value = ?" -- | Lookup the current claims on a value. lookupClaims :: MonadClient m => Text -> m [Id a] diff --git a/services/brig/test/integration/API/User/Auth.hs b/services/brig/test/integration/API/User/Auth.hs index be66d96677..8979a1b941 100644 --- a/services/brig/test/integration/API/User/Auth.hs +++ b/services/brig/test/integration/API/User/Auth.hs @@ -212,7 +212,7 @@ testLoginWith6CharPassword brig db = do p <- liftIO $ mkSafePassword t retry x5 $ write userPasswordUpdate (params LocalQuorum (p, u)) userPasswordUpdate :: PrepQuery W (Password, UserId) () - userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ? IF EXISTS" + userPasswordUpdate = "UPDATE user SET password = ? WHERE id = ?" -------------------------------------------------------------------------------- -- ZAuth test environment for generating arbitrary tokens. diff --git a/services/galley/src/Galley/Cassandra/Queries.hs b/services/galley/src/Galley/Cassandra/Queries.hs index d88de5ff07..e04507c944 100644 --- a/services/galley/src/Galley/Cassandra/Queries.hs +++ b/services/galley/src/Galley/Cassandra/Queries.hs @@ -177,7 +177,7 @@ listTeamAdmins :: PrepQuery R (Identity TeamId) (Identity UserId) listTeamAdmins = "select user from team_admin where team = ?" updatePermissions :: PrepQuery W (Permissions, TeamId, UserId) () -updatePermissions = "update team_member set perms = ? where team = ? and user = ? IF EXISTS" +updatePermissions = "update team_member set perms = ? where team = ? and user = ?" insertUserTeam :: PrepQuery W (UserId, TeamId) () insertUserTeam = "insert into user_team (user, team) values (?, ?)" @@ -186,25 +186,25 @@ deleteUserTeam :: PrepQuery W (UserId, TeamId) () deleteUserTeam = "delete from user_team where user = ? and team = ?" markTeamDeleted :: PrepQuery W (TeamStatus, TeamId) () -markTeamDeleted = "update team set status = ? where team = ? IF EXISTS" +markTeamDeleted = "update team set status = ? where team = ?" deleteTeam :: PrepQuery W (TeamStatus, TeamId) () -deleteTeam = "update team using timestamp 32503680000000000 set name = 'default', icon = 'default', status = ? where team = ? IF EXISTS" +deleteTeam = "update team using timestamp 32503680000000000 set name = 'default', icon = 'default', status = ? where team = ? " updateTeamName :: PrepQuery W (Text, TeamId) () -updateTeamName = "update team set name = ? where team = ? IF EXISTS" +updateTeamName = "update team set name = ? where team = ?" updateTeamIcon :: PrepQuery W (Text, TeamId) () -updateTeamIcon = "update team set icon = ? where team = ? IF EXISTS" +updateTeamIcon = "update team set icon = ? where team = ?" updateTeamIconKey :: PrepQuery W (Text, TeamId) () -updateTeamIconKey = "update team set icon_key = ? where team = ? IF EXISTS" +updateTeamIconKey = "update team set icon_key = ? where team = ?" updateTeamStatus :: PrepQuery W (TeamStatus, TeamId) () -updateTeamStatus = "update team set status = ? where team = ? IF EXISTS" +updateTeamStatus = "update team set status = ? where team = ?" updateTeamSplashScreen :: PrepQuery W (Text, TeamId) () -updateTeamSplashScreen = "update team set splash_screen = ? where team = ? IF EXISTS" +updateTeamSplashScreen = "update team set splash_screen = ? where team = ?" -- Conversations ------------------------------------------------------------ @@ -264,34 +264,34 @@ insertMLSSelfConv = <> ", ?, ?)" updateConvAccess :: PrepQuery W (C.Set Access, C.Set AccessRole, ConvId) () -updateConvAccess = "update conversation set access = ?, access_roles_v2 = ? where conv = ? IF EXISTS" +updateConvAccess = "update conversation set access = ?, access_roles_v2 = ? where conv = ?" updateConvReceiptMode :: PrepQuery W (ReceiptMode, ConvId) () -updateConvReceiptMode = "update conversation set receipt_mode = ? where conv = ? IF EXISTS" +updateConvReceiptMode = "update conversation set receipt_mode = ? where conv = ?" updateConvMessageTimer :: PrepQuery W (Maybe Milliseconds, ConvId) () -updateConvMessageTimer = "update conversation set message_timer = ? where conv = ? IF EXISTS" +updateConvMessageTimer = "update conversation set message_timer = ? where conv = ?" updateConvName :: PrepQuery W (Text, ConvId) () -updateConvName = "update conversation set name = ? where conv = ? IF EXISTS" +updateConvName = "update conversation set name = ? where conv = ?" updateConvType :: PrepQuery W (ConvType, ConvId) () -updateConvType = "update conversation set type = ? where conv = ? IF EXISTS" +updateConvType = "update conversation set type = ? where conv = ?" updateConvEpoch :: PrepQuery W (Epoch, ConvId) () -updateConvEpoch = "update conversation set epoch = ? where conv = ? IF EXISTS" +updateConvEpoch = "update conversation set epoch = ? where conv = ?" deleteConv :: PrepQuery W (Identity ConvId) () deleteConv = "delete from conversation using timestamp 32503680000000000 where conv = ?" markConvDeleted :: PrepQuery W (Identity ConvId) () -markConvDeleted = "update conversation set deleted = true where conv = ? IF EXISTS" +markConvDeleted = "update conversation set deleted = true where conv = ?" selectPublicGroupState :: PrepQuery R (Identity ConvId) (Identity (Maybe OpaquePublicGroupState)) selectPublicGroupState = "select public_group_state from conversation where conv = ?" updatePublicGroupState :: PrepQuery W (OpaquePublicGroupState, ConvId) () -updatePublicGroupState = "update conversation set public_group_state = ? where conv = ? IF EXISTS" +updatePublicGroupState = "update conversation set public_group_state = ? where conv = ?" -- Conversations accessible by code ----------------------------------------- @@ -349,16 +349,16 @@ removeMember :: PrepQuery W (ConvId, UserId) () removeMember = "delete from member where conv = ? and user = ?" updateOtrMemberMutedStatus :: PrepQuery W (MutedStatus, Maybe Text, ConvId, UserId) () -updateOtrMemberMutedStatus = "update member set otr_muted_status = ?, otr_muted_ref = ? where conv = ? and user = ? IF EXISTS" +updateOtrMemberMutedStatus = "update member set otr_muted_status = ?, otr_muted_ref = ? where conv = ? and user = ?" updateOtrMemberArchived :: PrepQuery W (Bool, Maybe Text, ConvId, UserId) () -updateOtrMemberArchived = "update member set otr_archived = ?, otr_archived_ref = ? where conv = ? and user = ? IF EXISTS" +updateOtrMemberArchived = "update member set otr_archived = ?, otr_archived_ref = ? where conv = ? and user = ?" updateMemberHidden :: PrepQuery W (Bool, Maybe Text, ConvId, UserId) () -updateMemberHidden = "update member set hidden = ?, hidden_ref = ? where conv = ? and user = ? IF EXISTS" +updateMemberHidden = "update member set hidden = ?, hidden_ref = ? where conv = ? and user = ?" updateMemberConvRoleName :: PrepQuery W (RoleName, ConvId, UserId) () -updateMemberConvRoleName = "update member set conversation_role = ? where conv = ? and user = ? IF EXISTS" +updateMemberConvRoleName = "update member set conversation_role = ? where conv = ? and user = ?" -- Federated conversations ----------------------------------------------------- -- @@ -379,7 +379,7 @@ selectRemoteMembers :: PrepQuery R (Identity ConvId) (Domain, UserId, RoleName) selectRemoteMembers = "select user_remote_domain, user_remote_id, conversation_role from member_remote_user where conv = ?" updateRemoteMemberConvRoleName :: PrepQuery W (RoleName, ConvId, Domain, UserId) () -updateRemoteMemberConvRoleName = "update member_remote_user set conversation_role = ? where conv = ? and user_remote_domain = ? and user_remote_id = ? IF EXISTS" +updateRemoteMemberConvRoleName = "update member_remote_user set conversation_role = ? where conv = ? and user_remote_domain = ? and user_remote_id = ?" -- Used when removing a federation domain, so that we can quickly list all of the affected remote users and conversations -- This returns local conversation IDs and remote users @@ -411,13 +411,13 @@ selectLocalMembersByDomain = "select conv_remote_id, user from user_remote_conv -- remote conversation status for local user updateRemoteOtrMemberMutedStatus :: PrepQuery W (MutedStatus, Maybe Text, Domain, ConvId, UserId) () -updateRemoteOtrMemberMutedStatus = "update user_remote_conv set otr_muted_status = ?, otr_muted_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ? IF EXISTS" +updateRemoteOtrMemberMutedStatus = "update user_remote_conv set otr_muted_status = ?, otr_muted_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ?" updateRemoteOtrMemberArchived :: PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) () -updateRemoteOtrMemberArchived = "update user_remote_conv set otr_archived = ?, otr_archived_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ? IF EXISTS" +updateRemoteOtrMemberArchived = "update user_remote_conv set otr_archived = ?, otr_archived_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ?" updateRemoteMemberHidden :: PrepQuery W (Bool, Maybe Text, Domain, ConvId, UserId) () -updateRemoteMemberHidden = "update user_remote_conv set hidden = ?, hidden_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ? IF EXISTS" +updateRemoteMemberHidden = "update user_remote_conv set hidden = ?, hidden_ref = ? where conv_remote_domain = ? and conv_remote_id = ? and user = ?" selectRemoteMemberStatus :: PrepQuery R (Domain, ConvId, UserId) (Maybe MutedStatus, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool, Maybe Text) selectRemoteMemberStatus = "select otr_muted_status, otr_muted_ref, otr_archived, otr_archived_ref, hidden, hidden_ref from user_remote_conv where conv_remote_domain = ? and conv_remote_id = ? and user = ?" @@ -433,12 +433,12 @@ rmClients = "delete from clients where user = ?" addMemberClient :: ClientId -> QueryString W (Identity UserId) () addMemberClient c = let t = LT.fromStrict (client c) - in QueryString $ "update clients set clients = clients + {'" <> t <> "'} where user = ? IF EXISTS" + in QueryString $ "update clients set clients = clients + {'" <> t <> "'} where user = ?" rmMemberClient :: ClientId -> QueryString W (Identity UserId) () rmMemberClient c = let t = LT.fromStrict (client c) - in QueryString $ "update clients set clients = clients - {'" <> t <> "'} where user = ? IF EXISTS" + in QueryString $ "update clients set clients = clients - {'" <> t <> "'} where user = ?" -- MLS Clients -------------------------------------------------------------- @@ -553,7 +553,7 @@ selectSearchVisibility = updateSearchVisibility :: PrepQuery W (TeamSearchVisibility, TeamId) () updateSearchVisibility = - "update team set search_visibility = ? where team = ? IF EXISTS" + "update team set search_visibility = ? where team = ?" -- Custom Backend ----------------------------------------------------------- @@ -563,7 +563,7 @@ selectCustomBackend = updateCustomBackend :: PrepQuery W (HttpsUrl, HttpsUrl, Domain) () updateCustomBackend = - "update custom_backend set config_json_url = ?, webapp_welcome_url = ? where domain = ? IF EXISTS" + "update custom_backend set config_json_url = ?, webapp_welcome_url = ? where domain = ?" deleteCustomBackend :: PrepQuery W (Identity Domain) () deleteCustomBackend = diff --git a/services/gundeck/src/Gundeck/Push/Data.hs b/services/gundeck/src/Gundeck/Push/Data.hs index c3976ffc7c..f00ddc1903 100644 --- a/services/gundeck/src/Gundeck/Push/Data.hs +++ b/services/gundeck/src/Gundeck/Push/Data.hs @@ -52,7 +52,7 @@ updateArn :: MonadClient m => UserId -> Transport -> AppName -> Token -> Endpoin updateArn uid transport app token arn = retry x5 $ write q (params LocalQuorum (arn, uid, transport, app, token)) where q :: PrepQuery W (EndpointArn, UserId, Transport, AppName, Token) () - q = "update user_push set arn = ? where usr = ? and transport = ? and app = ? and ptoken = ? IF EXISTS" + q = "update user_push set arn = ? where usr = ? and transport = ? and app = ? and ptoken = ?" delete :: MonadClient m => UserId -> Transport -> AppName -> Token -> m () delete u t a p = retry x5 $ write q (params LocalQuorum (u, t, a, p)) diff --git a/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs b/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs index 6ae8659117..2b3d347007 100644 --- a/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs +++ b/services/spar/src/Spar/Sem/IdPConfigStore/Cassandra.hs @@ -356,7 +356,7 @@ setReplacedBy (Replaced old) (Replacing new) = do retry x5 . write ins $ params LocalQuorum (new, old) where ins :: PrepQuery W (SAML.IdPId, SAML.IdPId) () - ins = "UPDATE idp SET replaced_by = ? WHERE idp = ? IF EXISTS" + ins = "UPDATE idp SET replaced_by = ? WHERE idp = ?" -- | See also: 'setReplacedBy'. clearReplacedBy :: @@ -367,7 +367,7 @@ clearReplacedBy (Replaced old) = do retry x5 . write ins $ params LocalQuorum (Identity old) where ins :: PrepQuery W (Identity SAML.IdPId) () - ins = "UPDATE idp SET replaced_by = null WHERE idp = ? IF EXISTS" + ins = "UPDATE idp SET replaced_by = null WHERE idp = ?" -- | If the IdP is 'WireIdPAPIV1', it must be deleted globally, if it is 'WireIdPAPIV2', it -- must be deleted inside one team. 'V1' can be either in the old table without team index, diff --git a/tools/db/migrate-sso-feature-flag/src/Work.hs b/tools/db/migrate-sso-feature-flag/src/Work.hs index 275fec582d..ff56a09447 100644 --- a/tools/db/migrate-sso-feature-flag/src/Work.hs +++ b/tools/db/migrate-sso-feature-flag/src/Work.hs @@ -68,4 +68,4 @@ writeSsoFlags = mapM_ (`setSSOTeamConfig` FeatureStatusEnabled) setSSOTeamConfig tid ssoTeamConfigStatus = do retry x5 $ write updateSSOTeamConfig (params LocalQuorum (ssoTeamConfigStatus, tid)) updateSSOTeamConfig :: PrepQuery W (FeatureStatus, TeamId) () - updateSSOTeamConfig = "update team_features set sso_status = ? where team_id = ? IF EXISTS" + updateSSOTeamConfig = "update team_features set sso_status = ? where team_id = ?" diff --git a/tools/db/repair-handles/src/Work.hs b/tools/db/repair-handles/src/Work.hs index 2bfc866b7a..7b91c7c98c 100644 --- a/tools/db/repair-handles/src/Work.hs +++ b/tools/db/repair-handles/src/Work.hs @@ -142,7 +142,7 @@ executeAction env = \case params LocalQuorum (handle, uid) where updateHandle :: PrepQuery W (Handle, UserId) () - updateHandle = "UPDATE user SET handle = ? WHERE id = ? IF EXISTS" + updateHandle = "UPDATE user SET handle = ? WHERE id = ?" removeHandle :: Env -> Handle -> IO () removeHandle Env {..} handle =