summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2016-10-19 22:09:14 +0200
committerGitHub <noreply@github.com>2016-10-19 22:09:14 +0200
commit73f4ae94dd7b0798278f64fec9feaad5d0badba3 (patch)
treee7c575f576abceaeb0a44a991bbdde6444f8fa5d
parent58d53eb94c2ec12782f8cf65d0245fd6391d43bf (diff)
parent303e0737244eebd055d74e2f6d75747a5cdb26da (diff)
downloadnextcloud-server-73f4ae94dd7b0798278f64fec9feaad5d0badba3.tar.gz
nextcloud-server-73f4ae94dd7b0798278f64fec9feaad5d0badba3.zip
Merge pull request #1773 from nextcloud/testing-characters-in-db
MySQL 4byte support
-rw-r--r--.drone.yml21
-rwxr-xr-xautotest.sh44
-rw-r--r--config/config.sample.php29
-rw-r--r--core/register_command.php2
-rw-r--r--lib/private/DB/AdapterMySQL.php14
-rw-r--r--lib/private/DB/ConnectionFactory.php11
-rw-r--r--lib/private/DB/MDB2SchemaReader.php14
-rw-r--r--lib/private/DB/MDB2SchemaWriter.php6
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php19
-rw-r--r--lib/private/Repair.php3
-rw-r--r--lib/private/Repair/Collation.php45
-rw-r--r--lib/private/Server.php2
-rw-r--r--lib/private/Setup/AbstractDatabase.php2
-rw-r--r--lib/private/Setup/MySQL.php5
-rw-r--r--tests/data/db_structure.xml15
-rw-r--r--tests/docker/mysqlmb4.config.php5
-rw-r--r--tests/docker/mysqlmb4/mb4.cnf5
-rw-r--r--tests/lib/DB/LegacyDBTest.php35
-rw-r--r--tests/lib/Files/Cache/CacheTest.php3
-rw-r--r--tests/lib/Repair/RepairCollationTest.php16
20 files changed, 263 insertions, 33 deletions
diff --git a/.drone.yml b/.drone.yml
index c54907cc5d9..78cdefd82b4 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -148,6 +148,14 @@ pipeline:
matrix:
DB: postgres
PHP: 5.6
+ mysqlmb4-php5.6:
+ image: nextcloudci/php5.6:php5.6-2
+ commands:
+ - NOCOVERAGE=true TEST_SELECTION=DB ./autotest.sh mysqlmb4
+ when:
+ matrix:
+ DB: mysqlmb4
+ PHP: 5.6
integration-capabilities_features:
image: nextcloudci/integration-php7.0:integration-php7.0-1
commands:
@@ -368,6 +376,8 @@ matrix:
PHP: 5.6
- DB: postgres
PHP: 5.6
+ - DB: mysqlmb4
+ PHP: 5.6
services:
cache:
@@ -390,3 +400,14 @@ services:
when:
matrix:
DB: mysql
+ mysqlmb4:
+ image: mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD=owncloud
+ - MYSQL_USER=oc_autotest
+ - MYSQL_PASSWORD=owncloud
+ - MYSQL_DATABASE=oc_autotest
+ command: [ "--innodb_large_prefix=true", "--innodb_file_format=barracuda", "--innodb_file_per_table=true" ]
+ when:
+ matrix:
+ DB: mysqlmb4
diff --git a/autotest.sh b/autotest.sh
index eca3d81c048..61e7426ab99 100755
--- a/autotest.sh
+++ b/autotest.sh
@@ -21,7 +21,7 @@ ADMINLOGIN=admin$EXECUTOR_NUMBER
BASEDIR=$PWD
PRIMARY_STORAGE_CONFIGS="local swift"
-DBCONFIGS="sqlite mysql mariadb pgsql oci"
+DBCONFIGS="sqlite mysql mariadb pgsql oci mysqlmb4"
# $PHP_EXE is run through 'which' and as such e.g. 'php' or 'hhvm' is usually
# sufficient. Due to the behaviour of 'which', $PHP_EXE may also be a path
@@ -209,6 +209,48 @@ function execute_tests {
exit 1
fi
fi
+ if [ "$DB" == "mysqlmb4" ] ; then
+ if [ ! -z "$USEDOCKER" ] ; then
+ echo "Fire up the mysql docker"
+ DOCKER_CONTAINER_ID=$(docker run \
+ -v $BASEDIR/tests/docker/mysqlmb4:/etc/mysql/conf.d \
+ -e MYSQL_ROOT_PASSWORD=owncloud \
+ -e MYSQL_USER="$DATABASEUSER" \
+ -e MYSQL_PASSWORD=owncloud \
+ -e MYSQL_DATABASE="$DATABASENAME" \
+ -d mysql:5.7
+ --innodb_large_prefix=true
+ --innodb_file_format=barracuda
+ --innodb_file_per_table=true)
+
+ DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
+
+ else
+ if [ -z "$DRONE" ] ; then # no need to drop the DB when we are on CI
+ if [ "mysql" != "$(mysql --version | grep -o mysql)" ] ; then
+ echo "Your mysql binary is not provided by mysql"
+ echo "To use the docker container set the USEDOCKER environment variable"
+ exit -1
+ fi
+ mysql -u "$DATABASEUSER" -powncloud -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
+ else
+ DATABASEHOST=127.0.0.1
+ fi
+ fi
+
+ echo "Waiting for MySQL(utf8mb4) initialisation ..."
+
+ if ! apps/files_external/tests/env/wait-for-connection $DATABASEHOST 3306 60; then
+ echo "[ERROR] Waited 60 seconds, no response" >&2
+ exit 1
+ fi
+ sleep 1
+
+ echo "MySQL(utf8mb4) is up."
+ _DB="mysql"
+
+ cp tests/docker/mysqlmb4.config.php config
+ fi
if [ "$DB" == "mariadb" ] ; then
if [ ! -z "$USEDOCKER" ] ; then
echo "Fire up the mariadb docker"
diff --git a/config/config.sample.php b/config/config.sample.php
index 3aa0f353c59..df1e2d16fc0 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -129,6 +129,7 @@ $CONFIG = array(
*/
'dbtableprefix' => '',
+
/**
* Indicates whether the Nextcloud instance was installed successfully; ``true``
* indicates a successful installation, and ``false`` indicates an unsuccessful
@@ -1080,6 +1081,34 @@ $CONFIG = array(
'sqlite.journal_mode' => 'DELETE',
/**
+ * If this setting is set to true MySQL can handle 4 byte characters instead of
+ * 3 byte characters
+ *
+ * MySQL requires a special setup for longer indexes (> 767 bytes) which are
+ * needed:
+ *
+ * [mysqld]
+ * innodb_large_prefix=true
+ * innodb_file_format=barracuda
+ * innodb_file_per_table=true
+ *
+ * Tables will be created with
+ * * character set: utf8mb4
+ * * collation: utf8mb4_bin
+ * * row_format: compressed
+ *
+ * See:
+ * https://dev.mysql.com/doc/refman/5.7/en/charset-unicode-utf8mb4.html
+ * https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix
+ * https://mariadb.com/kb/en/mariadb/xtradbinnodb-server-system-variables/#innodb_large_prefix
+ * http://www.tocker.ca/2013/10/31/benchmarking-innodb-page-compression-performance.html
+ * http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/
+ *
+ * WARNING: EXPERIMENTAL
+ */
+'mysql.utf8mb4' => false,
+
+/**
* Database types that are supported for installation.
*
* Available:
diff --git a/core/register_command.php b/core/register_command.php
index a6da3cbd899..89b0cf31ef4 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -83,7 +83,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
$application->add(new OC\Core\Command\Config\System\SetConfig(\OC::$server->getSystemConfig()));
$application->add(new OC\Core\Command\Db\GenerateChangeScript());
- $application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory()));
+ $application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory(\OC::$server->getConfig())));
$application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Encryption\Enable(\OC::$server->getConfig(), \OC::$server->getEncryptionManager()));
diff --git a/lib/private/DB/AdapterMySQL.php b/lib/private/DB/AdapterMySQL.php
index 3e2fceda8db..aa784bb83dc 100644
--- a/lib/private/DB/AdapterMySQL.php
+++ b/lib/private/DB/AdapterMySQL.php
@@ -27,6 +27,9 @@ namespace OC\DB;
class AdapterMySQL extends Adapter {
+ /** @var string */
+ protected $charset;
+
/**
* @param string $tableName
*/
@@ -39,7 +42,16 @@ class AdapterMySQL extends Adapter {
}
public function fixupStatement($statement) {
- $statement = str_replace(' ILIKE ', ' COLLATE utf8_general_ci LIKE ', $statement);
+ $statement = str_replace(' ILIKE ', ' COLLATE ' . $this->getCharset() . '_general_ci LIKE ', $statement);
return $statement;
}
+
+ protected function getCharset() {
+ if (!$this->charset) {
+ $params = $this->conn->getParams();
+ $this->charset = isset($params['charset']) ? $params['charset'] : 'utf8';
+ }
+
+ return $this->charset;
+ }
}
diff --git a/lib/private/DB/ConnectionFactory.php b/lib/private/DB/ConnectionFactory.php
index b2c356edef7..adb180da0c0 100644
--- a/lib/private/DB/ConnectionFactory.php
+++ b/lib/private/DB/ConnectionFactory.php
@@ -28,6 +28,7 @@ namespace OC\DB;
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
use Doctrine\DBAL\Event\Listeners\SQLSessionInit;
use Doctrine\DBAL\Event\Listeners\MysqlSessionInit;
+use OCP\IConfig;
/**
* Takes care of creating and configuring Doctrine connections.
@@ -64,6 +65,12 @@ class ConnectionFactory {
),
);
+ public function __construct(IConfig $config) {
+ if($config->getSystemValue('mysql.utf8mb4', false)) {
+ $this->defaultConnectionParams['mysql']['charset'] = 'utf8mb4';
+ }
+ }
+
/**
* @brief Get default connection parameters for a given DBMS.
* @param string $type DBMS type
@@ -99,7 +106,9 @@ class ConnectionFactory {
case 'mysql':
// Send "SET NAMES utf8". Only required on PHP 5.3 below 5.3.6.
// See http://stackoverflow.com/questions/4361459/php-pdo-charset-set-names#4361485
- $eventManager->addEventSubscriber(new MysqlSessionInit);
+ $eventManager->addEventSubscriber(new MysqlSessionInit(
+ $this->defaultConnectionParams['mysql']['charset']
+ ));
$eventManager->addEventSubscriber(
new SQLSessionInit("SET SESSION AUTOCOMMIT=1"));
break;
diff --git a/lib/private/DB/MDB2SchemaReader.php b/lib/private/DB/MDB2SchemaReader.php
index 3f183c9723a..c198bb31e00 100644
--- a/lib/private/DB/MDB2SchemaReader.php
+++ b/lib/private/DB/MDB2SchemaReader.php
@@ -33,6 +33,7 @@ namespace OC\DB;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\SchemaConfig;
+use Doctrine\DBAL\Platforms\MySqlPlatform;
use OCP\IConfig;
class MDB2SchemaReader {
@@ -54,12 +55,16 @@ class MDB2SchemaReader {
/** @var \Doctrine\DBAL\Schema\SchemaConfig $schemaConfig */
protected $schemaConfig;
+ /** @var IConfig */
+ protected $config;
+
/**
* @param \OCP\IConfig $config
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
*/
public function __construct(IConfig $config, AbstractPlatform $platform) {
$this->platform = $platform;
+ $this->config = $config;
$this->DBNAME = $config->getSystemValue('dbname', 'owncloud');
$this->DBTABLEPREFIX = $config->getSystemValue('dbtableprefix', 'oc_');
@@ -118,8 +123,15 @@ class MDB2SchemaReader {
$name = str_replace('*dbprefix*', $this->DBTABLEPREFIX, $name);
$name = $this->platform->quoteIdentifier($name);
$table = $schema->createTable($name);
- $table->addOption('collate', 'utf8_bin');
$table->setSchemaConfig($this->schemaConfig);
+
+ if($this->platform instanceof MySqlPlatform && $this->config->getSystemValue('mysql.utf8mb4', false)) {
+ $table->addOption('charset', 'utf8mb4');
+ $table->addOption('collate', 'utf8mb4_bin');
+ $table->addOption('row_format', 'compressed');
+ } else {
+ $table->addOption('collate', 'utf8_bin');
+ }
break;
case 'create':
case 'overwrite':
diff --git a/lib/private/DB/MDB2SchemaWriter.php b/lib/private/DB/MDB2SchemaWriter.php
index 26e32b036fe..7664b4359ab 100644
--- a/lib/private/DB/MDB2SchemaWriter.php
+++ b/lib/private/DB/MDB2SchemaWriter.php
@@ -43,7 +43,11 @@ class MDB2SchemaWriter {
$xml->addChild('name', $config->getSystemValue('dbname', 'owncloud'));
$xml->addChild('create', 'true');
$xml->addChild('overwrite', 'false');
- $xml->addChild('charset', 'utf8');
+ if($config->getSystemValue('dbtype', 'sqlite') === 'mysql' && $config->getSystemValue('mysql.utf8mb4', false)) {
+ $xml->addChild('charset', 'utf8mb4');
+ } else {
+ $xml->addChild('charset', 'utf8');
+ }
// FIX ME: bloody work around
if ($config->getSystemValue('dbtype', 'sqlite') === 'oci') {
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
index 66d8851632f..17f7fd5aa47 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
@@ -24,18 +24,31 @@
namespace OC\DB\QueryBuilder\ExpressionBuilder;
-use OC\DB\QueryBuilder\QueryFunction;
-use OCP\DB\QueryBuilder\IQueryBuilder;
+use OC\DB\Connection;
+use OCP\IDBConnection;
class MySqlExpressionBuilder extends ExpressionBuilder {
+ /** @var string */
+ protected $charset;
+
+ /**
+ * @param \OCP\IDBConnection|Connection $connection
+ */
+ public function __construct(IDBConnection $connection) {
+ parent::__construct($connection);
+
+ $params = $connection->getParams();
+ $this->charset = isset($params['charset']) ? $params['charset'] : 'utf8';
+ }
+
/**
* @inheritdoc
*/
public function iLike($x, $y, $type = null) {
$x = $this->helper->quoteColumnName($x);
$y = $this->helper->quoteColumnName($y);
- return $this->expressionBuilder->comparison($x, ' COLLATE utf8_general_ci LIKE', $y);
+ return $this->expressionBuilder->comparison($x, ' COLLATE ' . $this->charset . '_general_ci LIKE', $y);
}
}
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index 2ba118b9c37..7a5ef9fbd9e 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -129,6 +129,7 @@ class Repair implements IOutput{
*/
public static function getRepairSteps() {
return [
+ new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), \OC::$server->getDatabaseConnection(), false),
new RepairMimeTypes(\OC::$server->getConfig()),
new RepairLegacyStorages(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new AssetCache(),
@@ -179,7 +180,7 @@ class Repair implements IOutput{
$connection = \OC::$server->getDatabaseConnection();
$steps = [
new InnoDB(),
- new Collation(\OC::$server->getConfig(), $connection),
+ new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), $connection, true),
new SqliteAutoincrement($connection),
new SearchLuceneTables(),
];
diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php
index 74c4ca2e6ac..54de1a719bd 100644
--- a/lib/private/Repair/Collation.php
+++ b/lib/private/Repair/Collation.php
@@ -24,28 +24,38 @@
namespace OC\Repair;
+use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Platforms\MySqlPlatform;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\ILogger;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
class Collation implements IRepairStep {
- /**
- * @var \OCP\IConfig
- */
+ /** @var IConfig */
protected $config;
- /**
- * @var \OC\DB\Connection
- */
+ /** @var ILogger */
+ protected $logger;
+
+ /** @var IDBConnection */
protected $connection;
+ /** @var bool */
+ protected $ignoreFailures;
+
/**
- * @param \OCP\IConfig $config
- * @param \OC\DB\Connection $connection
+ * @param IConfig $config
+ * @param ILogger $logger
+ * @param IDBConnection $connection
+ * @param bool $ignoreFailures
*/
- public function __construct($config, $connection) {
+ public function __construct(IConfig $config, ILogger $logger, IDBConnection $connection, $ignoreFailures) {
$this->connection = $connection;
$this->config = $config;
+ $this->logger = $logger;
+ $this->ignoreFailures = $ignoreFailures;
}
public function getName() {
@@ -61,11 +71,21 @@ class Collation implements IRepairStep {
return;
}
+ $characterSet = $this->config->getSystemValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
+
$tables = $this->getAllNonUTF8BinTables($this->connection);
foreach ($tables as $table) {
$output->info("Change collation for $table ...");
- $query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;');
- $query->execute();
+ $query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET ' . $characterSet . ' COLLATE ' . $characterSet . '_bin;');
+ try {
+ $query->execute();
+ } catch (DriverException $e) {
+ // Just log this
+ $this->logger->logException($e);
+ if (!$this->ignoreFailures) {
+ throw $e;
+ }
+ }
}
}
@@ -75,11 +95,12 @@ class Collation implements IRepairStep {
*/
protected function getAllNonUTF8BinTables($connection) {
$dbName = $this->config->getSystemValue("dbname");
+ $characterSet = $this->config->getSystemValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
$rows = $connection->fetchAll(
"SELECT DISTINCT(TABLE_NAME) AS `table`" .
" FROM INFORMATION_SCHEMA . COLUMNS" .
" WHERE TABLE_SCHEMA = ?" .
- " AND (COLLATION_NAME <> 'utf8_bin' OR CHARACTER_SET_NAME <> 'utf8')" .
+ " AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" .
" AND TABLE_NAME LIKE \"*PREFIX*%\"",
array($dbName)
);
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 291714b23d1..11558118d52 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -407,8 +407,8 @@ class Server extends ServerContainer implements IServerContainer {
return new CredentialsManager($c->getCrypto(), $c->getDatabaseConnection());
});
$this->registerService('DatabaseConnection', function (Server $c) {
- $factory = new \OC\DB\ConnectionFactory();
$systemConfig = $c->getSystemConfig();
+ $factory = new \OC\DB\ConnectionFactory($c->getConfig());
$type = $systemConfig->getValue('dbtype', 'sqlite');
if (!$factory->isValidType($type)) {
throw new \OC\DatabaseException('Invalid database type');
diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php
index 310f74d4c0c..47c3e5ee1c6 100644
--- a/lib/private/Setup/AbstractDatabase.php
+++ b/lib/private/Setup/AbstractDatabase.php
@@ -134,7 +134,7 @@ abstract class AbstractDatabase {
}
$connectionParams = array_merge($connectionParams, $configOverwrite);
- $cf = new ConnectionFactory();
+ $cf = new ConnectionFactory($this->config);
return $cf->getConnection($this->config->getSystemValue('dbtype', 'sqlite'), $connectionParams);
}
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
index 4ad6926c2d7..c022616d8b3 100644
--- a/lib/private/Setup/MySQL.php
+++ b/lib/private/Setup/MySQL.php
@@ -58,8 +58,9 @@ class MySQL extends AbstractDatabase {
try{
$name = $this->dbName;
$user = $this->dbUser;
- //we can't use OC_BD functions here because we need to connect as the administrative user.
- $query = "CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET utf8 COLLATE utf8_bin;";
+ //we can't use OC_DB functions here because we need to connect as the administrative user.
+ $characterSet = \OC::$server->getSystemConfig()->getValue('mysql.utf8mb4', false) ? 'utf8mb4' : 'utf8';
+ $query = "CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET $characterSet COLLATE ${characterSet}_bin;";
$connection->executeUpdate($query);
} catch (\Exception $ex) {
$this->logger->error('Database creation failed: {error}', [
diff --git a/tests/data/db_structure.xml b/tests/data/db_structure.xml
index 371da944832..b155114f2ed 100644
--- a/tests/data/db_structure.xml
+++ b/tests/data/db_structure.xml
@@ -293,4 +293,19 @@
</table>
+ <table>
+
+ <name>*dbprefix*text_table</name>
+ <declaration>
+
+ <field>
+ <name>textfield</name>
+ <type>text</type>
+ <notnull>false</notnull>
+ <length>255</length>
+ </field>
+
+ </declaration>
+ </table>
+
</database>
diff --git a/tests/docker/mysqlmb4.config.php b/tests/docker/mysqlmb4.config.php
new file mode 100644
index 00000000000..4e78272fab4
--- /dev/null
+++ b/tests/docker/mysqlmb4.config.php
@@ -0,0 +1,5 @@
+<?php
+
+$CONFIG = array(
+ 'mysql.utf8mb4' => true,
+);
diff --git a/tests/docker/mysqlmb4/mb4.cnf b/tests/docker/mysqlmb4/mb4.cnf
new file mode 100644
index 00000000000..00333eab10d
--- /dev/null
+++ b/tests/docker/mysqlmb4/mb4.cnf
@@ -0,0 +1,5 @@
+
+[mysqld]
+innodb_large_prefix=true
+innodb_file_format=barracuda
+innodb_file_per_table=true
diff --git a/tests/lib/DB/LegacyDBTest.php b/tests/lib/DB/LegacyDBTest.php
index 7aeeb3dd1f9..f3de570c52d 100644
--- a/tests/lib/DB/LegacyDBTest.php
+++ b/tests/lib/DB/LegacyDBTest.php
@@ -46,6 +46,11 @@ class LegacyDBTest extends \Test\TestCase {
*/
private $table5;
+ /**
+ * @var string
+ */
+ private $text_table;
+
protected function setUp() {
parent::setUp();
@@ -63,6 +68,7 @@ class LegacyDBTest extends \Test\TestCase {
$this->table3 = $this->test_prefix.'vcategory';
$this->table4 = $this->test_prefix.'decimal';
$this->table5 = $this->test_prefix.'uniconst';
+ $this->text_table = $this->test_prefix.'text_table';
}
protected function tearDown() {
@@ -390,4 +396,33 @@ class LegacyDBTest extends \Test\TestCase {
$result = $query->execute(array('%ba%'));
$this->assertCount(1, $result->fetchAll());
}
+
+ /**
+ * @dataProvider insertAndSelectDataProvider
+ */
+ public function testInsertAndSelectData($expected, $throwsOnMysqlWithoutUTF8MB4) {
+ $table = "*PREFIX*{$this->text_table}";
+ $config = \OC::$server->getConfig();
+
+ $query = OC_DB::prepare("INSERT INTO `$table` (`textfield`) VALUES (?)");
+ if ($throwsOnMysqlWithoutUTF8MB4 && $config->getSystemValue('dbtype', 'sqlite') === 'mysql' && $config->getSystemValue('mysql.utf8mb4', false) === false) {
+ $this->markTestSkipped('MySQL requires UTF8mb4 to store value: ' . $expected);
+ }
+ $result = $query->execute(array($expected));
+ $this->assertEquals(1, $result);
+
+ $actual = OC_DB::prepare("SELECT `textfield` FROM `$table`")->execute()->fetchOne();
+ $this->assertSame($expected, $actual);
+ }
+
+ public function insertAndSelectDataProvider() {
+ return [
+ ['abcdefghijklmnopqrstuvwxyzABCDEFGHIKLMNOPQRSTUVWXYZ', false],
+ ['0123456789', false],
+ ['äöüÄÖÜß!"§$%&/()=?#\'+*~°^`´', false],
+ ['²³¼½¬{[]}\\', false],
+ ['♡⚗', false],
+ ['💩', true], # :hankey: on github
+ ];
+ }
}
diff --git a/tests/lib/Files/Cache/CacheTest.php b/tests/lib/Files/Cache/CacheTest.php
index 4a2581fbc54..4c4f43d63d5 100644
--- a/tests/lib/Files/Cache/CacheTest.php
+++ b/tests/lib/Files/Cache/CacheTest.php
@@ -113,7 +113,8 @@ class CacheTest extends \Test\TestCase {
public function testFolder($folder) {
if(strpos($folder, 'F09F9890')) {
// 4 byte UTF doesn't work on mysql
- if(\OC::$server->getDatabaseConnection()->getDatabasePlatform() instanceof MySqlPlatform) {
+ $params = \OC::$server->getDatabaseConnection()->getParams();
+ if(\OC::$server->getDatabaseConnection()->getDatabasePlatform() instanceof MySqlPlatform && $params['charset'] !== 'utf8mb4') {
$this->markTestSkipped('MySQL doesn\'t support 4 byte UTF-8');
}
}
diff --git a/tests/lib/Repair/RepairCollationTest.php b/tests/lib/Repair/RepairCollationTest.php
index 2e304a74abc..897f772a794 100644
--- a/tests/lib/Repair/RepairCollationTest.php
+++ b/tests/lib/Repair/RepairCollationTest.php
@@ -1,9 +1,4 @@
<?php
-
-namespace Test\Repair;
-
-use OCP\Migration\IOutput;
-
/**
* Copyright (c) 2014 Thomas Müller <deepdiver@owncloud.com>
* This file is licensed under the Affero General Public License version 3 or
@@ -11,6 +6,11 @@ use OCP\Migration\IOutput;
* See the COPYING-README file.
*/
+namespace Test\Repair;
+
+use OCP\ILogger;
+use OCP\Migration\IOutput;
+
class TestCollationRepair extends \OC\Repair\Collation {
/**
* @param \Doctrine\DBAL\Connection $connection
@@ -50,10 +50,14 @@ class RepairCollationTest extends \Test\TestCase {
*/
private $config;
+ /** @var ILogger */
+ private $logger;
+
protected function setUp() {
parent::setUp();
$this->connection = \OC::$server->getDatabaseConnection();
+ $this->logger = $this->createMock(ILogger::class);
$this->config = \OC::$server->getConfig();
if (!$this->connection->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\MySqlPlatform) {
$this->markTestSkipped("Test only relevant on MySql");
@@ -63,7 +67,7 @@ class RepairCollationTest extends \Test\TestCase {
$this->tableName = $this->getUniqueID($dbPrefix . "_collation_test");
$this->connection->exec("CREATE TABLE $this->tableName(text VARCHAR(16)) COLLATE utf8_unicode_ci");
- $this->repair = new TestCollationRepair($this->config, $this->connection);
+ $this->repair = new TestCollationRepair($this->config, $this->logger, $this->connection, false);
}
protected function tearDown() {