diff --git a/README.md b/README.md index 7d6b31d..5e13f93 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Features * [Trait](src/ORM/Trait/ExistsMethodRepositoryTrait.php) for easy use of [SELECT EXISTS(...)](https://www.postgresql.org/docs/current/functions-subquery.html#FUNCTIONS-SUBQUERY-EXISTS) in your entity repositories * Aggregate functions with filter condition support * Array types +* [Text Search](https://www.postgresql.org/docs/current/textsearch.html) support Requirement ----------- diff --git a/docs/Functions-and-Operators.md b/docs/Functions-and-Operators.md index 694bb21..3b1d541 100644 --- a/docs/Functions-and-Operators.md +++ b/docs/Functions-and-Operators.md @@ -1,12 +1,20 @@ Available functions =================== -| PostgreSQL function | DQL function | Implementation | -|---------------------|--------------|-------------------------------------------------------------------------------------------------------------| -| ARRAY_AGG() | ARRAY_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ArrayAgg](../src/ORM/Query/AST/Functions/ArrayAgg.php) | -| JSON_AGG() | JSON_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonAgg](../src/ORM/Query/AST/Functions/JsonAgg.php) | -| JSONB_AGG() | JSONB_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonbAgg](../src/ORM/Query/AST/Functions/JsonbAgg.php) | -| STRING_AGG() | STRING_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\StringAgg](../src/ORM/Query/AST/Functions/StringAgg.php) | +| PostgreSQL function | DQL function | Implementation | +|------------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------------| +| ARRAY_AGG() | ARRAY_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ArrayAgg](../src/ORM/Query/AST/Functions/ArrayAgg.php) | +| JSON_AGG() | JSON_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonAgg](../src/ORM/Query/AST/Functions/JsonAgg.php) | +| JSONB_AGG() | JSONB_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonbAgg](../src/ORM/Query/AST/Functions/JsonbAgg.php) | +| PHRASETO_TSQUERY() | PHRASETO_TSQUERY | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\PhraseToTsQuery](../src/ORM/Query/AST/Functions/PhraseToTsQuery.php) | +| PLAINTO_TSQUERY() | PLAINTO_TSQUERY | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\PlainToTsQuery](../src/ORM/Query/AST/Functions/PlainToTsQuery.php) | +| STRING_AGG() | STRING_AGG | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\StringAgg](../src/ORM/Query/AST/Functions/StringAgg.php) | +| TO_TSQUERY() | TO_TSQUERY | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ToTsQuery](../src/ORM/Query/AST/Functions/ToTsQuery.php) | +| TO_TSVECTOR() | TO_TSVECTOR | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ToTsVector](../src/ORM/Query/AST/Functions/ToTsVector.php) | +| TS_HEADLINE() | TS_HEADLINE | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsHeadline](../src/ORM/Query/AST/Functions/TsHeadline.php) | +| TS_RANK() | TS_RANK | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsRank](../src/ORM/Query/AST/Functions/TsRank.php) | +| TS_RANK_CD() | TS_RANK_CD | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsRankCd](../src/ORM/Query/AST/Functions/TsRankCd.php) | +| WEBSEARCH_TO_TSQUERY() | WEBSEARCH_TO_TSQUERY | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\WebsearchToTsQuery](../src/ORM/Query/AST/Functions/WebsearchToTsQuery.php) | Available operators =================== @@ -20,4 +28,57 @@ Available operators | -> | JSON_GET_FIELD | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetField](../src/ORM/Query/AST/Functions/JsonGetField.php) | | ->> | JSON_GET_FIELD_AS_TEXT | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetFieldAsText](../src/ORM/Query/AST/Functions/JsonGetFieldAsText.php) | | #> | JSON_GET_OBJECT | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetObject](../src/ORM/Query/AST/Functions/JsonGetObject.php) | -| #>> | JSON_GET_OBJECT_AS_TEXT | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetObjectAsText](../src/ORM/Query/AST/Functions/JsonGetObjectAsText.php) | \ No newline at end of file +| #>> | JSON_GET_OBJECT_AS_TEXT | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetObjectAsText](../src/ORM/Query/AST/Functions/JsonGetObjectAsText.php) | +| @@ | TS_MATCH | [Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsMatch](../src/ORM/Query/AST/Functions/TsMatch.php) | + +Integration with Doctrine +========================= + +```php +addCustomStringFunction('ARRAY_AGG', Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ArrayAgg::class); +$configuration->addCustomStringFunction('JSONB_CONCAT', Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonbConcat::class); +$configuration->addCustomStringFunction('JSON_GET_FIELD', Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetField::class); +$configuration->addCustomStringFunction('TO_TSVECTOR', Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ToTsVector::class); +$configuration->addCustomNumericFunction('TS_RANK', Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsRank::class); +$configuration->addCustomNumericFunction('TS_MATCH', Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsMatch::class); + +// ... + +$em = EntityManager::create($connection, $configuration); +``` + +Integration with Symfony +========================= + +```yaml +# config/packages/doctrine.yaml +doctrine: + orm: + dql: + string_functions: + array_agg: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ArrayAgg + jsonb_concat: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonbConcat + json_get_field: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetField + to_tsvector: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ToTsVector + ts_match: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsMatch + numeric_functions: + ts_rank: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsRank + # or only for specific em + entity_managers: + em_name: + string_functions: + array_agg: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ArrayAgg + jsonb_concat: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonbConcat + json_get_field: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\JsonGetField + to_tsvector: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\ToTsVector + ts_match: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsMatch + numeric_functions: + ts_rank: Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\Functions\TsRank +``` \ No newline at end of file diff --git a/docs/Types.md b/docs/Types.md index 30da482..71a7731 100644 --- a/docs/Types.md +++ b/docs/Types.md @@ -1,13 +1,14 @@ Available types =============== -| PostgreSQL type | Register as | Implementation | -|-----------------|-------------|-----------------------------------------------------------------------------------------| -| _bool | bool[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\BooleanArray](../src/DBAL/Type/BooleanArray.php) | -| _int2 | smallint[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArray](../src/DBAL/Type/SmallIntArray.php) | -| _int4 | integer[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArray](../src/DBAL/Type/IntegerArray.php) | -| _int8 | bigint[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArray](../src/DBAL/Type/BigIntArray.php) | -| _text | text[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArray](../src/DBAL/Type/TextArray.php) | +| PostgreSQL type | Register as | Implementation | +|-----------------|-------------|-------------------------------------------------------------------------------------------------| +| _bool | bool[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\BooleanArrayType](../src/DBAL/Type/BooleanArrayType.php) | +| _int2 | smallint[] | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArrayType](../src/DBAL/Type/SmallIntArrayType.php) | +| _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) | +| tsvector | tsvector | [Pfilsx\PostgreSQLDoctrine\DBAL\Type\TsVectorType](../src/DBAL/Type/TsVectorType.php) | Integration with Doctrine ========================= @@ -17,37 +18,41 @@ Integration with Doctrine use Doctrine\DBAL\Types\Type; -Type::addType('bool[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\BooleanArray'); -Type::addType('smallint[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArray'); -Type::addType('integer[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArray'); -Type::addType('bigint[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArray'); -Type::addType('text[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArray'); +Type::addType('bool[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\BooleanArrayType'); +Type::addType('smallint[]', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArrayType'); +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('tsvector', 'Pfilsx\PostgreSQLDoctrine\DBAL\Type\TsVectorType'); // ... $platform = $em->getConnection()->getDatabasePlatform(); -$platform->registerDoctrineTypeMapping('bool[]','bool[]'); -$platform->registerDoctrineTypeMapping('_bool','bool[]'); -$platform->registerDoctrineTypeMapping('integer[]','integer[]'); -$platform->registerDoctrineTypeMapping('_int4','integer[]'); -$platform->registerDoctrineTypeMapping('bigint[]','bigint[]'); -$platform->registerDoctrineTypeMapping('_int8','bigint[]'); -$platform->registerDoctrineTypeMapping('text[]','text[]'); -$platform->registerDoctrineTypeMapping('_text','text[]'); +$platform->registerDoctrineTypeMapping('bool[]', 'bool[]'); +$platform->registerDoctrineTypeMapping('_bool', 'bool[]'); +$platform->registerDoctrineTypeMapping('integer[]', 'integer[]'); +$platform->registerDoctrineTypeMapping('_int4', 'integer[]'); +$platform->registerDoctrineTypeMapping('bigint[]', 'bigint[]'); +$platform->registerDoctrineTypeMapping('_int8', 'bigint[]'); +$platform->registerDoctrineTypeMapping('text[]', 'text[]'); +$platform->registerDoctrineTypeMapping('_text', 'text[]'); +$platform->registerDoctrineTypeMapping('tsvector', 'tsvector'); ``` Integration with Symfony ========================= + ```yaml # config/packages/doctrine.yaml doctrine: dbal: types: - bool[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\BooleanArray - smallint[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArray - integer[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArray - bigint[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArray - text[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArray + bool[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\BooleanArrayType + smallint[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\SmallIntArrayType + integer[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\IntegerArrayType + bigint[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\BigIntArrayType + text[]: Pfilsx\PostgreSQLDoctrine\DBAL\Type\TextArrayType + tsvector: Pfilsx\PostgreSQLDoctrine\DBAL\Type\TsVectorType mapping_types: bool[]: bool[] @@ -60,7 +65,8 @@ doctrine: _int8: bigint[] text[]: text[] _text: text[] - # or + tsvector: tsvector + # or only for specific connection connections: connection_name: mapping_types: @@ -74,4 +80,5 @@ doctrine: _int8: bigint[] text[]: text[] _text: text[] + tsvector: tsvector ``` \ No newline at end of file diff --git a/src/DBAL/Type/BigIntArray.php b/src/DBAL/Type/BigIntArrayType.php similarity index 90% rename from src/DBAL/Type/BigIntArray.php rename to src/DBAL/Type/BigIntArrayType.php index 97d960d..eec563f 100644 --- a/src/DBAL/Type/BigIntArray.php +++ b/src/DBAL/Type/BigIntArrayType.php @@ -11,7 +11,7 @@ * * @see https://www.postgresql.org/docs/current/arrays.html */ -class BigIntArray extends AbstractArrayType +class BigIntArrayType extends AbstractArrayType { protected static function getArrayType(): ArrayTypeEnum { diff --git a/src/DBAL/Type/BooleanArray.php b/src/DBAL/Type/BooleanArrayType.php similarity index 90% rename from src/DBAL/Type/BooleanArray.php rename to src/DBAL/Type/BooleanArrayType.php index b885514..505af1c 100644 --- a/src/DBAL/Type/BooleanArray.php +++ b/src/DBAL/Type/BooleanArrayType.php @@ -11,7 +11,7 @@ * * @see https://www.postgresql.org/docs/current/arrays.html */ -class BooleanArray extends AbstractArrayType +class BooleanArrayType extends AbstractArrayType { protected static function getArrayType(): ArrayTypeEnum { diff --git a/src/DBAL/Type/IntegerArray.php b/src/DBAL/Type/IntegerArrayType.php similarity index 90% rename from src/DBAL/Type/IntegerArray.php rename to src/DBAL/Type/IntegerArrayType.php index dbc723b..7ecfda3 100644 --- a/src/DBAL/Type/IntegerArray.php +++ b/src/DBAL/Type/IntegerArrayType.php @@ -11,7 +11,7 @@ * * @see https://www.postgresql.org/docs/current/arrays.html */ -class IntegerArray extends AbstractArrayType +class IntegerArrayType extends AbstractArrayType { protected static function getArrayType(): ArrayTypeEnum { diff --git a/src/DBAL/Type/SmallIntArray.php b/src/DBAL/Type/SmallIntArrayType.php similarity index 90% rename from src/DBAL/Type/SmallIntArray.php rename to src/DBAL/Type/SmallIntArrayType.php index b3f2fad..8edd2d9 100644 --- a/src/DBAL/Type/SmallIntArray.php +++ b/src/DBAL/Type/SmallIntArrayType.php @@ -11,7 +11,7 @@ * * @see https://www.postgresql.org/docs/current/arrays.html */ -class SmallIntArray extends AbstractArrayType +class SmallIntArrayType extends AbstractArrayType { protected static function getArrayType(): ArrayTypeEnum { diff --git a/src/DBAL/Type/TextArray.php b/src/DBAL/Type/TextArrayType.php similarity index 90% rename from src/DBAL/Type/TextArray.php rename to src/DBAL/Type/TextArrayType.php index c396a01..cd78055 100644 --- a/src/DBAL/Type/TextArray.php +++ b/src/DBAL/Type/TextArrayType.php @@ -11,7 +11,7 @@ * * @see https://www.postgresql.org/docs/current/arrays.html */ -class TextArray extends AbstractArrayType +class TextArrayType extends AbstractArrayType { protected static function getArrayType(): ArrayTypeEnum { diff --git a/src/DBAL/Type/TsVectorType.php b/src/DBAL/Type/TsVectorType.php new file mode 100644 index 0000000..5dd5b7e --- /dev/null +++ b/src/DBAL/Type/TsVectorType.php @@ -0,0 +1,32 @@ + $column + * @param AbstractPlatform $platform + * + * @return string + */ + public function getSQLDeclaration(array $column, AbstractPlatform $platform): string + { + return 'TSVECTOR'; + } + + public function getName(): string + { + return 'tsvector'; + } +} diff --git a/src/ORM/Query/AST/Functions/AggregateWithFilterFunction.php b/src/ORM/Query/AST/Functions/AbstractAggregateWithFilterFunction.php similarity index 95% rename from src/ORM/Query/AST/Functions/AggregateWithFilterFunction.php rename to src/ORM/Query/AST/Functions/AbstractAggregateWithFilterFunction.php index 73370bf..9bdbdf8 100644 --- a/src/ORM/Query/AST/Functions/AggregateWithFilterFunction.php +++ b/src/ORM/Query/AST/Functions/AbstractAggregateWithFilterFunction.php @@ -10,7 +10,7 @@ use Doctrine\ORM\Query\SqlWalker; use Pfilsx\PostgreSQLDoctrine\ORM\Query\AST\FilterExpression; -abstract class AggregateWithFilterFunction extends FunctionNode +abstract class AbstractAggregateWithFilterFunction extends FunctionNode { private const FILTER_IDENTIFIER = 'FILTER'; private ?FilterExpression $filterExpression = null; diff --git a/src/ORM/Query/AST/Functions/AbstractToTsFunction.php b/src/ORM/Query/AST/Functions/AbstractToTsFunction.php new file mode 100644 index 0000000..55cca38 --- /dev/null +++ b/src/ORM/Query/AST/Functions/AbstractToTsFunction.php @@ -0,0 +1,49 @@ +match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $firstNode = $parser->StringPrimary(); + + $lexer = $parser->getLexer(); + + if ($lexer->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + $this->config = $firstNode; + $this->document = $parser->StringPrimary(); + } else { + $this->document = $firstNode; + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + public function getSql(SqlWalker $sqlWalker): string + { + return sprintf('%s(%s%s)', + $this->getFunctionName(), + $this->config !== null ? $this->config->dispatch($sqlWalker) . ', ' : '', + $this->document->dispatch($sqlWalker) + ); + } +} diff --git a/src/ORM/Query/AST/Functions/ArrayAgg.php b/src/ORM/Query/AST/Functions/ArrayAgg.php index 92e6055..cf39105 100644 --- a/src/ORM/Query/AST/Functions/ArrayAgg.php +++ b/src/ORM/Query/AST/Functions/ArrayAgg.php @@ -10,7 +10,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql ARRAY_AGG(). + * Implementation of PostgreSql ARRAY_AGG() function. * * @see https://www.postgresql.org/docs/current/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE * @@ -19,7 +19,7 @@ * @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) */ -final class ArrayAgg extends AggregateWithFilterFunction +final class ArrayAgg extends AbstractAggregateWithFilterFunction { private bool $distinct = false; diff --git a/src/ORM/Query/AST/Functions/JsonAgg.php b/src/ORM/Query/AST/Functions/JsonAgg.php index b76eeff..1b1a421 100644 --- a/src/ORM/Query/AST/Functions/JsonAgg.php +++ b/src/ORM/Query/AST/Functions/JsonAgg.php @@ -10,7 +10,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql JSON_AGG(). + * Implementation of PostgreSql JSON_AGG() function. * * @see https://www.postgresql.org/docs/current/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE * @@ -19,7 +19,7 @@ * @example JSON_AGG(entity.field) FILTER (WHERE entity.field IS NOT NULL) * @example JSON_AGG(DISTINCT entity.field) FILTER (WHERE entity.field IS NOT NULL) */ -final class JsonAgg extends AggregateWithFilterFunction +final class JsonAgg extends AbstractAggregateWithFilterFunction { private bool $distinct = false; diff --git a/src/ORM/Query/AST/Functions/JsonGetArrayElement.php b/src/ORM/Query/AST/Functions/JsonGetArrayElement.php index 9d14efd..412be7c 100644 --- a/src/ORM/Query/AST/Functions/JsonGetArrayElement.php +++ b/src/ORM/Query/AST/Functions/JsonGetArrayElement.php @@ -8,7 +8,7 @@ use Doctrine\ORM\Query\Parser; /** - * Implementation of PostgreSql json array field retrieval by index. + * Implementation of PostgreSql JSON(B) array field retrieval by index. * * @see https://www.postgresql.org/docs/current/functions-json.html * diff --git a/src/ORM/Query/AST/Functions/JsonGetArrayElementAsText.php b/src/ORM/Query/AST/Functions/JsonGetArrayElementAsText.php index 674b5e2..c73c85e 100644 --- a/src/ORM/Query/AST/Functions/JsonGetArrayElementAsText.php +++ b/src/ORM/Query/AST/Functions/JsonGetArrayElementAsText.php @@ -8,7 +8,7 @@ use Doctrine\ORM\Query\Parser; /** - * Implementation of PostgreSql json array field retrieval by index. + * Implementation of PostgreSql JSON(B) array field retrieval by index. * * @see https://www.postgresql.org/docs/current/functions-json.html * diff --git a/src/ORM/Query/AST/Functions/JsonGetField.php b/src/ORM/Query/AST/Functions/JsonGetField.php index 721a89d..06b3887 100644 --- a/src/ORM/Query/AST/Functions/JsonGetField.php +++ b/src/ORM/Query/AST/Functions/JsonGetField.php @@ -11,7 +11,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql json object field retrieval by path. + * Implementation of PostgreSql JSON(B) object field retrieval by path. * * @see https://www.postgresql.org/docs/current/functions-json.html * diff --git a/src/ORM/Query/AST/Functions/JsonGetFieldAsText.php b/src/ORM/Query/AST/Functions/JsonGetFieldAsText.php index 41f363b..470e46a 100644 --- a/src/ORM/Query/AST/Functions/JsonGetFieldAsText.php +++ b/src/ORM/Query/AST/Functions/JsonGetFieldAsText.php @@ -8,7 +8,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql json object field as text retrieval by path. + * Implementation of PostgreSql JSON(B) object field as text retrieval by path. * * @see https://www.postgresql.org/docs/current/functions-json.html * diff --git a/src/ORM/Query/AST/Functions/JsonGetObject.php b/src/ORM/Query/AST/Functions/JsonGetObject.php index 0944ed5..5681346 100644 --- a/src/ORM/Query/AST/Functions/JsonGetObject.php +++ b/src/ORM/Query/AST/Functions/JsonGetObject.php @@ -11,7 +11,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql json object retrieval by path. + * Implementation of PostgreSql JSON(B) object retrieval by path. * * @see https://www.postgresql.org/docs/current/functions-json.html * diff --git a/src/ORM/Query/AST/Functions/JsonGetObjectAsText.php b/src/ORM/Query/AST/Functions/JsonGetObjectAsText.php index 59cf7da..12e0f15 100644 --- a/src/ORM/Query/AST/Functions/JsonGetObjectAsText.php +++ b/src/ORM/Query/AST/Functions/JsonGetObjectAsText.php @@ -7,7 +7,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql json object as text retrieval by path. + * Implementation of PostgreSql JSON(B) object as text retrieval by path. * * @see https://www.postgresql.org/docs/current/functions-json.html * diff --git a/src/ORM/Query/AST/Functions/JsonbAgg.php b/src/ORM/Query/AST/Functions/JsonbAgg.php index 922fda1..5d79d23 100644 --- a/src/ORM/Query/AST/Functions/JsonbAgg.php +++ b/src/ORM/Query/AST/Functions/JsonbAgg.php @@ -10,14 +10,14 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql JSONB_AGG(). + * Implementation of PostgreSql JSONB_AGG() function. * * @see https://www.postgresql.org/docs/current/functions-aggregate.html#FUNCTIONS-AGGREGATE-TABLE * * @example JSONB_AGG(entity.field) * @example JSONB_AGG(entity.field) FILTER (WHERE entity.field IS NOT NULL) */ -final class JsonbAgg extends AggregateWithFilterFunction +final class JsonbAgg extends AbstractAggregateWithFilterFunction { private bool $distinct = false; diff --git a/src/ORM/Query/AST/Functions/JsonbConcat.php b/src/ORM/Query/AST/Functions/JsonbConcat.php index d53f320..55cd136 100644 --- a/src/ORM/Query/AST/Functions/JsonbConcat.php +++ b/src/ORM/Query/AST/Functions/JsonbConcat.php @@ -11,7 +11,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql jsonb concatenation function. + * Implementation of PostgreSql JSONB concatenation operator. * * @see https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSONB-OP-TABLE * diff --git a/src/ORM/Query/AST/Functions/JsonbContains.php b/src/ORM/Query/AST/Functions/JsonbContains.php index 8060c90..1d1fcc7 100644 --- a/src/ORM/Query/AST/Functions/JsonbContains.php +++ b/src/ORM/Query/AST/Functions/JsonbContains.php @@ -13,7 +13,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql jsonb contains function. + * Implementation of PostgreSql JSONB contains operator. * * @see https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSONB-OP-TABLE * diff --git a/src/ORM/Query/AST/Functions/JsonbKeyExists.php b/src/ORM/Query/AST/Functions/JsonbKeyExists.php index 24140a6..331deec 100644 --- a/src/ORM/Query/AST/Functions/JsonbKeyExists.php +++ b/src/ORM/Query/AST/Functions/JsonbKeyExists.php @@ -11,7 +11,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql jsonb contains function. + * Implementation of PostgreSql JSONB key exists operator. * * @see https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSONB-OP-TABLE * diff --git a/src/ORM/Query/AST/Functions/JsonbRemove.php b/src/ORM/Query/AST/Functions/JsonbRemove.php index c67aedd..7f731b6 100644 --- a/src/ORM/Query/AST/Functions/JsonbRemove.php +++ b/src/ORM/Query/AST/Functions/JsonbRemove.php @@ -11,7 +11,7 @@ use Doctrine\ORM\Query\SqlWalker; /** - * Implementation of PostgreSql jsonb remove by key function. + * Implementation of PostgreSql JSONB remove by key operator. * * @see https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-JSONB-OP-TABLE * diff --git a/src/ORM/Query/AST/Functions/PhraseToTsQuery.php b/src/ORM/Query/AST/Functions/PhraseToTsQuery.php new file mode 100644 index 0000000..58396ad --- /dev/null +++ b/src/ORM/Query/AST/Functions/PhraseToTsQuery.php @@ -0,0 +1,22 @@ +match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->node1 = $parser->StringPrimary(); + $parser->match(Lexer::T_COMMA); + $this->node2 = $parser->StringPrimary(); + + if ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + $this->node3 = $parser->StringPrimary(); + } + + if ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + $this->node4 = $parser->StringPrimary(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + public function getSql(SqlWalker $sqlWalker): string + { + return sprintf('TS_HEADLINE(%s, %s%s%s)', + $this->node1->dispatch($sqlWalker), + $this->node2->dispatch($sqlWalker), + $this->node3 !== null ? ', ' . $this->node3->dispatch($sqlWalker) : '', + $this->node4 !== null ? ', ' . $this->node4->dispatch($sqlWalker) : '' + ); + } +} diff --git a/src/ORM/Query/AST/Functions/TsMatch.php b/src/ORM/Query/AST/Functions/TsMatch.php new file mode 100644 index 0000000..8c06540 --- /dev/null +++ b/src/ORM/Query/AST/Functions/TsMatch.php @@ -0,0 +1,40 @@ +match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + $this->vector = $parser->StringPrimary(); + $parser->match(Lexer::T_COMMA); + $this->query = $parser->StringPrimary(); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + public function getSql(SqlWalker $sqlWalker): string + { + return "({$this->vector->dispatch($sqlWalker)} @@ {$this->query->dispatch($sqlWalker)})"; + } +} diff --git a/src/ORM/Query/AST/Functions/TsRank.php b/src/ORM/Query/AST/Functions/TsRank.php new file mode 100644 index 0000000..c6231c9 --- /dev/null +++ b/src/ORM/Query/AST/Functions/TsRank.php @@ -0,0 +1,54 @@ +match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->vector = $parser->StringPrimary(); + $parser->match(Lexer::T_COMMA); + $this->query = $parser->StringPrimary(); + + if ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + $this->normalization = $parser->ArithmeticPrimary(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + public function getSql(SqlWalker $sqlWalker): string + { + return sprintf('TS_RANK(%s, %s%s)', + $this->vector->dispatch($sqlWalker), + $this->query->dispatch($sqlWalker), + $this->normalization !== null ? ', ' . $this->normalization->dispatch($sqlWalker) : '' + ); + } +} diff --git a/src/ORM/Query/AST/Functions/TsRankCd.php b/src/ORM/Query/AST/Functions/TsRankCd.php new file mode 100644 index 0000000..aa925b9 --- /dev/null +++ b/src/ORM/Query/AST/Functions/TsRankCd.php @@ -0,0 +1,28 @@ +vector->dispatch($sqlWalker), + $this->query->dispatch($sqlWalker), + $this->normalization !== null ? ', ' . $this->normalization->dispatch($sqlWalker) : '' + ); + } +} diff --git a/src/ORM/Query/AST/Functions/WebsearchToTsQuery.php b/src/ORM/Query/AST/Functions/WebsearchToTsQuery.php new file mode 100644 index 0000000..aca5125 --- /dev/null +++ b/src/ORM/Query/AST/Functions/WebsearchToTsQuery.php @@ -0,0 +1,22 @@ +