diff --git a/src/Model/Migration.hs b/src/Model/Migration.hs index 7dc0f1de6..76a93e5ac 100644 --- a/src/Model/Migration.hs +++ b/src/Model/Migration.hs @@ -75,6 +75,14 @@ migrateAll = do runMigration migrateAll' +{- + Confusion about quotes, from the PostgreSQL Manual: + Single quotes for string constants, double quotes for table/column names. + + QuasiQuoter: ^{TableName} @{ColumnName} (includes Escaping); + #{anything} (no escaping); +-} + customMigrations :: MonadIO m => Map (Key AppliedMigration) (ReaderT SqlBackend m ()) customMigrations = Map.fromListWith (>>) @@ -105,47 +113,62 @@ customMigrations = Map.fromListWith (>>) _other -> return () ) , ( AppliedMigrationKey [migrationVersion|1.0.0|] [version|2.0.0|] - , do -- SchoolId is the Shorthand CI Text now - {- - Confusion about quotes, from the SQL Manual: - Single quotes for string constants, double quotes for table/column names. - - QuasiQuoter: ^{TableName} @{ColumnName} (includes Escaping); - #{anything} (no escaping); - -} + , whenM (tableExists "school") $ do -- SchoolId is the Shorthand CI Text now -- Read old table into memory - -- schoolTable :: [(Single Int64, Single Text)] schoolTable <- [sqlQQ| SELECT "id", "shorthand" FROM "school"; |] let _sT = schoolTable :: [(Single Int64, Single (CI Text))] -- Types needed -- Convert columns containing SchoolId - let convert0 = [executeQQ| - ALTER TABLE "user_admin" DROP CONSTRAINT user_admin_school_fkey; - ALTER TABLE "user_lecturer" DROP CONSTRAINT user_lecturer_school_fkey; - ALTER TABLE "course" DROP CONSTRAINT course_school_fkey; + whenM (tableExists "user_admin") $ do + [executeQQ| + ALTER TABLE "user_admin" DROP CONSTRAINT user_admin_school_fkey; + ALTER TABLE "user_admin" ALTER COLUMN school TYPE citext USING school::citext; |] --- let convert1 = [executeQQ| --- ALTER TABLE "user_admin" ALTER COLUMN school TYPE citext USING CAST(school AS citext); --- ALTER TABLE "user_lecturer" ALTER COLUMN school TYPE citext USING CAST(school AS citext); --- ALTER TABLE "course" ALTER COLUMN school TYPE citext USING CAST(school AS citext); --- |] - -- Convert Number-Strings to Shorthands - let convert2 = forM_ schoolTable (\(Single idnr, Single ssh) -> - [executeQQ| - UPDATE "user_admin" SET "school" = #{ssh} WHERE school = #{idnr}; - UPDATE "user_lecturer" SET "school" = #{ssh} WHERE school = #{idnr}; - UPDATE "user_course" SET "school" = #{ssh} WHERE school = #{idnr}; - |] - ) - -- Recreate constraints - let convert3 = [executeQQ| - ALTER TABLE "user_admin" ADD CONSTRAINT "user_admin_school_fkey" - FOREIGN KEY (school) REFERENCES school(shorthand); - ALTER TABLE "user_lecturer" ADD CONSTRAINT "user_lecturer_school_fkey" + forM_ schoolTable $ \(Single idnr, Single ssh) -> + [executeQQ| + UPDATE "user_admin" SET "school" = #{ssh} WHERE school = #{tshow idnr}; + |] + [executeQQ| + ALTER TABLE "user_admin" ADD CONSTRAINT "user_admin_school_fkey" + FOREIGN KEY (school) REFERENCES school(shorthand); + |] + whenM (tableExists "user_lecturer") $ do + [executeQQ| + ALTER TABLE "user_lecturer" DROP CONSTRAINT user_lecturer_school_fkey; + ALTER TABLE "user_lecturer" ALTER COLUMN school TYPE citext USING school::citext; + |] + forM_ schoolTable $ \(Single idnr, Single ssh) -> + [executeQQ| + UPDATE "user_lecturer" SET "school" = #{ssh} WHERE school = #{tshow idnr}; + |] + [executeQQ| + ALTER TABLE "user_lecturer" ADD CONSTRAINT "user_lecturer_school_fkey" FOREIGN KEY (school) REFERENCES school(shorthand);; - ALTER TABLE "course" ADD CONSTRAINT "course_school_fkey" + |] + whenM (tableExists "course") $ do + [executeQQ| + ALTER TABLE "course" DROP CONSTRAINT course_school_fkey; + ALTER TABLE "course" ALTER COLUMN school TYPE citext USING school::citext; + |] + forM_ schoolTable $ \(Single idnr, Single ssh) -> + [executeQQ| + UPDATE "course" SET "school" = #{ssh} WHERE school = #{tshow idnr}; + |] + [executeQQ| + ALTER TABLE "course" ADD CONSTRAINT "course_school_fkey" FOREIGN KEY (school) REFERENCES school(shorthand); |] - let convert = convert0 >> convert2 >> convert3 - convert + [executeQQ| + ALTER TABLE "school" DROP COLUMN "id"; + ALTER TABLE "school" ADD PRIMARY KEY (shorthand); + |] ) ] + + + +tableExists :: MonadIO m => Text -> ReaderT SqlBackend m Bool +tableExists table = do + haveSchoolTable <- [sqlQQ| SELECT to_regclass(#{table}); |] + case haveSchoolTable :: [Maybe (Single Text)] of + [Just _] -> return True + _other -> return False