Skip to content

Operator precedence and parentheses in queries #3055

@roji

Description

@roji

I have an issue with test QueryTestBase.String_Compare_nested. The test generates the following query:

SELECT "c"."CustomerID", "c"."Address", "c"."City", "c"."CompanyName", "c"."ContactName", "c"."ContactTitle", "c"."Country", "c"."Fax", "c"."Phone", "c"."PostalCode", "c"."Region"
        FROM "Customers" AS "c"
        WHERE "c"."CustomerID" <= 'M' || "c"."CustomerID"

However, it seems that in PostgreSQL, the string concatenation operator || has lower priority than the comparison operator <=, and so the WHERE clause gets a string instead of a bool.

IMHO this is very strange behavior on PostgreSQL's side - have sent a message to their dev list. However, it raises the larger question of operator precedence and parentheses. I can see some basic logic for that in DefaultQuerySqlGenerator.VisitBinary but in my case both sides of the expression are simple. I am also looking into mapping various C# operations to PostgreSQL-specific operators (regex, json), and the problem might pop up there as well.

A full, complete solution would assign an SQL priority to each expression, take that into account when generating parenthese and allow providers to override. This would be a non-trivial change I guess.

A quicker hack would be for providers to simply allow providers to override a new RequiresParentheses method, which would accept an Expression and would return whether to always surround its SQL with parentheses. If you want to go down that route I can submit a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions