- Field mapper is now removed from Adapters and set into it's own object
- Added a PK to Column (IS)
This commit is contained in:
		
							parent
							
								
									9977a25cf5
								
							
						
					
					
						commit
						3c2ae86653
					
				| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| namespace Ulmus\Adapter; | ||||
| 
 | ||||
| use Ulmus\Migration\FieldDefinition; | ||||
| use Ulmus\Migration\MigrateInterface; | ||||
| use Ulmus\QueryBuilder\Sql; | ||||
| use Ulmus\Common\PdoObject; | ||||
| @ -136,7 +137,14 @@ class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function escapeIdentifier(string $segment, int $type) : string  | ||||
|     public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string | ||||
|     { | ||||
|         $mapper = new MySQLFieldMapper($field); | ||||
| 
 | ||||
|         return $typeOnly ? $mapper->type : $mapper->render(); | ||||
|     } | ||||
| 
 | ||||
|     public static function escapeIdentifier(string $segment, int $type) : string | ||||
|     { | ||||
|         switch($type) { | ||||
|             case static::IDENTIFIER_DATABASE: | ||||
| @ -158,5 +166,4 @@ class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface { | ||||
|     { | ||||
|         return Sql\MysqlQueryBuilder::class; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
							
								
								
									
										31
									
								
								src/Adapter/MySQLFieldMapper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Adapter/MySQLFieldMapper.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Ulmus\Adapter; | ||||
| 
 | ||||
| use Ulmus\Migration\FieldDefinition; | ||||
| 
 | ||||
| class MySQLFieldMapper extends SqlFieldMapper | ||||
| { | ||||
|     public readonly string $type; | ||||
| 
 | ||||
|     public readonly string $length; | ||||
| 
 | ||||
|     public function map() : void | ||||
|     { | ||||
|         $type = $this->field->type; | ||||
|         $length = $this->field->length; | ||||
|          | ||||
|         if ( enum_exists($type) ) { | ||||
|             # Haven't found a better way yet to check for BackendEnum without an instance of the object
 | ||||
|             if ( ! method_exists($type, 'tryFrom') ) { | ||||
|                 throw new \Ulmus\Exception\BackedEnumRequired(sprintf("You must define your enum as a BackedEnum instead of an UnitEnum for field '%s'.", $this->field->getColumnName())); | ||||
|             } | ||||
| 
 | ||||
|             $this->length = implode(',', array_map(fn($e) => MySQL::escapeIdentifier($e->value, MySQL::IDENTIFIER_VALUE) , $type::cases())); | ||||
|             $this->type = "ENUM"; | ||||
|         } | ||||
|         else { | ||||
|             parent::map(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -61,7 +61,7 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface | ||||
|     } | ||||
| 
 | ||||
|     # https://sqlite.org/lang_keywords.html
 | ||||
|     public function escapeIdentifier(string $segment, int $type) : string  | ||||
|     public static function escapeIdentifier(string $segment, int $type) : string | ||||
|     { | ||||
|         switch($type) { | ||||
|             default: | ||||
|  | ||||
| @ -4,6 +4,6 @@ namespace Ulmus\Adapter; | ||||
| 
 | ||||
| interface SqlAdapterInterface | ||||
| { | ||||
|     public function escapeIdentifier(string $segment, int $type) : string; | ||||
|     public static function escapeIdentifier(string $segment, int $type) : string; | ||||
|     public function defaultEngine() : ? string; | ||||
| } | ||||
| @ -46,60 +46,9 @@ trait SqlAdapterTrait | ||||
| 
 | ||||
|     public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string | ||||
|     { | ||||
|         $type = $field->type; | ||||
|         $mapper = new SqlFieldMapper($field); | ||||
| 
 | ||||
|         $length = $field->length; | ||||
| 
 | ||||
|         if ( is_a($type, Entity\Field\Date::class, true) ) { | ||||
|             $type = "DATE"; | ||||
|         } | ||||
|         elseif ( is_a($type, Entity\Field\Time::class, true) ) { | ||||
|             $type = "TIME"; | ||||
|         } | ||||
|         elseif ( is_a($type, \DateTime::class, true) ) { | ||||
|             $type = "DATETIME"; | ||||
|         } | ||||
| 
 | ||||
|         switch($type) { | ||||
|             case "bool": | ||||
|                 $type = "TINYINT"; | ||||
|                 $length = 1; | ||||
|                 break; | ||||
| 
 | ||||
|             case "array": | ||||
|             case "string": | ||||
|                 if ($length && $length <= 255) { | ||||
|                     $type = "VARCHAR"; | ||||
|                     break; | ||||
|                 } | ||||
|                 elseif (! $length || ( $length <= 65535 ) ) { | ||||
|                     $type = "TEXT"; | ||||
|                 } | ||||
|                 elseif ( $length <= 16777215 ) { | ||||
|                     $type = "MEDIUMTEXT"; | ||||
|                 } | ||||
|                 elseif ($length <= 4294967295) { | ||||
|                     $type = "LONGTEXT"; | ||||
|                 } | ||||
|                 else { | ||||
|                     throw new \Exception("A column with size bigger than 4GB cannot be created."); | ||||
|                 } | ||||
| 
 | ||||
|                 # Length is unnecessary on TEXT fields
 | ||||
|                 unset($length); | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|             case "float": | ||||
|                 $type = "DOUBLE"; | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 $type = strtoupper($type); | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         return $typeOnly ? $type : $type . ( isset($length) ? "($length" . ( ! empty($precision) ? ",$precision" : "" ) . ")" : "" ); | ||||
|         return $typeOnly ? $mapper->type : $mapper->render(); | ||||
|     } | ||||
| 
 | ||||
|     public function whitelistAttributes(array &$parameters) : void | ||||
|  | ||||
							
								
								
									
										87
									
								
								src/Adapter/SqlFieldMapper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/Adapter/SqlFieldMapper.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Ulmus\Adapter; | ||||
| 
 | ||||
| use Ulmus\Migration\FieldDefinition; | ||||
| 
 | ||||
| class SqlFieldMapper | ||||
| { | ||||
|     public readonly string $type; | ||||
| 
 | ||||
|     public readonly string $length; | ||||
| 
 | ||||
|     public function __construct( | ||||
|         public FieldDefinition $field, | ||||
|     ) { | ||||
|         $this->map(); | ||||
|     } | ||||
| 
 | ||||
|     public function map() : void | ||||
|     { | ||||
|         $type = $this->field->type; | ||||
|         $length = $this->field->length; | ||||
|          | ||||
|         if ( is_a($type, Entity\Field\Date::class, true) ) { | ||||
|             $type = "DATE"; | ||||
|         } | ||||
|         elseif ( is_a($type, Entity\Field\Time::class, true) ) { | ||||
|             $type = "TIME"; | ||||
|         } | ||||
|         elseif ( is_a($type, \DateTime::class, true) ) { | ||||
|             $type = "DATETIME"; | ||||
|         } | ||||
|         elseif ( enum_exists($type) ) { | ||||
|             # Haven't found a better way yet to check for BackendEnum without an instance of the object
 | ||||
|             if ( ! method_exists($type, 'tryFrom') ) { | ||||
|                 throw new \Ulmus\Exception\BackedEnumRequired(sprintf("You must define your enum as a BackedEnum instead of an UnitEnum for field '%s'.", $this->field->getColumnName())); | ||||
|             } | ||||
| 
 | ||||
|             $type = "string"; | ||||
|         } | ||||
| 
 | ||||
|         switch($type) { | ||||
|             case "bool": | ||||
|                 $this->type = "TINYINT"; | ||||
|                 $length = 1; | ||||
|                 break; | ||||
| 
 | ||||
|             case "array": | ||||
|             case "string": | ||||
|                 if ($length && $length <= 255) { | ||||
|                     $this->type = "VARCHAR"; | ||||
|                     break; | ||||
|                 } | ||||
|                 elseif (! $length || ( $length <= 65535 ) ) { | ||||
|                     $this->type = "TEXT"; | ||||
|                 } | ||||
|                 elseif ( $length <= 16777215 ) { | ||||
|                     $this->type = "MEDIUMTEXT"; | ||||
|                 } | ||||
|                 elseif ($length <= 4294967295) { | ||||
|                     $this->type = "LONGTEXT"; | ||||
|                 } | ||||
|                 else { | ||||
|                     throw new \Exception("A column with a length bigger than 4GB cannot be created."); | ||||
|                 } | ||||
| 
 | ||||
|                 # Length is unnecessary on TEXT fields
 | ||||
|                 unset($length); | ||||
| 
 | ||||
|                 break; | ||||
| 
 | ||||
|             case "float": | ||||
|                 $this->type = "DOUBLE"; | ||||
|                 break; | ||||
| 
 | ||||
|             default: | ||||
|                 $this->type = strtoupper($type); | ||||
| 
 | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function render() : string | ||||
|     { | ||||
|         return $this->type . ( isset($this->length) ? "($this->length)" : "" ); | ||||
|     } | ||||
| } | ||||
| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| namespace Ulmus\Entity\InformationSchema; | ||||
| 
 | ||||
| use Notes\Common\ReflectedProperty; | ||||
| use Ulmus\Entity\Field\Datetime; | ||||
| 
 | ||||
| use Ulmus\{Attribute\Obj\Table}; | ||||
| @ -12,6 +13,9 @@ class Column | ||||
| { | ||||
|     use \Ulmus\EntityTrait; | ||||
| 
 | ||||
|     #[Field\Id]
 | ||||
|     public ? id $srs_id; | ||||
| 
 | ||||
|     #[Field(name: "TABLE_CATALOG", length: 512)]
 | ||||
|     public string $tableCatalog; | ||||
| 
 | ||||
| @ -78,4 +82,37 @@ class Column | ||||
|     #[Field(name: "GENERATION_EXPRESSION", type: "longtext")]
 | ||||
|     public ? string $generationExpression; | ||||
| 
 | ||||
|     public function matchFieldDefinition(ReflectedProperty $definition) : bool | ||||
|     { | ||||
|         if ($this->nullable === $definition->allowsNull()) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         if (isset($definition->value)) { | ||||
|             if ( $definition->value !== $this->defaultValue()) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         elseif (! isset($definition->value)) { | ||||
|             if ( ! $this->defaultValueIsNull() ) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|   | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     protected function defaultValueIsNull() : bool | ||||
|     { | ||||
|         return $this->defaultValue() === null; | ||||
|     } | ||||
| 
 | ||||
|     protected function defaultValue() : mixed | ||||
|     { | ||||
|         if (is_numeric($this->default)) { | ||||
|             return (int) $this->default; | ||||
|         } | ||||
| 
 | ||||
|         return $this->default; | ||||
|     } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user