Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DefaultQuerySqlGenerator not flexible enough for provider override #9143

Closed
roji opened this issue Jul 11, 2017 · 4 comments
Closed

DefaultQuerySqlGenerator not flexible enough for provider override #9143

roji opened this issue Jul 11, 2017 · 4 comments

Comments

@roji
Copy link
Member

roji commented Jul 11, 2017

As part of #9126, I set about adding a PostgreSQL-specific ILikeExpression and modifying NpgsqlQuerySqlGenerator to render it correctly. I hit several limitations with DefaultQuerySqlGenerator not exposing enough functionality to subclasses:

  • _typeMapping is private, and so I can't set it properly (as VisitLike() does)
  • isSearchCondition is a private static method, so there's no way to introduce a new expression type that is identified as a search condition. This means that a useless = TRUE is rendered out, and may have other consequences I'm not aware of as well.

I can submit PRs for these two specific problems, but I've run into similar issues previously, so you guys may want to do a proper review of DefaultQuerySqlGenerator keeping providers in mind.

@divega
Copy link
Contributor

divega commented Jul 11, 2017

@roji Thanks for reporting this.

I can submit PRs for these two specific problems, but I've run into similar issues previously, so you guys may want to do a proper review of DefaultQuerySqlGenerator keeping providers in mind.

Our general approach is intentionally to avoid overdesigning the provider model and wait for feedback like yours to help us triangulate where the extensibility and additional flexibility is needed. This obviously works much better if we have time to react to feedback like this... So the second point from my list of regrets at #9126 (comment) applies here too.

Fortunately in this case I believe we can take changes like the ones you suggest later, e.g. in 2.1, without them being breaking changes. So it would be great if you can send a PR.

I also hope you can either do something that works (even if it is suboptimal) for 2.0 or wait until 2.1 to add the new Like variant.

@smitpatel
Copy link
Member

  1. We should expose type mapping allowing providers to set it. Not sure if access as property or functions.
  2. There should not be side effect other than extra = True. Though the whole class BooleanConditionTranslatingExpressionVisitor is private. There is no way for providers to influence it at present. For custom nodes, providers can override VisitChildren but at present it allows no control over if Child are supposed to be condition or not. And there is no way to extend the set of condition nodes as you figured. At one point @anpete & me were thinking of a base class for all the custom expression defined in EF (& providers) such a base class would allow to add properties like that which we can directly evaluate. Give us some time to discuss 2nd point in team. The harm of that would be none apart from bit longer SQL.

@roji
Copy link
Member Author

roji commented Jul 12, 2017

Thanks (as always) for your reactions and for caring :)

The good news on this is that the lacking extensibility in DefaultSqlQueryGenerator doesn't have a big on me at the moment - the only tangible problem is the extra = TRUE (which is really unimportant). And in addition, it seems possible to open up more aspects for 2.1 without breaking any compatibility, so there's no big problem here.

@smitpatel no problem, I'll let you guys take a look at the two issues and fix them as you see fit. If you prefer to receive a PR from me on one of them (or both) let me know.

@ajcvickers ajcvickers added this to the 2.1.0 milestone Jul 12, 2017
@ajcvickers ajcvickers modified the milestones: 2.1.0-preview1, 2.1.0 Jan 17, 2018
@ajcvickers ajcvickers modified the milestones: 2.1.0, Backlog Jan 26, 2018
austindrenski added a commit to austindrenski/npgsql-efcore.pg that referenced this issue May 25, 2018
When a custom binary operator uses a standard comparison operator (=, <>, <, >, <=, >=)
EF Core will generate a pattern that causes a syntax error in PostgreSQL.

Example SQL:
  WHERE a < b = TRUE

This patch adds logic to check if the custom binary operator is one of the standard
comparison operators. If so, it wraps the expression in parenthesis.

While it seems like this could be avoided by having the custom translator construct
a standard Expression.LessThan(Expression,Expression), this causes an error to be
thrown...because the binary operator isn't defined.

See the related links for more information.

Example stack trace:

  System.InvalidOperationException : The binary operator LessThanOrEqual is not defined
     for the types 'System.Net.IPAddress' and 'System.Net.IPAddress'.
     at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow(...)
     at System.Linq.Expressions.Expression.GetComparisonOperator(...)
     at System.Linq.Expressions.Expression.LessThanOrEqual(...)

Related:

- dotnet/efcore#9143
- npgsql#323 (review)
austindrenski added a commit to austindrenski/npgsql-efcore.pg that referenced this issue May 25, 2018
When a custom binary operator uses a standard comparison operator (`=`, `<>`, `<`, `>`, `<=`, `>=`)
EF Core will generate a pattern that causes a syntax error in PostgreSQL.

Example SQL:
```sql
WHERE x."Inet" < @__inet_1 = TRUE
```

This patch adds logic to check if the custom binary operator is one of the standard
comparison operators. If so, it wraps the expression in parenthesis.

Example SQL (patched):
```sql
WHERE (x."Inet" < @__inet_1) = TRUE
```

While it seems like this could be avoided by having the custom translator construct
a standard Expression.LessThan(Expression,Expression), this causes an error to be
thrown...because the binary operator isn't defined.

Example stack trace:

```
System.InvalidOperationException : The binary operator LessThanOrEqual is not defined
  for the types 'System.Net.IPAddress' and 'System.Net.IPAddress'.
  at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow(...)
  at System.Linq.Expressions.Expression.GetComparisonOperator(...)
  at System.Linq.Expressions.Expression.LessThanOrEqual(...)
```

Related:

- [](dotnet/efcore#9143)
- [](npgsql#323 (review))
austindrenski added a commit to austindrenski/npgsql-efcore.pg that referenced this issue May 25, 2018
When a custom binary operator uses a standard comparison operator (`=`, `<>`, `<`, `>`, `<=`, `>=`)
EF Core will generate a pattern that causes a syntax error in PostgreSQL.

Example SQL:
```sql
WHERE x."Inet" < @__inet_1 = TRUE
```

This patch adds logic to check if the custom binary operator is one of the standard
comparison operators. If so, it wraps the expression in parenthesis.

Example SQL (patched):
```sql
WHERE (x."Inet" < @__inet_1) = TRUE
```

While it seems like this could be avoided by having the custom translator construct
a standard `Expression.LessThan(Expression,Expression)`, this causes an error to be
thrown...because the binary operator isn't defined.

Example stack trace:

```
System.InvalidOperationException : The binary operator LessThanOrEqual is not defined
  for the types 'System.Net.IPAddress' and 'System.Net.IPAddress'.
  at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow(...)
  at System.Linq.Expressions.Expression.GetComparisonOperator(...)
  at System.Linq.Expressions.Expression.LessThanOrEqual(...)
```

Related:

- dotnet/efcore#9143
- npgsql#323 (review)
roji pushed a commit to npgsql/efcore.pg that referenced this issue May 26, 2018
When a custom binary operator uses a standard comparison operator (`=`, `<>`, `<`, `>`, `<=`, `>=`)
EF Core will generate a pattern that causes a syntax error in PostgreSQL.

Example SQL:
```sql
WHERE x."Inet" < @__inet_1 = TRUE
```

This patch adds logic to check if the custom binary operator is one of the standard
comparison operators. If so, it wraps the expression in parenthesis.

Example SQL (patched):
```sql
WHERE (x."Inet" < @__inet_1) = TRUE
```

While it seems like this could be avoided by having the custom translator construct
a standard `Expression.LessThan(Expression,Expression)`, this causes an error to be
thrown...because the binary operator isn't defined.

Example stack trace:

```
System.InvalidOperationException : The binary operator LessThanOrEqual is not defined
  for the types 'System.Net.IPAddress' and 'System.Net.IPAddress'.
  at System.Linq.Expressions.Expression.GetUserDefinedBinaryOperatorOrThrow(...)
  at System.Linq.Expressions.Expression.GetComparisonOperator(...)
  at System.Linq.Expressions.Expression.LessThanOrEqual(...)
```

Related:

- dotnet/efcore#9143
- #323 (review)
@smitpatel
Copy link
Member

Superseded by #10513

@smitpatel smitpatel removed their assignment Sep 1, 2018
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants