mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-08 04:18:52 +00:00
[ticket/16741] Database tools to use Doctrine
PHPBB3-16741
This commit is contained in:
parent
aee5e373bc
commit
98134abe20
15 changed files with 877 additions and 3435 deletions
|
@ -7,6 +7,7 @@ imports:
|
|||
- { resource: services_content.yml }
|
||||
- { resource: services_cron.yml }
|
||||
- { resource: services_db.yml }
|
||||
- { resource: services_doctrine.yml }
|
||||
- { resource: services_event.yml }
|
||||
- { resource: services_extensions.yml }
|
||||
- { resource: services_feed.yml }
|
||||
|
|
5
phpBB/config/default/container/services_doctrine.yml
Normal file
5
phpBB/config/default/container/services_doctrine.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
services:
|
||||
doctrine.connection:
|
||||
class: Doctrine\DBAL\Connection
|
||||
factory: ['phpbb\db\doctrine\connection_factory', 'get_connection']
|
||||
arguments: ['@config.php']
|
55
phpBB/phpbb/db/doctrine/case_insensitive_string.php
Normal file
55
phpBB/phpbb/db/doctrine/case_insensitive_string.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\doctrine;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
/**
|
||||
* Case-insensitive string type (only supported by Postgres).
|
||||
*/
|
||||
class case_insensitive_string extends Type
|
||||
{
|
||||
public const CASE_INSENSITIVE_STRING = 'string_ci';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
|
||||
{
|
||||
if ($platform->getName() === 'postgresql')
|
||||
{
|
||||
return 'varchar_ci';
|
||||
}
|
||||
|
||||
// This relies on our own oracle_platform implementation, and the fact that
|
||||
// we used 3 times larger capacity for strings on oracle for unicode strings
|
||||
// as on other platforms. This is not the case with varchar_ci, which uses
|
||||
// the same length as other platforms.
|
||||
if ($platform->getName() === 'oracle')
|
||||
{
|
||||
return $platform->getAsciiStringTypeDeclarationSQL($column);
|
||||
}
|
||||
|
||||
return $platform->getVarcharTypeDeclarationSQL($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return self::CASE_INSENSITIVE_STRING;
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ namespace phpbb\db\doctrine;
|
|||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use InvalidArgumentException;
|
||||
use phpbb\config_php_file;
|
||||
use phpbb\exception\runtime_exception;
|
||||
|
@ -25,8 +26,6 @@ use phpbb\exception\runtime_exception;
|
|||
*/
|
||||
class connection_factory
|
||||
{
|
||||
use driver_convertor;
|
||||
|
||||
/**
|
||||
* Creates a Doctrine DBAL connection from phpBB configuration.
|
||||
*
|
||||
|
@ -97,7 +96,10 @@ class connection_factory
|
|||
|
||||
try
|
||||
{
|
||||
return DriverManager::getConnection($params);
|
||||
$connection = DriverManager::getConnection($params);
|
||||
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)
|
||||
{
|
||||
|
@ -105,6 +107,52 @@ class connection_factory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts phpBB driver names to Doctrine's equivalent.
|
||||
*
|
||||
* @param string $driver_name phpBB database driver name.
|
||||
*
|
||||
* @return string Doctrine DBAL's driver name.
|
||||
*
|
||||
* @throws InvalidArgumentException If $driver_name is not a valid phpBB database driver.
|
||||
*/
|
||||
private static function to_doctrine_driver(string $driver_name): string
|
||||
{
|
||||
// Normalize driver name.
|
||||
$name = str_replace('phpbb\db\driver', '', $driver_name);
|
||||
$name = preg_replace('/mysql$/i', 'mysqli', $name);
|
||||
$name = trim($name, '\\');
|
||||
|
||||
switch ($name)
|
||||
{
|
||||
case 'mssql_odbc':
|
||||
case 'mssqlnative':
|
||||
$name = 'pdo_sqlsrv';
|
||||
break;
|
||||
|
||||
case 'mysqli':
|
||||
$name = 'pdo_mysql';
|
||||
break;
|
||||
|
||||
case 'oracle':
|
||||
$name = 'oci8';
|
||||
break;
|
||||
|
||||
case 'postgres':
|
||||
$name = 'pdo_pgsql';
|
||||
break;
|
||||
|
||||
case 'sqlite3':
|
||||
$name = 'pdo_sqlite';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Invalid phpBB database driver provided: ' . $driver_name);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable constructor.
|
||||
*/
|
||||
|
|
|
@ -151,6 +151,7 @@ class connection_parameter_factory
|
|||
],
|
||||
'oci8' => [
|
||||
'charset' => 'UTF8',
|
||||
'platform' => new oracle_platform(),
|
||||
],
|
||||
'pdo_pgsql' => [
|
||||
'charset' => 'UTF8',
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\doctrine;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Driver convertor utility for Doctrine DBAL.
|
||||
*/
|
||||
trait driver_convertor
|
||||
{
|
||||
/**
|
||||
* Converts phpBB driver names to Doctrine's equivalent.
|
||||
*
|
||||
* @param string $driver_name phpBB database driver name.
|
||||
*
|
||||
* @return string Doctrine DBAL's driver name.
|
||||
*
|
||||
* @throws InvalidArgumentException If $driver_name is not a valid phpBB database driver.
|
||||
*/
|
||||
public static function to_doctrine_driver(string $driver_name) : string
|
||||
{
|
||||
// Normalize driver name.
|
||||
$name = str_replace('phpbb\db\driver', '', $driver_name);
|
||||
$name = preg_replace('/mysql$/i', 'mysqli', $name);
|
||||
$name = trim($name, '\\');
|
||||
|
||||
switch ($name)
|
||||
{
|
||||
case 'mssql_odbc':
|
||||
case 'mssqlnative':
|
||||
$name = 'pdo_sqlsrv';
|
||||
break;
|
||||
|
||||
case 'mysqli':
|
||||
$name = 'pdo_mysql';
|
||||
break;
|
||||
|
||||
case 'oracle':
|
||||
$name = 'oci8';
|
||||
break;
|
||||
|
||||
case 'postgres':
|
||||
$name = 'pdo_pgsql';
|
||||
break;
|
||||
|
||||
case 'sqlite3':
|
||||
$name = 'pdo_sqlite';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Invalid phpBB database driver provided: ' . $driver_name);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
43
phpBB/phpbb/db/doctrine/oracle_platform.php
Normal file
43
phpBB/phpbb/db/doctrine/oracle_platform.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\doctrine;
|
||||
|
||||
use Doctrine\DBAL\Platforms\OraclePlatform;
|
||||
|
||||
/**
|
||||
* Oracle specific schema restrictions for BC.
|
||||
*/
|
||||
class oracle_platform extends OraclePlatform
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getVarcharTypeDeclarationSQL(array $column): string
|
||||
{
|
||||
if (array_key_exists('length', $column) && is_int($column['length']))
|
||||
{
|
||||
$column['length'] *= 3;
|
||||
}
|
||||
|
||||
return parent::getVarcharTypeDeclarationSQL($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAsciiStringTypeDeclarationSQL(array $column): string
|
||||
{
|
||||
return parent::getVarcharTypeDeclarationSQL($column);
|
||||
}
|
||||
}
|
122
phpBB/phpbb/db/doctrine/table_helper.php
Normal file
122
phpBB/phpbb/db/doctrine/table_helper.php
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\doctrine;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class table_helper
|
||||
{
|
||||
/**
|
||||
* Converts phpBB's column representation to Doctrine's representation.
|
||||
*
|
||||
* @param array $column_data Column data.
|
||||
*
|
||||
* @return array<string, array> A pair of type and array of column options.
|
||||
*/
|
||||
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]);
|
||||
$options = array_merge($options, $opts);
|
||||
return [$type, $options];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve DBMS specific options in column data.
|
||||
*
|
||||
* @param array $column_data Original column data.
|
||||
* @param string $dbms_layer DBMS layer name.
|
||||
*
|
||||
* @return array Doctrine column options.
|
||||
*/
|
||||
private static function resolve_dbms_specific_options(array $column_data, string $dbms_layer): array
|
||||
{
|
||||
$doctrine_options = [];
|
||||
|
||||
if (is_array($column_data[1]))
|
||||
{
|
||||
$column_data[1] = self::get_default_column_option($column_data[1], $dbms_layer);
|
||||
}
|
||||
|
||||
if (!is_null($column_data[1]))
|
||||
{
|
||||
$doctrine_options['default'] = $column_data[1];
|
||||
$doctrine_options['notnull'] = true;
|
||||
}
|
||||
|
||||
$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'] === '')
|
||||
{
|
||||
unset($doctrine_options['notnull']);
|
||||
}
|
||||
|
||||
if (isset($column_data[2]))
|
||||
{
|
||||
if ($column_data[2] === 'auto_increment')
|
||||
{
|
||||
$doctrine_options['autoincrement'] = true;
|
||||
}
|
||||
elseif ($dbms_layer === 'mysql' && $column_data[2] === 'true_sort')
|
||||
{
|
||||
$doctrine_options['platformoptions']['collation'] = 'utf8_unicode_ci';
|
||||
}
|
||||
}
|
||||
|
||||
return $doctrine_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return mixed Default value for the current DBMS.
|
||||
*
|
||||
* @throws InvalidArgumentException When `$schema_name` contains an invalid legacy DBMS name.
|
||||
*/
|
||||
private static function get_default_column_option(array $default_options, string $dbms_layer)
|
||||
{
|
||||
switch ($dbms_layer)
|
||||
{
|
||||
case 'mysql':
|
||||
return array_key_exists('mysql_41', $default_options)
|
||||
? $default_options['mysql_41']
|
||||
: $default_options['default'];
|
||||
case 'oracle':
|
||||
return array_key_exists('oracle', $default_options)
|
||||
? $default_options['oracle']
|
||||
: $default_options['default'];
|
||||
case 'postgresql':
|
||||
return array_key_exists('postgres', $default_options)
|
||||
? $default_options['postgres']
|
||||
: $default_options['default'];
|
||||
case 'mssql':
|
||||
return array_key_exists('mssqlnative', $default_options)
|
||||
? $default_options['mssqlnative']
|
||||
: (array_key_exists('mssql', $default_options) ? $default_options['mssql'] : $default_options['default']);
|
||||
case 'sqlite':
|
||||
return array_key_exists('sqlite3', $default_options)
|
||||
? $default_options['sqlite3']
|
||||
: $default_options['default'];
|
||||
default:
|
||||
throw new InvalidArgumentException('Invalid schema name.');
|
||||
}
|
||||
}
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
}
|
120
phpBB/phpbb/db/doctrine/type_converter.php
Normal file
120
phpBB/phpbb/db/doctrine/type_converter.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\doctrine;
|
||||
|
||||
/**
|
||||
* Map phpBB's database types to Doctrine's portable types.
|
||||
*/
|
||||
class type_converter
|
||||
{
|
||||
/**
|
||||
* Type map.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private const TYPE_MAP = [
|
||||
'BINT' => ['bigint', []],
|
||||
'ULINT' => ['integer', ['unsigned' => true]],
|
||||
'UINT' => ['integer', ['unsigned' => true]],
|
||||
'TINT' => ['smallint', []],
|
||||
'USINT' => ['smallint', ['unsigned' => true]],
|
||||
'BOOL' => ['boolean', ['unsigned' => true]],
|
||||
'VCHAR' => ['string', ['length' => 255]],
|
||||
'CHAR' => ['ascii_string', []],
|
||||
'XSTEXT' => ['ascii_string', ['length' => 1000]],
|
||||
'XSTEXT_UNI'=> ['string', ['length' => 100]],
|
||||
'STEXT' => ['ascii_string', ['length' => 3000]],
|
||||
'STEXT_UNI' => ['string', ['length' => 255]],
|
||||
'TEXT' => ['text', ['length' => ((1 << 16) - 1)]],
|
||||
'TEXT_UNI' => ['text', ['length' => ((1 << 16) - 1)]],
|
||||
'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]],
|
||||
'VCHAR_UNI' => ['string', ['length' => 255]],
|
||||
'VCHAR_CI' => ['string_ci', ['length' => 255]],
|
||||
'VARBINARY' => ['binary', ['length' => 255]],
|
||||
];
|
||||
|
||||
/**
|
||||
* Convert legacy type to Doctrine's type system.
|
||||
*
|
||||
* @param string $type Legacy type name
|
||||
*
|
||||
* @return array<string, array> Pair of type name and options.
|
||||
*/
|
||||
public static function convert(string $type): array
|
||||
{
|
||||
if (strpos($type, ':') !== false)
|
||||
{
|
||||
list($typename, $length) = explode(':', $type);
|
||||
return self::mapWithLength($typename, (int) $length);
|
||||
}
|
||||
|
||||
return self::mapType($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map legacy types with length attribute.
|
||||
*
|
||||
* @param string $type Legacy type name.
|
||||
* @param int $length Type length.
|
||||
*
|
||||
* @return array<string, array> Pair of type name and options.
|
||||
*/
|
||||
private static function mapWithLength(string $type, int $length): array
|
||||
{
|
||||
switch ($type)
|
||||
{
|
||||
case 'UINT':
|
||||
case 'INT':
|
||||
case 'TINT':
|
||||
return self::TYPE_MAP[$type];
|
||||
|
||||
case 'DECIMAL':
|
||||
case 'PDECIMAL':
|
||||
$pair = self::TYPE_MAP[$type];
|
||||
$pair[1]['precision'] = $length;
|
||||
return $pair;
|
||||
|
||||
case 'VCHAR':
|
||||
case 'CHAR':
|
||||
case 'VCHAR_UNI':
|
||||
$pair = self::TYPE_MAP[$type];
|
||||
$pair[1]['length'] = $length;
|
||||
return $pair;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Database type is undefined.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map phpBB's legacy database types to Doctrine types.
|
||||
*
|
||||
* @param string $type Type name.
|
||||
*
|
||||
* @return array<string, array> Pair of type name and an array of options.
|
||||
*/
|
||||
private static function mapType(string $type): array
|
||||
{
|
||||
if (!in_array($type, self::TYPE_MAP, true))
|
||||
{
|
||||
throw new \InvalidArgumentException("Database type is undefined.");
|
||||
}
|
||||
|
||||
return self::TYPE_MAP[$type];
|
||||
}
|
||||
}
|
439
phpBB/phpbb/db/tools/doctrine.php
Normal file
439
phpBB/phpbb/db/tools/doctrine.php
Normal file
|
@ -0,0 +1,439 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace phpbb\db\tools;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Schema\AbstractAsset;
|
||||
use Doctrine\DBAL\Schema\Comparator;
|
||||
use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use phpbb\db\doctrine\table_helper;
|
||||
|
||||
/**
|
||||
* BC layer for database tools.
|
||||
*
|
||||
* In general, it is recommended to use Doctrine directly instead of this class as this
|
||||
* implementation is only a BC layer.
|
||||
*
|
||||
* In the 3.3.x version branch this class could return SQL statements instead of
|
||||
* performing changes. This functionality has been removed.
|
||||
*/
|
||||
class doctrine implements tools_interface
|
||||
{
|
||||
/**
|
||||
* @var Comparator
|
||||
*/
|
||||
private $comparator;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\DBAL\Schema\AbstractSchemaManager
|
||||
*/
|
||||
private $schema_manager;
|
||||
|
||||
/**
|
||||
* Database tools constructors.
|
||||
*
|
||||
* @param Connection $connection
|
||||
*
|
||||
* @throws Exception If the schema manager cannot be created.
|
||||
*/
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
$this->comparator = new Comparator();
|
||||
$this->schema_manager = $connection->createSchemaManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function perform_schema_changes(array $schema_changes): void
|
||||
{
|
||||
// @todo
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_list_tables(): array
|
||||
{
|
||||
try
|
||||
{
|
||||
return array_map('strtolower', $this->schema_manager->listTableNames());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_table_exists(string $table_name): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->schema_manager->tablesExist([$table_name]);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_create_table(string $table_name, array $table_data): bool
|
||||
{
|
||||
if ($this->sql_table_exists($table_name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$table = new Table($table_name);
|
||||
$dbms_name = $this->schema_manager->getDatabasePlatform()->getName();
|
||||
|
||||
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
|
||||
{
|
||||
list($type, $options) = table_helper::convert_column_data(
|
||||
$column_data,
|
||||
$dbms_name
|
||||
);
|
||||
$table->addColumn($column_name, $type, $options);
|
||||
}
|
||||
|
||||
$table_data['PRIMARY_KEY'] = (!is_array($table_data['PRIMARY_KEY']))
|
||||
? [$table_data['PRIMARY_KEY']]
|
||||
: $table_data['PRIMARY_KEY'];
|
||||
|
||||
$table->setPrimaryKey($table_data['PRIMARY_KEY']);
|
||||
|
||||
if (array_key_exists('KEYS', $table_data))
|
||||
{
|
||||
foreach ($table_data['KEYS'] as $key_name => $key_data)
|
||||
{
|
||||
$columns = (is_array($key_data[1])) ? $key_data[1] : [$key_data[1]];
|
||||
if ($key_data[0] === 'UNIQUE')
|
||||
{
|
||||
$table->addUniqueIndex($columns, $key_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->addIndex($columns, $key_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($dbms_name)
|
||||
{
|
||||
case 'mysql':
|
||||
$table->addOption('collate', 'utf8_bin');
|
||||
break;
|
||||
}
|
||||
|
||||
$this->schema_manager->createTable($table);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_table_drop(string $table_name): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->schema_manager->dropTable($table_name);
|
||||
return true;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_list_columns(string $table_name): array
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->get_asset_names($this->schema_manager->listTableColumns($table_name));
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_column_exists(string $table_name, string $column_name): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->asset_exists($column_name, $this->schema_manager->listTableColumns($table_name));
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_column_add(string $table_name, string $column_name, array $column_data): bool
|
||||
{
|
||||
$dbms_name = $this->schema_manager->getDatabasePlatform()->getName();
|
||||
return $this->alter_table(
|
||||
$table_name,
|
||||
function (Table $table) use ($column_name, $column_data, $dbms_name) {
|
||||
list($type, $options) = table_helper::convert_column_data($column_data, $dbms_name);
|
||||
return $table->addColumn($column_name, $type, $options);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_column_change(string $table_name, string $column_name, array $column_data): bool
|
||||
{
|
||||
// @todo: index handling.
|
||||
return $this->alter_table(
|
||||
$table_name,
|
||||
function (Table $table) use ($column_name, $column_data) {
|
||||
// @todo type maps to options['type']
|
||||
//$table->dropColumn($column_name);
|
||||
//list($type, $options) = table_helper::convert_column_data($column_data);
|
||||
//return $table->addColumn($column_name, $type, $options);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_column_remove(string $table_name, string $column_name): bool
|
||||
{
|
||||
// @todo: index handling.
|
||||
return $this->alter_table(
|
||||
$table_name,
|
||||
function (Table $table) use ($column_name) {
|
||||
return $table->dropColumn($column_name);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_list_index(string $table_name): array
|
||||
{
|
||||
return $this->get_asset_names($this->get_filtered_index_list($table_name, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_index_exists(string $table_name, string $index_name): bool
|
||||
{
|
||||
return $this->asset_exists($index_name, $this->get_filtered_index_list($table_name, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_create_index(string $table_name, string $index_name, $column): bool
|
||||
{
|
||||
$column = (is_array($column)) ? $column : [$column];
|
||||
$index = new Index($index_name, $column);
|
||||
try
|
||||
{
|
||||
$this->schema_manager->createIndex($index, $table_name);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_index_drop(string $table_name, string $index_name): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->schema_manager->dropIndex($index_name, $table_name);
|
||||
return true;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_unique_index_exists(string $table_name, string $index_name): bool
|
||||
{
|
||||
return $this->asset_exists($index_name, $this->get_filtered_index_list($table_name, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_create_unique_index(string $table_name, string $index_name, $column): bool
|
||||
{
|
||||
$column = (is_array($column)) ? $column : [$column];
|
||||
$index = new Index($index_name, $column, true);
|
||||
try
|
||||
{
|
||||
$this->schema_manager->createIndex($index, $table_name);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sql_create_primary_key(string $table_name, $column): bool
|
||||
{
|
||||
$column = (is_array($column)) ? $column : [$column];
|
||||
$index = new Index('primary', $column, true, true);
|
||||
try
|
||||
{
|
||||
$this->schema_manager->createIndex($index, $table_name);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of indices for either unique and primary keys, or simple indices.
|
||||
*
|
||||
* @param string $table_name The name of the table.
|
||||
* @param bool $is_non_unique Whether to return simple indices or primary and unique ones.
|
||||
*
|
||||
* @return array The filtered index array.
|
||||
*/
|
||||
private function get_filtered_index_list(string $table_name, bool $is_non_unique): array
|
||||
{
|
||||
try
|
||||
{
|
||||
$indices = $this->schema_manager->listTableIndexes($table_name);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($is_non_unique)
|
||||
{
|
||||
return array_filter($indices, function(Index $index) {
|
||||
return $index->isSimpleIndex();
|
||||
});
|
||||
}
|
||||
|
||||
return array_filter($indices, function(Index $index) {
|
||||
return !$index->isSimpleIndex();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of lowercase asset names.
|
||||
*
|
||||
* @param array $assets Array of assets.
|
||||
*
|
||||
* @return array An array of lowercase asset names.
|
||||
*/
|
||||
private function get_asset_names(array $assets): array
|
||||
{
|
||||
return array_map(
|
||||
function(AbstractAsset $asset) {
|
||||
return strtolower($asset->getName());
|
||||
},
|
||||
$assets
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether an asset name exists in a list of assets (case insensitive).
|
||||
*
|
||||
* @param string $needle The asset name to search for.
|
||||
* @param array $assets The array of assets.
|
||||
*
|
||||
* @return bool Whether the asset name exists in a list of assets.
|
||||
*/
|
||||
private function asset_exists(string $needle, array $assets): bool
|
||||
{
|
||||
return in_array(strtolower($needle), $this->get_asset_names($assets), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter table.
|
||||
*
|
||||
* @param string $table_name Table name.
|
||||
* @param callable $callback Callback function to modify the table.
|
||||
*
|
||||
* @return bool True if the changes were applied successfully, false otherwise.
|
||||
*/
|
||||
private function alter_table(string $table_name, callable $callback): bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$table = $this->schema_manager->listTableDetails($table_name);
|
||||
$altered_table = clone $table;
|
||||
$altered_table = call_user_func($callback, $altered_table);
|
||||
$diff = $this->comparator->diffTable($table, $altered_table);
|
||||
if ($diff === false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->schema_manager->alterTable($diff);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ class factory
|
|||
*/
|
||||
public function get($db_driver, $return_statements = false)
|
||||
{
|
||||
// @todo: only create the doctrine tools object.
|
||||
if ($db_driver instanceof \phpbb\db\driver\mssql_base)
|
||||
{
|
||||
return new \phpbb\db\tools\mssql($db_driver, $return_statements);
|
||||
|
|
|
@ -16,865 +16,9 @@ namespace phpbb\db\tools;
|
|||
/**
|
||||
* Database Tools for handling cross-db actions such as altering columns, etc.
|
||||
* Currently not supported is returning SQL for creating tables.
|
||||
*
|
||||
* @deprecated 4.0.0-a1
|
||||
*/
|
||||
class mssql extends tools
|
||||
{
|
||||
/**
|
||||
* Is the used MS SQL Server a SQL Server 2000?
|
||||
* @var bool
|
||||
*/
|
||||
protected $is_sql_server_2000;
|
||||
|
||||
/**
|
||||
* Get the column types for mssql based databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_dbms_type_map()
|
||||
{
|
||||
return array(
|
||||
'mssql' => array(
|
||||
'INT:' => '[int]',
|
||||
'BINT' => '[float]',
|
||||
'ULINT' => '[int]',
|
||||
'UINT' => '[int]',
|
||||
'UINT:' => '[int]',
|
||||
'TINT:' => '[int]',
|
||||
'USINT' => '[int]',
|
||||
'BOOL' => '[int]',
|
||||
'VCHAR' => '[varchar] (255)',
|
||||
'VCHAR:' => '[varchar] (%d)',
|
||||
'CHAR:' => '[char] (%d)',
|
||||
'XSTEXT' => '[varchar] (1000)',
|
||||
'STEXT' => '[varchar] (3000)',
|
||||
'TEXT' => '[varchar] (8000)',
|
||||
'MTEXT' => '[text]',
|
||||
'XSTEXT_UNI'=> '[nvarchar] (100)',
|
||||
'STEXT_UNI' => '[nvarchar] (255)',
|
||||
'TEXT_UNI' => '[nvarchar] (4000)',
|
||||
'MTEXT_UNI' => '[ntext]',
|
||||
'TIMESTAMP' => '[int]',
|
||||
'DECIMAL' => '[float]',
|
||||
'DECIMAL:' => '[float]',
|
||||
'PDECIMAL' => '[float]',
|
||||
'PDECIMAL:' => '[float]',
|
||||
'VCHAR_UNI' => '[nvarchar] (255)',
|
||||
'VCHAR_UNI:'=> '[nvarchar] (%d)',
|
||||
'VCHAR_CI' => '[nvarchar] (255)',
|
||||
'VARBINARY' => '[varchar] (255)',
|
||||
),
|
||||
|
||||
'mssqlnative' => array(
|
||||
'INT:' => '[int]',
|
||||
'BINT' => '[float]',
|
||||
'ULINT' => '[int]',
|
||||
'UINT' => '[int]',
|
||||
'UINT:' => '[int]',
|
||||
'TINT:' => '[int]',
|
||||
'USINT' => '[int]',
|
||||
'BOOL' => '[int]',
|
||||
'VCHAR' => '[varchar] (255)',
|
||||
'VCHAR:' => '[varchar] (%d)',
|
||||
'CHAR:' => '[char] (%d)',
|
||||
'XSTEXT' => '[varchar] (1000)',
|
||||
'STEXT' => '[varchar] (3000)',
|
||||
'TEXT' => '[varchar] (8000)',
|
||||
'MTEXT' => '[text]',
|
||||
'XSTEXT_UNI'=> '[nvarchar] (100)',
|
||||
'STEXT_UNI' => '[nvarchar] (255)',
|
||||
'TEXT_UNI' => '[nvarchar] (4000)',
|
||||
'MTEXT_UNI' => '[ntext]',
|
||||
'TIMESTAMP' => '[int]',
|
||||
'DECIMAL' => '[float]',
|
||||
'DECIMAL:' => '[float]',
|
||||
'PDECIMAL' => '[float]',
|
||||
'PDECIMAL:' => '[float]',
|
||||
'VCHAR_UNI' => '[nvarchar] (255)',
|
||||
'VCHAR_UNI:'=> '[nvarchar] (%d)',
|
||||
'VCHAR_CI' => '[nvarchar] (255)',
|
||||
'VARBINARY' => '[varchar] (255)',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Set DB Object and set {@link $return_statements return_statements}.
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db Database connection
|
||||
* @param bool $return_statements True if only statements should be returned and no SQL being executed
|
||||
*/
|
||||
public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
|
||||
{
|
||||
parent::__construct($db, $return_statements);
|
||||
|
||||
// Determine mapping database type
|
||||
switch ($this->db->get_sql_layer())
|
||||
{
|
||||
case 'mssql_odbc':
|
||||
$this->sql_layer = 'mssql';
|
||||
break;
|
||||
|
||||
case 'mssqlnative':
|
||||
$this->sql_layer = 'mssqlnative';
|
||||
break;
|
||||
}
|
||||
|
||||
$this->dbms_type_map = self::get_dbms_type_map();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_list_tables()
|
||||
{
|
||||
$sql = "SELECT name
|
||||
FROM sysobjects
|
||||
WHERE type='U'";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
$tables = array();
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$name = current($row);
|
||||
$tables[$name] = $name;
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_table($table_name, $table_data)
|
||||
{
|
||||
// holds the DDL for a column
|
||||
$columns = $statements = array();
|
||||
|
||||
if ($this->sql_table_exists($table_name))
|
||||
{
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
// Begin transaction
|
||||
$statements[] = 'begin';
|
||||
|
||||
// Determine if we have created a PRIMARY KEY in the earliest
|
||||
$primary_key_gen = false;
|
||||
|
||||
// Determine if the table requires a sequence
|
||||
$create_sequence = false;
|
||||
|
||||
// Begin table sql statement
|
||||
$table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n";
|
||||
|
||||
if (!isset($table_data['PRIMARY_KEY']))
|
||||
{
|
||||
$table_data['COLUMNS']['mssqlindex'] = array('UINT', null, 'auto_increment');
|
||||
$table_data['PRIMARY_KEY'] = 'mssqlindex';
|
||||
}
|
||||
|
||||
// Iterate through the columns to create a table
|
||||
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
|
||||
{
|
||||
// here lies an array, filled with information compiled on the column's data
|
||||
$prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
|
||||
|
||||
if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
|
||||
{
|
||||
trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// here we add the definition of the new column to the list of columns
|
||||
$columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default'];
|
||||
|
||||
// see if we have found a primary key set due to a column definition if we have found it, we can stop looking
|
||||
if (!$primary_key_gen)
|
||||
{
|
||||
$primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
|
||||
}
|
||||
|
||||
// create sequence DDL based off of the existence of auto incrementing columns
|
||||
if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
|
||||
{
|
||||
$create_sequence = $column_name;
|
||||
}
|
||||
}
|
||||
|
||||
// this makes up all the columns in the create table statement
|
||||
$table_sql .= implode(",\n", $columns);
|
||||
|
||||
// Close the table for two DBMS and add to the statements
|
||||
$table_sql .= "\n);";
|
||||
$statements[] = $table_sql;
|
||||
|
||||
// we have yet to create a primary key for this table,
|
||||
// this means that we can add the one we really wanted instead
|
||||
if (!$primary_key_gen)
|
||||
{
|
||||
// Write primary key
|
||||
if (isset($table_data['PRIMARY_KEY']))
|
||||
{
|
||||
if (!is_array($table_data['PRIMARY_KEY']))
|
||||
{
|
||||
$table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
|
||||
}
|
||||
|
||||
// We need the data here
|
||||
$old_return_statements = $this->return_statements;
|
||||
$this->return_statements = true;
|
||||
|
||||
$primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']);
|
||||
foreach ($primary_key_stmts as $pk_stmt)
|
||||
{
|
||||
$statements[] = $pk_stmt;
|
||||
}
|
||||
|
||||
$this->return_statements = $old_return_statements;
|
||||
}
|
||||
}
|
||||
|
||||
// Write Keys
|
||||
if (isset($table_data['KEYS']))
|
||||
{
|
||||
foreach ($table_data['KEYS'] as $key_name => $key_data)
|
||||
{
|
||||
if (!is_array($key_data[1]))
|
||||
{
|
||||
$key_data[1] = array($key_data[1]);
|
||||
}
|
||||
|
||||
$old_return_statements = $this->return_statements;
|
||||
$this->return_statements = true;
|
||||
|
||||
$key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
|
||||
|
||||
foreach ($key_stmts as $key_stmt)
|
||||
{
|
||||
$statements[] = $key_stmt;
|
||||
}
|
||||
|
||||
$this->return_statements = $old_return_statements;
|
||||
}
|
||||
}
|
||||
|
||||
// Commit Transaction
|
||||
$statements[] = 'commit';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_list_columns($table_name)
|
||||
{
|
||||
$columns = array();
|
||||
|
||||
$sql = "SELECT c.name
|
||||
FROM syscolumns c
|
||||
LEFT JOIN sysobjects o ON c.id = o.id
|
||||
WHERE o.name = '{$table_name}'";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$column = strtolower(current($row));
|
||||
$columns[$column] = $column;
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_index_exists($table_name, $index_name)
|
||||
{
|
||||
$sql = "EXEC sp_statistics '$table_name'";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
if ($row['TYPE'] == 3)
|
||||
{
|
||||
if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
|
||||
{
|
||||
$this->db->sql_freeresult($result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_unique_index_exists($table_name, $index_name)
|
||||
{
|
||||
$sql = "EXEC sp_statistics '$table_name'";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
// Usually NON_UNIQUE is the column we want to check, but we allow for both
|
||||
if ($row['TYPE'] == 3)
|
||||
{
|
||||
if (strtolower($row['INDEX_NAME']) == strtolower($index_name))
|
||||
{
|
||||
$this->db->sql_freeresult($result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_prepare_column_data($table_name, $column_name, $column_data)
|
||||
{
|
||||
if (strlen($column_name) > 30)
|
||||
{
|
||||
trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// Get type
|
||||
list($column_type, ) = $this->get_column_type($column_data[0]);
|
||||
|
||||
// Adjust default value if db-dependent specified
|
||||
if (is_array($column_data[1]))
|
||||
{
|
||||
$column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
|
||||
}
|
||||
|
||||
$sql = '';
|
||||
|
||||
$return_array = array();
|
||||
|
||||
$sql .= " {$column_type} ";
|
||||
$sql_default = " {$column_type} ";
|
||||
|
||||
// For adding columns we need the default definition
|
||||
if (!is_null($column_data[1]))
|
||||
{
|
||||
// For hexadecimal values do not use single quotes
|
||||
if (strpos($column_data[1], '0x') === 0)
|
||||
{
|
||||
$return_array['default'] = 'DEFAULT (' . $column_data[1] . ') ';
|
||||
$sql_default .= $return_array['default'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
|
||||
$sql_default .= $return_array['default'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
|
||||
{
|
||||
// $sql .= 'IDENTITY (1, 1) ';
|
||||
$sql_default .= 'IDENTITY (1, 1) ';
|
||||
}
|
||||
|
||||
$return_array['textimage'] = $column_type === '[text]';
|
||||
|
||||
if (!is_null($column_data[1]) || (isset($column_data[2]) && $column_data[2] == 'auto_increment'))
|
||||
{
|
||||
$sql .= 'NOT NULL';
|
||||
$sql_default .= 'NOT NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql .= 'NULL';
|
||||
$sql_default .= 'NULL';
|
||||
}
|
||||
|
||||
$return_array['column_type_sql_default'] = $sql_default;
|
||||
|
||||
$return_array['column_type_sql'] = $sql;
|
||||
|
||||
return $return_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_column_add($table_name, $column_name, $column_data, $inline = false)
|
||||
{
|
||||
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
|
||||
$statements = array();
|
||||
|
||||
// Does not support AFTER, only through temporary table
|
||||
$statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_column_remove($table_name, $column_name, $inline = false)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
// We need the data here
|
||||
$old_return_statements = $this->return_statements;
|
||||
$this->return_statements = true;
|
||||
|
||||
$indexes = $this->get_existing_indexes($table_name, $column_name);
|
||||
$indexes = array_merge($indexes, $this->get_existing_indexes($table_name, $column_name, true));
|
||||
|
||||
// Drop any indexes
|
||||
$recreate_indexes = array();
|
||||
if (!empty($indexes))
|
||||
{
|
||||
foreach ($indexes as $index_name => $index_data)
|
||||
{
|
||||
$result = $this->sql_index_drop($table_name, $index_name);
|
||||
$statements = array_merge($statements, $result);
|
||||
if (count($index_data) > 1)
|
||||
{
|
||||
// Remove this column from the index and recreate it
|
||||
$recreate_indexes[$index_name] = array_diff($index_data, array($column_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop primary keys depending on this column
|
||||
$result = $this->mssql_get_drop_default_primary_key_queries($table_name, $column_name);
|
||||
$statements = array_merge($statements, $result);
|
||||
|
||||
// Drop default value constraint
|
||||
$result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
|
||||
$statements = array_merge($statements, $result);
|
||||
|
||||
// Remove the column
|
||||
$statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
|
||||
|
||||
if (!empty($recreate_indexes))
|
||||
{
|
||||
// Recreate indexes after we removed the column
|
||||
foreach ($recreate_indexes as $index_name => $index_data)
|
||||
{
|
||||
$result = $this->sql_create_index($table_name, $index_name, $index_data);
|
||||
$statements = array_merge($statements, $result);
|
||||
}
|
||||
}
|
||||
|
||||
$this->return_statements = $old_return_statements;
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_index_drop($table_name, $index_name)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$statements[] = 'DROP INDEX [' . $table_name . '].[' . $index_name . ']';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_table_drop($table_name)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
if (!$this->sql_table_exists($table_name))
|
||||
{
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
// the most basic operation, get rid of the table
|
||||
$statements[] = 'DROP TABLE ' . $table_name;
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_primary_key($table_name, $column, $inline = false)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
|
||||
$sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
|
||||
$sql .= '[' . implode("],\n\t\t[", $column) . ']';
|
||||
$sql .= ')';
|
||||
|
||||
$statements[] = $sql;
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_unique_index($table_name, $index_name, $column)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
if ($this->mssql_is_sql_server_2000())
|
||||
{
|
||||
$this->check_index_name_length($table_name, $index_name);
|
||||
}
|
||||
|
||||
$statements[] = 'CREATE UNIQUE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_index($table_name, $index_name, $column)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$this->check_index_name_length($table_name, $index_name);
|
||||
|
||||
// remove index length
|
||||
$column = preg_replace('#:.*$#', '', $column);
|
||||
|
||||
$statements[] = 'CREATE INDEX [' . $index_name . '] ON [' . $table_name . ']([' . implode('], [', $column) . '])';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function get_max_index_name_length()
|
||||
{
|
||||
if ($this->mssql_is_sql_server_2000())
|
||||
{
|
||||
return parent::get_max_index_name_length();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_list_index($table_name)
|
||||
{
|
||||
$index_array = array();
|
||||
$sql = "EXEC sp_statistics '$table_name'";
|
||||
$result = $this->db->sql_query($sql);
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
if ($row['TYPE'] == 3)
|
||||
{
|
||||
$index_array[] = strtolower($row['INDEX_NAME']);
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $index_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_column_change($table_name, $column_name, $column_data, $inline = false)
|
||||
{
|
||||
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
|
||||
$statements = array();
|
||||
|
||||
// We need the data here
|
||||
$old_return_statements = $this->return_statements;
|
||||
$this->return_statements = true;
|
||||
|
||||
$indexes = $this->get_existing_indexes($table_name, $column_name);
|
||||
$unique_indexes = $this->get_existing_indexes($table_name, $column_name, true);
|
||||
|
||||
// Drop any indexes
|
||||
if (!empty($indexes) || !empty($unique_indexes))
|
||||
{
|
||||
$drop_indexes = array_merge(array_keys($indexes), array_keys($unique_indexes));
|
||||
foreach ($drop_indexes as $index_name)
|
||||
{
|
||||
$result = $this->sql_index_drop($table_name, $index_name);
|
||||
$statements = array_merge($statements, $result);
|
||||
}
|
||||
}
|
||||
|
||||
// Drop default value constraint
|
||||
$result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name);
|
||||
$statements = array_merge($statements, $result);
|
||||
|
||||
// Change the column
|
||||
$statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
|
||||
|
||||
if (!empty($column_data['default']) && !$this->mssql_is_column_identity($table_name, $column_name))
|
||||
{
|
||||
// Add new default value constraint
|
||||
$statements[] = 'ALTER TABLE [' . $table_name . '] ADD CONSTRAINT [DF_' . $table_name . '_' . $column_name . '_1] ' . $column_data['default'] . ' FOR [' . $column_name . ']';
|
||||
}
|
||||
|
||||
if (!empty($indexes))
|
||||
{
|
||||
// Recreate indexes after we changed the column
|
||||
foreach ($indexes as $index_name => $index_data)
|
||||
{
|
||||
$result = $this->sql_create_index($table_name, $index_name, $index_data);
|
||||
$statements = array_merge($statements, $result);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($unique_indexes))
|
||||
{
|
||||
// Recreate unique indexes after we changed the column
|
||||
foreach ($unique_indexes as $index_name => $index_data)
|
||||
{
|
||||
$result = $this->sql_create_unique_index($table_name, $index_name, $index_data);
|
||||
$statements = array_merge($statements, $result);
|
||||
}
|
||||
}
|
||||
|
||||
$this->return_statements = $old_return_statements;
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queries to drop the default constraints of a column
|
||||
*
|
||||
* We need to drop the default constraints of a column,
|
||||
* before being able to change their type or deleting them.
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $column_name
|
||||
* @return array Array with SQL statements
|
||||
*/
|
||||
protected function mssql_get_drop_default_constraints_queries($table_name, $column_name)
|
||||
{
|
||||
$statements = array();
|
||||
if ($this->mssql_is_sql_server_2000())
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
|
||||
// Deprecated in SQL Server 2005
|
||||
$sql = "SELECT so.name AS def_name
|
||||
FROM sysobjects so
|
||||
JOIN sysconstraints sc ON so.id = sc.constid
|
||||
WHERE object_name(so.parent_obj) = '{$table_name}'
|
||||
AND so.xtype = 'D'
|
||||
AND sc.colid = (SELECT colid FROM syscolumns
|
||||
WHERE id = object_id('{$table_name}')
|
||||
AND name = '{$column_name}')";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = "SELECT dobj.name AS def_name
|
||||
FROM sys.columns col
|
||||
LEFT OUTER JOIN sys.objects dobj ON (dobj.object_id = col.default_object_id AND dobj.type = 'D')
|
||||
WHERE col.object_id = object_id('{$table_name}')
|
||||
AND col.name = '{$column_name}'
|
||||
AND dobj.name IS NOT NULL";
|
||||
}
|
||||
|
||||
$result = $this->db->sql_query($sql);
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $row['def_name'] . ']';
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queries to drop the primary keys depending on the specified column
|
||||
*
|
||||
* We need to drop primary keys depending on this column before being able
|
||||
* to delete them.
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $column_name
|
||||
* @return array Array with SQL statements
|
||||
*/
|
||||
protected function mssql_get_drop_default_primary_key_queries($table_name, $column_name)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$sql = "SELECT ccu.CONSTRAINT_NAME, ccu.COLUMN_NAME
|
||||
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
|
||||
JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu ON tc.CONSTRAINT_NAME = ccu.Constraint_name
|
||||
WHERE tc.TABLE_NAME = '{$table_name}'
|
||||
AND tc.CONSTRAINT_TYPE = 'Primary Key'
|
||||
AND ccu.COLUMN_NAME = '{$column_name}'";
|
||||
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($primary_key = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $primary_key['CONSTRAINT_NAME'] . ']';
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if column is an identity column
|
||||
*
|
||||
* Identity columns cannot have defaults set for them.
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $column_name
|
||||
* @return bool true if identity, false if not
|
||||
*/
|
||||
protected function mssql_is_column_identity($table_name, $column_name)
|
||||
{
|
||||
if ($this->mssql_is_sql_server_2000())
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
|
||||
// Deprecated in SQL Server 2005
|
||||
$sql = "SELECT COLUMNPROPERTY(object_id('{$table_name}'), '{$column_name}', 'IsIdentity') AS is_identity";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = "SELECT is_identity FROM sys.columns
|
||||
WHERE object_id = object_id('{$table_name}')
|
||||
AND name = '{$column_name}'";
|
||||
}
|
||||
|
||||
$result = $this->db->sql_query($sql);
|
||||
$is_identity = $this->db->sql_fetchfield('is_identity');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return (bool) $is_identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list with existing indexes for the column
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $column_name
|
||||
* @param bool $unique Should we get unique indexes or normal ones
|
||||
* @return array Array with Index name => columns
|
||||
*/
|
||||
public function get_existing_indexes($table_name, $column_name, $unique = false)
|
||||
{
|
||||
$existing_indexes = array();
|
||||
if ($this->mssql_is_sql_server_2000())
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
|
||||
// Deprecated in SQL Server 2005
|
||||
$sql = "SELECT DISTINCT ix.name AS phpbb_index_name
|
||||
FROM sysindexes ix
|
||||
INNER JOIN sysindexkeys ixc
|
||||
ON ixc.id = ix.id
|
||||
AND ixc.indid = ix.indid
|
||||
INNER JOIN syscolumns cols
|
||||
ON cols.colid = ixc.colid
|
||||
AND cols.id = ix.id
|
||||
WHERE ix.id = object_id('{$table_name}')
|
||||
AND cols.name = '{$column_name}'
|
||||
AND INDEXPROPERTY(ix.id, ix.name, 'IsUnique') = " . ($unique ? '1' : '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = "SELECT DISTINCT ix.name AS phpbb_index_name
|
||||
FROM sys.indexes ix
|
||||
INNER JOIN sys.index_columns ixc
|
||||
ON ixc.object_id = ix.object_id
|
||||
AND ixc.index_id = ix.index_id
|
||||
INNER JOIN sys.columns cols
|
||||
ON cols.column_id = ixc.column_id
|
||||
AND cols.object_id = ix.object_id
|
||||
WHERE ix.object_id = object_id('{$table_name}')
|
||||
AND cols.name = '{$column_name}'
|
||||
AND ix.is_primary_key = 0
|
||||
AND ix.is_unique = " . ($unique ? '1' : '0');
|
||||
}
|
||||
|
||||
$result = $this->db->sql_query($sql);
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
if (!isset($row['is_unique']) || ($unique && $row['is_unique'] == 'UNIQUE') || (!$unique && $row['is_unique'] == 'NONUNIQUE'))
|
||||
{
|
||||
$existing_indexes[$row['phpbb_index_name']] = array();
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (empty($existing_indexes))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
if ($this->mssql_is_sql_server_2000())
|
||||
{
|
||||
$sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
|
||||
FROM sysindexes ix
|
||||
INNER JOIN sysindexkeys ixc
|
||||
ON ixc.id = ix.id
|
||||
AND ixc.indid = ix.indid
|
||||
INNER JOIN syscolumns cols
|
||||
ON cols.colid = ixc.colid
|
||||
AND cols.id = ix.id
|
||||
WHERE ix.id = object_id('{$table_name}')
|
||||
AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = "SELECT DISTINCT ix.name AS phpbb_index_name, cols.name AS phpbb_column_name
|
||||
FROM sys.indexes ix
|
||||
INNER JOIN sys.index_columns ixc
|
||||
ON ixc.object_id = ix.object_id
|
||||
AND ixc.index_id = ix.index_id
|
||||
INNER JOIN sys.columns cols
|
||||
ON cols.column_id = ixc.column_id
|
||||
AND cols.object_id = ix.object_id
|
||||
WHERE ix.object_id = object_id('{$table_name}')
|
||||
AND " . $this->db->sql_in_set('ix.name', array_keys($existing_indexes));
|
||||
}
|
||||
|
||||
$result = $this->db->sql_query($sql);
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$existing_indexes[$row['phpbb_index_name']][] = $row['phpbb_column_name'];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $existing_indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the used MS SQL Server a SQL Server 2000?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function mssql_is_sql_server_2000()
|
||||
{
|
||||
if ($this->is_sql_server_2000 === null)
|
||||
{
|
||||
$sql = "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(25)) AS mssql_version";
|
||||
$result = $this->db->sql_query($sql);
|
||||
$properties = $this->db->sql_fetchrow($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
$this->is_sql_server_2000 = $properties['mssql_version'][0] == '8';
|
||||
}
|
||||
|
||||
return $this->is_sql_server_2000;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,617 +16,9 @@ namespace phpbb\db\tools;
|
|||
/**
|
||||
* Database Tools for handling cross-db actions such as altering columns, etc.
|
||||
* Currently not supported is returning SQL for creating tables.
|
||||
*
|
||||
* @deprecated 4.0.0-a1
|
||||
*/
|
||||
class postgres extends tools
|
||||
{
|
||||
/**
|
||||
* Get the column types for postgres only
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_dbms_type_map()
|
||||
{
|
||||
return array(
|
||||
'postgres' => array(
|
||||
'INT:' => 'INT4',
|
||||
'BINT' => 'INT8',
|
||||
'ULINT' => 'INT4', // unsigned
|
||||
'UINT' => 'INT4', // unsigned
|
||||
'UINT:' => 'INT4', // unsigned
|
||||
'USINT' => 'INT2', // unsigned
|
||||
'BOOL' => 'INT2', // unsigned
|
||||
'TINT:' => 'INT2',
|
||||
'VCHAR' => 'varchar(255)',
|
||||
'VCHAR:' => 'varchar(%d)',
|
||||
'CHAR:' => 'char(%d)',
|
||||
'XSTEXT' => 'varchar(1000)',
|
||||
'STEXT' => 'varchar(3000)',
|
||||
'TEXT' => 'varchar(8000)',
|
||||
'MTEXT' => 'TEXT',
|
||||
'XSTEXT_UNI'=> 'varchar(100)',
|
||||
'STEXT_UNI' => 'varchar(255)',
|
||||
'TEXT_UNI' => 'varchar(4000)',
|
||||
'MTEXT_UNI' => 'TEXT',
|
||||
'TIMESTAMP' => 'INT4', // unsigned
|
||||
'DECIMAL' => 'decimal(5,2)',
|
||||
'DECIMAL:' => 'decimal(%d,2)',
|
||||
'PDECIMAL' => 'decimal(6,3)',
|
||||
'PDECIMAL:' => 'decimal(%d,3)',
|
||||
'VCHAR_UNI' => 'varchar(255)',
|
||||
'VCHAR_UNI:'=> 'varchar(%d)',
|
||||
'VCHAR_CI' => 'varchar_ci',
|
||||
'VARBINARY' => 'bytea',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Set DB Object and set {@link $return_statements return_statements}.
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db Database connection
|
||||
* @param bool $return_statements True if only statements should be returned and no SQL being executed
|
||||
*/
|
||||
public function __construct(\phpbb\db\driver\driver_interface $db, $return_statements = false)
|
||||
{
|
||||
parent::__construct($db, $return_statements);
|
||||
|
||||
// Determine mapping database type
|
||||
$this->sql_layer = 'postgres';
|
||||
|
||||
$this->dbms_type_map = self::get_dbms_type_map();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_list_tables()
|
||||
{
|
||||
$sql = 'SELECT relname
|
||||
FROM pg_stat_user_tables';
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
$tables = array();
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$name = current($row);
|
||||
$tables[$name] = $name;
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_table_exists($table_name)
|
||||
{
|
||||
$sql = "SELECT CAST(EXISTS(
|
||||
SELECT FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = '" . $this->db->sql_escape($table_name) . "'
|
||||
) AS INTEGER)";
|
||||
$result = $this->db->sql_query_limit($sql, 1);
|
||||
$row = $this->db->sql_fetchrow($result);
|
||||
$table_exists = (booL) $row['exists'];
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $table_exists;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_table($table_name, $table_data)
|
||||
{
|
||||
// holds the DDL for a column
|
||||
$columns = $statements = array();
|
||||
|
||||
if ($this->sql_table_exists($table_name))
|
||||
{
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
// Begin transaction
|
||||
$statements[] = 'begin';
|
||||
|
||||
// Determine if we have created a PRIMARY KEY in the earliest
|
||||
$primary_key_gen = false;
|
||||
|
||||
// Determine if the table requires a sequence
|
||||
$create_sequence = false;
|
||||
|
||||
// Begin table sql statement
|
||||
$table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n";
|
||||
|
||||
// Iterate through the columns to create a table
|
||||
foreach ($table_data['COLUMNS'] as $column_name => $column_data)
|
||||
{
|
||||
// here lies an array, filled with information compiled on the column's data
|
||||
$prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
|
||||
|
||||
if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen"
|
||||
{
|
||||
trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// here we add the definition of the new column to the list of columns
|
||||
$columns[] = "\t {$column_name} " . $prepared_column['column_type_sql'];
|
||||
|
||||
// see if we have found a primary key set due to a column definition if we have found it, we can stop looking
|
||||
if (!$primary_key_gen)
|
||||
{
|
||||
$primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set'];
|
||||
}
|
||||
|
||||
// create sequence DDL based off of the existence of auto incrementing columns
|
||||
if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'])
|
||||
{
|
||||
$create_sequence = $column_name;
|
||||
}
|
||||
}
|
||||
|
||||
// this makes up all the columns in the create table statement
|
||||
$table_sql .= implode(",\n", $columns);
|
||||
|
||||
// we have yet to create a primary key for this table,
|
||||
// this means that we can add the one we really wanted instead
|
||||
if (!$primary_key_gen)
|
||||
{
|
||||
// Write primary key
|
||||
if (isset($table_data['PRIMARY_KEY']))
|
||||
{
|
||||
if (!is_array($table_data['PRIMARY_KEY']))
|
||||
{
|
||||
$table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']);
|
||||
}
|
||||
|
||||
$table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// do we need to add a sequence for auto incrementing columns?
|
||||
if ($create_sequence)
|
||||
{
|
||||
$statements[] = "CREATE SEQUENCE {$table_name}_seq;";
|
||||
}
|
||||
|
||||
// close the table
|
||||
$table_sql .= "\n);";
|
||||
$statements[] = $table_sql;
|
||||
|
||||
// Write Keys
|
||||
if (isset($table_data['KEYS']))
|
||||
{
|
||||
foreach ($table_data['KEYS'] as $key_name => $key_data)
|
||||
{
|
||||
if (!is_array($key_data[1]))
|
||||
{
|
||||
$key_data[1] = array($key_data[1]);
|
||||
}
|
||||
|
||||
$old_return_statements = $this->return_statements;
|
||||
$this->return_statements = true;
|
||||
|
||||
$key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]);
|
||||
|
||||
foreach ($key_stmts as $key_stmt)
|
||||
{
|
||||
$statements[] = $key_stmt;
|
||||
}
|
||||
|
||||
$this->return_statements = $old_return_statements;
|
||||
}
|
||||
}
|
||||
|
||||
// Commit Transaction
|
||||
$statements[] = 'commit';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_list_columns($table_name)
|
||||
{
|
||||
$columns = array();
|
||||
|
||||
$sql = "SELECT a.attname
|
||||
FROM pg_class c, pg_attribute a
|
||||
WHERE c.relname = '{$table_name}'
|
||||
AND a.attnum > 0
|
||||
AND a.attrelid = c.oid";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$column = strtolower(current($row));
|
||||
$columns[$column] = $column;
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_index_exists($table_name, $index_name)
|
||||
{
|
||||
$sql = "SELECT ic.relname as index_name
|
||||
FROM pg_class bc, pg_class ic, pg_index i
|
||||
WHERE (bc.oid = i.indrelid)
|
||||
AND (ic.oid = i.indexrelid)
|
||||
AND (bc.relname = '" . $table_name . "')
|
||||
AND (i.indisunique != 't')
|
||||
AND (i.indisprimary != 't')";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
// This DBMS prefixes index names with the table name
|
||||
$row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
|
||||
|
||||
if (strtolower($row['index_name']) == strtolower($index_name))
|
||||
{
|
||||
$this->db->sql_freeresult($result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_unique_index_exists($table_name, $index_name)
|
||||
{
|
||||
$sql = "SELECT ic.relname as index_name, i.indisunique
|
||||
FROM pg_class bc, pg_class ic, pg_index i
|
||||
WHERE (bc.oid = i.indrelid)
|
||||
AND (ic.oid = i.indexrelid)
|
||||
AND (bc.relname = '" . $table_name . "')
|
||||
AND (i.indisprimary != 't')";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
if ($row['indisunique'] != 't')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// This DBMS prefixes index names with the table name
|
||||
$row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
|
||||
|
||||
if (strtolower($row['index_name']) == strtolower($index_name))
|
||||
{
|
||||
$this->db->sql_freeresult($result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to prepare some column information for better usage
|
||||
* @access private
|
||||
*/
|
||||
function sql_prepare_column_data($table_name, $column_name, $column_data)
|
||||
{
|
||||
if (strlen($column_name) > 30)
|
||||
{
|
||||
trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// Get type
|
||||
list($column_type, $orig_column_type) = $this->get_column_type($column_data[0]);
|
||||
|
||||
// Adjust default value if db-dependent specified
|
||||
if (is_array($column_data[1]))
|
||||
{
|
||||
$column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default'];
|
||||
}
|
||||
|
||||
$sql = " {$column_type} ";
|
||||
|
||||
$return_array = array(
|
||||
'column_type' => $column_type,
|
||||
'auto_increment' => false,
|
||||
);
|
||||
|
||||
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
|
||||
{
|
||||
$default_val = "nextval('{$table_name}_seq')";
|
||||
$return_array['auto_increment'] = true;
|
||||
}
|
||||
else if (!is_null($column_data[1]))
|
||||
{
|
||||
$default_val = "'" . $column_data[1] . "'";
|
||||
$return_array['null'] = 'NOT NULL';
|
||||
$sql .= 'NOT NULL ';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Integers need to have 0 instead of empty string as default
|
||||
if (strpos($column_type, 'INT') === 0)
|
||||
{
|
||||
$default_val = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
$default_val = "'" . $column_data[1] . "'";
|
||||
}
|
||||
$return_array['null'] = 'NULL';
|
||||
$sql .= 'NULL ';
|
||||
}
|
||||
|
||||
$return_array['default'] = $default_val;
|
||||
|
||||
$sql .= "DEFAULT {$default_val}";
|
||||
|
||||
// Unsigned? Then add a CHECK contraint
|
||||
if (in_array($orig_column_type, $this->unsigned_types))
|
||||
{
|
||||
$return_array['constraint'] = "CHECK ({$column_name} >= 0)";
|
||||
$sql .= " CHECK ({$column_name} >= 0)";
|
||||
}
|
||||
|
||||
$return_array['column_type_sql'] = $sql;
|
||||
|
||||
return $return_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_column_add($table_name, $column_name, $column_data, $inline = false)
|
||||
{
|
||||
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
|
||||
$statements = array();
|
||||
|
||||
// Does not support AFTER, only through temporary table
|
||||
if (version_compare($this->db->sql_server_info(true), '8.0', '>='))
|
||||
{
|
||||
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// old versions cannot add columns with default and null information
|
||||
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint'];
|
||||
|
||||
if (isset($column_data['null']))
|
||||
{
|
||||
if ($column_data['null'] == 'NOT NULL')
|
||||
{
|
||||
$statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($column_data['default']))
|
||||
{
|
||||
$statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_column_remove($table_name, $column_name, $inline = false)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_index_drop($table_name, $index_name)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_table_drop($table_name)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
if (!$this->sql_table_exists($table_name))
|
||||
{
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
// the most basic operation, get rid of the table
|
||||
$statements[] = 'DROP TABLE ' . $table_name;
|
||||
|
||||
// PGSQL does not "tightly" bind sequences and tables, we must guess...
|
||||
$sql = "SELECT relname
|
||||
FROM pg_class
|
||||
WHERE relkind = 'S'
|
||||
AND relname = '{$table_name}_seq'";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
// We don't even care about storing the results. We already know the answer if we get rows back.
|
||||
if ($this->db->sql_fetchrow($result))
|
||||
{
|
||||
$statements[] = "DROP SEQUENCE IF EXISTS {$table_name}_seq;\n";
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_primary_key($table_name, $column, $inline = false)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_unique_index($table_name, $index_name, $column)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$this->check_index_name_length($table_name, $index_name);
|
||||
|
||||
$statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_create_index($table_name, $index_name, $column)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
$this->check_index_name_length($table_name, $index_name);
|
||||
|
||||
// remove index length
|
||||
$column = preg_replace('#:.*$#', '', $column);
|
||||
|
||||
$statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_list_index($table_name)
|
||||
{
|
||||
$index_array = array();
|
||||
|
||||
$sql = "SELECT ic.relname as index_name
|
||||
FROM pg_class bc, pg_class ic, pg_index i
|
||||
WHERE (bc.oid = i.indrelid)
|
||||
AND (ic.oid = i.indexrelid)
|
||||
AND (bc.relname = '" . $table_name . "')
|
||||
AND (i.indisunique != 't')
|
||||
AND (i.indisprimary != 't')";
|
||||
$result = $this->db->sql_query($sql);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$row['index_name'] = $this->strip_table_name_from_index_name($table_name, $row['index_name']);
|
||||
|
||||
$index_array[] = $row['index_name'];
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return array_map('strtolower', $index_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
function sql_column_change($table_name, $column_name, $column_data, $inline = false)
|
||||
{
|
||||
$column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data);
|
||||
$statements = array();
|
||||
|
||||
$sql = 'ALTER TABLE ' . $table_name . ' ';
|
||||
|
||||
$sql_array = array();
|
||||
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
|
||||
|
||||
if (isset($column_data['null']))
|
||||
{
|
||||
if ($column_data['null'] == 'NOT NULL')
|
||||
{
|
||||
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
|
||||
}
|
||||
else if ($column_data['null'] == 'NULL')
|
||||
{
|
||||
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($column_data['default']))
|
||||
{
|
||||
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
|
||||
}
|
||||
|
||||
// we don't want to double up on constraints if we change different number data types
|
||||
if (isset($column_data['constraint']))
|
||||
{
|
||||
$constraint_sql = "SELECT pg_get_constraintdef(pc.oid) AS constraint_data
|
||||
FROM pg_constraint pc, pg_class bc
|
||||
WHERE conrelid = bc.oid
|
||||
AND bc.relname = '" . $this->db->sql_escape($table_name) . "'
|
||||
AND NOT EXISTS (
|
||||
SELECT *
|
||||
FROM pg_constraint AS c, pg_inherits AS i
|
||||
WHERE i.inhrelid = pc.conrelid
|
||||
AND c.conname = pc.conname
|
||||
AND pg_get_constraintdef(c.oid) = pg_get_constraintdef(pc.oid)
|
||||
AND c.conrelid = i.inhparent
|
||||
)";
|
||||
|
||||
$constraint_exists = false;
|
||||
|
||||
$result = $this->db->sql_query($constraint_sql);
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
if (trim($row['constraint_data']) == trim($column_data['constraint']))
|
||||
{
|
||||
$constraint_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
if (!$constraint_exists)
|
||||
{
|
||||
$sql_array[] = 'ADD ' . $column_data['constraint'];
|
||||
}
|
||||
}
|
||||
|
||||
$sql .= implode(', ', $sql_array);
|
||||
|
||||
$statements[] = $sql;
|
||||
|
||||
return $this->_sql_run_sql($statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list with existing indexes for the column
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $column_name
|
||||
* @param bool $unique Should we get unique indexes or normal ones
|
||||
* @return array Array with Index name => columns
|
||||
*/
|
||||
public function get_existing_indexes($table_name, $column_name, $unique = false)
|
||||
{
|
||||
// Not supported
|
||||
throw new \Exception('DBMS is not supported');
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -40,41 +40,40 @@ interface tools_interface
|
|||
*
|
||||
*
|
||||
* @param array $schema_changes
|
||||
* @return null
|
||||
*/
|
||||
public function perform_schema_changes($schema_changes);
|
||||
public function perform_schema_changes(array $schema_changes): void;
|
||||
|
||||
/**
|
||||
* Gets a list of tables in the database.
|
||||
*
|
||||
* @return array Array of table names (all lower case)
|
||||
*/
|
||||
public function sql_list_tables();
|
||||
public function sql_list_tables(): array;
|
||||
|
||||
/**
|
||||
* Check if table exists
|
||||
*
|
||||
* @param string $table_name The table name to check for
|
||||
* @return bool true if table exists, else false
|
||||
* @return bool True if table exists, else false
|
||||
*/
|
||||
public function sql_table_exists($table_name);
|
||||
public function sql_table_exists(string $table_name): bool;
|
||||
|
||||
/**
|
||||
* Create SQL Table
|
||||
*
|
||||
* @param string $table_name The table name to create
|
||||
* @param array $table_data Array containing table data.
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_create_table($table_name, $table_data);
|
||||
public function sql_create_table(string $table_name, array $table_data): bool;
|
||||
|
||||
/**
|
||||
* Drop Table
|
||||
*
|
||||
* @param string $table_name The table name to drop
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_table_drop($table_name);
|
||||
public function sql_table_drop(string $table_name): bool;
|
||||
|
||||
/**
|
||||
* Gets a list of columns of a table.
|
||||
|
@ -82,7 +81,7 @@ interface tools_interface
|
|||
* @param string $table_name Table name
|
||||
* @return array Array of column names (all lower case)
|
||||
*/
|
||||
public function sql_list_columns($table_name);
|
||||
public function sql_list_columns(string $table_name): array;
|
||||
|
||||
/**
|
||||
* Check whether a specified column exist in a table
|
||||
|
@ -91,7 +90,7 @@ interface tools_interface
|
|||
* @param string $column_name Column to check
|
||||
* @return bool True if column exists, false otherwise
|
||||
*/
|
||||
public function sql_column_exists($table_name, $column_name);
|
||||
public function sql_column_exists(string $table_name, string $column_name): bool;
|
||||
|
||||
/**
|
||||
* Add new column
|
||||
|
@ -99,11 +98,10 @@ interface tools_interface
|
|||
* @param string $table_name Table to modify
|
||||
* @param string $column_name Name of the column to add
|
||||
* @param array $column_data Column data
|
||||
* @param bool $inline Whether the query should actually be run,
|
||||
* or return a string for adding the column
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
*
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_column_add($table_name, $column_name, $column_data, $inline = false);
|
||||
public function sql_column_add(string $table_name, string $column_name, array $column_data): bool;
|
||||
|
||||
/**
|
||||
* Change column type (not name!)
|
||||
|
@ -111,22 +109,20 @@ interface tools_interface
|
|||
* @param string $table_name Table to modify
|
||||
* @param string $column_name Name of the column to modify
|
||||
* @param array $column_data Column data
|
||||
* @param bool $inline Whether the query should actually be run,
|
||||
* or return a string for modifying the column
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
*
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_column_change($table_name, $column_name, $column_data, $inline = false);
|
||||
public function sql_column_change(string $table_name, string $column_name, array $column_data): bool;
|
||||
|
||||
/**
|
||||
* Drop column
|
||||
*
|
||||
* @param string $table_name Table to modify
|
||||
* @param string $column_name Name of the column to drop
|
||||
* @param bool $inline Whether the query should actually be run,
|
||||
* or return a string for deleting the column
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
*
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_column_remove($table_name, $column_name, $inline = false);
|
||||
public function sql_column_remove(string $table_name, string $column_name): bool;
|
||||
|
||||
/**
|
||||
* List all of the indices that belong to a table
|
||||
|
@ -138,7 +134,7 @@ interface tools_interface
|
|||
* @param string $table_name Table to check
|
||||
* @return array Array with index names
|
||||
*/
|
||||
public function sql_list_index($table_name);
|
||||
public function sql_list_index(string $table_name): array;
|
||||
|
||||
/**
|
||||
* Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes.
|
||||
|
@ -147,7 +143,7 @@ interface tools_interface
|
|||
* @param string $index_name The index name to check
|
||||
* @return bool True if index exists, else false
|
||||
*/
|
||||
public function sql_index_exists($table_name, $index_name);
|
||||
public function sql_index_exists(string $table_name, string $index_name): bool;
|
||||
|
||||
/**
|
||||
* Add index
|
||||
|
@ -155,18 +151,18 @@ interface tools_interface
|
|||
* @param string $table_name Table to modify
|
||||
* @param string $index_name Name of the index to create
|
||||
* @param string|array $column Either a string with a column name, or an array with columns
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_create_index($table_name, $index_name, $column);
|
||||
public function sql_create_index(string $table_name, string $index_name, $column): bool;
|
||||
|
||||
/**
|
||||
* Drop Index
|
||||
*
|
||||
* @param string $table_name Table to modify
|
||||
* @param string $index_name Name of the index to delete
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_index_drop($table_name, $index_name);
|
||||
public function sql_index_drop(string $table_name, string $index_name): bool;
|
||||
|
||||
/**
|
||||
* Check if a specified index exists in table.
|
||||
|
@ -177,7 +173,7 @@ interface tools_interface
|
|||
* @param string $index_name The index name to check
|
||||
* @return bool True if index exists, else false
|
||||
*/
|
||||
public function sql_unique_index_exists($table_name, $index_name);
|
||||
public function sql_unique_index_exists(string $table_name, string $index_name): bool;
|
||||
|
||||
/**
|
||||
* Add unique index
|
||||
|
@ -185,18 +181,16 @@ interface tools_interface
|
|||
* @param string $table_name Table to modify
|
||||
* @param string $index_name Name of the unique index to create
|
||||
* @param string|array $column Either a string with a column name, or an array with columns
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_create_unique_index($table_name, $index_name, $column);
|
||||
public function sql_create_unique_index(string $table_name, string $index_name, $column): bool;
|
||||
|
||||
/**
|
||||
* Add primary key
|
||||
*
|
||||
* @param string $table_name Table to modify
|
||||
* @param string|array $column Either a string with a column name, or an array with columns
|
||||
* @param bool $inline Whether the query should actually be run,
|
||||
* or return a string for creating the key
|
||||
* @return array|true Statements to run, or true if the statements have been executed
|
||||
* @return bool True if the statements have been executed
|
||||
*/
|
||||
public function sql_create_primary_key($table_name, $column, $inline = false);
|
||||
public function sql_create_primary_key(string $table_name, $column): bool;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue