Skip to content

[13.x] fix(postgres): whereDate and whereTime crash when $column is an Expression#60305

Closed
ahawlitschek wants to merge 1 commit into
laravel:13.xfrom
ahawlitschek:fix/where-date-expression-argument
Closed

[13.x] fix(postgres): whereDate and whereTime crash when $column is an Expression#60305
ahawlitschek wants to merge 1 commit into
laravel:13.xfrom
ahawlitschek:fix/where-date-expression-argument

Conversation

@ahawlitschek
Copy link
Copy Markdown
Contributor

@ahawlitschek ahawlitschek commented May 28, 2026

fix: whereDate and whereTime crash when $column is an Expression
The ->whereDate and ->whereTime functions are typed to accept Expression or string as first parameter ($column). Since Laravel 12, both underlying functions in PostgresGrammar checks whether the $column is a JSON selector using the isJsonSelector($value) function defined in the base grammar. This function uses str_contains and causes a runtime exception if it receives something other than string. Currently, the function is called with the origin value of the $column parameter which in some cases may be Expression.

This changes the parameter from the isJsonSelector to the wrapped column instead of the original one. It also adds tests which check, that using Expression or Stringable in whereDate and whereTime produces proper SQL.

The `->whereDate` and `->whereTime` functions are typed to accept `Expression` or string as first parameter (`$column`). Since Laravel 12, both underlying functions in `PostgresGrammar` checks whether the `$column` is a JSON selector using the `isJsonSelector($value)` function defined in the base grammar. This function uses `str_contains` and causes a runtime exception if it receives something other than string. Currently, the function is called with the origin value of the `$column` parameter which in some cases may be `Expression`.

 This adds an `is_string` check to only call `isJsonSelector` if the type of the column is a string and also adds tests which check, that using `Expression` in `whereDate` and `whereTime` produces proper SQL.

 I discussed several ways to fix this with my colleagues. Swapping `$this->isJsonSelector($where['column'])` with `$this->isJsonSelector($column)` would also fix it. But in my opinion an `Expression` is semantically no json selector and the developer is responsible for ensuring a valid query if `DB::raw()` is used.
 Changing `isJsonSelector` to also handle `Expression` seems too broad.
 Another approach would be to always add parentheses within the return statement, since the parentheses are necessary because of the cast. But then more tests need to be adjusted and the created SQL will contain unnecessary parentheses most of the time.
@taylorotwell
Copy link
Copy Markdown
Member

Technically a breaking change for Stringable objects which would have worked previously.

@ahawlitschek
Copy link
Copy Markdown
Contributor Author

ahawlitschek commented May 29, 2026

@taylorotwell

Understood. I would still want to fix this bug in a way that's mergable.

Under this circumstances the other way I mentioned in my PR description would be suitable.
So that it looks like this:

CleanShot 2026-05-29 at 09 28 59

When we look at the current implementation in the where method of the query builder, it also performs JSON checks on Expression, so even it's against my personal opinion, doing it that way in whereDate and whereTime too, should fix the bug and stay analog to the current code base:
CleanShot 2026-05-29 at 09 31 20

I adjusted the PR Description, changed the code to the way described above and added tests, that checks also for Stringable.
I opened a new PR with it.

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