From 0eb1717ec4a43b8ff45e4aef49057b9334706966 Mon Sep 17 00:00:00 2001 From: Riccardo Binetti Date: Fri, 4 Oct 2024 18:20:45 +0200 Subject: [PATCH] Make reference indexes tenant scoped Previously, some resources indexed their relationships with an index that was global and did not include the tenant id. Remove custom_indexes and use the index? option on the reference instead. Migrations generated with: mix ash_postgres.generate_migrations make_reference_indexes_tenant_scoped Signed-off-by: Riccardo Binetti --- backend/lib/edgehog/devices/device/device.ex | 5 +- .../devices/hardware_type_part_number.ex | 5 +- .../devices/system_model/system_model.ex | 5 +- .../devices/system_model_part_number.ex | 5 +- .../ota_operation/ota_operation.ex | 5 +- .../update_campaign/update_campaign.ex | 7 +- .../update_target/update_target.ex | 7 +- ...3_make_reference_indexes_tenant_scoped.exs | 415 ++++++++++++++++++ .../repo/devices/20241004162033.json | 248 +++++++++++ .../20241004162033.json | 184 ++++++++ .../repo/ota_operations/20241004162033.json | 219 +++++++++ .../20241004162033.json | 184 ++++++++ .../repo/system_models/20241004162033.json | 228 ++++++++++ .../20241004162033.json | 280 ++++++++++++ .../repo/update_campaigns/20241004162033.json | 250 +++++++++++ 15 files changed, 2017 insertions(+), 30 deletions(-) create mode 100644 backend/priv/repo/migrations/20241004162033_make_reference_indexes_tenant_scoped.exs create mode 100644 backend/priv/resource_snapshots/repo/devices/20241004162033.json create mode 100644 backend/priv/resource_snapshots/repo/hardware_type_part_numbers/20241004162033.json create mode 100644 backend/priv/resource_snapshots/repo/ota_operations/20241004162033.json create mode 100644 backend/priv/resource_snapshots/repo/system_model_part_numbers/20241004162033.json create mode 100644 backend/priv/resource_snapshots/repo/system_models/20241004162033.json create mode 100644 backend/priv/resource_snapshots/repo/update_campaign_targets/20241004162033.json create mode 100644 backend/priv/resource_snapshots/repo/update_campaigns/20241004162033.json diff --git a/backend/lib/edgehog/devices/device/device.ex b/backend/lib/edgehog/devices/device/device.ex index 085e35657..79427cdbe 100644 --- a/backend/lib/edgehog/devices/device/device.ex +++ b/backend/lib/edgehog/devices/device/device.ex @@ -435,6 +435,7 @@ defmodule Edgehog.Devices.Device do references do reference :realm, + index?: true, on_delete: :nothing, match_with: [tenant_id: :tenant_id], match_type: :full @@ -444,9 +445,5 @@ defmodule Edgehog.Devices.Device do # Edgehog reference :system_model_part_number, ignore?: true end - - custom_indexes do - index [:realm_id], all_tenants?: true, unique: false - end end end diff --git a/backend/lib/edgehog/devices/hardware_type_part_number.ex b/backend/lib/edgehog/devices/hardware_type_part_number.ex index 26285069f..b25ab0149 100644 --- a/backend/lib/edgehog/devices/hardware_type_part_number.ex +++ b/backend/lib/edgehog/devices/hardware_type_part_number.ex @@ -74,14 +74,11 @@ defmodule Edgehog.Devices.HardwareTypePartNumber do references do reference :hardware_type, + index?: true, on_delete: :delete, # hardware_type_id can be null, so match_type is :simple, not :full match_type: :simple, match_with: [tenant_id: :tenant_id] end - - custom_indexes do - index [:hardware_type_id], all_tenants?: true, unique: false - end end end diff --git a/backend/lib/edgehog/devices/system_model/system_model.ex b/backend/lib/edgehog/devices/system_model/system_model.ex index 1faa3bf52..e3b58bbd6 100644 --- a/backend/lib/edgehog/devices/system_model/system_model.ex +++ b/backend/lib/edgehog/devices/system_model/system_model.ex @@ -219,13 +219,10 @@ defmodule Edgehog.Devices.SystemModel do references do reference :hardware_type, + index?: true, on_delete: :nothing, match_type: :full, match_with: [tenant_id: :tenant_id] end - - custom_indexes do - index [:hardware_type_id], all_tenants?: true, unique: false - end end end diff --git a/backend/lib/edgehog/devices/system_model_part_number.ex b/backend/lib/edgehog/devices/system_model_part_number.ex index 6b4e66897..9a288f960 100644 --- a/backend/lib/edgehog/devices/system_model_part_number.ex +++ b/backend/lib/edgehog/devices/system_model_part_number.ex @@ -79,14 +79,11 @@ defmodule Edgehog.Devices.SystemModelPartNumber do references do reference :system_model, + index?: true, on_delete: :delete, # system_model_id can be null, so match_type is :simple, not :full match_type: :simple, match_with: [tenant_id: :tenant_id] end - - custom_indexes do - index [:system_model_id], all_tenants?: true, unique: false - end end end diff --git a/backend/lib/edgehog/os_management/ota_operation/ota_operation.ex b/backend/lib/edgehog/os_management/ota_operation/ota_operation.ex index e3afbd730..92fed74c9 100644 --- a/backend/lib/edgehog/os_management/ota_operation/ota_operation.ex +++ b/backend/lib/edgehog/os_management/ota_operation/ota_operation.ex @@ -205,13 +205,10 @@ defmodule Edgehog.OSManagement.OTAOperation do references do reference :device, + index?: true, on_delete: :nothing, match_type: :full, match_with: [tenant_id: :tenant_id] end - - custom_indexes do - index [:device_id], all_tenants?: true, unique: false - end end end diff --git a/backend/lib/edgehog/update_campaigns/update_campaign/update_campaign.ex b/backend/lib/edgehog/update_campaigns/update_campaign/update_campaign.ex index 1f33ab831..0111f8b81 100644 --- a/backend/lib/edgehog/update_campaigns/update_campaign/update_campaign.ex +++ b/backend/lib/edgehog/update_campaigns/update_campaign/update_campaign.ex @@ -221,19 +221,16 @@ defmodule Edgehog.UpdateCampaigns.UpdateCampaign do references do reference :base_image, + index?: true, on_delete: :nothing, match_type: :full, match_with: [tenant_id: :tenant_id] reference :update_channel, + index?: true, on_delete: :nothing, match_type: :full, match_with: [tenant_id: :tenant_id] end - - custom_indexes do - index [:base_image_id], unique: false - index [:update_channel_id], unique: false - end end end diff --git a/backend/lib/edgehog/update_campaigns/update_target/update_target.ex b/backend/lib/edgehog/update_campaigns/update_target/update_target.ex index 052ab2bb4..0c91908ab 100644 --- a/backend/lib/edgehog/update_campaigns/update_target/update_target.ex +++ b/backend/lib/edgehog/update_campaigns/update_target/update_target.ex @@ -226,11 +226,13 @@ defmodule Edgehog.UpdateCampaigns.UpdateTarget do references do reference :update_campaign, + index?: true, on_delete: :delete, match_type: :full, match_with: [tenant_id: :tenant_id] reference :device, + index?: true, on_delete: :nothing, match_type: :full, match_with: [tenant_id: :tenant_id] @@ -239,10 +241,5 @@ defmodule Edgehog.UpdateCampaigns.UpdateTarget do on_delete: :nothing, match_with: [tenant_id: :tenant_id] end - - custom_indexes do - index [:device_id], all_tenants?: true, unique: false - index [:update_campaign_id], all_tenants?: true, unique: false - end end end diff --git a/backend/priv/repo/migrations/20241004162033_make_reference_indexes_tenant_scoped.exs b/backend/priv/repo/migrations/20241004162033_make_reference_indexes_tenant_scoped.exs new file mode 100644 index 000000000..ab4742ff0 --- /dev/null +++ b/backend/priv/repo/migrations/20241004162033_make_reference_indexes_tenant_scoped.exs @@ -0,0 +1,415 @@ +# +# This file is part of Edgehog. +# +# Copyright 2024 SECO Mind Srl +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +defmodule Edgehog.Repo.Migrations.MakeReferenceIndexesTenantScoped 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_campaigns, [:tenant_id, :update_channel_id]) + + drop_if_exists index(:update_campaigns, [:tenant_id, :base_image_id]) + + drop constraint(:update_campaigns, "update_campaigns_update_channel_id_fkey") + + drop constraint(:update_campaigns, "update_campaigns_base_image_id_fkey") + + alter table(:update_campaigns) do + modify :base_image_id, + references(:base_images, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaigns_base_image_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + drop_if_exists index(:update_campaign_targets, [:update_campaign_id]) + + drop_if_exists index(:update_campaign_targets, [:device_id]) + + drop constraint(:update_campaign_targets, "update_campaign_targets_device_id_fkey") + + drop constraint(:update_campaign_targets, "update_campaign_targets_update_campaign_id_fkey") + + alter table(:update_campaign_targets) do + modify :update_campaign_id, + references(:update_campaigns, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaign_targets_update_campaign_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :delete_all + ) + end + + drop_if_exists index(:system_models, [:hardware_type_id]) + + drop constraint(:system_models, "system_models_hardware_type_id_fkey") + + alter table(:system_models) do + modify :hardware_type_id, + references(:hardware_types, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "system_models_hardware_type_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + drop_if_exists index(:system_model_part_numbers, [:system_model_id]) + + drop constraint(:system_model_part_numbers, "system_model_part_numbers_system_model_id_fkey") + + alter table(:system_model_part_numbers) do + modify :system_model_id, + references(:system_models, + column: :id, + with: [tenant_id: :tenant_id], + match: :simple, + name: "system_model_part_numbers_system_model_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :delete_all + ) + end + + drop_if_exists index(:ota_operations, [:device_id]) + + drop constraint(:ota_operations, "ota_operations_device_id_fkey") + + alter table(:ota_operations) do + modify :device_id, + references(:devices, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "ota_operations_device_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + drop_if_exists index(:hardware_type_part_numbers, [:hardware_type_id]) + + drop constraint( + :hardware_type_part_numbers, + "hardware_type_part_numbers_hardware_type_id_fkey" + ) + + alter table(:hardware_type_part_numbers) do + modify :hardware_type_id, + references(:hardware_types, + column: :id, + with: [tenant_id: :tenant_id], + match: :simple, + name: "hardware_type_part_numbers_hardware_type_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :delete_all + ) + end + + drop_if_exists index(:devices, [:realm_id]) + + drop constraint(:devices, "devices_realm_id_fkey") + + alter table(:devices) do + modify :realm_id, + references(:realms, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "devices_realm_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + execute("ALTER TABLE devices alter CONSTRAINT devices_realm_id_fkey NOT DEFERRABLE") + + create index(:devices, [:tenant_id, :realm_id]) + + execute( + "ALTER TABLE hardware_type_part_numbers alter CONSTRAINT hardware_type_part_numbers_hardware_type_id_fkey NOT DEFERRABLE" + ) + + create index(:hardware_type_part_numbers, [:tenant_id, :hardware_type_id]) + + execute( + "ALTER TABLE ota_operations alter CONSTRAINT ota_operations_device_id_fkey NOT DEFERRABLE" + ) + + create index(:ota_operations, [:tenant_id, :device_id]) + + execute( + "ALTER TABLE system_model_part_numbers alter CONSTRAINT system_model_part_numbers_system_model_id_fkey NOT DEFERRABLE" + ) + + create index(:system_model_part_numbers, [:tenant_id, :system_model_id]) + + execute( + "ALTER TABLE system_models alter CONSTRAINT system_models_hardware_type_id_fkey NOT DEFERRABLE" + ) + + create index(:system_models, [:tenant_id, :hardware_type_id]) + + execute( + "ALTER TABLE update_campaign_targets alter CONSTRAINT update_campaign_targets_update_campaign_id_fkey NOT DEFERRABLE" + ) + + alter table(:update_campaign_targets) do + modify :device_id, + references(:devices, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaign_targets_device_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + execute( + "ALTER TABLE update_campaign_targets alter CONSTRAINT update_campaign_targets_device_id_fkey NOT DEFERRABLE" + ) + + create index(:update_campaign_targets, [:tenant_id, :update_campaign_id]) + + create index(:update_campaign_targets, [:tenant_id, :device_id]) + + execute( + "ALTER TABLE update_campaigns alter CONSTRAINT update_campaigns_base_image_id_fkey NOT DEFERRABLE" + ) + + alter table(:update_campaigns) do + modify :update_channel_id, + references(:update_channels, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaigns_update_channel_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + execute( + "ALTER TABLE update_campaigns alter CONSTRAINT update_campaigns_update_channel_id_fkey NOT DEFERRABLE" + ) + + create index(:update_campaigns, [:tenant_id, :base_image_id]) + + create index(:update_campaigns, [:tenant_id, :update_channel_id]) + end + + def down do + drop_if_exists index(:update_campaigns, [:tenant_id, :update_channel_id]) + + drop_if_exists index(:update_campaigns, [:tenant_id, :base_image_id]) + + drop constraint(:update_campaigns, "update_campaigns_update_channel_id_fkey") + + alter table(:update_campaigns) do + modify :update_channel_id, + references(:update_channels, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaigns_update_channel_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + drop_if_exists index(:update_campaign_targets, [:tenant_id, :device_id]) + + drop_if_exists index(:update_campaign_targets, [:tenant_id, :update_campaign_id]) + + drop constraint(:update_campaign_targets, "update_campaign_targets_device_id_fkey") + + alter table(:update_campaign_targets) do + modify :device_id, + references(:devices, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaign_targets_device_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + drop_if_exists index(:system_models, [:tenant_id, :hardware_type_id]) + + drop_if_exists index(:system_model_part_numbers, [:tenant_id, :system_model_id]) + + drop_if_exists index(:ota_operations, [:tenant_id, :device_id]) + + drop_if_exists index(:hardware_type_part_numbers, [:tenant_id, :hardware_type_id]) + + drop_if_exists index(:devices, [:tenant_id, :realm_id]) + + drop constraint(:devices, "devices_realm_id_fkey") + + alter table(:devices) do + modify :realm_id, + references(:realms, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "devices_realm_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + create index(:devices, [:realm_id]) + + drop constraint( + :hardware_type_part_numbers, + "hardware_type_part_numbers_hardware_type_id_fkey" + ) + + alter table(:hardware_type_part_numbers) do + modify :hardware_type_id, + references(:hardware_types, + column: :id, + with: [tenant_id: :tenant_id], + match: :simple, + name: "hardware_type_part_numbers_hardware_type_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :delete_all + ) + end + + create index(:hardware_type_part_numbers, [:hardware_type_id]) + + drop constraint(:ota_operations, "ota_operations_device_id_fkey") + + alter table(:ota_operations) do + modify :device_id, + references(:devices, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "ota_operations_device_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + create index(:ota_operations, [:device_id]) + + drop constraint(:system_model_part_numbers, "system_model_part_numbers_system_model_id_fkey") + + alter table(:system_model_part_numbers) do + modify :system_model_id, + references(:system_models, + column: :id, + with: [tenant_id: :tenant_id], + match: :simple, + name: "system_model_part_numbers_system_model_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :delete_all + ) + end + + create index(:system_model_part_numbers, [:system_model_id]) + + drop constraint(:system_models, "system_models_hardware_type_id_fkey") + + alter table(:system_models) do + modify :hardware_type_id, + references(:hardware_types, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "system_models_hardware_type_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + create index(:system_models, [:hardware_type_id]) + + drop constraint(:update_campaign_targets, "update_campaign_targets_update_campaign_id_fkey") + + alter table(:update_campaign_targets) do + modify :update_campaign_id, + references(:update_campaigns, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaign_targets_update_campaign_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :delete_all + ) + end + + create index(:update_campaign_targets, [:device_id]) + + create index(:update_campaign_targets, [:update_campaign_id]) + + drop constraint(:update_campaigns, "update_campaigns_base_image_id_fkey") + + alter table(:update_campaigns) do + modify :base_image_id, + references(:base_images, + column: :id, + with: [tenant_id: :tenant_id], + match: :full, + name: "update_campaigns_base_image_id_fkey", + type: :bigint, + prefix: "public", + on_delete: :nothing + ) + end + + create index(:update_campaigns, [:tenant_id, :base_image_id]) + + create index(:update_campaigns, [:tenant_id, :update_channel_id]) + end +end diff --git a/backend/priv/resource_snapshots/repo/devices/20241004162033.json b/backend/priv/resource_snapshots/repo/devices/20241004162033.json new file mode 100644 index 000000000..ce616363d --- /dev/null +++ b/backend/priv/resource_snapshots/repo/devices/20241004162033.json @@ -0,0 +1,248 @@ +{ + "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": "device_id", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "name", + "type": "text" + }, + { + "allow_nil?": false, + "default": "false", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "online", + "type": "boolean" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "last_connection", + "type": "utc_datetime" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "last_disconnection", + "type": "utc_datetime" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "serial_number", + "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": "devices_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?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "devices_realm_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "realms" + }, + "size": null, + "source": "realm_id", + "type": "bigint" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "part_number", + "type": "text" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "E21D1CF8EC910BFF7051312137E283AD90CC9BD2F4A11E8A03349793B223EB99", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "devices_unique_realm_device_id_index", + "keys": [ + { + "type": "atom", + "value": "device_id" + }, + { + "type": "atom", + "value": "realm_id" + } + ], + "name": "unique_realm_device_id", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "devices" +} \ No newline at end of file diff --git a/backend/priv/resource_snapshots/repo/hardware_type_part_numbers/20241004162033.json b/backend/priv/resource_snapshots/repo/hardware_type_part_numbers/20241004162033.json new file mode 100644 index 000000000..ebe574d9d --- /dev/null +++ b/backend/priv/resource_snapshots/repo/hardware_type_part_numbers/20241004162033.json @@ -0,0 +1,184 @@ +{ + "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": "part_number", + "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": "hardware_type_part_numbers_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?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": true, + "match_type": "simple", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "hardware_type_part_numbers_hardware_type_id_fkey", + "on_delete": "delete", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "hardware_types" + }, + "size": null, + "source": "hardware_type_id", + "type": "bigint" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "69072B99452B194D93D44D1C68626525B2F4B7CC7D983278ABE8A5238C2BFFB2", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "hardware_type_part_numbers_part_number_index", + "keys": [ + { + "type": "atom", + "value": "part_number" + } + ], + "name": "part_number", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "hardware_type_part_numbers" +} \ No newline at end of file diff --git a/backend/priv/resource_snapshots/repo/ota_operations/20241004162033.json b/backend/priv/resource_snapshots/repo/ota_operations/20241004162033.json new file mode 100644 index 000000000..2116365a0 --- /dev/null +++ b/backend/priv/resource_snapshots/repo/ota_operations/20241004162033.json @@ -0,0 +1,219 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "base_image_url", + "type": "text" + }, + { + "allow_nil?": false, + "default": "\"pending\"", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "status", + "type": "text" + }, + { + "allow_nil?": false, + "default": "0", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "status_progress", + "type": "bigint" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "status_code", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "message", + "type": "text" + }, + { + "allow_nil?": true, + "default": "false", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "is_manual", + "type": "boolean" + }, + { + "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": "ota_operations_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?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "ota_operations_device_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "devices" + }, + "size": null, + "source": "device_id", + "type": "bigint" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "1340404BC4DC63CDF1B865481D9016CCF167089CF9942700F7945529EDD1819C", + "identities": [], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "ota_operations" +} \ No newline at end of file diff --git a/backend/priv/resource_snapshots/repo/system_model_part_numbers/20241004162033.json b/backend/priv/resource_snapshots/repo/system_model_part_numbers/20241004162033.json new file mode 100644 index 000000000..9bf93a06b --- /dev/null +++ b/backend/priv/resource_snapshots/repo/system_model_part_numbers/20241004162033.json @@ -0,0 +1,184 @@ +{ + "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": "part_number", + "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": "system_model_part_numbers_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?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": true, + "match_type": "simple", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "system_model_part_numbers_system_model_id_fkey", + "on_delete": "delete", + "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?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "3651A6FC9976487CD76DE0922393F13DB03D8AEB2602303414623AEE83DF84C6", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "system_model_part_numbers_part_number_index", + "keys": [ + { + "type": "atom", + "value": "part_number" + } + ], + "name": "part_number", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "system_model_part_numbers" +} \ No newline at end of file diff --git a/backend/priv/resource_snapshots/repo/system_models/20241004162033.json b/backend/priv/resource_snapshots/repo/system_models/20241004162033.json new file mode 100644 index 000000000..125ca484e --- /dev/null +++ b/backend/priv/resource_snapshots/repo/system_models/20241004162033.json @@ -0,0 +1,228 @@ +{ + "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": "handle", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "name", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "picture_url", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "description", + "type": "map" + }, + { + "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": "system_models_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?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "system_models_hardware_type_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "hardware_types" + }, + "size": null, + "source": "hardware_type_id", + "type": "bigint" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "136F5260CA4A95EB0138BFE81604252C066711D42CEBDA8E434EC34DF22E77AA", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "system_models_handle_index", + "keys": [ + { + "type": "atom", + "value": "handle" + } + ], + "name": "handle", + "nils_distinct?": true, + "where": null + }, + { + "all_tenants?": false, + "base_filter": null, + "index_name": "system_models_name_index", + "keys": [ + { + "type": "atom", + "value": "name" + } + ], + "name": "name", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "system_models" +} \ No newline at end of file diff --git a/backend/priv/resource_snapshots/repo/update_campaign_targets/20241004162033.json b/backend/priv/resource_snapshots/repo/update_campaign_targets/20241004162033.json new file mode 100644 index 000000000..a8a47a020 --- /dev/null +++ b/backend/priv/resource_snapshots/repo/update_campaign_targets/20241004162033.json @@ -0,0 +1,280 @@ +{ + "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": "status", + "type": "text" + }, + { + "allow_nil?": false, + "default": "0", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "retry_count", + "type": "bigint" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "latest_attempt", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "completion_timestamp", + "type": "utc_datetime_usec" + }, + { + "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": "update_campaign_targets_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?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "update_campaign_targets_update_campaign_id_fkey", + "on_delete": "delete", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "update_campaigns" + }, + "size": null, + "source": "update_campaign_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?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "update_campaign_targets_device_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "devices" + }, + "size": null, + "source": "device_id", + "type": "bigint" + }, + { + "allow_nil?": true, + "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": null, + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "update_campaign_targets_ota_operation_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "ota_operations" + }, + "size": null, + "source": "ota_operation_id", + "type": "uuid" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "90757F58101FB98BB61270A7EF08952E0327AD45CBFCCB8A6C2D9F52597CC7A4", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "update_campaign_targets_unique_device_for_campaign_index", + "keys": [ + { + "type": "atom", + "value": "update_campaign_id" + }, + { + "type": "atom", + "value": "device_id" + } + ], + "name": "unique_device_for_campaign", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "update_campaign_targets" +} \ No newline at end of file diff --git a/backend/priv/resource_snapshots/repo/update_campaigns/20241004162033.json b/backend/priv/resource_snapshots/repo/update_campaigns/20241004162033.json new file mode 100644 index 000000000..8027705da --- /dev/null +++ b/backend/priv/resource_snapshots/repo/update_campaigns/20241004162033.json @@ -0,0 +1,250 @@ +{ + "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": "status", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "outcome", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "rollout_mechanism", + "type": "map" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "start_timestamp", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "completion_timestamp", + "type": "utc_datetime_usec" + }, + { + "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": "update_campaigns_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?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "update_campaigns_base_image_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "base_images" + }, + "size": null, + "source": "base_image_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?": true, + "match_type": "full", + "match_with": { + "tenant_id": "tenant_id" + }, + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "name": "update_campaigns_update_channel_id_fkey", + "on_delete": "nothing", + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "update_channels" + }, + "size": null, + "source": "update_channel_id", + "type": "bigint" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": true, + "concurrently": false, + "error_fields": [ + "id", + "tenant_id" + ], + "fields": [ + { + "type": "atom", + "value": "id" + }, + { + "type": "atom", + "value": "tenant_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": "3B316A370DBDCA78FC0043E47927853D79CDD83B1E894170E25B9496B218C3EB", + "identities": [], + "multitenancy": { + "attribute": "tenant_id", + "global": false, + "strategy": "attribute" + }, + "repo": "Elixir.Edgehog.Repo", + "schema": null, + "table": "update_campaigns" +} \ No newline at end of file