Make WordPress Core

Changeset 39921


Ignore:
Timestamp:
01/17/2017 04:00:09 AM (7 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.