[ticket/224] Use new create_schema_files from phpBB and json schema

B3P-224
This commit is contained in:
Marc Alexander
2014-04-05 14:49:59 +02:00
parent 3d755c1c95
commit 4319d7d041
10 changed files with 3420 additions and 10458 deletions

View File

@@ -12,7 +12,15 @@
*/
$schema_path = dirname(__FILE__) . '/../tests/schemas/';
$phpbb_root_path = dirname(__FILE__) . '/../../../../';
$supported_dbms = array(
'firebird',
'mssql',
'mysql_40',
'mysql_41',
'oracle',
'postgres',
'sqlite',
);
if (!is_writable($schema_path))
{
@@ -20,23 +28,38 @@ if (!is_writable($schema_path))
}
define('IN_PHPBB', true);
define('IN_INSTALL', true);
$phpbb_root_path = dirname(__FILE__) . '/../../../../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
require($phpbb_root_path . 'includes/db/schema_data.php');
require(dirname(__FILE__) . '/schema_data.php');
require($phpbb_root_path . 'phpbb/db/tools.php');
// Get board3 portal classes first
$classes = $phpbb_container->get('ext.manager')
->get_finder()
->core_path('ext/board3/portal/')
->directory('migrations')
->get_classes();
// Get phpBB classes and merge with above
$classes = array_merge($classes, $phpbb_container->get('ext.manager')
->get_finder()
->core_path('phpbb/')
->directory('db/migration/data')
->get_classes());
$db_tools = new \phpbb\db\tools($db, true);
$schema_generator = new \phpbb\db\migration\schema_generator($classes, $config, $db, $db_tools, $phpbb_root_path, $phpEx, 'phpbb_');
$schema_data = $schema_generator->get_schema();
$dbms_type_map = phpbb\db\tools::get_dbms_type_map();
// A list of types being unsigned for better reference in some db's
$unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
$supported_dbms = array('firebird', 'mssql', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite');
$fp = fopen($schema_path . 'schema.json', 'wb');
fwrite($fp, json_encode($schema_data, JSON_PRETTY_PRINT));
fclose($fp);
foreach ($supported_dbms as $dbms)
{
$fp = fopen($schema_path . $dbms . '_schema.sql', 'wb');
$line = '';
// Write Header
switch ($dbms)
{
@@ -64,16 +87,9 @@ foreach ($supported_dbms as $dbms)
break;
}
$line = '';
switch ($dbms)
{
case 'firebird':
$line .= custom_data('firebird') . "\n";
break;
case 'sqlite':
$line .= "BEGIN TRANSACTION;\n\n";
break;
case 'oracle':
$line .= custom_data('oracle') . "\n";
break;
@@ -81,501 +97,7 @@ foreach ($supported_dbms as $dbms)
case 'postgres':
$line .= "BEGIN;\n\n";
$line .= custom_data('postgres') . "\n";
break;
}
fwrite($fp, $line);
foreach ($schema_data as $table_name => $table_data)
{
// Write comment about table
switch ($dbms)
{
case 'mysql_40':
case 'mysql_41':
case 'firebird':
case 'sqlite':
fwrite($fp, "# Table: '{$table_name}'\n");
break;
case 'mssql':
case 'oracle':
case 'postgres':
fwrite($fp, "/*\n\tTable: '{$table_name}'\n*/\n");
break;
}
// Create Table statement
$generator = $textimage = false;
$line = '';
switch ($dbms)
{
case 'mysql_40':
case 'mysql_41':
case 'firebird':
case 'oracle':
case 'sqlite':
case 'postgres':
$line = "CREATE TABLE {$table_name} (\n";
break;
case 'mssql':
$line = "CREATE TABLE [{$table_name}] (\n";
break;
}
// Table specific so we don't get overlap
$modded_array = array();
// Write columns one by one...
foreach ($table_data['COLUMNS'] as $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);
}
if (isset($column_data[2]) && $column_data[2] == '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 is 30 characters.", E_USER_ERROR);
}
// Get type
if (strpos($column_data[0], ':') !== false)
{
list($orig_column_type, $column_length) = explode(':', $column_data[0]);
if (!is_array($dbms_type_map[$dbms][$orig_column_type . ':']))
{
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'], $column_length);
}
else
{
if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['rule']))
{
switch ($dbms_type_map[$dbms][$orig_column_type . ':']['rule'][0])
{
case 'div':
$column_length /= $dbms_type_map[$dbms][$orig_column_type . ':']['rule'][1];
$column_length = ceil($column_length);
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
break;
}
}
if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['limit']))
{
switch ($dbms_type_map[$dbms][$orig_column_type . ':']['limit'][0])
{
case 'mult':
$column_length *= $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][1];
if ($column_length > $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][2])
{
$column_type = $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][3];
$modded_array[$column_name] = $column_type;
}
else
{
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
}
break;
}
}
}
$orig_column_type .= ':';
}
else
{
$orig_column_type = $column_data[0];
$column_type = $dbms_type_map[$dbms][$column_data[0]];
if ($column_type == 'text' || $column_type == 'blob')
{
$modded_array[$column_name] = $column_type;
}
}
// Adjust default value if db-dependent specified
if (is_array($column_data[1]))
{
$column_data[1] = (isset($column_data[1][$dbms])) ? $column_data[1][$dbms] : $column_data[1]['default'];
}
switch ($dbms)
{
case 'mysql_40':
case 'mysql_41':
$line .= "\t{$column_name} {$column_type} ";
// For hexadecimal values do not use single quotes
if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob')
{
$line .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
}
$line .= 'NOT NULL';
if (isset($column_data[2]))
{
if ($column_data[2] == 'auto_increment')
{
$line .= ' auto_increment';
}
else if ($dbms === 'mysql_41' && $column_data[2] == 'true_sort')
{
$line .= ' COLLATE utf8_unicode_ci';
}
}
$line .= ",\n";
break;
case 'sqlite':
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
{
$line .= "\t{$column_name} INTEGER PRIMARY KEY ";
$generator = $column_name;
}
else
{
$line .= "\t{$column_name} {$column_type} ";
}
$line .= 'NOT NULL ';
$line .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : '';
$line .= ",\n";
break;
case 'firebird':
$line .= "\t{$column_name} {$column_type} ";
if (!is_null($column_data[1]))
{
$line .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
}
$line .= 'NOT NULL';
// This is a UNICODE column and thus should be given it's fair share
if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0]))
{
$line .= ' COLLATE UNICODE';
}
$line .= ",\n";
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
{
$generator = $column_name;
}
break;
case 'mssql':
if ($column_type == '[text]')
{
$textimage = true;
}
$line .= "\t[{$column_name}] {$column_type} ";
if (!is_null($column_data[1]))
{
// For hexadecimal values do not use single quotes
if (strpos($column_data[1], '0x') === 0)
{
$line .= 'DEFAULT (' . $column_data[1] . ') ';
}
else
{
$line .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
}
}
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
{
$line .= 'IDENTITY (1, 1) ';
}
$line .= 'NOT NULL';
$line .= " ,\n";
break;
case 'oracle':
$line .= "\t{$column_name} {$column_type} ";
$line .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
// In Oracle empty strings ('') are treated as NULL.
// Therefore in oracle we allow NULL's for all DEFAULT '' entries
$line .= ($column_data[1] === '') ? ",\n" : "NOT NULL,\n";
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
{
$generator = $column_name;
}
break;
case 'postgres':
$line .= "\t{$column_name} {$column_type} ";
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
{
$line .= "DEFAULT nextval('{$table_name}_seq'),\n";
// Make sure the sequence will be created before creating the table
$line = "CREATE SEQUENCE {$table_name}_seq;\n\n" . $line;
}
else
{
$line .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
$line .= "NOT NULL";
// Unsigned? Then add a CHECK contraint
if (in_array($orig_column_type, $unsigned_types))
{
$line .= " CHECK ({$column_name} >= 0)";
}
$line .= ",\n";
}
break;
}
}
switch ($dbms)
{
case 'firebird':
// Remove last line delimiter...
$line = substr($line, 0, -2);
$line .= "\n);;\n\n";
break;
case 'mssql':
$line = substr($line, 0, -2);
$line .= "\n) ON [PRIMARY]" . (($textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : '') . "\n";
$line .= "GO\n\n";
break;
}
// 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']);
}
switch ($dbms)
{
case 'mysql_40':
case 'mysql_41':
case 'postgres':
$line .= "\tPRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . "),\n";
break;
case 'firebird':
$line .= "ALTER TABLE {$table_name} ADD PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ");;\n\n";
break;
case 'sqlite':
if ($generator === false || !in_array($generator, $table_data['PRIMARY_KEY']))
{
$line .= "\tPRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . "),\n";
}
break;
case 'mssql':
$line .= "ALTER TABLE [{$table_name}] WITH NOCHECK ADD \n";
$line .= "\tCONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED \n";
$line .= "\t(\n";
$line .= "\t\t[" . implode("],\n\t\t[", $table_data['PRIMARY_KEY']) . "]\n";
$line .= "\t) ON [PRIMARY] \n";
$line .= "GO\n\n";
break;
case 'oracle':
$line .= "\tCONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . "),\n";
break;
}
}
switch ($dbms)
{
case 'oracle':
// UNIQUE contrains to be added?
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]);
}
if ($key_data[0] == 'UNIQUE')
{
$line .= "\tCONSTRAINT u_phpbb_{$key_name} UNIQUE (" . implode(', ', $key_data[1]) . "),\n";
}
}
}
// Remove last line delimiter...
$line = substr($line, 0, -2);
$line .= "\n)\n/\n\n";
break;
case 'postgres':
// Remove last line delimiter...
$line = substr($line, 0, -2);
$line .= "\n);\n\n";
break;
case 'sqlite':
// Remove last line delimiter...
$line = substr($line, 0, -2);
$line .= "\n);\n\n";
break;
}
// 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]);
}
if (strlen($table_name . $key_name) > 30)
{
trigger_error("Index name '${table_name}_$key_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR);
}
switch ($dbms)
{
case 'mysql_40':
case 'mysql_41':
$line .= ($key_data[0] == 'INDEX') ? "\tKEY" : '';
$line .= ($key_data[0] == 'UNIQUE') ? "\tUNIQUE" : '';
foreach ($key_data[1] as $key => $col_name)
{
if (isset($modded_array[$col_name]))
{
switch ($modded_array[$col_name])
{
case 'text':
case 'blob':
$key_data[1][$key] = $col_name . '(255)';
break;
}
}
}
$line .= ' ' . $key_name . ' (' . implode(', ', $key_data[1]) . "),\n";
break;
case 'firebird':
$line .= ($key_data[0] == 'INDEX') ? 'CREATE INDEX' : '';
$line .= ($key_data[0] == 'UNIQUE') ? 'CREATE UNIQUE INDEX' : '';
$line .= ' ' . $table_name . '_' . $key_name . ' ON ' . $table_name . '(' . implode(', ', $key_data[1]) . ");;\n";
break;
case 'mssql':
$line .= ($key_data[0] == 'INDEX') ? 'CREATE INDEX' : '';
$line .= ($key_data[0] == 'UNIQUE') ? 'CREATE UNIQUE INDEX' : '';
$line .= " [{$key_name}] ON [{$table_name}]([" . implode('], [', $key_data[1]) . "]) ON [PRIMARY]\n";
$line .= "GO\n\n";
break;
case 'oracle':
if ($key_data[0] == 'UNIQUE')
{
continue;
}
$line .= ($key_data[0] == 'INDEX') ? 'CREATE INDEX' : '';
$line .= " {$table_name}_{$key_name} ON {$table_name} (" . implode(', ', $key_data[1]) . ")\n";
$line .= "/\n";
break;
case 'sqlite':
$line .= ($key_data[0] == 'INDEX') ? 'CREATE INDEX' : '';
$line .= ($key_data[0] == 'UNIQUE') ? 'CREATE UNIQUE INDEX' : '';
$line .= " {$table_name}_{$key_name} ON {$table_name} (" . implode(', ', $key_data[1]) . ");\n";
break;
case 'postgres':
$line .= ($key_data[0] == 'INDEX') ? 'CREATE INDEX' : '';
$line .= ($key_data[0] == 'UNIQUE') ? 'CREATE UNIQUE INDEX' : '';
$line .= " {$table_name}_{$key_name} ON {$table_name} (" . implode(', ', $key_data[1]) . ");\n";
break;
}
}
}
switch ($dbms)
{
case 'mysql_40':
// Remove last line delimiter...
$line = substr($line, 0, -2);
$line .= "\n);\n\n";
break;
case 'mysql_41':
// Remove last line delimiter...
$line = substr($line, 0, -2);
$line .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;\n\n";
break;
// Create Generator
case 'firebird':
if ($generator !== false)
{
$line .= "\nCREATE GENERATOR {$table_name}_gen;;\n";
$line .= 'SET GENERATOR ' . $table_name . "_gen TO 0;;\n\n";
$line .= 'CREATE TRIGGER t_' . $table_name . ' FOR ' . $table_name . "\n";
$line .= "BEFORE INSERT\nAS\nBEGIN\n";
$line .= "\tNEW.{$generator} = GEN_ID({$table_name}_gen, 1);\nEND;;\n\n";
}
break;
case 'oracle':
if ($generator !== false)
{
$line .= "\nCREATE SEQUENCE {$table_name}_seq\n/\n\n";
$line .= "CREATE OR REPLACE TRIGGER t_{$table_name}\n";
$line .= "BEFORE INSERT ON {$table_name}\n";
$line .= "FOR EACH ROW WHEN (\n";
$line .= "\tnew.{$generator} IS NULL OR new.{$generator} = 0\n";
$line .= ")\nBEGIN\n";
$line .= "\tSELECT {$table_name}_seq.nextval\n";
$line .= "\tINTO :new.{$generator}\n";
$line .= "\tFROM dual;\nEND;\n/\n\n";
}
break;
}
fwrite($fp, $line . "\n");
}
$line = '';
// Write custom function at the end for some db's
switch ($dbms)
{
case 'mssql':
// No need to do this, no transaction support for schema changes
//$line = "\nCOMMIT\nGO\n\n";
break;
case 'sqlite':
$line = "\nCOMMIT;";
break;
case 'postgres':
$line = "\nCOMMIT;";
$line .= "COMMIT;\n\n";
break;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3383
tests/schemas/schema.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -11,12 +11,12 @@ namespace board3\portal\tests\testframework;
class database_test_connection_manager extends \phpbb_database_test_connection_manager
{
public function load_schema()
public function load_schema($db)
{
$this->ensure_connected(__METHOD__);
$directory = dirname(__FILE__) . '/../schemas/';
$this->load_schema_from_file($directory);
$this->load_schema_from_file($directory, $db);
}
}