Backend: Add unique constraint on `catalog_resource_components` to prevent duplicate components
Problem
Currently, both a Simple and Complex component can exist with the same name for the given catalog resource version.
For example, I can have these in my templates directory:
-
my_component.yml
(Simple) -
my_component/template.yml
(Complex)
The above generates the same name
, path
, and resource_type
values for the given version_id
in the table catalog_resource_components
(aka the components metadata table).
For now, it's not much of a problem because our code always prioritizes the Simple component when fetching. This scenario is also very rare and has not yet occurred (afaik).
However, this will be a problem when we're trying to identify exactly which component record is being referenced, which is something we have to do as part of Backend: Component usage instrumentation (#440382 - closed). Later we may have more significant features that really depend on retrieving the correct component record.
(Ref: Slack thread)
Proposal
We should add a unique constraint on version_id
-resource_type
-name
so that we can uniquely identify a component in the catalog_resource_components
table. There should also be a corresponding validation reflected in the model.
Considerations:
The process to add a unique constraint on an existing table with data can be a bit tricky. We must follow a similar approach as outlined for adding a not-null constraint. Furthermore, there are several important factors that need to be taken into account when "fixing" existing duplicate records. Please see #450737 (comment 1910018989) for possible approaches.
Recommended: In addition to the above effort, we should add a more verbose validation error message to help the user debug their components. We could let them know that a file-based component and a directory-based component folder cannot have the same name (for a given version). See #450737 (comment 1909359039) for further details.