Make WordPress Core

Opened 10 years ago

Closed 10 years ago

#34096 closed defect (bug) (invalid)

Failed to set charset

Reported by: kolorafa's profile kolorafa Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.4
Component: Database Keywords: has-patch
Focuses: Cc:

Change History (7)

#1 @pento
10 years ago

  • Keywords reporter-feedback added
  • Milestone Awaiting Review deleted

Hi, @kolorafa! Thank you for the patch!

Could you please provide a method to reproduce this bug? Particularly, I'm interested in a scenario where mysqli_set_charset() fails, but SET NAMES works.

#2 @SergeyBiryukov
10 years ago

  • Milestone set to Awaiting Review

#3 @kolorafa
10 years ago

Sorry for the delay, i did prepare a test code.
Probably problem in difference version of mysql and php_mysqli, but still WordPress should fallback to old method on failure.

Also it works with utf8 but fail with utf8mb4

http://kolorafa.firehost.pl/wptest.php

Right After connect
bool(true) 1: Row One - Test azsclo - without pl char
bool(true) 2: Row Two - Test ?????� - with pl char


charset
string(4) "utf8" 

mysqli_set_charset
bool(true) 

Right After mysqli_set_charset
bool(true) 1: Row One - Test azsclo - without pl char
bool(true) 2: Row Two - Test ążśćłó - with pl char


Right After SET NAMES
bool(true) 1: Row One - Test azsclo - without pl char
bool(true) 2: Row Two - Test ążśćłó - with pl char

Right After connect
bool(true) 1: Row One - Test azsclo - without pl char
bool(true) 2: Row Two - Test ?????� - with pl char


charset
string(7) "utf8mb4" 

mysqli_set_charset
bool(false) 

Right After mysqli_set_charset
bool(true) 1: Row One - Test azsclo - without pl char
bool(true) 2: Row Two - Test ?????� - with pl char


Right After SET NAMES
bool(true) 1: Row One - Test azsclo - without pl char
bool(true) 2: Row Two - Test ążśćłó - with pl char

<?php
define("DBHOST","****");
define("DBUSER","****");
define("DBPASS","****");
define("DBNAME","****");
/*EndOfDbConfig*/

echo '<meta charset="UTF-8" />';

$charset = "utf8mb4";

function print_data($link){
    $stmt =  $link->prepare("SELECT * FROM table1");
    $stmt->execute();
    $stmt->bind_result($id, $name, $text);
    while ($x = $stmt->fetch()) {var_dump($x);
        printf ("%d: %s - %s<br/>\n", $id,$name, $text);
    }
....
}

function title($text){
echo "<br/><br/>".$text."</br>";
}

$mysqli = new mysqli(DBHOST, DBUSER, DBPASS, DBNAME);

title("Right After connect");
print_data($mysqli);

title("mysqli_set_charset");
var_dump(mysqli_set_charset( $mysqli, $charset ));

title("Right After mysqli_set_charset");
print_data($mysqli);

$mysqli->query("SET NAMES ".$charset);

title("Right After SET NAMES");
print_data($mysqli);

title("Self Code");
$self = explode("/*EndOfDbConfig*/",file_get_contents(__FILE__),2);
echo "<br/><br/><pre>".htmlspecialchars($self[1])."</pre>";

Last edited 10 years ago by kolorafa (previous) (diff)

#4 @kolorafa
10 years ago

  • Keywords has-patch added

What else could I test/provide?

#5 @pento
10 years ago

Ah, I suspect what is happening is that mysqli_set_charset() checks whether the client library supports utf8mb4 before it sets the connection character set, whereas SET NAMES will just set it regardless.

In the case of your test, mysqli_set_charset() failing causes the connection to fall back to latin1, but SET NAMES "works", because you're only sending 3 byte characters, which will work even if your client doesn't support utf8mb4.

What version does mysqli_get_client_info() return on your server?

#6 @kolorafa
10 years ago

mysqli_get_client_info()
string(6) "5.1.34"

#7 @pento
10 years ago

  • Keywords reporter-feedback removed
  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

Ah, that'd be the problem, then. It needs to be at least 5.5.3 for utf8mb4 to work correctly. You'll need to upgrade your PHP MySQL client library, or speak to your host if you don't have access to upgrade it.

Note: See TracTickets for help on using tickets.