diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
index 72786e94826..7f36326f67c 100644
--- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
@@ -219,7 +219,7 @@ when entityQueryRootExpression.GetType() == typeof(EntityQueryRootExpression)
Check.DebugAssert(sqlParameterExpression is not null, "sqlParameterExpression is not null");
return TranslateCollection(
sqlParameterExpression,
- elementTypeMapping: null,
+ property: null,
char.ToLowerInvariant(sqlParameterExpression.Name.First(c => c != '_')).ToString())
?? base.VisitExtension(extensionExpression);
@@ -265,20 +265,24 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
if (translated == QueryCompilationContext.NotTranslatedExpression)
{
// Attempt to translate access into a primitive collection property (i.e. array column)
- if (_sqlTranslator.TryTranslatePropertyAccess(methodCallExpression, out var propertyAccessExpression)
- && propertyAccessExpression is SqlExpression
+
+ // TODO: We should be detecting primitive collections by looking at GetElementType() of the property and not at its type
+ // mapping; but #31469 is blocking that for shadow properties.
+ if (_sqlTranslator.TryTranslatePropertyAccess(methodCallExpression, out var translatedExpression, out var property)
+ && property is IProperty regularProperty
+ && translatedExpression is SqlExpression
{
- TypeMapping.ElementTypeMapping: RelationalTypeMapping elementTypeMapping
- } collectionPropertyAccessExpression)
+ TypeMapping.ElementTypeMapping: RelationalTypeMapping
+ } sqlExpression)
{
- var tableAlias = collectionPropertyAccessExpression switch
+ var tableAlias = sqlExpression switch
{
ColumnExpression c => c.Name[..1].ToLowerInvariant(),
JsonScalarExpression { Path: [.., { PropertyName: string propertyName }] } => propertyName[..1].ToLowerInvariant(),
_ => "j"
};
- if (TranslateCollection(collectionPropertyAccessExpression, elementTypeMapping, tableAlias) is
+ if (TranslateCollection(sqlExpression, regularProperty, tableAlias) is
{ } primitiveCollectionTranslation)
{
return primitiveCollectionTranslation;
@@ -316,17 +320,15 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
/// collections.
///
/// The expression to try to translate as a primitive collection expression.
- ///
- /// The type mapping of the collection's element, or when it's not known (i.e. for parameters).
+ ///
+ /// If the primitive collection is a property, contains the for that property. Otherwise, the collection
+ /// represents a parameter, and this contains .
///
///
/// Provides an alias to be used for the table returned from translation, which will represent the collection.
///
/// A if the translation was successful, otherwise .
- protected virtual ShapedQueryExpression? TranslateCollection(
- SqlExpression sqlExpression,
- RelationalTypeMapping? elementTypeMapping,
- string tableAlias)
+ protected virtual ShapedQueryExpression? TranslateCollection(SqlExpression sqlExpression, IProperty? property, string tableAlias)
=> null;
///
diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs
index a0c62e8a1ab..88716980b18 100644
--- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs
@@ -547,16 +547,13 @@ SqlExpression GeneratePredicateTpt(StructuralTypeProjectionExpression projection
else
{
var discriminatorColumn = BindProperty(typeReference, discriminatorProperty);
- if (discriminatorColumn != null)
- {
- return match
- ? _sqlExpressionFactory.Equal(
- discriminatorColumn,
- _sqlExpressionFactory.Constant(derivedType.GetDiscriminatorValue()))
- : _sqlExpressionFactory.NotEqual(
- discriminatorColumn,
- _sqlExpressionFactory.Constant(derivedType.GetDiscriminatorValue()));
- }
+ return match
+ ? _sqlExpressionFactory.Equal(
+ discriminatorColumn,
+ _sqlExpressionFactory.Constant(derivedType.GetDiscriminatorValue()))
+ : _sqlExpressionFactory.NotEqual(
+ discriminatorColumn,
+ _sqlExpressionFactory.Constant(derivedType.GetDiscriminatorValue()));
}
return QueryCompilationContext.NotTranslatedExpression;
@@ -739,8 +736,9 @@ protected override Expression VisitMember(MemberExpression memberExpression)
{
var innerExpression = Visit(memberExpression.Expression);
- return TryBindMember(innerExpression, MemberIdentity.Create(memberExpression.Member))
- ?? (TranslationFailed(memberExpression.Expression, innerExpression, out var sqlInnerExpression)
+ return TryBindMember(innerExpression, MemberIdentity.Create(memberExpression.Member), out var expression)
+ ? expression
+ : (TranslationFailed(memberExpression.Expression, innerExpression, out var sqlInnerExpression)
? QueryCompilationContext.NotTranslatedExpression
: Dependencies.MemberTranslatorProvider.Translate(
sqlInnerExpression, memberExpression.Member, memberExpression.Type, _queryCompilationContext.Logger))
@@ -760,26 +758,28 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
[EntityFrameworkInternal]
- public virtual bool TryTranslatePropertyAccess(Expression expression, [NotNullWhen(true)] out Expression? propertyAccessExpression)
+ public virtual bool TryTranslatePropertyAccess(
+ Expression expression,
+ [NotNullWhen(true)] out Expression? translatedExpression,
+ [NotNullWhen(true)] out IPropertyBase? property)
{
if (expression is MethodCallExpression methodCallExpression)
{
if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)
- && TryBindMember(Visit(source), MemberIdentity.Create(propertyName)) is Expression result)
+ && TryBindMember(Visit(source), MemberIdentity.Create(propertyName), out translatedExpression, out property))
{
- propertyAccessExpression = result;
return true;
}
if (methodCallExpression.TryGetIndexerArguments(_model, out source, out propertyName)
- && TryBindMember(Visit(source), MemberIdentity.Create(propertyName)) is Expression indexerResult)
+ && TryBindMember(Visit(source), MemberIdentity.Create(propertyName), out translatedExpression, out property))
{
- propertyAccessExpression = indexerResult;
return true;
}
}
- propertyAccessExpression = null;
+ translatedExpression = null;
+ property = null;
return false;
}
@@ -789,7 +789,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
// EF.Property case
if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName))
{
- if (TryBindMember(Visit(source), MemberIdentity.Create(propertyName)) is Expression result)
+ if (TryBindMember(Visit(source), MemberIdentity.Create(propertyName), out var result))
{
return result;
}
@@ -807,7 +807,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp
// EF Indexer property
if (methodCallExpression.TryGetIndexerArguments(_model, out source, out propertyName)
- && TryBindMember(Visit(source), MemberIdentity.Create(propertyName)) is Expression indexerResult)
+ && TryBindMember(Visit(source), MemberIdentity.Create(propertyName), out var indexerResult))
{
return indexerResult;
}
@@ -1129,21 +1129,16 @@ SqlExpression GeneratePredicateTpt(StructuralTypeProjectionExpression entityProj
{
var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList();
var discriminatorColumn = BindProperty(typeReference, discriminatorProperty);
- if (discriminatorColumn != null)
- {
- return concreteEntityTypes.Count == 1
- ? _sqlExpressionFactory.Equal(
- discriminatorColumn,
- _sqlExpressionFactory.Constant(concreteEntityTypes[0].GetDiscriminatorValue()))
- : _sqlExpressionFactory.In(
- discriminatorColumn,
- concreteEntityTypes.Select(et => _sqlExpressionFactory.Constant(et.GetDiscriminatorValue())).ToArray());
- }
- }
- else
- {
- return _sqlExpressionFactory.Constant(true);
+ return concreteEntityTypes.Count == 1
+ ? _sqlExpressionFactory.Equal(
+ discriminatorColumn,
+ _sqlExpressionFactory.Constant(concreteEntityTypes[0].GetDiscriminatorValue()))
+ : _sqlExpressionFactory.In(
+ discriminatorColumn,
+ concreteEntityTypes.Select(et => _sqlExpressionFactory.Constant(et.GetDiscriminatorValue())).ToArray());
}
+
+ return _sqlExpressionFactory.Constant(true);
}
return QueryCompilationContext.NotTranslatedExpression;
@@ -1207,22 +1202,36 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression)
return QueryCompilationContext.NotTranslatedExpression;
}
- private Expression? TryBindMember(Expression? source, MemberIdentity member)
+ private bool TryBindMember(
+ Expression? source,
+ MemberIdentity member,
+ [NotNullWhen(true)] out Expression? expression)
+ => TryBindMember(source, member, out expression, out _);
+
+ private bool TryBindMember(
+ Expression? source,
+ MemberIdentity member,
+ [NotNullWhen(true)] out Expression? expression,
+ [NotNullWhen(true)] out IPropertyBase? property)
{
if (source is not StructuralTypeReferenceExpression typeReference)
{
- return null;
+ expression = null;
+ property = null;
+ return false;
}
var structuralType = typeReference.StructuralType;
- var property = member.MemberInfo != null
+ var regularProperty = member.MemberInfo != null
? structuralType.FindProperty(member.MemberInfo)
: structuralType.FindProperty(member.Name!);
- if (property != null)
+ if (regularProperty != null)
{
- return BindProperty(typeReference, property);
+ expression = BindProperty(typeReference, regularProperty);
+ property = regularProperty;
+ return true;
}
var complexProperty = member.MemberInfo != null
@@ -1231,7 +1240,9 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression)
if (complexProperty is not null)
{
- return BindComplexProperty(typeReference, complexProperty);
+ expression = BindComplexProperty(typeReference, complexProperty);
+ property = complexProperty;
+ return true;
}
AddTranslationErrorDetails(
@@ -1239,103 +1250,109 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression)
member.Name,
typeReference.StructuralType.DisplayName()));
- return null;
+ expression = null;
+ property = null;
+ return false;
}
- private SqlExpression? BindProperty(StructuralTypeReferenceExpression typeReference, IProperty property)
+ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReference, IProperty property)
{
- if (typeReference.Parameter != null)
+ switch (typeReference)
{
- var valueBufferExpression = Visit(typeReference.Parameter.ValueBufferExpression);
- if (valueBufferExpression is JsonQueryExpression jsonQueryExpression)
+ case { Parameter: StructuralTypeShaperExpression shaper }:
{
- return jsonQueryExpression.BindProperty(property);
- }
+ var valueBufferExpression = Visit(shaper.ValueBufferExpression);
+ if (valueBufferExpression is JsonQueryExpression jsonQueryExpression)
+ {
+ return jsonQueryExpression.BindProperty(property);
+ }
- var projection = (StructuralTypeProjectionExpression)valueBufferExpression;
- var propertyAccess = projection.BindProperty(property);
+ var projection = (StructuralTypeProjectionExpression)valueBufferExpression;
+ var propertyAccess = projection.BindProperty(property);
- if (typeReference.StructuralType is not IEntityType entityType
- || entityType.FindDiscriminatorProperty() != null
- || entityType.FindPrimaryKey() == null
- || entityType.GetRootType() != entityType
- || entityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy)
- {
- return propertyAccess;
- }
+ if (typeReference.StructuralType is not IEntityType entityType
+ || entityType.FindDiscriminatorProperty() != null
+ || entityType.FindPrimaryKey() == null
+ || entityType.GetRootType() != entityType
+ || entityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy)
+ {
+ return propertyAccess;
+ }
- var table = entityType.GetViewOrTableMappings().SingleOrDefault(e => e.IsSplitEntityTypePrincipal ?? true)?.Table
- ?? entityType.GetDefaultMappings().Single().Table;
- if (!table.IsOptional(entityType))
- {
- return propertyAccess;
- }
+ var table = entityType.GetViewOrTableMappings().SingleOrDefault(e => e.IsSplitEntityTypePrincipal ?? true)?.Table
+ ?? entityType.GetDefaultMappings().Single().Table;
+ if (!table.IsOptional(entityType))
+ {
+ return propertyAccess;
+ }
- // this is optional dependent sharing table
- var nonPrincipalSharedNonPkProperties = entityType.GetNonPrincipalSharedNonPkProperties(table);
- if (nonPrincipalSharedNonPkProperties.Contains(property))
- {
- // The column is not being shared with principal side so we can always use directly
- return propertyAccess;
- }
+ // this is optional dependent sharing table
+ var nonPrincipalSharedNonPkProperties = entityType.GetNonPrincipalSharedNonPkProperties(table);
+ if (nonPrincipalSharedNonPkProperties.Contains(property))
+ {
+ // The column is not being shared with principal side so we can always use directly
+ return propertyAccess;
+ }
- SqlExpression? condition = null;
- // Property is being shared with principal side, so we need to make it conditional access
- var allRequiredNonPkProperties =
- entityType.GetProperties().Where(p => !p.IsNullable && !p.IsPrimaryKey()).ToList();
- if (allRequiredNonPkProperties.Count > 0)
- {
- condition = allRequiredNonPkProperties.Select(p => projection.BindProperty(p))
- .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null)))
- .Aggregate((a, b) => _sqlExpressionFactory.AndAlso(a, b));
- }
+ SqlExpression? condition = null;
+ // Property is being shared with principal side, so we need to make it conditional access
+ var allRequiredNonPkProperties =
+ entityType.GetProperties().Where(p => !p.IsNullable && !p.IsPrimaryKey()).ToList();
+ if (allRequiredNonPkProperties.Count > 0)
+ {
+ condition = allRequiredNonPkProperties.Select(p => projection.BindProperty(p))
+ .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null)))
+ .Aggregate((a, b) => _sqlExpressionFactory.AndAlso(a, b));
+ }
- if (nonPrincipalSharedNonPkProperties.Count != 0
- && nonPrincipalSharedNonPkProperties.All(p => p.IsNullable))
- {
- // If all non principal shared properties are nullable then we need additional condition
- var atLeastOneNonNullValueInNullableColumnsCondition = nonPrincipalSharedNonPkProperties
- .Select(p => projection.BindProperty(p))
- .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null)))
- .Aggregate((a, b) => _sqlExpressionFactory.OrElse(a, b));
-
- condition = condition == null
- ? atLeastOneNonNullValueInNullableColumnsCondition
- : _sqlExpressionFactory.AndAlso(condition, atLeastOneNonNullValueInNullableColumnsCondition);
- }
+ if (nonPrincipalSharedNonPkProperties.Count != 0
+ && nonPrincipalSharedNonPkProperties.All(p => p.IsNullable))
+ {
+ // If all non principal shared properties are nullable then we need additional condition
+ var atLeastOneNonNullValueInNullableColumnsCondition = nonPrincipalSharedNonPkProperties
+ .Select(p => projection.BindProperty(p))
+ .Select(c => (SqlExpression)_sqlExpressionFactory.NotEqual(c, _sqlExpressionFactory.Constant(null)))
+ .Aggregate((a, b) => _sqlExpressionFactory.OrElse(a, b));
+
+ condition = condition == null
+ ? atLeastOneNonNullValueInNullableColumnsCondition
+ : _sqlExpressionFactory.AndAlso(condition, atLeastOneNonNullValueInNullableColumnsCondition);
+ }
- if (condition == null)
- {
- // if we cannot compute condition then we just return property access (and hope for the best)
- return propertyAccess;
- }
+ if (condition == null)
+ {
+ // if we cannot compute condition then we just return property access (and hope for the best)
+ return propertyAccess;
+ }
- return _sqlExpressionFactory.Case(
- new List { new(condition, propertyAccess) },
- elseResult: null);
+ return _sqlExpressionFactory.Case(
+ new List { new(condition, propertyAccess) },
+ elseResult: null);
- // We don't do above processing for subquery entity since it comes from after subquery which has been
- // single result so either it is regular entity or a collection which always have their own table.
- }
+ // We don't do above processing for subquery entity since it comes from after subquery which has been
+ // single result so either it is regular entity or a collection which always have their own table.
+ }
- if (typeReference.Subquery != null)
- {
- var entityShaper = (StructuralTypeShaperExpression)typeReference.Subquery.ShaperExpression;
- var subSelectExpression = (SelectExpression)typeReference.Subquery.QueryExpression;
+ case { Subquery: ShapedQueryExpression subquery }:
+ {
+ var entityShaper = (StructuralTypeShaperExpression)subquery.ShaperExpression;
+ var subSelectExpression = (SelectExpression)subquery.QueryExpression;
- var projectionBindingExpression = (ProjectionBindingExpression)entityShaper.ValueBufferExpression;
- var projection = (StructuralTypeProjectionExpression)subSelectExpression.GetProjection(projectionBindingExpression);
- var innerProjection = projection.BindProperty(property);
- subSelectExpression.ReplaceProjection(new List { innerProjection });
- subSelectExpression.ApplyProjection();
+ var projectionBindingExpression = (ProjectionBindingExpression)entityShaper.ValueBufferExpression;
+ var projection = (StructuralTypeProjectionExpression)subSelectExpression.GetProjection(projectionBindingExpression);
+ var innerProjection = projection.BindProperty(property);
+ subSelectExpression.ReplaceProjection(new List { innerProjection });
+ subSelectExpression.ApplyProjection();
- return new ScalarSubqueryExpression(subSelectExpression);
- }
+ return new ScalarSubqueryExpression(subSelectExpression);
+ }
- return null;
+ default:
+ throw new UnreachableException();
+ }
}
- private StructuralTypeReferenceExpression? BindComplexProperty(
+ private StructuralTypeReferenceExpression BindComplexProperty(
StructuralTypeReferenceExpression typeReference,
IComplexProperty complexProperty)
{
@@ -1352,7 +1369,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression)
throw new InvalidOperationException(); // TODO: Figure this out; do we support it?
default:
- return null;
+ throw new UnreachableException();
}
}
diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
index d35d676055a..050489a2270 100644
--- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs
@@ -129,7 +129,7 @@ protected override Expression VisitExtension(Expression extensionExpression)
///
protected override ShapedQueryExpression? TranslateCollection(
SqlExpression sqlExpression,
- RelationalTypeMapping? elementTypeMapping,
+ IProperty? property,
string tableAlias)
{
if (_sqlServerCompatibilityLevel < 130)
@@ -145,6 +145,8 @@ protected override Expression VisitExtension(Expression extensionExpression)
// (i.e. with a columnInfo), which determines the type conversion to apply to the JSON elements coming out.
// For parameter collections, the element type mapping will only be inferred and applied later (see
// SqlServerInferredTypeMappingApplier below), at which point the we'll apply it to add the WITH clause.
+ var elementTypeMapping = (RelationalTypeMapping?)sqlExpression.TypeMapping?.ElementTypeMapping;
+
var openJsonExpression = elementTypeMapping is null
? new SqlServerOpenJsonExpression(tableAlias, sqlExpression)
: new SqlServerOpenJsonExpression(
@@ -159,9 +161,16 @@ protected override Expression VisitExtension(Expression extensionExpression)
}
});
- // TODO: This is a temporary CLR type-based check; when we have proper metadata to determine if the element is nullable, use it here
var elementClrType = sqlExpression.Type.GetSequenceType();
- var isColumnNullable = elementClrType.IsNullableType();
+
+ // If this is a collection property, get the element's nullability out of metadata. Otherwise, this is a parameter property, in
+ // which case we only have the CLR type (note that we cannot produce different SQLs based on the nullability of an *element* in
+ // a parameter collection - our caching mechanism only supports varying by the nullability of the parameter itself (i.e. the
+ // collection).
+ // TODO: if property is non-null, GetElementType() should never be null, but we have #31469 for shadow properties
+ var isElementNullable = property?.GetElementType() is null
+ ? elementClrType.IsNullableType()
+ : property.GetElementType()!.IsNullable;
#pragma warning disable EF1001 // Internal EF Core API usage.
var selectExpression = new SelectExpression(
@@ -169,7 +178,7 @@ protected override Expression VisitExtension(Expression extensionExpression)
columnName: "value",
columnType: elementClrType,
columnTypeMapping: elementTypeMapping,
- isColumnNullable,
+ isElementNullable,
identifierColumnName: "key",
identifierColumnType: typeof(string),
identifierColumnTypeMapping: _typeMappingSource.FindMapping("nvarchar(4000)"));
diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs
index 2e64f9aa569..6ef34247808 100644
--- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQueryableMethodTranslatingExpressionVisitor.cs
@@ -203,7 +203,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis
///
protected override ShapedQueryExpression? TranslateCollection(
SqlExpression sqlExpression,
- RelationalTypeMapping? elementTypeMapping,
+ IProperty? property,
string tableAlias)
{
// Support for JSON functions (e.g. json_each) was added in Sqlite 3.38.0 (2022-02-22, see https://www.sqlite.org/json1.html).
@@ -215,11 +215,18 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis
return null;
}
+ var elementTypeMapping = (RelationalTypeMapping?)sqlExpression.TypeMapping?.ElementTypeMapping;
var elementClrType = sqlExpression.Type.GetSequenceType();
var jsonEachExpression = new JsonEachExpression(tableAlias, sqlExpression);
- // TODO: This is a temporary CLR type-based check; when we have proper metadata to determine if the element is nullable, use it here
- var isColumnNullable = elementClrType.IsNullableType();
+ // If this is a collection property, get the element's nullability out of metadata. Otherwise, this is a parameter property, in
+ // which case we only have the CLR type (note that we cannot produce different SQLs based on the nullability of an *element* in
+ // a parameter collection - our caching mechanism only supports varying by the nullability of the parameter itself (i.e. the
+ // collection).
+ // TODO: if property is non-null, GetElementType() should never be null, but we have #31469 for shadow properties
+ var isElementNullable = property?.GetElementType() is null
+ ? elementClrType.IsNullableType()
+ : property.GetElementType()!.IsNullable;
#pragma warning disable EF1001 // Internal EF Core API usage.
var selectExpression = new SelectExpression(
@@ -227,7 +234,7 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis
columnName: "value",
columnType: elementClrType,
columnTypeMapping: elementTypeMapping,
- isColumnNullable,
+ isElementNullable,
identifierColumnName: "key",
identifierColumnType: typeof(int),
identifierColumnTypeMapping: _typeMappingSource.FindMapping(typeof(int)));
diff --git a/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs b/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs
index 80055aa0fdf..fa5ed19ba2e 100644
--- a/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs
+++ b/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
///
@@ -33,13 +35,19 @@ protected NonNullableConventionBase(ProviderConventionSetBuilderDependencies dep
///
/// The model builder used to build the model.
/// The member info.
+ ///
+ /// The nullability info for the , or if it does not represent a valid reference
+ /// type.
+ ///
/// if the member type is a non-nullable reference type.
- protected virtual bool IsNonNullableReferenceType(
+ protected virtual bool TryGetNullabilityInfo(
IConventionModelBuilder modelBuilder,
- MemberInfo memberInfo)
+ MemberInfo memberInfo,
+ [NotNullWhen(true)] out NullabilityInfo? nullabilityInfo)
{
if (memberInfo.GetMemberType().IsValueType)
{
+ nullabilityInfo = null;
return false;
}
@@ -49,14 +57,14 @@ protected virtual bool IsNonNullableReferenceType(
var nullabilityInfoContext = (NullabilityInfoContext)annotation.Value!;
- var nullabilityInfo = memberInfo switch
+ nullabilityInfo = memberInfo switch
{
PropertyInfo propertyInfo => nullabilityInfoContext.Create(propertyInfo),
FieldInfo fieldInfo => nullabilityInfoContext.Create(fieldInfo),
_ => null
};
- return nullabilityInfo?.ReadState == NullabilityState.NotNull;
+ return nullabilityInfo is not null;
}
///
diff --git a/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs
index f0e58e886d6..66baa664c4c 100644
--- a/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs
+++ b/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs
@@ -77,5 +77,6 @@ private void ProcessNavigation(IConventionNavigationBuilder navigationBuilder)
private bool IsNonNullable(IConventionModelBuilder modelBuilder, IConventionNavigation navigation)
=> navigation.DeclaringEntityType.GetRuntimeProperties().Find(navigation.Name) is PropertyInfo propertyInfo
- && IsNonNullableReferenceType(modelBuilder, propertyInfo);
+ && TryGetNullabilityInfo(modelBuilder, propertyInfo, out var nullabilityInfo)
+ && nullabilityInfo.ReadState == NullabilityState.NotNull;
}
diff --git a/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs
index 20e176575cf..d5c23f624df 100644
--- a/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs
+++ b/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs
@@ -29,16 +29,29 @@ public NonNullableReferencePropertyConvention(ProviderConventionSetBuilderDepend
private void Process(IConventionPropertyBuilder propertyBuilder)
{
if (propertyBuilder.Metadata.GetIdentifyingMemberInfo() is MemberInfo memberInfo
- && IsNonNullableReferenceType(propertyBuilder.ModelBuilder, memberInfo))
+ && TryGetNullabilityInfo(propertyBuilder.ModelBuilder, memberInfo, out var nullabilityInfo))
{
- propertyBuilder.IsRequired(true);
+ if (nullabilityInfo.ReadState == NullabilityState.NotNull)
+ {
+ propertyBuilder.IsRequired(true);
+ }
+
+ // If there's an element type, this is a primitive collection; check and apply the element's nullability as well.
+ if (propertyBuilder.Metadata.GetElementType() is IConventionElementType elementType
+ && nullabilityInfo is
+ { ElementType.ReadState: NullabilityState.NotNull } or
+ { GenericTypeArguments: [{ ReadState: NullabilityState.NotNull }] })
+ {
+ elementType.SetIsNullable(false);
+ }
}
}
private void Process(IConventionComplexPropertyBuilder propertyBuilder)
{
if (propertyBuilder.Metadata.GetIdentifyingMemberInfo() is MemberInfo memberInfo
- && IsNonNullableReferenceType(propertyBuilder.ModelBuilder, memberInfo))
+ && TryGetNullabilityInfo(propertyBuilder.ModelBuilder, memberInfo, out var nullabilityInfo)
+ && nullabilityInfo.ReadState == NullabilityState.NotNull)
{
propertyBuilder.IsRequired(true);
}
diff --git a/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs
index 4891eb90128..ca54815dd7a 100644
--- a/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs
+++ b/test/EFCore.Cosmos.FunctionalTests/JsonTypesCosmosTest.cs
@@ -3,10 +3,27 @@
#nullable enable
+using Xunit.Sdk;
+
namespace Microsoft.EntityFrameworkCore.Cosmos;
public class JsonTypesCosmosTest : JsonTypesTestBase
{
+ // #25765 - the Cosmos type mapping source doesn't support primitive collections, so we end up with a Property
+ // that has no ElementType; that causes the assertion on the element nullability to fail.
+ public override void Can_read_write_collection_of_string_JSON_values()
+ => Assert.Throws(() => base.Can_read_write_collection_of_string_JSON_values());
+
+ // #25765 - the Cosmos type mapping source doesn't support primitive collections, so we end up with a Property
+ // that has no ElementType; that causes the assertion on the element nullability to fail.
+ public override void Can_read_write_collection_of_binary_JSON_values()
+ => Assert.Throws(() => base.Can_read_write_collection_of_binary_JSON_values());
+
+ // #25765 - the Cosmos type mapping source doesn't support primitive collections, so we end up with a Property
+ // that has no ElementType; that causes the assertion on the element nullability to fail.
+ public override void Can_read_write_collection_of_nullable_string_JSON_values()
+ => Assert.Throws(() => base.Can_read_write_collection_of_nullable_string_JSON_values());
+
public override void Can_read_write_point()
// No built-in JSON support for spatial types in the Cosmos provider
=> Assert.Throws(() => base.Can_read_write_point());
diff --git a/test/EFCore.Specification.Tests/JsonTypesTestBase.cs b/test/EFCore.Specification.Tests/JsonTypesTestBase.cs
index fd81eaf10be..bd222c099d9 100644
--- a/test/EFCore.Specification.Tests/JsonTypesTestBase.cs
+++ b/test/EFCore.Specification.Tests/JsonTypesTestBase.cs
@@ -3443,9 +3443,29 @@ protected virtual void Can_read_and_write_JSON_value(
Assert.Equal(typeof(TModel).GetSequenceType(), element.ClrType);
Assert.Same(property, element.CollectionProperty);
- Assert.Equal(json.Contains("null", StringComparison.Ordinal) || !element.ClrType.IsValueType, element.IsNullable);
Assert.Null(element.FindTypeMapping()!.ElementTypeMapping);
+ bool elementNullable;
+ if (element.ClrType.IsValueType)
+ {
+ elementNullable = element.ClrType.IsNullableType();
+ }
+ else
+ {
+ var nullabilityInfo = property switch
+ {
+ { PropertyInfo: PropertyInfo p } => _nullabilityInfoContext.Create(p),
+ { FieldInfo: FieldInfo f } => _nullabilityInfoContext.Create(f),
+ _ => throw new UnreachableException()
+ };
+
+ elementNullable = nullabilityInfo is not
+ { ElementType.ReadState: NullabilityState.NotNull } and not
+ { GenericTypeArguments: [{ ReadState: NullabilityState.NotNull }] };
+ }
+
+ Assert.Equal(elementNullable, element.IsNullable);
+
var comparer = element.GetValueComparer()!;
var elementReaderWriter = element.GetJsonValueReaderWriter()!;
foreach (var item in (IEnumerable)value!)
@@ -3741,4 +3761,6 @@ protected virtual void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
CoreEventId.MappedEntityTypeIgnoredWarning,
CoreEventId.MappedPropertyIgnoredWarning,
CoreEventId.MappedNavigationIgnoredWarning));
+
+ private readonly NullabilityInfoContext _nullabilityInfoContext = new();
}
diff --git a/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs
index b54d968cc90..f6bc23f3eec 100644
--- a/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.EntityFrameworkCore.Diagnostics;
+#nullable enable
namespace Microsoft.EntityFrameworkCore.Query;
@@ -207,7 +207,7 @@ public virtual Task Parameter_collection_of_nullable_ints_Contains_nullable_int(
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
- public virtual Task Parameter_collection_of_strings_Contains(bool async)
+ public virtual Task Parameter_collection_of_strings_Contains_non_nullable_string(bool async)
{
var strings = new[] { "10", "999" };
@@ -217,6 +217,18 @@ public virtual Task Parameter_collection_of_strings_Contains(bool async)
entryCount: 1);
}
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task Parameter_collection_of_strings_Contains_nullable_string(bool async)
+ {
+ var strings = new[] { "999", null };
+
+ return AssertQuery(
+ async,
+ ss => ss.Set().Where(c => strings.Contains(c.NullableString)),
+ entryCount: 3);
+ }
+
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Parameter_collection_of_DateTimes_Contains(bool async)
@@ -261,11 +273,11 @@ public virtual Task Parameter_collection_of_enums_Contains(bool async)
[MemberData(nameof(IsAsyncData))]
public virtual async Task Parameter_collection_null_Contains(bool async)
{
- int[] ints = null;
+ int[]? ints = null;
await AssertQuery(
async,
- ss => ss.Set().Where(c => ints.Contains(c.Int)),
+ ss => ss.Set().Where(c => ints!.Contains(c.Int)),
ss => ss.Set().Where(c => false));
}
@@ -301,6 +313,14 @@ public virtual Task Column_collection_of_strings_contains_null(bool async)
ss => ss.Set().Where(c => c.Strings.Contains(null)),
entryCount: 0);
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task Column_collection_of_nullable_strings_contains_null(bool async)
+ => AssertQuery(
+ async,
+ ss => ss.Set().Where(c => c.NullableStrings.Contains(null)),
+ entryCount: 3);
+
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Column_collection_of_bools_Contains(bool async)
@@ -364,6 +384,28 @@ public virtual Task Column_collection_index_beyond_end(bool async)
ss => ss.Set().Where(c => false),
entryCount: 0);
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task Nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ => AssertQuery(
+ async,
+ ss => ss.Set()
+ .Where(c => c.NullableStrings[2] == c.NullableString),
+ ss => ss.Set()
+ .Where(c => (c.NullableStrings.Length > 2 ? c.NullableStrings[2] : default) == c.NullableString),
+ entryCount: 3);
+
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task Non_nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ => AssertQuery(
+ async,
+ ss => ss.Set()
+ .Where(c => c.Strings.Any() && c.Strings[1] == c.NullableString),
+ ss => ss.Set()
+ .Where(c => c.Strings.Any() && (c.Strings.Length > 1 ? c.Strings[1] : default) == c.NullableString),
+ entryCount: 1);
+
[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Inline_collection_index_Column(bool async)
@@ -834,7 +876,7 @@ public virtual Task Project_primitive_collections_element(bool async)
public abstract class PrimitiveCollectionsQueryFixtureBase : SharedStoreFixtureBase, IQueryFixtureBase
{
- private PrimitiveArrayData _expectedData;
+ private PrimitiveArrayData? _expectedData;
protected override string StoreName
=> "PrimitiveCollectionsTest";
@@ -851,12 +893,12 @@ protected override void Seed(PrimitiveCollectionsContext context)
public virtual ISetSource GetExpectedData()
=> _expectedData ??= new PrimitiveArrayData();
- public IReadOnlyDictionary EntitySorters { get; } = new Dictionary>
+ public IReadOnlyDictionary EntitySorters { get; } = new Dictionary>
{
- { typeof(PrimitiveCollectionsEntity), e => ((PrimitiveCollectionsEntity)e)?.Id }
- }.ToDictionary(e => e.Key, e => (object)e.Value);
+ { typeof(PrimitiveCollectionsEntity), e => ((PrimitiveCollectionsEntity?)e)?.Id }
+ }.ToDictionary(e => e.Key, e => (object?)e.Value);
- public IReadOnlyDictionary EntityAsserters { get; } = new Dictionary>
+ public IReadOnlyDictionary EntityAsserters { get; } = new Dictionary>
{
{
typeof(PrimitiveCollectionsEntity), (e, a) =>
@@ -865,7 +907,7 @@ public virtual ISetSource GetExpectedData()
if (a != null)
{
- var ee = (PrimitiveCollectionsEntity)e;
+ var ee = (PrimitiveCollectionsEntity)e!;
var aa = (PrimitiveCollectionsEntity)a;
Assert.Equal(ee.Id, aa.Id);
@@ -892,19 +934,21 @@ public class PrimitiveCollectionsEntity
{
public int Id { get; set; }
- public string String { get; set; }
+ public required string String { get; set; }
public int Int { get; set; }
public DateTime DateTime { get; set; }
public bool Bool { get; set; }
public MyEnum Enum { get; set; }
public int? NullableInt { get; set; }
-
- public string[] Strings { get; set; }
- public int[] Ints { get; set; }
- public DateTime[] DateTimes { get; set; }
- public bool[] Bools { get; set; }
- public MyEnum[] Enums { get; set; }
- public int?[] NullableInts { get; set; }
+ public string? NullableString { get; set; }
+
+ public required string[] Strings { get; set; }
+ public required int[] Ints { get; set; }
+ public required DateTime[] DateTimes { get; set; }
+ public required bool[] Bools { get; set; }
+ public required MyEnum[] Enums { get; set; }
+ public required int?[] NullableInts { get; set; }
+ public required string?[] NullableStrings { get; set; }
}
public enum MyEnum { Value1, Value2, Value3, Value4 }
@@ -913,7 +957,7 @@ public class PrimitiveArrayData : ISetSource
{
public IReadOnlyList PrimitiveArrayEntities { get; }
- public PrimitiveArrayData(PrimitiveCollectionsContext context = null)
+ public PrimitiveArrayData(PrimitiveCollectionsContext? context = null)
{
PrimitiveArrayEntities = CreatePrimitiveArrayEntities();
@@ -948,6 +992,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bool = true,
Enum = MyEnum.Value1,
NullableInt = 10,
+ NullableString = "10",
Ints = new[] { 1, 10 },
Strings = new[] { "1", "10" },
@@ -959,6 +1004,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bools = new[] { true, false },
Enums = new[] { MyEnum.Value1, MyEnum.Value2 },
NullableInts = new int?[] { 1, 10 },
+ NullableStrings = new[] { "1", "10" }
},
new()
{
@@ -970,6 +1016,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bool = false,
Enum = MyEnum.Value2,
NullableInt = null,
+ NullableString = null,
Ints = new[] { 1, 11, 111 },
Strings = new[] { "1", "11", "111" },
@@ -982,6 +1029,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bools = new[] { false },
Enums = new[] { MyEnum.Value2, MyEnum.Value3 },
NullableInts = new int?[] { 1, 11, null },
+ NullableStrings = new[] { "1", "11", null }
},
new()
{
@@ -993,6 +1041,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bool = true,
Enum = MyEnum.Value1,
NullableInt = 20,
+ NullableString = "20",
Ints = new[] { 1, 1, 10, 10, 10, 1, 10 },
Strings = new[] { "1", "10", "10", "1", "1" },
@@ -1007,6 +1056,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bools = new[] { true, false },
Enums = new[] { MyEnum.Value1, MyEnum.Value2 },
NullableInts = new int?[] { 1, 1, 10, 10, null, 1 },
+ NullableStrings = new[] { "1", "1", "10", "10", null, "1" }
},
new()
{
@@ -1018,6 +1068,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bool = false,
Enum = MyEnum.Value2,
NullableInt = null,
+ NullableString = null,
Ints = new[] { 1, 1, 111, 11, 1, 111 },
Strings = new[] { "1", "11", "111", "11" },
@@ -1035,6 +1086,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bools = new[] { false },
Enums = new[] { MyEnum.Value2, MyEnum.Value3 },
NullableInts = new int?[] { null, null },
+ NullableStrings = new string?[] { null, null }
},
new()
{
@@ -1046,6 +1098,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bool = false,
Enum = MyEnum.Value1,
NullableInt = null,
+ NullableString = null,
Ints = Array.Empty(),
Strings = Array.Empty(),
@@ -1053,6 +1106,7 @@ private static IReadOnlyList CreatePrimitiveArrayEnt
Bools = Array.Empty(),
Enums = Array.Empty(),
NullableInts = Array.Empty(),
+ NullableStrings = Array.Empty()
}
};
}
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs
index a06b20d0242..f3dce36adad 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQueryOldSqlServerTest.cs
@@ -26,7 +26,7 @@ public override async Task Inline_collection_of_ints_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (10, 999)
""");
@@ -38,7 +38,7 @@ public override async Task Inline_collection_of_nullable_ints_Contains(bool asyn
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[NullableInt] IN (10, 999)
""");
@@ -50,7 +50,7 @@ public override async Task Inline_collection_of_nullable_ints_Contains_null(bool
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[NullableInt] IS NULL OR [p].[NullableInt] = 999
""");
@@ -67,7 +67,7 @@ public override async Task Inline_collection_Count_with_one_value(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -82,7 +82,7 @@ public override async Task Inline_collection_Count_with_two_values(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -97,7 +97,7 @@ public override async Task Inline_collection_Count_with_three_values(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -117,7 +117,7 @@ public override async Task Inline_collection_Contains_with_one_value(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] = 2
""");
@@ -129,7 +129,7 @@ public override async Task Inline_collection_Contains_with_two_values(bool async
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, 999)
""");
@@ -141,7 +141,7 @@ public override async Task Inline_collection_Contains_with_three_values(bool asy
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, 999, 1000)
""");
@@ -156,7 +156,7 @@ public override async Task Inline_collection_Contains_with_all_parameters(bool a
@__i_0='2'
@__j_1='999'
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (@__i_0, @__j_1)
""");
@@ -170,7 +170,7 @@ public override async Task Inline_collection_Contains_with_constant_and_paramete
"""
@__j_0='999'
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, @__j_0)
""");
@@ -184,7 +184,7 @@ public override async Task Inline_collection_Contains_with_mixed_value_types(boo
"""
@__i_0='11'
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (999, @__i_0, [p].[Id], [p].[Id] + [p].[Int])
""");
@@ -196,7 +196,7 @@ public override async Task Inline_collection_Contains_as_Any_with_predicate(bool
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, 999)
""");
@@ -208,7 +208,7 @@ public override async Task Inline_collection_negated_Contains_as_All(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] NOT IN (2, 999)
""");
@@ -223,7 +223,7 @@ public override async Task Parameter_collection_of_ints_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (10, 999)
""");
@@ -235,7 +235,7 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_int(bo
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (10, 999)
""");
@@ -247,31 +247,43 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_nullab
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[NullableInt] IS NULL OR [p].[NullableInt] = 999
""");
}
- public override async Task Parameter_collection_of_strings_Contains(bool async)
+ public override async Task Parameter_collection_of_strings_Contains_non_nullable_string(bool async)
{
- await base.Parameter_collection_of_strings_Contains(async);
+ await base.Parameter_collection_of_strings_Contains_non_nullable_string(async);
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[String] IN (N'10', N'999')
""");
}
+ public override async Task Parameter_collection_of_strings_Contains_nullable_string(bool async)
+ {
+ await base.Parameter_collection_of_strings_Contains_nullable_string(async);
+
+ AssertSql(
+"""
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
+FROM [PrimitiveCollectionsEntity] AS [p]
+WHERE [p].[NullableString] IS NULL OR [p].[NullableString] = N'999'
+""");
+ }
+
public override async Task Parameter_collection_of_DateTimes_Contains(bool async)
{
await base.Parameter_collection_of_DateTimes_Contains(async);
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[DateTime] IN ('2020-01-10T12:30:00.0000000Z', '9999-01-01T00:00:00.0000000Z')
""");
@@ -283,7 +295,7 @@ public override async Task Parameter_collection_of_bools_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Bool] = CAST(1 AS bit)
""");
@@ -295,7 +307,7 @@ public override async Task Parameter_collection_of_enums_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Enum] IN (0, 3)
""");
@@ -307,7 +319,7 @@ public override async Task Parameter_collection_null_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE 0 = 1
""");
@@ -325,6 +337,9 @@ public override Task Column_collection_of_nullable_ints_Contains_null(bool async
public override Task Column_collection_of_strings_contains_null(bool async)
=> AssertTranslationFailed(() => base.Column_collection_of_strings_contains_null(async));
+ public override Task Column_collection_of_nullable_strings_contains_null(bool async)
+ => AssertTranslationFailed(() => base.Column_collection_of_strings_contains_null(async));
+
public override Task Column_collection_of_bools_Contains(bool async)
=> AssertCompatibilityLevelTooLow(() => base.Column_collection_of_bools_Contains(async));
@@ -356,13 +371,19 @@ public override Task Column_collection_index_datetime(bool async)
public override Task Column_collection_index_beyond_end(bool async)
=> AssertCompatibilityLevelTooLow(() => base.Column_collection_index_beyond_end(async));
+ public override Task Nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ => AssertCompatibilityLevelTooLow(() => base.Column_collection_index_beyond_end(async));
+
+ public override Task Non_nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ => AssertCompatibilityLevelTooLow(() => base.Column_collection_index_beyond_end(async));
+
public override async Task Inline_collection_index_Column(bool async)
{
await base.Inline_collection_index_Column(async);
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT [v].[Value]
@@ -437,7 +458,7 @@ public override async Task Column_collection_equality_parameter_collection(bool
"""
@__ints_0='[1,10]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Ints] = @__ints_0
""");
@@ -456,7 +477,7 @@ public override async Task Column_collection_equality_inline_collection(bool asy
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Ints] = N'[1,10]'
""");
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs
index dd15cb86944..e2ddaa9a82f 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrimitiveCollectionsQuerySqlServerTest.cs
@@ -3,6 +3,8 @@
namespace Microsoft.EntityFrameworkCore.Query;
+#nullable enable
+
public class PrimitiveCollectionsQuerySqlServerTest : PrimitiveCollectionsQueryTestBase<
PrimitiveCollectionsQuerySqlServerTest.PrimitiveCollectionsQuerySqlServerFixture>
{
@@ -19,7 +21,7 @@ public override async Task Inline_collection_of_ints_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (10, 999)
""");
@@ -31,7 +33,7 @@ public override async Task Inline_collection_of_nullable_ints_Contains(bool asyn
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[NullableInt] IN (10, 999)
""");
@@ -43,7 +45,7 @@ public override async Task Inline_collection_of_nullable_ints_Contains_null(bool
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[NullableInt] IS NULL OR [p].[NullableInt] = 999
""");
@@ -60,7 +62,7 @@ public override async Task Inline_collection_Count_with_one_value(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -75,7 +77,7 @@ public override async Task Inline_collection_Count_with_two_values(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -90,7 +92,7 @@ public override async Task Inline_collection_Count_with_three_values(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -110,7 +112,7 @@ public override async Task Inline_collection_Contains_with_one_value(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] = 2
""");
@@ -122,7 +124,7 @@ public override async Task Inline_collection_Contains_with_two_values(bool async
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, 999)
""");
@@ -134,7 +136,7 @@ public override async Task Inline_collection_Contains_with_three_values(bool asy
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, 999, 1000)
""");
@@ -149,7 +151,7 @@ public override async Task Inline_collection_Contains_with_all_parameters(bool a
@__i_0='2'
@__j_1='999'
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (@__i_0, @__j_1)
""");
@@ -163,7 +165,7 @@ public override async Task Inline_collection_Contains_with_constant_and_paramete
"""
@__j_0='999'
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, @__j_0)
""");
@@ -177,7 +179,7 @@ public override async Task Inline_collection_Contains_with_mixed_value_types(boo
"""
@__i_0='11'
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (999, @__i_0, [p].[Id], [p].[Id] + [p].[Int])
""");
@@ -189,7 +191,7 @@ public override async Task Inline_collection_Contains_as_Any_with_predicate(bool
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] IN (2, 999)
""");
@@ -201,7 +203,7 @@ public override async Task Inline_collection_negated_Contains_as_All(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] NOT IN (2, 999)
""");
@@ -215,7 +217,7 @@ public override async Task Parameter_collection_Count(bool async)
"""
@__ids_0='[2,999]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -232,7 +234,7 @@ public override async Task Parameter_collection_of_ints_Contains(bool async)
"""
@__ints_0='[10,999]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (
SELECT [i].[value]
@@ -249,7 +251,7 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_int(bo
"""
@__nullableInts_0='[10,999]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (
SELECT [n].[value]
@@ -266,7 +268,7 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_nullab
"""
@__nullableInts_0='[null,999]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE EXISTS (
SELECT 1
@@ -275,20 +277,37 @@ FROM OPENJSON(@__nullableInts_0) WITH ([value] int '$') AS [n]
""");
}
- public override async Task Parameter_collection_of_strings_Contains(bool async)
+ public override async Task Parameter_collection_of_strings_Contains_non_nullable_string(bool async)
{
- await base.Parameter_collection_of_strings_Contains(async);
+ await base.Parameter_collection_of_strings_Contains_non_nullable_string(async);
AssertSql(
"""
@__strings_0='["10","999"]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
+FROM [PrimitiveCollectionsEntity] AS [p]
+WHERE [p].[String] IN (
+ SELECT [s].[value]
+ FROM OPENJSON(@__strings_0) WITH ([value] nvarchar(max) '$') AS [s]
+)
+""");
+ }
+
+ public override async Task Parameter_collection_of_strings_Contains_nullable_string(bool async)
+ {
+ await base.Parameter_collection_of_strings_Contains_nullable_string(async);
+
+ AssertSql(
+ """
+@__strings_0='["999",null]' (Size = 4000)
+
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE EXISTS (
SELECT 1
FROM OPENJSON(@__strings_0) WITH ([value] nvarchar(max) '$') AS [s]
- WHERE [s].[value] = [p].[String] OR ([s].[value] IS NULL AND [p].[String] IS NULL))
+ WHERE [s].[value] = [p].[NullableString] OR ([s].[value] IS NULL AND [p].[NullableString] IS NULL))
""");
}
@@ -300,7 +319,7 @@ public override async Task Parameter_collection_of_DateTimes_Contains(bool async
"""
@__dateTimes_0='["2020-01-10T12:30:00Z","9999-01-01T00:00:00Z"]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[DateTime] IN (
SELECT [d].[value]
@@ -317,7 +336,7 @@ public override async Task Parameter_collection_of_bools_Contains(bool async)
"""
@__bools_0='[true]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Bool] IN (
SELECT [b].[value]
@@ -334,7 +353,7 @@ public override async Task Parameter_collection_of_enums_Contains(bool async)
"""
@__enums_0='[0,3]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Enum] IN (
SELECT [e].[value]
@@ -349,7 +368,7 @@ public override async Task Parameter_collection_null_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Int] IN (
SELECT [i].[value]
@@ -364,7 +383,7 @@ public override async Task Column_collection_of_ints_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE 10 IN (
SELECT [i].[value]
@@ -379,7 +398,7 @@ public override async Task Column_collection_of_nullable_ints_Contains(bool asyn
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE 10 IN (
SELECT [n].[value]
@@ -394,7 +413,7 @@ public override async Task Column_collection_of_nullable_ints_Contains_null(bool
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE EXISTS (
SELECT 1
@@ -409,12 +428,24 @@ public override async Task Column_collection_of_strings_contains_null(bool async
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
+FROM [PrimitiveCollectionsEntity] AS [p]
+WHERE 0 = 1
+""");
+ }
+
+ public override async Task Column_collection_of_nullable_strings_contains_null(bool async)
+ {
+ await base.Column_collection_of_nullable_strings_contains_null(async);
+
+ AssertSql(
+"""
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE EXISTS (
SELECT 1
- FROM OPENJSON([p].[Strings]) WITH ([value] nvarchar(max) '$') AS [s]
- WHERE [s].[value] IS NULL)
+ FROM OPENJSON([p].[NullableStrings]) WITH ([value] nvarchar(max) '$') AS [n]
+ WHERE [n].[value] IS NULL)
""");
}
@@ -424,7 +455,7 @@ public override async Task Column_collection_of_bools_Contains(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(1 AS bit) IN (
SELECT [b].[value]
@@ -450,7 +481,7 @@ public override async Task Column_collection_Count_method(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -464,7 +495,7 @@ public override async Task Column_collection_Length(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -478,7 +509,7 @@ public override async Task Column_collection_index_int(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(JSON_VALUE([p].[Ints], '$[1]') AS int) = 10
""");
@@ -490,7 +521,7 @@ public override async Task Column_collection_index_string(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE JSON_VALUE([p].[Strings], '$[1]') = N'10'
""");
@@ -502,7 +533,7 @@ public override async Task Column_collection_index_datetime(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(JSON_VALUE([p].[DateTimes], '$[1]') AS datetime2) = '2020-01-10T12:30:00.0000000Z'
""");
@@ -514,19 +545,45 @@ public override async Task Column_collection_index_beyond_end(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(JSON_VALUE([p].[Ints], '$[999]') AS int) = 10
""");
}
+ public override async Task Nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ {
+ await base.Nullable_reference_column_collection_index_equals_nullable_column(async);
+
+ AssertSql(
+ """
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
+FROM [PrimitiveCollectionsEntity] AS [p]
+WHERE JSON_VALUE([p].[NullableStrings], '$[2]') = [p].[NullableString] OR (JSON_VALUE([p].[NullableStrings], '$[2]') IS NULL AND [p].[NullableString] IS NULL)
+""");
+ }
+
+ public override async Task Non_nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ {
+ await base.Non_nullable_reference_column_collection_index_equals_nullable_column(async);
+
+ AssertSql(
+"""
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
+FROM [PrimitiveCollectionsEntity] AS [p]
+WHERE EXISTS (
+ SELECT 1
+ FROM OPENJSON([p].[Strings]) WITH ([value] nvarchar(max) '$') AS [s]) AND JSON_VALUE([p].[Strings], '$[1]') = [p].[NullableString]
+""");
+ }
+
public override async Task Inline_collection_index_Column(bool async)
{
await base.Inline_collection_index_Column(async);
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT [v].[Value]
@@ -545,7 +602,7 @@ public override async Task Parameter_collection_index_Column_equal_Column(bool a
"""
@__ints_0='[0,2,3]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(JSON_VALUE(@__ints_0, '$[' + CAST([p].[Int] AS nvarchar(max)) + ']') AS int) = [p].[Int]
""");
@@ -560,7 +617,7 @@ public override async Task Parameter_collection_index_Column_equal_constant(bool
"""
@__ints_0='[1,2,3]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(JSON_VALUE(@__ints_0, '$[' + CAST([p].[Int] AS nvarchar(max)) + ']') AS int) = 1
""");
@@ -572,7 +629,7 @@ public override async Task Column_collection_ElementAt(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE CAST(JSON_VALUE([p].[Ints], '$[1]') AS int) = 10
""");
@@ -584,7 +641,7 @@ public override async Task Column_collection_Skip(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -603,7 +660,7 @@ public override async Task Column_collection_Take(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE 11 IN (
SELECT TOP(2) CAST([i].[value] AS int) AS [value]
@@ -619,7 +676,7 @@ public override async Task Column_collection_Skip_Take(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE 11 IN (
SELECT CAST([i].[value] AS int) AS [value]
@@ -636,7 +693,7 @@ public override async Task Column_collection_OrderByDescending_ElementAt(bool as
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT [i].[value]
@@ -652,7 +709,7 @@ public override async Task Column_collection_Any(bool async)
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE EXISTS (
SELECT 1
@@ -665,8 +722,8 @@ public override async Task Column_collection_Distinct(bool async)
await base.Column_collection_Distinct(async);
AssertSql(
-"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+ """
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -697,7 +754,7 @@ public override async Task Column_collection_Join_parameter_collection(bool asyn
"""
@__ints_0='[11,111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -712,7 +769,7 @@ public override async Task Inline_collection_Join_ordered_column_collection(bool
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -729,7 +786,7 @@ public override async Task Parameter_collection_Concat_column_collection(bool as
"""
@__ints_0='[11,111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -751,7 +808,7 @@ public override async Task Column_collection_Union_parameter_collection(bool asy
"""
@__ints_0='[11,111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -771,7 +828,7 @@ public override async Task Column_collection_Intersect_inline_collection(bool as
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -791,7 +848,7 @@ public override async Task Inline_collection_Except_column_collection(bool async
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -814,7 +871,7 @@ public override async Task Column_collection_equality_parameter_collection(bool
"""
@__ints_0='[1,10]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Ints] = @__ints_0
""");
@@ -833,7 +890,7 @@ public override async Task Column_collection_equality_inline_collection(bool asy
AssertSql(
"""
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Ints] = N'[1,10]'
""");
@@ -854,7 +911,7 @@ public override async Task Parameter_collection_in_subquery_Union_column_collect
"""
@__ints='[10,111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -878,10 +935,10 @@ public override async Task Parameter_collection_in_subquery_Union_column_collect
await base.Parameter_collection_in_subquery_Union_column_collection(async);
AssertSql(
-"""
+ """
@__Skip_0='[111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -900,10 +957,10 @@ public override async Task Parameter_collection_in_subquery_Union_column_collect
await base.Parameter_collection_in_subquery_Union_column_collection_nested(async);
AssertSql(
-"""
+ """
@__Skip_0='[111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -975,7 +1032,7 @@ public override async Task Column_collection_in_subquery_Union_parameter_collect
"""
@__ints_0='[10,111]' (Size = 4000)
-SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[String], [p].[Strings]
+SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE (
SELECT COUNT(*)
@@ -999,7 +1056,7 @@ public override async Task Project_collection_of_ints_simple(bool async)
await base.Project_collection_of_ints_simple(async);
AssertSql(
-"""
+ """
SELECT [p].[Ints]
FROM [PrimitiveCollectionsEntity] AS [p]
ORDER BY [p].[Id]
@@ -1011,7 +1068,7 @@ public override async Task Project_collection_of_ints_ordered(bool async)
await base.Project_collection_of_ints_ordered(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], CAST([i].[value] AS int) AS [value], [i].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY OPENJSON([p].[Ints]) AS [i]
@@ -1024,7 +1081,7 @@ public override async Task Project_collection_of_datetimes_filtered(bool async)
await base.Project_collection_of_datetimes_filtered(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], [t].[value], [t].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY (
@@ -1041,7 +1098,7 @@ public override async Task Project_collection_of_ints_with_paging(bool async)
await base.Project_collection_of_ints_with_paging(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], [t].[value], [t].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY (
@@ -1058,7 +1115,7 @@ public override async Task Project_collection_of_ints_with_paging2(bool async)
await base.Project_collection_of_ints_with_paging2(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], [t].[value], [t].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY (
@@ -1076,7 +1133,7 @@ public override async Task Project_collection_of_ints_with_paging3(bool async)
await base.Project_collection_of_ints_with_paging3(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], [t].[value], [t].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY (
@@ -1094,7 +1151,7 @@ public override async Task Project_collection_of_ints_with_distinct(bool async)
await base.Project_collection_of_ints_with_distinct(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], [t].[value]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY (
@@ -1117,7 +1174,7 @@ public override async Task Project_empty_collection_of_nullables_and_collection_
await base.Project_empty_collection_of_nullables_and_collection_only_containing_nulls(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], [t].[value], [t].[key], [t0].[value], [t0].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY (
@@ -1139,7 +1196,7 @@ public override async Task Project_multiple_collections(bool async)
await base.Project_multiple_collections(async);
AssertSql(
-"""
+ """
SELECT [p].[Id], CAST([i].[value] AS int) AS [value], [i].[key], CAST([i0].[value] AS int) AS [value], [i0].[key], [t].[value], [t].[key], [t0].[value], [t0].[key]
FROM [PrimitiveCollectionsEntity] AS [p]
OUTER APPLY OPENJSON([p].[Ints]) AS [i]
@@ -1163,7 +1220,7 @@ public override async Task Project_primitive_collections_element(bool async)
await base.Project_primitive_collections_element(async);
AssertSql(
-"""
+ """
SELECT CAST(JSON_VALUE([p].[Ints], '$[0]') AS int) AS [Indexer], CAST(JSON_VALUE([p].[DateTimes], '$[0]') AS datetime2) AS [EnumerableElementAt], JSON_VALUE([p].[Strings], '$[1]') AS [QueryableElementAt]
FROM [PrimitiveCollectionsEntity] AS [p]
WHERE [p].[Id] < 4
diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs
index 37b34f924f1..e5e028e8ac3 100644
--- a/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs
+++ b/test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs
@@ -22,7 +22,7 @@ public override async Task Inline_collection_of_ints_Contains(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Int" IN (10, 999)
""");
@@ -34,7 +34,7 @@ public override async Task Inline_collection_of_nullable_ints_Contains(bool asyn
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."NullableInt" IN (10, 999)
""");
@@ -46,7 +46,7 @@ public override async Task Inline_collection_of_nullable_ints_Contains_null(bool
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."NullableInt" IS NULL OR "p"."NullableInt" = 999
""");
@@ -63,7 +63,7 @@ public override async Task Inline_collection_Count_with_one_value(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -78,7 +78,7 @@ public override async Task Inline_collection_Count_with_two_values(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -93,7 +93,7 @@ public override async Task Inline_collection_Count_with_three_values(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -113,7 +113,7 @@ public override async Task Inline_collection_Contains_with_one_value(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" = 2
""");
@@ -125,7 +125,7 @@ public override async Task Inline_collection_Contains_with_two_values(bool async
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" IN (2, 999)
""");
@@ -137,7 +137,7 @@ public override async Task Inline_collection_Contains_with_three_values(bool asy
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" IN (2, 999, 1000)
""");
@@ -152,7 +152,7 @@ public override async Task Inline_collection_Contains_with_all_parameters(bool a
@__i_0='2'
@__j_1='999'
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" IN (@__i_0, @__j_1)
""");
@@ -166,7 +166,7 @@ public override async Task Inline_collection_Contains_with_constant_and_paramete
"""
@__j_0='999'
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" IN (2, @__j_0)
""");
@@ -180,7 +180,7 @@ public override async Task Inline_collection_Contains_with_mixed_value_types(boo
"""
@__i_0='11'
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Int" IN (999, @__i_0, "p"."Id", "p"."Id" + "p"."Int")
""");
@@ -192,7 +192,7 @@ public override async Task Inline_collection_Contains_as_Any_with_predicate(bool
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" IN (2, 999)
""");
@@ -204,7 +204,7 @@ public override async Task Inline_collection_negated_Contains_as_All(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" NOT IN (2, 999)
""");
@@ -218,7 +218,7 @@ public override async Task Parameter_collection_Count(bool async)
"""
@__ids_0='[2,999]' (Size = 7)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -235,7 +235,7 @@ public override async Task Parameter_collection_of_ints_Contains(bool async)
"""
@__ints_0='[10,999]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Int" IN (
SELECT "i"."value"
@@ -252,7 +252,7 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_int(bo
"""
@__nullableInts_0='[10,999]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Int" IN (
SELECT "n"."value"
@@ -269,7 +269,7 @@ public override async Task Parameter_collection_of_nullable_ints_Contains_nullab
"""
@__nullableInts_0='[null,999]' (Size = 10)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE EXISTS (
SELECT 1
@@ -278,21 +278,39 @@ FROM json_each(@__nullableInts_0) AS "n"
""");
}
- public override async Task Parameter_collection_of_strings_Contains(bool async)
+ public override async Task Parameter_collection_of_strings_Contains_non_nullable_string(bool async)
{
- await base.Parameter_collection_of_strings_Contains(async);
+ await base.Parameter_collection_of_strings_Contains_non_nullable_string(async);
AssertSql(
"""
@__strings_0='["10","999"]' (Size = 12)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
+FROM "PrimitiveCollectionsEntity" AS "p"
+WHERE "p"."String" IN (
+ SELECT "s"."value"
+ FROM json_each(@__strings_0) AS "s"
+)
+""");
+ }
+
+ public override async Task Parameter_collection_of_strings_Contains_nullable_string(bool async)
+ {
+ await base.Parameter_collection_of_strings_Contains_nullable_string(async);
+
+ AssertSql(
+ """
+@__strings_0='["999",null]' (Size = 12)
+
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE EXISTS (
SELECT 1
FROM json_each(@__strings_0) AS "s"
- WHERE "s"."value" = "p"."String" OR ("s"."value" IS NULL AND "p"."String" IS NULL))
+ WHERE "s"."value" = "p"."NullableString" OR ("s"."value" IS NULL AND "p"."NullableString" IS NULL))
""");
+
}
public override async Task Parameter_collection_of_DateTimes_Contains(bool async)
@@ -303,7 +321,7 @@ public override async Task Parameter_collection_of_DateTimes_Contains(bool async
"""
@__dateTimes_0='["2020-01-10T12:30:00Z","9999-01-01T00:00:00Z"]' (Size = 47)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."DateTime" IN (
SELECT rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', "d"."value"), '0'), '.') AS "value"
@@ -320,7 +338,7 @@ public override async Task Parameter_collection_of_bools_Contains(bool async)
"""
@__bools_0='[true]' (Size = 6)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Bool" IN (
SELECT "b"."value"
@@ -337,7 +355,7 @@ public override async Task Parameter_collection_of_enums_Contains(bool async)
"""
@__enums_0='[0,3]' (Size = 5)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Enum" IN (
SELECT "e"."value"
@@ -352,7 +370,7 @@ public override async Task Parameter_collection_null_Contains(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Int" IN (
SELECT "i"."value"
@@ -367,7 +385,7 @@ public override async Task Column_collection_of_ints_Contains(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE 10 IN (
SELECT "i"."value"
@@ -382,7 +400,7 @@ public override async Task Column_collection_of_nullable_ints_Contains(bool asyn
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE 10 IN (
SELECT "n"."value"
@@ -397,7 +415,7 @@ public override async Task Column_collection_of_nullable_ints_Contains_null(bool
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE EXISTS (
SELECT 1
@@ -412,12 +430,24 @@ public override async Task Column_collection_of_strings_contains_null(bool async
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
+FROM "PrimitiveCollectionsEntity" AS "p"
+WHERE 0
+""");
+ }
+
+ public override async Task Column_collection_of_nullable_strings_contains_null(bool async)
+ {
+ await base.Column_collection_of_nullable_strings_contains_null(async);
+
+ AssertSql(
+ """
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE EXISTS (
SELECT 1
- FROM json_each("p"."Strings") AS "s"
- WHERE "s"."value" IS NULL)
+ FROM json_each("p"."NullableStrings") AS "n"
+ WHERE "n"."value" IS NULL)
""");
}
@@ -427,7 +457,7 @@ public override async Task Column_collection_of_bools_Contains(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE 1 IN (
SELECT "b"."value"
@@ -442,7 +472,7 @@ public override async Task Column_collection_Count_method(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE json_array_length("p"."Ints") = 2
""");
@@ -454,7 +484,7 @@ public override async Task Column_collection_Length(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE json_array_length("p"."Ints") = 2
""");
@@ -466,7 +496,7 @@ public override async Task Column_collection_index_int(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Ints" ->> 1 = 10
""");
@@ -478,7 +508,7 @@ public override async Task Column_collection_index_string(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Strings" ->> 1 = '10'
""");
@@ -490,7 +520,7 @@ public override async Task Column_collection_index_datetime(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', "p"."DateTimes" ->> 1), '0'), '.') = '2020-01-10 12:30:00'
""");
@@ -502,12 +532,36 @@ public override async Task Column_collection_index_beyond_end(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Ints" ->> 999 = 10
""");
}
+ public override async Task Nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ {
+ await base.Nullable_reference_column_collection_index_equals_nullable_column(async);
+
+ AssertSql(
+ """
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
+FROM "PrimitiveCollectionsEntity" AS "p"
+WHERE "p"."NullableStrings" ->> 2 = "p"."NullableString" OR ("p"."NullableStrings" ->> 2 IS NULL AND "p"."NullableString" IS NULL)
+""");
+ }
+
+ public override async Task Non_nullable_reference_column_collection_index_equals_nullable_column(bool async)
+ {
+ await base.Non_nullable_reference_column_collection_index_equals_nullable_column(async);
+
+ AssertSql(
+ """
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
+FROM "PrimitiveCollectionsEntity" AS "p"
+WHERE json_array_length("p"."Strings") > 0 AND "p"."Strings" ->> 1 = "p"."NullableString"
+""");
+ }
+
public override async Task Inline_collection_index_Column(bool async)
{
// SQLite doesn't support correlated subqueries where the outer column is used as the LIMIT/OFFSET (see OFFSET "p"."Int" below)
@@ -515,7 +569,7 @@ public override async Task Inline_collection_index_Column(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT "v"."Value"
@@ -533,7 +587,7 @@ public override async Task Parameter_collection_index_Column_equal_Column(bool a
"""
@__ints_0='[0,2,3]' (Size = 7)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE @__ints_0 ->> "p"."Int" = "p"."Int"
""");
@@ -547,7 +601,7 @@ public override async Task Parameter_collection_index_Column_equal_constant(bool
"""
@__ints_0='[1,2,3]' (Size = 7)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE @__ints_0 ->> "p"."Int" = 1
""");
@@ -559,7 +613,7 @@ public override async Task Column_collection_ElementAt(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Ints" ->> 1 = 10
""");
@@ -571,7 +625,7 @@ public override async Task Column_collection_Skip(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -590,7 +644,7 @@ public override async Task Column_collection_Take(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE 11 IN (
SELECT "i"."value"
@@ -607,7 +661,7 @@ public override async Task Column_collection_Skip_Take(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE 11 IN (
SELECT "i"."value"
@@ -624,7 +678,7 @@ public override async Task Column_collection_OrderByDescending_ElementAt(bool as
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT "i"."value"
@@ -640,7 +694,7 @@ public override async Task Column_collection_Any(bool async)
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE json_array_length("p"."Ints") > 0
""");
@@ -651,8 +705,8 @@ public override async Task Column_collection_Distinct(bool async)
await base.Column_collection_Distinct(async);
AssertSql(
-"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+ """
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -683,7 +737,7 @@ public override async Task Column_collection_Join_parameter_collection(bool asyn
"""
@__ints_0='[11,111]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -698,7 +752,7 @@ public override async Task Inline_collection_Join_ordered_column_collection(bool
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -715,7 +769,7 @@ public override async Task Parameter_collection_Concat_column_collection(bool as
"""
@__ints_0='[11,111]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -737,7 +791,7 @@ public override async Task Column_collection_Union_parameter_collection(bool asy
"""
@__ints_0='[11,111]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -757,7 +811,7 @@ public override async Task Column_collection_Intersect_inline_collection(bool as
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -776,7 +830,7 @@ public override async Task Inline_collection_Except_column_collection(bool async
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -798,7 +852,7 @@ public override async Task Column_collection_equality_parameter_collection(bool
"""
@__ints_0='[1,10]' (Size = 6)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Ints" = @__ints_0
""");
@@ -817,7 +871,7 @@ public override async Task Column_collection_equality_inline_collection(bool asy
AssertSql(
"""
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Ints" = '[1,10]'
""");
@@ -835,7 +889,7 @@ public override async Task Parameter_collection_in_subquery_Count_as_compiled_qu
await base.Parameter_collection_in_subquery_Count_as_compiled_query(async);
AssertSql(
-"""
+ """
@__ints='[10,111]' (Size = 8)
SELECT COUNT(*)
@@ -865,10 +919,10 @@ public override async Task Parameter_collection_in_subquery_Union_column_collect
await base.Parameter_collection_in_subquery_Union_column_collection_as_compiled_query(async);
AssertSql(
-"""
+ """
@__ints='[10,111]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -892,10 +946,10 @@ public override async Task Parameter_collection_in_subquery_Union_column_collect
await base.Parameter_collection_in_subquery_Union_column_collection(async);
AssertSql(
-"""
+ """
@__Skip_0='[111]' (Size = 5)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -914,10 +968,10 @@ public override async Task Parameter_collection_in_subquery_Union_column_collect
await base.Parameter_collection_in_subquery_Union_column_collection_nested(async);
AssertSql(
-"""
+ """
@__Skip_0='[111]' (Size = 5)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -959,7 +1013,7 @@ public override async Task Column_collection_in_subquery_Union_parameter_collect
"""
@__ints_0='[10,111]' (Size = 8)
-SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."String", "p"."Strings"
+SELECT "p"."Id", "p"."Bool", "p"."Bools", "p"."DateTime", "p"."DateTimes", "p"."Enum", "p"."Enums", "p"."Int", "p"."Ints", "p"."NullableInt", "p"."NullableInts", "p"."NullableString", "p"."NullableStrings", "p"."String", "p"."Strings"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE (
SELECT COUNT(*)
@@ -983,7 +1037,7 @@ public override async Task Project_collection_of_ints_simple(bool async)
await base.Project_collection_of_ints_simple(async);
AssertSql(
-"""
+ """
SELECT "p"."Ints"
FROM "PrimitiveCollectionsEntity" AS "p"
ORDER BY "p"."Id"
@@ -1043,7 +1097,7 @@ public override async Task Project_primitive_collections_element(bool async)
await base.Project_primitive_collections_element(async);
AssertSql(
-"""
+ """
SELECT "p"."Ints" ->> 0 AS "Indexer", rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', "p"."DateTimes" ->> 0), '0'), '.') AS "EnumerableElementAt", "p"."Strings" ->> 1 AS "QueryableElementAt"
FROM "PrimitiveCollectionsEntity" AS "p"
WHERE "p"."Id" < 4
diff --git a/test/EFCore.Tests/Metadata/Conventions/NonNullableReferencePropertyConventionTest.cs b/test/EFCore.Tests/Metadata/Conventions/NonNullableReferencePropertyConventionTest.cs
index e14810a40c1..718dc70294f 100644
--- a/test/EFCore.Tests/Metadata/Conventions/NonNullableReferencePropertyConventionTest.cs
+++ b/test/EFCore.Tests/Metadata/Conventions/NonNullableReferencePropertyConventionTest.cs
@@ -87,6 +87,25 @@ public void Dictionary_indexer_is_not_configured_as_non_nullable()
Assert.True(entityTypeBuilder.Property("b").Metadata.IsNullable);
}
+ [ConditionalFact]
+ public void Primitive_collection_with_non_nullable_element()
+ {
+ var modelBuilder = CreateModelBuilder();
+ var entityTypeBuilder = modelBuilder.Entity();
+
+ Assert.False(
+ entityTypeBuilder.PrimitiveCollection(a => a.PrimitiveCollectionWithNonNullableElement).ElementType().Metadata.IsNullable);
+ }
+
+ [ConditionalFact]
+ public void Primitive_collection_with_nullable_element()
+ {
+ var modelBuilder = CreateModelBuilder();
+ var entityTypeBuilder = modelBuilder.Entity();
+
+ Assert.True(entityTypeBuilder.PrimitiveCollection(a => a.PrimitiveCollectionWithNullableElement).ElementType().Metadata.IsNullable);
+ }
+
private void RunConvention(InternalPropertyBuilder propertyBuilder)
{
var context = new ConventionContext(
@@ -146,6 +165,9 @@ public string NonNullable
[Required]
public string? RequiredAndNullable { get; set; }
+ public List PrimitiveCollectionWithNonNullableElement { get; set; } = new();
+ public List PrimitiveCollectionWithNullableElement { get; set; } = new();
+
#nullable disable
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' context.
public string NullObliviousNonNullable { get; set; }
diff --git a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs
index 9413ae7ec64..606521fdfe9 100644
--- a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs
+++ b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs
@@ -3061,7 +3061,7 @@ public virtual void Element_types_are_nullable_by_default_if_the_type_is_nullabl
var entityType = modelBuilder.FinalizeModel().FindEntityType(typeof(CollectionQuarks))!;
Assert.False(entityType.FindProperty(nameof(CollectionQuarks.Up))!.GetElementType()!.IsNullable);
- Assert.True(entityType.FindProperty(nameof(CollectionQuarks.Down))!.GetElementType()!.IsNullable); // Issue #31416
+ Assert.False(entityType.FindProperty(nameof(CollectionQuarks.Down))!.GetElementType()!.IsNullable);
Assert.True(entityType.FindProperty("Charm")!.GetElementType()!.IsNullable);
Assert.True(entityType.FindProperty("Strange")!.GetElementType()!.IsNullable);
Assert.True(entityType.FindProperty("Stranger")!.GetElementType()!.IsNullable);