@@ -1651,6 +1651,60 @@ public function testOperatorPowerOnZeroOrNegativeBase(): void
16511651 $ database ->deleteCollection ($ collectionId );
16521652 }
16531653
1654+ /**
1655+ * A power with no maximum is computed directly by the database. When the result is not a real
1656+ * number (zero raised to a negative power, or a negative base with a fractional exponent) some
1657+ * databases throw a hard error. Validation rejects these before they reach the database, so the
1658+ * update fails the same way on every adapter and the stored value is left untouched.
1659+ */
1660+ public function testOperatorUnboundedPowerOnUndefinedBase (): void
1661+ {
1662+ $ database = static ::getDatabase ();
1663+
1664+ if (!$ database ->getAdapter ()->getSupportForOperators ()) {
1665+ $ this ->expectNotToPerformAssertions ();
1666+ return ;
1667+ }
1668+
1669+ $ collectionId = 'operator_power_undefined ' ;
1670+ $ database ->createCollection ($ collectionId );
1671+ $ database ->createAttribute ($ collectionId , 'value ' , Database::VAR_FLOAT , 0 , false , 0.0 );
1672+
1673+ // 0 raised to a negative power is undefined, so the update is rejected and 0 stays 0.
1674+ $ database ->createDocument ($ collectionId , new Document ([
1675+ '$id ' => 'zero ' ,
1676+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
1677+ 'value ' => 0.0 ,
1678+ ]));
1679+ try {
1680+ $ database ->updateDocument ($ collectionId , 'zero ' , new Document ([
1681+ 'value ' => Operator::power (-1 ),
1682+ ]));
1683+ $ this ->fail ('Expected the update to be rejected for zero raised to a negative power ' );
1684+ } catch (StructureException ) {
1685+ // expected
1686+ }
1687+ $ this ->assertEquals (0.0 , $ database ->getDocument ($ collectionId , 'zero ' )->getAttribute ('value ' ));
1688+
1689+ // The square root of a negative number is not a real number, so the update is rejected and -4 stays -4.
1690+ $ database ->createDocument ($ collectionId , new Document ([
1691+ '$id ' => 'neg ' ,
1692+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
1693+ 'value ' => -4.0 ,
1694+ ]));
1695+ try {
1696+ $ database ->updateDocument ($ collectionId , 'neg ' , new Document ([
1697+ 'value ' => Operator::power (0.5 ),
1698+ ]));
1699+ $ this ->fail ('Expected the update to be rejected for a negative base with a fractional exponent ' );
1700+ } catch (StructureException ) {
1701+ // expected
1702+ }
1703+ $ this ->assertEquals (-4.0 , $ database ->getDocument ($ collectionId , 'neg ' )->getAttribute ('value ' ));
1704+
1705+ $ database ->deleteCollection ($ collectionId );
1706+ }
1707+
16541708 /**
16551709 * Passing more values than the allowed maximum (10000) to an array operator must be rejected
16561710 * the same way on every adapter. Covers each operator that takes a caller-supplied value list.
0 commit comments