-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Translate XOR, shift left, shift right #18952
Conversation
test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs
Outdated
Show resolved
Hide resolved
@@ -179,6 +179,9 @@ private SqlExpression ApplyTypeMappingOnLike(LikeExpression likeExpression) | |||
case ExpressionType.Coalesce: | |||
case ExpressionType.And: | |||
case ExpressionType.Or: | |||
case ExpressionType.ExclusiveOr: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid a bug trail, we need to get a report on typeMapping characteristics on each of these operator on different databases. What are supported types. What are corresponding result types. etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
edit: added MySQL info as well
XOR/AND/OR
On both SQL Server, PostgreSQL and MySQL, these always casts up to the wider integral operand (so TINYINT XOR BIGINT yields BIGINT). Regular arithmetic operators (e.g. Add) work the same way, all of the below return BIGINT:
SQL Server:
SELECT SQL_VARIANT_PROPERTY(CAST(8 AS SMALLINT) + CAST(1 AS BIGINT), 'BaseType');
SELECT SQL_VARIANT_PROPERTY(CAST(8 AS BIGINT) + CAST(1 AS SMALLINT), 'BaseType');
PostgreSQL:
SELECT pg_typeof(8::BIGINT + 1::SMALLINT);
SELECT pg_typeof(8::SMALLINT + 1::BIGINT);
MySQL:
CREATE TABLE types (tiny TINYINT, small SMALLINT, normal INT, big BIGINT);
INSERT INTO types (tiny, small, normal, big) VALUES (8, 8, 8, 8);
CREATE TEMPORARY TABLE typeof AS SELECT tiny + big FROM types AS col;
DESCRIBE typeof;
DROP TABLE typeof;
Both return BIGINT. Our type inference doesn't match this: we just call ExpressionExtensions.InferTypeMapping on both sides. Did you have this on your radar, should I open an issue? Not sure if there's anything to check on Sqlite with its lack of real types.
SHL/SHR
Not supported on SQL Server.
On PostgreSQL the operation predictably returns the same type as the left operand. The right side can be SMALLINT or INT but not BIGINT. Modified the inference to simply apply the default mapping on the right-hand operand. Sqlite supports SHL/SHR but again no real typing so...
On MySQL the operation behaves like an arithmetic operator, taking the wider operand type:
CREATE TABLE types (tiny TINYINT, small SMALLINT, normal INT, big BIGINT);
INSERT INTO types (tiny, small, normal, big) VALUES (8, 8, 8, 8);
CREATE TEMPORARY TABLE typeof AS SELECT tiny >> big FROM types AS col;
DESCRIBE typeof;
DROP TABLE typeof;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing that the mismatch above (arithmetic widening) doesn't actually manifest as a bug, because integer literals are identical, and even when sent as parameters there's implicit widening logic (either in the ADO.NET driver or in the database). But we may still want to fix this for correctness etc.
}, | ||
elementSorter: e => (e.e2.EmployeeID, e.o2.OrderID), | ||
entryCount: 3))).Message); | ||
await AssertQuery( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smitpatel this testing for translation failure (because of the XOR operator), although the name and purpose logic don't seem to fit - removed the throws assertion and made it into a positive test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type mapping inference is incorrect. TypeMapping inference needs to account for actual C# expression trees.
Tests should be written for following types for leftshift/rightshift s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64
And for exclusive OR - s_SByte, s_Int16, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Boolean
} | ||
break; | ||
|
||
case ExpressionType.LeftShift: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect change
src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs
Show resolved
Hide resolved
src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs
Show resolved
Hide resolved
test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs
Show resolved
Hide resolved
test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs
Show resolved
Hide resolved
test/EFCore.Sqlite.FunctionalTests/Query/NorthwindMiscellaneousQuerySqliteTest.cs
Show resolved
Hide resolved
Closing this for now. |
Closes #18795
Because it just had to be done.