- Fixed conflicts
This commit is contained in:
commit
325704260b
|
@ -3,6 +3,7 @@
|
||||||
namespace Ulmus\Adapter;
|
namespace Ulmus\Adapter;
|
||||||
|
|
||||||
use Ulmus\Common\PdoObject;
|
use Ulmus\Common\PdoObject;
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
|
||||||
interface AdapterInterface {
|
interface AdapterInterface {
|
||||||
public const IDENTIFIER_FIELD = 1;
|
public const IDENTIFIER_FIELD = 1;
|
||||||
|
@ -10,11 +11,20 @@ interface AdapterInterface {
|
||||||
public const IDENTIFIER_DATABASE = 3;
|
public const IDENTIFIER_DATABASE = 3;
|
||||||
public const IDENTIFIER_SCHEMA = 4;
|
public const IDENTIFIER_SCHEMA = 4;
|
||||||
public const IDENTIFIER_VALUE = 5;
|
public const IDENTIFIER_VALUE = 5;
|
||||||
|
|
||||||
public function connect() : object /* | PdoObject|mixed */;
|
public function connect() : object /* | PdoObject|mixed */;
|
||||||
public function buildDataSourceName() : string;
|
public function buildDataSourceName() : string;
|
||||||
public function setup(array $configuration) : void;
|
public function setup(array $configuration) : void;
|
||||||
public function escapeIdentifier(string $segment, int $type) : string;
|
public function escapeIdentifier(string $segment, int $type) : string;
|
||||||
public function defaultEngine() : ? string;
|
public function defaultEngine() : ? string;
|
||||||
public function writableValue(/* mixed */ $value) /*: mixed*/;
|
|
||||||
|
public function writableValue(/* mixed */ $value); /*: mixed*/
|
||||||
|
|
||||||
|
/* public function databaseName() : string;
|
||||||
|
public function mapFieldType(FieldDefinition $field) : string;
|
||||||
|
public function schemaTable(string $databaseName, string $tableName) /*: object|EntityCollection
|
||||||
|
|
||||||
|
public function repositoryClass() : string;
|
||||||
|
public function queryBuilderClass() : string;
|
||||||
|
public function tableSyntax() : array; */
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Adapter;
|
||||||
|
|
||||||
|
use Ulmus\{Entity\InformationSchema\Table, Migration\FieldDefinition, Repository, QueryBuilder};
|
||||||
|
|
||||||
|
trait DefaultAdapterTrait
|
||||||
|
{
|
||||||
|
public function repositoryClass() : string
|
||||||
|
{
|
||||||
|
return Repository::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function queryBuilderClass() : string
|
||||||
|
{
|
||||||
|
return QueryBuilder::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tableSyntax() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'ai' => "AUTO_INCREMENT",
|
||||||
|
'pk' => "PRIMARY KEY",
|
||||||
|
'unsigned' => "UNSIGNED",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function databaseName() : string
|
||||||
|
{
|
||||||
|
return $this->database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schemaTable(string $databaseName, string $tableName) /* : ? object */
|
||||||
|
{
|
||||||
|
return Table::repository()->where(Table::field('schema'), $databaseName)->loadOneFromField(Table::field('name'), $tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mapFieldType(FieldDefinition $field, bool $typeOnly = false) : string
|
||||||
|
{
|
||||||
|
$type = $field->type;
|
||||||
|
|
||||||
|
$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 . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" );
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,9 +5,16 @@ namespace Ulmus\Adapter;
|
||||||
use Ulmus\Common\PdoObject;
|
use Ulmus\Common\PdoObject;
|
||||||
|
|
||||||
use Ulmus\Exception\AdapterConfigurationException;
|
use Ulmus\Exception\AdapterConfigurationException;
|
||||||
|
|
||||||
use Ulmus\Ulmus;
|
use Ulmus\Ulmus;
|
||||||
|
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
use Ulmus\{Entity\InformationSchema\Table, Repository, QueryBuilder};
|
||||||
|
|
||||||
class MsSQL implements AdapterInterface {
|
class MsSQL implements AdapterInterface {
|
||||||
|
use DefaultAdapterTrait;
|
||||||
|
|
||||||
|
const DSN_PREFIX = "sqlsrv";
|
||||||
|
|
||||||
public int $port;
|
public int $port;
|
||||||
|
|
||||||
|
@ -130,7 +137,7 @@ class MsSQL implements AdapterInterface {
|
||||||
$parts[] = "WSID={$this->wsid}";
|
$parts[] = "WSID={$this->wsid}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "sqlsrv:" . implode(';', $parts);
|
return static::DSN_PREFIX . ":" . implode(';', $parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setup(array $configuration) : void
|
public function setup(array $configuration) : void
|
||||||
|
|
|
@ -2,12 +2,19 @@
|
||||||
|
|
||||||
namespace Ulmus\Adapter;
|
namespace Ulmus\Adapter;
|
||||||
|
|
||||||
|
use Ulmus\Entity\InformationSchema\Table;
|
||||||
|
use Ulmus\QueryBuilder;
|
||||||
|
use Ulmus\Repository;
|
||||||
use Ulmus\Common\PdoObject;
|
use Ulmus\Common\PdoObject;
|
||||||
|
|
||||||
use Ulmus\Exception\AdapterConfigurationException;
|
use Ulmus\Exception\AdapterConfigurationException;
|
||||||
use Ulmus\Ulmus;
|
use Ulmus\Ulmus;
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
|
||||||
class MySQL implements AdapterInterface {
|
class MySQL implements AdapterInterface {
|
||||||
|
use DefaultAdapterTrait;
|
||||||
|
|
||||||
|
const DSN_PREFIX = "mysql";
|
||||||
|
|
||||||
public string $hostname;
|
public string $hostname;
|
||||||
|
|
||||||
|
@ -18,7 +25,7 @@ class MySQL implements AdapterInterface {
|
||||||
public string $password;
|
public string $password;
|
||||||
|
|
||||||
public string $charset = "utf8mb4";
|
public string $charset = "utf8mb4";
|
||||||
|
|
||||||
public ? string $socket;
|
public ? string $socket;
|
||||||
|
|
||||||
public int $port = 3306;
|
public int $port = 3306;
|
||||||
|
@ -69,6 +76,9 @@ class MySQL implements AdapterInterface {
|
||||||
catch(PDOException $ex){
|
catch(PDOException $ex){
|
||||||
throw $ex;
|
throw $ex;
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
$this->password = str_repeat('*', strlen($this->password));
|
||||||
|
}
|
||||||
|
|
||||||
return $pdo;
|
return $pdo;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +102,7 @@ class MySQL implements AdapterInterface {
|
||||||
$parts[] = "charset={$this->charset}";
|
$parts[] = "charset={$this->charset}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "mysql:" . implode(';', $parts);
|
return static::DSN_PREFIX . ":" . implode(';', $parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setup(array $configuration) : void
|
public function setup(array $configuration) : void
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Adapter;
|
||||||
|
|
||||||
|
use Ulmus\Common\PdoObject;
|
||||||
|
|
||||||
|
use Ulmus\Entity\Sqlite\Table;
|
||||||
|
use Ulmus\Exception\AdapterConfigurationException;
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
use Ulmus\{ Repository, QueryBuilder };
|
||||||
|
|
||||||
|
class SQLite implements AdapterInterface {
|
||||||
|
use DefaultAdapterTrait;
|
||||||
|
|
||||||
|
const DSN_PREFIX = "sqlite";
|
||||||
|
|
||||||
|
public string $path;
|
||||||
|
|
||||||
|
public array $pragma;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
? string $path = null,
|
||||||
|
? array $pragma = null
|
||||||
|
) {
|
||||||
|
if ($path !== null) {
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pragma !== null) {
|
||||||
|
$this->pragma = $pragma;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect() : PdoObject
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$pdo = new PdoObject($this->buildDataSourceName(), null, null);
|
||||||
|
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||||
|
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
|
||||||
|
$pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
catch(PDOException $ex){
|
||||||
|
throw $ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildDataSourceName() : string
|
||||||
|
{
|
||||||
|
$parts[] = $this->path;
|
||||||
|
|
||||||
|
return static::DSN_PREFIX . ":" . implode(';', $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setup(array $configuration) : void
|
||||||
|
{
|
||||||
|
$this->path = $configuration['path'] ?? "";
|
||||||
|
$this->pragma = $configuration['pragma'] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
# https://sqlite.org/lang_keywords.html
|
||||||
|
public function escapeIdentifier(string $segment, int $type) : string
|
||||||
|
{
|
||||||
|
switch($type) {
|
||||||
|
case static::IDENTIFIER_DATABASE:
|
||||||
|
case static::IDENTIFIER_TABLE:
|
||||||
|
case static::IDENTIFIER_FIELD:
|
||||||
|
return '"' . trim(str_replace('"', '""', $segment), '"') . '"';
|
||||||
|
|
||||||
|
case static::IDENTIFIER_VALUE:
|
||||||
|
return "'$segment'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defaultEngine(): ? string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function databaseName() : string
|
||||||
|
{
|
||||||
|
$base = basename($this->path);
|
||||||
|
|
||||||
|
return substr($base, 0, strrpos($base, '.') ?: strlen($base));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schemaTable(string $databaseName, string $tableName) /* : ? object */
|
||||||
|
{
|
||||||
|
return Table::repository()->loadOneFromField(Table::field('tableName'), $tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) ) {
|
||||||
|
$type = "TEXT";
|
||||||
|
$length = strlen((string) $type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch($type) {
|
||||||
|
case "bool":
|
||||||
|
$check = sprintf("CHECK (%s IN (0, 1))", $field->getColumnName());
|
||||||
|
|
||||||
|
case "bigint":
|
||||||
|
case "int":
|
||||||
|
$type = "INTEGER";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "array":
|
||||||
|
case "string":
|
||||||
|
$type = "TEXT";
|
||||||
|
$length = null;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "float":
|
||||||
|
$type = "REAL";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$type = "BLOB";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $typeOnly ? $type : $type . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tableSyntax() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'ai' => "AUTOINCREMENT",
|
||||||
|
'pk' => "PRIMARY KEY",
|
||||||
|
'unsigned' => "",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Annotation\Property\Field;
|
||||||
|
|
||||||
|
class Blob extends \Ulmus\Annotation\Property\Field
|
||||||
|
{
|
||||||
|
public function __construct(? string $type = "blob", ? int $length = null)
|
||||||
|
{
|
||||||
|
parent::__construct($type, $length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Annotation\Property\Field;
|
||||||
|
|
||||||
|
class Longblob extends \Ulmus\Annotation\Property\Field
|
||||||
|
{
|
||||||
|
public function __construct(? string $type = "longblob", ? int $length = null)
|
||||||
|
{
|
||||||
|
parent::__construct($type, $length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Annotation\Property\Field;
|
||||||
|
|
||||||
|
class Mediumblob extends \Ulmus\Annotation\Property\Field
|
||||||
|
{
|
||||||
|
public function __construct(? string $type = "mediumblob", ? int $length = null)
|
||||||
|
{
|
||||||
|
parent::__construct($type, $length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Annotation\Property\Field;
|
||||||
|
|
||||||
|
class Blob extends \Ulmus\Annotation\Property\Field
|
||||||
|
{
|
||||||
|
public function __construct(? string $type = "tinyblob", ? int $length = null)
|
||||||
|
{
|
||||||
|
parent::__construct($type, $length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,9 +50,9 @@ class EntityField implements WhereRawParameter
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function generateCreateColumn($field) : string
|
public static function generateCreateColumn(AdapterInterface $adapter, $field) : string
|
||||||
{
|
{
|
||||||
$definition = new FieldDefinition($field);
|
$definition = new FieldDefinition($adapter, $field);
|
||||||
|
|
||||||
return implode(" ", [
|
return implode(" ", [
|
||||||
$definition->getSqlName(),
|
$definition->getSqlName(),
|
||||||
|
|
|
@ -164,7 +164,7 @@ class EntityResolver {
|
||||||
|
|
||||||
public function databaseName() : ? string
|
public function databaseName() : ? string
|
||||||
{
|
{
|
||||||
return $this->tableAnnotation(false)->database ?? $this->databaseAdapter()->adapter()->database ?? null;
|
return $this->tableAnnotation(false)->database ?? $this->databaseAdapter()->adapter()->databaseName() ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sqlAdapter() : \Ulmus\ConnectionAdapter
|
public function sqlAdapter() : \Ulmus\ConnectionAdapter
|
||||||
|
|
|
@ -37,6 +37,8 @@ class ConnectionAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->adapter->setup($connection);
|
$this->adapter->setup($connection);
|
||||||
|
|
||||||
|
unset($this->configuration['connections'][$this->name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConfiguration() : array
|
public function getConfiguration() : array
|
||||||
|
@ -77,7 +79,7 @@ class ConnectionAdapter
|
||||||
*/
|
*/
|
||||||
protected function instanciateAdapter($name) : AdapterInterface
|
protected function instanciateAdapter($name) : AdapterInterface
|
||||||
{
|
{
|
||||||
$class = substr($name, 0, 2) === "\\" ? $name : "\\Ulmus\\Adapter\\$name";
|
$class = substr($name, 0, 2) === "\\" ? $name : sprintf("\\%s\\Adapter\\%s", __NAMESPACE__, $name);
|
||||||
|
|
||||||
return new $class();
|
return new $class();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Entity\Sqlite;
|
||||||
|
|
||||||
|
use Ulmus\EntityCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Table('name' => "sqlite_master")
|
||||||
|
*/
|
||||||
|
class Schema
|
||||||
|
{
|
||||||
|
use \Ulmus\EntityTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
*/
|
||||||
|
public ? string $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public ? string $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'tbl_name')
|
||||||
|
*/
|
||||||
|
public ? string $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public ? int $rootpage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public ? string $sql;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Relation('oneToMany', 'key' => 'tableName', 'foreignKey' => 'tableName', 'entity' => Schema::class)
|
||||||
|
*/
|
||||||
|
public EntityCollection $columns;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Entity\Sqlite;
|
||||||
|
|
||||||
|
use Ulmus\Repository;
|
||||||
|
|
||||||
|
class Table extends Schema
|
||||||
|
{
|
||||||
|
public static function repository(string $alias = Repository::DEFAULT_ALIAS): Repository
|
||||||
|
{
|
||||||
|
return new class(static::class, $alias) extends Repository\SqliteRepository
|
||||||
|
{
|
||||||
|
public function finalizeQuery(): void
|
||||||
|
{
|
||||||
|
$this->select(Table::field('tableName'))->groupBy(Table::field('tableName'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -146,7 +146,12 @@ class EntityCollection extends \ArrayObject {
|
||||||
return $this->filtersCollection(fn($obj) => is_a($obj, $className));
|
return $this->filtersCollection(fn($obj) => is_a($obj, $className));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function column($field, bool $unique = false) : array
|
public function column($field, bool $uniqueValue = false, $keyField = null) : array
|
||||||
|
{
|
||||||
|
return $this->map($field, $keyField, $uniqueValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($field, $keyField = null, bool $uniqueValue = false) : array
|
||||||
{
|
{
|
||||||
$list = [];
|
$list = [];
|
||||||
|
|
||||||
|
@ -158,11 +163,23 @@ class EntityCollection extends \ArrayObject {
|
||||||
$value = $item->$field;
|
$value = $item->$field;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($unique && in_array($value, $list, true)) {
|
if ($uniqueValue && in_array($value, $list, true)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$list[] = $value;
|
if ( $keyField !== null ) {
|
||||||
|
if ( is_callable($keyField) ) {
|
||||||
|
$key = call_user_func_array($keyField, [ $item ]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$key = $item->$keyField;
|
||||||
|
}
|
||||||
|
|
||||||
|
$list[$key] = $value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$list[] = $value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $list;
|
return $list;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use Ulmus\Repository,
|
||||||
|
|
||||||
use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
|
use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
|
||||||
use Ulmus\Annotation\Property\{ Field, Filter, FilterJoin, Relation, OrderBy, Where, OrWhere, Join, Virtual, On, WithJoin, };
|
use Ulmus\Annotation\Property\{ Field, Filter, FilterJoin, Relation, OrderBy, Where, OrWhere, Join, Virtual, On, WithJoin, };
|
||||||
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Text, Mediumtext, Longtext, };
|
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Blob, Text, Mediumtext, Longtext, Tinyblob, Mediumblob, Longblob };
|
||||||
use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore };
|
use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore };
|
||||||
|
|
||||||
trait EntityTrait {
|
trait EntityTrait {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Migration;
|
namespace Ulmus\Migration;
|
||||||
|
|
||||||
|
use Ulmus\Adapter\AdapterInterface;
|
||||||
use Ulmus\Annotation\Property\Field;
|
use Ulmus\Annotation\Property\Field;
|
||||||
use Ulmus\Entity;
|
use Ulmus\Entity;
|
||||||
|
|
||||||
|
@ -25,8 +26,12 @@ class FieldDefinition {
|
||||||
|
|
||||||
public ? string $update;
|
public ? string $update;
|
||||||
|
|
||||||
public function __construct(array $data)
|
public AdapterInterface $adapter;
|
||||||
|
|
||||||
|
public function __construct(AdapterInterface $adapter, array $data)
|
||||||
{
|
{
|
||||||
|
$this->adapter = $adapter;
|
||||||
|
|
||||||
$this->name = $data['name'];
|
$this->name = $data['name'];
|
||||||
$this->builtIn = $data['builtin'];
|
$this->builtIn = $data['builtin'];
|
||||||
$this->tags = $data['tags'];
|
$this->tags = $data['tags'];
|
||||||
|
@ -46,109 +51,57 @@ class FieldDefinition {
|
||||||
|
|
||||||
public function getSqlType(bool $typeOnly = false) : string
|
public function getSqlType(bool $typeOnly = false) : string
|
||||||
{
|
{
|
||||||
$type = $this->type;
|
return $this->adapter->mapFieldType($this, $typeOnly);
|
||||||
|
|
||||||
$length = $this->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 . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSqlParams() : string
|
public function getSqlParams() : string
|
||||||
{
|
{
|
||||||
$default = $this->getDefault();
|
$default = $this->getDefault();
|
||||||
|
$syntax = $this->adapter->tableSyntax();
|
||||||
|
|
||||||
return implode(' ', array_filter([
|
return implode(' ', array_filter([
|
||||||
$this->isUnsigned() ? "UNSIGNED" : null,
|
$this->isUnsigned() ? $syntax['unsigned'] : null,
|
||||||
$this->nullable ? "NULL" : "NOT NULL",
|
$this->nullable ? "NULL" : "NOT NULL",
|
||||||
$this->update ? "ON UPDATE {$this->update}" : null,
|
$this->update ? "ON UPDATE {$this->update}" : null,
|
||||||
$default ? "DEFAULT $default" : null,
|
$default ? "DEFAULT $default" : null,
|
||||||
$this->isAutoIncrement() ? "AUTO_INCREMENT" : null,
|
$this->isPrimaryKey() ? $syntax['pk'] : null,
|
||||||
$this->isPrimaryKey() ? "PRIMARY KEY" : null,
|
$this->isAutoIncrement() ? $syntax['ai'] : null,
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getFieldTag() : ? Field
|
public function getFieldTag() : ? Field
|
||||||
{
|
{
|
||||||
$field = array_filter($this->tags, fn($item) => $item['object'] instanceof Field);
|
$field = array_filter($this->tags, fn($item) => $item['object'] instanceof Field);
|
||||||
|
|
||||||
return array_pop($field)['object'];
|
return array_pop($field)['object'];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getColumnName() : ? string
|
public function getColumnName() : ? string
|
||||||
{
|
{
|
||||||
return $this->getFieldTag()->name ?? $this->name;
|
return $this->getFieldTag()->name ?? $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDefault() : ? string
|
public function getDefault() : ? string
|
||||||
{
|
{
|
||||||
return $this->getFieldTag()->attributes['default'] ?? ( $this->nullable ? "NULL" : null ) ;
|
return $this->getFieldTag()->attributes['default'] ?? ( $this->nullable ? "NULL" : null ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function isPrimaryKey() : bool
|
public function isPrimaryKey() : bool
|
||||||
{
|
{
|
||||||
return $this->getFieldTag()->attributes['primary_key'] ?? false;
|
return $this->getFieldTag()->attributes['primary_key'] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function isAutoIncrement() : bool
|
public function isAutoIncrement() : bool
|
||||||
{
|
{
|
||||||
return $this->getFieldTag()->attributes['auto_increment'] ?? false;
|
return $this->getFieldTag()->attributes['auto_increment'] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function isUnique() : bool
|
public function isUnique() : bool
|
||||||
{
|
{
|
||||||
return $this->getFieldTag()->attributes['unique'] ?? false;
|
return $this->getFieldTag()->attributes['unique'] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function isUnsigned() : bool
|
public function isUnsigned() : bool
|
||||||
{
|
{
|
||||||
return $this->getFieldTag()->attributes['unsigned'] ?? false;
|
return $this->getFieldTag()->attributes['unsigned'] ?? false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Ulmus\Modeler;
|
|
||||||
|
|
||||||
class Schema {
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function compare()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function migrate()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Query;
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
|
use Ulmus\Adapter\AdapterInterface;
|
||||||
use Ulmus\Annotation,
|
use Ulmus\Annotation,
|
||||||
Ulmus\Common\EntityField;
|
Ulmus\Common\EntityField;
|
||||||
|
|
||||||
|
@ -17,7 +18,13 @@ class Alter extends Fragment {
|
||||||
|
|
||||||
public bool $skipExisting = true;
|
public bool $skipExisting = true;
|
||||||
|
|
||||||
public array $fieldList;
|
public array $fieldList;
|
||||||
|
|
||||||
|
public AdapterInterface $adapter;
|
||||||
|
|
||||||
|
public function __construct(AdapterInterface $adapter) {
|
||||||
|
$this->adapter = $adapter;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
|
@ -29,7 +36,7 @@ class Alter extends Fragment {
|
||||||
public function renderFields() : string
|
public function renderFields() : string
|
||||||
{
|
{
|
||||||
return "(" . PHP_EOL . implode("," . PHP_EOL, array_map(function($field) {
|
return "(" . PHP_EOL . implode("," . PHP_EOL, array_map(function($field) {
|
||||||
return " " . EntityField::generateAlterColumn($field);
|
return " " . EntityField::generateAlterColumn($this->adapter, $field);
|
||||||
}, $this->fieldList)) . PHP_EOL . ")";
|
}, $this->fieldList)) . PHP_EOL . ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Ulmus\Query;
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
|
use Ulmus\Adapter\AdapterInterface;
|
||||||
use Ulmus\Annotation,
|
use Ulmus\Annotation,
|
||||||
Ulmus\Common\EntityField;
|
Ulmus\Common\EntityField;
|
||||||
|
|
||||||
|
@ -19,6 +20,12 @@ class Create extends Fragment {
|
||||||
|
|
||||||
public array $fieldList;
|
public array $fieldList;
|
||||||
|
|
||||||
|
public AdapterInterface $adapter;
|
||||||
|
|
||||||
|
public function __construct(AdapterInterface $adapter) {
|
||||||
|
$this->adapter = $adapter;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
|
@ -29,7 +36,7 @@ class Create extends Fragment {
|
||||||
public function renderFields() : string
|
public function renderFields() : string
|
||||||
{
|
{
|
||||||
return "(" . PHP_EOL . implode("," . PHP_EOL, array_map(function($field) {
|
return "(" . PHP_EOL . implode("," . PHP_EOL, array_map(function($field) {
|
||||||
return " " . EntityField::generateCreateColumn($field);
|
return " " . EntityField::generateCreateColumn($this->adapter, $field);
|
||||||
}, $this->fieldList)) . PHP_EOL . ")";
|
}, $this->fieldList)) . PHP_EOL . ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@ class Select extends Fragment {
|
||||||
if ( ! is_numeric($key) ) {
|
if ( ! is_numeric($key) ) {
|
||||||
$value = sprintf(static::FIELD_AS, $value, $key);
|
$value = sprintf(static::FIELD_AS, $value, $key);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Query\Sqlite;
|
||||||
|
|
||||||
|
class Pragma extends \Ulmus\Query\Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "PRAGMA %s%s";
|
||||||
|
|
||||||
|
public int $order = 15;
|
||||||
|
|
||||||
|
public /* object|string */ $pragma;
|
||||||
|
|
||||||
|
public $value;
|
||||||
|
|
||||||
|
public bool $callable;
|
||||||
|
|
||||||
|
public function set(/* object|Stringable */ $pragma, /* ? mixed */ $value = null, bool $callable = false) : self
|
||||||
|
{
|
||||||
|
$this->pragma = $pragma;
|
||||||
|
|
||||||
|
if ($value) {
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->callable = $callable;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() : string
|
||||||
|
{
|
||||||
|
if ( isset($this->value) ) {
|
||||||
|
$value = sprintf($this->callable ? " (%s)" : " = %s", $this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->renderSegments([
|
||||||
|
sprintf(static::SQL_TOKEN, $this->pragma, $value ?? "")
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -329,7 +329,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
|
public function create(Adapter\AdapterInterface $adapter, array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
|
||||||
{
|
{
|
||||||
if ( null === $this->getFragment(Query\Create::class) ) {
|
if ( null === $this->getFragment(Query\Create::class) ) {
|
||||||
if ( $schema ) {
|
if ( $schema ) {
|
||||||
|
@ -340,7 +340,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
$table = "$database.$table";
|
$table = "$database.$table";
|
||||||
}
|
}
|
||||||
|
|
||||||
$create = new Query\Create();
|
$create = new Query\Create($adapter);
|
||||||
$this->push($create);
|
$this->push($create);
|
||||||
|
|
||||||
$create->fieldList = $fieldlist;
|
$create->fieldList = $fieldlist;
|
||||||
|
@ -353,7 +353,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function alter(array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
|
public function alter(Adapter\AdapterInterface $adapter, array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
|
||||||
{
|
{
|
||||||
if ( null === $this->getFragment(Query\Create::class) ) {
|
if ( null === $this->getFragment(Query\Create::class) ) {
|
||||||
if ( $schema ) {
|
if ( $schema ) {
|
||||||
|
@ -364,7 +364,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
$table = "$database.$table";
|
$table = "$database.$table";
|
||||||
}
|
}
|
||||||
|
|
||||||
$alter = new Query\Alter();
|
$alter = new Query\Alter($adapter);
|
||||||
$this->push($alter);
|
$this->push($alter);
|
||||||
|
|
||||||
$alter->fieldList = $fieldlist;
|
$alter->fieldList = $fieldlist;
|
||||||
|
@ -406,7 +406,7 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
$sql = [];
|
$sql = [];
|
||||||
|
|
||||||
usort($this->queryStack, function($q1, $q2) {
|
usort($this->queryStack, function($q1, $q2) {
|
||||||
return $q1->order() <=> $q2->order();
|
return (float) $q1->order <=> (float) $q2->order;
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach($this->queryStack as $fragment) {
|
foreach($this->queryStack as $fragment) {
|
||||||
|
@ -486,13 +486,12 @@ class QueryBuilder implements Query\QueryBuilderInterface
|
||||||
{
|
{
|
||||||
$this->values = $values;
|
$this->values = $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function nextJoinOrder() : float
|
protected function nextJoinOrder() : float
|
||||||
{
|
{
|
||||||
$next = 0;
|
$next = 0;
|
||||||
|
|
||||||
foreach($this->getFragments(Query\Join::class) as $join) {
|
foreach($this->getFragments(Query\Join::class) as $join) {
|
||||||
$next = max($next, $join->joinOrder);
|
$next = max($next, $join->joinOrder - Query\Join::ORDER_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $next + 1;
|
return $next + 1;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\QueryBuilder;
|
||||||
|
|
||||||
|
use Ulmus\QueryBuilder;
|
||||||
|
|
||||||
|
use Ulmus\Query;
|
||||||
|
|
||||||
|
class MssqlQueryBuilder extends QueryBuilder implements Ulmus\Query\QueryBuilderInterface
|
||||||
|
{
|
||||||
|
public function limit(int $value) : self
|
||||||
|
{
|
||||||
|
if ( null === $offset = $this->getFragment(Query\MsSQL\Offset::class) ) {
|
||||||
|
$offset = new Query\MsSQL\Offset();
|
||||||
|
$this->push($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset->limit = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offset(int $value) : self
|
||||||
|
{
|
||||||
|
if ( null === $offset = $this->getFragment(Query\MsSQL\Offset::class) ) {
|
||||||
|
$offset = new Query\MsSQL\Offset();
|
||||||
|
$this->push($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset->offset = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\QueryBuilder;
|
||||||
|
|
||||||
|
use Ulmus\QueryBuilder;
|
||||||
|
|
||||||
|
use Ulmus\Query;
|
||||||
|
|
||||||
|
class SqliteQueryBuilder extends QueryBuilder implements Query\QueryBuilderInterface
|
||||||
|
{
|
||||||
|
public function pragma(/*object|Stringable*/ $name, $value = null, bool $callable = false) : self
|
||||||
|
{
|
||||||
|
if ( null !== ( $pragma = $this->getFragment(Query\Sqlite\Pragma::class) ) ) {
|
||||||
|
$pragma->set($name, $value, $callable);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$pragma = new Query\Sqlite\Pragma();
|
||||||
|
$pragma->set($name, $value, $callable);
|
||||||
|
$this->push($pragma);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ class Repository
|
||||||
$this->alias = $alias;
|
$this->alias = $alias;
|
||||||
$this->entityResolver = Ulmus::resolveEntity($entity);
|
$this->entityResolver = Ulmus::resolveEntity($entity);
|
||||||
$this->adapter = $adapter ?? $this->entityResolver->databaseAdapter();
|
$this->adapter = $adapter ?? $this->entityResolver->databaseAdapter();
|
||||||
$this->queryBuilder = new QueryBuilder();
|
$this->queryBuilder = Ulmus::queryBuilder($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __clone()
|
public function __clone()
|
||||||
|
@ -248,8 +248,6 @@ class Repository
|
||||||
return $update ? (bool) $update->rowCount() : false;
|
return $update ? (bool) $update->rowCount() : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function replace(/*object|array*/ $entity, ? array $fieldsAndValue = null) : bool
|
public function replace(/*object|array*/ $entity, ? array $fieldsAndValue = null) : bool
|
||||||
|
@ -882,13 +880,7 @@ class Repository
|
||||||
public function createSqlQuery() : self
|
public function createSqlQuery() : self
|
||||||
{
|
{
|
||||||
if ( null === $this->queryBuilder->getFragment(Query\Create::class) ) {
|
if ( null === $this->queryBuilder->getFragment(Query\Create::class) ) {
|
||||||
$this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
|
$this->queryBuilder->create($this->adapter->adapter(), $this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
|
||||||
}
|
|
||||||
|
|
||||||
if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) {
|
|
||||||
if ( $engine = $this->entityResolver->tableAnnotation()->engine ?? $this->entityResolver->databaseAdapter()->adapter()->defaultEngine() ) {
|
|
||||||
$this->queryBuilder->engine($engine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -897,7 +889,7 @@ class Repository
|
||||||
public function alterSqlQuery(array $fields) : self
|
public function alterSqlQuery(array $fields) : self
|
||||||
{
|
{
|
||||||
if ( null === $this->queryBuilder->getFragment(Query\Alter::class) ) {
|
if ( null === $this->queryBuilder->getFragment(Query\Alter::class) ) {
|
||||||
$this->queryBuilder->create($this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
|
$this->queryBuilder->create($this->adapter->adapter(), $this->escapeFieldList($this->entityResolver->fieldList(EntityResolver::KEY_ENTITY_NAME, true)), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -933,7 +925,6 @@ class Repository
|
||||||
return new $this->entityClass();
|
return new $this->entityClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function hasFilters() : bool
|
public function hasFilters() : bool
|
||||||
{
|
{
|
||||||
return isset($this->queryBuilder->where);
|
return isset($this->queryBuilder->where);
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Ulmus\Repository;
|
||||||
use Ulmus\{Repository, Query, Ulmus, Common};
|
use Ulmus\{Repository, Query, Ulmus, Common};
|
||||||
|
|
||||||
class MssqlRepository extends Repository {
|
class MssqlRepository extends Repository {
|
||||||
|
/*
|
||||||
protected function finalizeQuery() : void
|
protected function finalizeQuery() : void
|
||||||
{
|
{
|
||||||
if ( null !== $offset = $this->queryBuilder->getFragment(Query\Offset::class) ) {
|
if ( null !== $offset = $this->queryBuilder->getFragment(Query\Offset::class) ) {
|
||||||
|
@ -39,6 +39,30 @@ class MssqlRepository extends Repository {
|
||||||
$this->queryBuilder->removeFragment($limit);
|
$this->queryBuilder->removeFragment($limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected function finalizeQuery() : void
|
||||||
|
{
|
||||||
|
if ( null !== $offset = $this->queryBuilder->getFragment(Query\MsSQL\Offset::class) ) {
|
||||||
|
# an order by is mandatory for mssql offset/limit
|
||||||
|
if ( null === $order = $this->queryBuilder->getFragment(Query\OrderBy::class) ) {
|
||||||
|
$this->orderBy("(SELECT 0)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty ($offset->offset ) ) {
|
||||||
|
if ( null !== $select = $this->queryBuilder->getFragment(Query\Select::class) ) {
|
||||||
|
$select->top = $offset->limit;
|
||||||
|
}
|
||||||
|
elseif ( null !== $delete = $this->queryBuilder->getFragment(Query\Delete::class) ) {
|
||||||
|
$delete->top = $offset->limit;
|
||||||
|
}
|
||||||
|
$this->queryBuilder->removeFragment($offset);
|
||||||
|
}
|
||||||
|
elseif ( empty($offset->limit) ) {
|
||||||
|
throw new \Exception("Your offset query fragment is missing a LIMIT value.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function serverRequestCountRepository() : Repository
|
protected function serverRequestCountRepository() : Repository
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Repository;
|
||||||
|
|
||||||
|
use Ulmus\{Common\EntityResolver, ConnectionAdapter, QueryBuilder, Repository, Query, Ulmus};
|
||||||
|
|
||||||
|
class MysqlRepository extends Repository {
|
||||||
|
|
||||||
|
public function pragma(/*object|Stringable*/ $pragma, $argument = null, bool $callable = false) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->pragma($pragma, $argument, $callable);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createSqlQuery() : self
|
||||||
|
{
|
||||||
|
if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) {
|
||||||
|
if ( $engine = $this->entityResolver->tableAnnotation()->engine ?? $this->entityResolver->databaseAdapter()->adapter()->defaultEngine() ) {
|
||||||
|
$this->queryBuilder->engine($engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::createSqlQuery();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Repository;
|
||||||
|
|
||||||
|
use Ulmus\{ConnectionAdapter, QueryBuilder, Repository, Query, Ulmus};
|
||||||
|
|
||||||
|
class SqliteRepository extends Repository {
|
||||||
|
|
||||||
|
public function pragma(/*object|Stringable*/ $pragma, $argument = null, bool $callable = false) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->pragma($pragma, $argument, $callable);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function finalizeQuery() : void
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function serverRequestCountRepository() : Repository
|
||||||
|
{
|
||||||
|
return new static($this->entityClass, $this->alias, $this->adapter);
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,4 +41,10 @@ trait SearchRequestPaginationTrait {
|
||||||
{
|
{
|
||||||
return $this->pageCount() > 1;
|
return $this->pageCount() > 1;
|
||||||
}
|
}
|
||||||
|
public function skipCount(bool $value) : self
|
||||||
|
{
|
||||||
|
$this->skipCount = $value;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,14 +107,18 @@ abstract class Ulmus
|
||||||
return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass);
|
return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function repository(...$arguments) : Repository
|
public static function repository(string $entityClass, ...$arguments) : Repository
|
||||||
{
|
{
|
||||||
return new static::$repositoryClass(...$arguments);
|
$cls = $entityClass::resolveEntity()->sqlAdapter()->adapter()->repositoryClass();
|
||||||
|
|
||||||
|
return new $cls($entityClass, ...$arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function queryBuilder(...$arguments) : Query\QueryBuilderInterface
|
public static function queryBuilder($entityClass, ...$arguments) : Query\QueryBuilderInterface
|
||||||
{
|
{
|
||||||
return new static::$queryBuilderClass(...$arguments);
|
$cls = $entityClass::resolveEntity()->sqlAdapter()->adapter()->queryBuilderClass();
|
||||||
|
|
||||||
|
return new $cls(...$arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function instanciateObject(string $type, array $arguments) : object
|
public static function instanciateObject(string $type, array $arguments) : object
|
||||||
|
|
Loading…
Reference in New Issue