- Still working on Update and Insert statements

This commit is contained in:
Dave M. 2020-02-05 23:41:57 -05:00
parent 828daffec8
commit 3dc82b1f0d
11 changed files with 243 additions and 62 deletions

View File

@ -9,6 +9,7 @@ class Id extends \Ulmus\Annotation\Property\Field {
$this->nullable = false; $this->nullable = false;
$this->attributes['unsigned'] = true; $this->attributes['unsigned'] = true;
$this->attributes['primary_key'] = true; $this->attributes['primary_key'] = true;
$this->attributes['auto_increment'] = true;
parent::__construct('int'); parent::__construct('int');
} }

View File

@ -2,14 +2,12 @@
namespace Ulmus\Common; namespace Ulmus\Common;
use PDO, PDOStatement; use PDO,
PDOStatement;
class PdoObject extends PDO { class PdoObject extends PDO {
public function select(string $sql, array $parameters = []) : PDOStatement public function select(string $sql, array $parameters = []): PDOStatement {
{
# var_dump($sql, $parameters);
# die();
try { try {
if (false !== ( $statement = $this->prepare($sql) )) { if (false !== ( $statement = $this->prepare($sql) )) {
$statement = $this->execute($statement, $parameters, false); $statement = $this->execute($statement, $parameters, false);
@ -17,33 +15,36 @@ class PdoObject extends PDO {
return $statement; return $statement;
} }
} catch (\PDOException $e) { throw $e; } } catch (\PDOException $e) {
throw $e;
}
} }
public function runQuery(string $sql, array $parameters = []) : PDOStatement public function runQuery(string $sql, array $parameters = []): PDOStatement {
{
try { try {
if (false !== ( $statement = $this->prepare($sql) )) { if (false !== ( $statement = $this->prepare($sql) )) {
return $this->execute($statement, $parameters, true); return $this->execute($statement, $parameters, true);
} }
} catch (\PDOException $e) { throw $e; } } catch (\PDOException $e) {
throw $e;
}
} }
public function execute(PDOStatement $statement, array $parameters = [], bool $commit = true) : ? PDOStatement public function execute(PDOStatement $statement, array $parameters = [], bool $commit = true): ?PDOStatement {
{
try { try {
if (!$this->inTransaction()) { if (!$this->inTransaction()) {
$this->beginTransaction(); $this->beginTransaction();
} }
if (empty($parameters) ? $statement->execute() : $statement->execute($parameters)) { if (empty($parameters) ? $statement->execute() : $statement->execute($parameters)) {
$statement->lastInsertId = $this->lastInsertId();
if ($commit) { if ($commit) {
$this->commit(); $this->commit();
} }
return $statement; return $statement;
} } else {
else {
throw new PDOException('Could not begin transaction or given statement is invalid.'); throw new PDOException('Could not begin transaction or given statement is invalid.');
} }
} catch (\PDOException $e) { } catch (\PDOException $e) {

View File

@ -121,11 +121,21 @@ trait EntityTrait {
public function entityGetDataset() : array public function entityGetDataset() : array
{ {
$fields = array_keys($this->resolveEntity()->fieldList()); $dataset = [];
$entityResolver = $this->resolveEntity();
return array_combine($fields, array_map(function(string $key) { foreach($entityResolver->fieldList() as $key => $field) {
return $this->$key; $annotation = $entityResolver->searchFieldAnnotation($key, new Field() );
}, $fields));
if ( isset($this->$key) ) {
$dataset[ $annotation->name ?? $key ] = $this->$key;
}
elseif ( $field['nullable'] ) {
$dataset[ $annotation->name ?? $key ] = null;
}
}
return $dataset;
} }
public function toArray() : array public function toArray() : array

View File

@ -0,0 +1,5 @@
<?php
namespace Ulmus\Exception;
class EntityRequiredField extends \RuntimeException {}

View File

@ -31,6 +31,6 @@ class Insert extends Fragment {
protected function renderTable() : string protected function renderTable() : string
{ {
return $this->table . ( $this->alias ? " {$this->alias}" : "" ); return $this->table;
} }
} }

45
src/Query/Set.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace Ulmus\Query;
use Ulmus\QueryBuilder;
class Set extends Fragment {
public int $order = 0;
public array $dataset;
public QueryBuilder $queryBuilder;
public function __construct(QueryBuilder $queryBuilder)
{
$this->queryBuilder = $queryBuilder;
}
public function set(array $dataset) : self
{
$this->dataset = $dataset;
return $this;
}
public function render() : string
{
return $this->renderSegments([
'SET', $this->renderParameterPlaceholders(),
]);
}
public function renderParameterPlaceholders() : string
{
$keys = [];
foreach($this->dataset as $key =>$value) {
$this->queryBuilder->addParameter($value, ":v_$key");
$keys[] = "$key=:v_$key";
}
return implode(",", $keys);
}
}

35
src/Query/Update.php Normal file
View File

@ -0,0 +1,35 @@
<?php
namespace Ulmus\Query;
class Update extends Fragment {
public int $order = -100;
public bool $quick = false;
public bool $ignore = false;
public array $fieldlist = [];
public string $priority;
public string $table;
public ? string $alias = null;
public function render() : string
{
return $this->renderSegments([
'UPDATE',
( $this->priority ?? false ),
( $this->ignore ? 'IGNORE' : false ),
$this->table,
]);
}
protected function renderTable() : string
{
return $this->table;
}
}

View File

@ -2,10 +2,14 @@
namespace Ulmus\Query; namespace Ulmus\Query;
use Ulmus\QueryBuilder;
class Values extends Fragment { class Values extends Fragment {
public int $order = 0; public int $order = 0;
public ? int $fieldCount = null;
public array $rows; public array $rows;
public QueryBuilder $queryBuilder; public QueryBuilder $queryBuilder;
@ -17,36 +21,38 @@ class Values extends Fragment {
public function add(array $row) : self public function add(array $row) : self
{ {
$this->rows[] = $row; if ($this->fieldCount === null) {
$this->fieldCount = count($row);
}
$this->rows[] = array_values($row);
return $this; return $this;
} }
public function render() : string public function render() : string
{ {
$this->queryBuilder->addParameter($this->flattenRowsArray()); $this->queryBuilder->addValues($this->flattenRowsArray());
return $this->renderSegments([ return $this->renderSegments([
'VALUES', '(' . $this->renderParameterPlaceholders() . ')', 'VALUES', $this->renderParameterPlaceholders(),
]); ]);
} }
public function renderParameterPlaceholders() : string public function renderParameterPlaceholders() : string
{ {
$return = []; $return = [];
$count = null;
foreach($this->rows as $row) { foreach($this->rows as $row) {
if ($count === null) { if ($this->fieldCount === null) {
$count = count($row);
} }
else { else {
if (count($row) !== $count) { if (count($row) !== $this->fieldCount) {
throw new \Exception("Insert statement must contains the same number of values for each rows."); throw new \Exception("Insert statement must contains the same number of values for each rows.");
} }
} }
$return[] = implode(',', array_fill(0, $this->parameterCount, '?')); $return[] = implode(',', array_fill(0, $this->fieldCount, '?'));
} }
return "(" . implode('),(', $return) . ")"; return "(" . implode('),(', $return) . ")";
@ -54,6 +60,6 @@ class Values extends Fragment {
public function flattenRowsArray() : array public function flattenRowsArray() : array
{ {
return iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($this->rows))); return \iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($this->rows)));
} }
} }

View File

@ -51,7 +51,7 @@ class QueryBuilder
$insert = new Query\Insert(); $insert = new Query\Insert();
$this->push($insert); $this->push($insert);
$insert->fieldist = $fieldlist; $insert->fieldlist = $fieldlist;
$insert->alias = $alias; $insert->alias = $alias;
$insert->table = $table; $insert->table = $table;
} }
@ -63,7 +63,7 @@ class QueryBuilder
{ {
if ( false === ( $values = $this->has(Query\Values::class) ) ) { if ( false === ( $values = $this->has(Query\Values::class) ) ) {
$values = new Query\Values(); $values = new Query\Values($this);
$this->push($values); $this->push($values);
} }
@ -72,6 +72,40 @@ class QueryBuilder
return $this; return $this;
} }
public function update(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
{
if ( ! $this->has(Query\Update::class) ) {
if ( $database ) {
$table = "\"$database\".$table";
}
if ( $schema ) {
$table = "\"$schema\".$table";
}
$update = new Query\Update();
$this->push($update);
$update->alias = $alias;
$update->table = $table;
}
return $this;
}
public function set(array $dataset) : self
{
if ( false === ( $values = $this->has(Query\Set::class) ) ) {
$set = new Query\Set($this);
$this->push($set);
}
$set->set($dataset);
return $this;
}
public function delete() : self public function delete() : self
{ {
if ( ! $this->has(Query\Delete::class) ) { if ( ! $this->has(Query\Delete::class) ) {
@ -180,12 +214,14 @@ class QueryBuilder
} }
$orderBy->add($field, $direction); $orderBy->add($field, $direction);
return $this; return $this;
} }
public function push(Query\Fragment $queryFragment) : self public function push(Query\Fragment $queryFragment) : self
{ {
$this->queryStack[] = $queryFragment; $this->queryStack[] = $queryFragment;
return $this; return $this;
} }
@ -226,10 +262,12 @@ class QueryBuilder
} }
$this->parameters[$key] = $value; $this->parameters[$key] = $value;
return $key; return $key;
} }
public function addValues(array $values) { public function addValues(array $values) : void
{
$this->values = $values; $this->values = $values;
} }
} }

View File

@ -75,12 +75,28 @@ class Repository
public function save(object $entity) : bool public function save(object $entity) : bool
{ {
$dataset = $entity->toArray(); $dataset = $entity->toArray();
$primaryKeyDefinition = Ulmus::resolveEntity($this->entityClass)->getPrimaryKeyField();
if ( ! $entity->isLoaded() ) { if ( ! $entity->isLoaded() ) {
$save = $this->insertSqlQuery($dataset)->runQuery(); $statement = $this->insertSqlQuery($dataset)->runQuery();
if ( ( 0 !== $statement->lastInsertId ) &&
( null !== $primaryKeyDefinition )) {
$pkField = key($primaryKeyDefinition);
$entity->$pkField = $statement->lastInsertId;
}
} }
else { else {
$save = $this->updateSqlQuery($dataset)->runQuery(); if ($primaryKeyDefinition === null) {
throw new \Exception(sprintf("No primary key found for entity %s", $this->entityClass));
}
$pkField = key($primaryKeyDefinition);
$pkFieldName = $primaryKeyDefinition[$pkField]->name ?? $pkField;
$this->where($pkFieldName, $dataset[$pkFieldName]);
# DATASET MUST BE DIFF OF MODIF ONLY !
$update = $this->updateSqlQuery($dataset)->runQuery();
} }
return false; return false;
@ -119,6 +135,20 @@ class Repository
return $this; return $this;
} }
public function update(array $fieldlist, string $table, string $alias, ? string $schema) : self
{
$this->queryBuilder->update($table, $alias, $schema);
return $this;
}
public function set(array $dataset) : self
{
$this->queryBuilder->set($dataset);
return $this;
}
public function delete() : self public function delete() : self
{ {
$this->queryBuilder->delete($this->alias); $this->queryBuilder->delete($this->alias);
@ -176,7 +206,7 @@ class Repository
return $this; return $this;
} }
public function notWhere(array $condition) : self public function notWhere($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
{ {
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND, true); $this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND, true);
@ -269,18 +299,21 @@ class Repository
public function orderBy(string $field, ? string $direction = null) : self public function orderBy(string $field, ? string $direction = null) : self
{ {
$this->queryBuilder->orderBy($field, $direction); $this->queryBuilder->orderBy($field, $direction);
return $this; return $this;
} }
public function limit(int $value) : self public function limit(int $value) : self
{ {
$this->queryBuilder->limit($value); $this->queryBuilder->limit($value);
return $this; return $this;
} }
public function offset(int $value) : self public function offset(int $value) : self
{ {
$this->queryBuilder->offset($value); $this->queryBuilder->offset($value);
return $this; return $this;
} }
@ -314,7 +347,7 @@ class Repository
return $entityCollection; return $entityCollection;
} }
public function runQuery() public function runQuery() : \PDOStatement
{ {
return Ulmus::runQuery($this->queryBuilder); return Ulmus::runQuery($this->queryBuilder);
} }
@ -322,10 +355,10 @@ class Repository
protected function insertSqlQuery(array $dataset) : self protected function insertSqlQuery(array $dataset) : self
{ {
if ( ! $this->queryBuilder->has(Query\Insert::class) ) { if ( ! $this->queryBuilder->has(Query\Insert::class) ) {
$this->insert(array_keys($dataset)); $this->insert(array_keys($dataset), $this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
} }
$this->values(count($dataset)); $this->values($dataset);
return $this; return $this;
} }
@ -333,9 +366,11 @@ class Repository
protected function updateSqlQuery(array $dataset) : self protected function updateSqlQuery(array $dataset) : self
{ {
if ( ! $this->queryBuilder->has(Query\Update::class) ) { if ( ! $this->queryBuilder->has(Query\Update::class) ) {
# $this->insert(); $this->update($dataset, $this->entityResolver->tableName(), $this->alias, $this->entityResolver->schemaName());
} }
$this->set($dataset);
return $this; return $this;
} }

View File

@ -32,9 +32,14 @@ abstract class Ulmus
]; ];
} }
public static function pdo(?ConnectionAdapter $adapter = null) : Common\PdoObject
{
return ( $adapter ?: static::$defaultAdapter )->pdo;
}
public static function runQuery(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null) public static function runQuery(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null)
{ {
return ( $adapter ?: static::$defaultAdapter )->pdo->runQuery($queryBuilder->render(), $queryBuilder->parameters ?? []); return static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
} }
public static function resolveEntity(string $entityClass) : Common\EntityResolver public static function resolveEntity(string $entityClass) : Common\EntityResolver