Skip to content

Commit b607d68

Browse files
authored
test: Add concurrent index ordering repro test (#722)
1 parent f0f1626 commit b607d68

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

test/migration_generator_test.exs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,106 @@ defmodule AshPostgres.MigrationGeneratorTest do
490490
end
491491
end
492492

493+
describe "unique identities with `concurrent_indexes: true`" do
494+
test "dependent foreign keys are generated only after the unique index migration", %{
495+
snapshot_path: snapshot_path,
496+
migration_path: migration_path
497+
} do
498+
Code.compiler_options(ignore_module_conflict: true)
499+
500+
defmodule ConcurrentUniqueTarget do
501+
use Ash.Resource, data_layer: AshPostgres.DataLayer, domain: nil
502+
503+
postgres do
504+
table "concurrent_unique_targets"
505+
repo(AshPostgres.TestRepo)
506+
end
507+
508+
attributes do
509+
uuid_primary_key(:id)
510+
attribute(:code, :string, allow_nil?: false, public?: true)
511+
end
512+
513+
identities do
514+
identity(:uniq_code, [:code])
515+
end
516+
517+
actions do
518+
defaults([:create, :read, :update, :destroy])
519+
end
520+
end
521+
522+
defmodule ConcurrentUniqueDependent do
523+
use Ash.Resource, data_layer: AshPostgres.DataLayer, domain: nil
524+
525+
postgres do
526+
table "concurrent_unique_dependents"
527+
repo(AshPostgres.TestRepo)
528+
end
529+
530+
attributes do
531+
uuid_primary_key(:id)
532+
attribute(:target_code, :string, public?: true)
533+
end
534+
535+
relationships do
536+
belongs_to(:target, ConcurrentUniqueTarget) do
537+
source_attribute(:target_code)
538+
destination_attribute(:code)
539+
attribute_writable?(true)
540+
allow_nil?(true)
541+
public?(true)
542+
end
543+
end
544+
545+
actions do
546+
defaults([:create, :read, :update, :destroy])
547+
end
548+
end
549+
550+
defmodule ConcurrentUniqueDomain do
551+
use Ash.Domain
552+
553+
resources do
554+
resource(ConcurrentUniqueTarget)
555+
resource(ConcurrentUniqueDependent)
556+
end
557+
end
558+
559+
Code.compiler_options(ignore_module_conflict: false)
560+
561+
AshPostgres.MigrationGenerator.generate(ConcurrentUniqueDomain,
562+
snapshot_path: snapshot_path,
563+
migration_path: migration_path,
564+
quiet: true,
565+
format: false,
566+
auto_name: true,
567+
concurrent_indexes: true
568+
)
569+
570+
assert [migration_before_index, unique_index_migration] =
571+
Enum.sort(Path.wildcard("#{migration_path}/**/*_migrate_resources*.exs"))
572+
|> Enum.reject(&String.contains?(&1, "extensions"))
573+
574+
first_contents = File.read!(migration_before_index)
575+
second_contents = File.read!(unique_index_migration)
576+
577+
# The correct end state here likely needs three steps:
578+
# 1. create/alter tables without the FK to `:code`
579+
# 2. create the concurrent unique index on `concurrent_unique_targets.code`
580+
# 3. add the FK from `concurrent_unique_dependents.target_code`
581+
#
582+
# With only two files, the FK must not appear before the concurrent unique
583+
# index migration, because Postgres requires the referenced column to be
584+
# backed by a unique or primary key constraint before the FK is added.
585+
assert first_contents =~
586+
~S|create unique_index(:concurrent_unique_targets, [:code], name: "concurrent_unique_targets_uniq_code_index", concurrently: true)|
587+
588+
assert second_contents =~
589+
~S|modify :target_code, references(:concurrent_unique_targets, column: :code, name: "concurrent_unique_dependents_target_code_fkey", type: :text, prefix: "public")|
590+
end
591+
end
592+
493593
describe "custom_indexes with `null_distinct: false`" do
494594
setup %{snapshot_path: snapshot_path, migration_path: migration_path} do
495595
:ok

0 commit comments

Comments
 (0)