@@ -1242,6 +1242,116 @@ public function testFilteredPersistInsertsOnlyFilteredColumns(): void
12421242 $ this ->assertNull ($ row ['text ' ], 'Non-filtered columns should not be inserted ' );
12431243 }
12441244
1245+ /** Identity Map: fetch() short-circuit */
1246+ public function testFetchReturnsSameInstanceOnRepeatedPkLookup (): void
1247+ {
1248+ $ first = $ this ->mapper ->post (5 )->fetch ();
1249+ $ second = $ this ->mapper ->post (5 )->fetch ();
1250+
1251+ $ this ->assertSame ($ first , $ second );
1252+ }
1253+
1254+ public function testFetchWithExtraBypassesIdentityMap (): void
1255+ {
1256+ $ first = $ this ->mapper ->post (5 )->fetch ();
1257+ $ extra = new Sql ();
1258+ $ extra ->orderBy ('post.id ' );
1259+ $ second = $ this ->mapper ->post (5 )->fetch ($ extra );
1260+
1261+ $ this ->assertNotSame ($ first , $ second );
1262+ $ this ->assertEquals ($ first ->id , $ second ->id );
1263+ }
1264+
1265+ public function testIdentityMapCountIncreasesOnFetch (): void
1266+ {
1267+ $ this ->assertSame (0 , $ this ->mapper ->identityMapCount ());
1268+
1269+ $ this ->mapper ->author (1 )->fetch ();
1270+
1271+ $ this ->assertGreaterThan (0 , $ this ->mapper ->identityMapCount ());
1272+ }
1273+
1274+ public function testClearIdentityMapForcesFreshFetch (): void
1275+ {
1276+ $ first = $ this ->mapper ->post (5 )->fetch ();
1277+ $ this ->mapper ->clearIdentityMap ();
1278+ $ second = $ this ->mapper ->post (5 )->fetch ();
1279+
1280+ $ this ->assertNotSame ($ first , $ second );
1281+ $ this ->assertEquals ($ first ->id , $ second ->id );
1282+ }
1283+
1284+ /** Identity Map: flushSingle() insert/update/delete */
1285+ public function testInsertedEntityIsRetrievableFromIdentityMap (): void
1286+ {
1287+ $ entity = new stdClass ();
1288+ $ entity ->id = null ;
1289+ $ entity ->title = 'New Post ' ;
1290+ $ entity ->text = 'New Text ' ;
1291+ $ entity ->author_id = 1 ;
1292+
1293+ $ this ->mapper ->post ->persist ($ entity );
1294+ $ this ->mapper ->flush ();
1295+
1296+ // The entity should now have an auto-assigned id and be cached
1297+ $ this ->assertNotNull ($ entity ->id );
1298+
1299+ $ fetched = $ this ->mapper ->post ($ entity ->id )->fetch ();
1300+ $ this ->assertSame ($ entity , $ fetched );
1301+ }
1302+
1303+ public function testUpdatedEntityKeepsReturningUpdatedInstance (): void
1304+ {
1305+ $ entity = $ this ->mapper ->post (5 )->fetch ();
1306+ $ entity ->title = 'Updated Title ' ;
1307+
1308+ $ this ->mapper ->post ->persist ($ entity );
1309+ $ this ->mapper ->flush ();
1310+
1311+ $ fetched = $ this ->mapper ->post (5 )->fetch ();
1312+ $ this ->assertSame ($ entity , $ fetched );
1313+ $ this ->assertSame ('Updated Title ' , $ fetched ->title );
1314+ }
1315+
1316+ public function testDeletedEntityIsEvictedFromIdentityMap (): void
1317+ {
1318+ $ entity = $ this ->mapper ->post (5 )->fetch ();
1319+ $ this ->assertSame ($ entity , $ this ->mapper ->post (5 )->fetch ());
1320+
1321+ $ this ->mapper ->post ->remove ($ entity );
1322+ $ this ->mapper ->flush ();
1323+
1324+ // After delete, fetch should hit DB (and return false since the row is gone)
1325+ $ result = $ this ->mapper ->post (5 )->fetch ();
1326+ $ this ->assertFalse ($ result );
1327+ }
1328+
1329+ /** Identity Map: parseHydrated() registers related entities */
1330+ public function testRelatedEntityFromJoinReturnsSameInstanceOnDirectFetch (): void
1331+ {
1332+ // Fetch a comment with its related post via join
1333+ $ comment = $ this ->mapper ->comment (7 )->post ->fetch ();
1334+
1335+ // The related post entity should have been registered in the identity map
1336+ $ post = $ this ->mapper ->post (5 )->fetch ();
1337+ $ this ->assertSame ($ comment ->post_id , $ post ->id );
1338+
1339+ // They should be the same object instance since parseHydrated()
1340+ // registers all entities (including nested ones) in the identity map
1341+ $ this ->assertSame ($ post , $ this ->mapper ->post ($ post ->id )->fetch ());
1342+ }
1343+
1344+ public function testNestedRelatedEntitiesAllRegisteredInIdentityMap (): void
1345+ {
1346+ $ this ->mapper ->comment (7 )->post ->author ->fetch ();
1347+
1348+ $ postFromMap = $ this ->mapper ->post (5 )->fetch ();
1349+ $ authorFromMap = $ this ->mapper ->author (1 )->fetch ();
1350+
1351+ $ this ->assertSame ($ postFromMap , $ this ->mapper ->post (5 )->fetch ());
1352+ $ this ->assertSame ($ authorFromMap , $ this ->mapper ->author (1 )->fetch ());
1353+ }
1354+
12451355 private function query (string $ sql ): PDOStatement
12461356 {
12471357 $ stmt = $ this ->conn ->query ($ sql );
0 commit comments