Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/backend-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ jobs:
run: composer run-script --timeout=600 test-integration
env:
SEARCH_ENGINE: legacy
DATABASE_URL: "pgsql://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/testdb?server_version=10"
DATABASE_URL: "pgsql://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/testdb?serverVersion=11"

integration-tests-mysql:
name: MySQL integration tests
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
],
"require": {
"php": " >=8.3",
"ibexa/core": "~6.0.x-dev",
"ibexa/doctrine-schema": "~6.0.x-dev",
"ibexa/core": "dev-dbal-4-upgrade as 6.0.x-dev",
"ibexa/doctrine-schema": "dev-dbal-4-upgrade as 6.0.x-dev",
"symfony/config": "^7.4",
"symfony/dependency-injection": "^7.4",
"symfony/event-dispatcher": "^7.4",
Expand All @@ -20,7 +20,7 @@
"dama/doctrine-test-bundle": "^8.2",
"ibexa/code-style": "~2.0.0",
"ibexa/rector": "~6.0.x-dev",
"ibexa/test-core": "~6.0.x-dev",
"ibexa/test-core": "dev-dbal-4-upgrade as 6.0.x-dev",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^9.0",
Expand Down
31 changes: 27 additions & 4 deletions src/contracts/Gateway/AbstractDoctrineDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,37 @@ public function getMetadata(): DoctrineSchemaMetadataInterface
* @throws \Doctrine\DBAL\Exception
*/
protected function doInsert(array $data): int
{
$this->executeInsert($data);

return (int)$this->connection->lastInsertId();
}

/**
* Inserts a row into a table that generates no identity value, such as the child table of a
* joined inheritance hierarchy, where the identifier is supplied by the caller.
*
* @param array<string, mixed> $data
*
* @throws \Doctrine\DBAL\Exception
*/
protected function doInsertWithoutIdentity(array $data): void
{
$this->executeInsert($data);
}

/**
* @param array<string, mixed> $data
*
* @throws \Doctrine\DBAL\Exception
*/
private function executeInsert(array $data): void
{
$metadata = $this->getMetadata();
$data = $metadata->convertToDatabaseValues($data);
$types = $metadata->getBindingTypesForData($data);

$this->connection->insert($metadata->getTableName(), $data, $types);

return (int)$this->connection->lastInsertId();
}

/**
Expand Down Expand Up @@ -358,7 +381,7 @@ private function buildCondition(QueryBuilder $qb, string $column, $value): strin
} elseif (is_array($value)) {
$parameter = $qb->createPositionalParameter(
$value,
$columnBinding + Connection::ARRAY_PARAM_OFFSET
$metadata->getArrayBindingTypeForColumn($column)
);

$subquery->andWhere($qb->expr()->in($fullColumnName, $parameter));
Expand Down Expand Up @@ -390,7 +413,7 @@ private function buildCondition(QueryBuilder $qb, string $column, $value): strin
if (is_array($value)) {
$parameter = $qb->createPositionalParameter(
$value,
$columnBinding + Connection::ARRAY_PARAM_OFFSET
$metadata->getArrayBindingTypeForColumn($column)
);

return $qb->expr()->in($fullColumnName, $parameter);
Expand Down
19 changes: 17 additions & 2 deletions src/contracts/Gateway/DoctrineSchemaMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

namespace Ibexa\Contracts\CorePersistence\Gateway;

use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Types\Type;
use Ibexa\Contracts\CorePersistence\Exception\MappingException;
use Ibexa\Contracts\CorePersistence\Exception\RuntimeMappingException;
Expand Down Expand Up @@ -250,7 +252,7 @@ public function convertToDatabaseValues(array $data): array
/**
* @param array<string, mixed> $data
*
* @return array<string, int>
* @return array<string, \Doctrine\DBAL\ParameterType>
*
* @throws \Doctrine\DBAL\Exception
*/
Expand All @@ -267,11 +269,24 @@ public function getBindingTypesForData(array $data): array
/**
* @throws \Doctrine\DBAL\Exception
*/
public function getBindingTypeForColumn(string $columnName): int
public function getBindingTypeForColumn(string $columnName): ParameterType
{
return $this->getColumnType($columnName)->getBindingType();
}

/**
* @throws \Doctrine\DBAL\Exception
*/
public function getArrayBindingTypeForColumn(string $columnName): ArrayParameterType
{
return match ($this->getBindingTypeForColumn($columnName)) {
ParameterType::INTEGER => ArrayParameterType::INTEGER,
ParameterType::ASCII => ArrayParameterType::ASCII,
ParameterType::BINARY => ArrayParameterType::BINARY,
default => ArrayParameterType::STRING,
};
}

public function setTranslationSchemaMetadata(TranslationDoctrineSchemaMetadataInterface $translationMetadata): void
{
$this->translationMetadata = $translationMetadata;
Expand Down
8 changes: 6 additions & 2 deletions src/contracts/Gateway/DoctrineSchemaMetadataInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

namespace Ibexa\Contracts\CorePersistence\Gateway;

use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Types\Type;

/**
Expand Down Expand Up @@ -84,7 +86,7 @@ public function convertToDatabaseValues(array $data): array;
/**
* @param array<string, mixed> $data
*
* @return array<string, int>
* @return array<string, \Doctrine\DBAL\ParameterType>
*
* @throws \Ibexa\Contracts\CorePersistence\Exception\RuntimeMappingExceptionInterface
*/
Expand All @@ -99,7 +101,9 @@ public function getIdentifierColumn(): string;
* @throws \Doctrine\DBAL\Exception
* @throws \Ibexa\Contracts\CorePersistence\Exception\RuntimeMappingExceptionInterface
*/
public function getBindingTypeForColumn(string $columnName): int;
public function getBindingTypeForColumn(string $columnName): ParameterType;

public function getArrayBindingTypeForColumn(string $columnName): ArrayParameterType;

/**
* @throws \Ibexa\Contracts\CorePersistence\Exception\MappingExceptionInterface
Expand Down
22 changes: 9 additions & 13 deletions src/lib/Gateway/ExpressionVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,9 @@ public function walkComparison(Comparison $comparison)
$parameterName = $column . '_' . count($this->parameters);
$placeholder = $this->getPlaceholder($parameterName);
$value = $this->walkValue($comparison->getValue());
$type = $this->schemaMetadata->getBindingTypeForColumn($column);
if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET;
}
$type = is_array($value)
? $this->schemaMetadata->getArrayBindingTypeForColumn($column)
: $this->schemaMetadata->getBindingTypeForColumn($column);

if ($this->isInheritedColumn($column)) {
$inheritanceMetadata = $this->schemaMetadata->getInheritanceMetadataWithColumn($column);
Expand Down Expand Up @@ -288,11 +287,9 @@ private function handleJoinQuery(
QueryBuilder $relationshipQuery
): string {
$value = $this->walkValue($comparison->getValue());
$type = $relationshipMetadata->getBindingTypeForColumn($field);

if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET;
}
$type = is_array($value)
? $relationshipMetadata->getArrayBindingTypeForColumn($field)
: $relationshipMetadata->getBindingTypeForColumn($field);

$parameter = new Parameter($parameterName, $value, $type);
$placeholder = $this->getPlaceholder($parameterName);
Expand Down Expand Up @@ -323,10 +320,9 @@ private function handleSubSelectQuery(
QueryBuilder $relationshipQuery
): string {
$value = $this->walkValue($comparison->getValue());
$type = $relationshipMetadata->getBindingTypeForColumn($field);
if (is_array($value)) {
$type += Connection::ARRAY_PARAM_OFFSET;
}
$type = is_array($value)
? $relationshipMetadata->getArrayBindingTypeForColumn($field)
: $relationshipMetadata->getBindingTypeForColumn($field);

$this->parameters[] = new Parameter($parameterName, $value, $type);

Expand Down
29 changes: 9 additions & 20 deletions src/lib/Gateway/JoinedRelationshipTypeStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,28 @@

use Doctrine\DBAL\Query\QueryBuilder;
use Ibexa\Contracts\CorePersistence\Gateway\DoctrineRelationshipInterface;
use Ibexa\Core\Persistence\Doctrine\JoinedTablesTracker;

/**
* @internal
*/
final class JoinedRelationshipTypeStrategy implements RelationshipTypeStrategyInterface
{
private JoinedTablesTracker $joinedTablesTracker;

public function __construct()
{
$this->joinedTablesTracker = new JoinedTablesTracker();
}

public function handleRelationshipType(
QueryBuilder $queryBuilder,
DoctrineRelationshipInterface $relationship,
string $rootTableAlias,
string $fromTable,
string $toTable
): void {
if ($this->isTableAlreadyJoined($queryBuilder, $toTable)) {
if (!$this->joinedTablesTracker->markTableAsJoined($queryBuilder, $toTable)) {
return;
}

Expand All @@ -45,23 +53,4 @@ public function handleRelationshipTypeQuery(
): QueryBuilder {
return $queryBuilder;
}

private function isTableAlreadyJoined(
QueryBuilder $queryBuilder,
string $tableToJoin
): bool {
$joinQueryPart = $queryBuilder->getQueryPart('join');

foreach ($joinQueryPart as $joins) {
foreach ($joins as $join) {
$joinAlias = $join['joinAlias'] ?? $join['joinTable'];

if ($joinAlias === $tableToJoin) {
return true;
}
}
}

return false;
}
}
9 changes: 6 additions & 3 deletions src/lib/Gateway/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,25 @@

namespace Ibexa\CorePersistence\Gateway;

use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\ParameterType;

/**
* @internal
*/
final class Parameter
{
private string $name;

private int $type;
private ArrayParameterType|ParameterType $type;

/** @var mixed */
private $value;

/**
* @param mixed $value
*/
public function __construct(string $name, $value, int $type)
public function __construct(string $name, $value, ArrayParameterType|ParameterType $type)
{
$this->name = $name;
$this->value = $value;
Expand Down Expand Up @@ -51,7 +54,7 @@ public function getValue()
return $this->value;
}

public function getType(): int
public function getType(): ArrayParameterType|ParameterType
{
return $this->type;
}
Expand Down
22 changes: 19 additions & 3 deletions src/lib/Gateway/SubSelectRelationshipTypeStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

namespace Ibexa\CorePersistence\Gateway;

use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\DBAL\Query\Exception\NonUniqueAlias;
use Doctrine\DBAL\Query\Exception\UnknownAlias;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\DBAL\Query\QueryException;
use Ibexa\Contracts\CorePersistence\Gateway\DoctrineRelationshipInterface;
use LogicException;

Expand All @@ -17,14 +20,27 @@
*/
final class SubSelectRelationshipTypeStrategy implements RelationshipTypeStrategyInterface
{
private function isQueryInitialised(QueryBuilder $queryBuilder): bool
{
try {
$queryBuilder->getSQL();

return true;
} catch (UnknownAlias | NonUniqueAlias) {
return true;
} catch (QueryException) {
return false;
}
}

public function handleRelationshipType(
QueryBuilder $queryBuilder,
DoctrineRelationshipInterface $relationship,
string $rootTableAlias,
string $fromTable,
string $toTable
): void {
if (empty($queryBuilder->getQueryPart('select'))) {
if (!$this->isQueryInitialised($queryBuilder)) {
$queryBuilder
->select($toTable . '.' . $relationship->getRelatedClassIdColumn())
->from($toTable);
Expand All @@ -48,7 +64,7 @@ public function handleRelationshipTypeQuery(
string $fullColumnName,
string $placeholder
): QueryBuilder {
if (empty($queryBuilder->getQueryPart('select'))) {
if (!$this->isQueryInitialised($queryBuilder)) {
throw new LogicException(
'Query is not initialized.',
);
Expand Down
Loading
Loading