diff options
author | Lukas Reschke <lukas@statuscode.ch> | 2016-10-19 22:09:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-19 22:09:14 +0200 |
commit | 73f4ae94dd7b0798278f64fec9feaad5d0badba3 (patch) | |
tree | e7c575f576abceaeb0a44a991bbdde6444f8fa5d | |
parent | 58d53eb94c2ec12782f8cf65d0245fd6391d43bf (diff) | |
parent | 303e0737244eebd055d74e2f6d75747a5cdb26da (diff) | |
download | nextcloud-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.yml | 21 | ||||
-rwxr-xr-x | autotest.sh | 44 | ||||
-rw-r--r-- | config/config.sample.php | 29 | ||||
-rw-r--r-- | core/register_command.php | 2 | ||||
-rw-r--r-- | lib/private/DB/AdapterMySQL.php | 14 | ||||
-rw-r--r-- | lib/private/DB/ConnectionFactory.php | 11 | ||||
-rw-r--r-- | lib/private/DB/MDB2SchemaReader.php | 14 | ||||
-rw-r--r-- | lib/private/DB/MDB2SchemaWriter.php | 6 | ||||
-rw-r--r-- | lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php | 19 | ||||
-rw-r--r-- | lib/private/Repair.php | 3 | ||||
-rw-r--r-- | lib/private/Repair/Collation.php | 45 | ||||
-rw-r--r-- | lib/private/Server.php | 2 | ||||
-rw-r--r-- | lib/private/Setup/AbstractDatabase.php | 2 | ||||
-rw-r--r-- | lib/private/Setup/MySQL.php | 5 | ||||
-rw-r--r-- | tests/data/db_structure.xml | 15 | ||||
-rw-r--r-- | tests/docker/mysqlmb4.config.php | 5 | ||||
-rw-r--r-- | tests/docker/mysqlmb4/mb4.cnf | 5 | ||||
-rw-r--r-- | tests/lib/DB/LegacyDBTest.php | 35 | ||||
-rw-r--r-- | tests/lib/Files/Cache/CacheTest.php | 3 | ||||
-rw-r--r-- | tests/lib/Repair/RepairCollationTest.php | 16 |
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() { |