Make WordPress Core

Changeset 39921


Ignore:
Timestamp:
01/17/2017 04:00:09 AM (10 years ago)
Author:
pento
Message:

dbDelta: Ignore index subparts when checking for duplicate indices.

If index lengths change in table definitions, we don't recreate the index - instead, we throw a database error, as dbDelta() tries to create a new index with the same name.

It's better to leave the index as is, MySQL doesn't have an efficient process for resizing indices, and dropping/creating is a slow process which we don't want to trigger automatically.

Fixes #34870.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/upgrade.php

    r39754 r39921  
    22172217
    22182218                // Clear the field and index arrays.
    2219                 $cfields = $indices = array();
     2219                $cfields = $indices = $indices_without_subparts = array();
    22202220
    22212221                // Get all of the field names in the query from between the parentheses.
     
    22902290
    22912291                                        // Parse the columns. Multiple columns are separated by a comma.
    2292                                         $index_columns = array_map( 'trim', explode( ',', $index_matches['index_columns'] ) );
     2292                                        $index_columns = $index_columns_without_subparts = array_map( 'trim', explode( ',', $index_matches['index_columns'] ) );
    22932293
    22942294                                        // Normalize columns.
    2295                                         foreach ( $index_columns as &$index_column ) {
     2295                                        foreach ( $index_columns as $id => &$index_column ) {
    22962296                                                // Extract column name and number of indexed characters (sub_part).
    22972297                                                preg_match(
     
    23202320                                                $index_column = '`' . $index_column_matches['column_name'] . '`';
    23212321
     2322                                                // We don't need to add the subpart to $index_columns_without_subparts
     2323                                                $index_columns_without_subparts[ $id ] = $index_column;
     2324
    23222325                                                // Append the optional sup part with the number of indexed characters.
    23232326                                                if ( isset( $index_column_matches['sub_part'] ) ) {
     
    23282331                                        // Build the normalized index definition and add it to the list of indices.
    23292332                                        $indices[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns ) . ")";
     2333                                        $indices_without_subparts[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns_without_subparts ) . ")";
    23302334
    23312335                                        // Destroy no longer needed variables.
    2332                                         unset( $index_column, $index_column_matches, $index_matches, $index_type, $index_name, $index_columns );
     2336                                        unset( $index_column, $index_column_matches, $index_matches, $index_type, $index_name, $index_columns, $index_columns_without_subparts );
    23332337
    23342338                                        break;
     
    24472451                                        // Add the field to the column list string.
    24482452                                        $index_columns .= '`' . $column_data['fieldname'] . '`';
    2449                                         if ($column_data['subpart'] != '') {
    2450                                                 $index_columns .= '('.$column_data['subpart'].')';
    2451                                         }
    24522453                                }
    24532454
    2454                                 // The alternative index string doesn't care about subparts
    2455                                 $alt_index_columns = preg_replace( '/\([^)]*\)/', '', $index_columns );
    2456 
    24572455                                // Add the column list to the index create string.
    2458                                 $index_strings = array(
    2459                                         "$index_string ($index_columns)",
    2460                                         "$index_string ($alt_index_columns)",
    2461                                 );
    2462 
    2463                                 foreach ( $index_strings as $index_string ) {
    2464                                         if ( ! ( ( $aindex = array_search( $index_string, $indices ) ) === false ) ) {
    2465                                                 unset( $indices[ $aindex ] );
    2466                                                 break;
    2467                                         }
     2456                                $index_string .= " ($index_columns)";
     2457
     2458                                // Check if the index definition exists, ignoring subparts.
     2459                                if ( ! ( ( $aindex = array_search( $index_string, $indices_without_subparts ) ) === false ) ) {
     2460                                        // If the index already exists (even with different subparts), we don't need to create it.
     2461                                        unset( $indices_without_subparts[ $aindex ] );
     2462                                        unset( $indices[ $aindex ] );
    24682463                                }
    24692464                        }
  • trunk/tests/phpunit/tests/dbdelta.php

    r38591 r39921  
    827827
    828828        /**
     829         * @ticket 34870
     830         */
     831        function test_unchanged_key_lengths_do_not_recreate_index() {
     832                global $wpdb;
     833
     834                $updates = dbDelta(
     835                        "
     836                        CREATE TABLE {$wpdb->prefix}dbdelta_test (
     837                                id bigint(20) NOT NULL AUTO_INCREMENT,
     838                                column_1 varchar(255) NOT NULL,
     839                                column_2 text,
     840                                column_3 blob,
     841                                PRIMARY KEY  (id),
     842                                KEY key_1 (column_1(255)),
     843                                KEY compound_key (id,column_1),
     844                                FULLTEXT KEY fulltext_key (column_1)
     845                        ) ENGINE=MyISAM
     846                        ", false );
     847
     848                $this->assertEmpty( $updates );
     849        }
     850
     851        /**
     852         * @ticket 34870
     853         */
     854        function test_changed_key_lengths_do_not_recreate_index() {
     855                global $wpdb;
     856
     857                $updates = dbDelta(
     858                        "
     859                        CREATE TABLE {$wpdb->prefix}dbdelta_test (
     860                                id bigint(20) NOT NULL AUTO_INCREMENT,
     861                                column_1 varchar(255) NOT NULL,
     862                                column_2 text,
     863                                column_3 blob,
     864                                PRIMARY KEY  (id),
     865                                KEY key_1 (column_1),
     866                                KEY compound_key (id,column_1),
     867                                KEY changing_key_length (column_1(20)),
     868                                FULLTEXT KEY fulltext_key (column_1)
     869                        ) ENGINE=MyISAM
     870                        " );
     871
     872                $this->assertSame( array(
     873                        "Added index {$wpdb->prefix}dbdelta_test KEY `changing_key_length` (`column_1`(20))"
     874                ), $updates );
     875
     876                $updates = dbDelta(
     877                        "
     878                        CREATE TABLE {$wpdb->prefix}dbdelta_test (
     879                                id bigint(20) NOT NULL AUTO_INCREMENT,
     880                                column_1 varchar(255) NOT NULL,
     881                                column_2 text,
     882                                column_3 blob,
     883                                PRIMARY KEY  (id),
     884                                KEY key_1 (column_1),
     885                                KEY compound_key (id,column_1),
     886                                KEY changing_key_length (column_1(50)),
     887                                FULLTEXT KEY fulltext_key (column_1)
     888                        ) ENGINE=MyISAM
     889                        " );
     890
     891                $this->assertEmpty( $updates );
     892
     893                $updates = dbDelta(
     894                        "
     895                        CREATE TABLE {$wpdb->prefix}dbdelta_test (
     896                                id bigint(20) NOT NULL AUTO_INCREMENT,
     897                                column_1 varchar(255) NOT NULL,
     898                                column_2 text,
     899                                column_3 blob,
     900                                PRIMARY KEY  (id),
     901                                KEY key_1 (column_1),
     902                                KEY compound_key (id,column_1),
     903                                KEY changing_key_length (column_1(1)),
     904                                FULLTEXT KEY fulltext_key (column_1)
     905                        ) ENGINE=MyISAM
     906                        " );
     907
     908                $this->assertEmpty( $updates );
     909
     910                $updates = dbDelta(
     911                        "
     912                        CREATE TABLE {$wpdb->prefix}dbdelta_test (
     913                                id bigint(20) NOT NULL AUTO_INCREMENT,
     914                                column_1 varchar(255) NOT NULL,
     915                                column_2 text,
     916                                column_3 blob,
     917                                PRIMARY KEY  (id),
     918                                KEY key_1 (column_1),
     919                                KEY compound_key (id,column_1),
     920                                KEY changing_key_length (column_1),
     921                                FULLTEXT KEY fulltext_key (column_1)
     922                        ) ENGINE=MyISAM
     923                        " );
     924
     925                $this->assertEmpty( $updates );
     926        }
     927
     928        /**
    829929         * @ticket 31679
    830930         */
Note: See TracChangeset for help on using the changeset viewer.