Skip to content

Commit

Permalink
persistence insert database test
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubkulhan committed May 29, 2024
1 parent 6d0ec8a commit 7b0e74b
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 27 deletions.
76 changes: 53 additions & 23 deletions data-access-kit/src/Persistence.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

namespace DataAccessKit;

use DataAccessKit\Attribute\Column;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\MariaDBPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use LogicException;
use function array_merge;
use function count;
Expand Down Expand Up @@ -77,27 +81,41 @@ private function insertUpsertAll(array $objects, ?array $upsertColumns = null):
$table = $this->registry->get($objects[0], true);
$platform = $this->connection->getDatabasePlatform();

$columns = [];
$columnNames = [];
$rows = [];
$values = [];
$update = [];
$primaryKey = null;
$generatedColumnNames = [];
/** @var Column[] $generatedColumns */
$generatedColumns = [];
/** @var Column|null $primaryKeyColumn */
$primaryKeyColumn = null;
$supportsReturning = match (true) {
$platform instanceof MariaDBPlatform => true,
$platform instanceof PostgreSQLPlatform => true,
$platform instanceof SQLitePlatform => true,
default => false,
};

foreach ($table->columns as $column) {
if ($column->generated) {
if ($column->primary) {
if ($primaryKey !== null) {
if ($primaryKeyColumn !== null) {
throw new LogicException("Multiple generated primary columns.");
}
$primaryKey = $column;
$primaryKeyColumn = $column;
}
continue;
}

$columns[] = $platform->quoteSingleIdentifier($column->name);
if ($supportsReturning) {
$generatedColumnNames[] = $platform->quoteSingleIdentifier($column->name);
$generatedColumns[] = $column;
}
} else {
$columnNames[] = $platform->quoteSingleIdentifier($column->name);

if ($upsertColumns === null || in_array($column->name, $upsertColumns, true)) {
$update[] = $platform->quoteSingleIdentifier($column->name) . " = VALUES(" . $platform->quoteSingleIdentifier($column->name) . ")";
if ($upsertColumns === null || in_array($column->name, $upsertColumns, true)) {
$update[] = $platform->quoteSingleIdentifier($column->name) . " = VALUES(" . $platform->quoteSingleIdentifier($column->name) . ")";
}
}
}

Expand All @@ -123,22 +141,34 @@ private function insertUpsertAll(array $objects, ?array $upsertColumns = null):
$rows[] = "(" . implode(", ", $row) . ")";
}

$this->connection->executeStatement(
sprintf(
"INSERT INTO %s (%s) VALUES (%s)%s",
$platform->quoteSingleIdentifier($table->name),
implode(", ", $columns),
implode(", ", $rows),
match (count($update)) {
0 => "",
default => sprintf(" ON DUPLICATE KEY UPDATE %s", implode(", ", $update)),
},
),
$values,
$sql = sprintf(
"INSERT INTO %s (%s) VALUES %s%s%s",
$platform->quoteSingleIdentifier($table->name),
implode(", ", $columnNames),
implode(", ", $rows),
match (count($update)) {
0 => "",
default => sprintf(" ON DUPLICATE KEY UPDATE %s", implode(", ", $update)),
},
match ($supportsReturning) {
true => sprintf(" RETURNING %s", implode(", ", $generatedColumnNames)),
default => "",
},
);

if (count($objects) === 1 && $primaryKey !== null) {
$primaryKey->reflection->setValue($objects[0], $this->connection->lastInsertId());
$result = $this->connection->executeQuery($sql, $values);
if ($supportsReturning && count($generatedColumns) > 0) {
foreach ($result->iterateAssociative() as $index => $row) {
$object = $objects[$index];
foreach ($generatedColumns as $column) {
$column->reflection->setValue(
$object,
$this->valueConverter->databaseToObject($table, $column, $row[$column->name]),
);
}
}
} else if (count($objects) === 1 && $primaryKeyColumn !== null) {
$primaryKeyColumn->reflection->setValue($objects[0], $this->connection->lastInsertId());
}
}

Expand Down
62 changes: 58 additions & 4 deletions data-access-kit/test/PersistenceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
use DataAccessKit\Fixture\User;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\DBAL\Tools\DsnParser;
use LogicException;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use ReflectionProperty;
use function get_class;
use function getenv;
use function iterator_to_array;
use function var_dump;
use function sprintf;

#[Group("database")]
class PersistenceTest extends TestCase
Expand All @@ -33,9 +40,20 @@ public function setUp(): void
private function setUpUsersTable(): void
{
$this->connection->executeStatement("DROP TABLE IF EXISTS users");
$this->connection->executeStatement("CREATE TABLE users (user_id INT PRIMARY KEY, first_name VARCHAR(255))");
$this->connection->executeStatement("INSERT INTO users (user_id, first_name) VALUES (1, 'Alice')");
$this->connection->executeStatement("INSERT INTO users (user_id, first_name) VALUES (2, 'Bob')");

$platform = $this->connection->getDatabasePlatform();
if ($platform instanceof AbstractMySQLPlatform) {
$this->connection->executeStatement("CREATE TABLE users (user_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(255))");
} else if ($platform instanceof PostgreSQLPlatform) {
$this->connection->executeStatement("CREATE TABLE users (user_id SERIAL PRIMARY KEY, first_name VARCHAR(255))");
} else if ($platform instanceof SQLitePlatform) {
$this->connection->executeStatement("CREATE TABLE users (user_id INTEGER PRIMARY KEY AUTOINCREMENT, first_name TEXT)");
} else {
throw new LogicException(sprintf("Unsupported database platform [%s].", get_class($platform)));
}

$this->connection->executeStatement("INSERT INTO users (first_name) VALUES ('Alice')");
$this->connection->executeStatement("INSERT INTO users (first_name) VALUES ('Bob')");
}

public function testSelect(): void
Expand Down Expand Up @@ -64,4 +82,40 @@ public function testExecute(): void
$this->assertEquals(1, $count);
}

public function testInsert(): void
{
$this->setUpUsersTable();
$user = new User();
$user->firstName = "Charlie";
$this->persistence->insert($user);
$this->assertEquals(3, $user->id);

$users = iterator_to_array($this->persistence->select(User::class, "SELECT user_id, first_name FROM users WHERE user_id = ?", [$user->id]));
$this->assertCount(1, $users);
$this->assertEquals($user->id, $users[0]->id);
$this->assertEquals($user->firstName, $users[0]->firstName);
}

public function testInsertAll(): void
{
$this->setUpUsersTable();

$user1 = new User();
$user1->firstName = "Charlie";

$user2 = new User();
$user2->firstName = "David";

$this->persistence->insertAll([$user1, $user2]);

if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) {
$rp = new ReflectionProperty(User::class, "id");
$this->assertFalse($rp->isInitialized($user1));
$this->assertFalse($rp->isInitialized($user2));
} else {
$this->assertEquals(3, $user1->id);
$this->assertEquals(4, $user2->id);
}
}

}

0 comments on commit 7b0e74b

Please sign in to comment.