Skip to content

Conversation

@janklan
Copy link
Contributor

@janklan janklan commented Dec 3, 2025

The subject says it all.

Summary by CodeRabbit

  • New Features

    • Added DATE_TRUNC to truncate timestamps to precisions (microseconds, milliseconds, second, minute, hour, day, week, month, quarter, year, decade, century, millennium).
    • Supports an optional timezone parameter.
  • Documentation

    • Updated integration guides for Doctrine, Laravel, and Symfony.
    • Added examples demonstrating DATE_TRUNC with and without timezone.
  • Tests

    • Added unit tests covering usage scenarios and input validation.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 3, 2025

Warning

Rate limit exceeded

@janklan has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 21 minutes and 39 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 98054e6 and d897908.

📒 Files selected for processing (8)
  • docs/DATE-AND-RANGE-FUNCTIONS.md (1 hunks)
  • docs/INTEGRATING-WITH-DOCTRINE.md (1 hunks)
  • docs/INTEGRATING-WITH-LARAVEL.md (1 hunks)
  • docs/INTEGRATING-WITH-SYMFONY.md (1 hunks)
  • docs/USE-CASES-AND-EXAMPLES.md (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (1 hunks)

Walkthrough

Adds a new PostgreSQL-style DQL function DATE_TRUNC (variadic, 2–3 args) with truncation-field and timezone validation, a dedicated InvalidTruncFieldException, docs updates showing registration/examples, and unit tests covering SQL generation and validation paths.

Changes

Cohort / File(s) Summary
Documentation Updates
docs/DATE-AND-RANGE-FUNCTIONS.md, docs/INTEGRATING-WITH-DOCTRINE.md, docs/INTEGRATING-WITH-LARAVEL.md, docs/INTEGRATING-WITH-SYMFONY.md, docs/USE-CASES-AND-EXAMPLES.md
Added DATE_TRUNC mapping entries and usage examples (including timezone examples) across integration guides and function registry snippets
Core Implementation
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
New variadic function class DateTrunc implementing date_trunc, accepts 2–3 arguments (field, timestamp, optional timezone), validates truncation field against allowed FIELDS and validates timezone via TimezoneValidationTrait
Exception Handling
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
New exception class with factory constructors for non-literal field nodes and invalid field values; extends Doctrine's ConversionException and references DateTrunc::FIELDS in messages
Test Coverage
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
New unit tests covering SQL generation (with/without timezone), argument count validation, allowed/invalid field validation, timezone validation, and data providers for cases

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to:
    • src/.../DateTrunc.php — variadic argument bounds, literal extraction/normalization for the trunc field, and correct invocation of timezone validation.
    • src/.../Exception/InvalidTruncFieldException.php — wording and reference to DateTrunc::FIELDS.
    • tests/.../DateTruncTest.php — expected SQL strings and exception message assertions matching implementation.
    • Documentation snippets — consistent registration syntax across examples.

Possibly related PRs

Poem

🐇 I trim the seconds, minutes, day by day,

DATE_TRUNC hops in to carve time away,
With fields that fit and tz checks done right,
Docs, tests, and code all snug for the night,
A rabbit's tiny cheer for timestamps bright.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding support for the DATE_TRUNC function across documentation, implementation, and tests.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/USE-CASES-AND-EXAMPLES.md (1)

100-111: Fix DATE_TRUNC example with four arguments and invalid timezone

The second DATE_TRUNC example,

SELECT DATE_TRUNC('day', e.timestampWithTz, '2 hours', 'UTC') FROM Entity e

does not match the implemented function:

  • DateTrunc only allows 2 or 3 arguments (field, source, optional time_zone).
  • If used as written, it will trigger InvalidArgumentForVariadicFunctionException due to too many arguments.
  • '2 hours' is not a valid timezone string for the current timezone validation.

Consider updating to a 3‑argument example with a valid timezone, e.g.:

-SELECT DATE_TRUNC('day', e.timestampWithTz, '2 hours', 'UTC') FROM Entity e
+SELECT DATE_TRUNC('day', e.timestampWithTz, 'UTC') FROM Entity e

This keeps the “timezone parameter is optional” wording accurate and matches the actual API.

🧹 Nitpick comments (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1)

15-34: Exception wiring is fine; consider renaming parameter for clarity

InvalidTruncFieldException correctly provides:

  • forNonLiteralNode() for non-literal field arguments.
  • forInvalidField() including the list of allowed DateTrunc::FIELDS.

Only minor nit: the first parameter of forInvalidField() is named $timezone but represents the truncation field value. Renaming to $field would better reflect its purpose without changing behavior:

-    public static function forInvalidField(string $timezone, string $functionName): self
+    public static function forInvalidField(string $field, string $functionName): self
     {
         return new self(\sprintf(
             'Invalid date_trunc field value "%s" provided for %s. Must be one of: %s.',
-            $timezone,
+            $field,
             $functionName,
             \implode(', ', DateTrunc::FIELDS)
         ));
     }
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (1)

16-143: DateTrunc tests are solid; consider adding a non‑literal field case

The test suite nicely covers:

  • DQL → SQL translation for 2‑ and 3‑argument usages and WHERE clause.
  • Argument count validation via InvalidArgumentForVariadicFunctionException.
  • Field value validation against DateTrunc::FIELDS.
  • Timezone validation via InvalidTimezoneException.

To fully exercise InvalidTruncFieldException::forNonLiteralNode(), you could add a case where the first argument isn’t a string literal (e.g. using a field expression as the truncation unit). For example:

public function test_throws_exception_for_non_literal_field(): void
{
    $this->expectException(InvalidTruncFieldException::class);
    $this->expectExceptionMessage(
        'The date_trunc field parameter for date_trunc must be a string literal'
    );

    $dql = \sprintf("SELECT DATE_TRUNC(e.datetimetz1, e.datetimetz1) FROM %s e", ContainsDates::class);
    $this->buildEntityManager()->createQuery($dql)->getSQL();
}

(adjust the exact message assertion once DateTrunc uses InvalidTruncFieldException::forNonLiteralNode()).

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 266820d and 52cd4ad.

📒 Files selected for processing (8)
  • docs/DATE-AND-RANGE-FUNCTIONS.md (1 hunks)
  • docs/INTEGRATING-WITH-DOCTRINE.md (1 hunks)
  • docs/INTEGRATING-WITH-LARAVEL.md (1 hunks)
  • docs/INTEGRATING-WITH-SYMFONY.md (1 hunks)
  • docs/USE-CASES-AND-EXAMPLES.md (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: karpilin
Repo: martin-georgiev/postgresql-for-doctrine PR: 386
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTimestampTest.php:34-39
Timestamp: 2025-05-27T16:10:35.054Z
Learning: PostgreSQL's to_timestamp function returns a fallback result (like '2005-01-01 00:00:00+00') when given an invalid format string, rather than throwing an exception. This behavior is different from some other formatting functions and should be tested accordingly.
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.
📚 Learning: 2025-08-09T15:31:42.054Z
Learnt from: landure
Repo: martin-georgiev/postgresql-for-doctrine PR: 411
File: src/MartinGeorgiev/Doctrine/DBAL/Types/Exceptions/InvalidLtreeForPHPException.php:11-19
Timestamp: 2025-08-09T15:31:42.054Z
Learning: In the postgresql-for-doctrine library, exception classes for invalid PHP values (Invalid*ForPHPException) follow a consistent pattern using var_export() in their create() method to format error messages. When adding new exception classes, maintain consistency with existing patterns rather than introducing new approaches, even if technically superior alternatives exist.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 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.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
  • docs/INTEGRATING-WITH-SYMFONY.md
  • docs/DATE-AND-RANGE-FUNCTIONS.md
  • docs/INTEGRATING-WITH-DOCTRINE.md
  • docs/INTEGRATING-WITH-LARAVEL.md
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
  • docs/INTEGRATING-WITH-SYMFONY.md
  • docs/DATE-AND-RANGE-FUNCTIONS.md
  • docs/INTEGRATING-WITH-DOCTRINE.md
  • docs/INTEGRATING-WITH-LARAVEL.md
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
📚 Learning: 2025-08-25T21:29:08.737Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 0
File: :0-0
Timestamp: 2025-08-25T21:29:08.737Z
Learning: The repository should separate value object validation exceptions (extending \InvalidArgumentException) from DBAL conversion exceptions (extending ConversionException) - the Ltree implementation demonstrates this ideal pattern with InvalidLtreeException for validation and InvalidLtreeForPHPException/InvalidLtreeForDatabaseException for conversion errors.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-08-25T21:29:08.737Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 0
File: :0-0
Timestamp: 2025-08-25T21:29:08.737Z
Learning: Value object validation in this repository should use dedicated exception classes extending \InvalidArgumentException (like InvalidLtreeException, InvalidPointException) with clear documentation separating validation concerns from DBAL conversion concerns, and should include protected static assertion methods for validation logic.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-03-11T12:32:10.726Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 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.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
  • docs/INTEGRATING-WITH-SYMFONY.md
  • docs/INTEGRATING-WITH-LARAVEL.md
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
🧬 Code graph analysis (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTimezoneException.php (1)
  • InvalidTimezoneException (14-33)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (3)
  • InvalidTruncFieldException (15-35)
  • forNonLiteralNode (17-24)
  • forInvalidField (26-34)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php (1)
  • BaseVariadicFunction (20-143)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Traits/TimezoneValidationTrait.php (1)
  • validateTimezone (25-36)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (5)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php (1)
  • BaseVariadicFunction (20-143)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1)
  • DateTrunc (23-94)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidArgumentForVariadicFunctionException.php (1)
  • InvalidArgumentForVariadicFunctionException (7-56)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTimezoneException.php (1)
  • InvalidTimezoneException (14-33)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1)
  • InvalidTruncFieldException (15-35)
🔇 Additional comments (4)
docs/INTEGRATING-WITH-DOCTRINE.md (1)

158-165: DATE_TRUNC registration for Doctrine configuration looks correct

The DATE_TRUNC mapping to MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateTrunc::class is consistent with the new function and aligned with existing date-specific registrations.

docs/DATE-AND-RANGE-FUNCTIONS.md (1)

9-18: DATE_TRUNC entry in date/time function table is consistent

The new date_truncDATE_TRUNCDateTrunc row matches the implementation and follows the existing documentation pattern.

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

226-233: Symfony DQL registration for DATE_TRUNC is correct

The new DATE_TRUNC entry under string_functions correctly points to MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\DateTrunc and is consistent with the rest of the date-specific configuration.

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

243-250: Laravel custom_string_functions mapping for DATE_TRUNC is consistent

The 'DATE_TRUNC' => DateTrunc::class entry fits the existing pattern for date-specific functions and matches the new DateTrunc implementation.

@janklan janklan force-pushed the date-trunc branch 2 times, most recently from 4822f49 to 3da060e Compare December 3, 2025 03:11
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: 1

🧹 Nitpick comments (1)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1)

26-33: Clarify parameter naming in forInvalidField()

forInvalidField() currently uses $timezone as the parameter name, even though it represents the invalid truncation field. The behavior is correct but the name is confusing when reading the code next to DateTrunc::FIELDS.

Consider renaming the parameter to better reflect its meaning, for example:

-    public static function forInvalidField(string $timezone, string $functionName): self
+    public static function forInvalidField(string $field, string $functionName): self
     {
         return new self(\sprintf(
             'Invalid date_trunc field value "%s" provided for %s. Must be one of: %s.',
-            $timezone,
+            $field,
             $functionName,
             \implode(', ', DateTrunc::FIELDS)
         ));
     }

If you prefer to avoid changing the parameter name for potential named-argument callers, you could keep $timezone in the signature but assign it to a local $field variable and use that in the message.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52cd4ad and 3da060e.

📒 Files selected for processing (8)
  • docs/DATE-AND-RANGE-FUNCTIONS.md (1 hunks)
  • docs/INTEGRATING-WITH-DOCTRINE.md (1 hunks)
  • docs/INTEGRATING-WITH-LARAVEL.md (1 hunks)
  • docs/INTEGRATING-WITH-SYMFONY.md (1 hunks)
  • docs/USE-CASES-AND-EXAMPLES.md (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/INTEGRATING-WITH-LARAVEL.md
  • docs/DATE-AND-RANGE-FUNCTIONS.md
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
  • docs/USE-CASES-AND-EXAMPLES.md
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: karpilin
Repo: martin-georgiev/postgresql-for-doctrine PR: 386
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTimestampTest.php:34-39
Timestamp: 2025-05-27T16:10:35.054Z
Learning: PostgreSQL's to_timestamp function returns a fallback result (like '2005-01-01 00:00:00+00') when given an invalid format string, rather than throwing an exception. This behavior is different from some other formatting functions and should be tested accordingly.
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • docs/INTEGRATING-WITH-DOCTRINE.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • docs/INTEGRATING-WITH-SYMFONY.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 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.

Applied to files:

  • docs/INTEGRATING-WITH-DOCTRINE.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • docs/INTEGRATING-WITH-SYMFONY.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
📚 Learning: 2025-08-09T15:31:42.054Z
Learnt from: landure
Repo: martin-georgiev/postgresql-for-doctrine PR: 411
File: src/MartinGeorgiev/Doctrine/DBAL/Types/Exceptions/InvalidLtreeForPHPException.php:11-19
Timestamp: 2025-08-09T15:31:42.054Z
Learning: In the postgresql-for-doctrine library, exception classes for invalid PHP values (Invalid*ForPHPException) follow a consistent pattern using var_export() in their create() method to format error messages. When adding new exception classes, maintain consistency with existing patterns rather than introducing new approaches, even if technically superior alternatives exist.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
📚 Learning: 2025-08-25T21:29:08.737Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 0
File: :0-0
Timestamp: 2025-08-25T21:29:08.737Z
Learning: The repository should separate value object validation exceptions (extending \InvalidArgumentException) from DBAL conversion exceptions (extending ConversionException) - the Ltree implementation demonstrates this ideal pattern with InvalidLtreeException for validation and InvalidLtreeForPHPException/InvalidLtreeForDatabaseException for conversion errors.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-08-25T21:29:08.737Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 0
File: :0-0
Timestamp: 2025-08-25T21:29:08.737Z
Learning: Value object validation in this repository should use dedicated exception classes extending \InvalidArgumentException (like InvalidLtreeException, InvalidPointException) with clear documentation separating validation concerns from DBAL conversion concerns, and should include protected static assertion methods for validation logic.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-03-11T12:32:10.726Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 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.

Applied to files:

  • docs/INTEGRATING-WITH-SYMFONY.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
📚 Learning: 2025-04-18T10:33:52.412Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 350
File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php:78-88
Timestamp: 2025-04-18T10:33:52.412Z
Learning: In SQL generation code for the postgresql-for-doctrine library, it's better to fail explicitly with clear errors than to use fallback behavior that makes assumptions about node types, as this could lead to functional bugs or security issues.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
🧬 Code graph analysis (2)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1)
  • DateTrunc (23-94)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (4)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTimezoneException.php (1)
  • InvalidTimezoneException (14-33)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (3)
  • InvalidTruncFieldException (15-35)
  • forNonLiteralNode (17-24)
  • forInvalidField (26-34)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php (1)
  • BaseVariadicFunction (20-143)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Traits/TimezoneValidationTrait.php (1)
  • validateTimezone (25-36)
🪛 GitHub Actions: CI
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php

[error] 1-1: PHP CS Fixer: no_unused_imports violation. Removed unused import 'InvalidTimezoneException'.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.5
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.5
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.5
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.6 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.6 + PHP 8.2
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.6 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 2.14 + Doctrine Lexer latest
🔇 Additional comments (2)
docs/INTEGRATING-WITH-SYMFONY.md (1)

226-233: DATE_TRUNC registration in Symfony config is consistent

The new DATE_TRUNC mapping aligns with existing date functions and correctly references DateTrunc::class.

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

158-165: DATE_TRUNC registration in Doctrine config follows existing pattern

The DATE_TRUNC custom string function is registered consistently with other date functions and points to the correct DateTrunc class.

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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3da060e and 98054e6.

📒 Files selected for processing (8)
  • docs/DATE-AND-RANGE-FUNCTIONS.md (1 hunks)
  • docs/INTEGRATING-WITH-DOCTRINE.md (1 hunks)
  • docs/INTEGRATING-WITH-LARAVEL.md (1 hunks)
  • docs/INTEGRATING-WITH-SYMFONY.md (1 hunks)
  • docs/USE-CASES-AND-EXAMPLES.md (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1 hunks)
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1 hunks)
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/INTEGRATING-WITH-SYMFONY.md
  • docs/USE-CASES-AND-EXAMPLES.md
  • docs/INTEGRATING-WITH-LARAVEL.md
  • docs/INTEGRATING-WITH-DOCTRINE.md
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: karpilin
Repo: martin-georgiev/postgresql-for-doctrine PR: 386
File: tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/ToTimestampTest.php:34-39
Timestamp: 2025-05-27T16:10:35.054Z
Learning: PostgreSQL's to_timestamp function returns a fallback result (like '2005-01-01 00:00:00+00') when given an invalid format string, rather than throwing an exception. This behavior is different from some other formatting functions and should be tested accordingly.
📚 Learning: 2025-05-23T11:11:57.951Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 383
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RadiansTest.php:1-9
Timestamp: 2025-05-23T11:11:57.951Z
Learning: Tests in the `Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions` namespace extend a custom `TestCase` class from the same namespace (`Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TestCase`), rather than PHPUnit's TestCase directly, and therefore don't need an explicit import.

Applied to files:

  • docs/DATE-AND-RANGE-FUNCTIONS.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
📚 Learning: 2025-03-29T03:31:17.114Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 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.

Applied to files:

  • docs/DATE-AND-RANGE-FUNCTIONS.md
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
📚 Learning: 2025-04-18T10:33:52.412Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 350
File: src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php:78-88
Timestamp: 2025-04-18T10:33:52.412Z
Learning: In SQL generation code for the postgresql-for-doctrine library, it's better to fail explicitly with clear errors than to use fallback behavior that makes assumptions about node types, as this could lead to functional bugs or security issues.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
📚 Learning: 2025-08-09T15:31:42.054Z
Learnt from: landure
Repo: martin-georgiev/postgresql-for-doctrine PR: 411
File: src/MartinGeorgiev/Doctrine/DBAL/Types/Exceptions/InvalidLtreeForPHPException.php:11-19
Timestamp: 2025-08-09T15:31:42.054Z
Learning: In the postgresql-for-doctrine library, exception classes for invalid PHP values (Invalid*ForPHPException) follow a consistent pattern using var_export() in their create() method to format error messages. When adding new exception classes, maintain consistency with existing patterns rather than introducing new approaches, even if technically superior alternatives exist.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-03-11T12:32:10.726Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 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.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php
📚 Learning: 2025-08-25T21:29:08.737Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 0
File: :0-0
Timestamp: 2025-08-25T21:29:08.737Z
Learning: The repository should separate value object validation exceptions (extending \InvalidArgumentException) from DBAL conversion exceptions (extending ConversionException) - the Ltree implementation demonstrates this ideal pattern with InvalidLtreeException for validation and InvalidLtreeForPHPException/InvalidLtreeForDatabaseException for conversion errors.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-08-25T21:29:08.737Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 0
File: :0-0
Timestamp: 2025-08-25T21:29:08.737Z
Learning: Value object validation in this repository should use dedicated exception classes extending \InvalidArgumentException (like InvalidLtreeException, InvalidPointException) with clear documentation separating validation concerns from DBAL conversion concerns, and should include protected static assertion methods for validation logic.

Applied to files:

  • src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php
📚 Learning: 2025-09-01T18:48:28.508Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 434
File: tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/PostGIS/ST_CrossesTest.php:12-31
Timestamp: 2025-09-01T18:48:28.508Z
Learning: When analyzing unit test files in this codebase, always verify the actual file structure and existing patterns before suggesting changes. The ContainsGeometries fixture exists at ./fixtures/MartinGeorgiev/Doctrine/Entity/ContainsGeometries.php and the PostGIS unit tests use the namespace Tests\Unit\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PostGIS consistently.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
📚 Learning: 2025-04-22T00:03:37.733Z
Learnt from: martin-georgiev
Repo: martin-georgiev/postgresql-for-doctrine PR: 357
File: tests/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/RegexpMatchTest.php:28-62
Timestamp: 2025-04-22T00:03:37.733Z
Learning: This project focuses on providing Doctrine ORM interfaces to PostgreSQL functions. Tests should validate correct DQL-to-SQL translation rather than PostgreSQL functionality itself. Test cases should focus on parameter passing and SQL generation, not on testing specific PostgreSQL regex pattern behaviors.

Applied to files:

  • tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php
🧬 Code graph analysis (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (3)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (3)
  • InvalidTruncFieldException (15-35)
  • forNonLiteralNode (17-24)
  • forInvalidField (26-34)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php (1)
  • BaseVariadicFunction (20-143)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Traits/TimezoneValidationTrait.php (1)
  • validateTimezone (25-36)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1)
  • DateTrunc (22-93)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (6)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunction.php (1)
  • BaseVariadicFunction (20-143)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (1)
  • DateTrunc (22-93)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidArgumentForVariadicFunctionException.php (1)
  • InvalidArgumentForVariadicFunctionException (7-56)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTimezoneException.php (1)
  • InvalidTimezoneException (14-33)
src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Exception/InvalidTruncFieldException.php (1)
  • InvalidTruncFieldException (15-35)
tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TestCase.php (1)
  • buildEntityManager (115-118)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.5
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.4
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.5
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.5
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.3
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.4
  • GitHub Check: PostgreSQL 17 + PostGIS 3.6 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.6 + PHP 8.4
  • GitHub Check: PostgreSQL 18 + PostGIS 3.6 + PHP 8.2
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.6 + PHP 8.1
  • GitHub Check: PostgreSQL 17 + PostGIS 3.4 + PHP 8.2
  • GitHub Check: PostgreSQL 17 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.5 + PHP 8.1
  • GitHub Check: PostgreSQL 16 + PostGIS 3.4 + PHP 8.1
  • GitHub Check: PHP 8.4 + Doctrine ORM 2.14 + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer latest
  • GitHub Check: PHP 8.3 + Doctrine ORM latest + Doctrine Lexer 2.1
  • GitHub Check: PHP 8.2 + Doctrine ORM 3.0 + Doctrine Lexer 3.0
  • GitHub Check: wait-for-tests-worflows-before-upload
🔇 Additional comments (11)
docs/DATE-AND-RANGE-FUNCTIONS.md (1)

14-14: LGTM!

The documentation entry correctly maps the PostgreSQL date_trunc function to the DATE_TRUNC DQL identifier and follows the established table format.

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTruncTest.php (6)

18-28: LGTM!

The fixture setup and function mapping follow the established test patterns in this codebase.


30-46: LGTM!

The test cases cover the key scenarios: with timezone (3 arguments), without timezone (2 arguments), and usage in WHERE clauses. The expected SQL correctly reflects PostgreSQL's date_trunc syntax.


48-73: LGTM!

The test correctly validates argument count boundaries and verifies appropriate exception messages for both under and over-specification of arguments.


75-95: LGTM!

Using a data provider that iterates over DateTrunc::FIELDS ensures all valid truncation fields are tested, maintaining consistency with the implementation.


97-119: LGTM!

The test coverage for invalid fields includes edge cases like empty strings, whitespace, and clearly invalid values, ensuring robust validation.


121-143: LGTM!

The timezone validation tests cover similar edge cases and verify that the trait-based validation correctly rejects invalid timezone identifiers.

src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTrunc.php (4)

28-42: LGTM!

The FIELDS constant correctly lists all valid PostgreSQL truncation units as documented in the PostgreSQL reference, providing a clear contract for validation.


44-62: LGTM!

The function configuration correctly specifies:

  • StringPrimary node mapping for literal string arguments
  • 2–3 argument range matching PostgreSQL's date_trunc('field', source [, time_zone]) signature

64-74: LGTM!

The validation sequence is correct: parent validation for argument count, then field validation, and finally optional timezone validation when a third argument is present.


81-92: LGTM!

The field validation logic correctly:

  • Ensures the argument is a string literal
  • Normalizes the field value by trimming quotes and converting to lowercase
  • Validates against the FIELDS constant
  • Throws appropriate InvalidTruncFieldException for invalid cases

/**
* @see https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
*/
public const FIELDS = [
Copy link
Owner

Choose a reason for hiding this comment

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

Can you elaborate on why this is a public constant? There is no such pattern in any other classes in the repository. On the surface, it is needed for tests primarily.

Copy link
Contributor Author

@janklan janklan Dec 5, 2025

Choose a reason for hiding this comment

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

I wanted to both (a) enumerate the allowed options in InvalidTruncFieldException message and (b) have the list of valid options available for input validation.

It's in a public constant because it will likely never change (hence not a static variable), it's exposed as a class constant because it's needed in two separate classes, and it's not hardcoded as two separate arrays in each class because if it does change, someone will have to remember changing it in both places.

At the end of the day if you think it's better as two separate hardcoded arrays (because it's unlikely to change), let's do it that way for sake of overall consistency.

$field = \strtolower(\trim((string) $node->value, "'\""));

if (!\in_array($field, self::FIELDS, true)) {
throw InvalidTruncFieldException::forInvalidField($field, $this->getFunctionName());
Copy link
Owner

Choose a reason for hiding this comment

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

Why not let PostgreSQL decide whether this is fine? Excessive validation may limit support for future PostgreSQL versions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Personal preference of code that fails fast - this will fail before any SQL query gets executed.

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.

2 participants