Skip to content

feat(migration): create unique index on folders for parent_uuid and plain_name#882

Open
jzunigax2 wants to merge 1 commit intomasterfrom
chore/new-unique-index-on-folderuuid-and-plainName
Open

feat(migration): create unique index on folders for parent_uuid and plain_name#882
jzunigax2 wants to merge 1 commit intomasterfrom
chore/new-unique-index-on-folderuuid-and-plainName

Conversation

@jzunigax2
Copy link
Contributor

What

Create a new unique index folders_parentuuid_plainname_unique on the folders table using (parent_uuid,
plain_name) to replace the legacy folders_plainname_parentid_key index.

Why

1. Legacy index uses deprecated column

The current unique index folders_plainname_parentid_key uses parent_id (integer FK), while we have kept
migrating towards using parent_uuid (UUID FK) for all folder relationship operations.

-- Current (legacy)
CREATE UNIQUE INDEX folders_plainname_parentid_key
ON folders (plain_name, parent_id)
WHERE deleted = false;

-- New (aligned with application code)
CREATE UNIQUE INDEX folders_parentuuid_plainname_unique
ON folders (parent_uuid, plain_name)
WHERE deleted = false;

2. Suboptimal column order causing inefficient uniqueness checks

The legacy index has plain_name as the first column, which has low cardinality. This forces the db to possibly scan through entries before narrowing by parent.

The new index places parent_uuid first (high cardinality).

3. Application code already uses parent_uuid:

  // folder.repository.ts:397-414
  async findByNameAndParentUuid(
    name: FolderAttributes['name'],
    plainName: FolderAttributes['plainName'],
    parentUuid: FolderAttributes['parentUuid'],  // Uses UUID, not ID
    deleted: FolderAttributes['deleted'],
  ): Promise<Folder> {
    const folder = await this.folderModel.findOne({
      where: {
        [Op.or]: [{ name }, { plainName }],
        parentUuid: { [Op.eq]: parentUuid },
        deleted: { [Op.eq]: deleted },
      },
    });
    return folder ? this.toDomain(folder) : null;
  }

How

Migration uses CREATE INDEX CONCURRENTLY to avoid table locks:

  CREATE UNIQUE INDEX CONCURRENTLY folders_parentuuid_plainname_unique
  ON folders (parent_uuid, plain_name)
  WHERE deleted = false AND removed = false;

sg-gs
sg-gs previously approved these changes Jan 20, 2026
Copy link
Member

@sg-gs sg-gs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running migration @jzunigax2

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

This PR is stale because it has been open for more than 15 days with no activity.

@jzunigax2 jzunigax2 force-pushed the chore/new-unique-index-on-folderuuid-and-plainName branch from 6c4180d to e85fbd6 Compare February 5, 2026 02:22
@sg-gs
Copy link
Member

sg-gs commented Feb 5, 2026

This PR has conflicts with master @jzunigax2, let's reconcile it (waiting this before #883)

@jzunigax2 jzunigax2 force-pushed the chore/new-unique-index-on-folderuuid-and-plainName branch from e85fbd6 to 20491aa Compare February 5, 2026 13:01
@jzunigax2 jzunigax2 requested a review from sg-gs February 5, 2026 13:02
@github-actions github-actions bot removed the stalled label Feb 6, 2026
@github-actions
Copy link

This PR is stale because it has been open for more than 15 days with no activity.

@jzunigax2 jzunigax2 force-pushed the chore/new-unique-index-on-folderuuid-and-plainName branch from 20491aa to fe9b26f Compare February 25, 2026 02:43
@jzunigax2 jzunigax2 requested a review from apsantiso as a code owner February 25, 2026 02:43
@jzunigax2 jzunigax2 force-pushed the chore/new-unique-index-on-folderuuid-and-plainName branch from fe9b26f to 865c602 Compare February 25, 2026 13:05
sg-gs
sg-gs previously approved these changes Feb 25, 2026
Copy link
Member

@sg-gs sg-gs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running migration

@github-actions github-actions bot removed the stalled label Feb 26, 2026
@jzunigax2 jzunigax2 force-pushed the chore/new-unique-index-on-folderuuid-and-plainName branch from 865c602 to 65bfe8d Compare March 3, 2026 04:11
@jzunigax2 jzunigax2 requested a review from sg-gs March 3, 2026 04:18
await queryInterface.sequelize.query(`
CREATE UNIQUE INDEX CONCURRENTLY folders_parentuuid_plainname_unique
ON folders (parent_uuid, plain_name)
WHERE deleted = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index should include and removed = false also. Otherwise, permanently removed folders inside the a parent could prevent the same folder (=same name) creation inside. This could seem tricky but this could be a common case on a desktop sync if a rename happens, for instance.

Copy link
Contributor Author

@jzunigax2 jzunigax2 Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm it does seem tricky, this was meant to replace this other index which also only has a where deleted = false

by adding removed = false to the where wouldn't that prevent creaing a new folder with the same name as a trashed but not deleted one in the same parent? or am I missing something?

@apsantiso apsantiso added the migration-required A migration is included in the PR label Mar 4, 2026
… and create unique index on parent_uuid and plain_name
@jzunigax2 jzunigax2 force-pushed the chore/new-unique-index-on-folderuuid-and-plainName branch from 65bfe8d to 7b062dd Compare March 4, 2026 15:41
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 4, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request migration-required A migration is included in the PR ready-for-preview

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants