You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The following C# application example with Entity Framework will throw an error on Babelfish intermittently depending on current time (and the presence of records in tab1 table):
usingMicrosoft.EntityFrameworkCore;publicenumMyEnum:byte{None=0,One=1,Two=2,}publicclassTab1{publicintId{get;set;}publicMyEnum?Col1{get;set;}}publicclassTestContext:DbContext{conststringconnStr="Server=192.168.178.58,1433;Initial Catalog=ef1;User ID=jdbc_user;Password=12345678;Trust Server Certificate=true";publicDbSet<Tab1>Tab1{get;set;}protectedoverridevoidOnConfiguring(DbContextOptionsBuilderoptions){options.UseSqlServer(connStr);}}classProgram{staticvoidMain(){usingvardb=newTestContext();boolexternalFlag=DateTime.Now.Minute%2==0;IQueryable<Tab1>query1=fromtindb.Tab1selectnewTab1{Id=t.Id,Col1=externalFlag?(t.Id>0?MyEnum.Two:null):null};Console.WriteLine(query1.ToList().Count);}}
> dotnet run
1
> dotnet run
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Int16' to type 'System.Byte'.
at Microsoft.Data.SqlClient.SqlBuffer.get_Byte()
at Microsoft.Data.SqlClient.SqlDataReader.GetByte(Int32 i)
at lambda_method3(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Program.Main() in C:\projects\postgres\dotnet\ef3\Program.cs:line 44
In this example when externalFlag is set, EF will generate the following SQL:
SELECT [t].[Id], CASEWHEN [t].[Id] >0THENCAST(2AStinyint)
ELSENULLENDAS [Col1]
FROM [Tab1] AS [t]
On MSSQL Col1 column is returned as tinyint, but on Babelfish it is returned as smallint. In EF/ADO.NET the tynyint DB type is mapped to byte C# type and smallint is mapped to short (reference). When records are read from a result-set there is no implicit conversion allowed between byte and short in either way.
The problem happens because tinyint in Babelfish is implemented as a DOMAIN so when implicit cast to tinyint happens - the base type smallint is used instead.
Besides CASE, the same problem can be reproduced with UNION:
create view view1 asselect id, col1 from tab1
union allselect43as id, nullas col1
The problem happens not only with null as col1, but also with varchar conversion like '' as col1 or '42' as col1.
As a workaround it is possible to use the explicit cast to tinyint, it is trivial to do it in static T-SQL, and not so trivial in Entity Framework queries (can be done with user-defined function mapping - 1, 2).
I wonder if it is feasible to re-implement the tinyint in Babelfish as a proper TYPE instead of a DOMAIN without breaking compatibility with existing DBs that use tinyint columns?
Version
BABEL_4_X_DEV (Default)
Extension
babelfishpg_common
Which flavor of Linux are you using when you see the bug?
Fedora
Relevant log output
No response
Code of Conduct
I agree to follow this project's Code of Conduct.
The text was updated successfully, but these errors were encountered:
We recently fixed similar bug around resultant data type / typmod of case expression. I will check with @Yvinayak07 whether that fix will resolve this issue.
I've checked that the change from #2931 does not fix this issue, but the new hook is called, so perhaps it can be modified to cover tinyint. If it is possible to also add a hook to cover UNION for tinyint - that would be great. There is currently no workaround to this problem without large scale changes to either client app (adding casts with user-defined function mapping to all queries) or to both app and DB (changing the column type to smallint in all tables).
What happened?
With the following table:
The following C# application example with Entity Framework will throw an error on Babelfish intermittently depending on current time (and the presence of records in
tab1
table):In this example when
externalFlag
is set, EF will generate the following SQL:On MSSQL
Col1
column is returned astinyint
, but on Babelfish it is returned assmallint
. In EF/ADO.NET thetynyint
DB type is mapped tobyte
C# type andsmallint
is mapped toshort
(reference). When records are read from a result-set there is no implicit conversion allowed betweenbyte
andshort
in either way.The problem happens because
tinyint
in Babelfish is implemented as a DOMAIN so when implicit cast totinyint
happens - the base typesmallint
is used instead.Besides
CASE
, the same problem can be reproduced withUNION
:The problem happens not only with
null as col1
, but also with varchar conversion like'' as col1
or'42' as col1
.As a workaround it is possible to use the explicit cast to
tinyint
, it is trivial to do it in static T-SQL, and not so trivial in Entity Framework queries (can be done with user-defined function mapping - 1, 2).I wonder if it is feasible to re-implement the
tinyint
in Babelfish as a properTYPE
instead of aDOMAIN
without breaking compatibility with existing DBs that usetinyint
columns?Version
BABEL_4_X_DEV (Default)
Extension
babelfishpg_common
Which flavor of Linux are you using when you see the bug?
Fedora
Relevant log output
No response
Code of Conduct
The text was updated successfully, but these errors were encountered: