Skip to content

Conversation

@thienvu18
Copy link
Contributor

When querying the Postgres database, the attachment count query was generated as follows:

select count(*) from "system_files" where "system_files"."attachment_id" = "CAST(some_table"."id" as "TEXT)" and "system_files"."attachment_type" = Some\Model and "field" = images) as "images_count"

This query results in a syntax error due to an incorrect placement of double quotes in the CAST statement.

Changes Made:
Fixed the syntax error by properly wrapping keys before casting.
Used raw queries to prevent issues with double wrapping of keys.

@LukeTowers
Copy link
Member

Thanks for the contribution @thienvu18! Any chance you're able to add a test case for this? Also, is this an issue that's present in Laravel as well?

@thienvu18
Copy link
Contributor Author

Thank for your quick reply.

Sorry that I am not good at writing test cases. However, we can produce this bug using our Test Plugin as follows:

  • Precondition: Using Postgres database
  • Step 1: Add a Portfolio count column to user in file plugins/winter/test/models/user/columns.yaml
    portfolio_count:
        label: Portfolio count
        relation: portfolio
        useRelationCount: true
  • Step 2: Access Users list at endpoint backend/winter/test/users. Open list setup then tick Portfolio count then Apply

Then you will get an exception like this
image

Notice at the generated sql statement, you will see an incorrect placement of quotes in the CAST statement

This bug only happens when using postgres database because Dongle will not cast if driver is not pgsql

@LukeTowers LukeTowers added this to the 1.2.8 milestone Jan 22, 2025
@jaxwilko
Copy link
Member

Tested and confirmed the issue.

This is caused by DbDongle::cast() creating SQL that should not be treated as a value, however whereColumn() treats it as such, causing a syntax error.

I had a look through the code base and cannot find any other instances of DbDongle::cast() being passed to a non-raw function.

It may be benefitial to rely on $query instead of $this->query when getting the grammar object, additionally using sprintf() seems to be common for the other usages of DbDongle::cast() in the codebase.

Maybe something like:

$query = $query->select($columns)->whereRaw(sprintf(
    '%s = %s',
    $query->getGrammar()->wrap($this->getExistenceCompareKey()),
    DbDongle::cast($query->getGrammar()->wrap($this->getQualifiedParentKeyName()), 'TEXT')
));

Copy link
Member

@jaxwilko jaxwilko left a comment

Choose a reason for hiding this comment

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

LGTM

@LukeTowers
Copy link
Member

@thienvu18 can you test out the latest changes that we've made and let me know how it goes for you? Then we should be able to merge it.

@thienvu18
Copy link
Contributor Author

@LukeTowers
I’ve tested the latest changes on my end, and everything seems to be working fine. No issues from my side, so feel free to proceed with the merge!

Thanks for all your hard work on this – much appreciated!

Let me know if you need anything else.

Cheers!

@LukeTowers LukeTowers merged commit 6e74a46 into wintercms:develop Feb 27, 2025
10 checks passed
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