mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 09:48:40 +00:00
test and fix schema builder
This commit is contained in:
parent
6e2bfebc60
commit
0bd6cb95f5
|
|
@ -205,10 +205,6 @@ abstract class GrammarAbstract
|
|||
|
||||
foreach ($elements as $key => $element) {
|
||||
if (\is_string($element) && $element !== '*') {
|
||||
if (\strpos($element, '.') === false) {
|
||||
$prefix = '';
|
||||
}
|
||||
|
||||
$expression .= $this->compileSystem($element, $prefix) . ', ';
|
||||
} elseif (\is_string($element) && $element === '*') {
|
||||
$expression .= '*, ';
|
||||
|
|
|
|||
|
|
@ -31,11 +31,13 @@ class Builder extends QueryBuilder
|
|||
|
||||
public $createFields = [];
|
||||
|
||||
public $drop = [];
|
||||
public $dropDatabase = '';
|
||||
|
||||
public $dropTable = '';
|
||||
|
||||
public $selectTables = ['*'];
|
||||
|
||||
public $selectFields = [];
|
||||
public $selectFields = '';
|
||||
|
||||
public $createTableSettings = true;
|
||||
|
||||
|
|
@ -43,20 +45,70 @@ class Builder extends QueryBuilder
|
|||
* Constructor.
|
||||
*
|
||||
* @param ConnectionAbstract $connection Database connection
|
||||
* @param bool $readOnly Query is read only
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function __construct(ConnectionAbstract $connection)
|
||||
public function __construct(ConnectionAbstract $connection, bool $readOnly = false)
|
||||
{
|
||||
$this->isReadOnly = $readOnly;
|
||||
$this->setConnection($connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set connection for grammar.
|
||||
*
|
||||
* @param ConnectionAbstract $connection Database connection
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setConnection(ConnectionAbstract $connection) : void
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->grammar = $connection->getSchemaGrammar();
|
||||
}
|
||||
|
||||
public function drop(...$table) : self
|
||||
/**
|
||||
* Create schema builder from schema definition.
|
||||
*
|
||||
* @param array $definition Database schema definition
|
||||
* @param ConnectionAbstract $connection Database connection
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function createFromSchema(array $definition, ConnectionAbstract $connection) : self
|
||||
{
|
||||
$this->type = QueryType::DROP;
|
||||
$this->drop += $table;
|
||||
$this->drop = \array_unique($this->drop);
|
||||
$builder = new self($connection);
|
||||
$builder->prefix($connection->prefix);
|
||||
$builder->createTable($definition['name'] ?? '');
|
||||
|
||||
foreach ($definition['fields'] as $name => $def) {
|
||||
$builder->field(
|
||||
$name, $def['type'], $def['default'] ?? null,
|
||||
$def['null'] ?? true, $def['primary'] ?? false, $def['autoincrement'] ?? false,
|
||||
$def['foreignTable'] ?? null, $def['foreignKey'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
public function dropDatabase(string $database) : self
|
||||
{
|
||||
$this->type = QueryType::DROP_DATABASE;
|
||||
$this->dropDatabase = $database;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dropTable(string $table) : self
|
||||
{
|
||||
$this->type = QueryType::DROP_TABLE;
|
||||
$this->dropTable = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -70,8 +122,8 @@ class Builder extends QueryBuilder
|
|||
|
||||
public function selectFields(string $table) : self
|
||||
{
|
||||
$this->type = QueryType::FIELDS;
|
||||
$this->selectFields[0] = $table;
|
||||
$this->type = QueryType::FIELDS;
|
||||
$this->selectFields = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,18 @@ class Grammar extends QueryGrammar
|
|||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected $dropComponents = [
|
||||
'drop',
|
||||
protected $dropDatabaseComponents = [
|
||||
'dropDatabase',
|
||||
];
|
||||
|
||||
/**
|
||||
* Drop components.
|
||||
*
|
||||
* @var string[]
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected $dropTableComponents = [
|
||||
'dropTable',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -76,14 +86,16 @@ class Grammar extends QueryGrammar
|
|||
protected function getComponents(int $type) : array
|
||||
{
|
||||
switch ($type) {
|
||||
case QueryType::DROP:
|
||||
return $this->dropComponents;
|
||||
case QueryType::DROP_DATABASE:
|
||||
return $this->dropDatabaseComponents;
|
||||
case QueryType::TABLES:
|
||||
return $this->tablesComponents;
|
||||
case QueryType::FIELDS:
|
||||
return $this->fieldsComponents;
|
||||
case QueryType::CREATE_TABLE:
|
||||
return $this->createTablesComponents;
|
||||
case QueryType::DROP_TABLE:
|
||||
return $this->dropTableComponents;
|
||||
default:
|
||||
return parent::getComponents($type);
|
||||
}
|
||||
|
|
@ -123,15 +135,15 @@ class Grammar extends QueryGrammar
|
|||
* Compile drop query.
|
||||
*
|
||||
* @param BuilderAbstract $query Query
|
||||
* @param array $tables Tables to drop
|
||||
* @param string $table Tables to drop
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function compileDrop(BuilderAbstract $query, array $tables) : string
|
||||
protected function compileDropDatabase(BuilderAbstract $query, string $table) : string
|
||||
{
|
||||
$expression = $this->expressionizeTableColumn($tables, $query->getPrefix());
|
||||
$expression = $this->expressionizeTableColumn([$table], $query->getPrefix());
|
||||
|
||||
if ($expression === '') {
|
||||
$expression = '*';
|
||||
|
|
@ -139,4 +151,25 @@ class Grammar extends QueryGrammar
|
|||
|
||||
return 'DROP DATABASE ' . $expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile drop query.
|
||||
*
|
||||
* @param BuilderAbstract $query Query
|
||||
* @param string $table Tables to drop
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function compileDropTable(BuilderAbstract $query, string $table) : string
|
||||
{
|
||||
$expression = $this->expressionizeTableColumn([$table], $query->getPrefix());
|
||||
|
||||
if ($expression === '') {
|
||||
$expression = '*';
|
||||
}
|
||||
|
||||
return 'DROP TABLE ' . $expression;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@ class MysqlGrammar extends Grammar
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function compileSelectFields(Builder $query, array $table) : string
|
||||
protected function compileSelectFields(Builder $query, string $table) : string
|
||||
{
|
||||
$builder = new Builder($query->getConnection());
|
||||
$builder->select('*')
|
||||
->from('information_schema.columns')
|
||||
->where('table_schema', '=', $query->getConnection()->getDatabase())
|
||||
->andWhere('table_name', '=', 'test');
|
||||
->andWhere('table_name', '=', $query->getPrefix() . $table);
|
||||
|
||||
return \rtrim($builder->toSql(), ';');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ use phpOMS\DataStorage\Database\Query\QueryType as DefaultQueryType;
|
|||
*/
|
||||
abstract class QueryType extends DefaultQueryType
|
||||
{
|
||||
public const DROP = 128;
|
||||
public const ALTER = 129;
|
||||
public const TABLES = 130;
|
||||
public const FIELDS = 131;
|
||||
public const CREATE_TABLE = 132;
|
||||
public const DROP_DATABASE = 128;
|
||||
public const ALTER = 129;
|
||||
public const TABLES = 130;
|
||||
public const FIELDS = 131;
|
||||
public const CREATE_TABLE = 132;
|
||||
public const DROP_TABLE = 133;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,37 +119,10 @@ abstract class InstallerAbstract
|
|||
|
||||
$definitions = \json_decode($content, true);
|
||||
foreach ($definitions as $definition) {
|
||||
self::createTable($definition, $dbPool);
|
||||
SchemaBuilder::createFromSchema($definition, $dbPool->get('schema'))->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create table module.
|
||||
*
|
||||
* @param array $definition Table definition
|
||||
* @param DatabasePool $dbPool Database instance
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private static function createTable(array $definition, DatabasePool $dbPool) : void
|
||||
{
|
||||
$builder = new SchemaBuilder($dbPool->get('schema'));
|
||||
$builder->prefix($dbPool->get('schema')->prefix);
|
||||
$builder->createTable($definition['name'] ?? '');
|
||||
|
||||
foreach ($definition['fields'] as $name => $def) {
|
||||
$builder->field(
|
||||
$name, $def['type'], $def['default'] ?? null,
|
||||
$def['null'] ?? true, $def['primary'] ?? false, $def['autoincrement'] ?? false,
|
||||
$def['foreignTable'] ?? null, $def['foreignKey'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
$builder->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate after install.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class BuilderTest extends \PHPUnit\Framework\TestCase
|
|||
{
|
||||
$query = new Builder($this->con);
|
||||
$sql = 'DROP DATABASE `test`;';
|
||||
self::assertEquals($sql, $query->drop('test')->toSql());
|
||||
self::assertEquals($sql, $query->dropDatabase('test')->toSql());
|
||||
}
|
||||
|
||||
public function testMysqlShowTables() : void
|
||||
|
|
|
|||
|
|
@ -13,14 +13,55 @@
|
|||
|
||||
namespace phpOMS\tests\DataStorage\Database\Schema\Grammar;
|
||||
|
||||
use phpOMS\DataStorage\Database\Connection\MysqlConnection;
|
||||
use phpOMS\DataStorage\Database\Schema\Builder as SchemaBuilder;
|
||||
use phpOMS\DataStorage\Database\Schema\Grammar\MysqlGrammar;
|
||||
use phpOMS\Utils\ArrayUtils;
|
||||
use phpOMS\Utils\TestUtils;
|
||||
|
||||
class MysqlGrammarTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
protected $con = null;
|
||||
|
||||
protected function setUp() : void
|
||||
{
|
||||
$this->con = new MysqlConnection($GLOBALS['CONFIG']['db']['core']['masters']['admin']);
|
||||
}
|
||||
|
||||
public function testDefault() : void
|
||||
{
|
||||
self::assertInstanceOf('\phpOMS\DataStorage\Database\Schema\Grammar\Grammar', new MysqlGrammar());
|
||||
self::assertEquals('`', TestUtils::getMember(new MysqlGrammar(), 'systemIdentifier'));
|
||||
}
|
||||
|
||||
public function testSchemaCreateReadDelete() : void
|
||||
{
|
||||
$definitions = \json_decode(\file_get_contents(__DIR__ . '/testSchema.json'), true);
|
||||
foreach ($definitions as $definition) {
|
||||
SchemaBuilder::createFromSchema($definition, $this->con)->execute();
|
||||
}
|
||||
|
||||
$table = new SchemaBuilder($this->con);
|
||||
$tables = $table->prefix($this->con->prefix)->selectTables()->execute()->fetchAll(\PDO::FETCH_COLUMN);
|
||||
self::assertContains($this->con->prefix . 'test', $tables);
|
||||
self::assertContains($this->con->prefix . 'test_foreign', $tables);
|
||||
|
||||
$field = new SchemaBuilder($this->con);
|
||||
$fields = $field->prefix($this->con->prefix)->selectFields('test')->execute()->fetchAll();
|
||||
|
||||
foreach ($definitions['test']['fields'] as $key => $field) {
|
||||
self::assertTrue(
|
||||
ArrayUtils::inArrayRecursive($key, $fields),
|
||||
'Couldn\'t find "' . $key . '" in array'
|
||||
);
|
||||
}
|
||||
|
||||
$delete = new SchemaBuilder($this->con);
|
||||
$delete->prefix($this->con->prefix)->dropTable('test')->execute();
|
||||
$delete->prefix($this->con->prefix)->dropTable('test_foreign')->execute();
|
||||
|
||||
$tables = $table->prefix($this->con->prefix)->selectTables()->execute()->fetchAll();
|
||||
self::assertNotContains($this->con->prefix . 'test', $tables);
|
||||
self::assertNotContains($this->con->prefix . 'test_foreign', $tables);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
81
tests/DataStorage/Database/Schema/Grammar/testSchema.json
Normal file
81
tests/DataStorage/Database/Schema/Grammar/testSchema.json
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"test_foreign": {
|
||||
"name": "test_foreign",
|
||||
"fields": {
|
||||
"test_foreign_id": {
|
||||
"name": "test_foreign_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"name": "test",
|
||||
"fields": {
|
||||
"test_id": {
|
||||
"name": "test_id",
|
||||
"type": "INT",
|
||||
"null": false,
|
||||
"primary": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"test_varchar": {
|
||||
"name": "test_varchar",
|
||||
"type": "VARCHAR(255)",
|
||||
"null": false
|
||||
},
|
||||
"test_text": {
|
||||
"name": "test_text",
|
||||
"type": "TEXT",
|
||||
"null": false
|
||||
},
|
||||
"test_tinyint": {
|
||||
"name": "test_tinyint",
|
||||
"type": "TINYINT",
|
||||
"null": false
|
||||
},
|
||||
"test_smallint": {
|
||||
"name": "test_smallint",
|
||||
"type": "SMALLINT",
|
||||
"null": false
|
||||
},
|
||||
"test_int": {
|
||||
"name": "test_int",
|
||||
"type": "INT",
|
||||
"null": false
|
||||
},
|
||||
"test_bigint": {
|
||||
"name": "test_bigint",
|
||||
"type": "BIGINT",
|
||||
"null": false
|
||||
},
|
||||
"test_datetime": {
|
||||
"name": "test_datetime",
|
||||
"type": "DATETIME",
|
||||
"null": false
|
||||
},
|
||||
"test_null": {
|
||||
"name": "test_null",
|
||||
"type": "VARCHAR(2)",
|
||||
"default": null,
|
||||
"null": true
|
||||
},
|
||||
"test_default": {
|
||||
"name": "test_default",
|
||||
"type": "VARCHAR(10)",
|
||||
"default": "TeSt1",
|
||||
"null": true
|
||||
},
|
||||
"test_foreign": {
|
||||
"name": "test_foreign",
|
||||
"type": "INT",
|
||||
"default": null,
|
||||
"null": true,
|
||||
"foreignTable": "test_foreign",
|
||||
"foreignKey": "test_foreign_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,13 +19,14 @@ class QueryTypeTest extends \PHPUnit\Framework\TestCase
|
|||
{
|
||||
public function testEnums() : void
|
||||
{
|
||||
self::assertEquals(12, \count(QueryType::getConstants()));
|
||||
self::assertEquals(13, \count(QueryType::getConstants()));
|
||||
self::assertEquals(QueryType::getConstants(), array_unique(QueryType::getConstants()));
|
||||
|
||||
self::assertEquals(128, QueryType::DROP);
|
||||
self::assertEquals(128, QueryType::DROP_DATABASE);
|
||||
self::assertEquals(129, QueryType::ALTER);
|
||||
self::assertEquals(130, QueryType::TABLES);
|
||||
self::assertEquals(131, QueryType::FIELDS);
|
||||
self::assertEquals(132, QueryType::CREATE_TABLE);
|
||||
self::assertEquals(133, QueryType::DROP_TABLE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user