Skip to content

Commit

Permalink
Merge pull request #12 from pfilsx/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
pfilsx authored Jun 16, 2023
2 parents 9504380 + 179ae03 commit 965c746
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 3 deletions.
9 changes: 9 additions & 0 deletions docs/Types.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Available types
| _int4 | integer[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArrayType](../src/DBAL/Type/IntegerArrayType.php) |
| _int8 | bigint[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArrayType](../src/DBAL/Type/BigIntArrayType.php) |
| _text | text[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArrayType](../src/DBAL/Type/TextArrayType.php) |
| _json | json[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\JsonArrayType](../src/DBAL/Type/JsonArrayType.php) |
| tsvector | tsvector | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\TsVectorType](../src/DBAL/Type/TsVectorType.php) |

Integration with Doctrine
Expand All @@ -23,6 +24,7 @@ Type::addType('smallint[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArrayTy
Type::addType('integer[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArrayType');
Type::addType('bigint[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArrayType');
Type::addType('text[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArrayType');
Type::addType('json[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\JsonArrayType');
Type::addType('tsvector', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\TsVectorType');

// ...
Expand All @@ -36,6 +38,8 @@ $platform->registerDoctrineTypeMapping('bigint[]', 'bigint[]');
$platform->registerDoctrineTypeMapping('_int8', 'bigint[]');
$platform->registerDoctrineTypeMapping('text[]', 'text[]');
$platform->registerDoctrineTypeMapping('_text', 'text[]');
$platform->registerDoctrineTypeMapping('json[]', 'json[]');
$platform->registerDoctrineTypeMapping('_json', 'json[]');
$platform->registerDoctrineTypeMapping('tsvector', 'tsvector');
```

Expand All @@ -52,6 +56,7 @@ doctrine:
integer[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArrayType
bigint[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArrayType
text[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArrayType
json[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\JsonArrayType
tsvector: Pfilsx\PostgreSQLDoctrine\DBAL\Type\TsVectorType

mapping_types:
Expand All @@ -65,6 +70,8 @@ doctrine:
_int8: bigint[]
text[]: text[]
_text: text[]
json[]: json[]
_json: json[]
tsvector: tsvector
# or only for specific connection
connections:
Expand All @@ -80,5 +87,7 @@ doctrine:
_int8: bigint[]
text[]: text[]
_text: text[]
json[]: json[]
_json: json[]
tsvector: tsvector
```
2 changes: 1 addition & 1 deletion src/DBAL/Type/EnumType.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function getName(): string

/**
* @param null|int|string|\UnitEnum $value
* @param AbstractPlatform $platform
* @param AbstractPlatform $platform
*
* @return null|int|string
*/
Expand Down
25 changes: 25 additions & 0 deletions src/DBAL/Type/JsonArrayType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Pfilsx\PostgreSQLDoctrine\DBAL\Type;

use Pfilsx\PostgreSQLDoctrine\Enum\ArrayTypeEnum;

/**
* Implementation of PostgreSql JSON(B)[] data type.
*
* @see https://www.postgresql.org/docs/current/arrays.html
*/
class JsonArrayType extends AbstractArrayType
{
protected static function getArrayType(): ArrayTypeEnum
{
return ArrayTypeEnum::JsonArray;
}

public function getName(): string
{
return 'json[]';
}
}
1 change: 1 addition & 0 deletions src/Enum/ArrayTypeEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ enum ArrayTypeEnum: string
case BigIntArray = 'bigint';
case TextArray = 'text';
case BooleanArray = 'boolean';
case JsonArray = 'json';
}
22 changes: 21 additions & 1 deletion src/ORM/Query/AST/Functions/ArrayAgg.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\AST\TypedExpression;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
Expand All @@ -15,16 +18,20 @@
* @see https://www.postgresql.org/docs/current/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE
*
* @example ARRAY_AGG(entity.field)
* @example ARRAY_AGG(entity.field, 'int[]')
* @example ARRAY_AGG(DISTINCT entity.field)
* @example ARRAY_AGG(entity.field) FILTER (WHERE entity.field IS NOT NULL)
* @example ARRAY_AGG(DISTINCT entity.field) FILTER (WHERE entity.field IS NOT NULL)
* @example ARRAY_AGG(DISTINCT entity.field, 'json[]') FILTER (WHERE entity.field IS NOT NULL)
*/
final class ArrayAgg extends AbstractAggregateWithFilterFunction
final class ArrayAgg extends AbstractAggregateWithFilterFunction implements TypedExpression
{
private bool $distinct = false;

private Node $expr;

private string $returnType = Types::STRING;

public function parseFunction(Parser $parser): void
{
$parser->match(Lexer::T_IDENTIFIER);
Expand All @@ -37,11 +44,24 @@ public function parseFunction(Parser $parser): void
}

$this->expr = $parser->StringPrimary();

if ($lexer->isNextToken(Lexer::T_COMMA)) {
$parser->match(Lexer::T_COMMA);
$parser->match(Lexer::T_STRING);

$this->returnType = $lexer->token['value'];
}

$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}

public function getFunctionSql(SqlWalker $sqlWalker): string
{
return sprintf('ARRAY_AGG(%s%s)', $this->distinct ? 'DISTINCT ' : '', $this->expr->dispatch($sqlWalker));
}

public function getReturnType(): Type
{
return Type::getType($this->returnType);
}
}
16 changes: 15 additions & 1 deletion src/Tools/ArrayTypeTool.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public static function convertPHPArrayToDatabaseArrayString(array $array, ArrayT
$preparedArray = match ($type) {
ArrayTypeEnum::SmallIntArray, ArrayTypeEnum::IntArray, ArrayTypeEnum::BigIntArray => self::convertIntPHPArrayToDatabaseArray($array, $type),
ArrayTypeEnum::TextArray => self::convertStringPHPArrayToDatabaseArray($array),
ArrayTypeEnum::BooleanArray => self::convertBooleanPHPArrayToDatabaseArray($array, $platform)
ArrayTypeEnum::BooleanArray => self::convertBooleanPHPArrayToDatabaseArray($array, $platform),
ArrayTypeEnum::JsonArray => array_map(static fn ($row) => '"' . json_encode($row) . '"', $array),
};

return '{' . implode(',', $preparedArray) . '}';
Expand All @@ -65,6 +66,8 @@ public static function convertPHPArrayToDatabaseArrayString(array $array, ArrayT
* @param ArrayTypeEnum $type
* @param null|AbstractPlatform $platform
*
* @throws \JsonException
*
* @return bool[]|int[]|string[]
*/
public static function convertDatabaseArrayStringToPHPArray(string $value, ArrayTypeEnum $type, ?AbstractPlatform $platform = null): array
Expand All @@ -77,6 +80,7 @@ public static function convertDatabaseArrayStringToPHPArray(string $value, Array
ArrayTypeEnum::SmallIntArray, ArrayTypeEnum::IntArray, ArrayTypeEnum::BigIntArray => self::convertDatabaseArrayStringToIntPHPArray($value, $type),
ArrayTypeEnum::TextArray => self::convertDatabaseArrayStringToStringPHPArray($value),
ArrayTypeEnum::BooleanArray => self::convertDatabaseArrayStringToBoolPHPArray($value, $platform),
ArrayTypeEnum::JsonArray => self::convertDatabaseArrayJsonStringToPHPArray($value),
};
}

Expand Down Expand Up @@ -225,4 +229,14 @@ private static function convertDatabaseArrayStringToBoolPHPArray(string $value,

return $array;
}

private static function convertDatabaseArrayJsonStringToPHPArray(string $value): array
{
return json_decode(
'[' . stripcslashes(preg_replace('/\"(\{.+\})\"/U', '$1', trim($value, '{}'))) . ']',
true,
512,
JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING
);
}
}

0 comments on commit 965c746

Please sign in to comment.