WordPress.org

Make WordPress Core

Ticket #21212: 21212-utf8mb4.7.diff

File 21212-utf8mb4.7.diff, 11.4 KB (added by pento, 5 years ago)
  • src/wp-admin/includes/schema.php

     
    5151 slug varchar(200) NOT NULL default '',
    5252 term_group bigint(10) NOT NULL default 0,
    5353 PRIMARY KEY  (term_id),
    54  KEY slug (slug),
    55  KEY name (name)
     54 KEY slug (slug(191)),
     55 KEY name (name(191))
    5656) $charset_collate;
    5757CREATE TABLE $wpdb->term_taxonomy (
    5858 term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment,
     
    7979  meta_value longtext,
    8080  PRIMARY KEY  (meta_id),
    8181  KEY comment_id (comment_id),
    82   KEY meta_key (meta_key)
     82  KEY meta_key (meta_key(191))
    8383) $charset_collate;
    8484CREATE TABLE $wpdb->comments (
    8585  comment_ID bigint(20) unsigned NOT NULL auto_increment,
     
    136136  meta_value longtext,
    137137  PRIMARY KEY  (meta_id),
    138138  KEY post_id (post_id),
    139   KEY meta_key (meta_key)
     139  KEY meta_key (meta_key(191))
    140140) $charset_collate;
    141141CREATE TABLE $wpdb->posts (
    142142  ID bigint(20) unsigned NOT NULL auto_increment,
     
    163163  post_mime_type varchar(100) NOT NULL default '',
    164164  comment_count bigint(20) NOT NULL default '0',
    165165  PRIMARY KEY  (ID),
    166   KEY post_name (post_name),
     166  KEY post_name (post_name(191)),
    167167  KEY type_status_date (post_type,post_status,post_date,ID),
    168168  KEY post_parent (post_parent),
    169169  KEY post_author (post_author)
     
    213213  meta_value longtext,
    214214  PRIMARY KEY  (umeta_id),
    215215  KEY user_id (user_id),
    216   KEY meta_key (meta_key)
     216  KEY meta_key (meta_key(191))
    217217) $charset_collate;\n";
    218218
    219219        // Global tables
     
    261261  domain varchar(200) NOT NULL default '',
    262262  path varchar(100) NOT NULL default '',
    263263  PRIMARY KEY  (id),
    264   KEY domain (domain,path)
     264  KEY domain (domain(140),path(51))
    265265) $charset_collate;
    266266CREATE TABLE $wpdb->sitemeta (
    267267  meta_id bigint(20) NOT NULL auto_increment,
     
    269269  meta_key varchar(255) default NULL,
    270270  meta_value longtext,
    271271  PRIMARY KEY  (meta_id),
    272   KEY meta_key (meta_key),
     272  KEY meta_key (meta_key(191)),
    273273  KEY site_id (site_id)
    274274) $charset_collate;
    275275CREATE TABLE $wpdb->signups (
     
    288288  KEY activation_key (activation_key),
    289289  KEY user_email (user_email),
    290290  KEY user_login_email (user_login,user_email),
    291   KEY domain_path (domain,path)
     291  KEY domain_path (domain(140),path(51))
    292292) $charset_collate;";
    293293
    294294        switch ( $scope ) {
  • src/wp-admin/includes/upgrade.php

     
    519519        if ( $wp_current_db_version < 29630 )
    520520                upgrade_400();
    521521
     522        if ( $wp_current_db_version < 30134 )
     523                upgrade_420();
     524
    522525        maybe_disable_link_manager();
    523526
    524527        maybe_disable_automattic_widgets();
     
    14071410}
    14081411
    14091412/**
     1413 * Execute changes made in WordPress 4.2.0.
     1414 *
     1415 * @since 4.2.0
     1416 */
     1417function upgrade_420() {
     1418        global $wp_current_db_version, $wpdb;
     1419
     1420        if ( $wp_current_db_version < 30134 && $wpdb->charset === 'utf8mb4' ) {
     1421                if ( is_multisite() ) {
     1422                        $tables = $wpdb->tables;
     1423                } else {
     1424                        $tables = array_merge( $wpdb->tables, $wpdb->global_tables );
     1425                }
     1426
     1427                foreach ( $tables as $table ) {
     1428                        $results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `{$wpdb->$table}`" );
     1429                        if ( ! $results ) {
     1430                                continue;
     1431                        }
     1432
     1433                        $has_utf8 = false;
     1434                        foreach ( $results as $column ) {
     1435                                if ( $column->Collation ) {
     1436                                        if ( 'utf8' === $column->Collation ) {
     1437                                                $has_utf8 = true;
     1438                                        } else {
     1439                                                // Don't upgrade tables that have non-utf8 columns
     1440                                                continue 2;
     1441                                        }
     1442                                }
     1443                        }
     1444
     1445                        if ( ! $has_utf8 ) {
     1446                                // Don't bother upgrading tables that don't have utf8 columns
     1447                                continue;
     1448                        }
     1449
     1450                        $wpdb->query( "ALTER TABLE {$wpdb->$table} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" );
     1451                }
     1452        }
     1453}
     1454
     1455/**
    14101456 * Executes network-level upgrade routines.
    14111457 *
    14121458 * @since 3.0.0
     
    15021548                        update_site_option( 'illegal_names', $illegal_names );
    15031549                }
    15041550        }
     1551
     1552        // 4.2
     1553        if ( $wp_current_db_version < 30134 && $wpdb->charset === 'utf8mb4') {
     1554                $wpdb->query( "ALTER TABLE $wpdb->site DROP INDEX domain, ADD INDEX domain(domain(140),path(51))" );
     1555                $wpdb->query( "ALTER TABLE $wpdb->sitemeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
     1556                $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain, ADD INDEX domain(domain(140),path(51))" );
     1557
     1558                $tables = array_merge( $wpdb->ms_global_tables, $wpdb->global_tables );
     1559
     1560                foreach ( $tables as $table ) {
     1561                        $results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `{$wpdb->$table}`" );
     1562                        if ( ! $results ) {
     1563                                continue;
     1564                        }
     1565
     1566                        $has_utf8 = false;
     1567                        foreach ( $results as $column ) {
     1568                                if ( $column->Collation ) {
     1569                                        if ( 'utf8' === $column->Collation ) {
     1570                                                $has_utf8 = true;
     1571                                        } else {
     1572                                                // Don't upgrade tables that have non-utf8 columns
     1573                                                continue 2;
     1574                                        }
     1575                                }
     1576                        }
     1577
     1578                        if ( ! $has_utf8 ) {
     1579                                // Don't bother upgrading tables that don't have utf8 columns
     1580                                continue;
     1581                        }
     1582
     1583                        $wpdb->query( "ALTER TABLE {$wpdb->$table} CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" );
     1584                }
     1585        }
    15051586}
    15061587
    15071588//
     
    22842365                // dbDelta() can recreate but can't drop the index.
    22852366                $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX slug" );
    22862367        }
     2368
     2369        if ( $wp_current_db_version < 30134 ) {
     2370                // We need to alter some indices
     2371                $wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
     2372                $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX slug, ADD INDEX slug(slug(191))" );
     2373                $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX name, ADD INDEX name(name(191))" );
     2374                $wpdb->query( "ALTER TABLE $wpdb->commentmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
     2375                $wpdb->query( "ALTER TABLE $wpdb->postmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
     2376                $wpdb->query( "ALTER TABLE $wpdb->posts DROP INDEX post_name, ADD INDEX post_name(post_name(191))" );
     2377        }
    22872378}
    22882379
    22892380/**
  • src/wp-admin/setup-config.php

     
    280280                        case 'DB_HOST'     :
    281281                                $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n";
    282282                                break;
     283                        case 'DB_CHARSET'  :
     284                                if ( 'utf8mb4' === $wpdb->charset || ( ! $wpdb->charset && $wpdb->has_cap( 'utf8mb4' ) ) ) {
     285                                        $config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'utf8mb4');\r\n";
     286                                }
     287                                break;
    283288                        case 'AUTH_KEY'         :
    284289                        case 'SECURE_AUTH_KEY'  :
    285290                        case 'LOGGED_IN_KEY'    :
  • src/wp-includes/version.php

     
    1111 *
    1212 * @global int $wp_db_version
    1313 */
    14 $wp_db_version = 30133;
     14$wp_db_version = 30134;
    1515
    1616/**
    1717 * Holds the TinyMCE version
  • src/wp-includes/wp-db.php

     
    624624                        }
    625625                }
    626626
    627                 $this->init_charset();
    628 
    629627                $this->dbuser = $dbuser;
    630628                $this->dbpassword = $dbpassword;
    631629                $this->dbname = $dbname;
     
    717715        public function init_charset() {
    718716                if ( function_exists('is_multisite') && is_multisite() ) {
    719717                        $this->charset = 'utf8';
    720                         if ( defined( 'DB_COLLATE' ) && DB_COLLATE )
     718                        if ( defined( 'DB_COLLATE' ) && DB_COLLATE ) {
    721719                                $this->collate = DB_COLLATE;
    722                         else
     720                        } else {
    723721                                $this->collate = 'utf8_general_ci';
     722                        }
    724723                } elseif ( defined( 'DB_COLLATE' ) ) {
    725724                        $this->collate = DB_COLLATE;
    726725                }
    727726
    728                 if ( defined( 'DB_CHARSET' ) )
     727                if ( defined( 'DB_CHARSET' ) ) {
    729728                        $this->charset = DB_CHARSET;
     729                }
     730
     731                if ( ( $this->use_mysqli && ! ( $this->dbh instanceof mysqli ) )
     732                  || ( empty( $this->dbh ) || ! ( $this->dbh instanceof mysqli ) ) ) {
     733                        return;
     734                }
     735
     736                if ( 'utf8' === $this->charset && $this->has_cap( 'utf8mb4' ) ) {
     737                        $this->charset = 'utf8mb4';
     738                }
     739
     740                if ( 'utf8mb4' === $this->charset && ( ! $this->collate || stripos( $this->collate, 'utf8_' ) === 0 ) ) {
     741                        $this->collate = 'utf8mb4_unicode_ci';
     742                }
    730743        }
    731744
    732745        /**
     
    14771490                        return false;
    14781491                } elseif ( $this->dbh ) {
    14791492                        $this->has_connected = true;
     1493
     1494                        $this->init_charset();
    14801495                        $this->set_charset( $this->dbh );
     1496
    14811497                        $this->ready = true;
    14821498                        $this->set_sql_mode();
    14831499                        $this->select( $this->dbname, $this->dbh );
     
    22492265         * Retrieves the character set for the given column.
    22502266         *
    22512267         * @since 4.2.0
    2252          * @access protected
     2268         * @access public
    22532269         *
    22542270         * @param string $table  Table name.
    22552271         * @param string $column Column name.
     
    22562272         * @return mixed Column character set as a string. False if the column has no
    22572273         *               character set. {@see WP_Error} object if there was an error.
    22582274         */
    2259         protected function get_col_charset( $table, $column ) {
     2275        public function get_col_charset( $table, $column ) {
    22602276                $tablekey = strtolower( $table );
    22612277                $columnkey = strtolower( $column );
    22622278
     
    23562372                        'gb2312'  => 'EUC-CN',
    23572373                        'ujis'    => 'EUC-JP',
    23582374                        'utf32'   => 'UTF-32',
    2359                         'utf8mb4' => 'UTF-8',
    23602375                );
    23612376
    23622377                $supported_charsets = array();
     
    23912406                                }
    23922407                        }
    23932408
    2394                         // utf8(mb3) can be handled by regex, which is a bunch faster than a DB lookup.
    2395                         if ( 'utf8' === $charset || 'utf8mb3' === $charset ) {
     2409                        // utf8 can be handled by regex, which is a bunch faster than a DB lookup.
     2410                        if ( 'utf8' === $charset || 'utf8mb3' === $charset || 'utf8mb4' === $charset ) {
    23962411                                $regex = '/
    23972412                                        (
    23982413                                                (?: [\x00-\x7F]                  # single-byte sequences   0xxxxxxx
     
    24002415                                                |   \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
    24012416                                                |   [\xE1-\xEC][\x80-\xBF]{2}
    24022417                                                |   \xED[\x80-\x9F][\x80-\xBF]
    2403                                                 |   [\xEE-\xEF][\x80-\xBF]{2}
    2404                                                 ){1,50}                          # ...one or more times
     2418                                                |   [\xEE-\xEF][\x80-\xBF]{2}';
     2419
     2420                                if ( 'utf8mb4' === $charset) {
     2421                                        $regex .= '
     2422                                                |    \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
     2423                                                |    [\xF1-\xF3][\x80-\xBF]{3}
     2424                                                |    \xF4[\x80-\x8F][\x80-\xBF]{2}
     2425                                        ';
     2426                                }
     2427
     2428                                $regex .= '){1,50}                          # ...one or more times
    24052429                                        )
    24062430                                        | .                                  # anything else
    24072431                                        /x';
  • tests/phpunit/tests/db/charset.php

     
    130130        }
    131131
    132132        /**
    133          * @ ticket 21212
     133         * @ticket 21212
    134134         */
    135135        function test_process_fields_failure() {
    136136                global $wpdb;
    137                 $data = array( 'post_content' => "H€llo\xf0\x9f\x98\x88World¢" );
     137                // \xf0\xff\xff\xff is invalid in utf8 and utf8mb4
     138                $data = array( 'post_content' => "H€llo\xf0\xff\xff\xffWorld¢" );
    138139                $this->assertFalse( self::$_wpdb->process_fields( $wpdb->posts, $data, null ) );
    139140        }
    140141
     
    436437         */
    437438        function test_invalid_characters_in_query() {
    438439                global $wpdb;
    439                 $this->assertFalse( $wpdb->query( "INSERT INTO {$wpdb->posts} (post_content) VALUES ('foo\xf0\x9f\x98\x88bar')" ) );
     440                $this->assertFalse( $wpdb->query( "INSERT INTO {$wpdb->posts} (post_content) VALUES ('foo\xf0\xff\xff\xffbar')" ) );
    440441        }
    441442}