Renaming a table containing "drupal_" in the name with multiple indexes fails on PostreSQL

Created on 17 December 2024, 4 months ago

Problem/Motivation

The function \Drupal\pgsql\Driver\Database\pgsql\Schema::renameTable contains the following code:

if (str_contains($index->indexname, 'drupal_')) {
    preg_match('/^drupal_(.*)_' . preg_quote($index_type, NULL) . '/', $index->indexname, $matches);
    $index_name = $matches[1];
}

The check whether an index is of the special "drupal_Gk7Su_T1jcBHVuvSPeP22_I3Ni4GrVEgTYlIYnBJkro_idx" format (due to character limit constraints) uses str_contains for "drupal_" while the regular expression inside the if block checks for "drupal_" to be at the start of the index name with /^drupal_….

This causes the $matches array to be empty and the next line to set the index_name to NULL.

This causes the complete generated index name to be empty at that position (quadruple underscore) and leads to index naming collisions with other index names in the same table.

In my case this ultimately leads to a the field authorization_drupal_roles_roles not being able to be deleted in the authorization_drupal_roles_8004 update hook, because there is an index for the bundle and the revision_id column.

---------------------------- ------------------------------- --------------- ----------------------------------------------------------------------------------
Module                       Update ID                       Type            Description
---------------------------- ------------------------------- --------------- ----------------------------------------------------------------------------------
authorization_drupal_roles   8004                            hook_update_n   8004 - Migrate roles from field 'authorization_drupal_roles_roles' to user data.
---------------------------- ------------------------------- --------------- ----------------------------------------------------------------------------------

Do you wish to run the specified pending updates? (yes/no) [yes]:
>
[notice] Update started: authorization_drupal_roles_update_8004
[warning] Undefined array key 1 Schema.php:580
[warning] Undefined array key 1 Schema.php:580
[warning] Undefined array key 1 Schema.php:580
[error]  Exception thrown while performing a schema update. SQLSTATE[42P07]: Duplicate table: 7 ERROR:  relation "field_deleted_data_21874036cb____idx" already exists: ALTER INDEX "user__authorization_drupal_roles_roles__revision_id__idx" RENAME TO field_deleted_data_21874036cb____idx; Array()
[error]  Update failed: authorization_drupal_roles_update_8004
[error]  Update aborted by: authorization_drupal_roles_update_8004
[error]  Finished performing updates.

Steps to reproduce

  • install and configure a drupal site to use PostreSQL and Authorization β†’ 1.3
  • update Authorization to 1.4 or higher
  • try to update the database

Proposed resolution

Use str_starts_with instead of str_contains.

Remaining tasks

  • implement proposed resolution

User interface changes

There are no user interface changes.

Introduced terminology

There is no introduced terminology.

API changes

There are no API changes.

Data model changes

There are no data model changes.

Release notes snippet

Previously, a table which name contains "drupal_" and which has multiple indexes could not be renamed when using PostgreSQL. This is now resolved.

πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component

postgresql db driver

Created by

πŸ‡©πŸ‡ͺGermany tgauges

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Production build 0.71.5 2024