Skip to content

Commit 3e0c083

Browse files
committed
added support for utf8mb4 character sets. Closes #73
1 parent 9bc43ca commit 3e0c083

File tree

6 files changed

+114
-42
lines changed

6 files changed

+114
-42
lines changed

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,14 @@ Refer to the [wiki](https://github.com/ifsnop/mysqldump-php/wiki/full-example) f
125125
'hex-blob' => true,
126126
'databases' => false,
127127
'add-drop-database' => false,
128-
'skip-tz-utc' => false
128+
'skip-tz-utc' => false,
129+
'no-autocommit' => true,
130+
'default-character-set' => 'utf8',
129131
);
130132

131-
$pdoSettingsDefaults = array(PDO::ATTR_PERSISTENT => true,
133+
$pdoSettingsDefaults = array(
134+
PDO::ATTR_PERSISTENT => true,
132135
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
133-
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
134136
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
135137
);
136138

@@ -177,6 +179,14 @@ Refer to the [wiki](https://github.com/ifsnop/mysqldump-php/wiki/full-example) f
177179
- http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_add-drop-database
178180
- **skip-tz-utz**
179181
- http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_tz-utc
182+
- **no-autocommit**
183+
- Option to disable autocommit (faster inserts, no problems with index keys)
184+
- http://dev.mysql.com/doc/refman/4.1/en/commit.html
185+
- **default-character-set**
186+
- utf8 (default, compatible option), utf8mb4 (for full utf8 compliance)
187+
- Could be specified using the declared consts: IMysqldump\Mysqldump::UTF8 or IMysqldump\Mysqldump::UTF8MB4BZIP2
188+
- http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
189+
- https://mathiasbynens.be/notes/mysql-utf8mb4
180190

181191
The following options are now enabled by default, and there is no way to disable them since
182192
they should always be used.
@@ -215,7 +225,6 @@ Use **SHOW GRANTS FOR user@host;** to know what privileges user has. See the fol
215225

216226
## TODO
217227

218-
- Write any tests.
219228
- Write unit tests.
220229

221230
## Contributing

src/Ifsnop/Mysqldump/Mysqldump.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ class Mysqldump
4141
const BZIP2 = 'Bzip2';
4242
const NONE = 'None';
4343

44+
// Available connection strings
45+
const UTF8 = 'utf8';
46+
const UTF8MB4 = 'utf8mb4';
47+
4448
// This can be set both on constructor or manually
4549
public $host;
4650
public $user;
@@ -85,7 +89,7 @@ public function __construct(
8589
$dumpSettingsDefault = array(
8690
'include-tables' => array(),
8791
'exclude-tables' => array(),
88-
'compress' => 'None',
92+
'compress' => Mysqldump::NONE,
8993
'no-data' => false,
9094
'add-drop-table' => false,
9195
'single-transaction' => true,
@@ -102,13 +106,14 @@ public function __construct(
102106
'add-drop-database' => false,
103107
'skip-tz-utz' => false,
104108
'no-autocommit' => true,
109+
'default-character-set' => Mysqldump::UTF8,
105110
/* deprecated */
106111
'disable-foreign-keys-check' => true
107112
);
108113

109-
$pdoSettingsDefault = array(PDO::ATTR_PERSISTENT => true,
114+
$pdoSettingsDefault = array(
115+
PDO::ATTR_PERSISTENT => true,
110116
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
111-
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",
112117
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false
113118
);
114119

@@ -120,6 +125,10 @@ public function __construct(
120125
$this->pdoSettings = self::array_replace_recursive($pdoSettingsDefault, $pdoSettings);
121126
$this->dumpSettings = self::array_replace_recursive($dumpSettingsDefault, $dumpSettings);
122127

128+
if (!isset($this->pdoSettings[PDO::MYSQL_ATTR_INIT_COMMAND])) {
129+
$this->pdoSetttings[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES " . $this->dumpSettings['default-character-set'];
130+
}
131+
123132
$diff = array_diff(array_keys($this->dumpSettings), array_keys($dumpSettingsDefault));
124133
if (count($diff)>0) {
125134
throw new Exception("Unexpected value in dumpSettings: (" . implode(",", $diff) . ")");
@@ -178,7 +187,7 @@ private function connect()
178187
$this->pdoSettings
179188
);
180189
// Fix for always-unicode output
181-
$this->dbHandler->exec("SET NAMES utf8");
190+
$this->dbHandler->exec("SET NAMES " . $this->dumpSettings['default-character-set']);
182191
// Store server version
183192
$this->version = $this->dbHandler->getAttribute(PDO::ATTR_SERVER_VERSION);
184193
break;
@@ -441,7 +450,7 @@ private function getTableStructure($tableName)
441450
);
442451
}
443452
$this->compressManager->write(
444-
$this->typeAdapter->create_table($r)
453+
$this->typeAdapter->create_table($r, $this->dumpSettings)
445454
);
446455
break;
447456
}
@@ -915,7 +924,7 @@ public function show_create_table($tableName)
915924
* function create_table Get table creation code from database
916925
* @todo make it do something with sqlite
917926
*/
918-
public function create_table($row)
927+
public function create_table($row, $dumpSettings)
919928
{
920929
return "";
921930
}
@@ -1163,14 +1172,14 @@ public function show_create_trigger($triggerName)
11631172
return "SHOW CREATE TRIGGER `$triggerName`";
11641173
}
11651174

1166-
public function create_table($row)
1175+
public function create_table($row, $dumpSettings)
11671176
{
11681177
if (!isset($row['Create Table'])) {
11691178
throw new Exception("Error getting table code, unknown output");
11701179
}
11711180

11721181
$ret = "/*!40101 SET @saved_cs_client = @@character_set_client */;" . PHP_EOL .
1173-
"/*!40101 SET character_set_client = utf8 */;" . PHP_EOL .
1182+
"/*!40101 SET character_set_client = " . $dumpSettings['default-character-set'] . " */;" . PHP_EOL .
11741183
$row['Create Table'] . ";" . PHP_EOL .
11751184
"/*!40101 SET character_set_client = @saved_cs_client */;" . PHP_EOL .
11761185
PHP_EOL;
@@ -1462,7 +1471,7 @@ public function backup_parameters()
14621471
$ret = "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;" . PHP_EOL .
14631472
"/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;" . PHP_EOL .
14641473
"/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;" . PHP_EOL .
1465-
"/*!40101 SET NAMES utf8 */;" . PHP_EOL;
1474+
"/*!40101 SET NAMES " . $dumpSettings['default-character-set'] . " */;" . PHP_EOL;
14661475

14671476
if (false === $dumpSettings['skip-tz-utz']) {
14681477
$ret .= "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;" . PHP_EOL .

tests/test.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@
3737
"mysql",
3838
$dumpSettings);
3939

40-
$dump->start("mysqldump-php.sql");
40+
$dump->start("mysqldump-php_test001.sql");
41+
42+
43+
$dumpSettings['default-character-set'] = IMysqldump\Mysqldump::UTF8MB4;
44+
45+
$dump = new IMysqldump\Mysqldump(
46+
"test002",
47+
"travis",
48+
"",
49+
"localhost",
50+
"mysql",
51+
$dumpSettings);
52+
53+
$dump->start("mysqldump-php_test002.sql");
4154

4255
exit;

tests/test.sh

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,87 @@
11
#!/bin/bash
22

3-
function checksum() {
3+
function checksum_test001() {
44
for i in 000 001 002 003 010 011 015 027 029 033 200; do
55
mysql -B -e "CHECKSUM TABLE test${i}" test001 | grep -v -i checksum
66
done
77
}
88

9+
function checksum_test002() {
10+
for i in 201; do
11+
mysql --default-character-set=utf8mb4 -B -e "CHECKSUM TABLE test${i}" test002 | grep -v -i checksum
12+
done
13+
}
14+
915
for i in $(seq 0 20) ; do
10-
ret[i]=0
16+
ret[$i]=0
1117
done
1218

13-
mysql -uroot < original.sql
14-
ret[0]=$?
19+
mysql -e "CREATE USER 'travis'@'localhost' IDENTIFIED BY '';" 2> /dev/null
20+
mysql -e "GRANT ALL PRIVILEGES ON test001.* TO 'travis'@'localhost';" 2> /dev/null
21+
mysql -e "GRANT ALL PRIVILEGES ON test002.* TO 'travis'@'localhost';" 2> /dev/null
22+
23+
mysql -uroot < test001.src.sql; ret[0]=$?
24+
25+
mysql -uroot --default-character-set=utf8mb4 < test002.src.sql; ret[1]=$?
1526

16-
checksum > original.checksum
27+
checksum_test001 > test001.src.checksum
28+
checksum_test002 > test002.src.checksum
1729

1830
mysqldump -uroot test001 \
1931
--no-autocommit \
2032
--extended-insert=false \
2133
--hex-blob=true \
22-
> mysqldump.sql
23-
ret[1]=$?
24-
25-
php test.php
34+
> mysqldump_test001.sql
2635
ret[2]=$?
2736

28-
mysql -uroot test001 < mysqldump-php.sql
37+
mysqldump -uroot test002 \
38+
--no-autocommit \
39+
--extended-insert=false \
40+
--hex-blob=true \
41+
--default-character-set=utf8mb4 \
42+
> mysqldump_test002.sql
2943
ret[3]=$?
3044

31-
checksum > mysqldump-php.checksum
32-
33-
cat original.sql | grep ^INSERT > original.filtered.sql
34-
cat mysqldump.sql | grep ^INSERT > mysqldump.filtered.sql
35-
cat mysqldump-php.sql | grep ^INSERT > mysqldump-php.filtered.sql
36-
37-
diff original.filtered.sql mysqldump.filtered.sql
45+
php test.php
3846
ret[4]=$?
3947

40-
diff original.filtered.sql mysqldump-php.filtered.sql
48+
mysql -uroot test001 < mysqldump-php_test001.sql
4149
ret[5]=$?
42-
43-
diff original.checksum mysqldump-php.checksum
50+
mysql -uroot test002 < mysqldump-php_test002.sql
4451
ret[6]=$?
4552

46-
rm original.checksum
47-
rm mysqldump-php.checksum
48-
rm original.filtered.sql
49-
rm mysqldump.filtered.sql
50-
rm mysqldump-php.filtered.sql
51-
rm mysqldump-php.sql
52-
rm mysqldump.sql
53+
checksum_test001 > mysqldump-php_test001.checksum
54+
checksum_test002 > mysqldump-php_test002.checksum
55+
56+
cat test001.src.sql | grep ^INSERT > test001.filtered.sql
57+
cat test002.src.sql | grep ^INSERT > test002.filtered.sql
58+
cat mysqldump_test001.sql | grep ^INSERT > mysqldump_test001.filtered.sql
59+
cat mysqldump_test002.sql | grep ^INSERT > mysqldump_test002.filtered.sql
60+
cat mysqldump-php_test001.sql | grep ^INSERT > mysqldump-php_test001.filtered.sql
61+
cat mysqldump-php_test002.sql | grep ^INSERT > mysqldump-php_test002.filtered.sql
62+
63+
diff test001.filtered.sql mysqldump_test001.filtered.sql
64+
ret[7]=$?
65+
diff test002.filtered.sql mysqldump_test002.filtered.sql
66+
ret[8]=$?
67+
68+
diff test001.filtered.sql mysqldump-php_test001.filtered.sql
69+
ret[9]=$?
70+
diff test002.filtered.sql mysqldump-php_test002.filtered.sql
71+
ret[10]=$?
72+
73+
diff test001.src.checksum mysqldump-php_test001.checksum
74+
ret[11]=$?
75+
diff test002.src.checksum mysqldump-php_test002.checksum
76+
ret[12]=$?
77+
78+
rm *.checksum 2> /dev/null
79+
rm *.filtered.sql 2> /dev/null
80+
rm mysqldump* 2> /dev/null
5381

5482
total=0
5583
for i in $(seq 0 20) ; do
56-
total=(${ret[i]} + $total)
84+
total=$((${ret[$i]} + $total))
5785
done
5886

5987
exit $total
File renamed without changes.

tests/test002.src.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
DROP DATABASE IF EXISTS `test002`;
2+
CREATE DATABASE `test002`;
3+
USE `test002`;
4+
5+
DROP TABLE IF EXISTS `test201`;
6+
CREATE TABLE `test201` (
7+
`col` text COLLATE utf8mb4_unicode_ci
8+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
9+
10+
INSERT INTO `test201` VALUES ('áéíóú');
11+
INSERT INTO `test201` VALUES ('🎲');
12+
INSERT INTO `test201` VALUES ('🎭');
13+
INSERT INTO `test201` VALUES ('💩');

0 commit comments

Comments
 (0)