Make WordPress Core

Changeset 32162


Ignore:
Timestamp:
04/20/2015 04:45:12 AM (9 years ago)
Author:
pento
Message:

WPDB: When sanity checking read queries, there are some collations we can skip, for improved performance.

Props pento, nacin.

See #21212.

Location:
trunk
Files:
2 edited

Legend:

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

    r32116 r32162  
    170170     */
    171171    protected $check_current_query = true;
     172
     173    /**
     174     * Flag to ensure we don't run into recursion problems when checking the collation.
     175     *
     176     * @since 4.2.0
     177     * @access private
     178     * @see wpdb::check_safe_collation()
     179     * @var boolean
     180     */
     181    private $checking_collation = false;
    172182
    173183    /**
     
    20392049        $this->func_call = "\$db->get_var(\"$query\", $x, $y)";
    20402050
     2051        if ( $this->check_safe_collation( $query ) ) {
     2052            $this->check_current_query = false;
     2053        }
     2054
    20412055        if ( $query ) {
    20422056            $this->query( $query );
     
    20672081    public function get_row( $query = null, $output = OBJECT, $y = 0 ) {
    20682082        $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
     2083
     2084        if ( $this->check_safe_collation( $query ) ) {
     2085            $this->check_current_query = false;
     2086        }
     2087
    20692088        if ( $query ) {
    20702089            $this->query( $query );
     
    21042123     */
    21052124    public function get_col( $query = null , $x = 0 ) {
     2125        if ( $this->check_safe_collation( $query ) ) {
     2126            $this->check_current_query = false;
     2127        }
     2128
    21062129        if ( $query ) {
    21072130            $this->query( $query );
     
    21312154    public function get_results( $query = null, $output = OBJECT ) {
    21322155        $this->func_call = "\$db->get_results(\"$query\", $output)";
     2156
     2157        if ( $this->check_safe_collation( $query ) ) {
     2158            $this->check_current_query = false;
     2159        }
    21332160
    21342161        if ( $query ) {
     
    23602387
    23612388    /**
     2389     * Check if the query is accessing a collation considered safe on the current version of MySQL.
     2390     *
     2391     * @since 4.2.0
     2392     * @access protected
     2393     *
     2394     * @param string $query The query to check.
     2395     * @return bool True if the collation is safe, false if it isn't.
     2396     */
     2397    protected function check_safe_collation( $query ) {
     2398        if ( $this->checking_collation ) {
     2399            return true;
     2400        }
     2401
     2402        $table = $this->get_table_from_query( $query );
     2403        if ( ! $table ) {
     2404            return false;
     2405        }
     2406
     2407        $this->checking_collation = true;
     2408        $this->get_table_charset( $table );
     2409        $this->checking_collation = false;
     2410
     2411        $table = strtolower( $table );
     2412        if ( empty( $this->col_meta[ $table ] ) ) {
     2413            return false;
     2414        }
     2415
     2416        foreach( $this->col_meta[ $table ] as $col ) {
     2417            if ( empty( $col->Collation ) ) {
     2418                continue;
     2419            }
     2420
     2421            if ( ! in_array( $col->Collation, array( 'utf8_general_ci', 'utf8_bin', 'utf8mb4_general_ci', 'utf8mb4_bin' ), true ) ) {
     2422                return false;
     2423            }
     2424        }
     2425
     2426        return true;
     2427    }
     2428
     2429    /**
    23622430     * Strips any invalid characters based on value/charset pairs.
    23632431     *
  • trunk/tests/phpunit/tests/db/charset.php

    r31953 r32162  
    464464        $this->assertFalse( $wpdb->query( "INSERT INTO {$wpdb->posts} (post_content) VALUES ('foo\xf0\xff\xff\xffbar')" ) );
    465465    }
     466
     467    /**
     468     * @ticket 21212
     469     */
     470    function data_table_collation_check() {
     471        $table_name = 'table_collation_check';
     472        $data = array(
     473            array(
     474                // utf8_bin tables don't need extra sanity checking.
     475                "( a VARCHAR(50) COLLATE utf8_bin )", // create
     476                true                                  // expected result
     477            ),
     478            array(
     479                // Neither do utf8_general_ci tables.
     480                "( a VARCHAR(50) COLLATE utf8_general_ci )",
     481                true
     482            ),
     483            array(
     484                // utf8_unicode_ci tables do.
     485                "( a VARCHAR(50) COLLATE utf8_unicode_ci )",
     486                false
     487            ),
     488            array(
     489                // utf8_bin tables don't need extra sanity checking,
     490                // except for when they're not just utf8_bin.
     491                "( a VARCHAR(50) COLLATE utf8_bin, b VARCHAR(50) COLLATE big5_chinese_ci )",
     492                false
     493            ),
     494            array(
     495                // utf8_bin tables don't need extra sanity checking
     496                // when the other columns aren't strings.
     497                "( a VARCHAR(50) COLLATE utf8_bin, b INT )",
     498                true
     499            ),
     500        );
     501
     502        foreach( $data as &$value ) {
     503            $this_table_name = $table_name . '_' . rand_str( 5 );
     504
     505            $value[0] = "CREATE TABLE $this_table_name {$value[0]}";
     506            $value[2] = "SELECT * FROM $this_table_name";
     507            $value[3] = "DROP TABLE IF EXISTS $this_table_name";
     508        }
     509        unset( $value );
     510
     511        return $data;
     512    }
     513
     514
     515    /**
     516     * @dataProvider data_table_collation_check
     517     * @ticket 21212
     518     */
     519    function test_table_collation_check( $create, $expected, $query, $drop ) {
     520        self::$_wpdb->query( $drop );
     521
     522        self::$_wpdb->query( $create );
     523
     524        $return = self::$_wpdb->check_safe_collation( $query );
     525        $this->assertEquals( $expected, $return );
     526
     527        self::$_wpdb->query( $drop );
     528    }
    466529}
Note: See TracChangeset for help on using the changeset viewer.