1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace Vimeo \MysqlEngine \Tests ;
6+
7+ use PHPUnit \Framework \TestCase ;
8+ use Vimeo \MysqlEngine \FakePdoInterface ;
9+ use Vimeo \MysqlEngine \Processor \Expression \FunctionEvaluator ;
10+ use Vimeo \MysqlEngine \Processor \QueryResult ;
11+ use Vimeo \MysqlEngine \Processor \Scope ;
12+ use Vimeo \MysqlEngine \Query \Expression \ColumnExpression ;
13+ use Vimeo \MysqlEngine \Query \Expression \FunctionExpression ;
14+
15+ class FunctionEvaluatorTest extends TestCase
16+ {
17+
18+ public function dataFunction (): array
19+ {
20+ return [
21+ 'numeric ' => ['SELECT ? ' , 1 ],
22+ ':field ' => ['SELECT :field ' , ':field ' ],
23+ 'field ' => ['SELECT :field ' , 'field ' ],
24+ ];
25+ }
26+
27+ /**
28+ * @dataProvider maxValueProvider
29+ */
30+ public function testSqlMax (array $ rows , ?int $ expected ) : void
31+ {
32+ $ conn = $ this ->createMock (FakePdoInterface::class);
33+ $ scope = $ this ->createMock (Scope::class);
34+ $ queryResult = $ this ->createMock (QueryResult::class);
35+ /** @var array<int, non-empty-array<string, mixed>> $rows */
36+ $ queryResult ->rows = $ rows ;
37+
38+ $ token = new \Vimeo \MysqlEngine \Parser \Token (
39+ \Vimeo \MysqlEngine \TokenType::SQLFUNCTION ,
40+ 'MAX ' ,
41+ 'MAX ' ,
42+ 0
43+ );
44+
45+ $ exp = new ColumnExpression (
46+ new \Vimeo \MysqlEngine \Parser \Token (\Vimeo \MysqlEngine \TokenType::IDENTIFIER , "value " , '' , 0 )
47+ );
48+
49+ $ functionExpr = new FunctionExpression (
50+ $ token ,
51+ [$ exp ],
52+ false
53+ );
54+
55+ $ refMethod = new \ReflectionMethod (FunctionEvaluator::class, 'sqlMax ' );
56+ $ refMethod ->setAccessible (true );
57+
58+ if ($ expected === -1 ) {
59+ $ this ->expectException (\TypeError::class);
60+ $ this ->expectExceptionMessage ('Bad max value ' );
61+ }
62+
63+ /** @var int|null $actual */
64+ $ actual = $ refMethod ->invoke (null , $ conn , $ scope , $ functionExpr , $ queryResult );
65+
66+ if ($ expected !== -1 ) {
67+ $ this ->assertSame ($ expected , $ actual );
68+ }
69+ }
70+
71+ /**
72+ * @dataProvider minValueProvider
73+ */
74+ public function testSqlMin (array $ rows , ?int $ expected ) : void
75+ {
76+ $ conn = $ this ->createMock (FakePdoInterface::class);
77+ $ scope = $ this ->createMock (Scope::class);
78+ $ queryResult = $ this ->createMock (QueryResult::class);
79+ /** @var array<int, non-empty-array<string, mixed>> $rows */
80+ $ queryResult ->rows = $ rows ;
81+
82+ $ token = new \Vimeo \MysqlEngine \Parser \Token (
83+ \Vimeo \MysqlEngine \TokenType::SQLFUNCTION ,
84+ 'MIN ' ,
85+ 'MIN ' ,
86+ 0
87+ );
88+
89+ $ exp = new ColumnExpression (
90+ new \Vimeo \MysqlEngine \Parser \Token (\Vimeo \MysqlEngine \TokenType::IDENTIFIER , "value " , '' , 0 )
91+ );
92+
93+ $ functionExpr = new FunctionExpression (
94+ $ token ,
95+ [$ exp ],
96+ false
97+ );
98+
99+ $ refMethod = new \ReflectionMethod (FunctionEvaluator::class, 'sqlMin ' );
100+ $ refMethod ->setAccessible (true );
101+
102+ if ($ expected === -1 ) {
103+ $ this ->expectException (\TypeError::class);
104+ $ this ->expectExceptionMessage ('Bad min value ' );
105+ }
106+
107+ /** @var int|null $actual */
108+ $ actual = $ refMethod ->invoke (null , $ conn , $ scope , $ functionExpr , $ queryResult );
109+
110+ if ($ expected !== -1 ) {
111+ $ this ->assertSame ($ expected , $ actual );
112+ }
113+ }
114+
115+
116+ public static function maxValueProvider (): array
117+ {
118+ return [
119+ 'null when no rows ' => [
120+ 'rows ' => [],
121+ 'expected ' => null ,
122+ ],
123+ 'max of scalar values ' => [
124+ 'rows ' => [
125+ ['value ' => 10 ],
126+ ['value ' => 25 ],
127+ ['value ' => 5 ],
128+ ],
129+ 'expected ' => 25 ,
130+ ],
131+ 'null values mixed in ' => [
132+ 'rows ' => [
133+ ['value ' => null ],
134+ ['value ' => 7 ],
135+ ['value ' => null ],
136+ ],
137+ 'expected ' => 7 ,
138+ ],
139+ 'non scalar values ' => [
140+ 'rows ' => [
141+ ['value ' => ['test ' ]],
142+ ],
143+ 'expected ' => -1 ,
144+ ],
145+ ];
146+ }
147+
148+ public static function minValueProvider (): array
149+ {
150+ return [
151+ 'null when no rows ' => [
152+ 'rows ' => [],
153+ 'expected ' => null ,
154+ ],
155+ 'min of scalar values ' => [
156+ 'rows ' => [
157+ ['value ' => 10 ],
158+ ['value ' => 25 ],
159+ ['value ' => 5 ],
160+ ],
161+ 'expected ' => 5 ,
162+ ],
163+ 'null values mixed in ' => [
164+ 'rows ' => [
165+ ['value ' => null ],
166+ ['value ' => 7 ],
167+ ['value ' => null ],
168+ ],
169+ 'expected ' => null ,
170+ ],
171+ 'non scalar values ' => [
172+ 'rows ' => [
173+ ['value ' => ['test ' ]],
174+ ],
175+ 'expected ' => -1 ,
176+ ],
177+ ];
178+ }
179+ }
0 commit comments