@@ -16,9 +16,128 @@ public function test_connection(): void {
1616 }
1717
1818 public function test_query (): void {
19- $ result = $ this ->driver ->query ( ' SELECT 1 ' );
19+ $ result = $ this ->driver ->query ( " SELECT 1, 'abc' " );
2020 $ this ->assertInstanceOf ( PDOStatement::class, $ result );
21- $ this ->assertEquals ( 1 , $ result ->fetchColumn () );
21+ $ this ->assertSame (
22+ array (
23+ 1 => 1 ,
24+ 0 => 1 ,
25+ 'abc ' => 'abc ' ,
26+ ),
27+ $ result ->fetch ( PDO ::FETCH_BOTH )
28+ );
29+ }
30+
31+ /**
32+ * @dataProvider data_pdo_fetch_methods
33+ */
34+ public function test_query_with_fetch_mode ( $ query , $ mode , $ expected ): void {
35+ $ stmt = $ this ->driver ->query ( $ query , $ mode );
36+ $ result = $ stmt ->fetch ();
37+ if ( is_object ( $ expected ) ) {
38+ $ this ->assertInstanceOf ( get_class ( $ expected ), $ result );
39+ $ this ->assertEquals ( $ expected , $ result );
40+ } else {
41+ $ this ->assertSame ( $ expected , $ result );
42+ }
43+
44+ $ this ->assertFalse ( $ stmt ->fetch () );
45+ }
46+
47+ public function test_query_fetch_mode_not_set (): void {
48+ $ result = $ this ->driver ->query ( 'SELECT 1 ' );
49+ $ this ->assertSame (
50+ array (
51+ '1 ' => 1 ,
52+ 0 => 1 ,
53+ ),
54+ $ result ->fetch ()
55+ );
56+ $ this ->assertFalse ( $ result ->fetch () );
57+ }
58+
59+ public function test_query_fetch_mode_invalid_arg_count (): void {
60+ $ this ->expectException ( ArgumentCountError::class );
61+ $ this ->expectExceptionMessage ( 'PDO::query() expects exactly 2 arguments for the fetch mode provided, 3 given ' );
62+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_ASSOC , 0 );
63+ }
64+
65+ public function test_query_fetch_default_mode_allow_any_args (): void {
66+ $ expected_result = array (
67+ array (
68+ 1 => 1 ,
69+ 0 => 1 ,
70+ ),
71+ );
72+
73+ $ result = $ this ->driver ->query ( 'SELECT 1 ' );
74+ $ this ->assertSame ( $ expected_result , $ result ->fetchAll () );
75+
76+ $ result = $ this ->driver ->query ( 'SELECT 1 ' , null );
77+ $ this ->assertSame ( $ expected_result , $ result ->fetchAll () );
78+
79+ $ result = $ this ->driver ->query ( 'SELECT 1 ' , null , 1 );
80+ $ this ->assertSame ( $ expected_result , $ result ->fetchAll () );
81+
82+ $ result = $ this ->driver ->query ( 'SELECT 1 ' , null , 'abc ' );
83+ $ this ->assertSame ( $ expected_result , $ result ->fetchAll () );
84+
85+ $ result = $ this ->driver ->query ( 'SELECT 1 ' , null , 1 , 2 , 'abc ' , array (), true );
86+ $ this ->assertSame ( $ expected_result , $ result ->fetchAll () );
87+ }
88+
89+ public function test_query_fetch_column_invalid_arg_count (): void {
90+ $ this ->expectException ( ArgumentCountError::class );
91+ $ this ->expectExceptionMessage ( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, 2 given ' );
92+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_COLUMN );
93+ }
94+
95+ public function test_query_fetch_column_invalid_colno_type (): void {
96+ $ this ->expectException ( TypeError::class );
97+ $ this ->expectExceptionMessage ( 'PDO::query(): Argument #3 must be of type int, string given ' );
98+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_COLUMN , '0 ' );
99+ }
100+
101+ public function test_query_fetch_class_not_enough_args (): void {
102+ $ this ->expectException ( ArgumentCountError::class );
103+ $ this ->expectExceptionMessage ( 'PDO::query() expects at least 3 arguments for the fetch mode provided, 2 given ' );
104+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_CLASS );
105+ }
106+
107+ public function test_query_fetch_class_too_many_args (): void {
108+ $ this ->expectException ( ArgumentCountError::class );
109+ $ this ->expectExceptionMessage ( 'PDO::query() expects at most 4 arguments for the fetch mode provided, 5 given ' );
110+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_CLASS , '\stdClass ' , array (), array () );
111+ }
112+
113+ public function test_query_fetch_class_invalid_class_type (): void {
114+ $ this ->expectException ( TypeError::class );
115+ $ this ->expectExceptionMessage ( 'PDO::query(): Argument #3 must be of type string, int given ' );
116+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_CLASS , 1 );
117+ }
118+
119+ public function test_query_fetch_class_invalid_class_name (): void {
120+ $ this ->expectException ( TypeError::class );
121+ $ this ->expectExceptionMessage ( 'PDO::query(): Argument #3 must be a valid class ' );
122+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_CLASS , 'non-existent-class ' );
123+ }
124+
125+ public function test_query_fetch_class_invalid_constructor_args_type (): void {
126+ $ this ->expectException ( TypeError::class );
127+ $ this ->expectExceptionMessage ( 'PDO::query(): Argument #4 must be of type ?array, int given ' );
128+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_CLASS , 'stdClass ' , 1 );
129+ }
130+
131+ public function test_query_fetch_into_invalid_arg_count (): void {
132+ $ this ->expectException ( ArgumentCountError::class );
133+ $ this ->expectExceptionMessage ( 'PDO::query() expects exactly 3 arguments for the fetch mode provided, 2 given ' );
134+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_INTO );
135+ }
136+
137+ public function test_query_fetch_into_invalid_object_type (): void {
138+ $ this ->expectException ( TypeError::class );
139+ $ this ->expectExceptionMessage ( 'PDO::query(): Argument #3 must be of type object, int given ' );
140+ $ this ->driver ->query ( 'SELECT 1 ' , PDO ::FETCH_INTO , 1 );
22141 }
23142
24143 public function test_exec (): void {
@@ -92,4 +211,87 @@ public function test_rollback_no_active_transaction(): void {
92211 $ this ->expectExceptionCode ( 0 );
93212 $ this ->driver ->rollBack ();
94213 }
214+
215+ public function test_fetch_default (): void {
216+ // Default fetch mode is PDO::FETCH_BOTH.
217+ $ result = $ this ->driver ->query ( "SELECT 1, 'abc', 2 " );
218+ $ this ->assertSame (
219+ array (
220+ 1 => 1 ,
221+ 0 => 1 ,
222+ 'abc ' => 'abc ' ,
223+ '2 ' => 2 ,
224+ ),
225+ $ result ->fetch ()
226+ );
227+ }
228+
229+ /**
230+ * @dataProvider data_pdo_fetch_methods
231+ */
232+ public function test_fetch ( $ query , $ mode , $ expected ): void {
233+ $ stmt = $ this ->driver ->query ( $ query );
234+ $ result = $ stmt ->fetch ( $ mode );
235+ if ( is_object ( $ expected ) ) {
236+ $ this ->assertInstanceOf ( get_class ( $ expected ), $ result );
237+ $ this ->assertEquals ( $ expected , $ result );
238+ } else {
239+ $ this ->assertSame ( $ expected , $ result );
240+ }
241+ }
242+
243+ public function data_pdo_fetch_methods (): Generator {
244+ // PDO::FETCH_BOTH
245+ yield 'PDO::FETCH_BOTH ' => array (
246+ "SELECT 1, 'abc', 2, 'two' as `2` " ,
247+ PDO ::FETCH_BOTH ,
248+ array (
249+ 1 => 1 , // int
250+ 0 => 1 , // int
251+ 'abc ' => 'abc ' ,
252+ '2 ' => 'two ' ,
253+ '3 ' => 'two ' ,
254+ ),
255+ );
256+
257+ // PDO::FETCH_NUM
258+ yield 'PDO::FETCH_NUM ' => array (
259+ "SELECT 1, 'abc', 2, 'two' as `2` " ,
260+ PDO ::FETCH_NUM ,
261+ array ( 1 , 'abc ' , 2 , 'two ' ),
262+ );
263+
264+ // PDO::FETCH_ASSOC
265+ yield 'PDO::FETCH_ASSOC ' => array (
266+ "SELECT 1, 'abc', 2, 'two' as `2` " ,
267+ PDO ::FETCH_ASSOC ,
268+ array (
269+ '1 ' => 1 , // int
270+ 'abc ' => 'abc ' ,
271+ '2 ' => 'two ' ,
272+ ),
273+ );
274+
275+ // PDO::FETCH_NAMED
276+ yield 'PDO::FETCH_NAMED ' => array (
277+ "SELECT 1, 'abc', 2, 'two' as `2` " ,
278+ PDO ::FETCH_NAMED ,
279+ array (
280+ '1 ' => 1 , // int
281+ 'abc ' => 'abc ' ,
282+ '2 ' => array ( 2 , 'two ' ),
283+ ),
284+ );
285+
286+ // PDO::FETCH_OBJ
287+ yield 'PDO::FETCH_OBJ ' => array (
288+ "SELECT 1, 'abc', 2, 'two' as `2` " ,
289+ PDO ::FETCH_OBJ ,
290+ (object ) array (
291+ '1 ' => 1 , // int
292+ 'abc ' => 'abc ' ,
293+ '2 ' => 'two ' ,
294+ ),
295+ );
296+ }
95297}
0 commit comments