- 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;
use Ulmus\ConnectionAdapter;
use Ulmus\Entity\Mysql\Table;
use Ulmus\Migration\FieldDefinition;
use Ulmus\Migration\MigrateInterface;
use Ulmus\QueryBuilder\Sql;
use Ulmus\Common\PdoObject;
use Ulmus\Exception\AdapterConfigurationException;
use Ulmus\Repository;
class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
use SqlAdapterTrait;
@ -166,4 +169,12 @@ class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
{
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();
}
}
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
{
$type = $field->type;
$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) ) {
@ -115,6 +114,10 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
break;
case "array":
$type = "JSON";
$length = null;
break;
case "string":
$type = "TEXT";
$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" . ")" : "" );
}

View File

@ -46,6 +46,9 @@ class SqlFieldMapper
break;
case "array":
$this->type = "JSON";
break;
case "string":
if ($length && $length <= 255) {
$this->type = "VARCHAR";
@ -75,13 +78,18 @@ class SqlFieldMapper
default:
$this->type = strtoupper($type);
break;
}
$this->postProcess();
}
public function render() : string
{
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
{
if ($this->nullable === $definition->allowsNull()) {
$nullable = $this->nullable === 'YES';
if ($nullable !== $definition->allowsNull()) {
return false;
}
if (isset($definition->value)) {
if ( isset($definition->value) && $this->canHaveDefaultValue() ) {
if ( $definition->value !== $this->defaultValue()) {
return false;
}
@ -115,4 +117,9 @@ class Column
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]
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 {
# Define searchable properties here, some ex:

View File

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

View File

@ -44,7 +44,7 @@ trait SearchRequestPaginationTrait {
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