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

Add new SQLite Math function mappings #4432

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions entity-framework/core/providers/cosmos/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ DateTimeOffset.UtcNow | GetCurrentDateTime()
double.DegreesToRadians(x) | RADIANS(@x) | EF Core 8.0
double.RadiansToDegrees(x) | DEGREES(@x) | EF Core 8.0
EF.Functions.Random() | RAND()
float.DegreesToRadians(x) | RADIANS(@x) | EF Core 8.0
float.RadiansToDegrees(x) | DEGREES(@x) | EF Core 8.0
Math.Abs(value) | ABS(@value)
Math.Acos(d) | ACOS(@d)
Math.Asin(d) | ASIN(@d)
Expand All @@ -44,23 +42,11 @@ Math.Sin(a) | SIN(@a)
Math.Sqrt(d) | SQRT(@d)
Math.Tan(a) | TAN(@a)
Math.Truncate(d) | TRUNC(@d)
MathF.Acos(x) | ACOS(@x)
MathF.Asin(x) | ASIN(@x)
MathF.Atan(x) | ATAN(@x)
MathF.Atan2(y, x) | ATN2(@y, @x)
MathF.Ceiling(x) | CEILING(@x)
MathF.Cos(x) | COS(@x)
MathF.Exp(x) | EXP(@x)
MathF.Floor(x) | FLOOR(@x)
MathF.Log(x, y) | LOG(@x, @y)
MathF.Log(x) | LOG(@x)
MathF.Log10(x) | LOG10(@x)
MathF.Pow(x, y) | POWER(@x, @y)
MathF.Round(x) | ROUND(@x)
MathF.Sin(x) | SIN(@x)
MathF.Sqrt(x) | SQRT(@x)
MathF.Tan(x) | TAN(@x)
MathF.Truncate(x) | TRUNC(@x)

> [!TIP]
> In addition to the methods listed here, corresponding [generic math](/dotnet/standard/generics/math) implementations
bricelam marked this conversation as resolved.
Show resolved Hide resolved
> and [MathF](/dotnet/api/system.mathf) methods are also translated. For example, `Math.Sin`, `MathF.Sin`, `double.Sin`,
> and `float.Sin` all map to the `SIN` function in SQL.

## String functions

Expand Down
25 changes: 5 additions & 20 deletions entity-framework/core/providers/sql-server/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,6 @@ timeSpan.Seconds | DATEPART(second, @
double.DegreesToRadians(x) | RADIANS(@x) | EF Core 8.0
double.RadiansToDegrees(x) | DEGREES(@x) | EF Core 8.0
EF.Functions.Random() | RAND()
float.DegreesToRadians(x) | RADIANS(@x) | EF Core 8.0
float.RadiansToDegrees(x) | DEGREES(@x) | EF Core 8.0
Math.Abs(value) | ABS(@value)
Math.Acos(d) | ACOS(@d)
Math.Asin(d) | ASIN(@d)
Expand All @@ -182,24 +180,11 @@ Math.Sin(a) | SIN(@a)
Math.Sqrt(d) | SQRT(@d)
Math.Tan(a) | TAN(@a)
Math.Truncate(d) | ROUND(@d, 0, 1)
MathF.Acos(x) | ACOS(@x)
MathF.Asin(x) | ASIN(@x)
MathF.Atan(x) | ATAN(@x)
MathF.Atan2(y, x) | ATN2(@y, @x)
MathF.Ceiling(x) | CEILING(@x)
MathF.Cos(x) | COS(@x)
MathF.Exp(x) | EXP(@x)
MathF.Floor(x) | FLOOR(@x)
MathF.Log(x) | LOG(@x)
MathF.Log(x, y) | LOG(@x, @y)
MathF.Log10(x) | LOG10(@x)
MathF.Pow(x, y) | POWER(@x, @y)
MathF.Round(x) | ROUND(@x, 0)
MathF.Round(x, decimals) | ROUND(@x, @decimals)
MathF.Sin(x) | SIN(@x)
MathF.Sqrt(x) | SQRT(@x)
MathF.Tan(x) | TAN(@x)
MathF.Truncate(x) | ROUND(@x, 0, 1)

> [!TIP]
> In addition to the methods listed here, corresponding [generic math](/dotnet/standard/generics/math) implementations
> and [MathF](/dotnet/api/system.mathf) methods are also translated. For example, `Math.Sin`, `MathF.Sin`, `double.Sin`,
> and `float.Sin` all map to the `SIN` function in SQL.

## String functions

Expand Down
73 changes: 50 additions & 23 deletions entity-framework/core/providers/sqlite/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,29 +97,56 @@ dateTime.Year | strftime('%Y', @dateTime)

## Numeric functions

.NET | SQL | Added in
---------------------- | ------------------------------------ | --------
-decimalValue | ef_negate(@decimalValue)
decimalValue - d | ef_add(@decimalValue, ef_negate(@d))
decimalValue * d | ef_multiply(@decimalValue, @d)
decimalValue / d | ef_divide(@decimalValue, @d)
decimalValue % d | ef_mod(@decimalValue, @d)
decimalValue + d | ef_add(@decimalValue, @d)
decimalValue < d | ef_compare(@decimalValue, @d) < 0
decimalValue <= d | ef_compare(@decimalValue, @d) <= 0
decimalValue > d | ef_compare(@decimalValue, @d) > 0
decimalValue >= d | ef_compare(@decimalValue, @d) >= 0
doubleValue % d | ef_mod(@doubleValue, @d)
EF.Functions.Random() | abs(random() / 9223372036854780000.0)
floatValue % d | ef_mod(@floatValue, @d)
Math.Abs(value) | abs(@value)
Math.Max(val1, val2) | max(@val1, @val2)
Math.Min(val1, val2) | min(@val1, @val2)
Math.Round(d) | round(@d)
Math.Round(d, digits) | round(@d, @digits)
Math.Sign(d) | sign(@d) | EF Core 8.0
MathF.Round(x) | round(@x)
MathF.Round(x, digits) | round(@x, @digits)
.NET | SQL | Added in
-------------------------------- | ------------------------------------ | --------
-decimalValue | ef_negate(@decimalValue)
decimalValue - d | ef_add(@decimalValue, ef_negate(@d))
decimalValue * d | ef_multiply(@decimalValue, @d)
decimalValue / d | ef_divide(@decimalValue, @d)
decimalValue % d | ef_mod(@decimalValue, @d)
decimalValue + d | ef_add(@decimalValue, @d)
decimalValue < d | ef_compare(@decimalValue, @d) < 0
decimalValue <= d | ef_compare(@decimalValue, @d) <= 0
decimalValue > d | ef_compare(@decimalValue, @d) > 0
decimalValue >= d | ef_compare(@decimalValue, @d) >= 0
double.DegreesToRadians(degrees) | radians(@degrees) | EF Core 8.0
double.RadiansToDegrees(radians) | degrees(@dradians) | EF Core 8.0
doubleValue % d | mod(@doubleValue, @d)
EF.Functions.Random() | abs(random() / 9223372036854780000.0)
Math.Abs(value) | abs(@value)
Math.Acos(value) | acos(@value) | EF Core 8.0
Math.Acosh(d) | acosh(@d) | EF Core 8.0
Math.Asin(d) | asin(@d) | EF Core 8.0
Math.Asinh(d) | asinh(@d) | EF Core 8.0
Math.Atan(d) | atan(@d) | EF Core 8.0
Math.Atan2(y, x) | atan2(@y, @x) | EF Core 8.0
Math.Atanh(d) | atanh(@d) | EF Core 8.0
Math.Ceiling(d) | ceiling(@d) | EF Core 8.0
Math.Cos(d) | cos(@d) | EF Core 8.0
Math.Cosh(value) | cosh(@value) | EF Core 8.0
Math.Exp(d) | exp(@d) | EF Core 8.0
Math.Floor(d) | floor(@d) | EF Core 8.0
Math.Log(d) | ln(@d) | EF Core 8.0
Math.Log(a, newBase) | log(@newBase, @a) | EF Core 8.0
Math.Log2(x) | log2(@x) | EF Core 8.0
Math.Log10(d) | log10(@d) | EF Core 8.0
Math.Max(val1, val2) | max(@val1, @val2)
Math.Min(val1, val2) | min(@val1, @val2)
Math.Pow(x, y) | pow(@x, @y) | EF Core 8.0
Math.Round(d) | round(@d)
Math.Round(d, digits) | round(@d, @digits)
Math.Sign(d) | sign(@d) | EF Core 8.0
Math.Sin(a) | sin(@a) | EF Core 8.0
Math.Sinh(value) | sinh(@value) | EF Core 8.0
Math.Sqrt(d) | sqrt(@d) | EF Core 8.0
Math.Tan(a) | tan(@a) | EF Core 8.0
Math.Tanh(value) | tanh(@value) | EF Core 8.0
Math.Truncate(d) | trunc(@d) | EF Core 8.0

> [!TIP]
> In addition to the methods listed here, corresponding [generic math](/dotnet/standard/generics/math) implementations
> and [MathF](/dotnet/api/system.mathf) methods are also translated. For example, `Math.Sin`, `MathF.Sin`, `double.Sin`,
> and `float.Sin` all map to the `sin` function in SQL.

> [!TIP]
> SQL functions prefixed with *ef* are created by EF Core.
Expand Down
81 changes: 78 additions & 3 deletions entity-framework/core/what-is-new/ef-core-8.0/breaking-changes.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
---
title: Breaking changes in EF Core 8.0 (EF8) - EF Core
description: Complete list of breaking changes introduced in Entity Framework Core 8.0 (EF7)
description: Complete list of breaking changes introduced in Entity Framework Core 8.0 (EF8)
author: ajcvickers
ms.date: 12/13/2022
ms.date: 8/10/2023
uid: core/what-is-new/ef-core-8.0/breaking-changes
---

# Breaking changes in EF Core 8.0 (EF8)

This page will document API and behavior changes that have the potential to break existing applications updating to EF Core 8.0.
This page documents API and behavior changes that have the potential to break existing applications updating to EF Core 8.0.

## Summary

| **Breaking change** | **Impact** |
|:---------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| [SQL Server `date` and `time` now scaffold to .NET `DateOnly` and `TimeOnly`](#sqlserver-date-time-only) | Medium |
| [SQLite `Math` methods now translate to SQL](#sqlite-math) | Low |

## Medium-impact changes

Expand Down Expand Up @@ -60,3 +61,77 @@ It is recommended to react to this change by modifying your code to use the newl
public <#= code.Reference(clrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
<#
```

## Low-impact changes

<a name="sqlite-math"></a>

### SQLite `Math` methods now translate to SQL

[Tracking Issue #18843](https://github.com/dotnet/efcore/issues/18843)

#### Old Behavior

Previously only the Abs, Max, Min, and Round methods on `Math` were translated to SQL. All other members would be evaluated on the client if they appeared in the final Select expression of a query.

#### New behavior

In EF Core 8.0, all `Math` methods with corresponding [SQLite math functions](https://sqlite.org/lang_mathfunc.html) are translated to SQL.

These math functions have been enabled in the native SQLite library that we provide by default (through our dependency on the SQLitePCLRaw.bundle_e_sqlite3 NuGet package). They have also been enabled in the library provided by SQLitePCLRaw.bundle_e_sqlcipher. If you're using one of these libraries, your application should not be affected by this change.

There is a chance, however, that applications including the native SQLite library by other means may not enable the math functions. In these cases, the `Math` methods will be translated to SQL and encounter *no such function* errors when executed.

#### Why

SQLite added built-in math functions in version 3.35.0. Even though they're disabled by default, they've become pervasive enough that we decided to provide default translations for them in our EF Core SQLite provider.

We also collaborated with Eric Sink on the SQLitePCLRaw project to enable math functions in all of the native SQLite libraries provided as part of that project.

#### Mitigations

The simplest way to fix breaks is, when possible, to enable the math function is the native SQLite library by specifying the [SQLITE_ENABLE_MATH_FUNCTIONS](https://sqlite.org/compile.html#enable_math_functions) compile-time option.

If you don't control compilation of the native library, you can also fix breaks by create the functions yourself at runtime using the [Microsoft.Data.Sqlite](/dotnet/standard/data/sqlite/user-defined-functions) APIs.

```csharp
sqliteConnection
.CreateFunction<double, double, double>(
"pow",
Math.Pow,
isDeterministic: true);
```

Alternatively, you can force client-evaluation by splitting the Select expression into two parts separated by `AsEnumerable`.

```csharp
// Before
var query = dbContext.Cylinders
.Select(
c => new
{
Id = c.Id
// May throw "no such function: pow"
Volume = Math.PI * Math.Pow(c.Radius, 2) * c.Height
});

// After
var query = dbContext.Cylinders
// Select the properties you'll need from the database
.Select(
c => new
{
c.Id,
c.Radius,
c.Height
})
// Switch to client-eval
.AsEnumerable()
// Select the final results
.Select(
c => new
{
Id = c.Id,
Volume = Math.PI * Math.Pow(c.Radius, 2) * c.Height
});
```
Loading