Make WordPress Core

Changeset 37583

Timestamp:
05/27/2016 11:56:20 AM (8 years ago)
Author:
ocean90
Message:

Database: Normalize index definitions in dbDelta().

dbDelta() compares the index definitions against the result of SHOW INDEX FROM $table_name. This requires a specific format so indices are not unnecessarily re-created. This format wasn't ensured, until now.

  • Parse the raw index definition to extract the type, name and columns so a normalized definition can be built (#20263, #34873).
  • Standardize on uppercase types (#34871) and on 'KEY'. 'INDEX' is only a synonym for 'KEY'.
  • Escape index names with backticks (#20263).
  • Normalize columns: Ignore ASC and DESC definitions (#34959), remove whitespaces (#34869) and escape column names with backticks (#20263).
  • Add backticks to all index change queries (#20263).

Props ocean90, pento, kurtpayne.
Fixes #20263, #34869, #34871, #34873, #34959.

Location:
trunk
Files:
2 edited

Legend:

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

    r37574 r37583  
    21852185
    21862186        // For every field line specified in the query.
    2187         foreach ($flds as $fld) {
     2187        foreach ( $flds as $fld ) {
     2188            $fld = trim( $fld, " \t\n\r\0\x0B," ); // Default trim characters, plus ','.
    21882189
    21892190            // Extract the field name.
    2190             preg_match("|^([^ ]*)|", trim($fld), $fvals);
     2191            preg_match();
    21912192            $fieldname = trim( $fvals[1], '`' );
    21922193            $fieldname_lowercased = strtolower( $fieldname );
     
    22032204                case 'spatial':
    22042205                    $validfield = false;
    2205                     $indices[] = trim(trim($fld), ", \n");
     2206
     2207                    /*
     2208                     * Normalize the index definition.
     2209                     *
     2210                     * This is done so the definition can be compared against the result of a
     2211                     * `SHOW INDEX FROM $table_name` query which returns the current table
     2212                     * index information.
     2213                     */
     2214
     2215                    // Extract type, name and columns from the definition.
     2216                    preg_match(
     2217                          '/^'
     2218                        .   '(?P<index_type>'             // 1) Type of the index.
     2219                        .       'PRIMARY\s+KEY|(?:UNIQUE|FULLTEXT|SPATIAL)\s+(?:KEY|INDEX)|KEY|INDEX'
     2220                        .   ')'
     2221                        .   '\s+'                         // Followed by at least one white space character.
     2222                        .   '(?:'                         // Name of the index. Optional if type is PRIMARY KEY.
     2223                        .       '`?'                      // Name can be escaped with a backtick.
     2224                        .           '(?P<index_name>'     // 2) Name of the index.
     2225                        .               '(?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+'
     2226                        .           ')'
     2227                        .       '`?'                      // Name can be escaped with a backtick.
     2228                        .       '\s+'                     // Followed by at least one white space character.
     2229                        .   ')*'
     2230                        .   '\('                          // Opening bracket for the columns.
     2231                        .       '(?P<index_columns>'
     2232                        .           '.+?'                 // 3) Column names, index prefixes, and orders.
     2233                        .       ')'
     2234                        .   '\)'                          // Closing bracket for the columns.
     2235                        . '$/im',
     2236                        $fld,
     2237                        $index_matches
     2238                    );
     2239
     2240                    // Uppercase the index type and normalize space characters.
     2241                    $index_type = strtoupper( preg_replace( '/\s+/', ' ', trim( $index_matches['index_type'] ) ) );
     2242
     2243                    // 'INDEX' is a synonym for 'KEY', standardize on 'KEY'.
     2244                    $index_type = str_replace( 'INDEX', 'KEY', $index_type );
     2245
     2246                    // Escape the index name with backticks. An index for a primary key has no name.
     2247                    $index_name = ( 'PRIMARY KEY' === $index_type ) ? '' : '`' . $index_matches['index_name'] . '`';
     2248
     2249                    // Parse the columns. Multiple columns are separated by a comma.
     2250                    $index_columns = array_map( 'trim', explode( ',', $index_matches['index_columns'] ) );
     2251
     2252                    // Normalize columns.
     2253                    foreach ( $index_columns as &$index_column ) {
     2254                        // Extract column name and number of indexed characters (sub_part).
     2255                        preg_match(
     2256                              '/'
     2257                            .   '`?'                      // Name can be escaped with a backtick.
     2258                            .       '(?P<column_name>'    // 1) Name of the column.
     2259                            .           '(?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+'
     2260                            .       ')'
     2261                            .   '`?'                      // Name can be escaped with a backtick.
     2262                            .   '(?:'                     // Optional sub part.
     2263                            .       '\s*'                 // Optional white space character between name and opening bracket.
     2264                            .       '\('                  // Opening bracket for the sub part.
     2265                            .           '\s*'             // Optional white space character after opening bracket.
     2266                            .           '(?P<sub_part>'
     2267                            .               '\d+'         // 2) Number of indexed characters.
     2268                            .           ')'
     2269                            .           '\s*'             // Optional white space character before closing bracket.
     2270                            .        '\)'                 // Closing bracket for the sub part.
     2271                            .   ')?'
     2272                            . '/',
     2273                            $index_column,
     2274                            $index_column_matches
     2275                        );
     2276
     2277                        // Escape the column name with backticks.
     2278                        $index_column = '`' . $index_column_matches['column_name'] . '`';
     2279
     2280                        // Append the optional sup part with the number of indexed characters.
     2281                        if ( isset( $index_column_matches['sub_part'] ) ) {
     2282                            $index_column .= '(' . $index_column_matches['sub_part'] . ')';
     2283                        }
     2284                    }
     2285
     2286                    // Build the normalized index definition and add it to the list of indices.
     2287                    $indices[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns ) . ")";
     2288
     2289                    // Destroy no longer needed variables.
     2290                    unset( $index_column, $index_column_matches, $index_matches, $index_type, $index_name, $index_columns );
     2291
    22062292                    break;
    22072293            }
    2208             $fld = trim( $fld );
    22092294
    22102295            // If it's a valid field, add it to the field array.
    22112296            if ( $validfield ) {
    2212                 $cfields[ $fieldname_lowercased ] = trim( $fld, ", \n" );
     2297                $cfields[ $fieldname_lowercased ] = ;
    22132298            }
    22142299        }
     
    22442329                    if ( $do_change ) {
    22452330                        // Add a query to change the column type.
    2246                         $cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN {$tablefield->Field} " . $cfields[ $tablefield_field_lowercased ];
     2331                        $cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN " . $cfields[ $tablefield_field_lowercased ];
    22472332                        $for_update[$table.'.'.$tablefield->Field] = "Changed type of {$table}.{$tablefield->Field} from {$tablefield->Type} to {$fieldtype}";
    22482333                    }
     
    22542339                    if ($tablefield->Default != $default_value) {
    22552340                        // Add a query to change the column's default value
    2256                         $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN {$tablefield->Field} SET DEFAULT '{$default_value}'";
     2341                        $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN SET DEFAULT '{$default_value}'";
    22572342                        $for_update[$table.'.'.$tablefield->Field] = "Changed default value of {$table}.{$tablefield->Field} from {$tablefield->Default} to {$default_value}";
    22582343                    }
     
    23072392                }
    23082393                $index_string .= 'KEY ';
    2309                 if ($index_name != 'PRIMARY') {
    2310                     $index_string .= $index_name;
     2394                if () {
     2395                    $index_string .= ;
    23112396                }
    23122397                $index_columns = '';
     
    23142399                // For each column in the index.
    23152400                foreach ($index_data['columns'] as $column_data) {
    2316                     if ($index_columns != '') $index_columns .= ',';
     2401                    if ( $index_columns != '' ) {
     2402                        $index_columns .= ',';
     2403                    }
    23172404
    23182405                    // Add the field to the column list string.
    2319                     $index_columns .= $column_data['fieldname'];
     2406                    $index_columns .= ;
    23202407                    if ($column_data['subpart'] != '') {
    23212408                        $index_columns .= '('.$column_data['subpart'].')';
  • trunk/tests/phpunit/tests/dbdelta.php

    r37574 r37583  
    532532        $this->assertSame( array(
    533533            "{$wpdb->prefix}spatial_index_test.spatial_value2" => "Added column {$wpdb->prefix}spatial_index_test.spatial_value2",
    534             "Added index {$wpdb->prefix}spatial_index_test SPATIAL KEY spatial_key2 (spatial_value2)"
     534            "Added index {$wpdb->prefix}spatial_index_test SPATIAL KEY )"
    535535            ), $updates );
    536536
    537537        $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}spatial_index_test" );
    538538    }
     539
     540
     541
     542
     543
     544
     545
     546
     547
     548
     549
     550
     551
     552
     553
     554
     555
     556
     557
     558
     559
     560
     561
     562
     563
     564
     565
     566
     567
     568
     569
     570
     571
     572
     573
     574
     575
     576
     577
     578
     579
     580
     581
     582
     583
     584
     585
     586
     587
     588
     589
     590
     591
     592
     593
     594
     595
     596
     597
     598
     599
     600
     601
     602
     603
     604
     605
     606
     607
     608
     609
     610
     611
     612
     613
     614
     615
     616
     617
     618
     619
     620
     621
     622
     623
     624
     625
     626
     627
     628
     629
     630
     631
     632
     633
     634
     635
     636
     637
     638
     639
     640
     641
     642
     643
     644
     645
     646
     647
     648
     649
     650
     651
     652
     653
     654
     655
     656
     657
     658
     659
     660
     661
     662
     663
     664
     665
     666
     667
     668
     669
     670
     671
     672
     673
     674
     675
     676
     677
     678
     679
     680
     681
     682
     683
     684
     685
     686
     687
     688
     689
     690
     691
     692
     693
     694
     695
     696
     697
     698
     699
     700
     701
     702
     703
     704
     705
     706
     707
     708
     709
     710
     711
     712
     713
     714
     715
     716
     717
     718
     719
     720
     721
     722
     723
     724
     725
     726
     727
     728
     729
     730
     731
     732
     733
     734
     735
     736
     737
     738
     739
     740
     741
     742
     743
     744
     745
     746
     747
     748
     749
     750
     751
     752
     753
     754
     755
     756
     757
     758
     759
     760
     761
     762
     763
     764
     765
     766
     767
     768
     769
     770
     771
     772
     773
     774
     775
     776
     777
     778
     779
     780
     781
     782
     783
     784
     785
     786
     787
     788
     789
     790
     791
     792
     793
     794
     795
     796
     797
     798
     799
     800
     801
     802
     803
    539804}
Note: See TracChangeset for help on using the changeset viewer.