From 0e1482c2b88f25a6831273a5ae6e0ceac4602627 Mon Sep 17 00:00:00 2001 From: Malte Rohde Date: Wed, 6 Dec 2023 13:31:59 +0100 Subject: [PATCH] Handle missing schemas in ensure_up! We noticed that `c:Migrator.ensure_up!/0` does not check for existence of schemas before calling `Ecto.Migrator.migrations/3`, which unfortunately terminates with a rather cryptic error. This PR fixes that by explicitly checking schema existence before calling `migrations/3`. Opted for only checking (instead of creating it) to keep `ensure_up!/0`'s behaviour "read-only". --- CHANGELOG.md | 1 + lib/bitcrowd_ecto/migrator.ex | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d494bb6..5c726e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed * Allow any type of `id` param in `Repo.fetch/2`. Remove the (incorrect) guard restricting the `id` param to binaries, against the spec saying it would allow `any`. +* Handle missing schemas gracefully in `Migrator.ensure_up!/0`. ## [0.16.0] - 2023-03-21 diff --git a/lib/bitcrowd_ecto/migrator.ex b/lib/bitcrowd_ecto/migrator.ex index d136c76..3bfab80 100644 --- a/lib/bitcrowd_ecto/migrator.ex +++ b/lib/bitcrowd_ecto/migrator.ex @@ -215,10 +215,19 @@ defmodule BitcrowdEcto.Migrator do end defp down_tenant_migrations(repo) do + for tenant <- repo.known_prefixes() do + if schema_exists?(repo, tenant) do + down_tenant_migrations(repo, tenant) + else + ["SCHEMA DOES NOT EXIST: #{tenant}"] + end + end + end + + defp down_tenant_migrations(repo, tenant) do path = tenant_migrations_path(repo) - for tenant <- repo.known_prefixes(), - {:down, prefix, name} <- Migrator.migrations(repo, [path], prefix: tenant) do + for {:down, prefix, name} <- Migrator.migrations(repo, [path], prefix: tenant) do "#{prefix}_#{name} (tenant: #{tenant})" end end @@ -286,8 +295,12 @@ defmodule BitcrowdEcto.Migrator do SELECT 1 FROM information_schema.schemata WHERE schema_name = $1; """ + defp schema_exists?(repo, tenant) do + match?(%{rows: [[1]]}, SQL.query!(repo, @exists_query, [tenant])) + end + defp ensure_schema!(repo, tenant) do - unless match?(%{rows: [[1]]}, SQL.query!(repo, @exists_query, [tenant])) do + unless schema_exists?(repo, tenant) do SQL.query!(repo, ~s(CREATE SCHEMA "#{tenant}"), []) end end