Skip to content

Commit

Permalink
Few bug fixes.
Browse files Browse the repository at this point in the history
Update to version 1.0
  • Loading branch information
dotfry committed Feb 26, 2019
1 parent bb0fe2b commit 2348acc
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
Adds ability to multiple insert of entities or array to database using doctrine schema.

### Notes
* Designed for MySQL
* Designed for MySQL (also works with PostgreSQL)
* Works with custom id generators (need few tweaks)
* Without custom id generator, works only with MySQL AI
* Allows retrive first inserted id \ total updated
* As bonus this package includes <code>HashedIdGenerator</code> that can be used for generate char(25) ids from entity data
* Please note that UPDATE queries with HashedIdGenerator currently didn't support changing Id

### Samples
#### Default usage
Expand All @@ -16,18 +17,39 @@ declare(strict_types = 1);

use \Doctrine\ORM\EntityManagerInterface;
use \SixDreams\Bulk\BulkInsert;
use \SixDreams\Bulk\BulkUpdate;

/**
* Class DbWrite
*/
class DbWrite {
/** @var EntityManagerInterface */
private $manager;

public function createTwoUsers(): int {
/**
* Creates two users in one query.
*
* @return int
*/
public function createTwoUsers(): int
{
$firstInsertedId = (int) (new BulkInsert($this->manager, User::class))
->addEntity(new User('user 1', 'password'))
->addEntity(new User('user 2', 'password'))
->execute();

return $firstInsertedId;
}

/**
* Updates two users in database.
*/
public function updateTwoUsers(): void
{
(new BulkUpdate($this->manager, User::class))
->addEntity(new User(1, 'user 1', 'new_user1_password'))
->addEntity(new User(2, 'user 1', 'new_user2_password'), ['password'])
->execute();
}
}
```
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "6dreams/doctrine-bulk",
"description": "Simple classes that allows bulk operations on doctrine entities.",
"version": "0.0.3",
"version": "1.0",
"type": "library",
"license": "MIT",
"authors": [
Expand Down
12 changes: 11 additions & 1 deletion src/SixDreams/Bulk/BulkInsert.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ public function addEntity(object $entity): BulkInsert

$ret[$field] = $value;
}

$generator = $this->metadata->getGenerator();
$idField = $this->metadata->getIdField();

if ($generator && null === $ret[$idField] ?? null) {
$ret[$idField] = $generator->generateBulk($this->manager, $this->class, $ret);
}

$this->values[] = $ret;

return $this;
Expand Down Expand Up @@ -157,6 +165,8 @@ function (string $column) {

$stmt->execute();

return ($flags & self::FLAG_NO_RETURN_ID) === self::FLAG_NO_RETURN_ID ? null : $this->manager->getConnection()->lastInsertId();
$noLastId = ($flags & self::FLAG_NO_RETURN_ID) === self::FLAG_NO_RETURN_ID || $this->metadata->getGenerator() !== null;

return $noLastId ? null : $this->manager->getConnection()->lastInsertId();
}
}
27 changes: 20 additions & 7 deletions src/SixDreams/Bulk/BulkUpdate.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public function addEntity(object $entity, ?array $fields = null): BulkUpdate
$fields = $fields ? \array_flip($fields) : null;

$where = null;
$data = [];
$data = $flat = [];
foreach ($this->metadata->getFields() as $field => $column) {
if ($field === $this->whereField) {
$where = $this->getClassProperty($this->reflection, $field)->getValue($entity);
Expand All @@ -122,12 +122,18 @@ public function addEntity(object $entity, ?array $fields = null): BulkUpdate
$field
);
$data[$column->getName()] = [$value, $column];
$flat[$column->getName()] = $value;
if (null === $value && !$column->isNullable()) {
throw new NullValueException($this->class, $field);
}
}

if (\count($data)) {
$generator = $this->metadata->getGenerator();
if ($generator && null === $where) {
$where = $generator->generateBulk($this->manager, $this->class, $flat);
}

$this->values[$where] = $data;
}

Expand Down Expand Up @@ -171,32 +177,39 @@ public function getSQL(): array
}

$fields = $this->getAllUsedFields($values);
$idMeta = $this->metadata->getField($this->metadata->getIdField());

$cases = $bindings = [];
$thenId = 0;
foreach ($values as $when => $entity) {
$whenEsc = $this->simpleValue($when);
foreach ($fields as $field) {
if (null === $whenEsc) {
$bindings[':W' . $thenId] = $when;
$bindings[':W' . $thenId] = [$when, $idMeta];
}
if (\array_key_exists($field, $entity)) {
$cases[$field][] = \sprintf(
'WHEN %s THEN %s',
'WHEN %s = %s THEN %s',
$this->escape($idMeta->getName()),
$whenEsc ?? ':W' . $thenId,
$this->simpleValue($entity[$field][0]) ?? ':T' . $thenId
);
if ($this->simpleValue($entity[$field][0]) === null) {
$bindings[':T' . $thenId] = $entity[$field];
}
} else {
$cases[$field][] = \sprintf('WHEN %s THEN %s', $whenEsc ?? ':W' . $thenId, $this->escape($field));
$cases[$field][] = \sprintf(
'WHEN %s = %s THEN %s',
$this->escape($idMeta->getName()),
$whenEsc ?? ':W' . $thenId,
$this->escape($field)
);
}
$thenId++;
}
}
foreach ($cases as $field => &$case) {
$case = \sprintf('SET %s = (%s)', $this->escape($field), \implode(' ', $case));
$case = \sprintf('%s = CASE %s END', $this->escape($field), \implode(' ', $case));
}
unset($case);
$cases = \implode(', ', $cases);
Expand All @@ -210,13 +223,13 @@ public function getSQL(): array
$critEsc = $this->simpleValue($criteria);
$criterias .= $critEsc ?? ':C' . $critId;
if (null === $critEsc) {
$bindings[':C' . $critId] = $criteria;
$bindings[':C' . $critId] = [$criteria, $idMeta];
}
$critId++;
}

$query = \sprintf(
'UPDATE %s %s WHERE %s IN (%s);',
'UPDATE %s SET %s WHERE %s IN (%s);',
$this->escape($this->metadata->getTable()),
$cases,
$this->escape($this->whereField),
Expand Down

0 comments on commit 2348acc

Please sign in to comment.