1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-08-22 08:13:14 +02:00

[ticket/16741] General fixes

PHPBB3-16741
This commit is contained in:
Tristan Darricau
2021-11-09 02:48:34 +01:00
parent 300e5399f5
commit 6ce708539b
20 changed files with 941 additions and 385 deletions

View File

@@ -4,7 +4,7 @@
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
@@ -33,8 +33,8 @@ class connection_factory
*
* @return Connection Doctrine DBAL connection.
*
* @throws runtime_exception If the database connection could not be established.
* @throws InvalidArgumentException If the provided driver name is not a valid phpBB database driver.
* @throws runtime_exception If the database connection could not be established.
* @throws InvalidArgumentException If the provided driver name is not a valid phpBB database driver.
*/
public static function get_connection(config_php_file $config): Connection
{
@@ -58,17 +58,17 @@ class connection_factory
/**
* Creates a database connection from the specified parameters.
*
* @param string $driver Driver name.
* @param string $host Hostname.
* @param string|null $user Username.
* @param string|null $password Password.
* @param string|null $name Database name.
* @param string|null $port Database port.
* @param string $driver Driver name.
* @param string $host Hostname.
* @param string|null $user Username.
* @param string|null $password Password.
* @param string|null $name Database name.
* @param string|null $port Database port.
*
* @return Connection Doctrine DBAL connection.
*
* @throws runtime_exception If the database connection could not be established.
* @throws InvalidArgumentException If $driver is not a valid phpBB database driver.
* @throws runtime_exception If the database connection could not be established.
* @throws InvalidArgumentException If $driver is not a valid phpBB database driver.
*/
public static function get_connection_from_params(
string $driver,
@@ -97,13 +97,16 @@ class connection_factory
try
{
$connection = DriverManager::getConnection($params);
Type::addType(case_insensitive_string::CASE_INSENSITIVE_STRING, case_insensitive_string::class);
if (!Type::hasType(case_insensitive_string::CASE_INSENSITIVE_STRING))
{
Type::addType(case_insensitive_string::CASE_INSENSITIVE_STRING, case_insensitive_string::class);
}
$connection->getDatabasePlatform()->registerDoctrineTypeMapping('varchar_ci', case_insensitive_string::CASE_INSENSITIVE_STRING);
return $connection;
}
catch (Exception $e)
{
throw new runtime_exception('DB_CONNECTION_FAILED');
throw new runtime_exception('DB_CONNECTION_FAILED', [], $e);
}
}

View File

@@ -14,6 +14,7 @@
namespace phpbb\db\doctrine;
use InvalidArgumentException;
use phpbb\db\doctrine\oci8\driver as oci8_driver;
/**
* Helper class to generate Doctrine DBAL configuration.
@@ -152,9 +153,14 @@ class connection_parameter_factory
'oci8' => [
'charset' => 'UTF8',
'platform' => new oracle_platform(),
'driverClass' => oci8_driver::class,
],
'pdo_pgsql' => [
'charset' => 'UTF8',
'platform' => new postgresql_platform(),
],
'pdo_sqlsrv' => [
'platform' => new sqlsrv_platform(),
],
];

View File

@@ -4,7 +4,7 @@
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
@@ -27,7 +27,7 @@ class table_helper
public static function convert_column_data(array $column_data, string $dbms_layer): array
{
$options = self::resolve_dbms_specific_options($column_data, $dbms_layer);
list($type, $opts) = type_converter::convert($column_data[0]);
list($type, $opts) = type_converter::convert($column_data[0], $dbms_layer);
$options = array_merge($options, $opts);
return [$type, $options];
}
@@ -35,8 +35,8 @@ class table_helper
/**
* Resolve DBMS specific options in column data.
*
* @param array $column_data Original column data.
* @param string $dbms_layer DBMS layer name.
* @param array $column_data Original column data.
* @param string $dbms_layer DBMS layer name.
*
* @return array Doctrine column options.
*/
@@ -54,12 +54,19 @@ class table_helper
$doctrine_options['default'] = $column_data[1];
$doctrine_options['notnull'] = true;
}
else
{
$doctrine_options['notnull'] = false;
}
$non_string_pattern = '/^[a-z]*(?:int|decimal|bool|timestamp)(?::[0-9]+)?$/';
if ($dbms_layer === 'oracle' && !preg_match($non_string_pattern, strtolower($column_data[0]))
&& array_key_exists('default', $doctrine_options[0]) && $doctrine_options[0]['default'] === '')
if ($dbms_layer === 'oracle'
&& !preg_match($non_string_pattern, strtolower($column_data[0]))
&& array_key_exists('default', $doctrine_options)
&& $doctrine_options['default'] === '')
{
unset($doctrine_options['notnull']);
// Not null is true by default and Oracle does not allow empty strings in not null columns
$doctrine_options['notnull'] = false;
}
if (isset($column_data[2]))
@@ -80,8 +87,8 @@ class table_helper
/**
* Returns the DBMS specific default value for a column definition.
*
* @param array $default_options Database specific default value options.
* @param string $dbms_layer Name of the DBMS layer.
* @param array $default_options Database specific default value options.
* @param string $dbms_layer Name of the DBMS layer.
*
* @return mixed Default value for the current DBMS.
*

View File

@@ -24,6 +24,7 @@ class type_converter
* @var array
*/
private const TYPE_MAP = [
'INT' => ['integer', []],
'BINT' => ['bigint', []],
'ULINT' => ['integer', ['unsigned' => true]],
'UINT' => ['integer', ['unsigned' => true]],
@@ -41,8 +42,8 @@ class type_converter
'MTEXT' => ['text', ['length' => ((1 << 24) - 1)]],
'MTEXT_UNI' => ['text', ['length' => ((1 << 24) - 1)]],
'TIMESTAMP' => ['integer', ['unsigned' => true]],
'DECIMAL' => ['integer', ['precision' => 5, 'scale' => 2]],
'PDECIMAL' => ['integer', ['precision' => 6, 'scale' => 3]],
'DECIMAL' => ['decimal', ['precision' => 5, 'scale' => 2]],
'PDECIMAL' => ['decimal', ['precision' => 6, 'scale' => 3]],
'VCHAR_UNI' => ['string', ['length' => 255]],
'VCHAR_CI' => ['string_ci', ['length' => 255]],
'VARBINARY' => ['binary', ['length' => 255]],
@@ -55,7 +56,7 @@ class type_converter
*
* @return array<string, array> Pair of type name and options.
*/
public static function convert(string $type): array
public static function convert(string $type, string $dbms): array
{
if (strpos($type, ':') !== false)
{
@@ -63,7 +64,7 @@ class type_converter
return self::mapWithLength($typename, (int) $length);
}
return self::mapType($type);
return self::mapType($type, $dbms);
}
/**
@@ -108,13 +109,40 @@ class type_converter
*
* @return array<string, array> Pair of type name and an array of options.
*/
private static function mapType(string $type): array
private static function mapType(string $type, string $dbms): array
{
if (!in_array($type, self::TYPE_MAP, true))
if (!array_key_exists($type, self::TYPE_MAP))
{
throw new \InvalidArgumentException("Database type is undefined.");
}
// Historically, on mssql varbinary fields were stored as varchar.
// For compatibility reasons we have to keep it (because when
// querying the database, mssql does not convert strings to their
// binary representation automatically like the other dbms.
if ($type === 'VARBINARY' && $dbms === 'mssql')
{
return self::TYPE_MAP['VCHAR'];
}
// Historically, on mssql bool fields were stored as integer.
// For compatibility reasons we have to keep it because is
// some queries we are using MIN() to these columns which
// is forbidden by MSSQL for bool (bit) columns.
if ($type === 'BOOL' && $dbms === 'mssql')
{
return self::TYPE_MAP['TINT'];
}
// Historically, on postgres bool fields were stored as integer.
// For compatibility reasons we have to keep it because when
// querying the database, postgres does not convert automatically
// 0 and 1 to their boolean representation like the other dbms.
if ($type === 'BOOL' && $dbms === 'postgresql')
{
return self::TYPE_MAP['TINT'];
}
return self::TYPE_MAP[$type];
}
}