Skip to content

Conversation

@martin-georgiev
Copy link
Owner

@martin-georgiev martin-georgiev commented May 22, 2025

Summary by CodeRabbit

  • New Features

    • Added support for new PostgreSQL mathematical functions in DQL: CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, and WIDTH_BUCKET.
  • Documentation

    • Updated integration guides and function listings to reflect the expanded set of supported mathematical functions and removed references to the ABS function.
    • Added new "Geometric Types", "Mathematical/Arithmetic Functions", and "Range Functions" categories in documentation.
  • Tests

    • Introduced comprehensive integration and unit tests to ensure correct behavior and SQL translation for all newly added mathematical functions.
    • Enhanced existing rounding and truncation tests with additional coverage and stricter assertions.

@coderabbitai
Copy link

coderabbitai bot commented May 22, 2025

Warning

Rate limit exceeded

@martin-georgiev has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 35 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 9cb2fc1 and 69fa3bb.

📒 Files selected for processing (1)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php (1 hunks)
## Walkthrough

This update introduces new PostgreSQL mathematical and range functions into the Doctrine ORM extension. It adds implementations and documentation for functions such as CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, and WIDTH_BUCKET, along with comprehensive integration and unit tests. Documentation and configuration examples are updated accordingly.

## Changes

| Files/Paths                                                                                       | Change Summary                                                                                                                                                                                                                                   |
|-------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| README.md, docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md, docs/INTEGRATING-WITH-DOCTRINE.md,<br>docs/INTEGRATING-WITH-LARAVEL.md, docs/INTEGRATING-WITH-SYMFONY.md | Expanded documentation to list new mathematical/arithmetic and range functions, updated integration examples, and removed the `ABS` function from configuration samples.                                    |
| src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php,<br>Degrees.php, Exp.php, Ln.php, Log.php, Pi.php, Power.php, Radians.php, Random.php, Sign.php, WidthBucket.php | Added new PHP classes implementing PostgreSQL functions: CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, WIDTH_BUCKET. Each class defines the function name and argument handling as needed. |
| src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayShuffle.php                              | Updated PostgreSQL documentation URL in the class docblock.                                                                                                                                                |
| src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Round.php, src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Trunc.php | Added `getMinArgumentCount()` method to specify minimum argument counts for ROUND and TRUNC functions.                                                                                                          |
| tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php,<br>DegreesTest.php, ExpTest.php, LnTest.php, LogTest.php, PiTest.php, PowerTest.php, RadiansTest.php, RandomTest.php, SignTest.php, WidthBucketTest.php | Added integration tests for each new mathematical function, verifying correct DQL-to-SQL translation and results for literals and entity properties.                                                        |
| tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php                   | Refactored assertions for type and value checks; added a new test for rounding a column value.                                                                                                            |
| tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php,<br>PowerTest.php, SignTest.php, DegreesTest.php, ExpTest.php, LnTest.php, LogTest.php, PiTest.php, RadiansTest.php, RandomTest.php, WidthBucketTest.php | Added unit tests to verify DQL-to-SQL translation for all new mathematical functions including CBRT, POWER, SIGN, DEGREES, EXP, LN, LOG, PI, RADIANS, RANDOM, and WIDTH_BUCKET.                            |
| tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TruncTest.php                         | Updated test cases for TRUNC function to consolidate precision argument tests and adjust expected SQL and DQL statements.                                                                                 |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant DoctrineDQL
    participant CustomFunction
    participant PostgreSQL

    User->>DoctrineDQL: Use DQL with new function (e.g., CBRT, POWER)
    DoctrineDQL->>CustomFunction: Parse and translate function call
    CustomFunction->>PostgreSQL: Generate SQL with corresponding PG function
    PostgreSQL-->>CustomFunction: Return result
    CustomFunction-->>DoctrineDQL: Pass result
    DoctrineDQL-->>User: Return query result

Possibly related PRs

Suggested labels

enhancement

Poem

A hop, a skip, a mathematical leap,
New functions for Doctrine, robust and deep!
Cube roots and powers, randoms that spin,
Radians, degrees—let the queries begin!
With buckets and signs, and π in the mix,
This bunny just loves arithmetic tricks!
🐇✨


<!-- walkthrough_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpETZWaCrKNwSPbABsvkCiQBHbGlcSHFcLzpIACIAMxJqLjRaegdubnwKUNjM9Ap1WDZxBkhY7AwxeHwMZAADAGEAIRtoWoAaSFqAEQBRAHEbHp6AZXbOnoANKzHagBkAORnZgHk+masASXXlgHUemxmbAEEujaP50Y7a4/mu5YBZGeGNvsWOzHpanY2u6AAJAD6jQAqvUANI9VrRSAAdzQyAcAmY6ho9DkYVgHmwiEokGYznEGGIJEyRHgJAk6GQtkgGEcAlxAGYAByMjQwBDUuzJWgI7DpTLZXJoewkUL4WJ5ApFeAlD546iY/HFNC+MoVcTVZAEDEeXj4ERidnuUrlSpalAYXAURTYBhReAVLzYJSMbAMvz4fChAAUDWarQAlB0lER/B4mBgpBREFUsH7egMhqNg5ASAAPDLkK3wVWQP2TaapjDUbBUXxefBEZzS/NzRapyvV/K4Qp1lZrVOtiNa3CYULcHR+za1VMZGG49Xm+O1Ky7fajjpUWi5rCR6Ox6p146nc4ppcfFi0+m40jkKiamc3O6PVOxohYJQ0CjIkuXuvPV6L9AYejdzrfL8gIguCkK1KaGpxuy8z4KaWSYnwSiIAw+TcO+uTwMw3CRGwVrUHGkBPtoXjIBO/g8DaEjwEo9COrq9iOPiLgaOYlj1CwuG4HyTguG4mIKKw7DIFu/7cN4vj+EEIQKDUSChIg+CRF48gSugCjRmgpB+CQGRZKUNrMJA7EaT4iDskcDBMBQK4YEQYSwf+/i6bgHT/jQiChEwGlaWgsTPnilBkrZ9EMLAmCkMgqAAJxsgAbFFACsACkHQwggoXabw0hCWpiBePARCwKESgoQkOL8JKAAMGiMkl+lHqJ/hUfg2LqcoWmqVFAAsGiVZVXVJca/Fee1Hi0NQIpWf4iBZry9kBRQQV2UwrDqJ0zIpLQzIAOyMtttACLQCUMAlB0kAATIysW0OdsUkCQAjbQAjE9sRPbFe0JYyj3nV14EifxAhUBUsCdMqsBgFOl6IOBjo6ityKhLUUWxAI/VPSjjK0LEWPvSQ20JV1Kg8glX1dbEXXbXdsSxWgV2k/9WD/rU+KOuBQOYKF0GwTy6hxnmCNCSGSAMNim41B0uTxHQAhoAwADWsKUHqlHUQ6TP8TSgtWmZrGWD06ZyY6dmCIa4hSNxTHyDqHr8uNqJuOokRcPEiToCkDECnpOR8DWrYyiUUNxnUTQtDMiaDCMMyFksbydB26xbFcc57AcVw7mcFyHOcN5PC8cfyl8Pz/ECoIQq0kCQAY8wnhQXAsoylcGMCOJ1wqWSOsSpLkhIRj6MY4BQGQ9CqWgeCEGeyiogJnFcLw/DCKI5vSJA6JMEoVCqOoWg6P3JhQHAqCoJgOAEMS57UFE2ucH4aAwgxPHyGvijKFvmjaLoYCGAPpgGIMJz3B6BoZgtAOAGGiBAgwFhIBHA2OfKeUQHCPwqowMKtlpB8Q8P/LogDCL4FFpxfCW44TIDtpfP8PMPYinIPfaIfQSRFHyCUaAshuDSGhAwS+RBMjyHKBvei0QugTRgKw9hoppwdBmqIeAsRZSqmUpAfKHljb0SsPgOGYRRF1gyHDGYOirQAG0AC6o5zIpD5tUeRshXIwlgjQxgXDMjkkQB0aI9xFQkGVHIrwAB6I4LZChillJAAAYmaaG0J5TRBsOFDwYTIJajaNCMiHg4Y2loHaKIfDcT/miPE6ciBoQ4mnLCAoLVshlm7HwEgXgVCZCIVgXISjp7qE8brIwUDLBHC8M+Bp2oHL8RKrUi8wcUEZmclEXIYkBD5RKOwPmGDq7VBICxCB0Q+6/1oPgxAfiABqsDZhHEaLMHoYAQnAnmPUaAGxlgXDADnMAywrD7CONAZYNhhjANAeAyB0DYHwIvIgxizgVKSlCrExAmC8EEPYA00owoJDERUJEaw+APJhhIMMAAirMCCBTLT0S6DimSNB0yhBIZAMh090T+GYPgKiwV/zsBcPCvgzMVAwzxe+eUvNgoihxOKSU9jwaePwpwtU4Tg5DQ8LS+lURmXyBIWAgwUBagcvAv4MkHllb0HhJ0I5owUBYRwuwKI6JajuI7hgeh3cKQAB0uj4OtI6Egdr3n3DtVi4ILg7VHGGNAO1+Toa+oEDDFiBgTQ0IUTyKIQcLSOgYM6JQyrVUMCBrgcCPpQ7QEDCqzooZwycp9BHZMubVXjMzYWMtnQvAYEzQsattQmz1tWI2wcmbNhtvwGRDt84bCNuXKuItGc9wDsPMwTN14HiNvvHW/Mn55iNphNRVsAIBB2nlmKTNgES4gXLrmgwPQ5ag3sXGrAqBNVyR1ayyARLcXLtbCgLilL0iUE4eVEsbAfy0WNZ401aJ5CTUyNNWaKjE3wkihrDwFqCSOhtYtHuDqnX5HIG6mwHqvWUFkL6/1gbJVanAp+6Q3A5YrMgDBfgVTUEQvmv+DyFA7S4DLB4KWmRlSEhNpKNyyKPApIVEocNrEYE9KnqMnU/4hnOD6WMzMgpJl8GmbMtMOZxCLKgDBcg0rqPoOEhgaNsR4hiGhY4WF75Iw0CtIoo2wUz3IHlN2eAfBMLYT/XhaGABuWksF14eFnaWaa/BEKiGGdJvjdKVyyLoKsyBKrNnbJ8RseY0B+jHGufMPoYBvj/DAHcK5NhEtAJAWAtZnSYFwMnoC1IwKWWqXBTpqFWyYVuYIogDA8BX1Cic1aEgYZ8LBQfaDR1YgUMeDCjIe6WAqVRB1OFmR1t+LNJQZe7V/h6Ciw8keejKjbM3rvZAKS+RpBaays1bECjlvPiiAAcgNVdqU/sgmB3w1gClsqpC6t/JlWp9p6ADcgFd7NV2zErkvFYyRFJlC+HsX7QJxQuWjL4zG0B/2S0jCux0K7hZ0f/YWNjq7HY8ebEJ32vHI6Lik5zg8PHC7sfyiuzu4CZdIRA45NlbTEU0yZns/xAVKCYcB3hxaNAiL4C1JmR4H2lLyp0SG868gt7iUHecavQD5jgp0vIiKrx4r+BsJGULz7kYPL9jMqz7SHkUH/kjLIogZY4WS+9AhXXU9Mh2c+zt2l2gaiUpBrE2ggnSvdN6dDWjgzgtSZD6pcZcmR4KfdEp+ZqnIV5oo3VjnOpo9ZHk54GZwTE/yEk/rmonnqgKMayZ5rW4fOc7QL+0iys8SKBkeSf3Pz1mxbAEYRrOzEvJYGK8xLGWst/DAIc44uyeizC+cV35XTytkAQVV5BtW0ERQazIyUU3tQLbkktnrV7Vv3dh8EnbdF/yy5Gwr3F1uCp2/fANs//FZhSakL4OGPWi/GcIZedkww2EMGb3FWUg6DWjexXn/Bu0aGGDuzPW/XdjmmYG8HEBc1pBIHvn50e0FxqC4ABwDDx1R2gIxyxwx1xxINWEJw2GJ1Tgp13HJwxynXuGp3zlp0+3p2LkZ1AmgBZxNAzGszsh2wBx6A2FmDxxCRWHeVJ2WAuS6BYPoCu2gBsAuXqDu09zojNFXyiw5FQDTw8HGQ+G318zFD5wCQFx22FyRXFxvWxFSSwD2yVxXnRF5TshFCBnwGSFxGBg6klC1zFTzHwD1z6XDT+REyL36XokL2kyj1kyz1jxzwTxU2cT7nI28w0LCMz2nimXjzzxUwL3D1CJLz03kBv1t0/2cCoHkGZWVzCyb0i1oigy/1MwIgzFrxc2i3bwgE7wMG7wSySxSwH3S0yw2Gy2GAAE17gQlbkRjp829A958L5p4kErYUEdDk8TRy9v8CJJd39esONSlH1hhZBmAcgMB5AxtV4JsX17ZptYI9DPt/xFtVILtr09sMC4dbNjsmoqgzt5BmlY1nt9UoDwJXtPE5UPt6AnJvsog/sXCbR3C+BedR4TDMDT8nQXQVF/Qw4rgCDo4phY4lhVhE5thU5s5aDLhOgGC84vx3hPsi4gJS5ODagtMdsGghDZgZgxDlh3lDgpDbgxhC4FClCNVRU1Dfd0F/ctDkAdDtJYhIgxA3dOcLNxYUE0gJldUkS3jns7MRcxcUVJcL8XVIB3Ur99tvVldH8PADijjqgijqgbc78mj0wWjIggiukQjpNxMw9wNQiZNVTAs4jsjwhEillNMzcVi8gPB8pEZriGjK81xbTb9P9mi684CtkvNQhZtYhAMTjOdfTMjc85kcjCI8jAiZiO8jBEAKAGAfFLVCR4MyQKQfF9TyAfF3UfFMMXA/F/UfEg1g4/EKByjhhYBsADNnTuBYBuAZ91k/k5jF8H4liV8IUoVS8iiNDLjL4DCYy+wzMOJ2ArtkBgQbBcV/B4h/AKgJdch/w1F0V/BsVcUjgbBjgRiARhg/hgQQkxCegfRAwsD6pDJ/wKtglohRZ+z2BoQNwCJ8oMBFYdR+V/9ADIBwKtxognptpoRIL5ZuYsC/C+AmxvEFBXQwywt3CA9gjg8xMBkxpizI9JR0js9FMAyFlk8NMVlSyOjyzKzqzYNrUSQEMGymySAWz0M2zvVZBOzoBuzNSfF6h00NAxyJyZjpyAVyE5yQVljUijAjhUD74rA/grBGBalEAQ501YZINrRbQfsfd+F/wiMZpSNOgay4MeL6yJAkNhsXU0MMMRKcMA0eyCMhptCDLkAMwLM5pahGh4QSB/FpRHtfK515RnMTUdZVE0VcAMVbzOhs0vzwIz1Up0pQZxVRZal3IQp3QZUvRBU1IyQpAsA6Q2AmEczppxYtNwNDL+Box8gkJcpjYUV9QaAxAogihYBFBOhSBcBYr5ha8SAsr5p/AmMKB6ittgpahcCWgrsxgqkHp5ApEADMyVF/x0rYCiMMRqAMQAqINMppohJmrArLRE0XQV4tsjNcBWEVF4rkB1j/09jQYRRjzlYzzQ8PArzUqbziUPrYyb1mZMrAxsrnt3hKx+sChT4hrfZPtEKsBMAMBvQSyOlSLRMLQPTKKvTIiaLoiMi498zlNAy1NyM0D9LzqkcuBagWrkBpKshwJgrh50TwqcQoqHtihYrYYsBagKyqyHLuLbUJBGzkMXVBL7hhKsMxKJKEkagpKZK5LagU9abeql4BqxQhrdUUg6BGbtb+r6BYDRrxrJqvyuBFqiBBa6bWqGhjLtI5q2slqVquCNaSsyyDARbOKrU6ye4pa3LmzWz2zRK/VxLYqdkugP97ozI5LJzZilKFjqtQV2dFlNL7FmbOhY6MVpATLLQzKMkLLzTaRJrbL7R7KuLA77V+KPLPUvLI68Nlaw0JSHagqyVh46hubIr1TZQBa4CErXNn1LyUq0riVugUtkxpqcrYQ8qZJoxn1B1MAwiC147rrzq5V+y1Y7N7BuqVZvQdb6BBrhragLbnsJq2BpqdRZqywFq5c7JlqCC1rXIEJNqizZE3a7J9riVDrJrjrQhWxUBI6fynJLqdZN7WqE0k0HrnUnqXq+VPtUAwbp5oTpS/qq6CbUVrzMVQb8EK8tyCIeU8BkbLQfYvFqgSLXSyL8aKKiyibqKcyY8/T6KCyqbk8oB6gbqGbc646C6CVhaOKxba7Jb+LZb5aOzI6laClGz+GE7xyNaoB7g9bhreHagTbp5zaxRLbr7AwbbH77ac7uh5H7ahHRaa6nKg7xGw6RLFbo65H86FHuAvaYs2LfbhHLGJbg65cBLbGFbpGHGDZuBZLxyk7FKKtlLFjVKFz6sDAs7aadK9LjHgnC60lzKslfwcl+IbKSMq6YMA6rG67pbUN3VG6sNvKW6ClGT26c6Obfwe6Irebj8GBB74rf1OINygaJ7cVo9sxxA8xYDahCwsrcrZR8rVRCr1y0xb4kBozRJu1cRR5IAqqyBjxmAGQKAoHhJ2rd6urbIeqbQ+rp5T7PgL7lar6proaZqxR776JbbOhMcphX7LQVxOFdjf7cV/6v1QCdIIGuJtnbrYGER4GgHEHnDkH3qCHOIoTEbfrTz7QwjumQbcVUG4USHWwMIMAKGGlqHhNaHvdsGIimHaLYi2HKbGKkj5haac71HUnBG/aRGimxGSm/GhLw77HJLgnQmXGvq1JNHdbMWzmdHL6rb9H7BDGXb770SnmrA1q2iNlOjGWvHeKWWQ62W5aOXAnJLZgMAeXwm58U6gVl8wV1L4mtLrBdKO74450j4rR0lMl6Bsk2UcmK68noMmWJbXLfGG7w7Kno6anD5JSbr6nQre7mmA42nkGOmcox7cH0q3w7cKwqx+cfz6wsrAXt6OqV5+UD6KIj7TaAohWRqRWLmxWgSF6775qNyHnlrccxhHQ3m+sf7+IDr/ijrfmsocRIHQybrUBHqIhrZREwSgX7qoWmsiGtx4WyAADGVNZx6UXIAFgfz4rn00b97/q2RzpMLeZQdk2yQGAOhKAbQ+A0FaBIKiBJYFMpMihKA7NyJ0mS6zUSBZBqhUg4Ldq52Jd23Jq8Wg88bCX6HiXRkojczyb4iOGqWaWeHDbkc5hbWaq3W7KCnazmXvWRtfWm7cMA2+WRQBWT7VHhWxrRW9GDGUM7aFWfblXCnvGbH2W7HtXW6fFZgqx9WFLDXInU6TWM7k8En75jGWO7aUBTKHXS76jcnkPPXVX0P3Kym/Xm6A3/Lg3zrQ3Gmeb+7WnntwJ2mXNOnkr43J6OxZ7Yb57xmHEvApnir7iU2TDcP7AP2W9V4IrM3dnOrWxwx83jnBX9bEBGbznpxLnpqq3CWedH7HmCcZhRr7hHR/FbdOJ2JyhcAgvbnq3Ogno+SaSou0B0xYvCGEurRkvXa6hzo+SfBu09r+JYCYLLIdJQgSACgln5cLzbE8g4urre3zqYGx3LW9KB3NFBwkHaJx3CHYXH0fqSATyZ2PBsHkW8HUXoXGitwMWyHHQcWf8OlA83SQ8iWqKQOSawP/T2HKXNb+OYOaJGac7BOFTu7IBw2NPB66JzH/bUPaPWWJGtWuyHHBOeWlHIAVHi31H8Ofz/PLxAvxXbajGbq5gqxfv/v9b4CjbOggftHcBouMBcv4uWoCvxXdECUBOYe804e1HYPjajnj7gexR3EcvFo8usekucerRIfzroe7bWLf5qOXvVWfGRt3uGPPvJKrB4A2OSsImF9KsVKatTXFzzXs6ofBe0n7WMm6j6IJP8mpPnKZPSn0NymfUFPNTA3ORrXVPOg7vor+atOh6Y2kq43ga5vOhNhjPlaxmMpguNyfCVRfAjc+xLNAAB4Bc+Pb2fc/uk8/J9Od85LeI7Lb0aFKK/ubC+WqJ1qE83Psp+y4x/YHy/p+08y8p5i5p8x8S+moEEdylfmsgEqhAN/DkQ+bCiAf4lnA2Ed5KT7E3WQExta8IdNxNBzq686qSYlaYTBYG4haG83NG++owYRem/odm/SrRe5U+zHkxa6zW6gg29xu9J28Yb2+YZiNYayKO6TySO4fppJ/t/gHttV49ZVY1/rrk6w58v175bD7AUrlVWR/+JB7jDB7I+Ng1rf6R5k9C2KPKnunytCZ9raRdf/roEAEFstGn/XPuj3z4Z86ekA3RGzyVaeMaOXPOjpqz55R0BeizLZonXY5lYjWS+eclLziZ8drWs4IgQr2LqOsCU1lJDmrxv6IY7+2veTth315KcjeXdBpibyab3cLeOnRKqPXnYGdcUs4PtE33fCS5rCBKfioaXQwmksMMCf1OyA2DihXO4BWAB5yB4v8I+ujK5jH3vo1t4+V2FOPsBeYp9UeefNruANQHXNXenQErtSSI6gDkBTgwvi4JS7e5ag7g5TD7FnYtsTq/4WApJGwCOYV4zRMQAolwAtdnAjggFh12gYgtB+CQ4dkPVRJ99dKQ2GeDlGnYVAKugNBdnb3n7ENF+pDLFqvyobr8aGAHMIhJl24WhQOLDPMhB2O7qZoOp/c7vb3oHXcq+S1U3nzQHoW9HuHPRyq93Va88Am/PJjmojIg/c+WEQxSJWGXTBRDBhHXzgYAAF2CTBkAiHnsJgF2C0eYA3ABAIZ4ZoThqqLLtTxSFXCuA6A72u4ymHi0cBb3fxlIwWGyMYkK4VesL1nxkDOOxrSgTxw0oWt++xjf4UOgYGidMmVlV1mwErrX9sBt/VlphwqZ69W6BvM6q1WN5hVhBZvcYcrWz4/pdOsbSQbb3SrXATgmcYYNNTbZO9TOGUdcJQGfTr1wCsEFejUH9471OqubA5ofS84Edi2BwkjqYJuau04+5HR5mTmgLrV366IbanNlKGQBmRJSDtqEHAbZQe23fPtrkLgaD9+ur1SFmP1+yI1xuk3f6jN3KFz8Fu4NZbrULYy4sGh+LJoQDQYYhYSWpNOigfwpZH880J/VquoxzqwjV6QwuaKMJaYPcha7w0RtzxlrfCI6vw6GD4gjF8j1ahPQjgjzg4f9laKzUtgFzFa/9bITPR2pmM5STCsBnPZykmNDr0d5hBApjlWJ+4YD2KFjdEdYy+FNifhLYv4eOiBFTkOOYvKJmnTUrS8aBMI8dPCKV7MDkRxGSTuwOKbqssRuvHgbiL4F1MBBYbYkWMM05kjLelI63tSJ6bklKc9wJkX/RM5pQzOrgn6uOlKCVhm2YAfRKEERTOgPADIRIRcWqiVQ4CT0XqPyOzbb4DBQAk5jsL87FjQe5bUviF18yWCGCtg+4RcKuFmDUuFfOAmcIcG09fBGE73FhOPKyka+4Q+vgwTkEEQW+K8dvskM76At+2oLLIWwhHa98V4STAodfGQDFDQh+nGkfgwnbotqhy/chq6PW441Ghm/IDq0O9ztC9+nQhikGJ6Gnc+hiPa4LOKjFc19xsYiYfGNrHTDPhswlMZy1bFDj1aqwyrusPK5bCIJ3nRQLsP2Ff9qgP/Afn/1uER8vBjw5wc8MZ7uScJSAryb4J8k3DXh7PfSR8PrG4DJGqYgcemOGAFQ9WJAkXqOPmJgiYmVAtfDL0SZWtjG8Uh8HOKfZOssmLrDwFf2rrdjVxPre/tiM3HVNtxIbXcWpz7okjDx04ckUahPESCyhUgzoAukolUM0hOzAPoKI3ZEBDmcAuyUR0OHXM7xLvfwRYLlHLUacDbKvu83VGaj3w2oi6nqNSEGjOuGQ2UIO365RB4qRo4bhsSnYTdMG6o2fsSnBhYFzpi3dGsJJW7YsxJa/CSR6KknhEZJwkfbh0PA6KSgyXDM7mpLylzpQ2Wk9Ti1LjGdAExzLBsRq2ikmTZG4M9sco1zGA9bJZtBAZHxLGkdXJ5YvHlD3BlmN4ZMw3xnMP7EyM4pCU9saFMwFdi6xPYoyX2Jik0zeyOwFdLAEaAboxQw45OqCIoHpSIRWUlSY7S5m0BWwvMhWFumE5F0ERyvFgSiPdblTmZlUjDtVI3GP8txtTBqSFSakRsYqog6Np1K6b2jJ6DOekuXH6kYBne31QyglOQCfjggYRddLLOfQUMzRaYIIPADADLopZoMTkAQF6zMBAWSgL+noPAkTSxRPnaCXjNgnR94JC0mVlbL3TM5IuiAtCc4IInIAuoHgjyWn28GXCc5ycyAPnOCGZBeJrYE6nEKOk5AywHfPTogQtwegSMhleZpV2ewMSzpPXTiTuSSpIQUI8ANQMFHUDIAxIFADIDiA6DYhNIuhR0r+iUE4oC51ozBtPz4nnjKh9Qz6f+2+ktDt+bQ/6fJMBmH9gZRkUGXB0lnSy+ZGaBluFMTFRSPusUzmdzJlmbpNA5kv7C/z8kFiSkTkjAC5OOH7C/574VCcXKeFQDf52MinvYICl4TsewU1xu0V/juQuICWbrDsTjDPcDJkU3sXgObEcytQqtLINABCACzReqU4WZL1Fk0Dtin+NBbQNZq4AyFHkAqUwOdYq9WB0GVhVxDtQbBMFReO1Orw4GYitZ2GHEXVL1kqdGpnQGuHVVlC8L6gEVdqWgo3IYkK4e2WAsPRhYAZ6ITtNmh3S0yMKHArST+i6nUXZoYahY/EOkBUSPdRqwwR+tHRvo8xDK+CXMDQEJQ3jCxR1P7OPI6niC4UzNLQZ5GqB9hHQyABuWymkhh9AGnOUQHgA8B2FTSK8bEOqI0XWKSkW4RFPkBaiQYxIXEJIDwEoCGZPIpVKzL0l8A+hzo20XqKmGoTVA3xpSpeG6A9D5Qql+YJ6P+IaWoFqwy8dZps0qWQ58wYAWpfUtXnrNKAwSJgM6GYBYAXZHgP0HqxKiYRVQ6Xb8rEAMj0R88GVcJV7kQDyLplDANukegyiMKGMCEtQSylkQhEzU8gWoHq2oiQAAAvJAHS5LgxQh2C2PRGmhIFV5HcrINvjIk9gsISStbBUptDegFQuAUKHoIXn/5p4iyr6nRH5T4gfARZHpCKAICRBgYVdH0P+L6hPRAwxikIM7OmWZkFAIFIzGewvYoJp5fMKQB0HID9LJAJADoB0shwFzZljgIkLLBxB1FClUSi8sNEhXlUfyMuVlioPuDXLnEf7LbuRR+mHzZJx8smod0DHnyQxdmM/gYpYUhAzGaijBTQCwXVAcFEUlmZTOMmMdZGzC3he2IAFE8Da/QjRjApR5OLyOLi8VmUTQCyBoBGMgHjqvJZVcQgAINNFkABADYAQeuMpaGtKqQCJA6iWgH6r+6YzA1AY4NR5FDXpoI1BQAEJjQwBRqWlYgWNQyHjWJrk1jqvMcbXTX/E0FWa8NZGpZX4QpAea2uGWuogVrU1zqoNbWpDVhrcAOa1dDyvmUAhFl7apNR2IMCGqBFxqovGasfn4LkZ1q9MXnULR2qkpwI/5ELIl7p0VikI+xPQrhSMLjGq6+OrwsLpI5LK2TUqdws6C8LEA/CwRQ0mEUriXKnAzyjVJ1lSKg2/Ag2XIpMxMIlFKiuAmov0XYljSsBGlPvhWz2KPxuYfRY4ucVP9TmoSklAcrCAtdGFRg2oHWq5GcoMwiS4qiKBSXqD2RVqFtj2BqDe9QgPvfMGyCehdQnoCUKKLdC+gJRmQUUbaDFG/I6g8NcBCDByI3J/Kek8stAOkBtCGxlQNSeQE9GZD/iUV6NTFX2BQSErKoT0ZPrhvkaDrYAAIfPFGptB65nq7NdMIRpzbGkDsNpKMByPVG7L9Qhmh5asvRXpd5ofGnlICq6nm4kCom8TfgEk2XwFEsUNTRoEC0JRYozILqMyB2hXQuoXUBTWpCUBYqVNvUPqESulTlRQNn46iJfBCjAZWlh6hfvQAI2ix0IXGevuBtgJ/Zi+j6TleWAQqqhXZcBXZbVWOX5tDNcq90XvPdLSTlVf03fmqvJaJ5NVl8xmqeukDnrBG06p9ZeHnUIyn5+AohSrVG2IB11ijdyZWqxkxzYF7q42J6qSD9kfVnagNd2prWFjNNTjcdYdvh6A8TtzfENXhu026aci+m/whyNkAXbJ1k22dQ0hm0UyeeVqtMb2WCYrb5KyUkEWOK47gi91Ysouh/iPXSQUmmYcbXa0YEWVOFyspcfk3vWPqvtl4F9RVLfViKuBD/KptDDxHKcCRsi2oEcsA0hBlFOIVRWSv0X0stF/xHRU9NQ1ZtA+9fRDR6s1LTVTmNzLVP5GZgxwfytiliV6OGaZhwIISmAJhtiU7DwyVazoHWvGTTUitSSveiRpZQ4gSJNm2TP01zC+BVIVuXsP2HeX8b3NQm6QF5uPg+a/NNABRD0G8CUA9ygy3ED6A8CAAJIkgDbtnozIc6MyG/IP5FNiAdFb4AS19gNNIa8ZA9r012bXt6ukzcVrM3a6tqNSJePrqzDzI/CkoE+LZoM2vb800iJze1IE1ArflNukTYEGwCqg7M9utZY7vkBXRGQTGjQAlEqi3RtoXUX6LFA+jMgIa/EXZX9h+DvLSVHkZ2aqCy1eLTd1K0IPlqqGFaXZcKE3fX1F3aLbCUqo0vYXaRCZOt23brT6J36kt9+FNQbdTS1XK6pd3AJHULU+2w7ptIiviouufkLadkQO8hdmP9VXbA1rq3Gdttsi7a8g5RCsXUA/1sKcxR2tST2tO0x7MwF24mcz3AM3Dv9xPY7RTQzUDrY9ka+PYXqyBvbxWCajtYgcdrIHkFirIwPfpNUYAfthky1WzJRnpjdWwOg1mDqoU7rJx1Ai1gvpEjw6oezB/VfLMfYcLipXClWchyx0zqH9cYPHerIJ1rjxF/rXgdIop1/qqdAGxRbTuA32ZGdEQ57FPueqW56+urTNIm1q1Nh+c35FncrQ526D1FPOnbchtzG31oNwu4w4sDF1iaJd2DeDjLsCrGh5dFuOJc4EPpURnVda2tMZtM1a7FcIlczpZ3VFmG8wFh2zqvso3G5LMfu2TYHuyPhbmNlu1uB5uE3z769+oB3dJrH0ASQ98WmpMptUiqb1NKukNbWjj1PaE9+BqIynpiO4oLN8R7wM2y4VzVkjNnWsKPCwAF6Xt+B4vQAVL0FHBNlehwCJrt1lHG9FR7doyAShPRPo50BKM9A+iUxto20OLSKEj0ih6jyWlLUBLNwZaKVNpOfTDuoONbl9JW/RQsCyXvgZcsR6ZTm2rCRK6uCRI7B1oVV0MlVR+o+X1v9Fn6ATnDC+apLg4CG2FE2slUaukOmqn9aregwQuplfcMAwOy7WgegN/7CxDhwA3zq9X7bfVa2rtdAZu3vgIjGAd7Q6upP5jaTVE5owWpwNtG8Dz1d7QzMoPImpD1B2g3gtZlYn2ZX3KsCwdIFbrwdaUmhVDroVTa2TFufHkQCR0id5xaOxcaiLvVkrsdqJjALIdwWiKFDROz9STuDhk7f1N3dQwooYBAb6dcBJ4jGFeMEkIN/xcXZ3OgyCc/DEGVDeZnQ2JCHICuoVuHxw3NGYe2EiI1WFaPhBZAz2+zQb2gzRmhOAujXURvM1xGCq/RmvhGRGP+wnO5UbpSgm6UAS3NhR63YsZKPoAG9UmhRNuyqMFBUV9gcPUprQBaZwzmapsLGfUDxn2jRmotvD3TOp6vjLKbM0VXVEpHaw/KjwMWeWbNb6qEx+zdMbWVeBnN5Z+Y45Cr11cggdemsysbrMybeo50F6BxvOhRQoolUeKDFGZBPRjjYQAqEVFxCnHx9a7W4zlvuM8HnpS++rSvtK0RhsQBAQyHMDdMb7b0W+1QTvvlUEtmhnpMEyqohNksAx5+mE5fvUaCdb9TRifSiaFPonEZVM8Uzq0lOf7VtTJqA/mKJP/yxQABogEAe9WUmyLP+9A0pkwMAgmwjJmAetrTUYHe1XZmM5ybjMJnE9hB8tR9oFNKm0Tr6/C/9pfnELBeUp0HTKfYPRN5TZrRUzjuVOeQ5e8AdUwrM1OiH0dOp2oJIYkuGn0TmvV1IockWk76pMitQ9Ts0MeQ6dJABnRPpKobZDI1hkpA31hhW8WkQtcy++p14SLapwaeXq+etac7Oqdgmi56vAguGhd16+3lsB/J6liUJGGMMbH9P7LIlGG4M0EaglYWB1g4JPdEbUhp7RQeupag72uZbKjw+ewshuYr1bmqz3mg8/5oqK7nfA2Dd3nhS97m7aN6DMPfIjbP2RcVnMEgNHszWDgo1zoRAI9sEv9mCDnRzXeVdHPzYTqPIdRTVfeMERij80ahBocP7yAlrcx5q0PsdJGYkEdncQIVH8gvnrjjO6MHNipX+AjMX5p47+ZePMwRwP5ao8oKNLa72tu84E4B1BMR5j9fopC1Ccg7Bjht5/TC52fQWCm51eFubYQocbyWSLLjKk+RdJ6ba3VSG1upAPov4mnVNJni7AemvwAOLqB8myycpu3bqbs17EAtd7NCX8DvJtxqgvEsaXJL+O6SwweXW9klhlABS5upnLi8VLu6tS9wdMthA+DzPUWxQHG1nEGQazS9VqZvXiHMdeplG8+sCuE6P12si035RUOd17LR1h0y5ZA26Gu5ytAw+nR+uDCvLP+SANoO0iJWXTP1vtLta3Di69q9DOgT2iMWPWLcpirxWxOQCIEek7WFFFhsV01y6uyepJZme+OkJYwX7e3r7b+uI1clXxApXgHD7bFcQfTIWPpDlh7tmG/TFxH0ubXfiIqtdptQMrLs6xuVikXlXVq/FRLtlTKQsg0Bys1AHLJympmctBiMLhz3R65fIFuWXY9FIoWRCZsK2FlR9TVjzVNCXjkBWqaRgSIUqiDjgPC252eZnbsh1yfZtejpSpCCxYqwAM5tbCwAytIAtwkuGUm4Q4xvj1ElmYo7vs24wWvRwHcEyfoUlnyL98N4O2LcEOPcqDqNqS+jexOECyIeJ3G0xcJME3/9RNgpCTYpNk2r9MBpm8VaIEPaS7FAXTQbvYC02U1eNpHqyd4PTXCHkarZZXf5heBSH2exBQhVEuMWCTDNli7xYIdkQHtzdtlWugioUOuLzFk/Hw6jX0Pc1Qjlta3fp5cAiDE6rh/TerWM26TIag+yQ8jXDqC1iyxAFzZQWdFoH32tGy/vm0OMqx4tkcWwdnLS3ODmU9SwaYVsqmoe1jyBxqcKlXqSp5dHWzwr1umWjT5qjWbJzNMm3FO5tqMXUGHvW3XLHms9I7aMPQYqx4EV21BHds6Dhp8KiPrFbJPgQBdCVg/PooVF+2sAnpihCU+SBwjQ70AQI+mUV0hGr9da3kYY+uaT21rPRrM9UCXrqj+rlmWTQBL4231qnkYte5Wdt2lGJNqxhRLRp9D0bGNzG1jRsY41cbGQweps6HtbOnGprA61pz2eeoc2eT7TlOxmYqtkbdih1u04GJOvcmHNJe9ZfFZ5GjPvc4zhY15vQZZQAC5UB6yaBuP5BKVG996/LflDjm/zJT+kXuDKdKCILMqqC0Cb/tb94LvWoB6fI1WgO4TjNDx4iage82DTwpi1X9qFsA7iF2Lz+aRc4vMn8boorbRg+hhYOQDyD7h+o94dU29nLztp0o84eUuqHGjGh0zBDX7OBL7Npa0Y4oNTq8XuF2BxY4xuSUYkv4FgDY8FmynqFMtqcXLb5sCu3HzPeV1smYC6XhDqOgy9qdVnGXAnmr4J6IwsvriQrX6my1E8JGxOtDjp+UM6fUW6uWAaTnxSUnRBRWMlJJ2i/k8HPDUXDMok+PRYVB2L3ayEp51U4VcTpan9T4N3NCads7uscHFp+OlKtdHOn09yq5nqWoUTar2yhq3GdKCi457Kud210DOsSCQVnmpY3vVfsnUfxE4NZvJvlBASAJXXWMFIF2cAhgYerlm/NdwOTHjnK1s5+tfzeVAs7111SHSNuAPBpqPKcY4WQXPBJTrtQRzY8/Ld3K9FPwd4O5vVH7X8oDhMUG26wDdLeogEhs6O17dkY/nT1987Prevz6QXn2ddyUHKSFLb46CZJ+SQ0kVbNnadw7D/Y35dbwb3pOSf1uQvQnj+YDj1/q8gd37JXMDgW3A8IumT43SD1R7g8otgLqLdL4OAy4O1Mu1H1DjR5pYHdZuRLHasj7g/5euP2X8b4d2zcOeivaPE6vkxK+wv63H90r0U0upJcq0bAWPWgEq8oX2OJxsTTKY++1eVixP42ilDoUqeht/1dpuJ5aG1TJAUEtQfxOUTifmQMVQNmid2mnfZBe7Q+/u+xDwiRLh71YqjQkBHiSgB7tnmoPp59Vt0jgR7/GrXwogUgC7CiOFbLPoCfvjpfLNVO5o2CHKjr7U99HXxlTbn5ozb0IAyB9igrH7CkF7A3ghKkZLRj6FcK+86Dl7cAPQLq5yhWiZehcvxqjQ8aWZ8AUvXdhrQNnKQ5lZka0eL1lZgQWsE74olp2J4e16PR19Wm2xSiRz2ymP3EsT69SmX1U9HTXpZTho0Dbu1zo4QiDEPiEz3LPY0CaDOdrcTPq95X+iMQ7S7pdoLnopFxDcAdQ3T9XQpSZQ5Qc8PJHbLgdwN90cd2R1Y6zj6AfJKKfkPRVnvKZYJfP7BPr+qx3948j0zubJj1D2Y4E+YmhPsllWuDIk8pSpP3HBUxq5cfHqSZCUg14r28dl0ypZriffqeoOWu0OQV7gXa8tO2XVDNpp105e0OfY3X+ihdF66+b/FfXrnf14R9524jk30ou5v+ADs2ZcgS05grG+ZikzQ7HtgM7laDNMfk3YZutbOge0AAvSgPgAncjmun6g3XQW6fp9TKoxbhqPXxs8RKh7R1/DYWVnvXpzUzyt5eucX5W74lLVyZ50EqhJ8irAINX+97mX6ORvOvqe70YN8zujf+cH0CsoedrnTff5HnAA12VvOk77zxt2lyTPpanrU+q4h+aK8UgvrBEHe7UHZ+pXhQwy2rZr5tD8bZvMyj7wspG/nf95cFq7whdRfqqUL8HzF71Lx//ekbgPzV8D4xNEuxTjB3sij+xs4ONtNLwm/z8wfknGXuH67ZR9ocDq/fuayv/gDEdUuKPrL/B774SmDe6/w3r8WK59qmP+P6HmV/A6Y7XyeZt81H3Y6lvSeMpmdLH48Zx/M9b/78sUPj5R2IikrxPiZYWuhtqabG2trqbY1AVph/70+ggrabHKmnq66uGd7PoppyTOJoreu74BU6S6X/rfK+mhlNlZue2oEm7YadagHKro7sh/LtSSNjmqBya6LfIHOfZnc5Jm5bjGBAM0kB07EaU7o6AJq8sOiSoBDJHyw1aeYGF4ZWk1M+Bu4uqK74p+7vod4X2yAGyBm4xSG+xK+lyiH5xG6Skgw3OrWkXp6oyyP+6iBt7N7awQtJLuhoBfJFIH8Q+1sfDnomCpQAFyqorIhAEG1vPo7mcgZAAKBjQCXz/OL1i+55a77oVqnOhfv+YAQ7BNbJgQudsAyb66rNKqyqgJiDaIuh+i34ouN3sA7ouqFmA44BHsojbn+2CuY6g+ljpJSZBH8jh48uj3tS7k8M/o4bE28/qR6L+3Frv6aOmamQE6aFAWKBb+vLng6NBA6s0F0BHsgwFHOBBly50e3HoarAgbWLgCD+gtiP7C2xCrarY2rBkpbo+kOrLb2I5QGtDQBRlKQqCGathcSGu//r46ABepmMHqAFPl6xU+xOpE4/qO4n+ouEEVLqZM+LrncR22NhJq7/umShqIYBBEP9awubuntgZWJ9nATpUnHBk4e2EchYoYg0cjS7YaAbnFZly4bhSaRuw/N4qc+vigAzvBOoAEppuk7GuBQ8zCt752CwTMfTDAAQF4BOKl8J0zTU+oGEY5O4yOTzpU37ngA3oO+uZ59OYqtCrLMQgW/i2BfAD6A9635DygMMq5uW41I9AH6AreGyr+T6KFvgcqx0MxnXrs0ORJ5iFwo1F0AkhZITQAUhfgrHy+BM0G+wqIJngiAZ64fiVQegUKhVR0YADJyGNatvuSBeA4pHJ4fiFKsrjSB5vgGDQu2hLlqbe2kEwAPg8AJr4js1oKvRFUsaNsp7YOoAdQiqbOO+hxBe+qDawWhNMi4+kAMu35wecNl366q2QcibHBEwXkEI+YPpJRzBkPl/oPezLrALT+6DrP70uNQb6okGmwXqoQGdNnh5oOxJmKCEhptMSGkhW5CPScuwBgdq1hGVOmjnqkBmUFlhFQbjKqhnYeSFCQJHjWF0QxjIWEhS0PvybYW2YZMEYeo/nJZECD/osFP+GPisG00awWwHyedQMraq2eqOrY2Bf/kVJIi2thjoBOpPtmGnB0nOcHmmlwYbwbB0TvcGXCzPqPxIQCUtGTPWlKnoYO2l9m8HK2HPhKp+WuLJk7mKW9hCHB82wqGbxyeTtUG5yP4L2HyAovhRrumqIV+gJ8JOLG6YhUEWZiBUyfKNRthqIB2Hqh3YZSGqwgoujQIhoHHSGjmzoX54b2uoXcT0MBoecR7UIQHQAdAI0HKLRhpEIjTze8oFaF0SnTEqE58uABOHURmoWhHn4LEXoInUigj7bEkEQaDARYNoqECSR7AMdK12a3GgyI0fdmW7zhg9ogCyhq5m3QOhooExjcAGIK1BkAPGJPr5Q9sFRJ+e6kQuASqkpJ6FHSgYTUDBhZtKGHEo4YcSh0Q+dvkr2A9oCWB5KYHpJIQeB8omHQekJnd5Da6YaeG9+oweMFrhV/ph6yMmUUWEUujYVP5jhLYbgAoRc/ntoL+pQaWEuqzYVRalemYESFqhXYZqHVRtQbVHke9UeWHlRckW1HTh1YeQZn+WYTlG5hw/oj5v6PiOP5FRIOhLbkCHBjJ6v+qweMFK+uUj36ImOwWsx7B14QAG3qJPnwqPhIAVVLhO4AW+GoAH4cby3B5UAdHOW7UigzSA/4ZU6AR82N+wgRvZm8Ey+6TluBYh0ER7ZUhXOpCGh8hVjFZEeWoIVzmC6ERG5YRsoiohXYNOJLoy+zNGRGthzUe2GtRU4TrAQxqXPCHlEPpMxF6+oHvEpqR9fCX6wES3OX55gJ3ryFdQ/IZ9gAw0GOKHZUtoc55ShFkVZHoqNvnGbSRRHP1GYxXENjHe47EaBjBQ3EWH65mvUvnDQuXhqe6VOFoV+gSRn2LsqRYdoRFYCo/IPLL0YjGMxjPR2ftlouhySpPRkxtasDB5Q0zEC5HScMPQy0hhbOlTG4GoVdQIuF3okFQeqqqlFAyGLqGI6qM0XfK4uK4WNHw+E0fmFMcPsfaowCVgDAoC66jDCFkmHUQxbhxkcdv4EhaMZREYxDsVjFDR7khHGbaUcTqoqhacTRGZxIwaNHqAuUfkGyuTHEtrbhktuOJ7h6ritHrBito7RVxnjnpbeOWtn453hX4Q+pHRr6ta5WWoVrT7t0l0bIrXR94d+GPBv4Y9EPgAEc+72204Ek5F+S2hBHaKxESCEDgdEVHIIRicUhG5OYMTUCCx8pNDFeG6ot9GIceEVdgv0hEc+hYhYGKRER8FEXQBURA0RnFoRuMT6r4xtsVO620wKmEogUHEXLH8QBoTzER8fMenECxWoZDHvx6dBVY/xxMelpla09FHA/kW4FVoT8VocioruWgSrH2h/ECYq3MDka2CtQsQHLCi46gNMyZa7kQDD1uJjE4zQuFsQkKmxwYcgB7YVsTsopxUQLeSN+iUc36uxiFrd4ex6QemEtxOLih7+xpceNHJixLkj4x08jHiYWS55GVybCdkIhFxyfkjHHVBcccmrJxiKk/EFx7URhHaJ+cZOHgJPYaTZiW4iTmGBxUidMHCe7+ojrzB0pjXEQ6Ispj4NxR4VpZIGDiTi5eOIhjeGdxRlljq9x+Ov3GnRShrrI/qI8TcGFm48XdFD071NPHkAz0XPFvRC8aBFF+9LBtIEQH1t8HRB2+qkqm4oIRNzghQfCKLAxu8aDGVhlpnCEMReMTDF0YYXLKx3YPhvSzM0lfE2wSxsBGjohAKMU1G6JtAM/H8xnKADFucF1v0kfBuKAyGdYeVmtGN2gACgEegegxWhYXnpGWY8oIslWigoeirChdoZKGQ07MTH5cxvZr0lgJ3YYpHDQuWgAn6hUquHRLs4ULXpaQxaDijfk9sd2GD6UYY3bH2GStKGRKHMfKFaBq7HUBMxOybgnTc0kOrGEJQ5BPJOQIRmESUJ+sZ5Fr6uJD5GvWS8IwlBhylHVaeWoUbBDpUdEGgkyQGRrpHu4LMbfYRUqQDFE1gaKNwkH6kHsTT8JqQR35phXsc6pkGSJpYllxeYQUFMcyBisJ/YawkokqIqifZKv8pwholVRhieomox/SYMmmJM4UYligpyQYnmJxcRymSJjYrYkyJzHLiaOJils4lymarlwbuJa0fwY6pm0eeEXEmtsa63hgSUcHjBT4RiKgBwVuEnfq74U3EW2N3GPFfhcSW9RFks6LPEAur0VhTpJwQb4YTJEqvLa5JvjNKq/BOKKhojJW8WUmFs0IXz5VBc/m/G1JH8fUmhccot8zQY+OPMBrUkuiYYd0vSY/EDJ+iYNEZpGEZ/HTw6VMyEp+JMd6YeGsBDLGOcMFJTG+AmCYvyruZbjgkgJdgkqlVpZcsLF6hoscpGGhVVthH1g0sekCyxB1p2n8avaR9E4Jeyeb4HJcoSRAKhcZmrEEJjkVEqkJHShQl6xdJoimGx0gm8YopDCdbBMJylGwlMoHCfQB2xsgHhDpgNKYqpJRSQUmEnyKYbDYgy6YQia+xYiegqrh6qUjLBxsjIBl8pJkZZKCpNkjnFQSUqRVH7xZidg5IZ5abKmFxWiUhlDpGcdhmqpIGQHGX+5cdf6QZxFrNELB+qaq6OOy0QeGrRH4Szxnh42NtEE+fiXtH+O3cXajBJchqElgBLqfa6RJ7qZ+Fept0T+Hyyf4TPHJJgafRCJOIaa8aRmWST9GRpwHgDboYsaVPiDSsEYmkh8yaSDHipVYWMCzSoMA+KZpmESfFZ2Z8Z3Hhc5BNfGRQflnfEQYZaY+mYZCkRN4JpR8YxH7cBMXm5wJo6cMI/0sENpF/UoQHPIc4RfgnBYEA6cYnyRVaRN6uCSkYTGsRJ1IgBDU3gH+C3pkdlaDWxj6eGmvJnTBFbCRbUC6wecyEM5FxRxSlOYFmQ1nmwrJxcu8CKI+Zm2DVZwolsmDMLMU3LsAkypVlNZJkUkLFyyAD6B7e8oIsokqYdp4mtU1hJYobp1kdukfRLhjaJV0K3iCmQYyIbEGm4FGOMjteHicr5+kJXqMhNOKWd2h2ygSrIAVc9bnt6iZjpvlCboCiJNm6g5UPRZhE0amxinwLAMpRoKKiDvZnobuulQBRZseJKxhCQXSm+iB3ANqph/6SylqSGFllElxVicRlcpFcWRlqmE/lnE7xI4ZUlppVYdhkAC2cVCFJx5Ec5mVpeGZKk45aOXVHRZL8RAn4ZS4Tx6EZEidYkapk0ZjY6WuqfNHbqDjktG8cFrIeEmpStiznmpzGZeGKyPjmIZdxB0T3H2px0ZrJhJ1lkPGCZx4cJkxJ3qWJkPR/qVJk+B88XuwfRRfvLzhpG+q8FRpl+O6hu6vRqAzvEmmWCFwRpSTpmQSFSfpnEekCTjGmZiIeqIPMVgpQSS6uubATIxD8YTkmJhceBDuZUMZ5k5k3maH6P0v8aOyug/4KFksYoaTtZYEHQASkZG40PDQeAoLiwCjy4/DUabpIKVFmKpRORAloRfmTZB2QygrcnP4tkA8lLKd6C8mU5keeLH6KCea2lp5OQvAQWITMDzCtZaoO1lYpbMYQF/JW6Tc5paHgHEqzKeuq/gz2h6eQkz6IQGdkJeIHmaRRgikAyjTpzef8RNO16WEAZZ6sNgw2xdacSh5ZjsfEHOxwOZDag5sHn+mwmkOXBxY2oiQD4+IoGQzngZ3KQVH855LjjZ1B3avh4EQ9ueDGZxX+ag69RjURhmF5qGTVElRv+g1EEeskWAXypFiXTlw5chlMFM5crhy7VxC0Rzkv+XOcakMZZLuBBbR6NLBwi5hlqa5BJkuX3EvhETsoby542R6mwBCAeaISZSSfNAvRMmfoZyZzMKk44R04PGmbxYEtvEIZduammkmqETUk1p2aYhJyiV2AqLNJQdtwU+5OiS1H+5CkeIURuTEV/GJZKkX/EgYygdgzcRDILxHaotAPnmwFKhcOkmZNaapDcRGgdOmlOK7HOntpXeRgkjeS6dgksxu6fZFS4OTq56W+lkYcmzZhhuJjSQwESUiVaJfEBhUa5ugKFLZOCeHL4Apnm+53UroJtmygjcQVahmq8IyFeGCQC6ZaxYgDrHzQKpIKA8AN7GKDTK/oX6SOgCEK0h/g7AYEGoJ5KfwBQYD2RSbxRX0jwkJhX6SlHQ2aUZ7HaqzqvgXspiBZylBxr+emJkuYcVAC455Sejl/5B8QAUJxQhXMXSpyhTFnE55iaTnLF5OQXnmFGxWhkEZOyE/nw5YxYjkTF46BgXs5z/rQrc59GUJnqS2Hq3E7RJBSa4SGdqScFS5YTnxmy5ZtrQXWmggiJmMFU8WrmsFKSecRhQzUHwBF+iHivGs6a8QNJFJkcgIVJptuXHJ7xVSf/nVpx8VG7YRbuchKS6MJaWm+5MqXAWO5rzs7kaFB+YTFbUEefEol580DYUAhXBZeK2yphbhlF5ahSHmwJtJY2kIJKTiyW1WrOlgCN5R+UlTcBK+d8nTZnMYEWyAnhRrE5FzgGEQkJABEeleKS/G9lIqToWtLUJC+XtgLuN4LbLyyW+X9lBRRdNlnjJz6a+nvpIJp+l8JbfmDlX5aFjqqIemYWqnP5BFhuEieFxRP4KJ8KHBkqJZObyCipdwiIWBumiSTlipqxejF7FVORGUhlZhesWxlKqTTnZR9OScU2JqBTf5vy9/qzm2OO4bXHLB9cXRnpFdBQBDZlWQdsEWpGtsQUdxhwQ+EUFISVQVnRNBW6kK5hIkCXiZiSQGka5LwS45F+RQXLKKZL2Cpk/BLCelaKlZok+nEowIQiXFQxSVbn6CghXjnCFyGRiULFWJQiGSFPBZtJoh/AeXC2ZgSiPTBK98UoXRliZW06B5/BewkWlxKFMmEyRAMKp8AqzLYQTploAmpeAq+SgGhB6chXBnobJaSXnJPYP/EixZea+W2FX5XSQ/l0Ln9gGB5RS6a98KiMrEsxEgZ2ld8eCfDqN2RWVLjzy/7kB5jc3eSCnV+VoSd6LKR7DUBlg8+ciFgAZ8L9kZZBEPqBPsG5BbG5ZL6X2BvpTsU35dFdpSkFouTKRDkDFakgOX1hQGQ/nHFyBeuEzBKtEJXyJ38ohkgKP+VuDzF4BZ1Hv8ClVgAE5JJTGXKV8capXQFv+bsXnl8Bdx7kydBqcWkZExWJ4UKaPruGFlcTN3yrkewXvT2IwqZ4K4SBfNjz20XBWJ54BtdkZlly/4CRWuFtQGd7t0aZpmBbZZePOU5Or4JhCOA7ulCV56/WW77kSPJF0DSxNXGhCm4EcQF75KwBM0UJC/EPiCSacVaslhKiXLCB6oDgY5xUQIoGcJFygUh5XwS6JCVxaYu7ARBekzeNoXsFhYlEIxCdmKECRA8IOKDy4pVWRUhCM3jFWIEhkKVUKA5VV7xUAGiKqDVAD5WrDsJfBAqDFVYchxWdF3ot0VuxvRYIlJE4jkAVlRjUecIQK3klAL9h1wN5X3yTMsaYg+COeZW9konnwhQ+xjp2KjFGZRBnpi0AJcoMAVlY/4FlriWaz2VsSG3GZITlbTQC6/ktnL4SC4jwr/VPlXFnzSx3tyELe6fnwKpFABEdKW50VY6CxVhkLVRDKiJCkKR5zMAKSXI6VfaCZV7INlWnYeUNYj5VQaUVWE1HWZZhMA5VRShVVUQDVWFyDwggpZ8TVUtQtVZuG1VbgWyIkXoAIRJzjrVuFCUDroniQC6sRo+QTVTV2kL7KH4pVY+XdVvBdtW0ptpfSn2ll+d0Ilh3UaAr6VcCnDXsOuPHOFQ8f1WaBkyD8rNp5RnpTsgO1FQO9XiuqZUgUPVQ/t9XjFvZB7X2muZcq7KW1xVDq2RxjMHVKeeqFNiVOGZEGn75nCcSjyge2KKWeykYXeqKEVNVgTmQPXhhXlQY3sQWS41oGaADG9xK0i1ayKrUCkwFxudB9QzASdiBe6eqIGz5KpphWl1/1QMZbuMfiVx8sXzkgAEQtQF77YSK3oyBAkiNIPVKkwVUCQ5eOkJCTz2o0vHaF103N3W7EvdZun91MFW9ZD1W4LPXbiq5L5BlKMgF4FjJ3mXeXc4QFboX+ZxpBnW12RuIpDT6k5fYD5Qd1tGghE6otPXEMxcgjWTe1pWDaG1IOcmEOlptanipE/9r9LfpMHjDaMUSsJrjuEC4igwb4lHO4w5B/NuJWu1klTsj1A9XF4CXFKrotHYF+6rTQfWDGbg2i4v/sLm1l+0UAEGmDqSaYnR3xYPG/FhvNcEM+Vts6422Ohm5aQ0eDbCWFiv0W7Ye2UVj4VKVBTs4Y8iSAb44skwhNC5YBPhhQ1eAPlWrHRCmWckXaZvXmiV6BgEUllIw9QKyQy6fkedhiee9AyoDKS2cTUe6V7glDfkGsTqAvQ0kY7i4gujV1WyNbJKilehNoHwhQ1rKlIAEVVjTyFgANjXY2EJsEME2VQICfcRDVSvq42R57jdpyOF0ZCcYx+CgAH4Y1foJoBMx35PFnn1hbPaBkJwUMio+gL0KNlj2SvhwEgegGDV4W4+yYQH2eMpft65+m9tIC9akNIY1YEbulMkAN8YbtXcVF+bA33eTpc6pKNrpcjZA+YGR6XYNUlHg0lBkBd/l6VilaGV0WaGYAVPeT2C94FNLDpGrmNwjit7tB6OZ0FUeWzYI49Y9dgCD7N33vR5L+DQcc14Nh/gH7H+wQKf5oNsPhf6YNJGflHpiISJWCZABDeHV1xRqaQ3y2DGT81egKtk8WsZRrv4l1lfCnx4yGnxVrzMNNPqw34i9BaFSM+E8dw1PBvDZrnMO2uaGlgtmQAI28FMEaI32GyzU4bFsRTitj6KHJFySeGr6IAnQYRLRQAqNY2QxBmKUdvBFgpGRdo3y4cTfEoyxp2UtT0tBwAum7N/jZY21wXStVC2N/lXk1aMvzYfjUx3SoGBONVGMF7ywkecK3okYrbG7UIZzRY2pNgTaMohNCrdfWtKr9pkC75PWB7rBNxKlE0LYMTYwrwpVnH566toreITitHaUtnzexTUt7ZNa6boTWeFkQ00WtoecALKttraQA8hareyDlNE9qc66+ebtCQ+avAJ4p6gZReIF+kSFSKEoVJXkxV+RW9m02WB/glEDFGPTZA09a0De7EgOQiTfmM0rLWM39++LpM0yWU0c20o5azeUHACFYZjkO52OV1EMey/lq4Dq1rTo65qkrSQAXNMfgc11RRzSv4AgE7ac1+NM7Zc1DBKjsO03Nz3nv4rt/vrypPNVzJu3DR/cAYD7wymKzHqlC0dfBcAVAPfAOOz8BvAqAagO/C7wX8Oe2DwM8OoAAg1EPNafEaBHQC++fYHpBntF7QIA0wlUCjCsgAgDtAJQaAJsYkAjIAwByaJAB9DnQDAOeabGzILFDbQsQNtAMAlUHJrnQAgJ/CGAF7cyAMAqMAICMgSHXJocaLGgdCkwaACQBdQV5ph0kdbHRsbkw5MFFCUdlUCKB7wX7QdAEwT0LB1Ud8UB9A3QjIHx3bQl0PtCcarHbsZMdjILUrbQogB7BCdEAIwBRQaMFFD4w8HTR0MgmxlFCcID0LtBdQpMN3pYdtAHJ2MglUCh1oAXUFFBkdn7dp0bQKQFFr7Qh0MdCnQDIJdDXQt0PdCPQL0G9AfQBMN9BydsWlp1QApnQIDnQsQAwBPQaAJFq7QCUIHrBdfUOdBOd20JVDPQF5iQC7GzICQDMgAgFFC0AVHa51udUAAjA/tf7QO4BegHbQCPa9APoBAAA=== -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=martin-georgiev/postgresql-for-doctrine&utm_content=383):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@coveralls
Copy link

coveralls commented May 22, 2025

Coverage Status

coverage: 93.695% (-0.3%) from 94.004%
when pulling 69fa3bb on math-functions
into 9fb0419 on main.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 21

🧹 Nitpick comments (4)
docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md (1)

120-130: Documentation correctly lists the new mathematical functions.

The changes effectively document all the newly added mathematical functions. This aligns well with the PR objective of adding mathematical functions to the library.

For consistency with the rest of the table, consider removing the trailing pipe characters from the table rows:

-| cbrt | CBRT | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cbrt` |
+| cbrt | CBRT | `MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Cbrt`

(Apply similar changes to the other new entries)

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

120-120: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


121-121: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


122-122: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


123-123: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


124-124: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


125-125: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


126-126: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


127-127: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


128-128: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


129-129: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


130-130: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (3)

18-25: Test coverage looks comprehensive, consider adding edge cases.

The test cases cover perfect cubes, non-perfect cubes, negative numbers, and column values, which is good. Consider adding a test for edge cases like the cube root of 0.

+    public function test_cbrt_with_zero(): void
+    {
+        $dql = 'SELECT CBRT(0.0) as result 
+                FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics n 
+                WHERE n.id = 1';
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(0.0, $result[0]['result'], 0.0001);
+    }

Also applies to: 27-34, 36-43, 45-52


38-38: Consider simplifying the double parentheses.

The expression ((-27.0)) contains double parentheses. While this works, a single set of parentheses around the negative number should be sufficient: (-27.0).

-        $dql = 'SELECT CBRT((-27.0)) as result 
+        $dql = 'SELECT CBRT(-27.0) as result 

45-52: Add a comment about the expected test data value.

For better test clarity, consider adding a comment explaining what value is expected in n.decimal1 for the entity with ID=1. This would make the test more self-documenting and easier to maintain.

     public function test_cbrt_with_column_value(): void
     {
+        // Assuming n.decimal1 = 10.5 for entity with ID=1
         $dql = 'SELECT CBRT(n.decimal1) as result 
                 FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics n 
                 WHERE n.id = 1';
         $result = $this->executeDqlQuery($dql);
         $this->assertEqualsWithDelta(2.1897595699439445, $result[0]['result'], 0.0001);
     }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9fb0419 and bf609f8.

📒 Files selected for processing (32)
  • README.md (1 hunks)
  • docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md (1 hunks)
  • docs/INTEGRATING-WITH-DOCTRINE.md (1 hunks)
  • docs/INTEGRATING-WITH-LARAVEL.md (1 hunks)
  • docs/INTEGRATING-WITH-SYMFONY.md (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayShuffle.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php (4 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#263
File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php:19-21
Timestamp: 2025-03-11T12:32:10.726Z
Learning: In the postgresql-for-doctrine repository, PostgreSQL range functions have distinct implementations for different data types. The `Numrange` function works with numeric/decimal values and is tested using the `ContainsDecimals` fixture with properties typed as `float`. In contrast, the `Int4range` function works with 32-bit integers and is tested using the `ContainsIntegers` fixture with properties typed as `int`. While the PHP implementations share a similar structure (extending `BaseFunction`), they are semantically different as they handle different PostgreSQL data types.
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
🧬 Code Graph Analysis (12)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (11)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)
  • getFunctionName (19-22)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (11)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)
  • getFunctionName (19-22)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php (1)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (236-250)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (3)
  • getFunctionName (17-20)
  • getMaxArgumentCount (22-25)
  • getMinArgumentCount (27-30)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (11)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)
  • getFunctionName (19-22)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)
  • Power (15-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (2)
  • PowerTest (9-62)
  • getStringFunctions (11-16)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (11)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)
  • getFunctionName (19-22)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (3)
  • getFunctionName (17-20)
  • getMaxArgumentCount (22-25)
  • getMinArgumentCount (27-30)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • Pi (15-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php (1)
  • NumericTestCase (9-49)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (236-250)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (11)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseArithmeticFunction.php (1)
  • BaseArithmeticFunction (12-28)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1)
  • getFunctionName (17-20)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)
  • getFunctionName (19-22)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (14)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • Log (15-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php (1)
  • NumericTestCase (9-49)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php (1)
  • getStringFunctions (11-14)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (1)
  • getStringFunctions (11-16)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (236-250)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1)
  • Sign (15-21)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (2)
  • SignTest (9-35)
  • getStringFunctions (11-16)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (3)
  • getStringFunctions (12-17)
  • getExpectedSqlStatements (19-26)
  • getDqlStatements (28-35)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (3)
  • getStringFunctions (12-17)
  • getExpectedSqlStatements (19-26)
  • getDqlStatements (28-35)
🪛 GitHub Actions: Integrations
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php

[error] 63-63: Doctrine ORM QueryException: Entity 'Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsArrays' has no field or association named 'decimal1' causing test_round_with_column_value to fail.


[error] 31-31: Test failure: Expected -3.0 but got string '-3' in test_round_with_negative_number.


[error] 22-22: Test failure: Expected 3.0 but got string '3' in test_round_with_positive_number.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php

[error] 24-24: Test failure: Expected '0.0' but got '0' string mismatch in test_sign_with_zero.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_width_bucket to fail with TableNotFoundException.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php

[error] 50-50: Doctrine ORM QueryException: Syntax error in query near 'POWER(2, -2)' due to unexpected '-' causing test_power_with_negative_exponent to fail.


[error] 41-41: Doctrine ORM QueryException: Syntax error in query near 'POWER(-2, 3)' due to unexpected '-' causing test_power_with_negative_base to fail.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_exp to fail with TableNotFoundException.


[error] 29-29: Test failure: Expected '1' but got '36315.502674246638' in test_exp_with_entity_property.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_degrees to fail with TableNotFoundException.


[error] 29-29: Test failure: Expected '1' but got '601.6056848873644' in test_degrees_with_entity_property.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_radians to fail with TableNotFoundException.


[error] 29-29: Test failure: Value '0.1832595714594046' identical to expected in test_radians_with_entity_property but test failed.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_ln to fail with TableNotFoundException.


[error] 29-29: Test failure: Expected '1' but got '2.3513752571634777' in test_ln_with_entity_property.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_pi to fail with TableNotFoundException.


[error] 29-29: Test failure: Expected '5.2907810314839' but got '13.641592653589793' in test_pi_plus_entity_property.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_log to fail with TableNotFoundException.


[error] 29-29: Test failure: Expected '1' but got '1.0211892990699381' in test_log_with_entity_property.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php

[error] 21-21: Doctrine DBAL Exception: Table 'containsjsons' does not exist causing test_random to fail with TableNotFoundException.


[error] 30-30: Test failure: Value '10.9658236190421' not equal or greater than expected 11.0 in test_random_plus_entity_property.

🪛 markdownlint-cli2 (0.17.2)
docs/AVAILABLE-FUNCTIONS-AND-OPERATORS.md

120-120: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


121-121: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


122-122: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


123-123: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


124-124: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


125-125: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


126-126: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


127-127: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


128-128: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


129-129: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)


130-130: Table pipe style
Expected: leading_only; Actual: leading_and_trailing; Unexpected trailing pipe

(MD055, table-pipe-style)

🔇 Additional comments (21)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ArrayShuffle.php (1)

10-10: URL reference updated to specific PostgreSQL version

The documentation link has been updated from a generic version to specifically point to PostgreSQL version 17. This is a good practice for ensuring accurate and consistent documentation references.

README.md (1)

80-83: Great addition of mathematical and range functions documentation

The documentation has been clearly organized with the new mathematical/arithmetic functions and range functions sections. This provides users with a comprehensive overview of the available functionality.

docs/INTEGRATING-WITH-LARAVEL.md (1)

206-220: Comprehensive addition of mathematical functions

The integration documentation has been updated with a complete set of PostgreSQL mathematical functions. This is well-organized and consistent with the changes in the README file.

This implementation aligns well with the learning from previous PRs about how PostgreSQL functions are distinctly implemented for different data types in this repository.

docs/INTEGRATING-WITH-SYMFONY.md (1)

200-214: Arithmetic Functions List Updated Correctly

The new mathematical functions (CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, WIDTH_BUCKET) have been added in alphabetical order, and ABS was removed as intended. This matches the updates in other integration guides and maintains consistency across documentation.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1)

1-21: Consistent Exp Function Implementation

The Exp class correctly extends BaseArithmeticFunction, declares strict_types, and returns 'EXP' in getFunctionName(). The docblock is well-formed with proper references and author attribution, matching existing function implementations.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Ln.php (1)

1-21: Consistent Ln Function Implementation

The Ln class follows the same pattern as other arithmetic functions: it extends BaseArithmeticFunction, enforces strict_types, and returns 'LN' in getFunctionName(). Docblock annotations and links are correct.

docs/INTEGRATING-WITH-DOCTRINE.md (1)

151-165: Arithmetic Functions Registration Updated

New arithmetic functions (CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, WIDTH_BUCKET) have been registered in alphabetical order, replacing ABS. This aligns with the Symfony and Laravel guides and ensures consistency.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Sign.php (1)

1-21: Sign Function Follows Established Pattern

The Sign class is correctly implemented: it extends BaseArithmeticFunction, has declare(strict_types=1), and returns 'SIGN'. The docblock is consistent with the other arithmetic function classes.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)

1-21: Well-structured Degrees AST function.
The class correctly extends BaseArithmeticFunction, inherits the single-argument constraint, and returns the proper SQL name DEGREES. Docblock, strict typing, and namespace align with existing implementations.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)

1-21: Correct Radians AST function implementation.
This class mirrors the Degrees pattern, enforces exactly one argument, and exposes the RADIANS SQL function. Documentation, strict types, and method override are consistent with the codebase conventions.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)

1-31: Accurate zero-argument PI() function.
Overrides getMinArgumentCount() and getMaxArgumentCount() to 0 as expected for PI(). The function name, docblock, and strict typing follow the established pattern for no-argument functions.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Power.php (1)

1-32: Proper two-argument POWER() function.
Overrides both min and max argument counts to 2, correctly mapping to PostgreSQL’s POWER() signature. Implementation and documentation are aligned with the existing Log and other multi-arg functions.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Cbrt.php (1)

1-21: Standard CBRT() function extension.
Follows the same structure as other single-argument math functions. Inherits the argument count from BaseArithmeticFunction and properly returns CBRT as the SQL function name.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Random.php (1)

1-31: Implementation looks correct!

The class correctly implements the PostgreSQL RANDOM() function by extending BaseArithmeticFunction and overriding the necessary methods. The function takes no arguments, which is properly reflected in both min and max argument count returning 0.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)

1-33: Correct implementation with proper argument validation.

This implementation of PostgreSQL's WIDTH_BUCKET() function correctly enforces the requirement of exactly 4 arguments by setting both min and max argument counts to 4. The PHPDoc comment includes good documentation with the function description and an example of usage in DQL.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)

1-31: Correct implementation of PostgreSQL's LOG function.

The implementation properly extends BaseArithmeticFunction and enforces that LOG requires exactly 2 arguments (base and value), which aligns with PostgreSQL's implementation.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1)

1-36: LGTM!

The unit test for the Sign function is well-structured and follows the established pattern for other mathematical function tests in the project. It properly extends TestCase, registers the Sign function, and provides appropriate test SQL and DQL statements.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1)

1-36: LGTM! Unit tests for Power function are well-structured.

The PowerTest class is well-structured with appropriate test cases covering different scenarios of the POWER function usage. The expected SQL statements match the corresponding DQL statements correctly.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (1)

1-36: LGTM! Unit tests for CBRT function are well-structured.

The CbrtTest class is well-structured with appropriate test cases for the CBRT function. The expected SQL statements correctly match the corresponding DQL statements.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1)

54-61: Check for potential overflow with large power results

The expected result of approximately 8.6 × 10^20 is extremely large and may cause precision/overflow issues in some PostgreSQL configurations.

While the test looks correct, verify that the actual database supports such large values consistently. Consider adding a more moderate test case as well.

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (1)

1-53: Overall good test implementation for the PostgreSQL CBRT function.

The test class correctly covers various scenarios for the cube root function implementation. The structure follows good practices with the function registration and appropriate assertions with delta values for floating-point comparisons.

@martin-georgiev martin-georgiev changed the title feat: add mathematical functions feat: add support for arithmetic functions CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, and WIDTH_BUCKET. May 22, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (1)

9-31: Consider adding tests for edge cases.

The current tests cover basic functionality well, but consider adding tests for edge cases such as NULL values, negative values, or very large values to ensure the function handles all potential inputs correctly.

 class DegreesTest extends NumericTestCase
 {
     protected function getStringFunctions(): array
     {
         return [
             'DEGREES' => Degrees::class,
         ];
     }
 
     public function test_degrees(): void
     {
         $dql = 'SELECT DEGREES(3.141592653589793) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1';
         $result = $this->executeDqlQuery($dql);
         $this->assertEqualsWithDelta(180.0, $result[0]['result'], 0.0001);
     }
 
     public function test_degrees_with_entity_property(): void
     {
         $dql = 'SELECT DEGREES(n.decimal1) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics n WHERE n.id = 1';
         $result = $this->executeDqlQuery($dql);
         $this->assertEqualsWithDelta(601.6056848873644, $result[0]['result'], 0.000001);
     }
+
+    public function test_degrees_with_null_value(): void
+    {
+        // Assuming your database structure supports NULL values
+        $sql = sprintf('UPDATE %s.containsnumerics SET decimal2 = NULL WHERE id = 1', self::DATABASE_SCHEMA);
+        $this->connection->executeStatement($sql);
+
+        $dql = 'SELECT DEGREES(n.decimal2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics n WHERE n.id = 1';
+        $result = $this->executeDqlQuery($dql);
+        $this->assertNull($result[0]['result']);
+    }
+
+    public function test_degrees_with_negative_value(): void
+    {
+        $dql = 'SELECT DEGREES(-3.141592653589793) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1';
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(-180.0, $result[0]['result'], 0.0001);
+    }
 }
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (2)

22-23: Consider consistent delta precision

The delta value (0.0001) used here is different from the more precise delta (0.000001) used in the second test. Consider using consistent precision across similar tests unless there's a specific reason for the difference.


18-23: Consider adding tests for edge cases

The current test covers the basic case of EXP(1). Consider adding tests for important edge cases:

    public function test_exp(): void
    {
        $dql = 'SELECT EXP(1) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1';
        $result = $this->executeDqlQuery($dql);
        $this->assertEqualsWithDelta(2.718281828459, $result[0]['result'], 0.0001);
    }

+    public function test_exp_zero(): void
+    {
+        $dql = 'SELECT EXP(0) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1';
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(1.0, $result[0]['result'], 0.0001);
+    }
+
+    public function test_exp_negative(): void
+    {
+        $dql = 'SELECT EXP(-1) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1';
+        $result = $this->executeDqlQuery($dql);
+        $this->assertEqualsWithDelta(0.367879441171, $result[0]['result'], 0.0001);
+    }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf609f8 and 8cfbb3e.

📒 Files selected for processing (11)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php (2 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1 hunks)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RoundTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PowerTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php
  • tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#263
File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php:19-21
Timestamp: 2025-03-11T12:32:10.726Z
Learning: In the postgresql-for-doctrine repository, PostgreSQL range functions have distinct implementations for different data types. The `Numrange` function works with numeric/decimal values and is tested using the `ContainsDecimals` fixture with properties typed as `float`. In contrast, the `Int4range` function works with 32-bit integers and is tested using the `ContainsIntegers` fixture with properties typed as `int`. While the PHP implementations share a similar structure (extending `BaseFunction`), they are semantically different as they handle different PostgreSQL data types.
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
🧬 Code Graph Analysis (1)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)
  • Degrees (15-21)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php (1)
  • NumericTestCase (9-49)
tests/Integration/MartinGeorgiev/TestCase.php (1)
  • executeDqlQuery (236-250)
⏰ Context from checks skipped due to timeout of 90000ms (20)
  • GitHub Check: sloth
  • GitHub Check: PostgreSQL 16 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PHP 8.1
  • GitHub Check: PHP 8.4 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 3.0 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.18 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.18 + Doctrine Lexer latest
  • GitHub Check: PHP 8.4 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM 2.14 + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM latest + Doctrine Lexer 3.0
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.18 + Doctrine Lexer 3.0
🔇 Additional comments (4)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (3)

9-16: Well-structured test class with proper function registration.

The test class is well-organized and properly extends the NumericTestCase base class. The getStringFunctions() method correctly registers the Degrees function for use in DQL queries.


18-23: Good test case for constant value conversion.

This test correctly verifies that the PostgreSQL DEGREES function converts radians to degrees. Using π (3.141592653589793) as input to verify it outputs 180 degrees is a perfect test case. The assertEqualsWithDelta with a delta of 0.0001 is appropriate for floating-point comparisons.


25-30: Accurate test for entity property conversion.

This test correctly verifies the DEGREES function using the decimal1 entity property. The expected value of approximately 601.6 degrees is accurate for converting 10.5 radians to degrees (10.5 * 180/π).

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (1)

1-31: Implementation looks good overall

The test class properly validates the PostgreSQL EXP function implementation with both constant values and entity properties. The test correctly verifies that EXP(1) returns Euler's number and that EXP(n.decimal1) returns the expected result with appropriate precision.

I see that you've addressed the previous issues identified in the CI pipeline by:

  1. Using the correct fixture (ContainsNumerics instead of ContainsJsons)
  2. Using the correct expected value with assertEqualsWithDelta in the second test

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php (1)

1-34: LGTM! Well-structured unit test following project conventions.

The test properly implements the standard pattern for testing DQL function translation in this project. The use of ContainsDecimals fixture is appropriate since RANDOM() returns decimal values between 0 and 1, and the mapping between DQL statements and expected SQL is correct.

Consider enhancing test coverage with additional scenarios:

 protected function getDqlStatements(): array
 {
     return [
         \sprintf('SELECT RANDOM() FROM %s e', ContainsDecimals::class),
         \sprintf('SELECT RANDOM() + e.decimal1 FROM %s e', ContainsDecimals::class),
+        \sprintf('SELECT RANDOM() * 100 FROM %s e', ContainsDecimals::class),
+        \sprintf('SELECT FLOOR(RANDOM() * 10) FROM %s e', ContainsDecimals::class),
     ];
 }

And corresponding expected SQL statements:

 protected function getExpectedSqlStatements(): array
 {
     return [
         'SELECT RANDOM() AS sclr_0 FROM ContainsDecimals c0_',
         'SELECT RANDOM() + c0_.decimal1 AS sclr_0 FROM ContainsDecimals c0_',
+        'SELECT RANDOM() * 100 AS sclr_0 FROM ContainsDecimals c0_',
+        'SELECT FLOOR(RANDOM() * 10) AS sclr_0 FROM ContainsDecimals c0_',
     ];
 }

This would test more realistic usage patterns where RANDOM() is often scaled or used in mathematical expressions.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php (1)

19-33: Consider adding more comprehensive test cases.

While the basic functionality is well covered, consider adding test cases for edge conditions to improve robustness:

  • Zero value: LN(0) (should handle domain error)
  • Negative values: LN(-1) (should handle domain error)
  • Very small positive values: LN(0.001)
  • NULL handling: LN(NULL)

Example additional test cases:

 protected function getExpectedSqlStatements(): array
 {
     return [
         'SELECT LN(12) AS sclr_0 FROM ContainsDecimals c0_',
         'SELECT LN(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
+        'SELECT LN(0.001) AS sclr_0 FROM ContainsDecimals c0_',
+        'SELECT LN(c0_.decimal2) AS sclr_0 FROM ContainsDecimals c0_',
     ];
 }

 protected function getDqlStatements(): array
 {
     return [
         \sprintf('SELECT LN(12) FROM %s e', ContainsDecimals::class),
         \sprintf('SELECT LN(e.decimal1) FROM %s e', ContainsDecimals::class),
+        \sprintf('SELECT LN(0.001) FROM %s e', ContainsDecimals::class),
+        \sprintf('SELECT LN(e.decimal2) FROM %s e', ContainsDecimals::class),
     ];
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8cfbb3e and db751b8.

📒 Files selected for processing (10)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RandomTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/SignTest.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/CbrtTest.php
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#263
File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php:19-21
Timestamp: 2025-03-11T12:32:10.726Z
Learning: In the postgresql-for-doctrine repository, PostgreSQL range functions have distinct implementations for different data types. The `Numrange` function works with numeric/decimal values and is tested using the `ContainsDecimals` fixture with properties typed as `float`. In contrast, the `Int4range` function works with 32-bit integers and is tested using the `ContainsIntegers` fixture with properties typed as `int`. While the PHP implementations share a similar structure (extending `BaseFunction`), they are semantically different as they handle different PostgreSQL data types.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (2)
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
🧬 Code Graph Analysis (6)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucket.php (1)
  • WidthBucket (17-33)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (1)
  • WidthBucketTest (9-31)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Degrees.php (1)
  • Degrees (15-21)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (2)
  • DegreesTest (9-31)
  • getStringFunctions (11-16)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Radians.php (1)
  • Radians (15-21)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (2)
  • RadiansTest (9-31)
  • getStringFunctions (11-16)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php (1)
  • Log (15-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (2)
  • LogTest (9-31)
  • getStringFunctions (11-16)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exp.php (1)
  • Exp (15-21)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (2)
  • ExpTest (9-31)
  • getStringFunctions (11-16)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Pi.php (1)
  • Pi (15-31)
tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (2)
  • PiTest (9-31)
  • getStringFunctions (11-16)
🔇 Additional comments (28)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ExpTest.php (4)

1-11: LGTM! Proper file structure and class setup.

The file header, namespace declaration, imports, and class definition follow the expected conventions. The class correctly extends the custom TestCase from the same namespace.


12-17: LGTM! Correct function mapping.

The getStringFunctions() method properly maps the DQL function name 'EXP' to the Exp class implementation, following the expected pattern for registering custom functions.


19-25: LGTM! Expected SQL statements look correct.

The expected SQL statements properly reflect how Doctrine would transform the DQL:

  • Adds scalar aliases (AS sclr_0)
  • Transforms table aliases (ec0_)
  • Maintains the EXP function calls correctly

Both literal value and entity property scenarios are covered.


27-33: LGTM! DQL statements provide comprehensive test coverage.

The DQL statements test both:

  1. EXP function with a literal numeric value (11)
  2. EXP function with an entity property (e.decimal1)

Using ContainsDecimals entity is appropriate for testing mathematical functions that work with decimal values, which aligns with the function's purpose.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PiTest.php (4)

1-8: LGTM! Proper file structure and imports.

The PHP file header, namespace declaration, and imports are correctly structured. The imports are appropriate - ContainsDecimals entity for testing and the Pi function class being tested.


10-17: LGTM! Correct function registration.

The getStringFunctions() method properly maps the 'PI' string to the Pi class, which is the standard pattern for registering custom DQL functions in Doctrine.


19-25: LGTM! Expected SQL statements are accurate.

The expected SQL statements correctly represent how Doctrine should translate the DQL queries:

  • PI() becomes PI() AS sclr_0 with proper alias generation
  • PI() + e.decimal1 becomes PI() + c0_.decimal1 AS sclr_0 with entity alias transformation from e to c0_

27-33:

✅ Verification successful

Verify entity consistency between unit and integration tests.

The DQL statements are well-formed and test both standalone PI() usage and arithmetic operations with entity properties. However, there's an inconsistency in entity usage:

  • Unit test uses ContainsDecimals entity
  • Integration test uses ContainsNumerics entity

While this may be intentional (different fixtures for different test purposes), please verify that both entities have the required decimal1 property and that this difference is intended.


🏁 Script executed:

#!/bin/bash
# Description: Verify that both ContainsDecimals and ContainsNumerics entities have the decimal1 property

# Search for decimal1 property in ContainsDecimals entity
echo "=== ContainsDecimals entity ==="
fd -t f -e php | xargs grep -l "ContainsDecimals" | head -5 | xargs cat | grep -A5 -B5 "decimal1"

echo -e "\n=== ContainsNumerics entity ==="
# Search for decimal1 property in ContainsNumerics entity  
fd -t f -e php | xargs grep -l "ContainsNumerics" | head -5 | xargs cat | grep -A5 -B5 "decimal1"

Length of output: 4050


Entity consistency confirmed: both entities declare decimal1
Both ContainsDecimals (unit tests) and ContainsNumerics (integration tests) define the required decimal1 property. The use of different fixtures for unit vs. integration testing is intentional—no changes required.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php (4)

12-17: LGTM! Function registration follows established pattern.

The string function registration correctly maps 'LN' to the Ln class, following the standard pattern for DQL function registration in this codebase.


19-25: LGTM! SQL statements are correctly formatted.

The expected SQL statements properly test both literal values and entity fields, using the correct PostgreSQL LN function syntax.


27-33: LGTM! DQL statements match expected SQL output.

The DQL statements correctly use the ContainsDecimals fixture (appropriate for decimal operations based on the retrieved learnings) and will properly translate to the expected SQL.


10-10: ⚠️ Potential issue

Add missing TestCase import.

The class extends TestCase but there's no import statement for it, which will cause a fatal error.

Add the missing import at the top of the file:

 use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDecimals;
 use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ln;
+use PHPUnit\Framework\TestCase;
⛔ Skipped due to learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php (5)

12-17: LGTM! Correct function registration.

The getStringFunctions method correctly maps the DQL function name to its implementation class, following the established pattern.


19-25: LGTM! Expected SQL statements are correct.

The expected SQL statements properly represent the PostgreSQL WIDTH_BUCKET function with the correct number of parameters (4) and proper field/literal transformations.


27-33: LGTM! DQL statements cover key usage patterns.

The DQL statements appropriately test both entity property usage (e.decimal1) and literal value usage (15), providing good coverage for the WIDTH_BUCKET function transformation.


7-7:

❓ Verification inconclusive

Verify fixture consistency between unit and integration tests.

The unit test uses ContainsDecimals fixture while the integration test in tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php uses ContainsNumerics fixture. Please ensure this is intentional and both fixtures provide appropriate test data for the WIDTH_BUCKET function.


🏁 Script executed:

#!/bin/bash
# Description: Verify the properties and structure of both test fixtures to ensure consistency.

# Check ContainsDecimals fixture properties
echo "=== ContainsDecimals fixture properties ==="
ast-grep --pattern 'class ContainsDecimals {
  $$$
}'

echo -e "\n=== ContainsNumerics fixture properties ==="  
ast-grep --pattern 'class ContainsNumerics {
  $$$
}'

# Also check if there are other WIDTH_BUCKET tests using different fixtures
echo -e "\n=== Other WIDTH_BUCKET test usages ==="
rg -A 3 -B 1 "WIDTH_BUCKET.*ContainsDecimals\|WIDTH_BUCKET.*ContainsNumerics"

Length of output: 484


Here’s a deeper inspection to locate and peek into both fixtures, and to see exactly how they’re used in your WIDTH_BUCKET tests:


🏁 Script executed:

#!/bin/bash
# Locate fixture classes and inspect definitions

echo "=== Locate ContainsDecimals class ==="
rg -n "class ContainsDecimals" || echo "ContainsDecimals class not found"

echo -e "\n=== Locate ContainsNumerics class ==="
rg -n "class ContainsNumerics" || echo "ContainsNumerics class not found"

# Capture file paths
DEC_FILE=$(rg -l "class ContainsDecimals")
NUM_FILE=$(rg -l "class ContainsNumerics")

# Print the first chunk of each fixture to review properties
if [ -n "$DEC_FILE" ]; then
  echo -e "\n=== Contents of $DEC_FILE (first 50 lines) ==="
  sed -n '1,50p' "$DEC_FILE"
fi

if [ -n "$NUM_FILE" ]; then
  echo -e "\n=== Contents of $NUM_FILE (first 50 lines) ==="
  sed -n '1,50p' "$NUM_FILE"
fi

# Show how each fixture is referenced in WIDTH_BUCKET tests
echo -e "\n=== WIDTH_BUCKET test references ==="
rg -n "WIDTH_BUCKET" -C 2 tests/Unit tests/Integration

Length of output: 6620


Ensure fixture alignment in WIDTH_BUCKET tests

Unit tests import ContainsDecimals (decimal1, decimal2, decimal3 all as DECIMAL) while integration tests operate on ContainsNumerics (integer, bigint, and decimal columns with specific precision/scale). Please confirm this divergence is intentional and that both fixtures exercise the WIDTH_BUCKET logic correctly:

• fixtures/MartinGeorgiev/Doctrine/Entity/ContainsDecimals.php
• fixtures/MartinGeorgiev/Doctrine/Entity/ContainsNumerics.php
• tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php
• tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/WidthBucketTest.php

Verify that:

  1. Unit tests only need a pure decimal-type entity for AST serialization assertions.
  2. Integration tests cover actual numeric‐type behavior (integer/bigint/decimal precision).
  3. Any precision/scale differences won’t invalidate the expected bucket results.

1-9: ⚠️ Potential issue

Add missing import for TestCase.

The class extends TestCase but the import statement is missing.

Add the missing import:

+use Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase;
 use Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDecimals;
 use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\WidthBucket;
⛔ Skipped due to learnings
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), not PHPUnit's TestCase, and therefore don't need an explicit import statement.
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#318
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/XmlAggTest.php:1-9
Timestamp: 2025-03-29T03:31:17.114Z
Learning: Tests in the `Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase, and therefore don't need an explicit import.
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DegreesTest.php (5)

1-34: LGTM! Well-structured unit test following established patterns.

The test implementation correctly follows the project's testing conventions and provides comprehensive coverage for the DEGREES function with both literal values and entity properties.


12-17: Function mapping implementation is correct.

The getStringFunctions() method properly maps the 'DEGREES' string to the Degrees::class, following the established pattern for DQL function registration.


19-25: Expected SQL statements are well-defined.

The SQL expectations correctly represent the PostgreSQL DEGREES function usage with both literal values and entity properties. The table alias and field references are consistent.


27-33: DQL statements properly match expected SQL.

The DQL statements correctly use sprintf for dynamic entity class names and maintain consistency with the expected SQL patterns. Good test coverage with both literal and property-based usage.


7-7:

✅ Verification successful

Verify fixture consistency across test types.

The unit test uses ContainsDecimals fixture, while the integration test (from relevant code snippets) uses ContainsNumerics. Please verify that this fixture choice is intentional and appropriate for the DEGREES function testing strategy.


🏁 Script executed:

#!/bin/bash
# Description: Check fixture usage consistency across DEGREES function tests
# Expected: Verify if different fixtures are intentionally used for unit vs integration tests

echo "=== Checking fixture usage in DEGREES tests ==="
rg -A 3 -B 3 "ContainsDecimals|ContainsNumerics" tests/**/DegreesTest.php

echo "=== Checking other mathematical function tests for fixture patterns ==="
rg -A 2 "class.*Test extends" tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ | head -20

Length of output: 2081


🏁 Script executed:

#!/bin/bash
# Search for all occurrences of the two fixtures in the test suite
echo "=== Searching for ContainsNumerics across tests ==="
rg -Hn "ContainsNumerics" -g "tests/**/*.php" || echo "No occurrences of ContainsNumerics found."

echo
echo "=== Searching for ContainsDecimals across tests ==="
rg -Hn "ContainsDecimals" -g "tests/**/*.php" || echo "No occurrences of ContainsDecimals found."

Length of output: 20869


Fixture usage is intentional and consistent

Unit tests under tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/… all use the ContainsDecimals fixture, while integration tests under tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/… use ContainsNumerics. This pattern applies uniformly (including DegreesTest.php), so no changes are necessary.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php (2)

10-17: LGTM! Test structure follows established patterns.

The test class structure, namespace usage, and method implementations follow the established conventions in this codebase. The extension of the custom TestCase class and the three protected method pattern are consistent with other function tests.


7-7:

✅ Verification successful

Verify entity choice consistency.

The unit test uses ContainsDecimals entity while the integration test uses ContainsNumerics. Please verify this is intentional and consistent with the testing patterns for decimal vs numeric data types in PostgreSQL.


🏁 Script executed:

#!/bin/bash
# Description: Check if ContainsDecimals entity is used consistently in other mathematical function tests
# Expected: Find similar usage patterns in other math function unit tests

echo "Checking ContainsDecimals usage in other unit tests:"
fd "Test\.php$" tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ --exec grep -l "ContainsDecimals" {} \;

echo -e "\nChecking ContainsNumerics usage in integration tests:"
fd "Test\.php$" tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ --exec grep -l "ContainsNumerics" {} \;

echo -e "\nChecking entity properties in ContainsDecimals:"
ast-grep --pattern 'class ContainsDecimals {
  $$$
}'

Length of output: 3028


Math function tests use consistent entity classes

All unit tests under tests/Unit/.../Functions use ContainsDecimals, and all integration tests under tests/Integration/.../Functions use ContainsNumerics, matching the decimal vs. numeric mapping you’ve defined. No changes are required here.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php (4)

12-17: LGTM! Function mapping is correct.

The function mapping correctly associates the 'RADIANS' DQL function with the Radians class implementation.


27-33: LGTM! DQL statements are well-structured.

The DQL statements correctly test both literal values and entity properties, and the use of sprintf with the class constant is a good practice for maintainability.


19-25:

✅ Verification successful

Verify expected SQL statement accuracy.

The expected SQL statements look correct for PostgreSQL RADIANS function, but please ensure they match the actual output from Doctrine's SQL generation.

Consider running a test to verify these SQL statements match actual Doctrine output:


🏁 Script executed:

#!/bin/bash
# Description: Check if similar arithmetic functions have the same SQL generation pattern

# Look for similar arithmetic function tests to compare SQL patterns
rg -A 5 "getExpectedSqlStatements" tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ | grep -E "(DEGREES|EXP|LOG|POWER)" -A 3

Length of output: 2485


SQL generation for RADIANS is accurate

The expected SQL statements in RadiansTest match the pattern used by other arithmetic‐function tests (DEGREES, EXP, LOG, POWER) and correctly reflect Doctrine’s output. No changes required.


7-7:

❌ Incorrect review comment

Verify entity consistency across test types.

The unit test uses ContainsDecimals entity while the integration test uses ContainsNumerics. Based on the retrieved learnings, different entities are used for different data types, but this inconsistency should be verified.

Please verify that using different entities between unit and integration tests is intentional:

Also applies to: 22-24, 30-31


🏁 Script executed:

#!/bin/bash
# Description: Check entity usage patterns across RADIANS tests and similar function tests

# Search for other unit tests to see which entities they use
echo "=== Unit test entity usage patterns ==="
rg -A 3 -B 1 "ContainsDecimals\|ContainsNumerics\|ContainsIntegers" tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/

echo "=== Integration test entity usage patterns ==="
rg -A 3 -B 1 "ContainsDecimals\|ContainsNumerics\|ContainsIntegers" tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/

echo "=== Checking entity fixture definitions ==="
fd -t f "ContainsDecimals\|ContainsNumerics" --exec cat {}

Length of output: 618


#!/bin/bash

Search for entity references in unit tests

echo "=== Unit test entity usage patterns ==="
rg -n "ContainsDecimals|ContainsNumerics|ContainsIntegers" tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/

Search for entity references in integration tests

echo "=== Integration test entity usage patterns ==="
rg -n "ContainsDecimals|ContainsNumerics|ContainsIntegers" tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/

Locate the entity definitions

echo "=== Entity class definitions ==="
rg -n "class ContainsDecimals" -tphp
rg -n "class ContainsNumerics" -tphp


🏁 Script executed:

#!/usr/bin/env bash
set -e

echo "=== Unit Tests: Entity Imports ==="
rg -n "use Fixtures\\\\MartinGeorgiev\\\\Doctrine\\\\Entity\\\\Contains" -n tests/Unit

echo "=== Integration Tests: Entity Imports ==="
rg -n "use Fixtures\\\\MartinGeorgiev\\\\Doctrine\\\\Entity\\\\Contains" -n tests/Integration

echo "=== Integration Tests: Radians References ==="
rg -n "Radians" -n tests/Integration

echo "=== Locate Entity Class Files ==="
fd -e php "ContainsDecimals.php" "ContainsNumerics.php" || true

echo "=== Show Entity Class Definitions ==="
rg -n "class ContainsDecimals" -n .
rg -n "class ContainsNumerics" -n .

Length of output: 18860


Ignore entity consistency suggestion.
There is no integration test for the Radians AST function under tests/Integration/.../Functions/, so there’s no mismatch between unit- and integration-test fixtures. Disregard the previous request to verify different entities.

Likely an incorrect or invalid review comment.

Comment on lines +31 to +33
\sprintf('SELECT LOG(8) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(e.decimal1) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(10, e.decimal2) FROM %s e', ContainsDecimals::class),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix argument count mismatch in DQL statements.

The first two DQL statements use LOG with only 1 argument, which is inconsistent with the Log class requirement of exactly 2 arguments.

Apply this diff to fix the argument count:

-            \sprintf('SELECT LOG(8) FROM %s e', ContainsDecimals::class),
-            \sprintf('SELECT LOG(e.decimal1) FROM %s e', ContainsDecimals::class),
+            \sprintf('SELECT LOG(10, 8) FROM %s e', ContainsDecimals::class),
+            \sprintf('SELECT LOG(10, e.decimal1) FROM %s e', ContainsDecimals::class),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
\sprintf('SELECT LOG(8) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(e.decimal1) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(10, e.decimal2) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(10, 8) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(10, e.decimal1) FROM %s e', ContainsDecimals::class),
\sprintf('SELECT LOG(10, e.decimal2) FROM %s e', ContainsDecimals::class),
🤖 Prompt for AI Agents
In tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php around
lines 31 to 33, the DQL statements call the LOG function with only one argument,
but the Log class requires exactly two arguments. Update the first two LOG calls
to include two arguments by adding a second argument, such as a base value, to
match the expected function signature.

Comment on lines +22 to +24
'SELECT LOG(8) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(10, c0_.decimal2) AS sclr_0 FROM ContainsDecimals c0_',
Copy link

@coderabbitai coderabbitai bot May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix argument count mismatch in expected SQL statements.

The first two expected SQL statements use LOG with only 1 argument, but according to the Log class implementation, the function requires exactly 2 arguments (both getMinArgumentCount() and getMaxArgumentCount() return 2).

Apply this diff to fix the argument count:

-            'SELECT LOG(8) AS sclr_0 FROM ContainsDecimals c0_',
-            'SELECT LOG(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
+            'SELECT LOG(10, 8) AS sclr_0 FROM ContainsDecimals c0_',
+            'SELECT LOG(10, c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'SELECT LOG(8) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(10, c0_.decimal2) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(10, 8) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(10, c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
'SELECT LOG(10, c0_.decimal2) AS sclr_0 FROM ContainsDecimals c0_',
🤖 Prompt for AI Agents
In tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php around
lines 22 to 24, the expected SQL statements use the LOG function with only one
argument, but the Log class requires exactly two arguments. Update the first two
SQL statements to include two arguments in the LOG function call to match the
required argument count, ensuring the test expectations align with the function
implementation.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think again

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the implementation of the Log class
cat src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php

Length of output: 665


@martin-georgiev You're absolutely right to question my suggestion. After checking the actual implementation of the Log class, I see that it supports both single-argument and two-argument variants:

protected function getMinArgumentCount(): int
{
    return 1;
}

protected function getMaxArgumentCount(): int
{
    return 2;
}

The PostgreSQL LOG function allows both forms:

  • LOG(x) - logarithm base 10 (single argument)
  • LOG(b, x) - logarithm with specified base (two arguments)

The test cases correctly test both variants. My previous suggestion was incorrect, and the existing test is properly structured.


🧬 Code Graph Analysis Results

Relevant snippets for tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php


File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Log.php
Lines: 15-31

class Log extends BaseArithmeticFunction
{
    protected function getFunctionName(): string
    {
        return 'LOG';
    }

    protected function getMinArgumentCount(): int
    {
        return 1;
    }

    protected function getMaxArgumentCount(): int
    {
        return 2;
    }
}

This class defines the LOG function for Doctrine ORM DQL. It specifies the function name as 'LOG' and allows between 1 and 2 arguments.


File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php
Lines: 9-31

class LogTest extends NumericTestCase
{
    protected function getStringFunctions(): array
    {
        return [
            'LOG' => Log::class,
        ];
    }

    public function test_log(): void
    {
        $dql = 'SELECT LOG(10, 100) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1';
        $result = $this->executeDqlQuery($dql);
        $this->assertEqualsWithDelta(2.0, $result[0]['result'], 0.0001);
    }

    public function test_log_with_entity_property(): void
    {
        $dql = 'SELECT LOG(10, n.decimal1) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics n WHERE n.id = 1';
        $result = $this->executeDqlQuery($dql);
        $this->assertEqualsWithDelta(1.0211892990699381, $result[0]['result'], 0.000001);
    }
}

This integration test class for the LOG function extends NumericTestCase and includes tests that execute DQL queries using the LOG function with numeric literals and entity properties, asserting expected results with floating point tolerance.


Additional related test method patterns from other function tests (e.g., LnTest, PiTest, ExpTest, SignTest, DegreesTest, etc.)
These test classes follow a similar pattern with methods:

  • getStringFunctions() returning an array mapping the function name to its class.
  • getExpectedSqlStatements() returning expected SQL strings for various DQL inputs.
  • getDqlStatements() returning DQL strings to be tested.

Examples from tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LnTest.php:

protected function getStringFunctions(): array
{
    return [
        'LN' => Ln::class,
    ];
}

protected function getExpectedSqlStatements(): array
{
    return [
        'SELECT LN(12) AS sclr_0 FROM ContainsDecimals c0_',
        'SELECT LN(c0_.decimal1) AS sclr_0 FROM ContainsDecimals c0_',
    ];
}

protected function getDqlStatements(): array
{
    return [
        \sprintf('SELECT LN(12) FROM %s e', ContainsDecimals::class),
        \sprintf('SELECT LN(e.decimal1) FROM %s e', ContainsDecimals::class),
    ];
}

This pattern is consistent across many function test classes and is relevant for understanding the structure and intent of the LogTest unit test.


Summary:
The above snippets provide context on:

  • The implementation of the Log DQL function class.
  • Integration tests verifying the Log function's behavior with actual DQL queries and expected numeric results.
  • The typical structure of unit tests for similar DQL functions, including methods for registering the function, expected SQL, and DQL statements.

These are directly relevant to understanding and potentially addressing the user comment on the LogTest.php file.


✏️ Learnings added
Learnt from: martin-georgiev
PR: martin-georgiev/postgresql-for-doctrine#383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/LogTest.php:22-24
Timestamp: 2025-05-23T11:24:46.876Z
Learning: The LOG function in PostgreSQL/Doctrine implementation supports both single-argument form (LOG(x) for base 10 logarithm) and two-argument form (LOG(b, x) for logarithm with specified base).

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@martin-georgiev martin-georgiev merged commit 3665a25 into main May 23, 2025
54 of 57 checks passed
@martin-georgiev martin-georgiev deleted the math-functions branch May 23, 2025 11:34
@martin-georgiev martin-georgiev changed the title feat: add support for arithmetic functions CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN, and WIDTH_BUCKET. feat: add support for mathematical functions CBRT, DEGREES, EXP, LN, LOG, PI, POWER, RADIANS, RANDOM, SIGN and WIDTH_BUCKET May 23, 2025
@github-actions github-actions bot mentioned this pull request May 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants