55namespace Vimeo \MysqlEngine \Tests ;
66
77use 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 ;
148
159class FunctionEvaluatorTest extends TestCase
1610{
1711
18- public function dataFunction (): array
12+ public function tearDown () : void
1913 {
20- return [
21- 'numeric ' => ['SELECT ? ' , 1 ],
22- ':field ' => ['SELECT :field ' , ':field ' ],
23- 'field ' => ['SELECT :field ' , 'field ' ],
24- ];
14+ \Vimeo \MysqlEngine \Server::reset ();
2515 }
2616
2717 /**
2818 * @dataProvider maxValueProvider
2919 */
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
20+ public function testSqlMax (string $ sql , ?string $ expected , bool $ is_db_number ) : void
7521 {
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 );
22+ $ query = self ::getConnectionToFullDB ()->prepare ($ sql );
23+ $ query ->execute ();
24+ /** @var array<array<string, string|null>> $result */
25+ $ result = $ query ->fetchAll (\PDO ::FETCH_ASSOC );
26+
27+ if ($ is_db_number ) {
28+ $ this ->assertNotEmpty ($ result );
29+ $ this ->assertNotNull ($ result [0 ]['max ' ]);
30+ } else {
31+ $ this ->assertSame ([['max ' => $ expected ]], $ result );
11232 }
11333 }
11434
115-
11635 public static function maxValueProvider (): array
11736 {
11837 return [
11938 'null when no rows ' => [
120- 'rows ' => [] ,
39+ 'sql ' => ' SELECT MAX(null) as `max` FROM `video_game_characters` ' ,
12140 'expected ' => null ,
41+ 'is_db_number ' => false ,
12242 ],
12343 '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 ,
44+ 'sql ' => 'SELECT MAX(10) as `max` FROM `video_game_characters` ' ,
45+ 'expected ' => '10 ' ,
46+ 'is_db_number ' => false ,
13847 ],
139- 'non scalar values ' => [
140- 'rows ' => [
141- ['value ' => ['test ' ]],
142- ],
143- 'expected ' => -1 ,
48+ 'max in DB values ' => [
49+ 'sql ' => 'SELECT MAX(id) as `max` FROM `video_game_characters` ' ,
50+ 'expected ' => '' ,
51+ 'is_db_number ' => true ,
14452 ],
14553 ];
14654 }
14755
56+ /**
57+ * @dataProvider minValueProvider
58+ */
59+ public function testSqlMin (string $ sql , ?string $ expected , bool $ is_db_number ) : void
60+ {
61+ $ query = self ::getConnectionToFullDB ()->prepare ($ sql );
62+ $ query ->execute ();
63+ /** @var array<array<string, string|null>> $result */
64+ $ result = $ query ->fetchAll (\PDO ::FETCH_ASSOC );
65+
66+ if ($ is_db_number ) {
67+ $ this ->assertNotEmpty ($ result );
68+ $ this ->assertNotNull ($ result [0 ]['min ' ]);
69+ } else {
70+ $ this ->assertSame ([['min ' => $ expected ]], $ result );
71+ }
72+ }
73+
14874 public static function minValueProvider (): array
14975 {
15076 return [
15177 'null when no rows ' => [
152- 'rows ' => [] ,
78+ 'sql ' => ' SELECT MIN(null) as `min` FROM `video_game_characters` ' ,
15379 'expected ' => null ,
80+ 'is_db_number ' => false ,
15481 ],
15582 '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 ,
83+ 'sql ' => 'SELECT MIN(10) as `min` FROM `video_game_characters` ' ,
84+ 'expected ' => '10 ' ,
85+ 'is_db_number ' => false ,
17086 ],
171- 'non scalar values ' => [
172- 'rows ' => [
173- ['value ' => ['test ' ]],
174- ],
175- 'expected ' => -1 ,
87+ 'min in DB values ' => [
88+ 'sql ' => 'SELECT MIN(id) as `min` FROM `video_game_characters` ' ,
89+ 'expected ' => '' ,
90+ 'is_db_number ' => true ,
17691 ],
17792 ];
17893 }
94+
95+ private static function getPdo (string $ connection_string , bool $ strict_mode = false ) : \PDO
96+ {
97+ $ options = $ strict_mode ? [\PDO ::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode="STRICT_ALL_TABLES" ' ] : [];
98+
99+ if (\PHP_MAJOR_VERSION === 8 ) {
100+ return new \Vimeo \MysqlEngine \Php8 \FakePdo ($ connection_string , '' , '' , $ options );
101+ }
102+
103+ return new \Vimeo \MysqlEngine \Php7 \FakePdo ($ connection_string , '' , '' , $ options );
104+ }
105+
106+ private static function getConnectionToFullDB (bool $ emulate_prepares = true , bool $ strict_mode = false ) : \PDO
107+ {
108+ $ pdo = self ::getPdo ('mysql:foo;dbname=test; ' , $ strict_mode );
109+
110+ $ pdo ->setAttribute (\PDO ::ATTR_EMULATE_PREPARES , $ emulate_prepares );
111+
112+ // create table
113+ $ pdo ->prepare (file_get_contents (__DIR__ . '/fixtures/create_table.sql ' ))->execute ();
114+
115+ // insertData
116+ $ pdo ->prepare (file_get_contents (__DIR__ . '/fixtures/bulk_character_insert.sql ' ))->execute ();
117+ $ pdo ->prepare (file_get_contents (__DIR__ . '/fixtures/bulk_enemy_insert.sql ' ))->execute ();
118+ $ pdo ->prepare (file_get_contents (__DIR__ . '/fixtures/bulk_tag_insert.sql ' ))->execute ();
119+
120+ return $ pdo ;
121+ }
179122}
0 commit comments