Merge remote-tracking branch 'origin/v8/dev' into v9/feature/merge-v8_29-10-2021

# Conflicts:
#	src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs
#	src/Umbraco.Web.UI.Client/package.json
#	src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.html
#	src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html
#	src/Umbraco.Web.UI.Client/src/views/documenttypes/importdocumenttype.html
#	src/Umbraco.Web.UI/umbraco/config/lang/en.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
#	src/Umbraco.Web.UI/umbraco/config/lang/nl.xml
This commit is contained in:
Bjarke Berg
2021-10-29 09:52:39 +02:00
64 changed files with 669 additions and 496 deletions

View File

@@ -53,7 +53,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
var entries = new List<IAuditEntry>();
foreach (var group in ids.InGroupsOf(2000))
foreach (var group in ids.InGroupsOf(Constants.Sql.MaxParameterCount))
{
var sql = Sql()
.Select<AuditEntryDto>()

View File

@@ -657,7 +657,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
// in the table?
// get all PropertyDataDto for all definitions / versions
var allPropertyDataDtos = Database.FetchByGroups<PropertyDataDto, int>(versions, 2000, batch =>
var allPropertyDataDtos = Database.FetchByGroups<PropertyDataDto, int>(versions, Constants.Sql.MaxParameterCount, batch =>
SqlContext.Sql()
.Select<PropertyDataDto>()
.From<PropertyDataDto>()
@@ -666,7 +666,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
// get PropertyDataDto distinct PropertyTypeDto
var allPropertyTypeIds = allPropertyDataDtos.Select(x => x.PropertyTypeId).Distinct().ToList();
var allPropertyTypeDtos = Database.FetchByGroups<PropertyTypeDto, int>(allPropertyTypeIds, 2000, batch =>
var allPropertyTypeDtos = Database.FetchByGroups<PropertyTypeDto, int>(allPropertyTypeIds, Constants.Sql.MaxParameterCount, batch =>
SqlContext.Sql()
.Select<PropertyTypeDto>(r => r.Select(x => x.DataTypeDto))
.From<PropertyTypeDto>()

View File

@@ -795,7 +795,7 @@ AND umbracoNode.id <> @id",
// note: important to use SqlNullableEquals for nullable types, cannot directly compare language identifiers
var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0);
if (whereInArgsCount > 2000)
if (whereInArgsCount > Constants.Sql.MaxParameterCount)
throw new NotSupportedException("Too many property/content types.");
// delete existing relations (for target language)
@@ -933,7 +933,7 @@ AND umbracoNode.id <> @id",
// note: important to use SqlNullableEquals for nullable types, cannot directly compare language identifiers
//
var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0);
if (whereInArgsCount > 2000)
if (whereInArgsCount > Constants.Sql.MaxParameterCount)
throw new NotSupportedException("Too many property/content types.");
//first clear out any existing property data that might already exists under the target language
@@ -1032,7 +1032,7 @@ AND umbracoNode.id <> @id",
//based on the current variance of each item to see if it's 'edited' value should be true/false.
var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0);
if (whereInArgsCount > 2000)
if (whereInArgsCount > Constants.Sql.MaxParameterCount)
throw new NotSupportedException("Too many property/content types.");
var propertySql = Sql()
@@ -1121,14 +1121,20 @@ AND umbracoNode.id <> @id",
}
}
//lookup all matching rows in umbracoDocumentCultureVariation
var docCultureVariationsToUpdate = editedLanguageVersions.InGroupsOf(2000)
.SelectMany(_ => Database.Fetch<DocumentCultureVariationDto>(
Sql().Select<DocumentCultureVariationDto>().From<DocumentCultureVariationDto>()
.WhereIn<DocumentCultureVariationDto>(x => x.LanguageId, editedLanguageVersions.Keys.Select(x => x.langId).ToList())
.WhereIn<DocumentCultureVariationDto>(x => x.NodeId, editedLanguageVersions.Keys.Select(x => x.nodeId))))
//convert to dictionary with the same key type
.ToDictionary(x => (x.NodeId, (int?)x.LanguageId), x => x);
// lookup all matching rows in umbracoDocumentCultureVariation
// fetch in batches to account for maximum parameter count (distinct languages can't exceed 2000)
var languageIds = editedLanguageVersions.Keys.Select(x => x.langId).Distinct().ToArray();
var nodeIds = editedLanguageVersions.Keys.Select(x => x.nodeId).Distinct();
var docCultureVariationsToUpdate = nodeIds.InGroupsOf(Constants.Sql.MaxParameterCount - languageIds.Length)
.SelectMany(group =>
{
var sql = Sql().Select<DocumentCultureVariationDto>().From<DocumentCultureVariationDto>()
.WhereIn<DocumentCultureVariationDto>(x => x.LanguageId, languageIds)
.WhereIn<DocumentCultureVariationDto>(x => x.NodeId, group);
return Database.Fetch<DocumentCultureVariationDto>(sql);
})
.ToDictionary(x => (x.NodeId, (int?)x.LanguageId), x => x); //convert to dictionary with the same key type
var toUpdate = new List<DocumentCultureVariationDto>();
foreach (var ev in editedLanguageVersions)

View File

@@ -263,13 +263,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
Func<Guid[], IEnumerable<IEnumerable<IDictionaryItem>>> getItemsFromParents = guids =>
{
//needs to be in groups of 2000 because we are doing an IN clause and there's a max parameter count that can be used.
return guids.InGroupsOf(2000)
.Select(@group =>
return guids.InGroupsOf(Constants.Sql.MaxParameterCount)
.Select(group =>
{
var sqlClause = GetBaseQuery(false)
.Where<DictionaryDto>(x => x.Parent != null)
.Where($"{SqlSyntax.GetQuotedColumnName("parent")} IN (@parentIds)", new { parentIds = @group });
.WhereIn<DictionaryDto>(x => x.Parent, group);
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, Query<IDictionaryItem>());
var sql = translator.Translate();

View File

@@ -1390,7 +1390,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
{
var result = new Dictionary<int, ContentScheduleCollection>();
var scheduleDtos = Database.FetchByGroups<ContentScheduleDto, int>(contentIds, 2000, batch => Sql()
var scheduleDtos = Database.FetchByGroups<ContentScheduleDto, int>(contentIds, Constants.Sql.MaxParameterCount, batch => Sql()
.Select<ContentScheduleDto>()
.From<ContentScheduleDto>()
.WhereIn<ContentScheduleDto>(x => x.NodeId, batch));
@@ -1440,7 +1440,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
if (versions.Count == 0)
return new Dictionary<int, List<ContentVariation>>();
var dtos = Database.FetchByGroups<ContentVersionCultureVariationDto, int>(versions, 2000, batch
var dtos = Database.FetchByGroups<ContentVersionCultureVariationDto, int>(versions, Constants.Sql.MaxParameterCount, batch
=> Sql()
.Select<ContentVersionCultureVariationDto>()
.From<ContentVersionCultureVariationDto>()
@@ -1469,7 +1469,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
{
var ids = temps.Select(x => x.Id);
var dtos = Database.FetchByGroups<DocumentCultureVariationDto, int>(ids, 2000, batch =>
var dtos = Database.FetchByGroups<DocumentCultureVariationDto, int>(ids, Constants.Sql.MaxParameterCount, batch =>
Sql()
.Select<DocumentCultureVariationDto>()
.From<DocumentCultureVariationDto>()

View File

@@ -62,7 +62,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
{
if (ids.Any())
{
return Database.FetchByGroups<NodeDto, int>(ids, 2000, batch =>
return Database.FetchByGroups<NodeDto, int>(ids, Constants.Sql.MaxParameterCount, batch =>
GetBaseQuery(false)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
.WhereIn<NodeDto>(x => x.NodeId, batch))

View File

@@ -279,7 +279,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
if (v == null) return entitiesList;
// fetch all variant info dtos
var dtos = Database.FetchByGroups<VariantInfoDto, int>(v.Select(x => x.Id), 2000, GetVariantInfos);
var dtos = Database.FetchByGroups<VariantInfoDto, int>(v.Select(x => x.Id), Constants.Sql.MaxParameterCount, GetVariantInfos);
// group by node id (each group contains all languages)
var xdtos = dtos.GroupBy(x => x.NodeId).ToDictionary(x => x.Key, x => x);

View File

@@ -209,16 +209,15 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
// can't query more than 2000 ids at a time... but if someone is really querying 2000+ entities,
// the additional overhead of fetching them in groups is minimal compared to the lookup time of each group
const int maxParams = 2000;
if (ids.Length <= maxParams)
if (ids.Length <= Constants.Sql.MaxParameterCount)
{
return CachePolicy.GetAll(ids, PerformGetAll);
}
var entities = new List<TEntity>();
foreach (var groupOfIds in ids.InGroupsOf(maxParams))
foreach (var group in ids.InGroupsOf(Constants.Sql.MaxParameterCount))
{
entities.AddRange(CachePolicy.GetAll(groupOfIds.ToArray(), PerformGetAll));
entities.AddRange(CachePolicy.GetAll(group.ToArray(), PerformGetAll));
}
return entities;

View File

@@ -530,16 +530,13 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
var matchedMembers = Get(query).ToArray();
var membersInGroup = new List<IMember>();
//then we need to filter the matched members that are in the role
//since the max sql params are 2100 on sql server, we'll reduce that to be safe for potentially other servers and run the queries in batches
var inGroups = matchedMembers.InGroupsOf(1000);
foreach (var batch in inGroups)
{
var memberIdBatch = batch.Select(x => x.Id);
//then we need to filter the matched members that are in the role
foreach (var group in matchedMembers.Select(x => x.Id).InGroupsOf(Constants.Sql.MaxParameterCount))
{
var sql = Sql().SelectAll().From<Member2MemberGroupDto>()
.Where<Member2MemberGroupDto>(dto => dto.MemberGroup == memberGroup.Id)
.WhereIn<Member2MemberGroupDto>(dto => dto.Member, memberIdBatch);
.WhereIn<Member2MemberGroupDto>(dto => dto.Member, group);
var memberIdsInGroup = Database.Fetch<Member2MemberGroupDto>(sql)
.Select(x => x.Member).ToArray();

View File

@@ -38,44 +38,41 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
/// <param name="entityIds"></param>
/// <returns></returns>
/// <remarks>
/// This method will not support passing in more than 2000 group Ids
/// This method will not support passing in more than 2000 group IDs when also passing in entity IDs.
/// </remarks>
public EntityPermissionCollection GetPermissionsForEntities(int[] groupIds, params int[] entityIds)
{
var result = new EntityPermissionCollection();
foreach (var groupOfGroupIds in groupIds.InGroupsOf(2000))
if (entityIds.Length == 0)
{
//copy local
var localIds = groupOfGroupIds.ToArray();
if (entityIds.Length == 0)
foreach (var group in groupIds.InGroupsOf(Constants.Sql.MaxParameterCount))
{
var sql = Sql()
.SelectAll()
.From<UserGroup2NodePermissionDto>()
.Where<UserGroup2NodePermissionDto>(dto => localIds.Contains(dto.UserGroupId));
.Where<UserGroup2NodePermissionDto>(dto => group.Contains(dto.UserGroupId));
var permissions = AmbientScope.Database.Fetch<UserGroup2NodePermissionDto>(sql);
foreach (var permission in ConvertToPermissionList(permissions))
{
result.Add(permission);
}
}
else
}
else
{
foreach (var group in entityIds.InGroupsOf(Constants.Sql.MaxParameterCount - groupIds.Length))
{
//iterate in groups of 2000 since we don't want to exceed the max SQL param count
foreach (var groupOfEntityIds in entityIds.InGroupsOf(2000))
var sql = Sql()
.SelectAll()
.From<UserGroup2NodePermissionDto>()
.Where<UserGroup2NodePermissionDto>(dto => groupIds.Contains(dto.UserGroupId) && group.Contains(dto.NodeId));
var permissions = AmbientScope.Database.Fetch<UserGroup2NodePermissionDto>(sql);
foreach (var permission in ConvertToPermissionList(permissions))
{
var ids = groupOfEntityIds;
var sql = Sql()
.SelectAll()
.From<UserGroup2NodePermissionDto>()
.Where<UserGroup2NodePermissionDto>(dto => localIds.Contains(dto.UserGroupId) && ids.Contains(dto.NodeId));
var permissions = AmbientScope.Database.Fetch<UserGroup2NodePermissionDto>(sql);
foreach (var permission in ConvertToPermissionList(permissions))
{
result.Add(permission);
}
result.Add(permission);
}
}
}
@@ -133,11 +130,10 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
var db = AmbientScope.Database;
//we need to batch these in groups of 2000 so we don't exceed the max 2100 limit
var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND nodeId in (@nodeIds)";
foreach (var idGroup in entityIds.InGroupsOf(2000))
foreach (var group in entityIds.InGroupsOf(Constants.Sql.MaxParameterCount))
{
db.Execute(sql, new { groupId, nodeIds = idGroup });
db.Execute(sql, new { groupId, nodeIds = group });
}
var toInsert = new List<UserGroup2NodePermissionDto>();

View File

@@ -39,8 +39,9 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
protected override IEnumerable<IRedirectUrl> PerformGetAll(params Guid[] ids)
{
if (ids.Length > 2000)
throw new NotSupportedException("This repository does not support more than 2000 ids.");
if (ids.Length > Constants.Sql.MaxParameterCount)
throw new NotSupportedException($"This repository does not support more than {Constants.Sql.MaxParameterCount} ids.");
var sql = GetBaseQuery(false).WhereIn<RedirectUrlDto>(x => x.Id, ids);
var dtos = Database.Fetch<RedirectUrlDto>(sql);
return dtos.WhereNotNull().Select(Map);

View File

@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
{
var dtos = ids.Length == 0
? Database.Fetch<TagDto>(Sql().Select<TagDto>().From<TagDto>())
: Database.FetchByGroups<TagDto, int>(ids, 2000, batch => Sql().Select<TagDto>().From<TagDto>().WhereIn<TagDto>(x => x.Id, batch));
: Database.FetchByGroups<TagDto, int>(ids, Constants.Sql.MaxParameterCount, batch => Sql().Select<TagDto>().From<TagDto>().WhereIn<TagDto>(x => x.Id, batch));
return dtos.Select(TagFactory.BuildEntity).ToList();
}