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

SqlExpression for function with atypical format #33697

Closed
ronnyek opened this issue May 10, 2024 · 4 comments
Closed

SqlExpression for function with atypical format #33697

ronnyek opened this issue May 10, 2024 · 4 comments
Assignees
Labels
area-query closed-no-further-action The issue is closed and no further action is planned. customer-reported

Comments

@ronnyek
Copy link

ronnyek commented May 10, 2024

I'm trying to map date addition for this new database provider. This database has a DATE_ADD function that takes in a column or string, and then unit and amount like so:

DATE_ADD('2014-01-01', INTERVAL 1 DAY)

My understanding is that functions that are mapped, are assumed to be expecting typical function(param1, param2) type format.

To try and make this work, I've tried to make my expression take a SqlExpression for the source, and then have the second parameter be sqlExpressionFactory.Constant($"INTERVAL {amount} {unit}"). This doesn't work because the amount being passed in is a SqlExpression.

Is there a way to customize how a functions parameters are passed to the db function, or a way to effectively evaluate the amount expression so I can then pass that value in correctly?

Right now I'm getting this, when I attempt to just string interpolate the argument.

DATE_ADD("o"."OrderDate", 'INTERVAL [Microsoft.EntityFrameworkCore.Query.SqlExpressions.SqlUnaryExpression] YEAR')
@maumar
Copy link
Contributor

maumar commented May 10, 2024

MySql has to deal with a similar problem, you can try copying their solution:
https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/blob/main/src/EFCore.MySql/Query/Expressions/Internal/MySqlComplexFunctionArgumentExpression.cs

With that approach, your SqlFunctionExpression would take first argument representing the date and the second fragment would be the composite argument, with Delimiter being " ", first argument SqlFragment representing "INTERVAL", sql expression representing amount and another SqlFragment representing unit.

@roji
Copy link
Member

roji commented May 11, 2024

@ronnyek can you specify which database you're targeting?

@ronnyek
Copy link
Author

ronnyek commented May 13, 2024

MySql has to deal with a similar problem, you can try copying their solution: https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/blob/main/src/EFCore.MySql/Query/Expressions/Internal/MySqlComplexFunctionArgumentExpression.cs

With that approach, your SqlFunctionExpression would take first argument representing the date and the second fragment would be the composite argument, with Delimiter being " ", first argument SqlFragment representing "INTERVAL", sql expression representing amount and another SqlFragment representing unit.

I've spent a fair bit of time investigating this. It seems as is I've got it generating the sql but it looks like the SqlFragment expressions in the ComplexFunctionArgumentExpression are just not being included.

WHERE DATE_TO_STR(DATE_ADD("o"."OrderDate",  -1 ), 'yyyy') = 1997

Notice the spaces around -1, it seems like SqlFragments aren't being included as a part of the query. (the date_to_str comapring equality with 1997 is wrong, but I know how to fix that part)

I tried replacing the SqlFragment in the arguments to ComplexFunctionArgument with Constant, and it generates perfect, except wraps Interval and date unit in quotes (understandable since its thinking those are string values)

Currently this lib is targetting EF 6.0.29, and I'm looking at the pomelo driver branched 6.0 maint, which seems to reference 6.0.29. I'm unsure if this is a limitation of efcore at this version, or if there is something else going on.

As a side question (maybe reduce the amount of questions I ask here), are there any architecture documents with EFCORE? In getting this far, I was unsure when errors meant I needed a Visitor, or a Translator or whatever.

@ronnyek
Copy link
Author

ronnyek commented May 13, 2024

I just noticed that there was a overridden method in MysqlQuerySqlGenerator that looks like this

 protected override void CheckComposableSql(string sql)
 {
     // MySQL supports CTE (WITH) expressions within subqueries, as well as others,
     // so we allow any raw SQL to be composed over.
 }

Doing a similar override (unless I changed something else) actually execute, and return expected results. Would providing that override make the difference between SqlFragments being rendered in the sql commands or not?

@ronnyek ronnyek closed this as completed May 15, 2024
@roji roji added the closed-no-further-action The issue is closed and no further action is planned. label May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-query closed-no-further-action The issue is closed and no further action is planned. customer-reported
Projects
None yet
Development

No branches or pull requests

4 participants