Problem/Motivation
With a PostgreSQL backend, when you rename a table all the indexes also get renamed. When the renamed index has the same name as the old table name, the table renaming will fail.
Proposed resolution
Fix the bug and add testing.
Remaining tasks
None
User interface changes
None
API changes
An API-addition for the method Drupal\Core\Database\Schema::tableExists(). A second parameter is added named: $add_prefix, which defaults to TRUE. When the new parameter is not set, the method works the same as before the second parameter was added. When the second parameter is set to FALSE, the existance of the table is checked without adding its table prefix.
Data model changes
None
Release notes snippet
An API-addition for the method Drupal\Core\Database\Schema::tableExists(). A second parameter is added named: $add_prefix, which defaults to TRUE. When the new parameter is not set, the method works the same as before the second parameter was added. When the second parameter is set to FALSE, the existance of the table is checked without adding its table prefix.
Original bug report
I was upgrading from Drupal 8.5.11 to 8.8.5 and I have got this error: [error] Exception thrown while performing a schema update. SQLSTATE[42P07]: Duplicate table: 7 ERROR: relation "old_81ee22taxonomy_term_field_data____name" already exists: ALTER INDEX "idx_30852_taxonomy_term_field__name" RENAME TO old_81ee22taxonomy_term_field_data____name; Array.
I have read many threads related to this error but none patch worked in my case. In the end, I got this fixed with the attached patch.
More Information:
- I have checked for any suspicious term inside the table "taxonomy_term_field_data". All looked fine. No term with status set to '0'. All terms are having the valid name and mapped to correct and existing vocabularies.
- Checked for existing tables with pattern "old_%", found none.
More on the solution/patch:
On digging more into the issue i have found that in the function renameTable() of my Schema.php of PGSQL Driver (/core/lib/Drupal/Core/Database/Driver/pgsql/Install). The index_name was being passed empty and this caused the duplicate index issue. Extra if check makes sure "$index_name" is not empty or null.
| Comment | File | Size | Author |
|---|
Issue fork drupal-3159113
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3159113-cannot-upgrade-from
changes, plain diff MR !5461
Comments
Comment #2
saxenaakansha30I faced the same issue on upgrading from 8.5.11 to 8.9.2. Attaching patch with similar fix.
Comment #3
cilefen commentedComment #4
daffie commentedCreated a fix for the bug including added tests.
To do that I also had to add an API-addition for the method
Drupal\Core\Database\Schema::tableExists(). I added a second parameter to the method$add_prefixwhich defaults to TRUE. Also added testing for that.Comment #6
daffie commentedFixing the failure for MySQL. Therefore added the internal method
Drupal\Core\Database\Connection::getQuoteIdentifiers().Comment #7
daffie commentedUpdated the IS.
Comment #8
daffie commentedAdded a CR.
Comment #9
daffie commentedUpdated the table names in the added test.
Comment #11
quietone commentedI have read the patch and this looks fine to me and the test shows it fixes the problem in the IS.
The patch still applies to 9.2.x.
My only comment is about readability. After applying the patch and reading the change in \Drupal\Core\Database\Driver\mysql\Schema::tableExists I found myself constantly checking the two queryRange statements to see the difference. So, I was thinking it help to modify that a bit.
Maybe modify this so that only the queryRange statement is inside the try. Something like
$this->connection->queryRange("SELECT 1 FROM $name", 0, 1);Comment #18
quietone commentedConverted to an MR and hide patches.
There is a failing test, Drupal\Tests\migrate_drupal\Unit\MigrationConfigurationTraitTest.
Comment #19
quietone commentedComment #20
smustgrave commentedSmall nitpicky stuff.
Comment #21
quietone commented@smustgrave, thanks. I should have done a self review and picked those up before setting to needs review.
I removed the method getQuoteIdentifiers which was in the patch but no longer used in the MR because there is no longer a tableExists method specific for mysql.
Known random failure on
Therefore setting back to Needs review.
Comment #22
daffie commentedMinor remark on the MR.
Could we run the pipeline for PostgreSQL for this MR?
Comment #23
quietone commented@daffie, thanks for the review.
I made the change requested and ran against MySQL, PostgreSQL and SQLite.
Unrelated failure in Drupal\Tests\field_ui\FunctionalJavascript\ManageFieldsTest
Comment #24
smustgrave commentedAppears all feedback has been addressed.
Comment #25
quietone commentedSimplify title a bit.
Comment #26
catchRe-titling again since this isn't really about updating from 8.5
Comment #28
larowlanCommitted to 11.x
Didn't backport to 10.2.x due to the risk of disruption from the signature change
Published change record
Thanks all
Comment #31
jurgenhaasThis is unfortunately a breaking change for Drupal 10.3, isn't it?
Comment #32
bradjones1Re: #31, no BC issue because the new parameter has a default value which preserves current behavior.
Comment #33
jurgenhaas@bradjones1 for those calling the method, that's OK. But there is e.g. the sqlsrv module which extends that method, see
\Drupal\sqlsrv\Driver\Database\sqlsrv\Schema::tableExistsand suddenly becomes incompatible.As the abstract class
\Drupal\Core\Database\Schemaisn't marked internal, it feels as if extending it is what's supposed to be done.