@@ -152,6 +152,26 @@ public function testCreateTable() {
152152 $ data = \Kyte \Core \DBI ::query ('SELECT * FROM `TestTable`; ' );
153153 $ this ->assertTrue (count ($ data ) > 0 ? true : false );
154154
155+ // test column projection (KYTE-#190): DBI::select with a field list
156+ // reads only the requested columns (plus `id`, always included),
157+ // keeping large/other columns out of the result set.
158+ $ projected = \Kyte \Core \DBI ::select ('TestTable ' , null , null , null , ['name ' ]);
159+ $ this ->assertNotEmpty ($ projected );
160+ $ this ->assertArrayHasKey ('id ' , $ projected [0 ]); // id auto-included
161+ $ this ->assertArrayHasKey ('name ' , $ projected [0 ]); // requested column
162+ $ this ->assertArrayNotHasKey ('temperature ' , $ projected [0 ]); // projected out
163+ $ this ->assertArrayNotHasKey ('category ' , $ projected [0 ]); // projected out
164+ // backward compatible: no field list still returns every column
165+ $ full = \Kyte \Core \DBI ::select ('TestTable ' );
166+ $ this ->assertArrayHasKey ('temperature ' , $ full [0 ]);
167+ // an empty / all-invalid field list falls back to SELECT * (never emits
168+ // invalid SQL), and an injection-y column name is dropped
169+ $ fallback = \Kyte \Core \DBI ::select ('TestTable ' , null , null , null , []);
170+ $ this ->assertArrayHasKey ('temperature ' , $ fallback [0 ]);
171+ $ sanitized = \Kyte \Core \DBI ::select ('TestTable ' , null , null , null , ['name ' , 'temperature; DROP TABLE x ' ]);
172+ $ this ->assertArrayHasKey ('name ' , $ sanitized [0 ]);
173+ $ this ->assertArrayNotHasKey ('temperature ' , $ sanitized [0 ]); // malformed name dropped
174+
155175 // test udpate entry
156176 $ model = new \Kyte \Core \ModelObject (TestTable);
157177 $ this ->assertTrue ($ model ->retrieve ('name ' , 'Test ' ));
@@ -234,6 +254,17 @@ public function testCreateTable() {
234254 $ this ->assertTrue ($ model ->retrieve ('category ' , 'Test ' ));
235255 $ this ->assertEquals (2 , $ model ->count ());
236256
257+ // test Model column projection (KYTE-#190 fluent select): projected
258+ // rows hydrate the requested column but not the omitted ones.
259+ $ model = new \Kyte \Core \Model (TestTable);
260+ $ this ->assertTrue ($ model ->select (['name ' ])->retrieve ('category ' , 'Test ' ));
261+ $ this ->assertEquals (2 , $ model ->count ());
262+ $ projObj = $ model ->first ();
263+ $ this ->assertIsObject ($ projObj );
264+ $ this ->assertNotFalse ($ projObj ->getParam ('name ' )); // projected column present
265+ $ this ->assertNotFalse ($ projObj ->getParam ('id ' )); // id always included
266+ $ this ->assertFalse ($ projObj ->getParam ('temperature ' )); // omitted column not hydrated
267+
237268 // test retrieve with conditions
238269 $ model = new \Kyte \Core \Model (TestTable);
239270 $ this ->assertTrue ($ model ->retrieve ('category ' , 'Test ' , false , [['field ' => 'name ' , 'value ' => 'Test2 ' ]]));
0 commit comments