Skip to content

Commit

Permalink
Swap :id and :tenant_id columns in match_full unique indexes
Browse files Browse the repository at this point in the history
Make everything consistent, :tenant_id is always the first column in indexes.

Migrations generated with:
mix ash_postgres.generate_migrations swap_id_and_tenant_id_used_for_match_full

Signed-off-by: Riccardo Binetti <[email protected]>
  • Loading branch information
rbino committed Oct 4, 2024
1 parent 1efd59f commit eae85a0
Show file tree
Hide file tree
Showing 16 changed files with 3,057 additions and 4 deletions.
6 changes: 2 additions & 4 deletions backend/lib/edgehog/multitenant_resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule Edgehog.MultitenantResource do
reference :tenant, on_delete: :delete
end

# We have to create a unique index on `[:id, :tenant_id]` to be able to use composite
# We have to create a unique index on `[:tenant_id, :id]` to be able to use composite
# foreign keys (i.e. `with: [tenant_id: :tenant_id]`).
# We have to wrap this in an `if` because some resources (e.g. many-to-many join tables
# like `devices_tags`) don't have a single :id primary key. Those resources manually add
Expand All @@ -63,9 +63,7 @@ defmodule Edgehog.MultitenantResource do
custom_indexes do
# Assumptions:
# - There is a primary key and it's called :id
# We use `all_tenants?: true` so we can control the order of the index and be
# consistent with the indexes that were created when using Ecto manually
index [:id, :tenant_id], unique: true, all_tenants?: true
index [:id], unique: true
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
defmodule Edgehog.Repo.Migrations.SwapIdAndTenantIdUsedForMatchFull do
@moduledoc """
Updates resources based on their most recent snapshots.
This file was autogenerated with `mix ash_postgres.generate_migrations`
"""

use Ecto.Migration

def up do
drop_if_exists index(:update_channels, [:id, :tenant_id])

create index(:update_channels, [:tenant_id, :id], unique: true)

drop_if_exists index(:update_campaigns, [:id, :tenant_id])

create index(:update_campaigns, [:tenant_id, :id], unique: true)

drop_if_exists index(:update_campaign_targets, [:id, :tenant_id])

create index(:update_campaign_targets, [:tenant_id, :id], unique: true)

drop_if_exists index(:tags, [:id, :tenant_id])

create index(:tags, [:tenant_id, :id], unique: true)

drop_if_exists index(:system_models, [:id, :tenant_id])

create index(:system_models, [:tenant_id, :id], unique: true)

drop_if_exists index(:system_model_part_numbers, [:id, :tenant_id])

create index(:system_model_part_numbers, [:tenant_id, :id], unique: true)

drop_if_exists index(:realms, [:id, :tenant_id])

create index(:realms, [:tenant_id, :id], unique: true)

drop_if_exists index(:ota_operations, [:id, :tenant_id])

create index(:ota_operations, [:tenant_id, :id], unique: true)

drop_if_exists index(:hardware_types, [:id, :tenant_id])

create index(:hardware_types, [:tenant_id, :id], unique: true)

drop_if_exists index(:hardware_type_part_numbers, [:id, :tenant_id])

create index(:hardware_type_part_numbers, [:tenant_id, :id], unique: true)

drop_if_exists index(:devices, [:id, :tenant_id])

create index(:devices, [:tenant_id, :id], unique: true)

drop_if_exists index(:device_groups, [:id, :tenant_id])

create index(:device_groups, [:tenant_id, :id], unique: true)

drop_if_exists index(:base_images, [:id, :tenant_id])

create index(:base_images, [:tenant_id, :id], unique: true)

drop_if_exists index(:base_image_collections, [:id, :tenant_id])

create index(:base_image_collections, [:tenant_id, :id], unique: true)
end

def down do
drop_if_exists index(:base_image_collections, [:tenant_id, :id])

create index(:base_image_collections, [:id, :tenant_id], unique: true)

drop_if_exists index(:base_images, [:tenant_id, :id])

create index(:base_images, [:id, :tenant_id], unique: true)

drop_if_exists index(:device_groups, [:tenant_id, :id])

create index(:device_groups, [:id, :tenant_id], unique: true)

drop_if_exists index(:devices, [:tenant_id, :id])

create index(:devices, [:id, :tenant_id], unique: true)

drop_if_exists index(:hardware_type_part_numbers, [:tenant_id, :id])

create index(:hardware_type_part_numbers, [:id, :tenant_id], unique: true)

drop_if_exists index(:hardware_types, [:tenant_id, :id])

create index(:hardware_types, [:id, :tenant_id], unique: true)

drop_if_exists index(:ota_operations, [:tenant_id, :id])

create index(:ota_operations, [:id, :tenant_id], unique: true)

drop_if_exists index(:realms, [:tenant_id, :id])

create index(:realms, [:id, :tenant_id], unique: true)

drop_if_exists index(:system_model_part_numbers, [:tenant_id, :id])

create index(:system_model_part_numbers, [:id, :tenant_id], unique: true)

drop_if_exists index(:system_models, [:tenant_id, :id])

create index(:system_models, [:id, :tenant_id], unique: true)

drop_if_exists index(:tags, [:tenant_id, :id])

create index(:tags, [:id, :tenant_id], unique: true)

drop_if_exists index(:update_campaign_targets, [:tenant_id, :id])

create index(:update_campaign_targets, [:id, :tenant_id], unique: true)

drop_if_exists index(:update_campaigns, [:tenant_id, :id])

create index(:update_campaigns, [:id, :tenant_id], unique: true)

drop_if_exists index(:update_channels, [:tenant_id, :id])

create index(:update_channels, [:id, :tenant_id], unique: true)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
{
"attributes": [
{
"allow_nil?": false,
"default": "nil",
"generated?": true,
"primary_key?": true,
"references": null,
"size": null,
"source": "id",
"type": "bigint"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "name",
"type": "text"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "handle",
"type": "text"
},
{
"allow_nil?": false,
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "inserted_at",
"type": "utc_datetime_usec"
},
{
"allow_nil?": false,
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "updated_at",
"type": "utc_datetime_usec"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": {
"deferrable": false,
"destination_attribute": "tenant_id",
"destination_attribute_default": null,
"destination_attribute_generated": null,
"index?": false,
"match_type": null,
"match_with": null,
"multitenancy": {
"attribute": null,
"global": null,
"strategy": null
},
"name": "base_image_collections_tenant_id_fkey",
"on_delete": "delete",
"on_update": null,
"primary_key?": true,
"schema": "public",
"table": "tenants"
},
"size": null,
"source": "tenant_id",
"type": "bigint"
},
{
"allow_nil?": false,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": {
"deferrable": false,
"destination_attribute": "id",
"destination_attribute_default": null,
"destination_attribute_generated": null,
"index?": false,
"match_type": "full",
"match_with": {
"tenant_id": "tenant_id"
},
"multitenancy": {
"attribute": "tenant_id",
"global": false,
"strategy": "attribute"
},
"name": "base_image_collections_system_model_id_fkey",
"on_delete": "nothing",
"on_update": null,
"primary_key?": true,
"schema": "public",
"table": "system_models"
},
"size": null,
"source": "system_model_id",
"type": "bigint"
}
],
"base_filter": null,
"check_constraints": [],
"custom_indexes": [
{
"all_tenants?": false,
"concurrently": false,
"error_fields": [
"id"
],
"fields": [
{
"type": "atom",
"value": "id"
}
],
"include": null,
"message": null,
"name": null,
"nulls_distinct": true,
"prefix": null,
"table": null,
"unique": true,
"using": null,
"where": null
},
{
"all_tenants?": true,
"concurrently": false,
"error_fields": [
"tenant_id"
],
"fields": [
{
"type": "atom",
"value": "tenant_id"
}
],
"include": null,
"message": null,
"name": null,
"nulls_distinct": true,
"prefix": null,
"table": null,
"unique": false,
"using": null,
"where": null
}
],
"custom_statements": [],
"has_create_action": true,
"hash": "09AEADC1ACB92FF4DF87315A7F456DF5459A3746CE7AFA686480DB8ACD8E65AF",
"identities": [
{
"all_tenants?": false,
"base_filter": null,
"index_name": "base_image_collections_handle_index",
"keys": [
{
"type": "atom",
"value": "handle"
}
],
"name": "handle",
"nils_distinct?": true,
"where": null
},
{
"all_tenants?": false,
"base_filter": null,
"index_name": "base_image_collections_name_index",
"keys": [
{
"type": "atom",
"value": "name"
}
],
"name": "name",
"nils_distinct?": true,
"where": null
},
{
"all_tenants?": false,
"base_filter": null,
"index_name": "base_image_collections_system_model_id_index",
"keys": [
{
"type": "atom",
"value": "system_model_id"
}
],
"name": "system_model_id",
"nils_distinct?": true,
"where": null
}
],
"multitenancy": {
"attribute": "tenant_id",
"global": false,
"strategy": "attribute"
},
"repo": "Elixir.Edgehog.Repo",
"schema": null,
"table": "base_image_collections"
}
Loading

0 comments on commit eae85a0

Please sign in to comment.