[wp-trac] [WordPress Trac] #40357: dbDelta can't change primary keys, create AUTO_INCREMENT columns and doesn't make significant index changes
WordPress Trac
noreply at wordpress.org
Tue Apr 4 17:20:07 UTC 2017
#40357: dbDelta can't change primary keys, create AUTO_INCREMENT columns and
doesn't make significant index changes
-------------------------+-----------------------------
Reporter: stuporglue | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Database | Version: trunk
Severity: normal | Keywords:
Focuses: |
-------------------------+-----------------------------
dbDelta has three inter-related issues which center around changing
indexes.
1) It isn't possible to change which column is the primary key
2) It isn't possible to add a new AUTO_INCREMENT column
2b) It isn't possible to modify an existing AUTO_INCREMENT to no longer be
AUTO_INCREMENT
3) Indices with the same name are not dropped/re-created, even when the
index definition is changed significantly.
== Use case ==
A client had been tracking inventory in a custom table where the product
ID was the primary key. When he opened a new location, we added a location
column, and wanted to be able to track how many of each product was in
each location.
1. A table's purpose is being expanded, or otherwise doesn't meet the
needs of the data.
Since the primary key is unique, we needed to add a new key column and
change which column was designated as the primary key.
2. A table was originally defined without an AUTO_INCREMENT column and the
need for such a column arises.
The new column we wanted to add and use for the key was simply an
AUTO_INCREMENT integer column. In testing we defined the new column and
also defined a new UNIQUE index (so, not changing the primary key yet).
Since dbDelta adds new columns before adding the new indices, and in
separate ALTER TABLE statements, MySQL refuses to add a new AUTO_INCREMENT
column without an index.
The solution is to add the new column without the AUTO_INCREMENT
designation, then add the UNIQUE index, then alter the table to use
AUTO_INCREMENT.
3. A primary (or other key) could be significantly and intentionally
altered, significantly changing how queries are run.
I understand that WP doesn't want to drop and recreate indices when
changing the sub-part of an index (see:
https://core.trac.wordpress.org/ticket/34870#comment:21)
However I think that it should change the index, if the definition is
significantly altered.
In the use case above, we could've changed the primary key to be `PRIMARY
KEY(productId,location)` instead of adding a new column and switching the
index to that column.
In other use cases, changing from a BTREE to FULLTEXT index would change
which types of queries need to a full table scan.
== This Patch ==
This patch does the following:
1. You can now add a new AUTO_INCREMENT column to an existing table
When a new AUTO_INCREMENT column is added to an existing table, the column
creation is done in two parts. First the column is created as a non-
AUTO_INCREMENT column, and a separate `ALTER TABLE` statement is set to
run after index creation to enable AUTO_INCREMENT.
Note: The CREATE TABLE statement given to dbDelta must provide the
required indexes that MySQL expects.
2. You can now modify a column with AUTO_INCREMENT to no longer use
AUTO_INCREMENT
3. You can change which column is the primary key
4. Significant index definitions cause an index to be dropped and re-
created
The cases that cause an index to be dropped and re-created are:
* An index which wasn't UNIQUE, but now is or vice-versa
* An index which changes index type (eg. FULLTEXT => BTREE)
* An index which contains a different number of columns
* An index which contains a different column order
* An index which contains different columns
Note: Changing the index sub-part or no longer defining the index in the
table does not cause it to be dropped.
== Other notes ==
1. I've tried to use WP coding standards and comment my code well. I'd
love feedback if there are things I can do better.
2. I've included a file, test.php which takes 13 table definitions, takes
them two at a time, and converts between each possible combination.
To run it, put it in the root WordPress directory and run `php
./test.php`.
3. Also, the dbDelta phpunit tests still pass.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/40357>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list