Denormalize variants for perfs
This commit is contained in:
@@ -118,6 +118,7 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
Chain<RenameTrueFalseField>("{517CE9EA-36D7-472A-BF4B-A0D6FB1B8F89}"); // from 7.12.0
|
||||
Chain<SetDefaultTagsStorageType>("{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}"); // from 7.12.0
|
||||
Chain<UpdateDefaultMandatoryLanguage>("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}");
|
||||
Chain<RefactorVariantsModel>("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}");
|
||||
//FINAL
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class RefactorVariantsModel : MigrationBase
|
||||
{
|
||||
public RefactorVariantsModel(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
Delete.Column("edited").FromTable(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation).Do();
|
||||
|
||||
|
||||
// add available column
|
||||
AddColumn<DocumentCultureVariationDto>("available", out var sqls);
|
||||
|
||||
// so far, only those cultures that were available had records in the table
|
||||
Update.Table(DocumentCultureVariationDto.TableName).Set(new { available = true }).AllRows().Do();
|
||||
|
||||
foreach (var sql in sqls) Execute.Sql(sql).Do();
|
||||
|
||||
|
||||
// add published column
|
||||
AddColumn<DocumentCultureVariationDto>("published", out sqls);
|
||||
|
||||
// make it false by default
|
||||
Update.Table(DocumentCultureVariationDto.TableName).Set(new { published = false }).AllRows().Do();
|
||||
|
||||
// now figure out whether these available cultures are published, too
|
||||
var getPublished = Sql()
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.AndSelect<ContentVersionCultureVariationDto>(x => x.LanguageId)
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((node, cv) => node.NodeId == cv.NodeId)
|
||||
.InnerJoin<DocumentVersionDto>().On<ContentVersionDto, DocumentVersionDto>((cv, dv) => cv.Id == dv.Id && dv.Published)
|
||||
.InnerJoin<ContentVersionCultureVariationDto>().On<ContentVersionDto, ContentVersionCultureVariationDto>((cv, ccv) => cv.Id == ccv.VersionId);
|
||||
|
||||
foreach (var dto in Database.Fetch<TempDto>(getPublished))
|
||||
Database.Execute(Sql()
|
||||
.Update<DocumentCultureVariationDto>(u => u.Set(x => x.Published, true))
|
||||
.Where<DocumentCultureVariationDto>(x => x.NodeId == dto.NodeId && x.LanguageId == dto.LanguageId));
|
||||
|
||||
foreach (var sql in sqls) Execute.Sql(sql).Do();
|
||||
|
||||
// so far, it was kinda impossible to make a culture unavailable again,
|
||||
// so we *should* not have anything published but not available - ignore
|
||||
|
||||
|
||||
// add name column
|
||||
AddColumn<DocumentCultureVariationDto>("name");
|
||||
|
||||
// so far, every record in the table mapped to an available culture
|
||||
var getNames = Sql()
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.AndSelect<ContentVersionCultureVariationDto>(x => x.LanguageId, x => x.Name)
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((node, cv) => node.NodeId == cv.NodeId && cv.Current)
|
||||
.InnerJoin<ContentVersionCultureVariationDto>().On<ContentVersionDto, ContentVersionCultureVariationDto>((cv, ccv) => cv.Id == ccv.VersionId);
|
||||
|
||||
foreach (var dto in Database.Fetch<TempDto>(getNames))
|
||||
Database.Execute(Sql()
|
||||
.Update<DocumentCultureVariationDto>(u => u.Set(x => x.Name, dto.Name))
|
||||
.Where<DocumentCultureVariationDto>(x => x.NodeId == dto.NodeId && x.LanguageId == dto.LanguageId));
|
||||
}
|
||||
|
||||
// ReSharper disable once ClassNeverInstantiated.Local
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||
private class TempDto
|
||||
{
|
||||
public int NodeId { get; set; }
|
||||
public int LanguageId { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
// ReSharper restore UnusedAutoPropertyAccessor.Local
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,7 @@ namespace Umbraco.Core.Models
|
||||
if (_publishInfos == null)
|
||||
_publishInfos = new Dictionary<string, (string Name, DateTime Date)>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
_publishInfos[culture] = (name, date);
|
||||
_publishInfos[culture.ToLowerInvariant()] = (name, date);
|
||||
}
|
||||
|
||||
private void ClearPublishInfos()
|
||||
@@ -294,7 +294,7 @@ namespace Umbraco.Core.Models
|
||||
throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (_editedCultures == null)
|
||||
_editedCultures = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
_editedCultures.Add(culture);
|
||||
_editedCultures.Add(culture.ToLowerInvariant());
|
||||
}
|
||||
|
||||
// sets all publish edited
|
||||
|
||||
@@ -41,9 +41,5 @@ namespace Umbraco.Core.Persistence.Dtos
|
||||
[ForeignKey(typeof(UserDto))]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public int? PublishedUserId { get => _publishedUserId == 0 ? null : _publishedUserId; set => _publishedUserId = value; } //return null if zero
|
||||
|
||||
// fixme: I've commented this out, it's never used, need to review
|
||||
//[Column("edited")]
|
||||
//public bool Edited { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,25 @@ namespace Umbraco.Core.Persistence.Dtos
|
||||
[Ignore]
|
||||
public string Culture { get; set; }
|
||||
|
||||
// authority on whether a culture has been edited
|
||||
[Column("edited")]
|
||||
public bool Edited { get; set; }
|
||||
|
||||
// de-normalized for perfs
|
||||
// (means there is a current content version culture variation for the language)
|
||||
[Column("available")]
|
||||
public bool Available { get; set; }
|
||||
|
||||
// de-normalized for perfs
|
||||
// (means there is a published content version culture variation for the language)
|
||||
[Column("published")]
|
||||
public bool Published { get; set; }
|
||||
|
||||
// de-normalized for perfs
|
||||
// (when available, copies name from current content version culture variation for the language)
|
||||
// (otherwise, it's the published one, 'cos we need to have one)
|
||||
[Column("name")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,12 @@ using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
using static Umbraco.Core.Persistence.NPocoSqlExtensions.Statics;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
{
|
||||
@@ -1099,16 +1097,22 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
private IEnumerable<DocumentCultureVariationDto> GetDocumentVariationDtos(IContent content, bool publishing, HashSet<string> editedCultures)
|
||||
{
|
||||
foreach (var (culture, name) in content.CultureNames)
|
||||
var allCultures = content.AvailableCultures.Union(content.PublishedCultures); // union = distinct
|
||||
foreach (var culture in allCultures)
|
||||
yield return new DocumentCultureVariationDto
|
||||
{
|
||||
NodeId = content.Id,
|
||||
LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."),
|
||||
Culture = culture,
|
||||
|
||||
// if not published, always edited
|
||||
// no need to check for availability: it *is* available since it is in content.CultureNames
|
||||
Edited = !content.IsCulturePublished(culture) || (editedCultures != null && editedCultures.Contains(culture))
|
||||
Name = content.GetCultureName(culture) ?? content.GetPublishName(culture),
|
||||
|
||||
// note: can't use IsCultureEdited at that point - hasn't been updated yet - see PersistUpdatedItem
|
||||
|
||||
Available = content.IsCultureAvailable(culture),
|
||||
Published = content.IsCulturePublished(culture),
|
||||
Edited = content.IsCultureAvailable(culture) &&
|
||||
(!content.IsCulturePublished(culture) || (editedCultures != null && editedCultures.Contains(culture)))
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -313,17 +313,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
protected Sql<ISqlContext> GetVariantInfos(IEnumerable<int> ids)
|
||||
{
|
||||
// this ... is an interesting query - could we make it simpler? probably, by having DocumentCultureVariationDto
|
||||
// handle 'available' and 'published' in addition to 'edited' - would take (a bit) more time to save a document,
|
||||
// but would make querying way faster
|
||||
|
||||
return Sql()
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.AndSelect<LanguageDto>(x => x.IsoCode)
|
||||
.AndSelect<DocumentDto>("doc", x => Alias(x.Published, "DocumentPublished"), x => Alias(x.Edited, "DocumentEdited"))
|
||||
.AndSelect<ContentVersionCultureVariationDto>("ccv", x => Alias(x.Id, "CultureAvailableData"), x => Alias(x.Name, "Name"))
|
||||
.AndSelect<ContentVersionCultureVariationDto>("pcv", x => Alias(x.Id, "CulturePublishedData"))
|
||||
.AndSelect<DocumentCultureVariationDto>("dcv", x => Alias(x.Edited, "CultureEditedData"))
|
||||
.AndSelect<DocumentCultureVariationDto>("dcv",
|
||||
x => Alias(x.Available, "CultureAvailable"), x => Alias(x.Published, "CulturePublished"), x => Alias(x.Edited, "CultureEdited"),
|
||||
x => Alias(x.Name, "Name"))
|
||||
|
||||
// from node x language
|
||||
.From<NodeDto>()
|
||||
@@ -337,22 +333,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
.LeftJoin<DocumentCultureVariationDto>("dcv")
|
||||
.On<NodeDto, DocumentCultureVariationDto, LanguageDto>((node, dcv, lang) => node.NodeId == dcv.NodeId && lang.Id == dcv.LanguageId, aliasRight: "dcv")
|
||||
|
||||
// join to current version - always exists
|
||||
// left-join to current version variations - indicates which cultures are *available*
|
||||
.InnerJoin<ContentVersionDto>("cv")
|
||||
.On<NodeDto, ContentVersionDto>((node, ev) => node.NodeId == ev.NodeId && ev.Current, aliasRight: "cv")
|
||||
.LeftJoin<ContentVersionCultureVariationDto>("ccv")
|
||||
.On<ContentVersionDto, ContentVersionCultureVariationDto, LanguageDto>((cv, ccv, lang) => cv.Id == ccv.VersionId && lang.Id == ccv.LanguageId, "cv", "ccv")
|
||||
|
||||
// left-join to published version - exists when whole node is published
|
||||
// left-join to published version variations - matches cultures that are *published*
|
||||
.LeftJoin<ContentVersionDto>(nested => nested.InnerJoin<DocumentVersionDto>("dv")
|
||||
.On<ContentVersionDto, DocumentVersionDto>((pv, dv) => pv.Id == dv.Id && dv.Published, "pv", "dv"),
|
||||
"pv")
|
||||
.On<NodeDto, ContentVersionDto>((node, pv) => node.NodeId == pv.NodeId, aliasRight: "pv")
|
||||
.LeftJoin<ContentVersionCultureVariationDto>("pcv")
|
||||
.On<ContentVersionDto, ContentVersionCultureVariationDto, LanguageDto>((pv, pcv, lang) => pv.Id == pcv.VersionId && lang.Id == pcv.LanguageId, "pv", "pcv")
|
||||
|
||||
// for selected nodes
|
||||
.WhereIn<NodeDto>(x => x.NodeId, ids);
|
||||
}
|
||||
@@ -566,16 +546,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
public bool DocumentPublished { get; set; }
|
||||
public bool DocumentEdited { get; set; }
|
||||
|
||||
public int? CultureAvailableData { get; set; }
|
||||
public int? CulturePublishedData { get; set; }
|
||||
public bool? CultureEditedData { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public bool CultureAvailable => CultureAvailableData.HasValue;
|
||||
[ResultColumn]
|
||||
public bool CulturePublished => CulturePublishedData.HasValue;
|
||||
[ResultColumn]
|
||||
public bool CultureEdited => CultureEditedData ?? false;
|
||||
public bool CultureAvailable { get; set; }
|
||||
public bool CulturePublished { get; set; }
|
||||
public bool CultureEdited { get; set; }
|
||||
}
|
||||
|
||||
// ReSharper disable once ClassNeverInstantiated.Local
|
||||
|
||||
@@ -359,6 +359,7 @@
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\LanguageColumns.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\PropertyEditorsMigration.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\RefactorMacroColumns.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\RefactorVariantsModel.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\SuperZero.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\TagsMigration.cs" />
|
||||
<Compile Include="Migrations\Upgrade\V_8_0_0\UpdateDefaultMandatoryLanguage.cs" />
|
||||
|
||||
Reference in New Issue
Block a user