- Added a new Field Mapper to SQLs Adapters.

- Defined missing MySQL fields attributes
- WIP on lean-console's migration methods
This commit is contained in:
Dave Mc Nicoll 2024-10-21 18:12:24 +00:00
parent 5f4f23a8e4
commit 411992c7a8
17 changed files with 214 additions and 8 deletions

View File

@ -2,12 +2,15 @@
namespace Ulmus\Adapter; namespace Ulmus\Adapter;
use Ulmus\ConnectionAdapter;
use Ulmus\Entity\Mysql\Table;
use Ulmus\Migration\FieldDefinition; use Ulmus\Migration\FieldDefinition;
use Ulmus\Migration\MigrateInterface; use Ulmus\Migration\MigrateInterface;
use Ulmus\QueryBuilder\Sql; use Ulmus\QueryBuilder\Sql;
use Ulmus\Common\PdoObject; use Ulmus\Common\PdoObject;
use Ulmus\Exception\AdapterConfigurationException; use Ulmus\Exception\AdapterConfigurationException;
use Ulmus\Repository;
class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
use SqlAdapterTrait; use SqlAdapterTrait;
@ -166,4 +169,12 @@ class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
{ {
return Sql\MysqlQueryBuilder::class; return Sql\MysqlQueryBuilder::class;
} }
public function schemaTable(ConnectionAdapter $adapter, $databaseName, string $tableName) : null|object
{
return Table::repository(Repository::DEFAULT_ALIAS, $adapter)
->select(\Ulmus\Common\Sql::raw('this.*'))
->where($this->escapeIdentifier('table_schema', AdapterInterface::IDENTIFIER_FIELD), $databaseName)
->loadOneFromField($this->escapeIdentifier('table_name', AdapterInterface::IDENTIFIER_FIELD), $tableName);
}
} }

View File

@ -28,4 +28,14 @@ class MySQLFieldMapper extends SqlFieldMapper
parent::map(); parent::map();
} }
} }
public function postProcess() : void
{
if (
in_array($this->type, [ 'BLOB', 'TINYBLOB', 'MEDIUMBLOB', 'LONGBLOB', 'JSON', 'TEXT', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT', 'GEOMETRY' ]) &&
! is_object($this->field->default ?? false) # Could be a functional default, which would now be valid
) {
unset($this->field->default);
}
}
} }

View File

@ -97,7 +97,6 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
{ {
$type = $field->type; $type = $field->type;
$length = $field->length; $length = $field->length;
if ( is_a($type, Entity\Field\Date::class, true) || is_a($type, Entity\Field\Time::class, true) || is_a($type, \DateTime::class, true) ) { if ( is_a($type, Entity\Field\Date::class, true) || is_a($type, Entity\Field\Time::class, true) || is_a($type, \DateTime::class, true) ) {
@ -115,6 +114,10 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
break; break;
case "array": case "array":
$type = "JSON";
$length = null;
break;
case "string": case "string":
$type = "TEXT"; $type = "TEXT";
$length = null; $length = null;
@ -130,6 +133,10 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
} }
} }
if (in_array($type, [ 'JSON', 'TEXT', 'BLOB', 'GEOMETRY' ])) {
$field->default = "";
}
return $typeOnly ? $type : $type . ( $length ? "($length" . ")" : "" ); return $typeOnly ? $type : $type . ( $length ? "($length" . ")" : "" );
} }

View File

@ -46,6 +46,9 @@ class SqlFieldMapper
break; break;
case "array": case "array":
$this->type = "JSON";
break;
case "string": case "string":
if ($length && $length <= 255) { if ($length && $length <= 255) {
$this->type = "VARCHAR"; $this->type = "VARCHAR";
@ -75,13 +78,18 @@ class SqlFieldMapper
default: default:
$this->type = strtoupper($type); $this->type = strtoupper($type);
break; break;
} }
$this->postProcess();
} }
public function render() : string public function render() : string
{ {
return $this->type . ( isset($this->length) ? "($this->length)" : "" ); return $this->type . ( isset($this->length) ? "($this->length)" : "" );
} }
public function postProcess() : void
{
}
} }

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Binary extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "binary",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Char extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "char",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Double extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "float",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Json extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "json",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Varbinary extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "varbinary",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Varchar extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "varchar",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Ulmus\Attribute\Property\Field;
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class Year extends \Ulmus\Attribute\Property\Field
{
public function __construct(
public ? string $name = null,
public ? string $type = "year",
public null|int|string $length = null,
public ? int $precision = null,
public array $attributes = [],
public bool $nullable = false,
public mixed $default = null,
public bool $readonly = false,
public string $description = "",
) {}
}

View File

@ -84,11 +84,13 @@ class Column
public function matchFieldDefinition(ReflectedProperty $definition) : bool public function matchFieldDefinition(ReflectedProperty $definition) : bool
{ {
if ($this->nullable === $definition->allowsNull()) { $nullable = $this->nullable === 'YES';
if ($nullable !== $definition->allowsNull()) {
return false; return false;
} }
if (isset($definition->value)) { if ( isset($definition->value) && $this->canHaveDefaultValue() ) {
if ( $definition->value !== $this->defaultValue()) { if ( $definition->value !== $this->defaultValue()) {
return false; return false;
} }
@ -115,4 +117,9 @@ class Column
return $this->default; return $this->default;
} }
protected function canHaveDefaultValue() : bool
{
return true;
}
} }

View File

@ -0,0 +1,15 @@
<?php
namespace Ulmus\Entity\Mysql;
class Column extends \Ulmus\Entity\InformationSchema\Column
{
# TODO ! Handle FUNCTIONAL default value
protected function canHaveDefaultValue(): bool
{
return ! in_array(strtoupper($this->dataType), [
'BLOB', 'TINYBLOB', 'MEDIUMBLOB', 'LONGBLOB', 'JSON', 'TEXT', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT', 'GEOMETRY'
]);
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Ulmus\Entity\Mysql;
use Ulmus\EntityCollection,
Ulmus\Entity\Field\Datetime;
use Ulmus\{Attribute\Obj\Table as TableObj};
use Ulmus\Attribute\Property\{Field, Filter, FilterJoin, Relation, Join, Virtual, Where};
#[TableObj(name: "tables", database: "information_schema")]
class Table extends \Ulmus\Entity\InformationSchema\Table
{
#[Relation(type: "oneToMany", key: "name", foreignKey: [ Column::class, 'tableName' ], entity: Column::class)]
#[Where('TABLE_SCHEMA', fieldValue: [ Column::class, 'tableSchema' ])]
public EntityCollection $columns;
}

View File

@ -251,7 +251,7 @@ trait EntityTrait {
} }
#[Ignore] #[Ignore]
public static function searchRequest(...$arguments) : SearchRequestInterface public static function searchRequest(...$arguments) : SearchRequest\SearchRequestInterface
{ {
return new /* #[SearchRequest\Attribute\SearchRequestParameter(YourEntityClass::class)] */ class(... $arguments) extends SearchRequest\SearchRequest { return new /* #[SearchRequest\Attribute\SearchRequestParameter(YourEntityClass::class)] */ class(... $arguments) extends SearchRequest\SearchRequest {
# Define searchable properties here, some ex: # Define searchable properties here, some ex:

View File

@ -74,8 +74,6 @@ trait SearchRequestFromRequestTrait
case $attribute instanceof SearchWhere: case $attribute instanceof SearchWhere:
case $attribute instanceof SearchLike: case $attribute instanceof SearchLike:
case $attribute instanceof SearchManual: case $attribute instanceof SearchManual:
if ($attribute->toggle) { if ($attribute->toggle) {
$this->$propertyName = !empty($value); $this->$propertyName = !empty($value);
} elseif ($value !== null) { } elseif ($value !== null) {

View File

@ -44,7 +44,7 @@ trait SearchRequestPaginationTrait {
public function pageCount() : int public function pageCount() : int
{ {
return $this->pageCount = ceil($this->count() / $this->limit()); return $this->limit() ? $this->pageCount = ceil($this->count() / $this->limit()) : 1;
} }
public function hasPagination() : int public function hasPagination() : int