content: {-# LANGUAGE RecordWildCards #-}
  
  -- This file is part of the Wire Server implementation.
  --
  -- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
  --
  -- This program is free software: you can redistribute it and/or modify it under
  -- the terms of the GNU Affero General Public License as published by the Free
  -- Software Foundation, either version 3 of the License, or (at your option) any
  -- later version.
  --
  -- This program is distributed in the hope that it will be useful, but WITHOUT
  -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  -- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  -- details.
  --
  -- You should have received a copy of the GNU Affero General Public License along
  -- with this program. If not, see <https://www.gnu.org/licenses/>.
  
  module Schema where
  
  import Cassandra
  import Common
  import Data.Conduit
  import Data.IP (IP)
  import Data.Id
  import Data.Time
  import Data.UUID
  import Imports
  import System.FilePath.Posix ((</>))
  import Types
  import Wire.API.Team.Permission
  import Wire.ConversationStore.Cassandra.Instances ()
  
  -- This file was autogenerated by move-team-generate
  
  -- brig.clients
  
  type RowBrigClients = (Maybe UUID, Maybe Text, Maybe Int32, Maybe Text, Maybe IP, Maybe Text, Maybe Double, Maybe Double, Maybe Text, Maybe UTCTime, Maybe Int32)
  
  selectBrigClients :: PrepQuery R (Identity [UserId]) RowBrigClients
  selectBrigClients = "SELECT user, client, class, cookie, ip, label, lat, lon, model, tstamp, type FROM clients WHERE user in ?"
  
  readBrigClients :: Env -> [UserId] -> ConduitM () [RowBrigClients] IO ()
  readBrigClients Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigClients (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigClientsAll :: PrepQuery R () RowBrigClients
  selectBrigClientsAll = "SELECT user, client, class, cookie, ip, label, lat, lon, model, tstamp, type FROM clients"
  
  readBrigClientsAll :: Env -> ConduitM () [RowBrigClients] IO ()
  readBrigClientsAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigClientsAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigClientsFull :: Env -> FilePath -> IO ()
  exportBrigClientsFull env path = do
    putStrLn $ "Exporting " <> "brig.clients" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigClientsAll env
          .| sinkJsonLines handle
  
  insertBrigClients :: PrepQuery W RowBrigClients ()
  insertBrigClients =
    "INSERT INTO clients (user, client, class, cookie, ip, label, lat, lon, model, tstamp, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
  
  importBrigClients :: Env -> FilePath -> IO ()
  importBrigClients Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.clients"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigClients)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.connection
  
  type RowBrigConnection = (Maybe UUID, Maybe UUID, Maybe UUID, Maybe UTCTime, Maybe Text, Maybe Int32)
  
  selectBrigConnection :: PrepQuery R (Identity [UserId]) RowBrigConnection
  selectBrigConnection = "SELECT left, right, conv, last_update, message, status FROM connection WHERE left in ?"
  
  readBrigConnection :: Env -> [UserId] -> ConduitM () [RowBrigConnection] IO ()
  readBrigConnection Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigConnection (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigConnectionAll :: PrepQuery R () RowBrigConnection
  selectBrigConnectionAll = "SELECT left, right, conv, last_update, message, status FROM connection"
  
  readBrigConnectionAll :: Env -> ConduitM () [RowBrigConnection] IO ()
  readBrigConnectionAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigConnectionAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigConnectionFull :: Env -> FilePath -> IO ()
  exportBrigConnectionFull env path = do
    putStrLn $ "Exporting " <> "brig.connection" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigConnectionAll env
          .| sinkJsonLines handle
  
  insertBrigConnection :: PrepQuery W RowBrigConnection ()
  insertBrigConnection =
    "INSERT INTO connection (left, right, conv, last_update, message, status) VALUES (?, ?, ?, ?, ?, ?)"
  
  importBrigConnection :: Env -> FilePath -> IO ()
  importBrigConnection Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.connection"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigConnection)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.login_codes
  
  type RowBrigLoginCodes = (Maybe UUID, Maybe Text, Maybe Int32, Maybe UTCTime)
  
  selectBrigLoginCodes :: PrepQuery R (Identity [UserId]) RowBrigLoginCodes
  selectBrigLoginCodes = "SELECT user, code, retries, timeout FROM login_codes WHERE user in ?"
  
  readBrigLoginCodes :: Env -> [UserId] -> ConduitM () [RowBrigLoginCodes] IO ()
  readBrigLoginCodes Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigLoginCodes (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigLoginCodesAll :: PrepQuery R () RowBrigLoginCodes
  selectBrigLoginCodesAll = "SELECT user, code, retries, timeout FROM login_codes"
  
  readBrigLoginCodesAll :: Env -> ConduitM () [RowBrigLoginCodes] IO ()
  readBrigLoginCodesAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigLoginCodesAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigLoginCodesFull :: Env -> FilePath -> IO ()
  exportBrigLoginCodesFull env path = do
    putStrLn $ "Exporting " <> "brig.login_codes" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigLoginCodesAll env
          .| sinkJsonLines handle
  
  insertBrigLoginCodes :: PrepQuery W RowBrigLoginCodes ()
  insertBrigLoginCodes =
    "INSERT INTO login_codes (user, code, retries, timeout) VALUES (?, ?, ?, ?)"
  
  importBrigLoginCodes :: Env -> FilePath -> IO ()
  importBrigLoginCodes Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.login_codes"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigLoginCodes)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.password_reset
  
  type RowBrigPasswordReset = (Maybe Ascii, Maybe Ascii, Maybe Int32, Maybe UTCTime, Maybe UUID)
  
  selectBrigPasswordResetAll :: PrepQuery R () RowBrigPasswordReset
  selectBrigPasswordResetAll = "SELECT key, code, retries, timeout, user FROM password_reset"
  
  readBrigPasswordResetAll :: Env -> ConduitM () [RowBrigPasswordReset] IO ()
  readBrigPasswordResetAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigPasswordResetAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigPasswordResetFull :: Env -> FilePath -> IO ()
  exportBrigPasswordResetFull env path = do
    putStrLn $ "Exporting " <> "brig.password_reset" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigPasswordResetAll env
          .| sinkJsonLines handle
  
  insertBrigPasswordReset :: PrepQuery W RowBrigPasswordReset ()
  insertBrigPasswordReset =
    "INSERT INTO password_reset (key, code, retries, timeout, user) VALUES (?, ?, ?, ?, ?)"
  
  importBrigPasswordReset :: Env -> FilePath -> IO ()
  importBrigPasswordReset Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.password_reset"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigPasswordReset)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.prekeys
  
  type RowBrigPrekeys = (Maybe UUID, Maybe Text, Maybe Int32, Maybe Text)
  
  selectBrigPrekeys :: PrepQuery R (Identity [UserId]) RowBrigPrekeys
  selectBrigPrekeys = "SELECT user, client, key, data FROM prekeys WHERE user in ?"
  
  readBrigPrekeys :: Env -> [UserId] -> ConduitM () [RowBrigPrekeys] IO ()
  readBrigPrekeys Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigPrekeys (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigPrekeysAll :: PrepQuery R () RowBrigPrekeys
  selectBrigPrekeysAll = "SELECT user, client, key, data FROM prekeys"
  
  readBrigPrekeysAll :: Env -> ConduitM () [RowBrigPrekeys] IO ()
  readBrigPrekeysAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigPrekeysAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigPrekeysFull :: Env -> FilePath -> IO ()
  exportBrigPrekeysFull env path = do
    putStrLn $ "Exporting " <> "brig.prekeys" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigPrekeysAll env
          .| sinkJsonLines handle
  
  insertBrigPrekeys :: PrepQuery W RowBrigPrekeys ()
  insertBrigPrekeys =
    "INSERT INTO prekeys (user, client, key, data) VALUES (?, ?, ?, ?)"
  
  importBrigPrekeys :: Env -> FilePath -> IO ()
  importBrigPrekeys Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.prekeys"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigPrekeys)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.properties
  
  type RowBrigProperties = (Maybe UUID, Maybe Ascii, Maybe Blob)
  
  selectBrigProperties :: PrepQuery R (Identity [UserId]) RowBrigProperties
  selectBrigProperties = "SELECT user, key, value FROM properties WHERE user in ?"
  
  readBrigProperties :: Env -> [UserId] -> ConduitM () [RowBrigProperties] IO ()
  readBrigProperties Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigProperties (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigPropertiesAll :: PrepQuery R () RowBrigProperties
  selectBrigPropertiesAll = "SELECT user, key, value FROM properties"
  
  readBrigPropertiesAll :: Env -> ConduitM () [RowBrigProperties] IO ()
  readBrigPropertiesAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigPropertiesAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigPropertiesFull :: Env -> FilePath -> IO ()
  exportBrigPropertiesFull env path = do
    putStrLn $ "Exporting " <> "brig.properties" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigPropertiesAll env
          .| sinkJsonLines handle
  
  insertBrigProperties :: PrepQuery W RowBrigProperties ()
  insertBrigProperties =
    "INSERT INTO properties (user, key, value) VALUES (?, ?, ?)"
  
  importBrigProperties :: Env -> FilePath -> IO ()
  importBrigProperties Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.properties"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigProperties)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.rich_info
  
  type RowBrigRichInfo = (Maybe UUID, Maybe Blob)
  
  selectBrigRichInfo :: PrepQuery R (Identity [UserId]) RowBrigRichInfo
  selectBrigRichInfo = "SELECT user, json FROM rich_info WHERE user in ?"
  
  readBrigRichInfo :: Env -> [UserId] -> ConduitM () [RowBrigRichInfo] IO ()
  readBrigRichInfo Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigRichInfo (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigRichInfoAll :: PrepQuery R () RowBrigRichInfo
  selectBrigRichInfoAll = "SELECT user, json FROM rich_info"
  
  readBrigRichInfoAll :: Env -> ConduitM () [RowBrigRichInfo] IO ()
  readBrigRichInfoAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigRichInfoAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigRichInfoFull :: Env -> FilePath -> IO ()
  exportBrigRichInfoFull env path = do
    putStrLn $ "Exporting " <> "brig.rich_info" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigRichInfoAll env
          .| sinkJsonLines handle
  
  insertBrigRichInfo :: PrepQuery W RowBrigRichInfo ()
  insertBrigRichInfo =
    "INSERT INTO rich_info (user, json) VALUES (?, ?)"
  
  importBrigRichInfo :: Env -> FilePath -> IO ()
  importBrigRichInfo Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.rich_info"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigRichInfo)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.user
  
  type RowBrigUser = (Maybe UUID, Maybe [Float], Maybe Int32, Maybe Bool, Maybe [AssetIgnoreData], Maybe Ascii, Maybe Text, Maybe UTCTime, Maybe Text, Maybe Ascii, Maybe Int32, Maybe Text, Maybe Blob, Maybe [Blob], Maybe UUID, Maybe Bool, Maybe UUID, Maybe Text, Maybe Int32, Maybe UUID)
  
  selectBrigUser :: PrepQuery R (Identity [UserId]) RowBrigUser
  selectBrigUser = "SELECT id, accent, accent_id, activated, assets, country, email, expires, handle, language, managed_by, name, password, picture, provider, searchable, service, sso_id, status, team FROM user WHERE id in ?"
  
  readBrigUser :: Env -> [UserId] -> ConduitM () [RowBrigUser] IO ()
  readBrigUser Env {..} uids =
    transPipe (runClient envBrig) $
      paginateC selectBrigUser (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectBrigUserAll :: PrepQuery R () RowBrigUser
  selectBrigUserAll = "SELECT id, accent, accent_id, activated, assets, country, email, expires, handle, language, managed_by, name, password, picture, provider, searchable, service, sso_id, status, team FROM user"
  
  readBrigUserAll :: Env -> ConduitM () [RowBrigUser] IO ()
  readBrigUserAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigUserAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigUserFull :: Env -> FilePath -> IO ()
  exportBrigUserFull env path = do
    putStrLn $ "Exporting " <> "brig.user" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigUserAll env
          .| sinkJsonLines handle
  
  insertBrigUser :: PrepQuery W RowBrigUser ()
  insertBrigUser =
    "INSERT INTO user (id, accent, accent_id, activated, assets, country, email, expires, handle, language, managed_by, name, password, picture, provider, searchable, service, sso_id, status, team) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
  
  importBrigUser :: Env -> FilePath -> IO ()
  importBrigUser Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.user"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigUser)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.user_handle
  
  type RowBrigUserHandle = (Maybe Text, Maybe UUID)
  
  selectBrigUserHandleAll :: PrepQuery R () RowBrigUserHandle
  selectBrigUserHandleAll = "SELECT handle, user FROM user_handle"
  
  readBrigUserHandleAll :: Env -> ConduitM () [RowBrigUserHandle] IO ()
  readBrigUserHandleAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigUserHandleAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigUserHandleFull :: Env -> FilePath -> IO ()
  exportBrigUserHandleFull env path = do
    putStrLn $ "Exporting " <> "brig.user_handle" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigUserHandleAll env
          .| sinkJsonLines handle
  
  insertBrigUserHandle :: PrepQuery W RowBrigUserHandle ()
  insertBrigUserHandle =
    "INSERT INTO user_handle (handle, user) VALUES (?, ?)"
  
  importBrigUserHandle :: Env -> FilePath -> IO ()
  importBrigUserHandle Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.user_handle"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigUserHandle)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- brig.user_keys
  
  type RowBrigUserKeys = (Maybe Text, Maybe UUID)
  
  selectBrigUserKeysAll :: PrepQuery R () RowBrigUserKeys
  selectBrigUserKeysAll = "SELECT key, user FROM user_keys"
  
  readBrigUserKeysAll :: Env -> ConduitM () [RowBrigUserKeys] IO ()
  readBrigUserKeysAll Env {..} =
    transPipe (runClient envBrig) $
      paginateC selectBrigUserKeysAll (paramsP LocalQuorum () envPageSize) x5
  
  exportBrigUserKeysFull :: Env -> FilePath -> IO ()
  exportBrigUserKeysFull env path = do
    putStrLn $ "Exporting " <> "brig.user_keys" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readBrigUserKeysAll env
          .| sinkJsonLines handle
  
  insertBrigUserKeys :: PrepQuery W RowBrigUserKeys ()
  insertBrigUserKeys =
    "INSERT INTO user_keys (key, user) VALUES (?, ?)"
  
  importBrigUserKeys :: Env -> FilePath -> IO ()
  importBrigUserKeys Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "brig.user_keys"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envBrig) (sinkTableRows insertBrigUserKeys)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.billing_team_member
  
  type RowGalleyBillingTeamMember = (Maybe UUID, Maybe UUID)
  
  selectGalleyBillingTeamMember :: PrepQuery R (Identity TeamId) RowGalleyBillingTeamMember
  selectGalleyBillingTeamMember = "SELECT team, user FROM billing_team_member WHERE team = ?"
  
  readGalleyBillingTeamMember :: Env -> TeamId -> ConduitM () [RowGalleyBillingTeamMember] IO ()
  readGalleyBillingTeamMember Env {..} tid =
    transPipe (runClient envGalley) $
      paginateC selectGalleyBillingTeamMember (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectGalleyBillingTeamMemberAll :: PrepQuery R () RowGalleyBillingTeamMember
  selectGalleyBillingTeamMemberAll = "SELECT team, user FROM billing_team_member"
  
  readGalleyBillingTeamMemberAll :: Env -> ConduitM () [RowGalleyBillingTeamMember] IO ()
  readGalleyBillingTeamMemberAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyBillingTeamMemberAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyBillingTeamMemberFull :: Env -> FilePath -> IO ()
  exportGalleyBillingTeamMemberFull env path = do
    putStrLn $ "Exporting " <> "galley.billing_team_member" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyBillingTeamMemberAll env
          .| sinkJsonLines handle
  
  insertGalleyBillingTeamMember :: PrepQuery W RowGalleyBillingTeamMember ()
  insertGalleyBillingTeamMember =
    "INSERT INTO billing_team_member (team, user) VALUES (?, ?)"
  
  importGalleyBillingTeamMember :: Env -> FilePath -> IO ()
  importGalleyBillingTeamMember Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.billing_team_member"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyBillingTeamMember)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.clients
  
  type RowGalleyClients = (Maybe UUID, Maybe (Cassandra.Set Text))
  
  selectGalleyClients :: PrepQuery R (Identity [UserId]) RowGalleyClients
  selectGalleyClients = "SELECT user, clients FROM clients WHERE user in ?"
  
  readGalleyClients :: Env -> [UserId] -> ConduitM () [RowGalleyClients] IO ()
  readGalleyClients Env {..} uids =
    transPipe (runClient envGalley) $
      paginateC selectGalleyClients (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectGalleyClientsAll :: PrepQuery R () RowGalleyClients
  selectGalleyClientsAll = "SELECT user, clients FROM clients"
  
  readGalleyClientsAll :: Env -> ConduitM () [RowGalleyClients] IO ()
  readGalleyClientsAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyClientsAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyClientsFull :: Env -> FilePath -> IO ()
  exportGalleyClientsFull env path = do
    putStrLn $ "Exporting " <> "galley.clients" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyClientsAll env
          .| sinkJsonLines handle
  
  insertGalleyClients :: PrepQuery W RowGalleyClients ()
  insertGalleyClients =
    "INSERT INTO clients (user, clients) VALUES (?, ?)"
  
  importGalleyClients :: Env -> FilePath -> IO ()
  importGalleyClients Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.clients"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyClients)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.conversation
  
  type RowGalleyConversation =
    ( Maybe UUID,
      Maybe (Cassandra.Set Int32),
      Maybe Int32,
      Maybe UUID,
      Maybe Bool,
      Maybe Int64,
      Maybe Text,
      Maybe Int32,
      Maybe UUID,
      Maybe Int32,
      Maybe UUID
    )
  
  selectGalleyConversation :: PrepQuery R (Identity [ConvId]) RowGalleyConversation
  selectGalleyConversation = "SELECT conv, access, access_role, creator, deleted, message_timer, name, receipt_mode, team, type, parent_conv FROM conversation WHERE conv in ?"
  
  readGalleyConversation :: Env -> [ConvId] -> ConduitM () [RowGalleyConversation] IO ()
  readGalleyConversation Env {..} cids =
    transPipe (runClient envGalley) $
      paginateC selectGalleyConversation (paramsP LocalQuorum (pure cids) envPageSize) x5
  
  selectGalleyConversationAll :: PrepQuery R () RowGalleyConversation
  selectGalleyConversationAll = "SELECT conv, access, access_role, creator, deleted, message_timer, name, receipt_mode, team, type, parent_conv FROM conversation"
  
  readGalleyConversationAll :: Env -> ConduitM () [RowGalleyConversation] IO ()
  readGalleyConversationAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyConversationAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyConversationFull :: Env -> FilePath -> IO ()
  exportGalleyConversationFull env path = do
    putStrLn $ "Exporting " <> "galley.conversation" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyConversationAll env
          .| sinkJsonLines handle
  
  insertGalleyConversation :: PrepQuery W RowGalleyConversation ()
  insertGalleyConversation =
    "INSERT INTO conversation (conv, access, access_role, creator, deleted, message_timer, name, receipt_mode, team, type, parent_conv) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
  
  importGalleyConversation :: Env -> FilePath -> IO ()
  importGalleyConversation Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.conversation"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyConversation)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.member
  
  type RowGalleyMember = (Maybe UUID, Maybe UUID, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool, Maybe Text, Maybe Bool, Maybe Text, Maybe Int32, Maybe UUID, Maybe UUID, Maybe Int32, Maybe Text, Maybe UUID)
  
  selectGalleyMember :: PrepQuery R (Identity [ConvId]) RowGalleyMember
  selectGalleyMember = "SELECT conv, user, conversation_role, hidden, hidden_ref, otr_archived, otr_archived_ref, otr_muted, otr_muted_ref, otr_muted_status, provider, service, status, user_remote_domain, user_remote_id FROM member WHERE conv in ?"
  
  readGalleyMember :: Env -> [ConvId] -> ConduitM () [RowGalleyMember] IO ()
  readGalleyMember Env {..} cids =
    transPipe (runClient envGalley) $
      paginateC selectGalleyMember (paramsP LocalQuorum (pure cids) envPageSize) x5
  
  selectGalleyMemberAll :: PrepQuery R () RowGalleyMember
  selectGalleyMemberAll = "SELECT conv, user, conversation_role, hidden, hidden_ref, otr_archived, otr_archived_ref, otr_muted, otr_muted_ref, otr_muted_status, provider, service, status, user_remote_domain, user_remote_id FROM member"
  
  readGalleyMemberAll :: Env -> ConduitM () [RowGalleyMember] IO ()
  readGalleyMemberAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyMemberAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyMemberFull :: Env -> FilePath -> IO ()
  exportGalleyMemberFull env path = do
    putStrLn $ "Exporting " <> "galley.member" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyMemberAll env
          .| sinkJsonLines handle
  
  insertGalleyMember :: PrepQuery W RowGalleyMember ()
  insertGalleyMember =
    "INSERT INTO member (conv, user, conversation_role, hidden, hidden_ref, otr_archived, otr_archived_ref, otr_muted, otr_muted_ref, otr_muted_status, provider, service, status, user_remote_domain, user_remote_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
  
  importGalleyMember :: Env -> FilePath -> IO ()
  importGalleyMember Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.member"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyMember)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.team
  
  type RowGalleyTeam = (Maybe UUID, Maybe Bool, Maybe UUID, Maybe Bool, Maybe Text, Maybe Text, Maybe Text, Maybe Int32, Maybe Int32)
  
  selectGalleyTeam :: PrepQuery R (Identity TeamId) RowGalleyTeam
  selectGalleyTeam = "SELECT team, binding, creator, deleted, icon, icon_key, name, search_visibility, status FROM team WHERE team = ?"
  
  readGalleyTeam :: Env -> TeamId -> ConduitM () [RowGalleyTeam] IO ()
  readGalleyTeam Env {..} tid =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeam (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectGalleyTeamAll :: PrepQuery R () RowGalleyTeam
  selectGalleyTeamAll = "SELECT team, binding, creator, deleted, icon, icon_key, name, search_visibility, status FROM team"
  
  readGalleyTeamAll :: Env -> ConduitM () [RowGalleyTeam] IO ()
  readGalleyTeamAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyTeamFull :: Env -> FilePath -> IO ()
  exportGalleyTeamFull env path = do
    putStrLn $ "Exporting " <> "galley.team" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyTeamAll env
          .| sinkJsonLines handle
  
  insertGalleyTeam :: PrepQuery W RowGalleyTeam ()
  insertGalleyTeam =
    "INSERT INTO team (team, binding, creator, deleted, icon, icon_key, name, search_visibility, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
  
  importGalleyTeam :: Env -> FilePath -> IO ()
  importGalleyTeam Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.team"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyTeam)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.team_conv
  
  type RowGalleyTeamConv = (Maybe UUID, Maybe UUID, Maybe Bool)
  
  selectGalleyTeamConv :: PrepQuery R (Identity TeamId) RowGalleyTeamConv
  selectGalleyTeamConv = "SELECT team, conv, managed FROM team_conv WHERE team = ?"
  
  readGalleyTeamConv :: Env -> TeamId -> ConduitM () [RowGalleyTeamConv] IO ()
  readGalleyTeamConv Env {..} tid =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamConv (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectGalleyTeamConvAll :: PrepQuery R () RowGalleyTeamConv
  selectGalleyTeamConvAll = "SELECT team, conv, managed FROM team_conv"
  
  readGalleyTeamConvAll :: Env -> ConduitM () [RowGalleyTeamConv] IO ()
  readGalleyTeamConvAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamConvAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyTeamConvFull :: Env -> FilePath -> IO ()
  exportGalleyTeamConvFull env path = do
    putStrLn $ "Exporting " <> "galley.team_conv" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyTeamConvAll env
          .| sinkJsonLines handle
  
  insertGalleyTeamConv :: PrepQuery W RowGalleyTeamConv ()
  insertGalleyTeamConv =
    "INSERT INTO team_conv (team, conv, managed) VALUES (?, ?, ?)"
  
  importGalleyTeamConv :: Env -> FilePath -> IO ()
  importGalleyTeamConv Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.team_conv"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyTeamConv)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.team_features
  
  type RowGalleyTeamFeatures = (Maybe UUID, Maybe Int32, Maybe Int32, Maybe Int32, Maybe Int32, Maybe Int32, Maybe Int32, Maybe Int32, Maybe Int32)
  
  selectGalleyTeamFeatures :: PrepQuery R (Identity TeamId) RowGalleyTeamFeatures
  selectGalleyTeamFeatures = "SELECT team_id, app_lock_enforce, app_lock_inactivity_timeout_secs, app_lock_status, digital_signatures, legalhold_status, search_visibility_status, sso_status, validate_saml_emails FROM team_features WHERE team_id = ?"
  
  readGalleyTeamFeatures :: Env -> TeamId -> ConduitM () [RowGalleyTeamFeatures] IO ()
  readGalleyTeamFeatures Env {..} tid =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamFeatures (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectGalleyTeamFeaturesAll :: PrepQuery R () RowGalleyTeamFeatures
  selectGalleyTeamFeaturesAll = "SELECT team_id, app_lock_enforce, app_lock_inactivity_timeout_secs, app_lock_status, digital_signatures, legalhold_status, search_visibility_status, sso_status, validate_saml_emails FROM team_features"
  
  readGalleyTeamFeaturesAll :: Env -> ConduitM () [RowGalleyTeamFeatures] IO ()
  readGalleyTeamFeaturesAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamFeaturesAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyTeamFeaturesFull :: Env -> FilePath -> IO ()
  exportGalleyTeamFeaturesFull env path = do
    putStrLn $ "Exporting " <> "galley.team_features" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyTeamFeaturesAll env
          .| sinkJsonLines handle
  
  insertGalleyTeamFeatures :: PrepQuery W RowGalleyTeamFeatures ()
  insertGalleyTeamFeatures =
    "INSERT INTO team_features (team_id, app_lock_enforce, app_lock_inactivity_timeout_secs, app_lock_status, digital_signatures, legalhold_status, search_visibility_status, sso_status, validate_saml_emails) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
  
  importGalleyTeamFeatures :: Env -> FilePath -> IO ()
  importGalleyTeamFeatures Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.team_features"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyTeamFeatures)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.team_member
  
  type RowGalleyTeamMember = (Maybe UUID, Maybe UUID, Maybe UTCTime, Maybe UUID, Maybe Int32, Maybe Permissions)
  
  selectGalleyTeamMember :: PrepQuery R (Identity TeamId) RowGalleyTeamMember
  selectGalleyTeamMember = "SELECT team, user, invited_at, invited_by, legalhold_status, perms FROM team_member WHERE team = ?"
  
  readGalleyTeamMember :: Env -> TeamId -> ConduitM () [RowGalleyTeamMember] IO ()
  readGalleyTeamMember Env {..} tid =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamMember (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectGalleyTeamMemberAll :: PrepQuery R () RowGalleyTeamMember
  selectGalleyTeamMemberAll = "SELECT team, user, invited_at, invited_by, legalhold_status, perms FROM team_member"
  
  readGalleyTeamMemberAll :: Env -> ConduitM () [RowGalleyTeamMember] IO ()
  readGalleyTeamMemberAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamMemberAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyTeamMemberFull :: Env -> FilePath -> IO ()
  exportGalleyTeamMemberFull env path = do
    putStrLn $ "Exporting " <> "galley.team_member" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyTeamMemberAll env
          .| sinkJsonLines handle
  
  insertGalleyTeamMember :: PrepQuery W RowGalleyTeamMember ()
  insertGalleyTeamMember =
    "INSERT INTO team_member (team, user, invited_at, invited_by, legalhold_status, perms) VALUES (?, ?, ?, ?, ?, ?)"
  
  importGalleyTeamMember :: Env -> FilePath -> IO ()
  importGalleyTeamMember Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.team_member"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyTeamMember)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.team_notifications
  
  type RowGalleyTeamNotifications = (Maybe UUID, Maybe TimeUuid, Maybe Blob)
  
  selectGalleyTeamNotifications :: PrepQuery R (Identity TeamId) RowGalleyTeamNotifications
  selectGalleyTeamNotifications = "SELECT team, id, payload FROM team_notifications WHERE team = ?"
  
  readGalleyTeamNotifications :: Env -> TeamId -> ConduitM () [RowGalleyTeamNotifications] IO ()
  readGalleyTeamNotifications Env {..} tid =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamNotifications (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectGalleyTeamNotificationsAll :: PrepQuery R () RowGalleyTeamNotifications
  selectGalleyTeamNotificationsAll = "SELECT team, id, payload FROM team_notifications"
  
  readGalleyTeamNotificationsAll :: Env -> ConduitM () [RowGalleyTeamNotifications] IO ()
  readGalleyTeamNotificationsAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyTeamNotificationsAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyTeamNotificationsFull :: Env -> FilePath -> IO ()
  exportGalleyTeamNotificationsFull env path = do
    putStrLn $ "Exporting " <> "galley.team_notifications" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyTeamNotificationsAll env
          .| sinkJsonLines handle
  
  insertGalleyTeamNotifications :: PrepQuery W RowGalleyTeamNotifications ()
  insertGalleyTeamNotifications =
    "INSERT INTO team_notifications (team, id, payload) VALUES (?, ?, ?)"
  
  importGalleyTeamNotifications :: Env -> FilePath -> IO ()
  importGalleyTeamNotifications Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.team_notifications"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyTeamNotifications)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.user
  
  type RowGalleyUser = (Maybe UUID, Maybe UUID, Maybe Text, Maybe UUID)
  
  selectGalleyUser :: PrepQuery R (Identity [UserId]) RowGalleyUser
  selectGalleyUser = "SELECT user, conv, conv_remote_domain, conv_remote_id FROM user WHERE user in ?"
  
  readGalleyUser :: Env -> [UserId] -> ConduitM () [RowGalleyUser] IO ()
  readGalleyUser Env {..} uids =
    transPipe (runClient envGalley) $
      paginateC selectGalleyUser (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectGalleyUserAll :: PrepQuery R () RowGalleyUser
  selectGalleyUserAll = "SELECT user, conv, conv_remote_domain, conv_remote_id FROM user"
  
  readGalleyUserAll :: Env -> ConduitM () [RowGalleyUser] IO ()
  readGalleyUserAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyUserAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyUserFull :: Env -> FilePath -> IO ()
  exportGalleyUserFull env path = do
    putStrLn $ "Exporting " <> "galley.user" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyUserAll env
          .| sinkJsonLines handle
  
  insertGalleyUser :: PrepQuery W RowGalleyUser ()
  insertGalleyUser =
    "INSERT INTO user (user, conv, conv_remote_domain, conv_remote_id) VALUES (?, ?, ?, ?)"
  
  importGalleyUser :: Env -> FilePath -> IO ()
  importGalleyUser Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.user"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyUser)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- galley.user_team
  
  type RowGalleyUserTeam = (Maybe UUID, Maybe UUID)
  
  selectGalleyUserTeam :: PrepQuery R (Identity [UserId]) RowGalleyUserTeam
  selectGalleyUserTeam = "SELECT user, team FROM user_team WHERE user in ?"
  
  readGalleyUserTeam :: Env -> [UserId] -> ConduitM () [RowGalleyUserTeam] IO ()
  readGalleyUserTeam Env {..} uids =
    transPipe (runClient envGalley) $
      paginateC selectGalleyUserTeam (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectGalleyUserTeamAll :: PrepQuery R () RowGalleyUserTeam
  selectGalleyUserTeamAll = "SELECT user, team FROM user_team"
  
  readGalleyUserTeamAll :: Env -> ConduitM () [RowGalleyUserTeam] IO ()
  readGalleyUserTeamAll Env {..} =
    transPipe (runClient envGalley) $
      paginateC selectGalleyUserTeamAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGalleyUserTeamFull :: Env -> FilePath -> IO ()
  exportGalleyUserTeamFull env path = do
    putStrLn $ "Exporting " <> "galley.user_team" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGalleyUserTeamAll env
          .| sinkJsonLines handle
  
  insertGalleyUserTeam :: PrepQuery W RowGalleyUserTeam ()
  insertGalleyUserTeam =
    "INSERT INTO user_team (user, team) VALUES (?, ?)"
  
  importGalleyUserTeam :: Env -> FilePath -> IO ()
  importGalleyUserTeam Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "galley.user_team"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGalley) (sinkTableRows insertGalleyUserTeam)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- gundeck.notifications
  
  type RowGundeckNotifications = (Maybe UUID, Maybe TimeUuid, Maybe (Cassandra.Set Text), Maybe Blob)
  
  selectGundeckNotifications :: PrepQuery R (Identity [UserId]) RowGundeckNotifications
  selectGundeckNotifications = "SELECT user, id, clients, payload FROM notifications WHERE user in ?"
  
  readGundeckNotifications :: Env -> [UserId] -> ConduitM () [RowGundeckNotifications] IO ()
  readGundeckNotifications Env {..} uids =
    transPipe (runClient envGundeck) $
      paginateC selectGundeckNotifications (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectGundeckNotificationsAll :: PrepQuery R () RowGundeckNotifications
  selectGundeckNotificationsAll = "SELECT user, id, clients, payload FROM notifications"
  
  readGundeckNotificationsAll :: Env -> ConduitM () [RowGundeckNotifications] IO ()
  readGundeckNotificationsAll Env {..} =
    transPipe (runClient envGundeck) $
      paginateC selectGundeckNotificationsAll (paramsP LocalQuorum () envPageSize) x5
  
  exportGundeckNotificationsFull :: Env -> FilePath -> IO ()
  exportGundeckNotificationsFull env path = do
    putStrLn $ "Exporting " <> "gundeck.notifications" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readGundeckNotificationsAll env
          .| sinkJsonLines handle
  
  insertGundeckNotifications :: PrepQuery W RowGundeckNotifications ()
  insertGundeckNotifications =
    "INSERT INTO notifications (user, id, clients, payload) VALUES (?, ?, ?, ?)"
  
  importGundeckNotifications :: Env -> FilePath -> IO ()
  importGundeckNotifications Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "gundeck.notifications"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envGundeck) (sinkTableRows insertGundeckNotifications)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- spar.scim_external
  
  type RowSparScimExternal = (Maybe UUID, Maybe Text, Maybe UUID)
  
  selectSparScimExternal :: PrepQuery R (Identity TeamId) RowSparScimExternal
  selectSparScimExternal = "SELECT team, external_id, user FROM scim_external WHERE team = ?"
  
  readSparScimExternal :: Env -> TeamId -> ConduitM () [RowSparScimExternal] IO ()
  readSparScimExternal Env {..} tid =
    transPipe (runClient envSpar) $
      paginateC selectSparScimExternal (paramsP LocalQuorum (pure tid) envPageSize) x5
  
  selectSparScimExternalAll :: PrepQuery R () RowSparScimExternal
  selectSparScimExternalAll = "SELECT team, external_id, user FROM scim_external"
  
  readSparScimExternalAll :: Env -> ConduitM () [RowSparScimExternal] IO ()
  readSparScimExternalAll Env {..} =
    transPipe (runClient envSpar) $
      paginateC selectSparScimExternalAll (paramsP LocalQuorum () envPageSize) x5
  
  exportSparScimExternalFull :: Env -> FilePath -> IO ()
  exportSparScimExternalFull env path = do
    putStrLn $ "Exporting " <> "spar.scim_external" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readSparScimExternalAll env
          .| sinkJsonLines handle
  
  insertSparScimExternal :: PrepQuery W RowSparScimExternal ()
  insertSparScimExternal =
    "INSERT INTO scim_external (team, external_id, user) VALUES (?, ?, ?)"
  
  importSparScimExternal :: Env -> FilePath -> IO ()
  importSparScimExternal Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "spar.scim_external"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envSpar) (sinkTableRows insertSparScimExternal)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- spar.scim_user_times
  
  type RowSparScimUserTimes = (Maybe UUID, Maybe UTCTime, Maybe UTCTime)
  
  selectSparScimUserTimes :: PrepQuery R (Identity [UserId]) RowSparScimUserTimes
  selectSparScimUserTimes = "SELECT uid, created_at, last_updated_at FROM scim_user_times WHERE uid in ?"
  
  readSparScimUserTimes :: Env -> [UserId] -> ConduitM () [RowSparScimUserTimes] IO ()
  readSparScimUserTimes Env {..} uids =
    transPipe (runClient envSpar) $
      paginateC selectSparScimUserTimes (paramsP LocalQuorum (pure uids) envPageSize) x5
  
  selectSparScimUserTimesAll :: PrepQuery R () RowSparScimUserTimes
  selectSparScimUserTimesAll = "SELECT uid, created_at, last_updated_at FROM scim_user_times"
  
  readSparScimUserTimesAll :: Env -> ConduitM () [RowSparScimUserTimes] IO ()
  readSparScimUserTimesAll Env {..} =
    transPipe (runClient envSpar) $
      paginateC selectSparScimUserTimesAll (paramsP LocalQuorum () envPageSize) x5
  
  exportSparScimUserTimesFull :: Env -> FilePath -> IO ()
  exportSparScimUserTimesFull env path = do
    putStrLn $ "Exporting " <> "spar.scim_user_times" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readSparScimUserTimesAll env
          .| sinkJsonLines handle
  
  insertSparScimUserTimes :: PrepQuery W RowSparScimUserTimes ()
  insertSparScimUserTimes =
    "INSERT INTO scim_user_times (uid, created_at, last_updated_at) VALUES (?, ?, ?)"
  
  importSparScimUserTimes :: Env -> FilePath -> IO ()
  importSparScimUserTimes Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "spar.scim_user_times"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envSpar) (sinkTableRows insertSparScimUserTimes)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  -- spar.user
  
  type RowSparUser = (Maybe Text, Maybe Text, Maybe UUID)
  
  selectSparUserAll :: PrepQuery R () RowSparUser
  selectSparUserAll = "SELECT issuer, sso_id, uid FROM user"
  
  readSparUserAll :: Env -> ConduitM () [RowSparUser] IO ()
  readSparUserAll Env {..} =
    transPipe (runClient envSpar) $
      paginateC selectSparUserAll (paramsP LocalQuorum () envPageSize) x5
  
  exportSparUserFull :: Env -> FilePath -> IO ()
  exportSparUserFull env path = do
    putStrLn $ "Exporting " <> "spar.user" <> " to " <> path
    withBinaryFile path WriteMode $ \handle ->
      runConduit $
        readSparUserAll env
          .| sinkJsonLines handle
  
  insertSparUser :: PrepQuery W RowSparUser ()
  insertSparUser =
    "INSERT INTO user (issuer, sso_id, uid) VALUES (?, ?, ?)"
  
  importSparUser :: Env -> FilePath -> IO ()
  importSparUser Env {..} path = do
    exists <- doesFileExist path
    if exists
      then do
        putStrLn $ "Importing " <> path <> " to " <> "spar.user"
        withBinaryFile path ReadMode $ \handle ->
          runConduit $
            sourceJsonLines handle
              .| transPipe (runClient envSpar) (sinkTableRows insertSparUser)
      else do
        putStrLn $ "Skipping because not found: " <> path
        pure ()
  
  importAllTables :: Env -> IO ()
  importAllTables env@Env {..} = do
    importBrigClients env (envTargetPath </> "brig.clients")
    importBrigConnection env (envTargetPath </> "brig.connection")
    importBrigLoginCodes env (envTargetPath </> "brig.login_codes")
    importBrigPasswordReset env (envTargetPath </> "brig.password_reset")
    importBrigPrekeys env (envTargetPath </> "brig.prekeys")
    importBrigProperties env (envTargetPath </> "brig.properties")
    importBrigRichInfo env (envTargetPath </> "brig.rich_info")
    importBrigUser env (envTargetPath </> "brig.user")
    importBrigUserHandle env (envTargetPath </> "brig.user_handle")
    importBrigUserKeys env (envTargetPath </> "brig.user_keys")
    importGalleyBillingTeamMember env (envTargetPath </> "galley.billing_team_member")
    importGalleyClients env (envTargetPath </> "galley.clients")
    importGalleyConversation env (envTargetPath </> "galley.conversation")
    importGalleyMember env (envTargetPath </> "galley.member")
    importGalleyTeam env (envTargetPath </> "galley.team")
    importGalleyTeamConv env (envTargetPath </> "galley.team_conv")
    importGalleyTeamFeatures env (envTargetPath </> "galley.team_features")
    importGalleyTeamMember env (envTargetPath </> "galley.team_member")
    importGalleyTeamNotifications env (envTargetPath </> "galley.team_notifications")
    importGalleyUser env (envTargetPath </> "galley.user")
    importGalleyUserTeam env (envTargetPath </> "galley.user_team")
    importGundeckNotifications env (envTargetPath </> "gundeck.notifications")
    importSparScimExternal env (envTargetPath </> "spar.scim_external")
    importSparScimUserTimes env (envTargetPath </> "spar.scim_user_times")
    importSparUser env (envTargetPath </> "spar.user")
  
  exportAllTablesFull :: Env -> IO ()
  exportAllTablesFull env@Env {..} = do
    exportBrigClientsFull env (envTargetPath </> "brig.clients")
    exportBrigConnectionFull env (envTargetPath </> "brig.connection")
    exportBrigLoginCodesFull env (envTargetPath </> "brig.login_codes")
    exportBrigPasswordResetFull env (envTargetPath </> "brig.password_reset")
    exportBrigPrekeysFull env (envTargetPath </> "brig.prekeys")
    exportBrigPropertiesFull env (envTargetPath </> "brig.properties")
    exportBrigRichInfoFull env (envTargetPath </> "brig.rich_info")
    exportBrigUserFull env (envTargetPath </> "brig.user")
    exportBrigUserHandleFull env (envTargetPath </> "brig.user_handle")
    exportBrigUserKeysFull env (envTargetPath </> "brig.user_keys")
    exportGalleyBillingTeamMemberFull env (envTargetPath </> "galley.billing_team_member")
    exportGalleyClientsFull env (envTargetPath </> "galley.clients")
    exportGalleyConversationFull env (envTargetPath </> "galley.conversation")
    exportGalleyMemberFull env (envTargetPath </> "galley.member")
    exportGalleyTeamFull env (envTargetPath </> "galley.team")
    exportGalleyTeamConvFull env (envTargetPath </> "galley.team_conv")
    exportGalleyTeamFeaturesFull env (envTargetPath </> "galley.team_features")
    exportGalleyTeamMemberFull env (envTargetPath </> "galley.team_member")
    exportGalleyTeamNotificationsFull env (envTargetPath </> "galley.team_notifications")
    exportGalleyUserFull env (envTargetPath </> "galley.user")
    exportGalleyUserTeamFull env (envTargetPath </> "galley.user_team")
    exportGundeckNotificationsFull env (envTargetPath </> "gundeck.notifications")
    exportSparScimExternalFull env (envTargetPath </> "spar.scim_external")
    exportSparScimUserTimesFull env (envTargetPath </> "spar.scim_user_times")
    exportSparUserFull env (envTargetPath </> "spar.user")
  