- Work done on many-to-many relations - code must still be refactored out of the EntityTrait.
- Fixed Entity::field("propertyname") function to look for name into @Field() annotation and returns it if it exists. - A lot of bug fixes made into SQL fragments.
This commit is contained in:
parent
6e84fc7195
commit
c64c7778bd
|
@ -20,6 +20,8 @@ class Relation implements \Ulmus\Annotation\Annotation {
|
||||||
|
|
||||||
public string $entity;
|
public string $entity;
|
||||||
|
|
||||||
|
public string $function = "loadAll";
|
||||||
|
|
||||||
public function __construct(string $type = null)
|
public function __construct(string $type = null)
|
||||||
{
|
{
|
||||||
if ( $type !== null ) {
|
if ( $type !== null ) {
|
||||||
|
@ -32,4 +34,10 @@ class Relation implements \Ulmus\Annotation\Annotation {
|
||||||
|
|
||||||
return new $e();
|
return new $e();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function bridge() {
|
||||||
|
$e = $this->bridge;
|
||||||
|
|
||||||
|
return new $e();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
namespace Ulmus\Common;
|
namespace Ulmus\Common;
|
||||||
|
|
||||||
use Ulmus\Ulmus;
|
use Ulmus\Ulmus,
|
||||||
|
Ulmus\Annotation\Property\Field;
|
||||||
|
|
||||||
class EntityField
|
class EntityField
|
||||||
{
|
{
|
||||||
|
@ -14,20 +15,19 @@ class EntityField
|
||||||
|
|
||||||
protected EntityResolver $entityResolver;
|
protected EntityResolver $entityResolver;
|
||||||
|
|
||||||
public function __construct(string $entityClass, string $name, string $alias)
|
public function __construct(string $entityClass, string $name, string $alias, EntityResolver $resolver)
|
||||||
{
|
{
|
||||||
$this->entityClass = $entityClass;
|
$this->entityClass = $entityClass;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->alias = $alias;
|
$this->alias = $alias;
|
||||||
$this->entityResolver = Ulmus::resolveEntity(static::class);
|
$this->entityResolver = $resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function name($useAlias = true) : string
|
public function name($useAlias = true) : string
|
||||||
{
|
{
|
||||||
# Must use REFLECTION before throwing this value.
|
$name = $this->entityResolver->searchFieldAnnotation($this->name, new Field() )->name ?? $this->name;
|
||||||
# Should first check if it's a relation field, and if it is,
|
|
||||||
# it's real key must be returned (PK usually)
|
return $useAlias ? "{$this->alias}.\"{$name}\"" : "\"{$name}\"";
|
||||||
return $useAlias ? "{$this->alias}.\"{$this->name}\"" : "\"{$this->name}\"";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isScalarType($type) : bool
|
public static function isScalarType($type) : bool
|
||||||
|
|
|
@ -94,9 +94,9 @@ class EntityResolver {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
catch(\Throwable $e) {
|
catch(\Throwable $e) {
|
||||||
if ( $throwException) {
|
# if ( $throwException) {
|
||||||
throw new \InvalidArgumentException("Can't find entity relation's column named `$name` from entity {$this->entityClass}");
|
throw new \InvalidArgumentException("Can't find entity relation's column named `$name` from entity {$this->entityClass}");
|
||||||
}
|
# }
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -16,6 +16,7 @@ class PdoObject extends PDO {
|
||||||
return $statement;
|
return $statement;
|
||||||
}
|
}
|
||||||
} catch (\PDOException $e) {
|
} catch (\PDOException $e) {
|
||||||
|
debogueur($sql, $parameters);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +27,7 @@ class PdoObject extends PDO {
|
||||||
return $this->execute($statement, $parameters, true);
|
return $this->execute($statement, $parameters, true);
|
||||||
}
|
}
|
||||||
} catch (\PDOException $e) {
|
} catch (\PDOException $e) {
|
||||||
|
debogueur($sql, $parameters);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +43,7 @@ class PdoObject extends PDO {
|
||||||
if (empty($parameters) ? $statement->execute() : $statement->execute($parameters)) {
|
if (empty($parameters) ? $statement->execute() : $statement->execute($parameters)) {
|
||||||
$statement->lastInsertId = $this->lastInsertId();
|
$statement->lastInsertId = $this->lastInsertId();
|
||||||
|
|
||||||
if ($commit) {
|
if ( $commit ) {
|
||||||
$this->commit();
|
$this->commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Ulmus;
|
namespace Ulmus;
|
||||||
|
|
||||||
use Ulmus\Repository,
|
use Ulmus\Repository,
|
||||||
|
Ulmus\Query,
|
||||||
Ulmus\Common\EntityResolver,
|
Ulmus\Common\EntityResolver,
|
||||||
Ulmus\Common\EntityField;
|
Ulmus\Common\EntityField;
|
||||||
|
|
||||||
|
@ -35,11 +36,17 @@ trait EntityTrait {
|
||||||
$entityResolver = $this->resolveEntity();
|
$entityResolver = $this->resolveEntity();
|
||||||
|
|
||||||
# Resolve relations here if one is called
|
# Resolve relations here if one is called
|
||||||
|
|
||||||
|
# @TODO REFACTOR THIS CODE URGENTLY !
|
||||||
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
|
if ( null !== ( $relation = $entityResolver->searchFieldAnnotation($name, new Relation() ) ) ) {
|
||||||
|
$relationType = strtolower(str_replace(['-', '_'], '', $relation->type));
|
||||||
|
|
||||||
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
|
$order = $entityResolver->searchFieldAnnotationList($name, new OrderBy() );
|
||||||
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
|
$where = $entityResolver->searchFieldAnnotationList($name, new Where() );
|
||||||
|
|
||||||
|
if ( $relation->entity ?? false ) {
|
||||||
$baseEntity = $relation->entity();
|
$baseEntity = $relation->entity();
|
||||||
|
|
||||||
$repository = $baseEntity->repository();
|
$repository = $baseEntity->repository();
|
||||||
|
|
||||||
foreach($where as $condition) {
|
foreach($where as $condition) {
|
||||||
|
@ -55,23 +62,59 @@ trait EntityTrait {
|
||||||
if ( method_exists($this, $filterMethod = "filterRelation$name") ) {
|
if ( method_exists($this, $filterMethod = "filterRelation$name") ) {
|
||||||
$this->$filterMethod($repository);
|
$this->$filterMethod($repository);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch($relation->type) {
|
switch( $relationType ) {
|
||||||
case 'oneToMany':
|
case 'onetoone':
|
||||||
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field); # <<<<<<<<< CHANGE $THIS->ID WITH PROPER NOMENCLATURE
|
|
||||||
|
|
||||||
return $this->$name = $repository->loadAll();
|
|
||||||
|
|
||||||
case 'oneToOne':
|
|
||||||
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field );
|
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field );
|
||||||
|
$result = call_user_func([$repository, $relation->function]);
|
||||||
$result = $repository->loadAll();
|
|
||||||
|
|
||||||
if ( count($result) === 0 ) {
|
if ( count($result) === 0 ) {
|
||||||
return $baseEntity;
|
return $baseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->$name = $result[0];
|
return $this->$name = $result[0];
|
||||||
|
|
||||||
|
case 'onetomany':
|
||||||
|
$repository->where( $baseEntity->field($relation->foreignKey), $this->$field); # <<<<<<<<< CHANGE $THIS->ID WITH PROPER NOMENCLATURE
|
||||||
|
|
||||||
|
return $this->$name = call_user_func([$repository, $relation->function]);
|
||||||
|
|
||||||
|
case 'manytomany':
|
||||||
|
if ( false === $relation->bridge ?? false ) {
|
||||||
|
throw new \Exception("Your many-to-many @Relation() from variable `$name` is missing a 'bridge' value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$bridgeEntity = Ulmus::resolveEntity($relation->bridge);
|
||||||
|
$bridgeRelation = $bridgeEntity->searchFieldAnnotation($relation->field, new Relation() );
|
||||||
|
$relationRelation = $bridgeEntity->searchFieldAnnotation($relation->foreignField, new Relation() );
|
||||||
|
|
||||||
|
$repository = $relationRelation->entity()->repository();
|
||||||
|
|
||||||
|
$bridgeAlias = uniqid("bridge_");
|
||||||
|
$relationAlias = uniqid("relation_");
|
||||||
|
|
||||||
|
$repository->select("{$repository->alias}.*")
|
||||||
|
->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName() . " $bridgeAlias", $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey))
|
||||||
|
->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName() . " $relationAlias", $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias))
|
||||||
|
->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} );
|
||||||
|
|
||||||
|
$this->$name = call_user_func([ $repository, $relationRelation->function ]);
|
||||||
|
|
||||||
|
if ($relation->bridgeField ?? false) {
|
||||||
|
$repository = $relationRelation->entity::repository();
|
||||||
|
|
||||||
|
$repository->select("$bridgeAlias.*")
|
||||||
|
->join(Query\Join::TYPE_INNER, $bridgeEntity->tableName() . " $bridgeAlias", $relation->bridge::field($relationRelation->key, $bridgeAlias), $relationRelation->entity::field($relationRelation->foreignKey))
|
||||||
|
->join(Query\Join::TYPE_INNER, $this->resolveEntity()->tableName() . " $relationAlias", $relation->bridge::field($bridgeRelation->key, $bridgeAlias), static::field($bridgeRelation->foreignKey, $relationAlias))
|
||||||
|
->where( static::field($bridgeRelation->foreignKey, $relationAlias), $this->{$bridgeRelation->foreignKey} );
|
||||||
|
|
||||||
|
$bridgeName = $relation->bridgeField;
|
||||||
|
|
||||||
|
$this->$bridgeName = $repository->collectionFromQuery($relation->bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->$name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -225,16 +268,16 @@ trait EntityTrait {
|
||||||
*/
|
*/
|
||||||
public static function field($name, ? string $alias = null) : EntityField
|
public static function field($name, ? string $alias = null) : EntityField
|
||||||
{
|
{
|
||||||
return new EntityField(static::class, $name, $alias ?: Repository::DEFAULT_ALIAS);
|
return new EntityField(static::class, $name, $alias ?: Repository::DEFAULT_ALIAS, Ulmus::resolveEntity(static::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Ignore
|
* @Ignore
|
||||||
*/
|
*/
|
||||||
public static function fields(...$fields) : string
|
public static function fields(array $fields, ? string $alias = null) : string
|
||||||
{
|
{
|
||||||
return implode(', ', array_map(function($name) {
|
return implode(', ', array_map(function($item) use ($alias){
|
||||||
return static::field($name);
|
return static::field($item, $alias);
|
||||||
}, $fields));
|
}, $fields));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ namespace Ulmus\Query;
|
||||||
|
|
||||||
class Delete extends Fragment {
|
class Delete extends Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "DELETE";
|
||||||
|
|
||||||
public int $order = -100;
|
public int $order = -100;
|
||||||
|
|
||||||
public bool $quick = false;
|
public bool $quick = false;
|
||||||
|
@ -17,7 +19,7 @@ class Delete extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
'DELETE',
|
static::SQL_TOKEN,
|
||||||
( $this->top ? sprintf('TOP (%s)', $this->top) : false ),
|
( $this->top ? sprintf('TOP (%s)', $this->top) : false ),
|
||||||
( $this->priority ?? false ),
|
( $this->priority ?? false ),
|
||||||
( $this->quick ? 'QUICK' : false ),
|
( $this->quick ? 'QUICK' : false ),
|
||||||
|
|
|
@ -4,6 +4,8 @@ namespace Ulmus\Query;
|
||||||
|
|
||||||
class Explain extends Fragment {
|
class Explain extends Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "EXPLAIN";
|
||||||
|
|
||||||
public int $order = -1500;
|
public int $order = -1500;
|
||||||
|
|
||||||
public bool $extended = false;
|
public bool $extended = false;
|
||||||
|
@ -11,7 +13,7 @@ class Explain extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
"EXPLAIN", $this->extended ? "EXTENDED" : ""
|
static::SQL_TOKEN, $this->extended ? "EXTENDED" : ""
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ namespace Ulmus\Query;
|
||||||
|
|
||||||
class From extends Fragment {
|
class From extends Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "FROM";
|
||||||
|
|
||||||
public int $order = -80;
|
public int $order = -80;
|
||||||
|
|
||||||
public array $tables = [];
|
public array $tables = [];
|
||||||
|
@ -27,7 +29,7 @@ class From extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
'FROM', $this->renderTables(),
|
static::SQL_TOKEN, $this->renderTables(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
namespace Ulmus\Query;
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
class GroupBy extends Fragment {
|
class GroupBy extends Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "GROUP BY";
|
||||||
|
|
||||||
public int $order = 70;
|
public int $order = 70;
|
||||||
|
|
||||||
public array $groupBy = [];
|
public array $groupBy = [];
|
||||||
|
@ -22,7 +25,7 @@ class GroupBy extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
'GROUP BY', implode(", ", $this->groupBy)
|
static::SQL_TOKEN, implode(", ", $this->groupBy)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
namespace Ulmus\Query;
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
class Having extends Where {
|
class Having extends Where {
|
||||||
|
const SQL_TOKEN = "HAVING";
|
||||||
|
public int $order = 75;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ namespace Ulmus\Query;
|
||||||
|
|
||||||
class Insert extends Fragment {
|
class Insert extends Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "INSERT";
|
||||||
|
|
||||||
public int $order = -100;
|
public int $order = -100;
|
||||||
|
|
||||||
public bool $quick = false;
|
public bool $quick = false;
|
||||||
|
@ -21,7 +23,7 @@ class Insert extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
'INSERT',
|
static::SQL_TOKEN,
|
||||||
( $this->priority ?? false ),
|
( $this->priority ?? false ),
|
||||||
( $this->ignore ? 'IGNORE' : false ),
|
( $this->ignore ? 'IGNORE' : false ),
|
||||||
'INTO', $this->renderTable(),
|
'INTO', $this->renderTable(),
|
||||||
|
|
|
@ -2,8 +2,12 @@
|
||||||
|
|
||||||
namespace Ulmus\Query;
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
|
use Ulmus\QueryBuilder;
|
||||||
|
|
||||||
class Join extends Fragment {
|
class Join extends Fragment {
|
||||||
|
|
||||||
|
const SQL_TOKEN = "JOIN";
|
||||||
|
|
||||||
const TYPE_LEFT = "LEFT";
|
const TYPE_LEFT = "LEFT";
|
||||||
const TYPE_RIGHT = "RIGHT";
|
const TYPE_RIGHT = "RIGHT";
|
||||||
const TYPE_INNER = "INNER";
|
const TYPE_INNER = "INNER";
|
||||||
|
@ -15,23 +19,32 @@ class Join extends Fragment {
|
||||||
|
|
||||||
public array $joins = [];
|
public array $joins = [];
|
||||||
|
|
||||||
public function add(string $side, string $table, string $field, $value)
|
public string $attachment = "ON";
|
||||||
|
|
||||||
|
public string $side;
|
||||||
|
|
||||||
|
public /*string|QueryBuilder*/ $table;
|
||||||
|
|
||||||
|
public string $field;
|
||||||
|
|
||||||
|
public /*string|QueryBuilder*/ $value;
|
||||||
|
|
||||||
|
public /* QueryBuilder */ $queryBuilder;
|
||||||
|
|
||||||
|
public function __construct(QueryBuilder $queryBuilder) {
|
||||||
|
$this->queryBuilder = $queryBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(string $side, /* QueryBuilder|string */ $table, string $field, /* QueryBuilder|string */ $value)
|
||||||
{
|
{
|
||||||
$this->joins[] = [
|
$this->side = $side;
|
||||||
'side' => $side,
|
$this->table = $table;
|
||||||
'table' => $table,
|
$this->field = $field;
|
||||||
'field' => $field,
|
$this->value = $value;
|
||||||
'value' => $value,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([ $this->side, static::SQL_TOKEN, $this->table, $this->attachment, $this->field, "=", $this->value ]);
|
||||||
#'JOIN',
|
|
||||||
# table,
|
|
||||||
# 'ON',
|
|
||||||
# WHERE ! ,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@ namespace Ulmus\Query;
|
||||||
|
|
||||||
class Limit extends Fragment {
|
class Limit extends Fragment {
|
||||||
|
|
||||||
public int $order = 80;
|
const SQL_TOKEN = "LIMIT";
|
||||||
|
|
||||||
|
public int $order = 90;
|
||||||
|
|
||||||
public int $limit = 0;
|
public int $limit = 0;
|
||||||
|
|
||||||
public string $keyword = "LIMIT %d";
|
|
||||||
|
|
||||||
public function set($limit) : self
|
public function set($limit) : self
|
||||||
{
|
{
|
||||||
$this->limit = $limit;
|
$this->limit = $limit;
|
||||||
|
@ -20,7 +20,7 @@ class Limit extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
sprintf($this->keyword, $this->limit)
|
static::SQL_TOKEN, $this->limit
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@ namespace Ulmus\Query;
|
||||||
|
|
||||||
class Offset extends Fragment {
|
class Offset extends Fragment {
|
||||||
|
|
||||||
public int $order = 81;
|
const SQL_TOKEN = "OFFSET";
|
||||||
|
|
||||||
|
public int $order = 95;
|
||||||
|
|
||||||
protected int $offset = 0;
|
protected int $offset = 0;
|
||||||
|
|
||||||
|
@ -17,7 +19,7 @@ class Offset extends Fragment {
|
||||||
public function render() : string
|
public function render() : string
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
'OFFSET', $this->offset,
|
static::SQL_TOKEN, $this->offset,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
namespace Ulmus\Query;
|
namespace Ulmus\Query;
|
||||||
|
|
||||||
class OrderBy extends Fragment {
|
class OrderBy extends Fragment {
|
||||||
public int $order = 70;
|
public int $order = 80;
|
||||||
|
|
||||||
public array $orderBy = [];
|
public array $orderBy = [];
|
||||||
|
|
||||||
|
const SQL_TOKEN = "ORDER BY";
|
||||||
|
|
||||||
public function set(array $order) : self
|
public function set(array $order) : self
|
||||||
{
|
{
|
||||||
$this->orderBy = $order;
|
$this->orderBy = $order;
|
||||||
|
@ -27,7 +29,7 @@ class OrderBy extends Fragment {
|
||||||
}, $this->orderBy);
|
}, $this->orderBy);
|
||||||
|
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
'ORDER BY', implode(", ", $list)
|
static::SQL_TOKEN, implode(", ", $list)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ class Select extends Fragment {
|
||||||
|
|
||||||
protected array $fields = [];
|
protected array $fields = [];
|
||||||
|
|
||||||
|
const SQL_TOKEN = "SELECT";
|
||||||
|
|
||||||
public function set($fields) : self
|
public function set($fields) : self
|
||||||
{
|
{
|
||||||
$this->fields = is_array($fields) ? $fields : [ $fields ];
|
$this->fields = is_array($fields) ? $fields : [ $fields ];
|
||||||
|
@ -36,7 +38,7 @@ class Select extends Fragment {
|
||||||
{
|
{
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
( $this->union ? 'UNION' : false ),
|
( $this->union ? 'UNION' : false ),
|
||||||
'SELECT',
|
static::SQL_TOKEN,
|
||||||
( $this->top ? sprintf('TOP (%s)', $this->top) : false ),
|
( $this->top ? sprintf('TOP (%s)', $this->top) : false ),
|
||||||
implode(', ', $this->fields)
|
implode(', ', $this->fields)
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -18,6 +18,8 @@ class Where extends Fragment {
|
||||||
const COMPARISON_IS = "IS";
|
const COMPARISON_IS = "IS";
|
||||||
const COMPARISON_NULL = "NULL";
|
const COMPARISON_NULL = "NULL";
|
||||||
|
|
||||||
|
const SQL_TOKEN = "WHERE";
|
||||||
|
|
||||||
public int $order = 50;
|
public int $order = 50;
|
||||||
|
|
||||||
public array $conditionList;
|
public array $conditionList;
|
||||||
|
@ -65,7 +67,7 @@ class Where extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->renderSegments([
|
return $this->renderSegments([
|
||||||
! $this->parent ? "WHERE" : "",
|
! $this->parent ? static::SQL_TOKEN : "",
|
||||||
implode(" ", $stack)
|
implode(" ", $stack)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ class QueryBuilder
|
||||||
{
|
{
|
||||||
public Query\Where $where;
|
public Query\Where $where;
|
||||||
|
|
||||||
|
public Query\Having $having;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Those are the parameters we are going to bind to PDO.
|
* Those are the parameters we are going to bind to PDO.
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +19,9 @@ class QueryBuilder
|
||||||
*/
|
*/
|
||||||
public array $values = [];
|
public array $values = [];
|
||||||
|
|
||||||
public string $conditionOperator = Query\Where::CONDITION_AND;
|
public string $whereConditionOperator = Query\Where::CONDITION_AND;
|
||||||
|
|
||||||
|
public string $havingConditionOperator = Query\Having::CONDITION_AND;
|
||||||
|
|
||||||
protected int $parameterIndex = 0;
|
protected int $parameterIndex = 0;
|
||||||
|
|
||||||
|
@ -166,12 +170,29 @@ class QueryBuilder
|
||||||
$this->push($where);
|
$this->push($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->conditionOperator = $operator;
|
$this->whereConditionOperator = $operator;
|
||||||
$where->add($field, $value, $operator, $condition, $not);
|
$where->add($field, $value, $operator, $condition, $not);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function having($field, $value, string $operator = Query\Having::OPERATOR_EQUAL, string $condition = Query\Having::CONDITION_AND, bool $not = false) : self
|
||||||
|
{
|
||||||
|
if ( $this->having ?? false ) {
|
||||||
|
$having = $this->having;
|
||||||
|
}
|
||||||
|
elseif ( null === ( $having = $this->getFragment(Query\Having::class) ) ) {
|
||||||
|
$this->having = $having = new Query\Having($this);
|
||||||
|
$this->push($having);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->havingConditionOperator = $operator;
|
||||||
|
$having->add($field, $value, $operator, $condition, $not);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function notWhere($field, $value, string $operator = Query\Where::CONDITION_AND) : self
|
public function notWhere($field, $value, string $operator = Query\Where::CONDITION_AND) : self
|
||||||
{
|
{
|
||||||
return $this->where($field, $value, $operator, true);
|
return $this->where($field, $value, $operator, true);
|
||||||
|
@ -179,7 +200,7 @@ class QueryBuilder
|
||||||
|
|
||||||
public function groupBy() : self
|
public function groupBy() : self
|
||||||
{
|
{
|
||||||
//$this->queryBuilder->groupBy();
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,28 +240,19 @@ class QueryBuilder
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function join(string $type, $table, $field, $value, bool $outer = false) : self
|
public function join(string $type, /*string | QueryBuilder*/ $table, $field, $value, bool $outer = false) : self
|
||||||
{
|
{
|
||||||
if ( null === $join = $this->getFragment(Query\Join::class) ) {
|
#if ( null === $join = $this->getFragment(Query\Join::class) ) {#}
|
||||||
$join = new Query\Join();
|
|
||||||
$this->push($join);
|
|
||||||
}
|
|
||||||
|
|
||||||
$join->add($type, $table, $field, $value);
|
$join = new Query\Join($this);
|
||||||
|
$this->push($join);
|
||||||
|
$join->set($type, $table, $field, $value);
|
||||||
|
|
||||||
$join->outer = $outer;
|
$join->outer = $outer;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
"LEFT JOIN PAI_DOS ON PAI_DOS.MATR = PAI_DOS_EMPL.MATR"
|
|
||||||
"LEFT JOIN PAI_DOS_2 ON PAI_DOS_2.MATR = PAI_DOS.MATR"
|
|
||||||
"LEFT JOIN PAI_CAND ON PAI_CAND.MATR = PAI_DOS.MATR"
|
|
||||||
|
|
||||||
"LEFT JOIN PAI_TAB_CORP_EMPL ON PAI_TAB_CORP_EMPL.CORP_EMPL = PAI_DOS_EMPL.CORP_EMPL",
|
|
||||||
"LEFT JOIN PAI_TAB_LIEU_TRAV ON PAI_TAB_LIEU_TRAV.LIEU_TRAV = PAI_DOS_EMPL.LIEU_TRAV",
|
|
||||||
"LEFT JOIN PAI_TAB_BAT ON PAI_TAB_BAT.BAT = PAI_TAB_LIEU_TRAV.BAT"
|
|
||||||
*/
|
|
||||||
public function push(Query\Fragment $queryFragment) : self
|
public function push(Query\Fragment $queryFragment) : self
|
||||||
{
|
{
|
||||||
$this->queryStack[] = $queryFragment;
|
$this->queryStack[] = $queryFragment;
|
||||||
|
@ -266,7 +278,8 @@ class QueryBuilder
|
||||||
public function reset() : void
|
public function reset() : void
|
||||||
{
|
{
|
||||||
$this->parameters = $this->values = $this->queryStack = [];
|
$this->parameters = $this->values = $this->queryStack = [];
|
||||||
$this->conditionOperator = Query\Where::CONDITION_AND;
|
$this->whereConditionOperator = Query\Where::CONDITION_AND;
|
||||||
|
$this->havingConditionOperator = Query\Having::CONDITION_AND;
|
||||||
$this->parameterIndex = 0;
|
$this->parameterIndex = 0;
|
||||||
|
|
||||||
unset($this->where);
|
unset($this->where);
|
||||||
|
|
|
@ -53,15 +53,11 @@ class Repository
|
||||||
|
|
||||||
public function count() : int
|
public function count() : int
|
||||||
{
|
{
|
||||||
$this->select("count(*) as totalItem")->selectSqlQuery();
|
$this->select("COUNT(*)")->selectSqlQuery();
|
||||||
|
|
||||||
$this->finalizeQuery();
|
$this->finalizeQuery();
|
||||||
|
|
||||||
foreach(Ulmus::iterateQueryBuilder($this->queryBuilder, $this->adapter) as $entityData) {
|
return Ulmus::runSelectQuery($this->queryBuilder, $this->adapter)->fetchColumn(0);
|
||||||
return $entityData['totalItem'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteOne()
|
public function deleteOne()
|
||||||
|
@ -157,7 +153,7 @@ class Repository
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(array $fieldlist, string $table, string $alias, ? string $schema) : self
|
public function update(string $table, string $alias, ? string $schema) : self
|
||||||
{
|
{
|
||||||
$this->queryBuilder->update($table, $alias, $schema);
|
$this->queryBuilder->update($table, $alias, $schema);
|
||||||
|
|
||||||
|
@ -239,18 +235,36 @@ class Repository
|
||||||
|
|
||||||
public function orNot($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
public function orNot($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
{
|
{
|
||||||
$this->queryBuilder->notWhere($condition, Query\Where::CONDITION_OR, true);
|
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR, true);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function having() : self
|
public function having($field, $value, string $operator = Query\Having::OPERATOR_EQUAL) : self
|
||||||
{
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_AND);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notHaving() : self
|
public function orHaving($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
{
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_OR);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notHaving($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_AND, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orNotHaving($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, Query\Having::CONDITION_OR, true);
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,10 +376,10 @@ class Repository
|
||||||
return $this->where($primaryKeyField[$pkField]->name ?? $pkField, $value);
|
return $this->where($primaryKeyField[$pkField]->name ?? $pkField, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function collectionFromQuery() : EntityCollection
|
public function collectionFromQuery(? string $entityClass = null) : EntityCollection
|
||||||
{
|
{
|
||||||
|
|
||||||
$class = $this->entityClass;
|
$class = $entityClass ?: $this->entityClass;
|
||||||
|
|
||||||
$entityCollection = new EntityCollection();
|
$entityCollection = new EntityCollection();
|
||||||
|
|
||||||
|
@ -401,7 +415,7 @@ class Repository
|
||||||
protected function updateSqlQuery(array $dataset) : self
|
protected function updateSqlQuery(array $dataset) : self
|
||||||
{
|
{
|
||||||
if ( null === $this->queryBuilder->getFragment(Query\Update::class) ) {
|
if ( null === $this->queryBuilder->getFragment(Query\Update::class) ) {
|
||||||
$this->update($dataset, $this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
|
$this->update($this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set($dataset);
|
$this->set($dataset);
|
||||||
|
|
|
@ -41,12 +41,14 @@ abstract class Ulmus
|
||||||
return ( $adapter ?: static::$defaultAdapter )->pdo();
|
return ( $adapter ?: static::$defaultAdapter )->pdo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function runSelectQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null)
|
||||||
|
{
|
||||||
|
return static::pdo($adapter)->select($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
|
||||||
|
}
|
||||||
|
|
||||||
public static function runQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null)
|
public static function runQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null)
|
||||||
{
|
{
|
||||||
$result = static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
|
return static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
|
||||||
$queryBuilder->reset();
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function resolveEntity(string $entityClass) : Common\EntityResolver
|
public static function resolveEntity(string $entityClass) : Common\EntityResolver
|
||||||
|
|
Loading…
Reference in New Issue