Skip to content

Commit 081f14f

Browse files
committed
add function info for YEAR
1 parent 3bf9ef9 commit 081f14f

File tree

7 files changed

+822
-1
lines changed

7 files changed

+822
-1
lines changed

src/Database/FunctionInfo/FunctionInfoRegistryFactory.php

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public function createDefaultFunctionInfos(): array
3535
new Sum(),
3636
new Trim(),
3737
new Value(),
38+
new Year(),
3839
];
3940
}
4041
}

src/Database/FunctionInfo/Year.php

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MariaStan\Database\FunctionInfo;
6+
7+
use MariaStan\Analyser\AnalyserConditionTypeEnum;
8+
use MariaStan\Analyser\ExprTypeResult;
9+
use MariaStan\Ast\Expr\FunctionCall\FunctionCall;
10+
use MariaStan\Parser\Exception\ParserException;
11+
use MariaStan\Schema\DbType\DbTypeEnum;
12+
use MariaStan\Schema\DbType\IntType;
13+
use MariaStan\Schema\DbType\NullType;
14+
15+
use function count;
16+
use function in_array;
17+
18+
final class Year implements FunctionInfo
19+
{
20+
/** @inheritDoc */
21+
public function getSupportedFunctionNames(): array
22+
{
23+
return ['YEAR'];
24+
}
25+
26+
public function getFunctionType(): FunctionTypeEnum
27+
{
28+
return FunctionTypeEnum::SIMPLE;
29+
}
30+
31+
public function checkSyntaxErrors(FunctionCall $functionCall): void
32+
{
33+
$args = $functionCall->getArguments();
34+
$argCount = count($args);
35+
36+
if ($argCount !== 1) {
37+
throw new ParserException(
38+
FunctionInfoHelper::createArgumentCountErrorMessageFixed(
39+
$functionCall->getFunctionName(),
40+
1,
41+
$argCount,
42+
),
43+
);
44+
}
45+
}
46+
47+
/** @inheritDoc */
48+
public function getInnerConditions(?AnalyserConditionTypeEnum $condition, array $arguments): array
49+
{
50+
// TRUTHY(YEAR(A)) => NOT_NULL(A)
51+
// FALSY(YEAR(A)) => NOT_NULL(A)
52+
// NOT_NULL(YEAR(A)) => NOT_NULL(A)
53+
// NULL(YEAR(A)) => []
54+
$innerCondition = match ($condition) {
55+
null, AnalyserConditionTypeEnum::NULL => null,
56+
default => AnalyserConditionTypeEnum::NOT_NULL,
57+
};
58+
59+
return [$innerCondition];
60+
}
61+
62+
/**
63+
* @inheritDoc
64+
* @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter
65+
*/
66+
public function getReturnType(
67+
FunctionCall $functionCall,
68+
array $argumentTypes,
69+
?AnalyserConditionTypeEnum $condition,
70+
bool $isNonEmptyAggResultSet,
71+
): ExprTypeResult {
72+
$date = $argumentTypes[0];
73+
$isNullable = $date->isNullable || $date->type::getTypeEnum() !== DbTypeEnum::DATETIME;
74+
$type = in_array($date->type::getTypeEnum(), [DbTypeEnum::DATETIME, DbTypeEnum::VARCHAR], true)
75+
? new IntType()
76+
: new NullType();
77+
78+
return new ExprTypeResult($type, $isNullable, null, $date->knowledgeBase);
79+
}
80+
}

tests/Analyser/AnalyserTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ private static function provideValidFunctionCallTestData(): iterable
836836
$selects["DATE_FORMAT({$label}, Y-m, null)"] = "SELECT DATE_FORMAT({$value}, '%Y-%m', null)";
837837
$selects["DATE_FORMAT({$label}, Y-m, en_US)"] = "SELECT DATE_FORMAT({$value}, '%Y-%m', 'en_US')";
838838
$selects["DATE({$label})"] = "SELECT DATE({$value})";
839+
$selects["YEAR({$label})"] = "SELECT YEAR({$value})";
839840
$selects["DATE_ADD({$label}, INTERVAL)"] = "SELECT DATE_ADD({$value}, INTERVAL 1 SECOND)";
840841

841842
// TODO: handle this later when we have better type system.
@@ -1604,6 +1605,8 @@ private static function provideValidNullabilityOperatorTestData(): iterable
16041605
'NOT LCASE(col_vchar)',
16051606
'UPPER(col_vchar) IS NULL',
16061607
'UCASE(col_vchar) IS NOT NULL',
1608+
'YEAR(col_vchar) IS NOT NULL',
1609+
'YEAR(col_vchar) IS NULL',
16071610
];
16081611

16091612
foreach (['COALESCE', 'IFNULL', 'NVL'] as $coalesceFn) {

0 commit comments

Comments
 (0)