diff --git a/src/EFCore.Ydb/src/Extensions/YdbServiceCollectionExtensions.cs b/src/EFCore.Ydb/src/Extensions/YdbServiceCollectionExtensions.cs index 7b511196..f74cdc31 100644 --- a/src/EFCore.Ydb/src/Extensions/YdbServiceCollectionExtensions.cs +++ b/src/EFCore.Ydb/src/Extensions/YdbServiceCollectionExtensions.cs @@ -42,10 +42,14 @@ public static IServiceCollection AddEntityFrameworkYdb(this IServiceCollection s .TryAdd() .TryAdd() + .TryAdd() .TryAdd() .TryAdd() .TryAdd() .TryAdd() +#pragma warning disable EF9002 + .TryAdd() +#pragma warning restore EF9002 .TryAdd() .TryAdd() .TryAdd() diff --git a/src/EFCore.Ydb/src/Query/Internal/Translators/YdbByteArrayMethodTranslator.cs b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbByteArrayMethodTranslator.cs new file mode 100644 index 00000000..f3e06b37 --- /dev/null +++ b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbByteArrayMethodTranslator.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using EntityFrameworkCore.Ydb.Utilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace EntityFrameworkCore.Ydb.Query.Internal.Translators; + +public class YdbByteArrayMethodTranslator : IMethodCallTranslator +{ + private readonly ISqlExpressionFactory _sqlExpressionFactory; + + public YdbByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) + => _sqlExpressionFactory = sqlExpressionFactory; + + private static MethodInfo Contains => typeof(Enumerable) + .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(m => m.Name == nameof(Enumerable.Contains)) + .Single(mi => mi.IsGenericMethod && + mi.GetGenericArguments().Length == 1 && + mi.GetParameters() + .Select(e => e.ParameterType) + .SequenceEqual( + [ + typeof(IEnumerable<>).MakeGenericType(mi.GetGenericArguments()[0]), + mi.GetGenericArguments()[0] + ] + ) + ); + + public virtual SqlExpression? Translate( + SqlExpression? instance, + MethodInfo method, + IReadOnlyList arguments, + IDiagnosticsLogger logger + ) + { + if (method.IsGenericMethod + && method.GetGenericMethodDefinition().Equals(Contains) + && arguments[0].Type == typeof(byte[])) + { + var source = arguments[0]; + + var value = arguments[1] is SqlConstantExpression constantValue + ? _sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value! }, source.TypeMapping) + : _sqlExpressionFactory.Function( + "ToBytes", + [arguments[1]], + nullable: false, + argumentsPropagateNullability: ArrayUtil.TrueArrays[1], + typeof(string)); + + return _sqlExpressionFactory.IsNotNull( + _sqlExpressionFactory.Function( + "FIND", + [source, value], + nullable: true, + argumentsPropagateNullability: ArrayUtil.FalseArrays[2], + typeof(int) + ) + ); + } + return null; + } +} diff --git a/src/EFCore.Ydb/src/Query/Internal/Translators/YdbDAteTimeMemberTranslator.cs b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbDAteTimeMemberTranslator.cs new file mode 100644 index 00000000..38eae3a4 --- /dev/null +++ b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbDAteTimeMemberTranslator.cs @@ -0,0 +1,116 @@ +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using EntityFrameworkCore.Ydb.Storage.Internal; +using EntityFrameworkCore.Ydb.Storage.Internal.Mapping; +using EntityFrameworkCore.Ydb.Utilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace EntityFrameworkCore.Ydb.Query.Internal.Translators; + +public class YdbDateTimeMemberTranslator : IMemberTranslator +{ + private readonly IRelationalTypeMappingSource _typeMappingSource; + private readonly YdbSqlExpressionFactory _sqlExpressionFactory; + private readonly RelationalTypeMapping _timestampMapping; + + public YdbDateTimeMemberTranslator( + IRelationalTypeMappingSource typeMappingSource, + YdbSqlExpressionFactory sqlExpressionFactory + ) + { + _typeMappingSource = typeMappingSource; + _timestampMapping = typeMappingSource.FindMapping(typeof(DateTime), "TimeStamp")!; + _sqlExpressionFactory = sqlExpressionFactory; + } + + public virtual SqlExpression? Translate( + SqlExpression? instance, + MemberInfo member, + Type returnType, + IDiagnosticsLogger logger + ) + { + var declaringType = member.DeclaringType; + + if (declaringType == typeof(TimeOnly)) + { + throw new InvalidOperationException("Ydb doesn't support TimeOnly right now"); + } + + if (declaringType != typeof(DateTime) && declaringType != typeof(DateOnly)) + { + return null; + } + + if (member.Name == nameof(DateTime.Date)) + { + switch (instance) + { + case { TypeMapping: YdbDateTimeTypeMapping }: + case { Type: var type } when type == typeof(DateTime): + return _sqlExpressionFactory.Convert( + _sqlExpressionFactory.Convert(instance, typeof(DateOnly)), + typeof(DateTime) + ); + case { TypeMapping: YdbDateOnlyTypeMapping }: + case { Type: var type } when type == typeof(DateOnly): + return instance; + default: + return null; + } + } + + return member.Name switch + { + // TODO: Find out how to add + // nameof(DateTime.Now) => ???, + // nameof(DateTime.Today) => ??? + + nameof(DateTime.UtcNow) => UtcNow(), + + nameof(DateTime.Year) => DatePart(instance!, "GetYear"), + nameof(DateTime.Month) => DatePart(instance!, "GetMonth"), + nameof(DateTime.Day) => DatePart(instance!, "GetDayOfMonth"), + nameof(DateTime.Hour) => DatePart(instance!, "GetHour"), + nameof(DateTime.Minute) => DatePart(instance!, "GetMinute"), + nameof(DateTime.Second) => DatePart(instance!, "GetSecond"), + nameof(DateTime.Millisecond) => DatePart(instance!, "GetMillisecondOfSecond"), + + nameof(DateTime.DayOfYear) => DatePart(instance!, "GetDayOfYear"), + nameof(DateTime.DayOfWeek) => DatePart(instance!, "GetDayOfWeek"), + + // TODO: Research if it's possible to implement + nameof(DateTime.Ticks) => null, + _ => null + }; + + SqlExpression UtcNow() + => _sqlExpressionFactory.Function( + "CurrentUtc" + returnType.Name == "DateOnly" ? "Date" : returnType.Name, + [], + nullable: false, + argumentsPropagateNullability: ArrayUtil.TrueArrays[0], + returnType, + _typeMappingSource.FindMapping(returnType) + ); + } + + private SqlExpression? DatePart(SqlExpression instance, string partName) + { + var result = _sqlExpressionFactory.Function( + $"DateTime::{partName}", + [instance], + nullable: true, + argumentsPropagateNullability: ArrayUtil.TrueArrays[1], + typeof(short) // Doesn't matter because we cast it to int in next line anyway + ); + + return _sqlExpressionFactory.Convert(result, typeof(int)); + } +} diff --git a/src/EFCore.Ydb/src/Query/Internal/Translators/YdbDateTimeMethodTranslator.cs b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbDateTimeMethodTranslator.cs new file mode 100644 index 00000000..111d3884 --- /dev/null +++ b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbDateTimeMethodTranslator.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using EntityFrameworkCore.Ydb.Utilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.Storage; + +namespace EntityFrameworkCore.Ydb.Query.Internal.Translators; + +public class YdbDateTimeMethodTranslator : IMethodCallTranslator +{ + private static readonly Dictionary MethodInfoDatePartMapping = new() + { + { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddYears), [typeof(int)])!, " Years" }, + { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddMonths), [typeof(int)])!, " Months" }, + { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddDays), [typeof(int)])!, " Days" }, + + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddYears), [typeof(int)])!, "Years" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMonths), [typeof(int)])!, "Months" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddDays), [typeof(double)])!, "Days" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddHours), [typeof(double)])!, "Hours" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMinutes), [typeof(double)])!, "Mins" }, + { typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddSeconds), [typeof(double)])!, "Secs" }, + + { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddYears), [typeof(int)])!, "Years" }, + { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMonths), [typeof(int)])!, "Months" }, + { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddDays), [typeof(double)])!, "Days" }, + { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddHours), [typeof(double)])!, "Hours" }, + { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMinutes), [typeof(double)])!, "Mins" }, + { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddSeconds), [typeof(double)])!, "Secs" }, + }; + + private readonly YdbSqlExpressionFactory _sqlExpressionFactory; + + public YdbDateTimeMethodTranslator(YdbSqlExpressionFactory sqlExpressionFactory) + { + _sqlExpressionFactory = sqlExpressionFactory; + } + + + public virtual SqlExpression? Translate( + SqlExpression? instance, + MethodInfo method, + IReadOnlyList arguments, + IDiagnosticsLogger logger + ) => TranslateDatePart(instance, method, arguments); + + private SqlExpression? TranslateDatePart( + SqlExpression? instance, + MethodInfo method, + IReadOnlyList arguments + ) + { + if ( + instance is not null + && MethodInfoDatePartMapping.TryGetValue(method, out var datePart)) + { + var shiftDatePartFunction = _sqlExpressionFactory.Function( + "DateTime::Shift" + datePart, + [instance, arguments[0]], + nullable: true, + ArrayUtil.TrueArrays[2], + returnType: typeof(DateTime) + ); + + return _sqlExpressionFactory.Function( + "DateTime::MakeDate", + arguments: [shiftDatePartFunction], + nullable: true, + ArrayUtil.TrueArrays[1], + returnType: typeof(DateTime) + ); + } + + return null; + } +} diff --git a/src/EFCore.Ydb/src/Query/Internal/Translators/YdbMathTranslator.cs b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbMathTranslator.cs new file mode 100644 index 00000000..d8f99f3a --- /dev/null +++ b/src/EFCore.Ydb/src/Query/Internal/Translators/YdbMathTranslator.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using EntityFrameworkCore.Ydb.Utilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using ExpressionExtensions = Microsoft.EntityFrameworkCore.Query.ExpressionExtensions; + +namespace EntityFrameworkCore.Ydb.Query.Internal.Translators; + +public class YdbMathTranslator : IMethodCallTranslator +{ + private static readonly Dictionary SupportedMethods = new() + { + { typeof(Math).GetMethod(nameof(Math.Abs), [typeof(double)])!, "Abs" }, + { typeof(Math).GetMethod(nameof(Math.Abs), [typeof(float)])!, "Abs" }, + { typeof(Math).GetMethod(nameof(Math.Abs), [typeof(int)])!, "Abs" }, + { typeof(Math).GetMethod(nameof(Math.Abs), [typeof(long)])!, "Abs" }, + { typeof(Math).GetMethod(nameof(Math.Abs), [typeof(sbyte)])!, "Abs" }, + { typeof(Math).GetMethod(nameof(Math.Abs), [typeof(short)])!, "Abs" }, + { typeof(Math).GetMethod(nameof(Math.Acos), [typeof(double)])!, "Acos" }, + { typeof(Math).GetMethod(nameof(Math.Acosh), [typeof(double)])!, "Acosh" }, + { typeof(Math).GetMethod(nameof(Math.Asin), [typeof(double)])!, "Asin" }, + { typeof(Math).GetMethod(nameof(Math.Asinh), [typeof(double)])!, "Asinh" }, + { typeof(Math).GetMethod(nameof(Math.Atan), [typeof(double)])!, "Atan" }, + { typeof(Math).GetMethod(nameof(Math.Atan2), [typeof(double), typeof(double)])!, "Atan2" }, + { typeof(Math).GetMethod(nameof(Math.Atanh), [typeof(double)])!, "Atanh" }, + { typeof(Math).GetMethod(nameof(Math.Ceiling), [typeof(double)])!, "Ceil" }, + { typeof(Math).GetMethod(nameof(Math.Cos), [typeof(double)])!, "Cos" }, + { typeof(Math).GetMethod(nameof(Math.Cosh), [typeof(double)])!, "Cosh" }, + { typeof(Math).GetMethod(nameof(Math.Exp), [typeof(double)])!, "Exp" }, + { typeof(Math).GetMethod(nameof(Math.Floor), [typeof(double)])!, "Floor" }, + { typeof(Math).GetMethod(nameof(Math.Log), [typeof(double)])!, "Log" }, + { typeof(Math).GetMethod(nameof(Math.Log2), [typeof(double)])!, "Log2" }, + { typeof(Math).GetMethod(nameof(Math.Log10), [typeof(double)])!, "Log10" }, + { typeof(Math).GetMethod(nameof(Math.Pow), [typeof(double), typeof(double)])!, "Pow" }, + { typeof(Math).GetMethod(nameof(Math.Round), [typeof(double)])!, "Round" }, + { typeof(Math).GetMethod(nameof(Math.Sign), [typeof(double)])!, "Sign" }, + { typeof(Math).GetMethod(nameof(Math.Sign), [typeof(float)])!, "Sign" }, + { typeof(Math).GetMethod(nameof(Math.Sign), [typeof(long)])!, "Sign" }, + { typeof(Math).GetMethod(nameof(Math.Sign), [typeof(sbyte)])!, "Sign" }, + { typeof(Math).GetMethod(nameof(Math.Sign), [typeof(short)])!, "Sign" }, + { typeof(Math).GetMethod(nameof(Math.Sin), [typeof(double)])!, "Sin" }, + { typeof(Math).GetMethod(nameof(Math.Sinh), [typeof(double)])!, "Sinh" }, + { typeof(Math).GetMethod(nameof(Math.Sqrt), [typeof(double)])!, "Sqrt" }, + { typeof(Math).GetMethod(nameof(Math.Tan), [typeof(double)])!, "Tan" }, + { typeof(Math).GetMethod(nameof(Math.Tanh), [typeof(double)])!, "Tanh" }, + { typeof(Math).GetMethod(nameof(Math.Truncate), [typeof(double)])!, "Trunc" }, + { typeof(MathF).GetMethod(nameof(MathF.Acos), [typeof(float)])!, "Acos" }, + { typeof(MathF).GetMethod(nameof(MathF.Acosh), [typeof(float)])!, "Acosh" }, + { typeof(MathF).GetMethod(nameof(MathF.Asin), [typeof(float)])!, "Asin" }, + { typeof(MathF).GetMethod(nameof(MathF.Asinh), [typeof(float)])!, "Asinh" }, + { typeof(MathF).GetMethod(nameof(MathF.Atan), [typeof(float)])!, "Atan" }, + { typeof(MathF).GetMethod(nameof(MathF.Atan2), [typeof(float), typeof(float)])!, "Atan2" }, + { typeof(MathF).GetMethod(nameof(MathF.Atanh), [typeof(float)])!, "Atanh" }, + { typeof(MathF).GetMethod(nameof(MathF.Ceiling), [typeof(float)])!, "Ceil" }, + { typeof(MathF).GetMethod(nameof(MathF.Cos), [typeof(float)])!, "Cos" }, + { typeof(MathF).GetMethod(nameof(MathF.Cosh), [typeof(float)])!, "Cosh" }, + { typeof(MathF).GetMethod(nameof(MathF.Exp), [typeof(float)])!, "Exp" }, + { typeof(MathF).GetMethod(nameof(MathF.Floor), [typeof(float)])!, "Floor" }, + { typeof(MathF).GetMethod(nameof(MathF.Log), [typeof(float)])!, "Log" }, + { typeof(MathF).GetMethod(nameof(MathF.Log10), [typeof(float)])!, "Log10" }, + { typeof(MathF).GetMethod(nameof(MathF.Log2), [typeof(float)])!, "Log2" }, + { typeof(MathF).GetMethod(nameof(MathF.Pow), [typeof(float), typeof(float)])!, "Pow" }, + { typeof(MathF).GetMethod(nameof(MathF.Round), [typeof(float)])!, "Round" }, + { typeof(MathF).GetMethod(nameof(MathF.Sin), [typeof(float)])!, "Sin" }, + { typeof(MathF).GetMethod(nameof(MathF.Sinh), [typeof(float)])!, "Sinh" }, + { typeof(MathF).GetMethod(nameof(MathF.Sqrt), [typeof(float)])!, "Sqrt" }, + { typeof(MathF).GetMethod(nameof(MathF.Tan), [typeof(float)])!, "Tan" }, + { typeof(MathF).GetMethod(nameof(MathF.Tanh), [typeof(float)])!, "Tanh" }, + { typeof(MathF).GetMethod(nameof(MathF.Truncate), [typeof(float)])!, "Trunc" }, + }; + + private static readonly List _roundWithDecimalMethods = + [ + typeof(Math).GetMethod(nameof(Math.Round), [typeof(double), typeof(int)])!, + typeof(MathF).GetMethod(nameof(MathF.Round), [typeof(float), typeof(int)])! + ]; + + private static readonly List _logWithBaseMethods = + [ + typeof(Math).GetMethod(nameof(Math.Log), [typeof(double), typeof(double)])!, + typeof(MathF).GetMethod(nameof(MathF.Log), [typeof(float), typeof(float)])! + ]; + + private readonly ISqlExpressionFactory _sqlExpressionFactory; + + public YdbMathTranslator(ISqlExpressionFactory sqlExpressionFactory) + => _sqlExpressionFactory = sqlExpressionFactory; + + public virtual SqlExpression? Translate( + SqlExpression? instance, + MethodInfo method, + IReadOnlyList arguments, + IDiagnosticsLogger logger + ) + { + if (SupportedMethods.TryGetValue(method, out var sqlFunctionName)) + { + var typeMapping = ExpressionExtensions.InferTypeMapping(arguments.ToArray()); + var newArguments = arguments + .Select(a => _sqlExpressionFactory.ApplyTypeMapping(a, typeMapping)) + .ToList(); + + return _sqlExpressionFactory.Function( + "Math::" + sqlFunctionName, + newArguments, + nullable: true, + argumentsPropagateNullability: newArguments.Select(_ => true).ToList(), + method.ReturnType, + typeMapping + ); + } + + if (_roundWithDecimalMethods.Contains(method)) + { + return _sqlExpressionFactory.Function( + "Math::Round", + arguments, + nullable: true, + argumentsPropagateNullability: ArrayUtil.TrueArrays[2], + method.ReturnType, + arguments[0].TypeMapping); + } + + return null; + } +} diff --git a/src/EFCore.Ydb/src/Query/Internal/YdbMemberTranslatorProvider.cs b/src/EFCore.Ydb/src/Query/Internal/YdbMemberTranslatorProvider.cs index 965d9fef..6e045a65 100644 --- a/src/EFCore.Ydb/src/Query/Internal/YdbMemberTranslatorProvider.cs +++ b/src/EFCore.Ydb/src/Query/Internal/YdbMemberTranslatorProvider.cs @@ -1,15 +1,21 @@ using EntityFrameworkCore.Ydb.Query.Internal.Translators; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Storage; namespace EntityFrameworkCore.Ydb.Query.Internal; public sealed class YdbMemberTranslatorProvider : RelationalMemberTranslatorProvider { - public YdbMemberTranslatorProvider(RelationalMemberTranslatorProviderDependencies dependencies) : base(dependencies) + public YdbMemberTranslatorProvider( + RelationalMemberTranslatorProviderDependencies dependencies, + IRelationalTypeMappingSource typeMappingSource + ) : base(dependencies) { + var sqlExpressionFactory = (YdbSqlExpressionFactory)dependencies.SqlExpressionFactory; + AddTranslators( [ - new StubTranslator() + new YdbDateTimeMemberTranslator(typeMappingSource, sqlExpressionFactory), ] ); } diff --git a/src/EFCore.Ydb/src/Query/Internal/YdbMethodCallTranslatorProvider.cs b/src/EFCore.Ydb/src/Query/Internal/YdbMethodCallTranslatorProvider.cs index 800f1a41..68782d0b 100644 --- a/src/EFCore.Ydb/src/Query/Internal/YdbMethodCallTranslatorProvider.cs +++ b/src/EFCore.Ydb/src/Query/Internal/YdbMethodCallTranslatorProvider.cs @@ -5,13 +5,16 @@ namespace EntityFrameworkCore.Ydb.Query.Internal; public sealed class YdbMethodCallTranslatorProvider : RelationalMethodCallTranslatorProvider { - public YdbMethodCallTranslatorProvider( - RelationalMethodCallTranslatorProviderDependencies dependencies - ) : base(dependencies) + public YdbMethodCallTranslatorProvider(RelationalMethodCallTranslatorProviderDependencies dependencies) : + base(dependencies) { + var sqlExpressionFactory = (YdbSqlExpressionFactory)dependencies.SqlExpressionFactory; + AddTranslators( [ - new StubTranslator() + new YdbDateTimeMethodTranslator(sqlExpressionFactory), + new YdbMathTranslator(sqlExpressionFactory), + new YdbByteArrayMethodTranslator(sqlExpressionFactory), ] ); } diff --git a/src/EFCore.Ydb/src/Query/Internal/YdbQuerySqlGenerator.cs b/src/EFCore.Ydb/src/Query/Internal/YdbQuerySqlGenerator.cs index 719b5fc4..b04c92e1 100644 --- a/src/EFCore.Ydb/src/Query/Internal/YdbQuerySqlGenerator.cs +++ b/src/EFCore.Ydb/src/Query/Internal/YdbQuerySqlGenerator.cs @@ -264,4 +264,60 @@ protected override Expression VisitJsonScalar(JsonScalarExpression jsonScalarExp Sql.Append("\")"); return jsonScalarExpression; } + + protected override Expression VisitProjection(ProjectionExpression projectionExpression) + { + Visit(projectionExpression.Expression); + + if (projectionExpression.Alias != string.Empty) + { + Sql + .Append(AliasSeparator) + .Append(SqlGenerationHelper.DelimitIdentifier(projectionExpression.Alias)); + } + + return projectionExpression; + } + + protected override Expression VisitCase(CaseExpression caseExpression) + { + Sql.Append("CASE"); + + if (caseExpression.Operand != null) + { + Sql.Append(" "); + Visit(caseExpression.Operand); + } + + using (Sql.Indent()) + { + foreach (var whenClause in caseExpression.WhenClauses) + { + Sql + .AppendLine() + .Append("WHEN "); + Visit(whenClause.Test); + Sql.Append(" THEN "); + Visit(whenClause.Result); + } + + Sql + .AppendLine() + .Append("ELSE "); + if (caseExpression.ElseResult != null) + { + Visit(caseExpression.ElseResult); + } + else + { + Sql.Append("NULL"); + } + } + + Sql + .AppendLine() + .Append("END"); + + return caseExpression; + } } diff --git a/src/EFCore.Ydb/src/Query/Internal/YdbSqlAliasManager.cs b/src/EFCore.Ydb/src/Query/Internal/YdbSqlAliasManager.cs new file mode 100644 index 00000000..ed0bcb7d --- /dev/null +++ b/src/EFCore.Ydb/src/Query/Internal/YdbSqlAliasManager.cs @@ -0,0 +1,161 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; + +namespace EntityFrameworkCore.Ydb.Query.Internal; + +public class YdbSqlAliasManager : SqlAliasManager +{ + public override Expression PostprocessAliases(Expression expression) + { + var aliasRewriter = new AliasRewriter(); + return base.PostprocessAliases(aliasRewriter.Visit(expression)); + } + + // TODO: Temporary solution to solve following problem (https://t.me/ydb_ru/28649) + // Doesn't work in all cases. Should be improved + private sealed class AliasRewriter : ExpressionVisitor + { + private bool isRootSelect = true; + + [return: NotNullIfNotNull("node")] + public override Expression? Visit(Expression? node) => node switch + { + ShapedQueryExpression shapedQuery => shapedQuery.UpdateQueryExpression(Visit(shapedQuery.QueryExpression)), + SelectExpression selectExpression => VisitSelect(selectExpression), + + _ => base.Visit(node) + }; + + protected override Expression VisitExtension(Expression node) => node switch + { + ShapedQueryExpression shapedQuery => shapedQuery.UpdateQueryExpression(Visit(shapedQuery.QueryExpression)), + SelectExpression selectExpression => VisitSelect(selectExpression), + _ => base.VisitExtension(node) + }; + + private Expression VisitSelect(SelectExpression selectExpression) + { + var newProjections = AdjustAliases(selectExpression.Projection, isRootSelect); + isRootSelect = false; + + var newTables = new List(selectExpression.Tables.Count); + foreach (var table in selectExpression.Tables) + { + // We cannot change type in current expressionVisitor. Only adjust aliases + newTables.Add((Visit(table) as TableExpressionBase)!); + } + + var news = selectExpression.Update( + tables: newTables, + predicate: selectExpression.Predicate, + groupBy: selectExpression.GroupBy, + having: selectExpression.Having, + projections: newProjections, + orderings: selectExpression.Orderings, + offset: selectExpression.Offset, + limit: selectExpression.Limit + ); + return news; + } + + private Expression VisitTableBase(TableExpressionBase tableExpression) + => tableExpression switch + { + TableExpression t => VisitTable(t), + SelectExpression selectExpression => VisitSelect(selectExpression), + LeftJoinExpression leftJoinExpression => VisitLeftJoin(leftJoinExpression), + _ => Visit(tableExpression) + }; + + private Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression) + => leftJoinExpression.Update( + (VisitTableBase(leftJoinExpression.Table) as TableExpressionBase)!, + leftJoinExpression.JoinPredicate + ); + + private static Expression VisitTable(TableExpressionBase tableExpression) => tableExpression; + + private IReadOnlyList AdjustAliases( + IReadOnlyList projections, + bool isRoot + ) + { + var newProjections = new ProjectionExpression[projections.Count]; + + if (isRoot) + { + for (var i = 0; i < projections.Count; i++) + { + var currentProjection = projections[i]; + if (currentProjection.Expression is not ColumnExpression columnExpression) + { + newProjections[i] = currentProjection; + } + else + { + newProjections[i] = + currentProjection.Alias == columnExpression.Name + ? new ProjectionExpression(currentProjection.Expression, string.Empty) + : currentProjection; + } + } + + return newProjections; + } + + var knownAliases = new Dictionary(); + var isTrueAlias = new bool[projections.Count]; + + for (var i = 0; i < projections.Count; i++) + { + if (projections[i].Alias != string.Empty) + { + if (projections[i].Expression is ColumnExpression columnExpression && + columnExpression.Name == projections[i].Alias) + { + isTrueAlias[i] = false; + knownAliases.TryAdd(projections[i].Alias, i); + } + else + { + isTrueAlias[i] = true; + knownAliases[projections[i].Alias] = i; + } + } + else + { + isTrueAlias[i] = false; + } + } + + for (var i = 0; i < projections.Count; i++) + { + if (isTrueAlias[i]) + { + newProjections[i] = projections[i]; + continue; + } + + var currentProjection = projections[i]; + int? key = knownAliases.TryGetValue(currentProjection.Alias, out var aliasPosition) + ? aliasPosition + : null; + + if (key == i) + { + newProjections[i] = currentProjection; + } + else + { + newProjections[i] = + new ProjectionExpression(currentProjection.Expression, alias: string.Empty); + } + } + + return newProjections; + } + } +} diff --git a/src/EFCore.Ydb/src/Query/Internal/YdbSqlAliasManagerFactory.cs b/src/EFCore.Ydb/src/Query/Internal/YdbSqlAliasManagerFactory.cs new file mode 100644 index 00000000..8ddaecdd --- /dev/null +++ b/src/EFCore.Ydb/src/Query/Internal/YdbSqlAliasManagerFactory.cs @@ -0,0 +1,11 @@ +using System.Diagnostics.CodeAnalysis; +using Microsoft.EntityFrameworkCore.Query; + +namespace EntityFrameworkCore.Ydb.Query.Internal; + +[Experimental("EF9002")] +public class YdbSqlAliasManagerFactory : ISqlAliasManagerFactory +{ + public SqlAliasManager Create() + => new YdbSqlAliasManager(); +} diff --git a/src/EFCore.Ydb/src/Query/Internal/YdbSqlTranslatingExpressionVisitor.cs b/src/EFCore.Ydb/src/Query/Internal/YdbSqlTranslatingExpressionVisitor.cs index 8f56eb74..e4113508 100644 --- a/src/EFCore.Ydb/src/Query/Internal/YdbSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Ydb/src/Query/Internal/YdbSqlTranslatingExpressionVisitor.cs @@ -161,7 +161,7 @@ private bool TryTranslateStartsEndsWithContains( var substringArguments = new SqlExpression[3]; substringArguments[0] = translatedInstance; substringArguments[2] = _sqlExpressionFactory.Function( - "len", + "LENGTH", [translatedPattern], nullable: true, argumentsPropagateNullability: [true], @@ -176,14 +176,14 @@ private bool TryTranslateStartsEndsWithContains( { substringArguments[1] = _sqlExpressionFactory.Subtract( _sqlExpressionFactory.Function( - "len", + "LENGTH", [translatedInstance], nullable: true, argumentsPropagateNullability: [true], typeof(int) ), _sqlExpressionFactory.Function( - "len", + "LENGTH", [translatedPattern], nullable: true, argumentsPropagateNullability: [true], @@ -193,7 +193,7 @@ private bool TryTranslateStartsEndsWithContains( } var substringFunction = _sqlExpressionFactory.Function( - "substring", + "SUBSTRING", substringArguments, nullable: true, argumentsPropagateNullability: [true, false, false], diff --git a/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbDateOnlyTypeMapping.cs b/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbDateOnlyTypeMapping.cs new file mode 100644 index 00000000..47c0ef7b --- /dev/null +++ b/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbDateOnlyTypeMapping.cs @@ -0,0 +1,37 @@ +using System; +using System.Data; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Json; + +namespace EntityFrameworkCore.Ydb.Storage.Internal.Mapping; + +// TODO: Await DateOnly support in Ydb.Sdk +public class YdbDateOnlyTypeMapping : RelationalTypeMapping +{ + private const string DateOnlyFormatConst = "{0:yyyy-MM-dd}"; + + public YdbDateOnlyTypeMapping(string storeType) + : base( + new RelationalTypeMappingParameters( + new CoreTypeMappingParameters(typeof(DateOnly)), + storeType, + StoreTypePostfix.None, + System.Data.DbType.Date + ) + ) + { + } + + protected YdbDateOnlyTypeMapping(RelationalTypeMappingParameters parameters) : base(parameters) + { + } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new YdbDateOnlyTypeMapping(parameters); + + protected override string GenerateNonNullSqlLiteral(object value) + { + var dateOnly = (DateOnly)value; + return $"Date('{dateOnly.ToString(DateOnlyFormatConst)}')"; + } +} diff --git a/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbDateTimeTypeMapping.cs b/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbDateTimeTypeMapping.cs new file mode 100644 index 00000000..85629cb4 --- /dev/null +++ b/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbDateTimeTypeMapping.cs @@ -0,0 +1,28 @@ +using System; +using System.Data; +using Microsoft.EntityFrameworkCore.Storage; + +namespace EntityFrameworkCore.Ydb.Storage.Internal.Mapping; + +public class YdbDateTimeTypeMapping : DateTimeTypeMapping +{ + private const string DateTimeFormatConst = @"{0:yyyy-MM-dd HH\:mm\:ss.fffffff}"; + + private string StoreTypeLiteral { get; } + + public YdbDateTimeTypeMapping( + string storeType, + DbType? dbType, + Type clrType + ) : base(storeType, dbType) + { + StoreTypeLiteral = storeType; + } + + protected YdbDateTimeTypeMapping(RelationalTypeMappingParameters parameters) : base(parameters) + { + } + + protected override string SqlLiteralFormatString + => "CAST('" + DateTimeFormatConst + $"' AS {StoreTypeLiteral})"; +} diff --git a/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbTextTypeMapping.cs b/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbTextTypeMapping.cs new file mode 100644 index 00000000..ffecd91a --- /dev/null +++ b/src/EFCore.Ydb/src/Storage/Internal/Mapping/YdbTextTypeMapping.cs @@ -0,0 +1,37 @@ +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Json; + +namespace EntityFrameworkCore.Ydb.Storage.Internal.Mapping; + +public class YdbTextTypeMapping : RelationalTypeMapping +{ + public static YdbTextTypeMapping Default { get; } = new("Text"); + + public YdbTextTypeMapping(string storeType) + : base( + new RelationalTypeMappingParameters( + new CoreTypeMappingParameters( + typeof(string), + jsonValueReaderWriter: JsonStringReaderWriter.Instance + ), + storeType: storeType, + storeTypePostfix: StoreTypePostfix.None, + dbType: System.Data.DbType.String, + unicode: true + ) + ) + { + } + + protected YdbTextTypeMapping(RelationalTypeMappingParameters parameters) + : base(parameters) + { + } + + protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters) + => new YdbTextTypeMapping(parameters); + + protected virtual string EscapeSqlLiteral(string literal) => literal.Replace("'", "\\'"); + + protected override string GenerateNonNullSqlLiteral(object value) => $"'{EscapeSqlLiteral((string)value)}'u"; +} diff --git a/src/EFCore.Ydb/src/Storage/Internal/YdbExecutionStrategy.cs b/src/EFCore.Ydb/src/Storage/Internal/YdbExecutionStrategy.cs new file mode 100644 index 00000000..46cea9ed --- /dev/null +++ b/src/EFCore.Ydb/src/Storage/Internal/YdbExecutionStrategy.cs @@ -0,0 +1,12 @@ +using System; +using Microsoft.EntityFrameworkCore.Storage; +using Ydb.Sdk.Ado; + +namespace EntityFrameworkCore.Ydb.Storage.Internal; + +public class YdbExecutionStrategy(ExecutionStrategyDependencies dependencies) + : ExecutionStrategy(dependencies, maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(10)) // TODO User settings +{ + protected override bool ShouldRetryOn(Exception exception) + => exception is YdbException { IsTransient: true }; +} diff --git a/src/EFCore.Ydb/src/Storage/Internal/YdbExecutionStrategyFactory.cs b/src/EFCore.Ydb/src/Storage/Internal/YdbExecutionStrategyFactory.cs new file mode 100644 index 00000000..d9c3a1f2 --- /dev/null +++ b/src/EFCore.Ydb/src/Storage/Internal/YdbExecutionStrategyFactory.cs @@ -0,0 +1,10 @@ +using Microsoft.EntityFrameworkCore.Storage; + +namespace EntityFrameworkCore.Ydb.Storage.Internal; + +public class YdbExecutionStrategyFactory(ExecutionStrategyDependencies dependencies) + : RelationalExecutionStrategyFactory(dependencies) +{ + protected override IExecutionStrategy CreateDefaultStrategy(ExecutionStrategyDependencies dependencies) + => new YdbExecutionStrategy(dependencies); +} diff --git a/src/EFCore.Ydb/src/Storage/Internal/YdbTypeMappingSource.cs b/src/EFCore.Ydb/src/Storage/Internal/YdbTypeMappingSource.cs index 67e11beb..7f5dbee1 100644 --- a/src/EFCore.Ydb/src/Storage/Internal/YdbTypeMappingSource.cs +++ b/src/EFCore.Ydb/src/Storage/Internal/YdbTypeMappingSource.cs @@ -32,14 +32,15 @@ RelationalTypeMappingSourceDependencies relationalDependencies private static readonly YdbDecimalTypeMapping Decimal = new(typeof(decimal)); - private static readonly StringTypeMapping Text = new("Text", DbType.String); + private static readonly YdbTextTypeMapping Text = YdbTextTypeMapping.Default; private static readonly YdbBytesTypeMapping Bytes = YdbBytesTypeMapping.Default; - private static readonly YdbJsonTypeMapping Json = new("Json", typeof(JsonElement), DbType.String); + private static readonly YdbJsonTypeMapping Json = new("Json", typeof(JsonElement), null); - private static readonly DateOnlyTypeMapping Date = new("Date"); - private static readonly DateTimeTypeMapping DateTime = new("Datetime"); - private static readonly DateTimeTypeMapping Timestamp = new("Timestamp"); - private static readonly TimeSpanTypeMapping Interval = new("Interval"); + private static readonly YdbDateOnlyTypeMapping Date = new("Date"); + private static readonly DateTimeTypeMapping DateTime = new("DateTime"); + private static readonly YdbDateTimeTypeMapping Timestamp = new("Timestamp", DbType.DateTime, typeof(DateTime)); + // TODO: Await interval in Ydb.Sdk + private static readonly TimeSpanTypeMapping Interval = new("Interval", DbType.Object); #endregion diff --git a/src/EFCore.Ydb/src/Update/Internal/YdbModificationCommandBatch.cs b/src/EFCore.Ydb/src/Update/Internal/YdbModificationCommandBatch.cs index b64da9d9..9d16d101 100644 --- a/src/EFCore.Ydb/src/Update/Internal/YdbModificationCommandBatch.cs +++ b/src/EFCore.Ydb/src/Update/Internal/YdbModificationCommandBatch.cs @@ -3,6 +3,5 @@ namespace EntityFrameworkCore.Ydb.Update.Internal; public class YdbModificationCommandBatch( - ModificationCommandBatchFactoryDependencies dependencies, - int? maxBatchSize = null -) : AffectedCountModificationCommandBatch(dependencies, maxBatchSize); + ModificationCommandBatchFactoryDependencies dependencies +) : AffectedCountModificationCommandBatch(dependencies, 100 /* Temporary solve */); diff --git a/src/EFCore.Ydb/src/Update/Internal/YdbUpdateSqlGenerator.cs b/src/EFCore.Ydb/src/Update/Internal/YdbUpdateSqlGenerator.cs index ee819ce0..d1c8c8bf 100644 --- a/src/EFCore.Ydb/src/Update/Internal/YdbUpdateSqlGenerator.cs +++ b/src/EFCore.Ydb/src/Update/Internal/YdbUpdateSqlGenerator.cs @@ -142,10 +142,12 @@ protected override void AppendReturningClause( commandStringBuilder .AppendLine() .Append("RETURNING "); - foreach (var operation in operations) - { - SqlGenerationHelper.DelimitIdentifier(commandStringBuilder, operation.ColumnName); - } + + commandStringBuilder.AppendJoin( + ',', + operations + .Select(operation => SqlGenerationHelper.DelimitIdentifier(operation.ColumnName)) + ); } public override string GenerateNextSequenceValueOperation(string name, string? schema) diff --git a/src/EFCore.Ydb/src/Utilities/ArrayUtil.cs b/src/EFCore.Ydb/src/Utilities/ArrayUtil.cs index e2d3fd09..e505028a 100644 --- a/src/EFCore.Ydb/src/Utilities/ArrayUtil.cs +++ b/src/EFCore.Ydb/src/Utilities/ArrayUtil.cs @@ -9,4 +9,12 @@ internal static class ArrayUtil [false, false], [false, false, false] ]; + + internal static readonly bool[][] TrueArrays = + [ + [], + [true], + [true, true], + [true, true, true] + ]; } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/ComplexTypeBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesYdbTest.cs similarity index 99% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/ComplexTypeBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesYdbTest.cs index ca59b2b9..2b104046 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/ComplexTypeBulkUpdatesYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesYdbTest.cs @@ -4,7 +4,7 @@ using Xunit; using Xunit.Abstractions; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.BulkUpdates; +namespace EntityFrameworkCore.Ydb.FunctionalTests.BulkUpdates; #pragma warning disable xUnit1000 internal class ComplexTypeBulkUpdatesYdbTest( diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NonSharedModelBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesYdbTest.cs similarity index 84% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NonSharedModelBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesYdbTest.cs index 25d37a79..caac77f3 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NonSharedModelBulkUpdatesYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.BulkUpdates; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.BulkUpdates; +namespace EntityFrameworkCore.Ydb.FunctionalTests.BulkUpdates; // TODO: need fix internal class NonSharedModelBulkUpdatesYdbTest : NonSharedModelBulkUpdatesRelationalTestBase diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NorthwindBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesYdbFixture.cs similarity index 87% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NorthwindBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesYdbFixture.cs index 704a0c57..7b0a234d 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NorthwindBulkUpdatesYdbFixture.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesYdbFixture.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.BulkUpdates; +namespace EntityFrameworkCore.Ydb.FunctionalTests.BulkUpdates; internal class NorthwindBulkUpdatesYdbFixture : NorthwindBulkUpdatesRelationalFixture diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NorthwindBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesYdbTest.cs similarity index 89% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NorthwindBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesYdbTest.cs index 2503ffe1..5b8786dc 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/NorthwindBulkUpdatesYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesYdbTest.cs @@ -1,3 +1,4 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.BulkUpdates; using Microsoft.EntityFrameworkCore.BulkUpdates; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit.Abstractions; diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbFixture.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbFixture.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCFiltersInheritanceBulkUpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbFixture.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbFixture.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPCInheritanceBulkUpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbFixture.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbFixture.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbFixture.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbFixture.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPHInheritanceBulkUpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbFixture.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbFixture.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTFiltersInheritanceBulkUpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbFixture.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbFixture.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbFixture.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/BulkUpdates/TPTInheritanceBulkUpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ComplexTypesTrackingYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ComplexTypesTrackingYdbTest.cs new file mode 100644 index 00000000..fa9e3861 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ComplexTypesTrackingYdbTest.cs @@ -0,0 +1,31 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class ComplexTypesTrackingYdbTest : ComplexTypesTrackingTestBase +{ + public ComplexTypesTrackingYdbTest(YdbFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + fixture.TestSqlLoggerFactory.Clear(); + fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class YdbFixture : FixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + } + +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/CompositeKeyEndToEndTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/CompositeKeyEndToEndTest.cs new file mode 100644 index 00000000..08de6406 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/CompositeKeyEndToEndTest.cs @@ -0,0 +1,21 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class CompositeKeyEndToEndYdbTest(CompositeKeyEndToEndYdbTest.CompositeKeyEndToEndYdbFixture fixture) + : CompositeKeyEndToEndTestBase(fixture) +{ + + [ConditionalFact(Skip = "TODO: Cannot access table")] + public override Task Can_use_generated_values_in_composite_key_end_to_end() + => base.Can_use_generated_values_in_composite_key_end_to_end(); + + public class CompositeKeyEndToEndYdbFixture : CompositeKeyEndToEndFixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConcurrencyDetectorDisabledYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConcurrencyDetectorDisabledYdbTest.cs new file mode 100644 index 00000000..d7f37813 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConcurrencyDetectorDisabledYdbTest.cs @@ -0,0 +1,47 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class ConcurrencyDetectorDisabledYdbTest : ConcurrencyDetectorDisabledRelationalTestBase< + ConcurrencyDetectorDisabledYdbTest.ConcurrencyDetectorYdbFixture> +{ + public ConcurrencyDetectorDisabledYdbTest(ConcurrencyDetectorYdbFixture fixture) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } + + public override Task FromSql(bool async) + => ConcurrencyDetectorTest( + async c => async + ? await c.Products.FromSqlRaw( + """ + select * from `Products` + """).ToListAsync() + : c.Products.FromSqlRaw( + """ + select * from `Products` + """).ToList()); + + protected override async Task ConcurrencyDetectorTest(Func> test) + { + await base.ConcurrencyDetectorTest(test); + + Assert.NotEmpty(Fixture.TestSqlLoggerFactory.SqlStatements); + } + + public class ConcurrencyDetectorYdbFixture : ConcurrencyDetectorFixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => builder.EnableThreadSafetyChecks(enableChecks: false); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConcurrencyDetectorEnabledYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConcurrencyDetectorEnabledYdbTest.cs new file mode 100644 index 00000000..8cc37298 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConcurrencyDetectorEnabledYdbTest.cs @@ -0,0 +1,44 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class ConcurrencyDetectorEnabledYdbTest : ConcurrencyDetectorEnabledRelationalTestBase< + ConcurrencyDetectorEnabledYdbTest.ConcurrencyDetectorYdbFixture> +{ + public ConcurrencyDetectorEnabledYdbTest(ConcurrencyDetectorYdbFixture fixture) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } + + public override Task FromSql(bool async) + => ConcurrencyDetectorTest( + async c => async + ? await c.Products.FromSqlRaw( + """ + select * from `Products` + """).ToListAsync() + : c.Products.FromSqlRaw( + """ + select * from `Products` + """).ToList()); + + protected override async Task ConcurrencyDetectorTest(Func> test) + { + await base.ConcurrencyDetectorTest(test); + + Assert.Empty(Fixture.TestSqlLoggerFactory.SqlStatements); + } + + public class ConcurrencyDetectorYdbFixture : ConcurrencyDetectorFixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConvertToProviderTypesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConvertToProviderTypesYdbTest.cs new file mode 100644 index 00000000..9dcd5307 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ConvertToProviderTypesYdbTest.cs @@ -0,0 +1,51 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +// TODO: Expects actual decimal precision. But ydb supports only (22, 9) +internal class ConvertToProviderTypesYdbTest : ConvertToProviderTypesTestBase< + ConvertToProviderTypesYdbTest.ConvertToProviderTypesYdbFixture> +{ + public ConvertToProviderTypesYdbTest(ConvertToProviderTypesYdbFixture fixture) : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } + + public class ConvertToProviderTypesYdbFixture : ConvertToProviderTypesFixtureBase + { + public override bool StrictEquality + => true; + + public override bool SupportsAnsi + => false; + + public override bool SupportsUnicodeToAnsiConversion + => false; + + public override bool SupportsLargeStringComparisons + => true; + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ServiceProvider.GetRequiredService(); + + public override bool SupportsBinaryKeys + => true; + + public override bool SupportsDecimalComparisons + => true; + + public override DateTime DefaultDateTime + => new(); + + public override bool PreservesDateTimeKind + => false; + + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/DesignTimeYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/DesignTimeYdbTest.cs new file mode 100644 index 00000000..65b3ede5 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/DesignTimeYdbTest.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using EntityFrameworkCore.Ydb.Design.Internal; +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class DesignTimeYdbTest(DesignTimeYdbTest.DesignTimeYdbFixture fixture) + : DesignTimeTestBase(fixture) +{ + protected override Assembly ProviderAssembly + => typeof(YdbDesignTimeServices).Assembly; + + public class DesignTimeYdbFixture : DesignTimeFixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/EntitySplittingYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/EntitySplittingYdbTest.cs similarity index 86% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/EntitySplittingYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/EntitySplittingYdbTest.cs index a287ab88..97b71f4c 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/EntitySplittingYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/EntitySplittingYdbTest.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit.Abstractions; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests; +namespace EntityFrameworkCore.Ydb.FunctionalTests; public class EntitySplittingYdbTest(ITestOutputHelper testOutputHelper) : EntitySplittingTestBase(testOutputHelper) { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/F1YdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/F1YdbFixture.cs new file mode 100644 index 00000000..24a0ed03 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/F1YdbFixture.cs @@ -0,0 +1,21 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class F1ULongYdbFixture : F1YdbFixtureBase +{ + protected override string StoreName + => "F1ULongTest"; +} +public class F1YdbFixture : F1YdbFixtureBase; + +public abstract class F1YdbFixtureBase : F1RelationalFixture +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + public override TestHelpers TestHelpers + => YdbTestHelpers.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/FieldMappingYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/FieldMappingYdbTest.cs new file mode 100644 index 00000000..d3509979 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/FieldMappingYdbTest.cs @@ -0,0 +1,22 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class FieldMappingYdbTest(FieldMappingYdbTest.FieldMappingYdbFixture fixture) + : FieldMappingTestBase(fixture) +{ + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class FieldMappingYdbFixture : FieldMappingFixtureBase + { + protected override string StoreName => "FieldMapping"; + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/FindYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/FindYdbTest.cs new file mode 100644 index 00000000..f180f126 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/FindYdbTest.cs @@ -0,0 +1,56 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public abstract class FindYdbTest : FindTestBase +{ + protected FindYdbTest(FindYdbFixture fixture) + : base(fixture) + { + fixture.TestSqlLoggerFactory.Clear(); + } + + [ConditionalFact(Skip = "TODO: Requires fixes")] + public override void Find_int_key_from_store() => base.Find_int_key_from_store(); + + [ConditionalTheory(Skip = "TODO: Requires fixes")] + [InlineData(CancellationType.None)] + public override Task Find_int_key_from_store_async(CancellationType cancellationType) => base.Find_int_key_from_store_async(cancellationType); + + [ConditionalFact(Skip = "Requires fixes")] + public override void Returns_null_for_int_key_not_in_store() => base.Returns_null_for_int_key_not_in_store(); + + [ConditionalTheory(Skip = "TODO: Requires fixes")] + [InlineData(CancellationType.None)] + public override Task Returns_null_for_int_key_not_in_store_async(CancellationType cancellationType) => base.Returns_null_for_int_key_not_in_store_async(cancellationType); + + public class FindYdbTestSet(FindYdbFixture fixture) : FindYdbTest(fixture) + { + protected override TestFinder Finder { get; } = new FindViaSetFinder(); + } + + public class FindYdbTestContext(FindYdbFixture fixture) : FindYdbTest(fixture) + { + protected override TestFinder Finder { get; } = new FindViaContextFinder(); + } + + public class FindYdbTestNonGeneric(FindYdbFixture fixture) : FindYdbTest(fixture) + { + protected override TestFinder Finder { get; } = new FindViaNonGenericContextFinder(); + } + + public class FindYdbFixture : FindFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ServiceProvider.GetRequiredService(); + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + } + +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/KeysWithConvertersYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/KeysWithConvertersYdbTest.cs new file mode 100644 index 00000000..8268c868 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/KeysWithConvertersYdbTest.cs @@ -0,0 +1,20 @@ +using EntityFrameworkCore.Ydb.Extensions; +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class KeysWithConvertersYdbTest(KeysWithConvertersYdbTest.KeysWithConvertersYdbFixture fixture) + : KeysWithConvertersTestBase< + KeysWithConvertersYdbTest.KeysWithConvertersYdbFixture>(fixture) +{ + public class KeysWithConvertersYdbFixture : KeysWithConvertersFixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + => builder.UseYdb(""); + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/LazyLoadProxyYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/LazyLoadProxyYdbTest.cs new file mode 100644 index 00000000..30f6e7ba --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/LazyLoadProxyYdbTest.cs @@ -0,0 +1,34 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class LazyLoadProxyYdbTest : LazyLoadProxyTestBase +{ + public LazyLoadProxyYdbTest(LoadYdbFixture fixture) : base(fixture) + { + } + + [ConditionalFact(Skip = "TODO: Fix precision")] + public override void Can_serialize_proxies_to_JSON() => base.Can_serialize_proxies_to_JSON(); + + [ConditionalTheory(Skip = "TODO: InvalidOperationException")] + [InlineData(EntityState.Unchanged)] + public override void Lazy_load_one_to_one_reference_with_recursive_property(EntityState state) => base.Lazy_load_one_to_one_reference_with_recursive_property(state); + + [ConditionalFact(Skip = "TODO: InvalidOperationException")] + public override void Top_level_projection_track_entities_before_passing_to_client_method() => base.Top_level_projection_track_entities_before_passing_to_client_method(); + + public class LoadYdbFixture : LoadFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ServiceProvider.GetRequiredService(); + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/LoadYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/LoadYdbTest.cs new file mode 100644 index 00000000..4fd379ff --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/LoadYdbTest.cs @@ -0,0 +1,46 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class LoadYdbTest : LoadTestBase +{ + + public LoadYdbTest(LoadYdbFixture fixture) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } + + protected override void ClearLog() + => Fixture.TestSqlLoggerFactory.Clear(); + + protected override void RecordLog() + => Sql = Fixture.TestSqlLoggerFactory.Sql; + + private string Sql { get; set; } = null!; + + public class LoadYdbFixture : LoadFixtureBase + { + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ServiceProvider.GetRequiredService(); + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder + .Entity() + .ToView("OptionalChildView"); + modelBuilder + .Entity() + .ToView("RequiredChildView"); + } + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/MaterializationInterceptionYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/MaterializationInterceptionYdbTest.cs new file mode 100644 index 00000000..bb7d5713 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/MaterializationInterceptionYdbTest.cs @@ -0,0 +1,22 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class MaterializationInterceptionYdbTest : + MaterializationInterceptionTestBase +{ + public class YdbLibraryContext(DbContextOptions options) : LibraryContext(options) + { + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity().OwnsMany(e => e.Settings); + } + } + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsInfrastructureTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsInfrastructureTest.cs index 5a2819ea..1ff1f72b 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsInfrastructureTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsInfrastructureTest.cs @@ -1,7 +1,9 @@ using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; using Xunit; namespace EntityFrameworkCore.Ydb.FunctionalTests.Migrations; @@ -12,6 +14,12 @@ public class YdbMigrationsInfrastructureTest(YdbMigrationsInfrastructureTest.Ydb public class YdbMigrationsInfrastructureFixture : MigrationsInfrastructureFixtureBase { protected override ITestStoreFactory TestStoreFactory => YdbTestStoreFactory.Instance; + + protected override IServiceCollection AddServices(IServiceCollection serviceCollection) + { + serviceCollection.AddScoped(); + return base.AddServices(serviceCollection); + } } protected override void GiveMeSomeTime(DbContext db) @@ -98,6 +106,12 @@ public override void Can_get_active_provider() Assert.Equal("EntityFrameworkCore.Ydb", ActiveProvider); } + [ConditionalFact(Skip = "TODO")] + public override void Can_apply_one_migration_in_parallel() => base.Can_apply_one_migration_in_parallel(); + + [ConditionalFact(Skip = "TODO")] + public override Task Can_apply_one_migration_in_parallel_async() => base.Can_apply_one_migration_in_parallel_async(); + protected override Task ExecuteSqlAsync(string value) => ((YdbTestStore)Fixture.TestStore).ExecuteNonQueryAsync(value); } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs index 5a236821..93955e6e 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsSqlGeneratorTest.cs @@ -12,7 +12,7 @@ public override void AddColumnOperation_with_fixed_length_no_model() { base.AddColumnOperation_with_fixed_length_no_model(); - AssertSql("ALTER TABLE `Person` ADD `Name` Text;"); + AssertSql("ALTER TABLE `Person` ADD `Name` TEXT;"); } @@ -20,7 +20,7 @@ public override void AddColumnOperation_without_column_type() { base.AddColumnOperation_without_column_type(); - AssertSql("ALTER TABLE `People` ADD `Alias` Text NOT NULL;"); + AssertSql("ALTER TABLE `People` ADD `Alias` TEXT NOT NULL;"); } @@ -28,7 +28,7 @@ public override void AddColumnOperation_with_unicode_overridden() { base.AddColumnOperation_with_unicode_overridden(); - AssertSql("ALTER TABLE `Person` ADD `Name` Text;"); + AssertSql("ALTER TABLE `Person` ADD `Name` TEXT;"); } @@ -36,7 +36,7 @@ public override void AddColumnOperation_with_unicode_no_model() { base.AddColumnOperation_with_unicode_no_model(); - AssertSql("ALTER TABLE `Person` ADD `Name` Text;"); + AssertSql("ALTER TABLE `Person` ADD `Name` TEXT;"); } @@ -44,7 +44,7 @@ public override void AddColumnOperation_with_maxLength_overridden() { base.AddColumnOperation_with_maxLength_overridden(); - AssertSql("ALTER TABLE `Person` ADD `Name` Text;"); + AssertSql("ALTER TABLE `Person` ADD `Name` TEXT;"); } @@ -52,7 +52,7 @@ public override void AddColumnOperation_with_maxLength_no_model() { base.AddColumnOperation_with_maxLength_no_model(); - AssertSql("ALTER TABLE `Person` ADD `Name` Text;"); + AssertSql("ALTER TABLE `Person` ADD `Name` TEXT;"); } @@ -116,7 +116,7 @@ public override void InsertDataOperation_required_args() AssertSql( """ INSERT INTO `dbo/People` (`First Name`) - VALUES ('John'); + VALUES ('John'u); """); } @@ -128,7 +128,7 @@ public override void InsertDataOperation_required_args_composite() AssertSql( """ INSERT INTO `dbo/People` (`First Name`, `Last Name`) - VALUES ('John', 'Snow'); + VALUES ('John'u, 'Snow'u); """); } @@ -140,9 +140,9 @@ public override void InsertDataOperation_required_args_multiple_rows() AssertSql( """ INSERT INTO `dbo/People` (`First Name`) - VALUES ('John'); + VALUES ('John'u); INSERT INTO `dbo/People` (`First Name`) - VALUES ('Daenerys'); + VALUES ('Daenerys'u); """); } @@ -168,15 +168,15 @@ public override void DeleteDataOperation_all_args() AssertSql( """ DELETE FROM `People` - WHERE `First Name` = 'Hodor'; + WHERE `First Name` = 'Hodor'u; DELETE FROM `People` - WHERE `First Name` = 'Daenerys'; + WHERE `First Name` = 'Daenerys'u; DELETE FROM `People` - WHERE `First Name` = 'John'; + WHERE `First Name` = 'John'u; DELETE FROM `People` - WHERE `First Name` = 'Arya'; + WHERE `First Name` = 'Arya'u; DELETE FROM `People` - WHERE `First Name` = 'Harry'; + WHERE `First Name` = 'Harry'u; """); } @@ -188,15 +188,15 @@ public override void DeleteDataOperation_all_args_composite() AssertSql( """ DELETE FROM `People` - WHERE `First Name` = 'Hodor' AND `Last Name` IS NULL; + WHERE `First Name` = 'Hodor'u AND `Last Name` IS NULL; DELETE FROM `People` - WHERE `First Name` = 'Daenerys' AND `Last Name` = 'Targaryen'; + WHERE `First Name` = 'Daenerys'u AND `Last Name` = 'Targaryen'u; DELETE FROM `People` - WHERE `First Name` = 'John' AND `Last Name` = 'Snow'; + WHERE `First Name` = 'John'u AND `Last Name` = 'Snow'u; DELETE FROM `People` - WHERE `First Name` = 'Arya' AND `Last Name` = 'Stark'; + WHERE `First Name` = 'Arya'u AND `Last Name` = 'Stark'u; DELETE FROM `People` - WHERE `First Name` = 'Harry' AND `Last Name` = 'Strickland'; + WHERE `First Name` = 'Harry'u AND `Last Name` = 'Strickland'u; """); } @@ -208,7 +208,7 @@ public override void DeleteDataOperation_required_args() AssertSql( """ DELETE FROM `People` - WHERE `Last Name` = 'Snow'; + WHERE `Last Name` = 'Snow'u; """); } @@ -220,7 +220,7 @@ public override void DeleteDataOperation_required_args_composite() AssertSql( """ DELETE FROM `People` - WHERE `First Name` = 'John' AND `Last Name` = 'Snow'; + WHERE `First Name` = 'John'u AND `Last Name` = 'Snow'u; """); } @@ -231,10 +231,10 @@ public override void UpdateDataOperation_all_args() AssertSql( """ - UPDATE `People` SET `Birthplace` = 'Winterfell', `House Allegiance` = 'Stark', `Culture` = 'Northmen' - WHERE `First Name` = 'Hodor'; - UPDATE `People` SET `Birthplace` = 'Dragonstone', `House Allegiance` = 'Targaryen', `Culture` = 'Valyrian' - WHERE `First Name` = 'Daenerys'; + UPDATE `People` SET `Birthplace` = 'Winterfell'u, `House Allegiance` = 'Stark'u, `Culture` = 'Northmen'u + WHERE `First Name` = 'Hodor'u; + UPDATE `People` SET `Birthplace` = 'Dragonstone'u, `House Allegiance` = 'Targaryen'u, `Culture` = 'Valyrian'u + WHERE `First Name` = 'Daenerys'u; """); } @@ -245,10 +245,10 @@ public override void UpdateDataOperation_all_args_composite() AssertSql( """ - UPDATE `People` SET `House Allegiance` = 'Stark' - WHERE `First Name` = 'Hodor' AND `Last Name` IS NULL; - UPDATE `People` SET `House Allegiance` = 'Targaryen' - WHERE `First Name` = 'Daenerys' AND `Last Name` = 'Targaryen'; + UPDATE `People` SET `House Allegiance` = 'Stark'u + WHERE `First Name` = 'Hodor'u AND `Last Name` IS NULL; + UPDATE `People` SET `House Allegiance` = 'Targaryen'u + WHERE `First Name` = 'Daenerys'u AND `Last Name` = 'Targaryen'u; """); } @@ -259,10 +259,10 @@ public override void UpdateDataOperation_all_args_composite_multi() AssertSql( """ - UPDATE `People` SET `Birthplace` = 'Winterfell', `House Allegiance` = 'Stark', `Culture` = 'Northmen' - WHERE `First Name` = 'Hodor' AND `Last Name` IS NULL; - UPDATE `People` SET `Birthplace` = 'Dragonstone', `House Allegiance` = 'Targaryen', `Culture` = 'Valyrian' - WHERE `First Name` = 'Daenerys' AND `Last Name` = 'Targaryen'; + UPDATE `People` SET `Birthplace` = 'Winterfell'u, `House Allegiance` = 'Stark'u, `Culture` = 'Northmen'u + WHERE `First Name` = 'Hodor'u AND `Last Name` IS NULL; + UPDATE `People` SET `Birthplace` = 'Dragonstone'u, `House Allegiance` = 'Targaryen'u, `Culture` = 'Valyrian'u + WHERE `First Name` = 'Daenerys'u AND `Last Name` = 'Targaryen'u; """); } @@ -273,8 +273,8 @@ public override void UpdateDataOperation_all_args_multi() AssertSql( """ - UPDATE `People` SET `Birthplace` = 'Dragonstone', `House Allegiance` = 'Targaryen', `Culture` = 'Valyrian' - WHERE `First Name` = 'Daenerys'; + UPDATE `People` SET `Birthplace` = 'Dragonstone'u, `House Allegiance` = 'Targaryen'u, `Culture` = 'Valyrian'u + WHERE `First Name` = 'Daenerys'u; """); } @@ -285,8 +285,8 @@ public override void UpdateDataOperation_required_args() AssertSql( """ - UPDATE `People` SET `House Allegiance` = 'Targaryen' - WHERE `First Name` = 'Daenerys'; + UPDATE `People` SET `House Allegiance` = 'Targaryen'u + WHERE `First Name` = 'Daenerys'u; """); } @@ -297,10 +297,10 @@ public override void UpdateDataOperation_required_args_multiple_rows() AssertSql( """ - UPDATE `People` SET `House Allegiance` = 'Stark' - WHERE `First Name` = 'Hodor'; - UPDATE `People` SET `House Allegiance` = 'Targaryen' - WHERE `First Name` = 'Daenerys'; + UPDATE `People` SET `House Allegiance` = 'Stark'u + WHERE `First Name` = 'Hodor'u; + UPDATE `People` SET `House Allegiance` = 'Targaryen'u + WHERE `First Name` = 'Daenerys'u; """); } @@ -311,8 +311,8 @@ public override void UpdateDataOperation_required_args_composite() AssertSql( """ - UPDATE `People` SET `House Allegiance` = 'Targaryen' - WHERE `First Name` = 'Daenerys' AND `Last Name` = 'Targaryen'; + UPDATE `People` SET `House Allegiance` = 'Targaryen'u + WHERE `First Name` = 'Daenerys'u AND `Last Name` = 'Targaryen'u; """); } @@ -323,8 +323,8 @@ public override void UpdateDataOperation_required_args_composite_multi() AssertSql( """ - UPDATE `People` SET `Birthplace` = 'Dragonstone', `House Allegiance` = 'Targaryen', `Culture` = 'Valyrian' - WHERE `First Name` = 'Daenerys' AND `Last Name` = 'Targaryen'; + UPDATE `People` SET `Birthplace` = 'Dragonstone'u, `House Allegiance` = 'Targaryen'u, `Culture` = 'Valyrian'u + WHERE `First Name` = 'Daenerys'u AND `Last Name` = 'Targaryen'u; """); } @@ -334,8 +334,8 @@ public override void UpdateDataOperation_required_args_multi() AssertSql( """ - UPDATE `People` SET `Birthplace` = 'Dragonstone', `House Allegiance` = 'Targaryen', `Culture` = 'Valyrian' - WHERE `First Name` = 'Daenerys'; + UPDATE `People` SET `Birthplace` = 'Dragonstone'u, `House Allegiance` = 'Targaryen'u, `Culture` = 'Valyrian'u + WHERE `First Name` = 'Daenerys'u; """ ); } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsTest.cs index ceaaecf9..29a5e315 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Migrations/YdbMigrationsTest.cs @@ -147,7 +147,6 @@ public override async Task Add_column_with_max_length() public override async Task Add_column_with_unbounded_max_length() { await base.Add_column_with_unbounded_max_length(); - AssertSql("ALTER TABLE `People` ADD `Name` Text;"); } @@ -466,13 +465,13 @@ public override async Task InsertDataOperation() AssertSql( """ INSERT INTO `Person` (`Id`, `Name`) - VALUES (1, 'Daenerys Targaryen'); + VALUES (1, 'Daenerys Targaryen'u); INSERT INTO `Person` (`Id`, `Name`) - VALUES (2, 'John Snow'); + VALUES (2, 'John Snow'u); INSERT INTO `Person` (`Id`, `Name`) - VALUES (3, 'Arya Stark'); + VALUES (3, 'Arya Stark'u); INSERT INTO `Person` (`Id`, `Name`) - VALUES (4, 'Harry Strickland'); + VALUES (4, 'Harry Strickland'u); INSERT INTO `Person` (`Id`, `Name`) VALUES (5, NULL); """ @@ -507,7 +506,7 @@ public override async Task UpdateDataOperation_simple_key() AssertSql( """ - UPDATE `Person` SET `Name` = 'Another John Snow' + UPDATE `Person` SET `Name` = 'Another John Snow'u WHERE `Id` = 2; """); } @@ -518,7 +517,7 @@ public override async Task UpdateDataOperation_composite_key() AssertSql( """ - UPDATE `Person` SET `Name` = 'Another John Snow' + UPDATE `Person` SET `Name` = 'Another John Snow'u WHERE `AnotherId` = 11 AND `Id` = 2; """); } @@ -529,7 +528,7 @@ public override async Task UpdateDataOperation_multiple_columns() AssertSql( """ - UPDATE `Person` SET `Age` = 21, `Name` = 'Another John Snow' + UPDATE `Person` SET `Age` = 21, `Name` = 'Another John Snow'u WHERE `Id` = 2; """); } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding/YdbModelBuilderGenericTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding/YdbModelBuilderGenericTest.cs new file mode 100644 index 00000000..cf58cd14 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding/YdbModelBuilderGenericTest.cs @@ -0,0 +1,73 @@ +using EfCore.Ydb.FunctionalTests.ModelBuilding; +using Microsoft.EntityFrameworkCore; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.ModelBuilding; + +public class YdbModelBuilderGenericTest : YdbModelBuilderTestBase +{ + + public class YdbGenericNonRelationship(YdbModelBuilderFixture fixture) : YdbNonRelationship(fixture) + { + [ConditionalFact(Skip = "TODO: Not ready yet")] + public override void Element_types_can_have_precision_and_scale() => base.Element_types_can_have_precision_and_scale(); + + [ConditionalFact(Skip = "TODO: Not ready yet")] + public override void Element_types_have_default_precision_and_scale() => base.Element_types_have_default_precision_and_scale(); + + [ConditionalFact(Skip = "TODO: Not ready yet")] + public override void Element_types_have_default_unicode() => base.Element_types_have_default_unicode(); + + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericComplexType(YdbModelBuilderFixture fixture) : YdbComplexType(fixture) + { + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericInheritance(YdbModelBuilderFixture fixture) : YdbInheritance(fixture) + { + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericOneToMany(YdbModelBuilderFixture fixture) : YdbOneToMany(fixture) + { + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericManyToOne(YdbModelBuilderFixture fixture) : YdbManyToOne(fixture) + { + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericOneToOne(YdbModelBuilderFixture fixture) : YdbOneToOne(fixture) + { + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericManyToMany(YdbModelBuilderFixture fixture) : YdbManyToMany(fixture) + { + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } + + public class YdbGenericOwnedTypes(YdbModelBuilderFixture fixture) : YdbOwnedTypes(fixture) + { + [ConditionalFact(Skip = "TODO: Not ready yet")] + public override void Can_configure_one_to_one_owned_type_with_fields() => base.Can_configure_one_to_one_owned_type_with_fields(); + + [ConditionalFact(Skip = "TODO: Not ready yet")] + public override void Shared_type_entity_types_with_FK_to_another_entity_works() => base.Shared_type_entity_types_with_FK_to_another_entity_works(); + + + protected override TestModelBuilder CreateModelBuilder(Action? configure) + => new GenericTestModelBuilder(Fixture, configure); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding/YdbModelBuilderTestBase.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding/YdbModelBuilderTestBase.cs new file mode 100644 index 00000000..a148acac --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding/YdbModelBuilderTestBase.cs @@ -0,0 +1,39 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore.ModelBuilding; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace EfCore.Ydb.FunctionalTests.ModelBuilding; + +public class YdbModelBuilderTestBase : RelationalModelBuilderTest +{ + public abstract class YdbNonRelationship(YdbModelBuilderFixture fixture) + : RelationalNonRelationshipTestBase(fixture), IClassFixture; + + public abstract class YdbComplexType(YdbModelBuilderFixture fixture) + : RelationalComplexTypeTestBase(fixture), IClassFixture; + + public abstract class YdbInheritance(YdbModelBuilderFixture fixture) + : RelationalInheritanceTestBase(fixture), IClassFixture; + + public abstract class YdbOneToMany(YdbModelBuilderFixture fixture) + : RelationalOneToManyTestBase(fixture), IClassFixture; + + public abstract class YdbManyToOne(YdbModelBuilderFixture fixture) + : RelationalManyToOneTestBase(fixture), IClassFixture; + + public abstract class YdbOneToOne(YdbModelBuilderFixture fixture) + : RelationalOneToOneTestBase(fixture), IClassFixture; + + public abstract class YdbManyToMany(YdbModelBuilderFixture fixture) + : RelationalManyToManyTestBase(fixture), IClassFixture; + + public abstract class YdbOwnedTypes(YdbModelBuilderFixture fixture) + : RelationalOwnedTypesTestBase(fixture), IClassFixture; + + public class YdbModelBuilderFixture : RelationalModelBuilderFixture + { + public override TestHelpers TestHelpers + => YdbTestHelpers.Instance; + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/ModelBuilding101YdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding101YdbTest.cs similarity index 83% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/ModelBuilding101YdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding101YdbTest.cs index d9083c33..fd83287f 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/ModelBuilding101YdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/ModelBuilding101YdbTest.cs @@ -1,7 +1,7 @@ using EntityFrameworkCore.Ydb.Extensions; using Microsoft.EntityFrameworkCore; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests; +namespace EntityFrameworkCore.Ydb.FunctionalTests; public class ModelBuilding101YdbTest : ModelBuilding101RelationalTestBase { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Northwind.sql b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Northwind.sql index 67a4da9b..53aaf30c 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Northwind.sql +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Northwind.sql @@ -229,15 +229,14 @@ VALUES ('BOLID', 'Bólido Comidas preparadas', 'Martín Sommer', 'Owner', 'C/ Ar 'Spain', '(91) 555 22 82', '(91) 555 91 99'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) -VALUES ('BONAP', 'Bon app\'\'', 'Laurence Lebihan', 'Owner', '12, rue des Bouchers', 'Marseille', NULL, '13008', +VALUES ('BONAP', 'Bon app\'', 'Laurence Lebihan', 'Owner', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France', '91.24.45.40', '91.24.45.41'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) VALUES ('BOTTM', 'Bottom-Dollar Markets', 'Elizabeth Lincoln', 'Accounting Manager', '23 Tsawassen Blvd.', 'Tsawassen', 'BC', 'T2F 8M4', 'Canada', '(604) 555-4729', '(604) 555-3745'); GO -INSERT INTO `Customers`(`CustomerID`,`CompanyName`,`ContactName`,`ContactTitle`,`Address`,`City`,`Region`,`PostalCode`,`Country`,`Phone`,`Fax`) VALUES ('BSBEV','B\' -\'s Beverages','Victoria Ashworth','Sales Representative','Fauntleroy Circus','London',NULL,'EC2 5NT','UK','(171) 555-1212',NULL); +INSERT INTO `Customers`(`CustomerID`,`CompanyName`,`ContactName`,`ContactTitle`,`Address`,`City`,`Region`,`PostalCode`,`Country`,`Phone`,`Fax`) VALUES ('BSBEV','B\'s Beverages','Victoria Ashworth','Sales Representative','Fauntleroy Circus','London',NULL,'EC2 5NT','UK','(171) 555-1212',NULL); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) VALUES ('CACTU', 'Cactus Comidas para llevar', 'Patricio Simpson', 'Sales Agent', 'Cerrito 333', 'Buenos Aires', NULL, @@ -349,7 +348,7 @@ VALUES ('KOENE', 'Königlich Essen', 'Philip Cramer', 'Sales Associate', 'Maubel 'Germany', '0555-09876', NULL); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) -VALUES ('LACOR', 'La corne d\'\'abondance', 'Daniel Tonini', 'Sales Representative', '67, avenue de l\'\'Europe', +VALUES ('LACOR', 'La corne d\'abondance', 'Daniel Tonini', 'Sales Representative', '67, avenue de l\'Europe', 'Versailles', NULL, '78000', 'France', '30.59.84.10', '30.59.85.11'); GO INSERT INTO `Customers`(`CustomerID`,`CompanyName`,`ContactName`,`ContactTitle`,`Address`,`City`,`Region`,`PostalCode`,`Country`,`Phone`,`Fax`) VALUES ('LAMAI','La maison d\' @@ -368,7 +367,7 @@ VALUES ('LEHMS', 'Lehmanns Marktstand', 'Renate Messner', 'Sales Representative' NULL, '60528', 'Germany', '069-0245984', '069-0245874'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) -VALUES ('LETSS', 'Let\'\'s Stop N Shop', 'Jaime Yorres', 'Owner', '87 Polk St. Suite 5', 'San Francisco', 'CA', '94117', +VALUES ('LETSS', 'Let\'s Stop N Shop', 'Jaime Yorres', 'Owner', '87 Polk St. Suite 5', 'San Francisco', 'CA', '94117', 'USA', '(415) 555-5938', NULL); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) @@ -509,7 +508,7 @@ GO INSERT INTO `Customers`(`CustomerID`,`CompanyName`,`ContactName`,`ContactTitle`,`Address`,`City`,`Region`,`PostalCode`,`Country`,`Phone`,`Fax`) VALUES ('TRADH','Tradição Hipermercados','Anabela Domingues','Sales Representative','Av. Inês de Castro, 414','Sao Paulo','SP','05634-030','Brazil','(11) 555-2167','(11) 555-2168'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) -VALUES ('TRAIH', 'Trail\'\'s Head Gourmet Provisioners', 'Helvetius Nagy', 'Sales Associate', '722 DaVinci Blvd.', +VALUES ('TRAIH', 'Trail\'s Head Gourmet Provisioners', 'Helvetius Nagy', 'Sales Associate', '722 DaVinci Blvd.', 'Kirkland', 'WA', '98034', 'USA', '(206) 555-8257', '(206) 555-2174'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) @@ -521,7 +520,7 @@ VALUES ('VICTE', 'Victuailles en stock', 'Mary Saveley', 'Sales Agent', '2, rue 'France', '78.32.54.86', '78.32.54.87'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) -VALUES ('VINET', 'Vins et alcools Chevalier', 'Paul Henriot', 'Accounting Manager', '59 rue de l\'\'Abbaye', 'Reims', +VALUES ('VINET', 'Vins et alcools Chevalier', 'Paul Henriot', 'Accounting Manager', '59 rue de l\'Abbaye', 'Reims', NULL, '51100', 'France', '26.47.15.10', '26.47.15.11'); INSERT INTO `Customers`(`CustomerID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`) @@ -5065,7 +5064,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10274, 'VINET', 6, Date ('1996-8-6'), Date ('1996-9-3'), Date ('1996-8-16'), 1, Decimal('6.01', 22, 9), - 'Vins et alcools Chevalier', '59 rue de l\'\'Abbaye', 'Reims', + 'Vins et alcools Chevalier', '59 rue de l\'Abbaye', 'Reims', NULL, '51100', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5170,7 +5169,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10289, 'BSBEV', 7, Date ('1996-8-26'), Date ('1996-9-23'), Date ('1996-8-28'), 3, Decimal('22.77', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5212,7 +5211,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10295, 'VINET', 2, Date ('1996-9-2'), Date ('1996-9-30'), Date ('1996-9-10'), 2, Decimal('1.15', 22, 9), - 'Vins et alcools Chevalier', '59 rue de l\'\'Abbaye', 'Reims', + 'Vins et alcools Chevalier', '59 rue de l\'Abbaye', 'Reims', NULL, '51100', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5464,7 +5463,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10331, 'BONAP', 9, Date ('1996-10-16'), Date ('1996-11-27'), Date ('1996-10-21'), 1, Decimal('10.19', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5527,7 +5526,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10340, 'BONAP', 1, Date ('1996-10-29'), Date ('1996-11-26'), Date ('1996-11-8'), 3, Decimal('166.31', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5598,7 +5597,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10350, 'LAMAI', 6, Date ('1996-11-11'), Date ('1996-12-9'), Date ('1996-12-3'), 2, Decimal('64.19', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5654,7 +5653,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10358, 'LAMAI', 5, Date ('1996-11-20'), Date ('1996-12-18'), Date ('1996-11-27'), 1, Decimal('19.64', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5682,7 +5681,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10362, 'BONAP', 3, Date ('1996-11-25'), Date ('1996-12-23'), Date ('1996-11-28'), 1, Decimal('96.04', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -5745,7 +5744,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10371, 'LAMAI', 1, Date ('1996-12-3'), Date ('1996-12-31'), Date ('1996-12-24'), 1, Decimal('0.45', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6039,7 +6038,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10413, 'LAMAI', 3, Date ('1997-1-14'), Date ('1997-2-11'), Date ('1997-1-16'), 2, Decimal('95.66', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6123,7 +6122,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10425, 'LAMAI', 6, Date ('1997-1-24'), Date ('1997-2-21'), Date ('1997-2-14'), 2, Decimal('7.93', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6327,7 +6326,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10454, 'LAMAI', 4, Date ('1997-2-21'), Date ('1997-3-21'), Date ('1997-2-25'), 3, Decimal('2.74', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6439,14 +6438,14 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10470, 'BONAP', 4, Date ('1997-3-11'), Date ('1997-4-8'), Date ('1997-3-14'), 2, Decimal('64.56', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10471, 'BSBEV', 2, Date ('1997-3-11'), Date ('1997-4-8'), Date ('1997-3-18'), 3, Decimal('45.59', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6537,7 +6536,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10484, 'BSBEV', 3, Date ('1997-3-24'), Date ('1997-4-21'), Date ('1997-4-1'), 3, Decimal('6.88', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6600,7 +6599,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10493, 'LAMAI', 4, Date ('1997-4-2'), Date ('1997-4-30'), Date ('1997-4-10'), 3, Decimal('10.64', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); GO INSERT INTO `Orders` @@ -6650,7 +6649,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10500, 'LAMAI', 6, Date ('1997-4-9'), Date ('1997-5-7'), Date ('1997-4-17'), 1, Decimal('42.68', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6727,7 +6726,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10511, 'BONAP', 4, Date ('1997-4-18'), Date ('1997-5-16'), Date ('1997-4-21'), 3, Decimal('350.64', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6825,7 +6824,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10525, 'BONAP', 1, Date ('1997-5-2'), Date ('1997-5-30'), Date ('1997-5-23'), 2, Decimal('11.06', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -6916,14 +6915,14 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10538, 'BSBEV', 9, Date ('1997-5-15'), Date ('1997-6-12'), Date ('1997-5-16'), 3, Decimal('4.87', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10539, 'BSBEV', 6, Date ('1997-5-16'), Date ('1997-6-13'), Date ('1997-5-23'), 3, Decimal('12.36', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7169,7 +7168,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10574, 'TRAIH', 4, Date ('1997-6-19'), Date ('1997-7-17'), Date ('1997-6-30'), 2, Decimal('37.60', 22, 9), - 'Trail\'\'s Head Gourmet Provisioners', '722 DaVinci Blvd.', 'Kirkland', + 'Trail\'s Head Gourmet Provisioners', '722 DaVinci Blvd.', 'Kirkland', 'WA', '98034', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7190,21 +7189,21 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10577, 'TRAIH', 9, Date ('1997-6-23'), Date ('1997-8-4'), Date ('1997-6-30'), 2, Decimal('25.41', 22, 9), - 'Trail\'\'s Head Gourmet Provisioners', '722 DaVinci Blvd.', 'Kirkland', + 'Trail\'s Head Gourmet Provisioners', '722 DaVinci Blvd.', 'Kirkland', 'WA', '98034', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10578, 'BSBEV', 4, Date ('1997-6-24'), Date ('1997-7-22'), Date ('1997-7-25'), 3, Decimal('29.60', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10579, 'LETSS', 1, Date ('1997-6-25'), Date ('1997-7-23'), Date ('1997-7-4'), 2, Decimal('13.73', 22, 9), - 'Let\'\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', + 'Let\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', 'CA', '94117', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7344,7 +7343,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10599, 'BSBEV', 6, Date ('1997-7-15'), Date ('1997-8-26'), Date ('1997-7-21'), 3, Decimal('29.98', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7421,7 +7420,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10610, 'LAMAI', 8, Date ('1997-7-25'), Date ('1997-8-22'), Date ('1997-8-6'), 1, Decimal('26.78', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7568,7 +7567,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10631, 'LAMAI', 8, Date ('1997-8-14'), Date ('1997-9-11'), Date ('1997-8-15'), 1, Decimal('0.87', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7793,7 +7792,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10663, 'BONAP', 2, Date ('1997-9-10'), Date ('1997-9-24'), Date ('1997-10-3'), 2, Decimal('113.15', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -7997,7 +7996,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10692, 'ALFKI', 4, Date ('1997-10-3'), Date ('1997-10-31'), Date ('1997-10-13'), 2, Decimal('61.02', 22, 9), - 'Alfred\'\'s Futterkiste', 'Obere Str. 57', 'Berlin', + 'Alfred\'s Futterkiste', 'Obere Str. 57', 'Berlin', NULL, '12209', 'Germany'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8067,7 +8066,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10702, 'ALFKI', 4, Date ('1997-10-13'), Date ('1997-11-24'), Date ('1997-10-21'), 1, Decimal('23.94', 22, 9), - 'Alfred\'\'s Futterkiste', 'Obere Str. 57', 'Berlin', + 'Alfred\'s Futterkiste', 'Obere Str. 57', 'Berlin', NULL, '12209', 'Germany'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8158,7 +8157,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10715, 'BONAP', 3, Date ('1997-10-23'), Date ('1997-11-6'), Date ('1997-10-29'), 1, Decimal('63.20', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8186,7 +8185,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10719, 'LETSS', 8, Date ('1997-10-27'), Date ('1997-11-24'), Date ('1997-11-5'), 2, Decimal('51.44', 22, 9), - 'Let\'\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', + 'Let\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', 'CA', '94117', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8263,7 +8262,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10730, 'BONAP', 5, Date ('1997-11-5'), Date ('1997-12-3'), Date ('1997-11-14'), 1, Decimal('20.12', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8277,7 +8276,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10732, 'BONAP', 3, Date ('1997-11-6'), Date ('1997-12-4'), Date ('1997-11-7'), 1, Decimal('16.97', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8298,7 +8297,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10735, 'LETSS', 6, Date ('1997-11-10'), Date ('1997-12-8'), Date ('1997-11-21'), 2, Decimal('45.97', 22, 9), - 'Let\'\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', + 'Let\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', 'CA', '94117', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8312,7 +8311,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10737, 'VINET', 2, Date ('1997-11-11'), Date ('1997-12-9'), Date ('1997-11-18'), 2, Decimal('7.79', 22, 9), - 'Vins et alcools Chevalier', '59 rue de l\'\'Abbaye', 'Reims', + 'Vins et alcools Chevalier', '59 rue de l\'Abbaye', 'Reims', NULL, '51100', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8326,7 +8325,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10739, 'VINET', 3, Date ('1997-11-12'), Date ('1997-12-10'), Date ('1997-11-17'), 3, Decimal('11.08', 22, 9), - 'Vins et alcools Chevalier', '59 rue de l\'\'Abbaye', 'Reims', + 'Vins et alcools Chevalier', '59 rue de l\'Abbaye', 'Reims', NULL, '51100', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8439,7 +8438,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10755, 'BONAP', 4, Date ('1997-11-26'), Date ('1997-12-24'), Date ('1997-11-28'), 2, Decimal('16.71', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8663,7 +8662,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10787, 'LAMAI', 2, Date ('1997-12-19'), Date ('1998-1-2'), Date ('1997-12-26'), 1, Decimal('249.93', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8909,7 +8908,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10822, 'TRAIH', 6, Date ('1998-1-8'), Date ('1998-2-5'), Date ('1998-1-16'), 3, Decimal('7.00', 22, 9), - 'Trail\'\'s Head Gourmet Provisioners', '722 DaVinci Blvd.', 'Kirkland', + 'Trail\'s Head Gourmet Provisioners', '722 DaVinci Blvd.', 'Kirkland', 'WA', '98034', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8944,7 +8943,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10827, 'BONAP', 1, Date ('1998-1-12'), Date ('1998-1-26'), Date ('1998-2-6'), 2, Decimal('63.54', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -8979,7 +8978,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10832, 'LAMAI', 2, Date ('1998-1-14'), Date ('1998-2-11'), Date ('1998-1-19'), 2, Decimal('43.26', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9000,7 +8999,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10835, 'ALFKI', 1, Date ('1998-1-15'), Date ('1998-2-12'), Date ('1998-1-21'), 3, Decimal('69.53', 22, 9), - 'Alfred\'\'s Futterkiste', 'Obere Str. 57', 'Berlin', + 'Alfred\'s Futterkiste', 'Obere Str. 57', 'Berlin', NULL, '12209', 'Germany'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9162,7 +9161,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10858, 'LACOR', 2, Date ('1998-1-29'), Date ('1998-2-26'), Date ('1998-2-3'), 1, Decimal('52.51', 22, 9), - 'La corne d\'\'abondance', '67, avenue de l\'\'Europe', 'Versailles', + 'La corne d\'abondance', '67, avenue de l\'Europe', 'Versailles', NULL, '78000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9253,7 +9252,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10871, 'BONAP', 9, Date ('1998-2-5'), Date ('1998-3-5'), Date ('1998-2-10'), 2, Decimal('112.27', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9288,7 +9287,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10876, 'BONAP', 7, Date ('1998-2-9'), Date ('1998-3-9'), Date ('1998-2-12'), 3, Decimal('60.42', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9344,7 +9343,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10884, 'LETSS', 4, Date ('1998-2-12'), Date ('1998-3-12'), Date ('1998-2-13'), 2, Decimal('90.97', 22, 9), - 'Let\'\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', + 'Let\'s Stop N Shop', '87 Polk St. Suite 5', 'San Francisco', 'CA', '94117', 'USA'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9617,7 +9616,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10923, 'LAMAI', 7, Date ('1998-3-3'), Date ('1998-4-14'), Date ('1998-3-13'), 3, Decimal('68.26', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9645,7 +9644,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10927, 'LACOR', 4, Date ('1998-3-5'), Date ('1998-4-2'), Date ('1998-4-8'), 1, Decimal('19.79', 22, 9), - 'La corne d\'\'abondance', '67, avenue de l\'\'Europe', 'Versailles', + 'La corne d\'abondance', '67, avenue de l\'Europe', 'Versailles', NULL, '78000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9680,7 +9679,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10932, 'BONAP', 8, Date ('1998-3-6'), Date ('1998-4-3'), Date ('1998-3-24'), 1, Decimal('134.64', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9736,7 +9735,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10940, 'BONAP', 8, Date ('1998-3-11'), Date ('1998-4-8'), Date ('1998-3-23'), 3, Decimal('19.77', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9757,7 +9756,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10943, 'BSBEV', 4, Date ('1998-3-11'), Date ('1998-4-8'), Date ('1998-3-19'), 2, Decimal('2.17', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9785,7 +9784,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10947, 'BSBEV', 3, Date ('1998-3-13'), Date ('1998-4-10'), Date ('1998-3-16'), 2, Decimal('3.26', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9820,7 +9819,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10952, 'ALFKI', 1, Date ('1998-3-16'), Date ('1998-4-27'), Date ('1998-3-24'), 1, Decimal('40.42', 22, 9), - 'Alfred\'\'s Futterkiste', 'Obere Str. 57', 'Berlin', + 'Alfred\'s Futterkiste', 'Obere Str. 57', 'Berlin', NULL, '12209', 'Germany'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -9961,14 +9960,14 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10972, 'LACOR', 4, Date ('1998-3-24'), Date ('1998-4-21'), Date ('1998-3-26'), 2, Decimal('0.02', 22, 9), - 'La corne d\'\'abondance', '67, avenue de l\'\'Europe', 'Versailles', + 'La corne d\'abondance', '67, avenue de l\'Europe', 'Versailles', NULL, '78000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (10973, 'LACOR', 6, Date ('1998-3-24'), Date ('1998-4-21'), Date ('1998-3-27'), 2, Decimal('15.17', 22, 9), - 'La corne d\'\'abondance', '67, avenue de l\'\'Europe', 'Versailles', + 'La corne d\'abondance', '67, avenue de l\'Europe', 'Versailles', NULL, '78000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -10234,7 +10233,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (11011, 'ALFKI', 3, Date ('1998-4-9'), Date ('1998-5-7'), Date ('1998-4-13'), 1, Decimal('1.21', 22, 9), - 'Alfred\'\'s Futterkiste', 'Obere Str. 57', 'Berlin', + 'Alfred\'s Futterkiste', 'Obere Str. 57', 'Berlin', NULL, '12209', 'Germany'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -10318,7 +10317,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (11023, 'BSBEV', 1, Date ('1998-4-14'), Date ('1998-4-28'), Date ('1998-4-24'), 2, Decimal('123.83', 22, 9), - 'B\'\'s Beverages', 'Fauntleroy Circus', 'London', + 'B\'s Beverages', 'Fauntleroy Circus', 'London', NULL, 'EC2 5NT', 'UK'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -10515,7 +10514,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (11051, 'LAMAI', 7, Date ('1998-4-27'), Date ('1998-5-25'), NULL, 3, Decimal('2.79', 22, 9), - 'La maison d\'\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', + 'La maison d\'Asie', '1 rue Alsace-Lorraine', 'Toulouse', NULL, '31000', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -10690,7 +10689,7 @@ INSERT INTO `Orders` `ShippedDate`, `ShipVia`, `Freight`, `ShipName`, `ShipAddress`, `ShipCity`, `ShipRegion`, `ShipPostalCode`, `ShipCountry`) VALUES (11076, 'BONAP', 4, Date ('1998-5-6'), Date ('1998-6-3'), NULL, 2, Decimal('38.28', 22, 9), - 'Bon app\'\'', '12, rue des Bouchers', 'Marseille', + 'Bon app\'', '12, rue des Bouchers', 'Marseille', NULL, '13008', 'France'); INSERT INTO `Orders` (`OrderID`, `CustomerID`, `EmployeeID`, `OrderDate`, `RequiredDate`, @@ -10709,16 +10708,16 @@ INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, ` VALUES (3, 'Aniseed Syrup', 1, 2, '12 - 550 ml bottles', Decimal('10', 22, 9), 13, 70, 25, false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) -VALUES (4, 'Chef Anton\'\'s Cajun Seasoning', 2, 2, '48 - 6 oz jars', Decimal('22', 22, 9), 53, 0, 0, false); +VALUES (4, 'Chef Anton\'s Cajun Seasoning', 2, 2, '48 - 6 oz jars', Decimal('22', 22, 9), 53, 0, 0, false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) -VALUES (5, 'Chef Anton\'\'s Gumbo Mix', 2, 2, '36 boxes', Decimal('21.35', 22, 9), 0, 0, 0, true); +VALUES (5, 'Chef Anton\'s Gumbo Mix', 2, 2, '36 boxes', Decimal('21.35', 22, 9), 0, 0, 0, true); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) -VALUES (6, 'Grandma\'\'s Boysenberry Spread', 3, 2, '12 - 8 oz jars', Decimal('25', 22, 9), 120, 0, 25, false); +VALUES (6, 'Grandma\'s Boysenberry Spread', 3, 2, '12 - 8 oz jars', Decimal('25', 22, 9), 120, 0, 25, false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) -VALUES (7, 'Uncle Bob\'\'s Organic Dried Pears', 3, 7, '12 - 1 lb pkgs.', Decimal('30', 22, 9), 15, 0, 10, false); +VALUES (7, 'Uncle Bob\'s Organic Dried Pears', 3, 7, '12 - 1 lb pkgs.', Decimal('30', 22, 9), 15, 0, 10, false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) VALUES (8, 'Northwoods Cranberry Sauce', 3, 2, '12 - 12 oz jars', Decimal('40', 22, 9), 6, 0, 0, false); @@ -10756,13 +10755,13 @@ INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, ` VALUES (19, 'Teatime Chocolate Biscuits', 8, 3, '10 boxes x 12 pieces', Decimal('9.2', 22, 9), 25, 0, 5, false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) -VALUES (20, 'Sir Rodney\'\'s Marmalade', 8, 3, '30 gift boxes', Decimal('81', 22, 9), 40, 0, 0, false); +VALUES (20, 'Sir Rodney\'s Marmalade', 8, 3, '30 gift boxes', Decimal('81', 22, 9), 40, 0, 0, false); GO INSERT INTO `Products`(`ProductID`,`ProductName`,`SupplierID`,`CategoryID`,`QuantityPerUnit`,`UnitPrice`,`UnitsInStock`,`UnitsOnOrder`,`ReorderLevel`,`Discontinued`) VALUES (21,'Sir Rodney\' \'s Scones',8,3,'24 pkgs. x 4 pieces',Decimal('10', 22, 9),3,40,5,false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) -VALUES (22, 'Gustaf\'\'s Knäckebröd', 9, 5, '24 - 500 g pkgs.', Decimal('21', 22, 9), 104, 0, 25, false); +VALUES (22, 'Gustaf\'s Knäckebröd', 9, 5, '24 - 500 g pkgs.', Decimal('21', 22, 9), 104, 0, 25, false); INSERT INTO `Products`(`ProductID`, `ProductName`, `SupplierID`, `CategoryID`, `QuantityPerUnit`, `UnitPrice`, `UnitsInStock`, `UnitsOnOrder`, `ReorderLevel`, `Discontinued`) VALUES (23, 'Tunnbröd', 9, 5, '12 - 250 g pkgs.', Decimal('9', 22, 9), 61, 0, 25, false); @@ -10939,7 +10938,7 @@ VALUES (2, 'New Orleans Cajun Delights', 'Shelley Burke', 'Order Administrator', '70117', 'USA', '(100) 555-4822', NULL, '#CAJUN.HTM#'); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) -VALUES (3, 'Grandma Kelly\'\'s Homestead', 'Regina Murphy', 'Sales Representative', '707 Oxford Rd.', 'Ann Arbor', 'MI', +VALUES (3, 'Grandma Kelly\'s Homestead', 'Regina Murphy', 'Sales Representative', '707 Oxford Rd.', 'Ann Arbor', 'MI', '48104', 'USA', '(313) 555-5735', '(313) 555-3349', NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) @@ -10947,20 +10946,20 @@ VALUES (4, 'Tokyo Traders', 'Yoshi Nagase', 'Marketing Manager', '9-8 Sekimai Mu 'Japan', '(03) 3555-5011', NULL, NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) -VALUES (5, 'Cooperativa de Quesos \'\'Las Cabras\'\'', 'Antonio del Valle Saavedra', 'Export Administrator', +VALUES (5, 'Cooperativa de Quesos \'Las Cabras\'', 'Antonio del Valle Saavedra', 'Export Administrator', 'Calle del Rosal 4', 'Oviedo', 'Asturias', '33007', 'Spain', '(98) 598 76 54', NULL, NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) -VALUES (6, 'Mayumi\'\'s', 'Mayumi Ohno', 'Marketing Representative', '92 Setsuko Chuo-ku', 'Osaka', NULL, '545', +VALUES (6, 'Mayumi\'s', 'Mayumi Ohno', 'Marketing Representative', '92 Setsuko Chuo-ku', 'Osaka', NULL, '545', 'Japan', '(06) 431-7877', NULL, - 'Mayumi\'\'s (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/mayumi.htm#'); + 'Mayumi\'s (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/mayumi.htm#'); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) VALUES (7, 'Pavlova, Ltd.', 'Ian Devling', 'Marketing Manager', '74 Rose St. Moonie Ponds', 'Melbourne', 'Victoria', '3058', 'Australia', '(03) 444-2343', '(03) 444-6588', NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) -VALUES (8, 'Specialty Biscuits, Ltd.', 'Peter Wilson', 'Sales Representative', '29 King\'\'s Way', 'Manchester', NULL, +VALUES (8, 'Specialty Biscuits, Ltd.', 'Peter Wilson', 'Sales Representative', '29 King\'s Way', 'Manchester', NULL, 'M14 GSD', 'UK', '(161) 555-4448', NULL, NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) @@ -11022,9 +11021,9 @@ VALUES (23, 'Karkki Oy', 'Anne Heikkonen', 'Product Manager', 'Valtakatu 12', 'L '(953) 10956', NULL, NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) -VALUES (24, 'G\'\'day, Mate', 'Wendy Mackenzie', 'Sales Representative', '170 Prince Edward Parade Hunter\'\'s Hill', +VALUES (24, 'G\'day, Mate', 'Wendy Mackenzie', 'Sales Representative', '170 Prince Edward Parade Hunter\'s Hill', 'Sydney', 'NSW', '2042', 'Australia', '(02) 555-5914', '(02) 555-4873', - 'G\'\'day Mate (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/gdaymate.htm#'); + 'G\'day Mate (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/gdaymate.htm#'); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) VALUES (25, 'Ma Maison', 'Jean-Guy Lauzon', 'Marketing Manager', '2960 Rue St. Laurent', 'Montréal', 'Québec', @@ -11043,7 +11042,7 @@ VALUES (28, 'Gai pâturage', 'Eliane Noz', 'Sales Representative', 'Bat. B 3, ru 'France', '38.76.98.06', '38.76.98.58', NULL); INSERT INTO `Suppliers`(`SupplierID`, `CompanyName`, `ContactName`, `ContactTitle`, `Address`, `City`, `Region`, `PostalCode`, `Country`, `Phone`, `Fax`, `HomePage`) -VALUES (29, 'Forêts d\'\'érables', 'Chantal Goulet', 'Accounting Manager', '148 rue Chasseur', 'Ste-Hyacinthe', +VALUES (29, 'Forêts d\'érables', 'Chantal Goulet', 'Accounting Manager', '148 rue Chasseur', 'Ste-Hyacinthe', 'Québec', 'J2S 7S8', 'Canada', '(514) 555-2955', '(514) 555-2921', NULL); GO CREATE TABLE `CustomerCustomerDemo` diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/NotificationEntitiesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/NotificationEntitiesYdbTest.cs similarity index 91% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/NotificationEntitiesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/NotificationEntitiesYdbTest.cs index c99eb1d8..c31583f0 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/NotificationEntitiesYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/NotificationEntitiesYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests; +namespace EntityFrameworkCore.Ydb.FunctionalTests; public class NotificationEntitiesYdbTest(NotificationEntitiesYdbTest.NotificationEntitiesYdbFixture fixture) : NotificationEntitiesTestBase(fixture) diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/OverzealousInitializationYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/OverzealousInitializationYdbTest.cs similarity index 91% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/OverzealousInitializationYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/OverzealousInitializationYdbTest.cs index e0f6a1b6..5bcb6441 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/OverzealousInitializationYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/OverzealousInitializationYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests; +namespace EntityFrameworkCore.Ydb.FunctionalTests; public class OverzealousInitializationYdbTest( OverzealousInitializationYdbTest.OverzealousInitializationYdbFixture fixture diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/PropertyValuesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/PropertyValuesYdbTest.cs similarity index 95% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/PropertyValuesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/PropertyValuesYdbTest.cs index a724491b..00d94cdd 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/PropertyValuesYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/PropertyValuesYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests; +namespace EntityFrameworkCore.Ydb.FunctionalTests; public class PropertyValuesYdbTest(PropertyValuesYdbTest.PropertyValuesYdbFixture fixture) : PropertyValuesTestBase(fixture) diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocAdvancedMappingsQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocAdvancedMappingsQueryYdbTest.cs similarity index 81% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocAdvancedMappingsQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocAdvancedMappingsQueryYdbTest.cs index 66efceda..8782c4db 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocAdvancedMappingsQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocAdvancedMappingsQueryYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; // TODO: Fix tests // Right now success rate is ~30/45 @@ -16,10 +16,6 @@ protected override ITestStoreFactory TestStoreFactory public override Task Two_similar_complex_properties_projected_with_split_query2() => Task.CompletedTask; - public override Task Projecting_one_of_two_similar_complex_types_picks_the_correct_one() => Task.CompletedTask; - - public override Task Hierarchy_query_with_abstract_type_sibling_TPT(bool async) => Task.CompletedTask; - public override Task Projecting_correlated_collection_along_with_non_mapped_property() => Task.CompletedTask; public override Task Double_convert_interface_created_expression_tree() => Task.CompletedTask; diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocComplexTypeQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocComplexTypeQueryYdbTest.cs similarity index 83% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocComplexTypeQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocComplexTypeQueryYdbTest.cs index 319a3a82..90b7ce68 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocComplexTypeQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocComplexTypeQueryYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; public class AdHocComplexTypeQueryYdbTest : AdHocComplexTypeQueryTestBase { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocNavigationsQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocNavigationsQueryYdbTest.cs similarity index 96% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocNavigationsQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocNavigationsQueryYdbTest.cs index 73ad6331..4ffd1b4a 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocNavigationsQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocNavigationsQueryYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; public class AdHocNavigationsQueryYdbTest : AdHocNavigationsQueryRelationalTestBase { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocQueryFiltersQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocQueryFiltersQueryYdbTest.cs similarity index 92% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocQueryFiltersQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocQueryFiltersQueryYdbTest.cs index d385d62f..b02f5500 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/AdHocQueryFiltersQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/AdHocQueryFiltersQueryYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; public class AdHocQueryFiltersQueryYdbTest : AdHocQueryFiltersQueryRelationalTestBase { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsCollectionsQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsCollectionsQueryYdbTest.cs new file mode 100644 index 00000000..be45f638 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsCollectionsQueryYdbTest.cs @@ -0,0 +1,152 @@ +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; +using Xunit; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Success rate: 250/300 +public class ComplexNavigationsCollectionsQueryYdbTest : ComplexNavigationsCollectionsQueryRelationalTestBase< + ComplexNavigationsQueryYdbFixture> +{ + public ComplexNavigationsCollectionsQueryYdbTest( + ComplexNavigationsQueryYdbFixture fixture, + ITestOutputHelper outputHelper + ) : base(fixture) + { + fixture.TestSqlLoggerFactory.Clear(); + fixture.TestSqlLoggerFactory.SetTestOutputHelper(outputHelper); + } + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_inside_subquery(bool async) => base.Include_inside_subquery(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Complex_query_with_let_collection_projection_FirstOrDefault_with_ToList_on_inner_and_outer(bool async) => + base.Complex_query_with_let_collection_projection_FirstOrDefault_with_ToList_on_inner_and_outer(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Complex_query_with_let_collection_projection_FirstOrDefault(bool async) => + base.Complex_query_with_let_collection_projection_FirstOrDefault(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Take_Select_collection_Take(bool async) => base.Take_Select_collection_Take(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_Select_collection_Skip_Take(bool async) => + base.Skip_Take_Select_collection_Skip_Take(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_multiple_orderbys_methodcall(bool async) => + base.Include_collection_with_multiple_orderbys_methodcall(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_multiple_orderbys_complex(bool async) => + base.Include_collection_with_multiple_orderbys_complex(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_multiple_with_filter(bool async) => + base.Include_collection_multiple_with_filter(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_multiple_with_filter_EF_Property(bool async) => + base.Include_collection_multiple_with_filter_EF_Property(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_after_different_filtered_include_different_level(bool async) => + base.Filtered_include_after_different_filtered_include_different_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(bool async) => + base.Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only( + bool async + ) => + base + .Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only( + async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_and_non_filtered_include_followed_by_then_include_on_same_navigation(bool async) => + base.Filtered_include_and_non_filtered_include_followed_by_then_include_on_same_navigation(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_complex_three_level_with_middle_having_filter1(bool async) => + base.Filtered_include_complex_three_level_with_middle_having_filter1(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_complex_three_level_with_middle_having_filter2(bool async) => + base.Filtered_include_complex_three_level_with_middle_having_filter2(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_context_accessed_inside_filter_correlated(bool async) => + base.Filtered_include_context_accessed_inside_filter_correlated(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_outer_parameter_used_inside_filter(bool async) => + base.Filtered_include_outer_parameter_used_inside_filter(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_Take_with_another_Take_on_top_level(bool async) => + base.Filtered_include_Take_with_another_Take_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_Skip_Take_with_another_Skip_Take_on_top_level(bool async) => + base.Filtered_include_Skip_Take_with_another_Skip_Take_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level( + bool async + ) => + base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level( + bool async + ) => + base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_Distinct_on_grouping_element(bool async) => + base.Skip_Take_Distinct_on_grouping_element(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_on_grouping_element_with_collection_include(bool async) => + base.Skip_Take_on_grouping_element_with_collection_include(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_on_grouping_element_with_reference_include(bool async) => + base.Skip_Take_on_grouping_element_with_reference_include(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_on_grouping_element_inside_collection_projection(bool async) => + base.Skip_Take_on_grouping_element_inside_collection_projection(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection( + bool async + ) => + base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection( + async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Complex_query_issue_21665(bool async) => base.Complex_query_issue_21665(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Projecting_collection_after_optional_reference_correlated_with_parent(bool async) => + base.Projecting_collection_after_optional_reference_correlated_with_parent(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Projecting_collection_with_group_by_after_optional_reference_correlated_with_parent(bool async) => + base.Projecting_collection_with_group_by_after_optional_reference_correlated_with_parent(async); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQueryYdbTest.cs new file mode 100644 index 00000000..5cbf6c3a --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsCollectionsSharedTypeQueryYdbTest.cs @@ -0,0 +1,135 @@ +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; +using Xunit; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Success rate: 250/300 +public class ComplexNavigationsCollectionsSharedTypeQueryYdbTest : + ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase< + ComplexNavigationsSharedTypeQueryYdbFixture> +{ + public ComplexNavigationsCollectionsSharedTypeQueryYdbTest( + ComplexNavigationsSharedTypeQueryYdbFixture fixture, + ITestOutputHelper testOutputHelper + ) : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Complex_query_with_let_collection_projection_FirstOrDefault_with_ToList_on_inner_and_outer(bool async) => + base.Complex_query_with_let_collection_projection_FirstOrDefault_with_ToList_on_inner_and_outer(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Complex_query_with_let_collection_projection_FirstOrDefault(bool async) => + base.Complex_query_with_let_collection_projection_FirstOrDefault(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Take_Select_collection_Take(bool async) => base.Take_Select_collection_Take(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_Select_collection_Skip_Take(bool async) => + base.Skip_Take_Select_collection_Skip_Take(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_multiple_with_filter(bool async) => + base.Include_collection_multiple_with_filter(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_multiple_with_filter_EF_Property(bool async) => + base.Include_collection_multiple_with_filter_EF_Property(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_after_different_filtered_include_different_level(bool async) => + base.Filtered_include_after_different_filtered_include_different_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(bool async) => + base.Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only( + bool async + ) => + base + .Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only( + async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_and_non_filtered_include_followed_by_then_include_on_same_navigation(bool async) => + base.Filtered_include_and_non_filtered_include_followed_by_then_include_on_same_navigation(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_complex_three_level_with_middle_having_filter1(bool async) => + base.Filtered_include_complex_three_level_with_middle_having_filter1(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_complex_three_level_with_middle_having_filter2(bool async) => + base.Filtered_include_complex_three_level_with_middle_having_filter2(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_context_accessed_inside_filter_correlated(bool async) => + base.Filtered_include_context_accessed_inside_filter_correlated(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_Take_with_another_Take_on_top_level(bool async) => + base.Filtered_include_Take_with_another_Take_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_include_Skip_Take_with_another_Skip_Take_on_top_level(bool async) => + base.Filtered_include_Skip_Take_with_another_Skip_Take_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level( + bool async + ) => + base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level( + bool async + ) => + base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_Distinct_on_grouping_element(bool async) => + base.Skip_Take_Distinct_on_grouping_element(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_on_grouping_element_with_collection_include(bool async) => + base.Skip_Take_on_grouping_element_with_collection_include(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_on_grouping_element_with_reference_include(bool async) => + base.Skip_Take_on_grouping_element_with_reference_include(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Skip_Take_on_grouping_element_inside_collection_projection(bool async) => + base.Skip_Take_on_grouping_element_inside_collection_projection(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection( + bool async + ) => + base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection( + async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Projecting_collection_after_optional_reference_correlated_with_parent(bool async) => + base.Projecting_collection_after_optional_reference_correlated_with_parent(async); + + [ConditionalTheory(Skip = "TODO: Try to fix correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Projecting_collection_with_group_by_after_optional_reference_correlated_with_parent(bool async) => + base.Projecting_collection_with_group_by_after_optional_reference_correlated_with_parent(async); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsQueryYdbFixture.cs new file mode 100644 index 00000000..d37ebe8d --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsQueryYdbFixture.cs @@ -0,0 +1,11 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class ComplexNavigationsQueryYdbFixture : ComplexNavigationsQueryRelationalFixtureBase +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsQueryYdbTest.cs new file mode 100644 index 00000000..17ed97d8 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsQueryYdbTest.cs @@ -0,0 +1,274 @@ +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; +using Xunit.Sdk; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Fix translation for INNER JOIN: +// Join cannot contain `>` +// ``` +// SELECT ... +// FROM ... AS `l` +// INNER JOIN ( +// SELECT ... +// FROM .. AS `l1` +// ) AS `l2` ON `l`.`Id` = `l2`.`Key` AND `l2`.`Sum` > 10 +// ``` +public class ComplexNavigationsQueryYdbTest + : ComplexNavigationsQueryRelationalTestBase +{ + public ComplexNavigationsQueryYdbTest(ComplexNavigationsQueryYdbFixture fixture) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Simple_level1_level2_GroupBy_Having_Count(bool async) => + base.Simple_level1_level2_GroupBy_Having_Count(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Optional_navigation_inside_nested_method_call_translated_to_join(bool async) => + base.Optional_navigation_inside_nested_method_call_translated_to_join(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Method_call_on_optional_navigation_translates_to_null_conditional_properly_for_arguments(bool async) => + base.Method_call_on_optional_navigation_translates_to_null_conditional_properly_for_arguments(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Optional_navigation_inside_method_call_translated_to_join_keeps_original_nullability(bool async) => + base.Optional_navigation_inside_method_call_translated_to_join_keeps_original_nullability(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability(bool async) => + base.Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability_also_for_arguments( + bool async + ) => + base + .Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability_also_for_arguments( + async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Query_source_materialization_bug_4547(bool async) => + base.Query_source_materialization_bug_4547(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection(bool async) => + base.Where_navigation_property_to_collection(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection2(bool async) => + base.Where_navigation_property_to_collection2(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection_of_original_entity_type(bool async) => + base.Where_navigation_property_to_collection_of_original_entity_type(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level(bool async) => + base.Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(bool async) => + base.Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task SelectMany_where_with_subquery(bool async) => base.SelectMany_where_with_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Select_join_with_key_selector_being_a_subquery(bool async) => + base.Select_join_with_key_selector_being_a_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Contains_with_subquery_optional_navigation_and_constant_item(bool async) => + base.Contains_with_subquery_optional_navigation_and_constant_item(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Contains_with_subquery_optional_navigation_scalar_distinct_and_constant_item(bool async) => + base.Contains_with_subquery_optional_navigation_scalar_distinct_and_constant_item(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_First_in_projection(bool async) => + base.Required_navigation_on_a_subquery_with_First_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_complex_projection_and_First(bool async) => + base.Required_navigation_on_a_subquery_with_complex_projection_and_First(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_First_in_predicate(bool async) => + base.Required_navigation_on_a_subquery_with_First_in_predicate(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_result_operator(bool async) => + base.GroupJoin_in_subquery_with_client_result_operator(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_projection(bool async) => + base.GroupJoin_in_subquery_with_client_projection(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_projection_nested1(bool async) => + base.GroupJoin_in_subquery_with_client_projection_nested1(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_projection_nested2(bool async) => + base.GroupJoin_in_subquery_with_client_projection_nested2(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Explicit_GroupJoin_in_subquery_with_scalar_result_operator(bool async) => + base.Explicit_GroupJoin_in_subquery_with_scalar_result_operator(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Explicit_GroupJoin_in_subquery_with_multiple_result_operator_distinct_count_materializes_main_clause( + bool async + ) => + base.Explicit_GroupJoin_in_subquery_with_multiple_result_operator_distinct_count_materializes_main_clause( + async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Join_condition_optimizations_applied_correctly_when_anonymous_type_with_single_property(bool async) => + base.Join_condition_optimizations_applied_correctly_when_anonymous_type_with_single_property(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task + Join_condition_optimizations_applied_correctly_when_anonymous_type_with_multiple_properties(bool async) => + base.Join_condition_optimizations_applied_correctly_when_anonymous_type_with_multiple_properties(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Navigations_compared_to_each_other3(bool async) => + base.Navigations_compared_to_each_other3(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Navigations_compared_to_each_other4(bool async) => + base.Navigations_compared_to_each_other4(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Navigations_compared_to_each_other5(bool async) => + base.Navigations_compared_to_each_other5(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_navigation1(bool async) => + base.Select_subquery_with_client_eval_and_navigation1(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_navigation2(bool async) => + base.Select_subquery_with_client_eval_and_navigation2(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_multi_level_navigation(bool async) => + base.Select_subquery_with_client_eval_and_multi_level_navigation(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Member_doesnt_get_pushed_down_into_subquery_with_result_operator(bool async) => + base.Member_doesnt_get_pushed_down_into_subquery_with_result_operator(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(bool async) => + base.Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_count(bool async) => + base.Project_collection_navigation_count(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Member_pushdown_chain_3_levels_deep(bool async) => + base.Member_pushdown_chain_3_levels_deep(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Member_pushdown_with_collection_navigation_in_the_middle(bool async) => + base.Member_pushdown_with_collection_navigation_in_the_middle(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Member_pushdown_with_multiple_collections(bool async) => + base.Member_pushdown_with_multiple_collections(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task OrderBy_collection_count_ThenBy_reference_navigation(bool async) => + base.OrderBy_collection_count_ThenBy_reference_navigation(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Sum_with_filter_with_include_selector_cast_using_as(bool async) => + base.Sum_with_filter_with_include_selector_cast_using_as(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(bool async) => + base.SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Contains_over_optional_navigation_with_null_column(bool async) => + base.Contains_over_optional_navigation_with_null_column(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Contains_over_optional_navigation_with_null_entity_reference(bool async) => + base.Contains_over_optional_navigation_with_null_entity_reference(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Element_selector_with_coalesce_repeated_in_aggregate(bool async) => + base.Element_selector_with_coalesce_repeated_in_aggregate(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Nested_object_constructed_from_group_key_properties(bool async) => + base.Nested_object_constructed_from_group_key_properties(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Let_let_contains_from_outer_let(bool async) => base.Let_let_contains_from_outer_let(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key2(bool async) => + base.Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key2(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Collection_FirstOrDefault_property_accesses_in_projection(bool async) => + base.Collection_FirstOrDefault_property_accesses_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Multiple_collection_FirstOrDefault_followed_by_member_access_in_projection(bool async) => + base.Multiple_collection_FirstOrDefault_followed_by_member_access_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Prune_does_not_throw_null_ref(bool async) => base.Prune_does_not_throw_null_ref(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_projection_with_first(bool async) => base.Correlated_projection_with_first(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Max_in_multi_level_nested_subquery(bool async) => + base.Max_in_multi_level_nested_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Multiple_select_many_in_projection(bool async) => + base.Multiple_select_many_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Single_select_many_in_projection_with_take(bool async) => + base.Single_select_many_in_projection_with_take(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key(bool async) => + base.Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_client_method_in_OrderBy(bool async) + => base.GroupJoin_client_method_in_OrderBy(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Nested_SelectMany_correlated_with_join_table_correctly_translated_to_apply(bool async) + => base.Nested_SelectMany_correlated_with_join_table_correctly_translated_to_apply(async); + + [ConditionalTheory(Skip = "TODO: Fix translation for INNER JOIN"), MemberData(nameof(IsAsyncData))] + public override Task Join_with_result_selector_returning_queryable_throws_validation_error(bool async) => + base.Join_with_result_selector_returning_queryable_throws_validation_error(async); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsSharedTypeQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsSharedTypeQueryYdbFixture.cs new file mode 100644 index 00000000..b5be897f --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsSharedTypeQueryYdbFixture.cs @@ -0,0 +1,11 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class ComplexNavigationsSharedTypeQueryYdbFixture : ComplexNavigationsSharedTypeQueryRelationalFixtureBase +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsSharedTypeQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsSharedTypeQueryYdbTest.cs new file mode 100644 index 00000000..cb1f024e --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/ComplexNavigationsSharedTypeQueryYdbTest.cs @@ -0,0 +1,249 @@ +using Microsoft.EntityFrameworkCore.Query; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Success rate ~500/550 +public class ComplexNavigationsSharedTypeQueryYdbTest + : ComplexNavigationsSharedTypeQueryRelationalTestBase +{ + public ComplexNavigationsSharedTypeQueryYdbTest(ComplexNavigationsSharedTypeQueryYdbFixture fixture) : base(fixture) + { + } + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Simple_level1_level2_GroupBy_Having_Count(bool async) => + base.Simple_level1_level2_GroupBy_Having_Count(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Optional_navigation_inside_nested_method_call_translated_to_join(bool async) => + base.Optional_navigation_inside_nested_method_call_translated_to_join(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Method_call_on_optional_navigation_translates_to_null_conditional_properly_for_arguments(bool async) => + base.Method_call_on_optional_navigation_translates_to_null_conditional_properly_for_arguments(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Optional_navigation_inside_method_call_translated_to_join_keeps_original_nullability(bool async) => + base.Optional_navigation_inside_method_call_translated_to_join_keeps_original_nullability(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability(bool async) => + base.Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability_also_for_arguments( + bool async + ) => + base + .Optional_navigation_inside_nested_method_call_translated_to_join_keeps_original_nullability_also_for_arguments( + async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Query_source_materialization_bug_4547(bool async) => + base.Query_source_materialization_bug_4547(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection(bool async) => + base.Where_navigation_property_to_collection(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection2(bool async) => + base.Where_navigation_property_to_collection2(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Where_navigation_property_to_collection_of_original_entity_type(bool async) => + base.Where_navigation_property_to_collection_of_original_entity_type(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level(bool async) => + base.Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(bool async) => + base.Correlated_subquery_doesnt_project_unnecessary_columns_in_top_level_join(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task SelectMany_where_with_subquery(bool async) => base.SelectMany_where_with_subquery(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Select_join_with_key_selector_being_a_subquery(bool async) => + base.Select_join_with_key_selector_being_a_subquery(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Contains_with_subquery_optional_navigation_and_constant_item(bool async) => + base.Contains_with_subquery_optional_navigation_and_constant_item(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Contains_with_subquery_optional_navigation_scalar_distinct_and_constant_item(bool async) => + base.Contains_with_subquery_optional_navigation_scalar_distinct_and_constant_item(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_First_in_projection(bool async) => + base.Required_navigation_on_a_subquery_with_First_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_complex_projection_and_First(bool async) => + base.Required_navigation_on_a_subquery_with_complex_projection_and_First(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Required_navigation_on_a_subquery_with_First_in_predicate(bool async) => + base.Required_navigation_on_a_subquery_with_First_in_predicate(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_result_operator(bool async) => + base.GroupJoin_in_subquery_with_client_result_operator(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_projection(bool async) => + base.GroupJoin_in_subquery_with_client_projection(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_projection_nested1(bool async) => + base.GroupJoin_in_subquery_with_client_projection_nested1(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_in_subquery_with_client_projection_nested2(bool async) => + base.GroupJoin_in_subquery_with_client_projection_nested2(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupJoin_client_method_in_OrderBy(bool async) => + base.GroupJoin_client_method_in_OrderBy(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Explicit_GroupJoin_in_subquery_with_scalar_result_operator(bool async) => + base.Explicit_GroupJoin_in_subquery_with_scalar_result_operator(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task + Explicit_GroupJoin_in_subquery_with_multiple_result_operator_distinct_count_materializes_main_clause( + bool async + ) => + base.Explicit_GroupJoin_in_subquery_with_multiple_result_operator_distinct_count_materializes_main_clause( + async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Navigations_compared_to_each_other3(bool async) => + base.Navigations_compared_to_each_other3(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Navigations_compared_to_each_other4(bool async) => + base.Navigations_compared_to_each_other4(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Navigations_compared_to_each_other5(bool async) => + base.Navigations_compared_to_each_other5(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_navigation1(bool async) => + base.Select_subquery_with_client_eval_and_navigation1(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_navigation2(bool async) => + base.Select_subquery_with_client_eval_and_navigation2(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_with_client_eval_and_multi_level_navigation(bool async) => + base.Select_subquery_with_client_eval_and_multi_level_navigation(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Member_doesnt_get_pushed_down_into_subquery_with_result_operator(bool async) => + base.Member_doesnt_get_pushed_down_into_subquery_with_result_operator(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(bool async) => + base.Subquery_with_Distinct_Skip_FirstOrDefault_without_OrderBy(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_count(bool async) => + base.Project_collection_navigation_count(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Member_pushdown_with_multiple_collections(bool async) => + base.Member_pushdown_with_multiple_collections(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task OrderBy_collection_count_ThenBy_reference_navigation(bool async) => + base.OrderBy_collection_count_ThenBy_reference_navigation(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Sum_with_filter_with_include_selector_cast_using_as(bool async) => + base.Sum_with_filter_with_include_selector_cast_using_as(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(bool async) => + base.SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Nested_SelectMany_correlated_with_join_table_correctly_translated_to_apply(bool async) => + base.Nested_SelectMany_correlated_with_join_table_correctly_translated_to_apply(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Contains_over_optional_navigation_with_null_column(bool async) => + base.Contains_over_optional_navigation_with_null_column(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Contains_over_optional_navigation_with_null_entity_reference(bool async) => + base.Contains_over_optional_navigation_with_null_entity_reference(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Element_selector_with_coalesce_repeated_in_aggregate(bool async) => + base.Element_selector_with_coalesce_repeated_in_aggregate(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Nested_object_constructed_from_group_key_properties(bool async) => + base.Nested_object_constructed_from_group_key_properties(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupBy_aggregate_where_required_relationship(bool async) => + base.GroupBy_aggregate_where_required_relationship(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task GroupBy_aggregate_where_required_relationship_2(bool async) => + base.GroupBy_aggregate_where_required_relationship_2(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Let_let_contains_from_outer_let(bool async) => base.Let_let_contains_from_outer_let(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key(bool async) => + base.Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key2(bool async) => + base.Composite_key_join_on_groupby_aggregate_projecting_only_grouping_key2(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Collection_FirstOrDefault_property_accesses_in_projection(bool async) => + base.Collection_FirstOrDefault_property_accesses_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Multiple_collection_FirstOrDefault_followed_by_member_access_in_projection(bool async) => + base.Multiple_collection_FirstOrDefault_followed_by_member_access_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Join_with_result_selector_returning_queryable_throws_validation_error(bool async) => + base.Join_with_result_selector_returning_queryable_throws_validation_error(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Prune_does_not_throw_null_ref(bool async) => base.Prune_does_not_throw_null_ref(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_projection_with_first(bool async) => base.Correlated_projection_with_first(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Max_in_multi_level_nested_subquery(bool async) => + base.Max_in_multi_level_nested_subquery(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Multiple_select_many_in_projection(bool async) => + base.Multiple_select_many_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Correlated subquery"), MemberData(nameof(IsAsyncData))] + public override Task Single_select_many_in_projection_with_take(bool async) => + base.Single_select_many_in_projection_with_take(async); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/CompositeKeysQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/CompositeKeysQueryYdbFixture.cs new file mode 100644 index 00000000..d8deb870 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/CompositeKeysQueryYdbFixture.cs @@ -0,0 +1,11 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class CompositeKeysQueryYdbFixture : CompositeKeysQueryRelationalFixtureBase +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/CompositeKeysQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/CompositeKeysQueryYdbTest.cs new file mode 100644 index 00000000..ca38afa1 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/CompositeKeysQueryYdbTest.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Query; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Unable to translate expression +public class CompositeKeysQueryYdbTest(CompositeKeysQueryYdbFixture fixture) + : CompositeKeysQueryRelationalTestBase(fixture) +{ + [ConditionalTheory(Skip = "TODO: Unable to translate"), MemberData(nameof(IsAsyncData))] + public override Task Projecting_multiple_collections_on_multiple_levels_some_explicit_ordering(bool async) => + base.Projecting_multiple_collections_on_multiple_levels_some_explicit_ordering(async); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/EntitySplittingQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/EntitySplittingQueryYdbTest.cs similarity index 85% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/EntitySplittingQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/EntitySplittingQueryYdbTest.cs index 0f762d7c..86fa47ae 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/EntitySplittingQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/EntitySplittingQueryYdbTest.cs @@ -1,8 +1,14 @@ using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using EntityFrameworkCore.Ydb.Storage.Internal; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; // TODO: Fix tests // Right now success rate is ~70/114 @@ -75,4 +81,10 @@ public override Task Tpc_entity_owning_a_split_reference_on_middle_without_table public override Task Tpc_entity_owning_a_split_reference_on_leaf_without_table_sharing(bool async) => Task.CompletedTask; + + protected override IServiceCollection AddServices(IServiceCollection serviceCollection) + { + serviceCollection.AddScoped(); + return serviceCollection; + } } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/FieldsOnlyLoadYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/FieldsOnlyLoadYdbTest.cs similarity index 59% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/FieldsOnlyLoadYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/FieldsOnlyLoadYdbTest.cs index 045361e9..8a2eee3e 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/FieldsOnlyLoadYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/FieldsOnlyLoadYdbTest.cs @@ -2,12 +2,13 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; -public abstract class FieldsOnlyLoadYdbTest(FieldsOnlyLoadYdbTest.FieldsOnlyLoadYdbFixture fixture) +public class FieldsOnlyLoadYdbTest(FieldsOnlyLoadYdbTest.FieldsOnlyLoadYdbFixture fixture) : FieldsOnlyLoadTestBase(fixture) { - public abstract class FieldsOnlyLoadYdbFixture : FieldsOnlyLoadFixtureBase + + public class FieldsOnlyLoadYdbFixture : FieldsOnlyLoadFixtureBase { protected override ITestStoreFactory TestStoreFactory => YdbTestStoreFactory.Instance; diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/FiltersInheritanceQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/FiltersInheritanceQueryYdbTest.cs new file mode 100644 index 00000000..b824c31f --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/FiltersInheritanceQueryYdbTest.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Query; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class FiltersInheritanceQueryYdbTest : FiltersInheritanceQueryTestBase +{ + public FiltersInheritanceQueryYdbTest(TphFiltersInheritanceQueryYdbFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarFromSqlQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarFromSqlQueryYdbTest.cs new file mode 100644 index 00000000..5f993185 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarFromSqlQueryYdbTest.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Query; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class GearsOfWarFromSqlQueryYdbTest : GearsOfWarFromSqlQueryTestBase +{ + public GearsOfWarFromSqlQueryYdbTest(GearsOfWarQueryYdbFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarQueryYdbFixture.cs new file mode 100644 index 00000000..e9e61151 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarQueryYdbFixture.cs @@ -0,0 +1,35 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.GearsOfWarModel; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class GearsOfWarQueryYdbFixture : GearsOfWarQueryRelationalFixture +{ + protected override string StoreName + => "GearsOfWarQueryTest"; + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity() + .Property(e => e.Date) + .HasConversion( + v => v.ToDateTime(TimeOnly.MinValue), + v => DateOnly.FromDateTime(v)); + + modelBuilder.Entity() + .Property(e => e.Duration) + .HasConversion( + v => new DateTime(1970, 1, 1).Add(v), + v => v.TimeOfDay); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarQueryYdbTest.cs new file mode 100644 index 00000000..b9619e9e --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/GearsOfWarQueryYdbTest.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore.Query; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Requires Time type and additional methods, contains correlated subqueries +internal class GearsOfWarQueryYdbTest + : GearsOfWarQueryRelationalTestBase +{ + public GearsOfWarQueryYdbTest( + GearsOfWarQueryYdbFixture fixture, + ITestOutputHelper outputHelper + ) : base(fixture) + { + fixture.TestSqlLoggerFactory.Clear(); + fixture.TestSqlLoggerFactory.SetTestOutputHelper(outputHelper); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/IncludeOneToOneYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/IncludeOneToOneYdbTest.cs similarity index 93% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/IncludeOneToOneYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/IncludeOneToOneYdbTest.cs index 20461857..6708b21c 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/IncludeOneToOneYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/IncludeOneToOneYdbTest.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; using Xunit.Abstractions; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; public class IncludeOneToOneYdbTest : IncludeOneToOneTestBase { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/InheritanceRelationshipsQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/InheritanceRelationshipsQueryYdbFixture.cs new file mode 100644 index 00000000..463ef8dd --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/InheritanceRelationshipsQueryYdbFixture.cs @@ -0,0 +1,11 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class InheritanceRelationshipsQueryYdbFixture : InheritanceRelationshipsQueryRelationalFixture +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/InheritanceRelationshipsQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/InheritanceRelationshipsQueryYdbTest.cs new file mode 100644 index 00000000..2c523af2 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/InheritanceRelationshipsQueryYdbTest.cs @@ -0,0 +1,6 @@ +using Microsoft.EntityFrameworkCore.Query; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class InheritanceRelationshipsQueryYdbTest(InheritanceRelationshipsQueryYdbFixture fixture) + : InheritanceRelationshipsQueryTestBase(fixture); \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindAggregateOperatorsQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindAggregateOperatorsQueryYdbTest.cs similarity index 99% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindAggregateOperatorsQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindAggregateOperatorsQueryYdbTest.cs index 3d404317..a1797bfe 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindAggregateOperatorsQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindAggregateOperatorsQueryYdbTest.cs @@ -1,8 +1,7 @@ -using EntityFrameworkCore.Ydb.FunctionalTests.Query; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; // TODO: Fix tests // Right now success rate is ~160/422 diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindCompiledQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindCompiledQueryYdbTest.cs similarity index 89% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindCompiledQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindCompiledQueryYdbTest.cs index 8dc1fc56..cf0a3bf9 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindCompiledQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindCompiledQueryYdbTest.cs @@ -1,11 +1,10 @@ -using EntityFrameworkCore.Ydb.FunctionalTests.Query; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit.Abstractions; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; -// TODO: Fix tests +// TODO: Fix tests. Success rate 23/32 public class NorthwindCompiledQueryYdbTest : NorthwindCompiledQueryTestBase> { diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindGroupByQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindGroupByQueryYdbTest.cs similarity index 98% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindGroupByQueryYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindGroupByQueryYdbTest.cs index 74dbef44..2eb3f53a 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NorthwindGroupByQueryYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NorthwindGroupByQueryYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; // TODO: Fix tests // Right now success rate is ~260/520 @@ -296,4 +296,6 @@ public override Task GroupBy_aggregate_projecting_conditional_expression_based_o public override Task GroupBy_count_filter(bool async) => Task.CompletedTask; public override Task GroupBy_Property_Select_Key_with_constant(bool async) => Task.CompletedTask; + + public override Task GroupBy_conditional_properties(bool async) => Task.CompletedTask; } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NullKeysYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NullKeysYdbTest.cs similarity index 89% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NullKeysYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NullKeysYdbTest.cs index 15bc3a6e..10da2c6f 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Query/NullKeysYdbTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/NullKeysYdbTest.cs @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.TestUtilities; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests.Query; +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; public class NullKeysYdbTest(NullKeysYdbTest.NullKeysYdbFixture fixture) : NullKeysTestBase(fixture) diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/QueryNoClientEvalYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/QueryNoClientEvalYdbFixture.cs new file mode 100644 index 00000000..8790add3 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/QueryNoClientEvalYdbFixture.cs @@ -0,0 +1,5 @@ +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class QueryNoClientEvalYdbFixture: NorthwindQueryYdbFixture; \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPCGearsOfWarQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPCGearsOfWarQueryYdbFixture.cs new file mode 100644 index 00000000..ef15affc --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPCGearsOfWarQueryYdbFixture.cs @@ -0,0 +1,33 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.GearsOfWarModel; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Ydb.Sdk.Ado; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class TPCGearsOfWarQueryYdbFixture : TPCGearsOfWarQueryRelationalFixture +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity() + .Property(e => e.Time) + .HasConversion( + v => new DateTime(2000, 1, 1).Add(v.ToTimeSpan()), // Time → DateTime + v => new TimeOnly(v.TimeOfDay.Ticks)) // DateTime → Time + .HasColumnType("DATETIME"); + + modelBuilder.Entity() + .Property(e => e.Duration) + .HasConversion( + v => new DateTime(2000, 1, 1).Add(v), // TimeSpan → DateTime + v => v.TimeOfDay) // DateTime → TimeSpan + .HasColumnType("DATETIME"); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPCGearsOfWarQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPCGearsOfWarQueryYdbTest.cs new file mode 100644 index 00000000..fc9c9639 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPCGearsOfWarQueryYdbTest.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore.Query; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Requires Time type and additional methods, contains correlated subqueries +internal class TpcGearsOfWarQueryYdbTest : TPCGearsOfWarQueryRelationalTestBase +{ + public TpcGearsOfWarQueryYdbTest(TPCGearsOfWarQueryYdbFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPHFiltersInheritanceQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPHFiltersInheritanceQueryYdbFixture.cs new file mode 100644 index 00000000..78e4eba0 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPHFiltersInheritanceQueryYdbFixture.cs @@ -0,0 +1,7 @@ +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class TphFiltersInheritanceQueryYdbFixture : TphInheritanceQueryYdbFixture +{ + public override bool EnableFilters + => true; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPHInheritanceQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPHInheritanceQueryYdbFixture.cs new file mode 100644 index 00000000..c1a1f437 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPHInheritanceQueryYdbFixture.cs @@ -0,0 +1,29 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.InheritanceModel; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class TphInheritanceQueryYdbFixture : TPHInheritanceQueryFixture +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + // TODO: For unknown reason ToSqlQuery doesn't work + // Better to use it but ToView is pretty good replacement + modelBuilder + .Entity() + .HasNoKey() + .ToView( + """ + SELECT * FROM "Animals" + """ + ); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTGearsOfWarQueryYdbFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTGearsOfWarQueryYdbFixture.cs new file mode 100644 index 00000000..18f3e6ef --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTGearsOfWarQueryYdbFixture.cs @@ -0,0 +1,32 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestModels.GearsOfWarModel; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class TptGearsOfWarQueryYdbFixture: TPTGearsOfWarQueryRelationalFixture +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity() + .Property(e => e.Time) + .HasConversion( + v => new DateTime(2000, 1, 1).Add(v.ToTimeSpan()), // Time → DateTime + v => new TimeOnly(v.TimeOfDay.Ticks)) // DateTime → Time + .HasColumnType("DATETIME"); + + modelBuilder.Entity() + .Property(e => e.Date) + .HasConversion( + v => new DateTime(v.Year, v.Month, v.Day), // DateOnly → DateTime + v => new DateOnly(v.Year, v.Month, v.Day)) // DateTime → DateOnly + .HasColumnType("DATETIME"); + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTGearsOfWarQueryYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTGearsOfWarQueryYdbTest.cs new file mode 100644 index 00000000..094522d4 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTGearsOfWarQueryYdbTest.cs @@ -0,0 +1,938 @@ +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +// TODO: Correlated subqueries right now are not supported in YDB +public class TptGearsOfWarQueryYdbTest : TPTGearsOfWarQueryRelationalTestBase +{ + // ReSharper disable once UnusedParameter.Local + public TptGearsOfWarQueryYdbTest(TptGearsOfWarQueryYdbFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Correlated_collection_with_distinct_not_projecting_identifier_column_also_projecting_complex_expressions( + bool async + ) => + base.Correlated_collection_with_distinct_not_projecting_identifier_column_also_projecting_complex_expressions( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_after_distinct_3_levels_without_original_identifiers(bool async) => + base.Correlated_collection_after_distinct_3_levels_without_original_identifiers(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_and_enum(bool async) => base.Where_bitwise_and_enum(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_and_integral(bool async) => base.Where_bitwise_and_integral(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_and_nullable_enum_with_constant(bool async) => + base.Where_bitwise_and_nullable_enum_with_constant(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_and_nullable_enum_with_null_constant(bool async) => + base.Where_bitwise_and_nullable_enum_with_null_constant(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_and_nullable_enum_with_non_nullable_parameter(bool async) => + base.Where_bitwise_and_nullable_enum_with_non_nullable_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_and_nullable_enum_with_nullable_parameter(bool async) => + base.Where_bitwise_and_nullable_enum_with_nullable_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_bitwise_or_enum(bool async) => base.Where_bitwise_or_enum(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Bitwise_projects_values_in_select(bool async) => base.Bitwise_projects_values_in_select(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_enum_has_flag(bool async) => base.Where_enum_has_flag(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_enum_has_flag_subquery(bool async) => base.Where_enum_has_flag_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_enum_has_flag_subquery_with_pushdown(bool async) => + base.Where_enum_has_flag_subquery_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_enum_has_flag_subquery_client_eval(bool async) => + base.Where_enum_has_flag_subquery_client_eval(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_enum_has_flag_with_non_nullable_parameter(bool async) => + base.Where_enum_has_flag_with_non_nullable_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_has_flag_with_nullable_parameter(bool async) => + base.Where_has_flag_with_nullable_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_enum_has_flag(bool async) => base.Select_enum_has_flag(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_count_subquery_without_collision(bool async) => + base.Where_count_subquery_without_collision(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_any_subquery_without_collision(bool async) => + base.Where_any_subquery_without_collision(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_null_parameter(bool async) => base.Select_null_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Null_propagation_optimization4(bool async) => base.Null_propagation_optimization4(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Null_propagation_optimization5(bool async) => base.Null_propagation_optimization5(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Null_propagation_optimization6(bool async) => base.Null_propagation_optimization6(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_null_propagation_negative3(bool async) => base.Select_null_propagation_negative3(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_null_propagation_negative4(bool async) => base.Select_null_propagation_negative4(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_null_propagation_negative5(bool async) => base.Select_null_propagation_negative5(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_null_propagation_works_for_multiple_navigations_with_composite_keys(bool async) => + base.Select_null_propagation_works_for_multiple_navigations_with_composite_keys(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_boolean(bool async) => base.Where_subquery_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_boolean_with_pushdown(bool async) => + base.Where_subquery_boolean_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_firstordefault_boolean(bool async) => + base.Where_subquery_distinct_firstordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_firstordefault_boolean_with_pushdown(bool async) => + base.Where_subquery_distinct_firstordefault_boolean_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_first_boolean(bool async) => + base.Where_subquery_distinct_first_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_singleordefault_boolean1(bool async) => + base.Where_subquery_distinct_singleordefault_boolean1(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_singleordefault_boolean2(bool async) => + base.Where_subquery_distinct_singleordefault_boolean2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_singleordefault_boolean_with_pushdown(bool async) => + base.Where_subquery_distinct_singleordefault_boolean_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_lastordefault_boolean(bool async) => + base.Where_subquery_distinct_lastordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_last_boolean(bool async) => + base.Where_subquery_distinct_last_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_orderby_firstordefault_boolean(bool async) => + base.Where_subquery_distinct_orderby_firstordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_distinct_orderby_firstordefault_boolean_with_pushdown(bool async) => + base.Where_subquery_distinct_orderby_firstordefault_boolean_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_union_firstordefault_boolean(bool async) => + base.Where_subquery_union_firstordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_join_firstordefault_boolean(bool async) => + base.Where_subquery_join_firstordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_left_join_firstordefault_boolean(bool async) => + base.Where_subquery_left_join_firstordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_concat_firstordefault_boolean(bool async) => + base.Where_subquery_concat_firstordefault_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_navigation_with_concat_and_count(bool async) => + base.Select_navigation_with_concat_and_count(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Concat_with_collection_navigations(bool async) => + base.Concat_with_collection_navigations(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Union_with_collection_navigations(bool async) => base.Union_with_collection_navigations(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_firstordefault(bool async) => + base.Select_subquery_distinct_firstordefault(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Non_unicode_string_literals_is_used_for_non_unicode_column_with_subquery(bool async) => + base.Non_unicode_string_literals_is_used_for_non_unicode_column_with_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Join_predicate_value_equals_condition(bool async) => + base.Join_predicate_value_equals_condition(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Join_predicate_value(bool async) => base.Join_predicate_value(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Join_predicate_condition_equals_condition(bool async) => + base.Join_predicate_condition_equals_condition(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Left_join_predicate_value_equals_condition(bool async) => + base.Left_join_predicate_value_equals_condition(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Left_join_predicate_value(bool async) => base.Left_join_predicate_value(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Left_join_predicate_condition_equals_condition(bool async) => + base.Left_join_predicate_condition_equals_condition(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_now(bool async) => base.Where_datetimeoffset_now(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_utcnow(bool async) => base.Where_datetimeoffset_utcnow(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_date_component(bool async) => + base.Where_datetimeoffset_date_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_year_component(bool async) => + base.Where_datetimeoffset_year_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_month_component(bool async) => + base.Where_datetimeoffset_month_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_dayofyear_component(bool async) => + base.Where_datetimeoffset_dayofyear_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_day_component(bool async) => + base.Where_datetimeoffset_day_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_hour_component(bool async) => + base.Where_datetimeoffset_hour_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_minute_component(bool async) => + base.Where_datetimeoffset_minute_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_second_component(bool async) => + base.Where_datetimeoffset_second_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_datetimeoffset_millisecond_component(bool async) => + base.Where_datetimeoffset_millisecond_component(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddYears(bool async) => base.DateTimeOffset_DateAdd_AddYears(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddMonths(bool async) => base.DateTimeOffset_DateAdd_AddMonths(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddDays(bool async) => base.DateTimeOffset_DateAdd_AddDays(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddHours(bool async) => base.DateTimeOffset_DateAdd_AddHours(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddMinutes(bool async) => base.DateTimeOffset_DateAdd_AddMinutes(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_DateAdd_AddSeconds(bool async) => base.DateTimeOffset_DateAdd_AddSeconds(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Any_with_optional_navigation_as_subquery_predicate_is_translated_to_sql(bool async) => + base.Any_with_optional_navigation_as_subquery_predicate_is_translated_to_sql(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Subquery_created_by_include_gets_lifted_nested(bool async) => + base.Subquery_created_by_include_gets_lifted_nested(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Skip_with_orderby_followed_by_orderBy_is_pushed_down(bool async) => + base.Skip_with_orderby_followed_by_orderBy_is_pushed_down(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Take_without_orderby_followed_by_orderBy_is_pushed_down1(bool async) => + base.Take_without_orderby_followed_by_orderBy_is_pushed_down1(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Take_without_orderby_followed_by_orderBy_is_pushed_down2(bool async) => + base.Take_without_orderby_followed_by_orderBy_is_pushed_down2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Collection_navigation_access_on_derived_entity_using_cast(bool async) => + base.Collection_navigation_access_on_derived_entity_using_cast(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Optional_navigation_with_collection_composite_key(bool async) => + base.Optional_navigation_with_collection_composite_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_with_inheritance2(bool async) => + base.Project_collection_navigation_with_inheritance2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_with_inheritance3(bool async) => + base.Project_collection_navigation_with_inheritance3(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Include_reference_on_derived_type_using_string_nested2(bool async) => + base.Include_reference_on_derived_type_using_string_nested2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task ThenInclude_collection_on_derived_after_derived_reference(bool async) => + base.ThenInclude_collection_on_derived_after_derived_reference(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Multiple_derived_included_on_one_method(bool async) => + base.Multiple_derived_included_on_one_method(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_naked_navigation_with_ToList_followed_by_projecting_count(bool async) => + base.Correlated_collections_naked_navigation_with_ToList_followed_by_projecting_count(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys(bool async) => + base.Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys_inside_subquery(bool async) => + base.Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys_inside_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys_inside_subquery_duplicated_orderings( + bool async + ) => + base.Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys_inside_subquery_duplicated_orderings( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys_inside_subquery_complex_orderings( + bool async + ) => base.Multiple_orderby_with_navigation_expansion_on_one_of_the_order_bys_inside_subquery_complex_orderings( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_multiple_nested_complex_collections(bool async) => + base.Correlated_collections_multiple_nested_complex_collections(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_inner_subquery_selector_references_outer_qsre(bool async) => + base.Correlated_collections_inner_subquery_selector_references_outer_qsre(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_inner_subquery_predicate_references_outer_qsre(bool async) => + base.Correlated_collections_inner_subquery_predicate_references_outer_qsre(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_nested_inner_subquery_references_outer_qsre_one_level_up(bool async) => + base.Correlated_collections_nested_inner_subquery_references_outer_qsre_one_level_up(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_nested_inner_subquery_references_outer_qsre_two_levels_up(bool async) => + base.Correlated_collections_nested_inner_subquery_references_outer_qsre_two_levels_up(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_with_Distinct(bool async) => + base.Correlated_collections_with_Distinct(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_with_FirstOrDefault(bool async) => + base.Correlated_collections_with_FirstOrDefault(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collections_left_join_with_self_reference(bool async) => + base.Correlated_collections_left_join_with_self_reference(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Include_on_derived_type_with_order_by_and_paging(bool async) => + base.Include_on_derived_type_with_order_by_and_paging(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Outer_parameter_in_join_key(bool async) => base.Outer_parameter_in_join_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Outer_parameter_in_join_key_inner_and_outer(bool async) => + base.Outer_parameter_in_join_key_inner_and_outer(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Outer_parameter_in_group_join_with_DefaultIfEmpty(bool async) => + base.Outer_parameter_in_group_join_with_DefaultIfEmpty(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_one_value_type_from_empty_collection(bool async) => + base.Project_one_value_type_from_empty_collection(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_one_value_type_converted_to_nullable_from_empty_collection(bool async) => + base.Project_one_value_type_converted_to_nullable_from_empty_collection(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Filter_on_subquery_projecting_one_value_type_from_empty_collection(bool async) => + base.Filter_on_subquery_projecting_one_value_type_from_empty_collection(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_projecting_single_constant_int(bool async) => + base.Select_subquery_projecting_single_constant_int(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_projecting_single_constant_string(bool async) => + base.Select_subquery_projecting_single_constant_string(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_projecting_single_constant_bool(bool async) => + base.Select_subquery_projecting_single_constant_bool(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_OrderBy_aggregate(bool async) => + base.Include_collection_OrderBy_aggregate(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_complex_OrderBy2(bool async) => + base.Include_collection_with_complex_OrderBy2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Include_collection_with_complex_OrderBy3(bool async) => + base.Include_collection_with_complex_OrderBy3(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_complex_OrderBy(bool async) => + base.Correlated_collection_with_complex_OrderBy(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_very_complex_order_by(bool async) => + base.Correlated_collection_with_very_complex_order_by(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_boolean(bool async) => base.Select_subquery_boolean(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_boolean_with_pushdown(bool async) => + base.Select_subquery_boolean_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_int_with_inside_cast_and_coalesce(bool async) => + base.Select_subquery_int_with_inside_cast_and_coalesce(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_int_with_outside_cast_and_coalesce(bool async) => + base.Select_subquery_int_with_outside_cast_and_coalesce(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_int_with_pushdown_and_coalesce(bool async) => + base.Select_subquery_int_with_pushdown_and_coalesce(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_int_with_pushdown_and_coalesce2(bool async) => + base.Select_subquery_int_with_pushdown_and_coalesce2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_boolean_empty(bool async) => base.Select_subquery_boolean_empty(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_boolean_empty_with_pushdown(bool async) => + base.Select_subquery_boolean_empty_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_singleordefault_boolean1(bool async) => + base.Select_subquery_distinct_singleordefault_boolean1(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_singleordefault_boolean2(bool async) => + base.Select_subquery_distinct_singleordefault_boolean2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_singleordefault_boolean_with_pushdown(bool async) => + base.Select_subquery_distinct_singleordefault_boolean_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_singleordefault_boolean_empty1(bool async) => + base.Select_subquery_distinct_singleordefault_boolean_empty1(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_singleordefault_boolean_empty2(bool async) => + base.Select_subquery_distinct_singleordefault_boolean_empty2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Select_subquery_distinct_singleordefault_boolean_empty_with_pushdown(bool async) => + base.Select_subquery_distinct_singleordefault_boolean_empty_with_pushdown(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task GroupBy_Property_Include_Select_LongCount(bool async) => + base.GroupBy_Property_Include_Select_LongCount(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task GroupBy_Property_Include_Aggregate_with_anonymous_selector(bool async) => + base.GroupBy_Property_Include_Aggregate_with_anonymous_selector(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task OrderBy_same_expression_containing_IsNull_correctly_deduplicates_the_ordering(bool async) => + base.OrderBy_same_expression_containing_IsNull_correctly_deduplicates_the_ordering(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task GetValueOrDefault_with_argument_complex(bool async) => + base.GetValueOrDefault_with_argument_complex(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Filter_with_complex_predicate_containing_subquery(bool async) => + base.Filter_with_complex_predicate_containing_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Query_with_complex_let_containing_ordering_and_filter_projecting_firstOrDefault_element_of_let(bool async) => + base.Query_with_complex_let_containing_ordering_and_filter_projecting_firstOrDefault_element_of_let(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation( + bool async + ) => + base.Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation_complex( + bool async + ) => + base + .Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation_complex( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_contains_on_navigation_with_composite_keys(bool async) => + base.Where_contains_on_navigation_with_composite_keys(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Include_with_complex_order_by(bool async) => base.Include_with_complex_order_by(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Bool_projection_from_subquery_treated_appropriately_in_where(bool async) => + base.Bool_projection_from_subquery_treated_appropriately_in_where(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_Contains_Less_than_Greater_than(bool async) => + base.DateTimeOffset_Contains_Less_than_Greater_than(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffsetNow_minus_timespan(bool async) => base.DateTimeOffsetNow_minus_timespan(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_nested_with_take_composite_key(bool async) => + base.Project_collection_navigation_nested_with_take_composite_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_collection_navigation_nested_composite_key(bool async) => + base.Project_collection_navigation_nested_composite_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Null_checks_in_correlated_predicate_are_correctly_translated(bool async) => + base.Null_checks_in_correlated_predicate_are_correctly_translated(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Collection_navigation_ofType_filter_works(bool async) => + base.Collection_navigation_ofType_filter_works(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Query_reusing_parameter_with_inner_query_expression_doesnt_declare_duplicate_parameter(bool async) => + base.Query_reusing_parameter_with_inner_query_expression_doesnt_declare_duplicate_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Complex_GroupBy_after_set_operator(bool async) => + base.Complex_GroupBy_after_set_operator(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Complex_GroupBy_after_set_operator_using_result_selector(bool async) => + base.Complex_GroupBy_after_set_operator_using_result_selector(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task GroupBy_with_boolean_groupin_key_thru_navigation_access(bool async) => + base.GroupBy_with_boolean_groupin_key_thru_navigation_access(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_with_enum_flags_parameter(bool async) => base.Where_with_enum_flags_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + FirstOrDefault_navigation_access_entity_equality_in_where_predicate_apply_peneding_selector(bool async) => + base.FirstOrDefault_navigation_access_entity_equality_in_where_predicate_apply_peneding_selector(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Conditional_expression_with_test_being_simplified_to_constant_complex(bool isAsync) => + base.Conditional_expression_with_test_being_simplified_to_constant_complex(isAsync); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Bitwise_operation_with_non_null_parameter_optimizes_null_checks(bool async) => + base.Bitwise_operation_with_non_null_parameter_optimizes_null_checks(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Bitwise_operation_with_null_arguments(bool async) => + base.Bitwise_operation_with_null_arguments(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Byte_array_filter_by_length_literal_does_not_cast_on_varbinary_n(bool async) => + base.Byte_array_filter_by_length_literal_does_not_cast_on_varbinary_n(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Byte_array_filter_by_length_literal(bool async) => + base.Byte_array_filter_by_length_literal(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Byte_array_filter_by_length_parameter(bool async) => + base.Byte_array_filter_by_length_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override void Byte_array_filter_by_length_parameter_compiled() => + base.Byte_array_filter_by_length_parameter_compiled(); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_Date_returns_datetime(bool async) => + base.DateTimeOffset_Date_returns_datetime(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeSpan_Hours(bool async) => base.Where_TimeSpan_Hours(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeSpan_Minutes(bool async) => base.Where_TimeSpan_Minutes(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeSpan_Seconds(bool async) => base.Where_TimeSpan_Seconds(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeSpan_Milliseconds(bool async) => base.Where_TimeSpan_Milliseconds(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Contains_on_collection_of_nullable_byte_subquery(bool async) => + base.Contains_on_collection_of_nullable_byte_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion(bool async) => + base.Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion_negated( + bool async + ) => + base.Subquery_projecting_non_nullable_scalar_contains_non_nullable_value_doesnt_need_null_expansion_negated( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion(bool async) => + base.Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion_negated(bool async) => + base.Subquery_projecting_nullable_scalar_contains_nullable_value_needs_null_expansion_negated(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Enum_flags_closure_typed_as_underlying_type_generates_correct_parameter_type(bool async) => + base.Enum_flags_closure_typed_as_underlying_type_generates_correct_parameter_type(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Enum_flags_closure_typed_as_different_type_generates_correct_parameter_type(bool async) => + base.Enum_flags_closure_typed_as_different_type_generates_correct_parameter_type(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Constant_enum_with_same_underlying_value_as_previously_parameterized_int(bool async) => + base.Constant_enum_with_same_underlying_value_as_previously_parameterized_int(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task SelectMany_predicate_with_non_equality_comparison_converted_to_inner_join(bool async) => + base.SelectMany_predicate_with_non_equality_comparison_converted_to_inner_join(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + SelectMany_predicate_with_non_equality_comparison_DefaultIfEmpty_converted_to_left_join(bool async) => + base.SelectMany_predicate_with_non_equality_comparison_DefaultIfEmpty_converted_to_left_join(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + SelectMany_predicate_after_navigation_with_non_equality_comparison_DefaultIfEmpty_converted_to_left_join( + bool async + ) => + base.SelectMany_predicate_after_navigation_with_non_equality_comparison_DefaultIfEmpty_converted_to_left_join( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task SelectMany_without_result_selector_and_non_equality_comparison_converted_to_join(bool async) => + base.SelectMany_without_result_selector_and_non_equality_comparison_converted_to_join(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Filtered_collection_projection_with_order_comparison_predicate_converted_to_join(bool async) => + base.Filtered_collection_projection_with_order_comparison_predicate_converted_to_join(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_collection_projection_with_order_comparison_predicate_converted_to_join2(bool async) => + base.Filtered_collection_projection_with_order_comparison_predicate_converted_to_join2(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Filtered_collection_projection_with_order_comparison_predicate_converted_to_join3(bool async) => + base.Filtered_collection_projection_with_order_comparison_predicate_converted_to_join3(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + SelectMany_predicate_with_non_equality_comparison_with_Take_doesnt_convert_to_join(bool async) => + base.SelectMany_predicate_with_non_equality_comparison_with_Take_doesnt_convert_to_join(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task FirstOrDefault_over_int_compared_to_zero(bool async) => + base.FirstOrDefault_over_int_compared_to_zero(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_inner_collection_references_element_two_levels_up(bool async) => + base.Correlated_collection_with_inner_collection_references_element_two_levels_up(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task FirstOrDefault_on_empty_collection_of_DateTime_in_subquery(bool async) => + base.FirstOrDefault_on_empty_collection_of_DateTime_in_subquery(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task First_on_byte_array(bool async) => base.First_on_byte_array(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Array_access_on_byte_array(bool async) => base.Array_access_on_byte_array(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Projecting_property_converted_to_nullable_with_function_call(bool async) => + base.Projecting_property_converted_to_nullable_with_function_call(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Projecting_property_converted_to_nullable_into_member_access(bool async) => + base.Projecting_property_converted_to_nullable_into_member_access(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_distinct_projecting_identifier_column(bool async) => + base.Correlated_collection_with_distinct_projecting_identifier_column(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_with_distinct_not_projecting_identifier_column(bool async) => + base.Correlated_collection_with_distinct_not_projecting_identifier_column(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Correlated_collection_with_groupby_not_projecting_identifier_column_but_only_grouping_key_in_final_projection( + bool async + ) => + base + .Correlated_collection_with_groupby_not_projecting_identifier_column_but_only_grouping_key_in_final_projection( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection( + bool async + ) => + base + .Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection_multiple_grouping_keys( + bool async + ) => + base + .Correlated_collection_with_groupby_not_projecting_identifier_column_with_group_aggregate_in_final_projection_multiple_grouping_keys( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Correlated_collection_with_groupby_with_complex_grouping_key_not_projecting_identifier_column_with_group_aggregate_in_final_projection( + bool async + ) => + base + .Correlated_collection_with_groupby_with_complex_grouping_key_not_projecting_identifier_column_with_group_aggregate_in_final_projection( + async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Correlated_collection_via_SelectMany_with_Distinct_missing_indentifying_columns_in_projection(bool async) => + base.Correlated_collection_via_SelectMany_with_Distinct_missing_indentifying_columns_in_projection(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Correlated_collection_after_distinct_3_levels(bool async) => + base.Correlated_collection_after_distinct_3_levels(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_DateOnly_Month(bool async) => base.Where_DateOnly_Month(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_DateOnly_AddYears(bool async) => base.Where_DateOnly_AddYears(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_DateOnly_AddMonths(bool async) => base.Where_DateOnly_AddMonths(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_DateOnly_AddDays(bool async) => base.Where_DateOnly_AddDays(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_Hour(bool async) => base.Where_TimeOnly_Hour(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_Minute(bool async) => base.Where_TimeOnly_Minute(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_Second(bool async) => base.Where_TimeOnly_Second(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_Millisecond(bool async) => base.Where_TimeOnly_Millisecond(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_AddHours(bool async) => base.Where_TimeOnly_AddHours(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_AddMinutes(bool async) => base.Where_TimeOnly_AddMinutes(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_Add_TimeSpan(bool async) => base.Where_TimeOnly_Add_TimeSpan(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_IsBetween(bool async) => base.Where_TimeOnly_IsBetween(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_subtract_TimeOnly(bool async) => base.Where_TimeOnly_subtract_TimeOnly(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_FromDateTime_compared_to_property(bool async) => + base.Where_TimeOnly_FromDateTime_compared_to_property(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_FromDateTime_compared_to_parameter(bool async) => + base.Where_TimeOnly_FromDateTime_compared_to_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_FromDateTime_compared_to_constant(bool async) => + base.Where_TimeOnly_FromDateTime_compared_to_constant(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_FromTimeSpan_compared_to_property(bool async) => + base.Where_TimeOnly_FromTimeSpan_compared_to_property(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_TimeOnly_FromTimeSpan_compared_to_parameter(bool async) => + base.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Order_by_TimeOnly_FromTimeSpan(bool async) => base.Order_by_TimeOnly_FromTimeSpan(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_DateOnly_FromDateTime_compared_to_property(bool async) => + base.Where_DateOnly_FromDateTime_compared_to_property(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_DateOnly_FromDateTime_compared_to_constant_and_parameter(bool async) => + base.Where_DateOnly_FromDateTime_compared_to_constant_and_parameter(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Project_navigation_defined_on_base_from_entity_with_inheritance_using_soft_cast(bool async) => + base.Project_navigation_defined_on_base_from_entity_with_inheritance_using_soft_cast(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task + Project_navigation_defined_on_derived_from_entity_with_inheritance_using_soft_cast(bool async) => + base.Project_navigation_defined_on_derived_from_entity_with_inheritance_using_soft_cast(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Join_entity_with_itself_grouped_by_key_followed_by_include_skip_take(bool async) => + base.Join_entity_with_itself_grouped_by_key_followed_by_include_skip_take(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Enum_matching_take_value_gets_different_type_mapping(bool async) => + base.Enum_matching_take_value_gets_different_type_mapping(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_equality_to_null_with_composite_key(bool async) => + base.Where_subquery_equality_to_null_with_composite_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_equality_to_null_with_composite_key_should_match_nulls(bool async) => + base.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_equality_to_null_without_composite_key(bool async) => + base.Where_subquery_equality_to_null_without_composite_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_equality_to_null_without_composite_key_should_match_null(bool async) => + base.Where_subquery_equality_to_null_without_composite_key_should_match_null(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_with_ElementAtOrDefault_equality_to_null_with_composite_key(bool async) => + base.Where_subquery_with_ElementAtOrDefault_equality_to_null_with_composite_key(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Where_subquery_with_ElementAt_using_column_as_index(bool async) => + base.Where_subquery_with_ElementAt_using_column_as_index(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_to_unix_time_milliseconds(bool async) => + base.DateTimeOffset_to_unix_time_milliseconds(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task DateTimeOffset_to_unix_time_seconds(bool async) => + base.DateTimeOffset_to_unix_time_seconds(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Set_operator_with_navigation_in_projection_groupby_aggregate(bool async) => + base.Set_operator_with_navigation_in_projection_groupby_aggregate(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Nav_expansion_inside_Contains_argument(bool async) => + base.Nav_expansion_inside_Contains_argument(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Nav_expansion_with_member_pushdown_inside_Contains_argument(bool async) => + base.Nav_expansion_with_member_pushdown_inside_Contains_argument(async); + + [ConditionalTheory(Skip = "TODO: Fix tests"), MemberData(nameof(IsAsyncData))] + public override Task Subquery_inside_Take_argument(bool async) => base.Subquery_inside_Take_argument(async); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTManyToManyQueryNpgsqlFixture.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTManyToManyQueryNpgsqlFixture.cs new file mode 100644 index 00000000..1a7da1a4 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Query/TPTManyToManyQueryNpgsqlFixture.cs @@ -0,0 +1,11 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.TestUtilities; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.Query; + +public class TptManyToManyQueryYdbFixture : TPTManyToManyQueryRelationalFixture +{ + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/QueryExpressionInterceptionYdbTestBase.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/QueryExpressionInterceptionYdbTestBase.cs new file mode 100644 index 00000000..62e9d836 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/QueryExpressionInterceptionYdbTestBase.cs @@ -0,0 +1,62 @@ +using EntityFrameworkCore.Ydb.Extensions; +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using EntityFrameworkCore.Ydb.Infrastructure; +using EntityFrameworkCore.Ydb.Storage.Internal; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public abstract class QueryExpressionInterceptionYdbTestBase( + QueryExpressionInterceptionYdbTestBase.InterceptionYdbFixtureBase fixture) + : QueryExpressionInterceptionTestBase(fixture) +{ + public abstract class InterceptionYdbFixtureBase : InterceptionFixtureBase + { + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override IServiceCollection InjectInterceptors( + IServiceCollection serviceCollection, + IEnumerable injectedInterceptors) + => base.InjectInterceptors(serviceCollection.AddEntityFrameworkYdb(), injectedInterceptors); + + public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) + { + new YdbDbContextOptionsBuilder(base.AddOptions(builder)) + .ExecutionStrategy(d => new YdbExecutionStrategy(d)); + return builder; + } + } + + public class QueryExpressionInterceptionYdbTest(QueryExpressionInterceptionYdbTest.InterceptionYdbFixture fixture) + : QueryExpressionInterceptionYdbTestBase(fixture), IClassFixture + { + public class InterceptionYdbFixture : InterceptionYdbFixtureBase + { + protected override string StoreName + => "QueryExpressionInterception"; + + protected override bool ShouldSubscribeToDiagnosticListener + => false; + } + } + + public class QueryExpressionInterceptionWithDiagnosticsYdbTest( + QueryExpressionInterceptionWithDiagnosticsYdbTest.InterceptionYdbFixture fixture) + : QueryExpressionInterceptionYdbTestBase(fixture), + IClassFixture + { + public class InterceptionYdbFixture : InterceptionYdbFixtureBase + { + protected override string StoreName + => "QueryExpressionInterceptionWithDiagnostics"; + + protected override bool ShouldSubscribeToDiagnosticListener + => true; + } + } +} \ No newline at end of file diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TPTTableSplittingYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TPTTableSplittingYdbTest.cs new file mode 100644 index 00000000..7e578399 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TPTTableSplittingYdbTest.cs @@ -0,0 +1,23 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; +using Xunit.Abstractions; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class TptTableSplittingYdbTest(ITestOutputHelper testOutputHelper) : TPTTableSplittingTestBase(testOutputHelper) +{ + // TODO: Should be fixed + [ConditionalFact(Skip = "Sequence contains no elements` almost without stacktrace")] + public override Task Can_insert_dependent_with_just_one_parent() + => base.Can_insert_dependent_with_just_one_parent(); + + [ConditionalTheory(Skip = "Requires fix")] + [MemberData(nameof(IsAsyncData))] + public override Task ExecuteUpdate_works_for_table_sharing(bool async) + => base.ExecuteUpdate_works_for_table_sharing(async); + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/NonRetryingExecutionStrategyFactory.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/NonRetryingExecutionStrategyFactory.cs new file mode 100644 index 00000000..dabeeda3 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/NonRetryingExecutionStrategyFactory.cs @@ -0,0 +1,10 @@ +using Microsoft.EntityFrameworkCore.Storage; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; + +internal class NonRetryingExecutionStrategyFactory(ExecutionStrategyDependencies dependencies) + : RelationalExecutionStrategyFactory(dependencies) +{ + protected override IExecutionStrategy CreateDefaultStrategy(ExecutionStrategyDependencies dependencies) + => new NonRetryingExecutionStrategy(dependencies); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbDbContextOptionsBuilderExtensions.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbDbContextOptionsBuilderExtensions.cs new file mode 100644 index 00000000..b98610ea --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbDbContextOptionsBuilderExtensions.cs @@ -0,0 +1,17 @@ +using EntityFrameworkCore.Ydb.Infrastructure; +using Microsoft.EntityFrameworkCore; + +namespace EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; + +public static class YdbDbContextOptionsBuilderExtensions +{ + + public static YdbDbContextOptionsBuilder ApplyConfiguration(this YdbDbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery); + optionsBuilder.CommandTimeout(YdbTestStore.CommandTimeout); + + return optionsBuilder; + } + +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbTestStore.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbTestStore.cs index 05fef6cb..d7a95713 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbTestStore.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TestUtilities/YdbTestStore.cs @@ -2,6 +2,7 @@ using System.Data.Common; using System.Text.RegularExpressions; using EntityFrameworkCore.Ydb.Extensions; +using EntityFrameworkCore.Ydb.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.TestUtilities; using Ydb.Sdk.Ado; @@ -14,19 +15,25 @@ public class YdbTestStore( string? additionalSql = null ) : RelationalTestStore(name, false, CreateConnection()) { - private const int CommandTimeout = 6942; + public const int CommandTimeout = 6942; + + internal Task ExecuteNonQueryAsync(string sql, params object[] parameters) + => ExecuteAsync(Connection, command => command.ExecuteNonQueryAsync(), sql, false, parameters); public static YdbTestStore GetOrCreate( string name, string? scriptPath = null ) => new(name: name, scriptPath: scriptPath); - public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) => UseConnectionString - ? builder.UseYdb(Connection.ConnectionString) - : builder.UseYdb(Connection); + public override DbContextOptionsBuilder AddProviderOptions(DbContextOptionsBuilder builder) + { + Action ydbOptionsBuilder = b => b.ApplyConfiguration() + .CommandTimeout(CommandTimeout); - internal Task ExecuteNonQueryAsync(string sql, params object[] parameters) - => ExecuteAsync(Connection, command => command.ExecuteNonQueryAsync(), sql, false, parameters); + return UseConnectionString + ? builder.UseYdb(Connection.ConnectionString, ydbOptionsBuilder) + : builder.UseYdb(Connection, ydbOptionsBuilder); + } protected override async Task InitializeAsync( Func createContext, @@ -34,32 +41,41 @@ protected override async Task InitializeAsync( Func? clean ) { - await using var context = createContext(); - if (clean != null) await clean(context); - await CleanAsync(context); - if (scriptPath is not null) + try { - await ExecuteScript(scriptPath); + await using var context = createContext(); + if (clean != null) await clean(context); + await CleanAsync(context); - if (additionalSql is not null) + if (scriptPath is not null) { - await ExecuteAsync(Connection, command => command.ExecuteNonQueryAsync(), additionalSql); - } - } - else - { - await context.Database.EnsureCreatedAsync(); + await ExecuteScript(scriptPath); - if (additionalSql is not null) - { - await ExecuteAsync(Connection, command => command.ExecuteNonQueryAsync(), additionalSql); + if (additionalSql is not null) + { + await ExecuteAsync(Connection, command => command.ExecuteNonQueryAsync(), additionalSql); + } } + else + { + await context.Database.EnsureCreatedAsync(); + + if (additionalSql is not null) + { + await ExecuteAsync(Connection, command => command.ExecuteNonQueryAsync(), additionalSql); + } - if (seed is not null) - { - await seed(context); + if (seed is not null) + { + await seed(context); + } } } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } } private async Task ExecuteScript(string scriptPathParam) @@ -165,30 +181,36 @@ private static YdbCommand CreateCommand( } - private static YdbConnection CreateConnection() => new(new YdbConnectionStringBuilder()); + private static YdbConnection CreateConnection() => new(new YdbConnectionStringBuilder { MaxSessionPool = 10 }); public override async Task CleanAsync(DbContext context) { - await context.Database.EnsureDeletedAsync(); var connection = context.Database.GetDbConnection(); if (connection.State != ConnectionState.Open) { await connection.OpenAsync(); } - var schema = await connection.GetSchemaAsync("Tables", [null, "TABLE"]); + var schema = await connection.GetSchemaAsync("tables"); var tables = schema .AsEnumerable() - .Select(entry => (string)entry["table_name"]); + .Select(entry => (string)entry["table_name"]) + .Where(tableName => !tableName.StartsWith('.')); + + if (!tables.Any()) return; var command = connection.CreateCommand(); foreach (var table in tables) { - command.CommandText = $"DROP TABLE IF EXISTS `{table}`;"; - await command.ExecuteNonQueryAsync(); + command.CommandText += $"DROP TABLE IF EXISTS `{table}`;"; } + await command.ExecuteNonQueryAsync(); + await connection.CloseAsync(); } + + protected override string OpenDelimiter => "`"; + protected override string CloseDelimiter => "`"; } diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TransactionInterceptionYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TransactionInterceptionYdbTest.cs new file mode 100644 index 00000000..39e75068 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TransactionInterceptionYdbTest.cs @@ -0,0 +1,75 @@ +using EntityFrameworkCore.Ydb.Extensions; +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public abstract class TransactionInterceptionYdbTestBase( + TransactionInterceptionYdbTestBase.InterceptionYdbFixtureBase fixture +) + : TransactionInterceptionTestBase(fixture) +{ + public abstract class InterceptionYdbFixtureBase : InterceptionFixtureBase + { + protected override string StoreName + => "TransactionInterception"; + + protected override ITestStoreFactory TestStoreFactory + => YdbTestStoreFactory.Instance; + + protected override IServiceCollection InjectInterceptors( + IServiceCollection serviceCollection, + IEnumerable injectedInterceptors + ) + => base.InjectInterceptors(serviceCollection.AddEntityFrameworkYdb(), injectedInterceptors); + } + + public class TransactionInterceptionYdbTest( + TransactionInterceptionYdbTest.InterceptionYdbFixture fixture + ) : TransactionInterceptionYdbTestBase(fixture), + IClassFixture + { + [ConditionalTheory(Skip = "Unsupported isolation level")] + [InlineData(false)] + [InlineData(true)] + public override Task Intercept_BeginTransaction_with_isolation_level(bool async) + => base.Intercept_BeginTransaction_with_isolation_level(async); + + // Savepoints are not supported in YDB + public override Task Intercept_CreateSavepoint(bool async) => Task.CompletedTask; + public override Task Intercept_ReleaseSavepoint(bool async) => Task.CompletedTask; + public override Task Intercept_RollbackToSavepoint(bool async) => Task.CompletedTask; + + public class InterceptionYdbFixture : InterceptionYdbFixtureBase + { + protected override bool ShouldSubscribeToDiagnosticListener => false; + } + } + + public class TransactionInterceptionWithDiagnosticsYdbTest( + TransactionInterceptionWithDiagnosticsYdbTest.InterceptionYdbFixture fixture + ) : TransactionInterceptionYdbTestBase(fixture), + IClassFixture + { + [ConditionalTheory(Skip = "Unsupported isolation level")] + [InlineData(false)] + [InlineData(true)] + public override Task Intercept_BeginTransaction_with_isolation_level(bool async) + => base.Intercept_BeginTransaction_with_isolation_level(async); + + + // Savepoints are not supported in YDB + public override Task Intercept_CreateSavepoint(bool async) => Task.CompletedTask; + public override Task Intercept_ReleaseSavepoint(bool async) => Task.CompletedTask; + public override Task Intercept_RollbackToSavepoint(bool async) => Task.CompletedTask; + + public class InterceptionYdbFixture : InterceptionYdbFixtureBase + { + protected override bool ShouldSubscribeToDiagnosticListener => true; + } + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TwoDatabasesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TwoDatabasesYdbTest.cs new file mode 100644 index 00000000..6c63751b --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/TwoDatabasesYdbTest.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +// TODO: Right now in tests we can access only one database +public class TwoDatabasesYdbTest(ComplexTypesTrackingYdbTest.YdbFixture fixture) + : TwoDatabasesTestBase(fixture), IClassFixture +{ + [ConditionalFact(Skip = "Explained in TODO")] + public override void Can_query_from_one_connection_and_save_changes_to_another() => + base.Can_query_from_one_connection_and_save_changes_to_another(); + + [ConditionalFact(Skip = "Explained in TODO")] + public override void Can_query_from_one_connection_string_and_save_changes_to_another() => + base.Can_query_from_one_connection_string_and_save_changes_to_another(); + + [ConditionalTheory(Skip = "Explained in TODO")] + [InlineData(true, false)] + [InlineData(true, true)] + public override void Can_set_connection_string_in_interceptor( + bool withConnectionString, bool withNullConnectionString + ) => base.Can_set_connection_string_in_interceptor(withConnectionString, withNullConnectionString); + + protected override DbContextOptionsBuilder CreateTestOptions( + DbContextOptionsBuilder optionsBuilder, + bool withConnectionString = false, + bool withNullConnectionString = false + ) => throw new NotImplementedException(); + + protected override TwoDatabasesWithDataContext CreateBackingContext(string databaseName) + => throw new NotImplementedException(); + + protected override string DummyConnectionString + => throw new NotImplementedException(); +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Update/UpdatesYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Update/UpdatesYdbTest.cs similarity index 100% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/Update/UpdatesYdbTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/Update/UpdatesYdbTest.cs diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/WithConstructorsYdbTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/WithConstructorsYdbTest.cs new file mode 100644 index 00000000..b0f4f412 --- /dev/null +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/WithConstructorsYdbTest.cs @@ -0,0 +1,31 @@ +using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Xunit; + +namespace EntityFrameworkCore.Ydb.FunctionalTests; + +public class WithConstructorsYdbTest(WithConstructorsYdbTest.WithConstructorsYdbFixture fixture) + : WithConstructorsTestBase(fixture) +{ + [ConditionalFact(Skip = "Cannot create table without key")] + public override void Query_with_keyless_type() => base.Query_with_keyless_type(); + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + public class WithConstructorsYdbFixture : WithConstructorsFixtureBase + { + protected override ITestStoreFactory TestStoreFactory => YdbTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + // Necessary because YDB cannot create tables without keys + modelBuilder.Entity().HasKey(x => x.Title); + } + } +} diff --git a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/YdbServiceCollectionExtensionsTest.cs b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/YdbServiceCollectionExtensionsTest.cs similarity index 79% rename from src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/YdbServiceCollectionExtensionsTest.cs rename to src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/YdbServiceCollectionExtensionsTest.cs index 45c54558..45a73903 100644 --- a/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/AllTests/YdbServiceCollectionExtensionsTest.cs +++ b/src/EFCore.Ydb/test/EntityFrameworkCore.Ydb.FunctionalTests/YdbServiceCollectionExtensionsTest.cs @@ -1,7 +1,7 @@ using EntityFrameworkCore.Ydb.FunctionalTests.TestUtilities; using Microsoft.EntityFrameworkCore; -namespace EntityFrameworkCore.Ydb.FunctionalTests.AllTests; +namespace EntityFrameworkCore.Ydb.FunctionalTests; public class YdbServiceCollectionExtensionsTest() : RelationalServiceCollectionExtensionsTestBase(YdbTestHelpers.Instance); diff --git a/src/Ydb.Sdk/src/Ado/YdbCommand.cs b/src/Ydb.Sdk/src/Ado/YdbCommand.cs index 9fece60e..d27f2752 100644 --- a/src/Ydb.Sdk/src/Ado/YdbCommand.cs +++ b/src/Ydb.Sdk/src/Ado/YdbCommand.cs @@ -213,8 +213,7 @@ protected override async Task ExecuteDbDataReaderAsync(CommandBeha var ydbDataReader = await YdbDataReader.CreateYdbDataReader( await YdbConnection.Session.ExecuteQuery( preparedSql.ToString(), ydbParameters, execSettings, transaction?.TransactionControl - ), - YdbConnection.Session.OnStatus, transaction + ), YdbConnection.OnStatus, transaction ); YdbConnection.LastReader = ydbDataReader; diff --git a/src/Ydb.Sdk/src/Ado/YdbConnection.cs b/src/Ydb.Sdk/src/Ado/YdbConnection.cs index 1c82aadc..71a25a9d 100644 --- a/src/Ydb.Sdk/src/Ado/YdbConnection.cs +++ b/src/Ydb.Sdk/src/Ado/YdbConnection.cs @@ -160,6 +160,16 @@ public override string ConnectionString private ConnectionState ConnectionState { get; set; } = ConnectionState.Closed; // Invoke AsyncOpen() + internal void OnStatus(Status status) + { + _session.OnStatus(status); + + if (!_session.IsActive) + { + ConnectionState = ConnectionState.Broken; + } + } + internal YdbDataReader? LastReader { get; set; } internal string LastCommand { get; set; } = string.Empty; internal bool IsBusy => LastReader is { IsOpen: true }; diff --git a/src/Ydb.Sdk/src/Ado/YdbParameter.cs b/src/Ydb.Sdk/src/Ado/YdbParameter.cs index 00a9cde4..c9c2d84b 100644 --- a/src/Ydb.Sdk/src/Ado/YdbParameter.cs +++ b/src/Ydb.Sdk/src/Ado/YdbParameter.cs @@ -2,6 +2,7 @@ using System.Data; using System.Data.Common; using System.Diagnostics.CodeAnalysis; +using System.Text.Json; using Ydb.Sdk.Value; namespace Ydb.Sdk.Ado; @@ -172,6 +173,9 @@ string valueString when DbType is DbType.String or DbType.AnsiString or DbType.A Guid guidValue when DbType is DbType.Guid or DbType.Object => YdbValue.MakeUuid(guidValue), MemoryStream memoryStream when DbType is DbType.Binary or DbType.Object => YdbValue.MakeString( memoryStream.ToArray()), + TimeSpan timeSpan when DbType is DbType.Object => YdbValue.MakeInterval(timeSpan), + JsonElement jsonElement => YdbValue.MakeJson(jsonElement.ToString()), + JsonDocument jsonDocument => YdbValue.MakeJson(jsonDocument.RootElement.ToString()), _ when DbType is DbType.VarNumeric or DbType.Xml or DbType.Time => throw new YdbException($"Ydb don't supported this DbType: {DbType}"), _ => ThrowInvalidOperation() diff --git a/src/Ydb.Sdk/src/Ado/YdbSchema.cs b/src/Ydb.Sdk/src/Ado/YdbSchema.cs index 514efa20..402eb571 100644 --- a/src/Ydb.Sdk/src/Ado/YdbSchema.cs +++ b/src/Ydb.Sdk/src/Ado/YdbSchema.cs @@ -65,7 +65,7 @@ internal static async Task DescribeTable( if (status.IsNotSuccess) { - ydbConnection.Session.OnStatus(status); + ydbConnection.OnStatus(status); throw new YdbException(status); } @@ -76,7 +76,7 @@ internal static async Task DescribeTable( } catch (Driver.TransportException e) { - ydbConnection.Session.OnStatus(e.Status); + ydbConnection.OnStatus(e.Status); throw new YdbException("Transport error on DescribeTable", e); } diff --git a/src/Ydb.Sdk/src/Ado/YdbTransaction.cs b/src/Ydb.Sdk/src/Ado/YdbTransaction.cs index 32ba5f89..6765b8d1 100644 --- a/src/Ydb.Sdk/src/Ado/YdbTransaction.cs +++ b/src/Ydb.Sdk/src/Ado/YdbTransaction.cs @@ -99,7 +99,7 @@ private async Task FinishTransaction(Func> finishMethod) { Failed = true; - DbConnection.Session.OnStatus(status); + DbConnection.OnStatus(status); throw new YdbException(status); } @@ -108,7 +108,7 @@ private async Task FinishTransaction(Func> finishMethod) { Failed = true; - DbConnection.Session.OnStatus(e.Status); + DbConnection.OnStatus(e.Status); throw new YdbException(e.Status); }