Skip to content

Commit 3f04c0e

Browse files
authored
feat: add support for arithmetic functions ABS, CEIL, FLOOR, ROUND and TRUNC (#369)
1 parent 8174368 commit 3f04c0e

File tree

13 files changed

+284
-0
lines changed

13 files changed

+284
-0
lines changed

docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
| PostgreSQL functions | Register for DQL as | Implemented by
3030
|---|---|---|
31+
| abs | ABS | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Abs` |
3132
| all | ALL_OF | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\All` |
3233
| any | ANY_OF | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Any` |
3334
| any_value | ANY_VALUE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\AnyValue` |
@@ -47,11 +48,13 @@
4748
| array_to_string | ARRAY_TO_STRING | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToString` |
4849
| cardinality | ARRAY_CARDINALITY | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cardinality` |
4950
| cast | CAST | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cast` |
51+
| ceil | CEIL | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil` |
5052
| date_add | DATE_ADD | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateAdd` |
5153
| date_bin | DATE_BIN | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateBin` |
5254
| date_subtract | DATE_SUBTRACT | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateSubtract` |
5355
| daterange | DATERANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Daterange` |
5456
| extract | DATE_EXTRACT | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateExtract` |
57+
| floor | FLOOR | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Floor` |
5558
| greatest | GREATEST | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Greatest` |
5659
| int4range | INT4RANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int4range` |
5760
| int8range | INT8RANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int8range` |
@@ -98,6 +101,7 @@
98101
| regexp_match | REGEXP_MATCH | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch` |
99102
| regexp_replace | REGEXP_REPLACE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace` |
100103
| regexp_substr | REGEXP_SUBSTR | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr` |
104+
| round | ROUND | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Round` |
101105
| row | ROW | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Row` |
102106
| row_to_json | ROW_TO_JSON | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RowToJson` |
103107
| split_part | SPLIT_PART | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SplitPart` |
@@ -108,6 +112,7 @@
108112
| to_jsonb | TO_JSONB | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToJsonb` |
109113
| to_tsquery | TO_TSQUERY | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsquery` |
110114
| to_tsvector | TO_TSVECTOR | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsvector` |
115+
| trunc | TRUNC | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trunc` |
111116
| tsrange | TSRANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsrange` |
112117
| tstzrange | TSTZRANGE | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange` |
113118
| unaccent | UNACCENT | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unaccent` |

docs/INTEGRATING-WITH-DOCTRINE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@ $configuration->addCustomStringFunction('NUMRANGE', MartinGeorgiev\Doctrine\ORM\
147147
$configuration->addCustomStringFunction('TSRANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsrange::class);
148148
$configuration->addCustomStringFunction('TSTZRANGE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange::class);
149149

150+
# Arithmetic functions
151+
$configuration->addCustomStringFunction('ABS', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Abs::class);
152+
$configuration->addCustomStringFunction('CEIL', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil::class);
153+
$configuration->addCustomStringFunction('FLOOR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Floor::class);
154+
$configuration->addCustomStringFunction('ROUND', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Round::class);
155+
$configuration->addCustomStringFunction('TRUNC', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trunc::class);
156+
150157
# other operators
151158
$configuration->addCustomStringFunction('CAST', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cast::class);
152159
$configuration->addCustomStringFunction('ILIKE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ilike::class);

docs/INTEGRATING-WITH-LARAVEL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,13 @@ return [
201201
'NUMRANGE' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Numrange::class,
202202
'TSRANGE' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsrange::class,
203203
'TSTZRANGE' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange::class,
204+
205+
# Arithmetic functions
206+
'ABS' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Abs::class,
207+
'CEIL' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil::class,
208+
'FLOOR' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Floor::class,
209+
'ROUND' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Round::class,
210+
'TRUNC' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trunc::class,
204211

205212
# other operators
206213
'CAST' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cast::class,

docs/INTEGRATING-WITH-SYMFONY.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ doctrine:
195195
NUMRANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Numrange
196196
TSRANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsrange
197197
TSTZRANGE: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange
198+
199+
# Arithmetic functions
200+
ABS: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Abs
201+
CEIL: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil
202+
FLOOR: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Floor
203+
ROUND: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Round
204+
TRUNC: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trunc
198205
199206
# other operators
200207
CAST: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cast
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
/**
8+
* @since 3.2
9+
*
10+
* @author Jan Klan <jan@klan.com.au>
11+
*/
12+
abstract class BaseArithmeticFunction extends BaseVariadicFunction
13+
{
14+
protected function getNodeMappingPattern(): array
15+
{
16+
return ['ArithmeticPrimary'];
17+
}
18+
19+
protected function getMinArgumentCount(): int
20+
{
21+
return 1;
22+
}
23+
24+
protected function getMaxArgumentCount(): int
25+
{
26+
return 1;
27+
}
28+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
/**
8+
* Implementation of PostgreSQL CEIL().
9+
*
10+
* @see https://www.postgresql.org/docs/17/functions-math.html
11+
* @since 3.2
12+
*
13+
* @author Jan Klan <jan@klan.com.au>
14+
*/
15+
class Ceil extends BaseArithmeticFunction
16+
{
17+
protected function getFunctionName(): string
18+
{
19+
return 'CEIL';
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
/**
8+
* Implementation of PostgreSQL FLOOR().
9+
*
10+
* @see https://www.postgresql.org/docs/17/functions-math.html
11+
* @since 3.2
12+
*
13+
* @author Jan Klan <jan@klan.com.au>
14+
*/
15+
class Floor extends BaseArithmeticFunction
16+
{
17+
protected function getFunctionName(): string
18+
{
19+
return 'FLOOR';
20+
}
21+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
/**
8+
* Implementation of PostgreSQL ROUND().
9+
*
10+
* @see https://www.postgresql.org/docs/17/functions-math.html
11+
* @since 3.2
12+
*
13+
* @author Jan Klan <jan@klan.com.au>
14+
*/
15+
class Round extends BaseArithmeticFunction
16+
{
17+
protected function getFunctionName(): string
18+
{
19+
return 'ROUND';
20+
}
21+
22+
protected function getMaxArgumentCount(): int
23+
{
24+
return 2;
25+
}
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
/**
8+
* Implementation of PostgreSQL TRUNC().
9+
*
10+
* @see https://www.postgresql.org/docs/17/functions-math.html
11+
* @since 3.2
12+
*
13+
* @author Jan Klan <jan@klan.com.au>
14+
*/
15+
class Trunc extends BaseArithmeticFunction
16+
{
17+
protected function getFunctionName(): string
18+
{
19+
return 'TRUNC';
20+
}
21+
22+
protected function getMaxArgumentCount(): int
23+
{
24+
return 2;
25+
}
26+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDecimals;
8+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ceil;
9+
10+
class CeilTest extends TestCase
11+
{
12+
protected function getStringFunctions(): array
13+
{
14+
return [
15+
'CEIL' => Ceil::class,
16+
];
17+
}
18+
19+
protected function getExpectedSqlStatements(): array
20+
{
21+
return [
22+
'SELECT CEIL(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
23+
];
24+
}
25+
26+
protected function getDqlStatements(): array
27+
{
28+
return [
29+
\sprintf('SELECT CEIL(e.decimal1) FROM %s e', ContainsDecimals::class),
30+
];
31+
}
32+
}

0 commit comments

Comments
 (0)