Merge branch 'temp8-3675-variant-tags' of https://github.com/umbraco/Umbraco-CMS into temp8-3675-variant-tags
This commit is contained in:
@@ -797,7 +797,7 @@ namespace Umbraco.Core
|
||||
/// <param name="fallbackValue">The value to use when any value is null.</param>
|
||||
/// <remarks>Do not use outside of Sql expressions.</remarks>
|
||||
// see usage in ExpressionVisitorBase
|
||||
public static bool NEquals<T>(this T? value, T? other, T fallbackValue)
|
||||
public static bool SqlNullableEquals<T>(this T? value, T? other, T fallbackValue)
|
||||
where T : struct
|
||||
{
|
||||
return (value ?? fallbackValue).Equals(other ?? fallbackValue);
|
||||
|
||||
@@ -656,13 +656,13 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
// c# 'x == null' becomes sql 'x IS NULL' which is fine
|
||||
// c# 'x == y' becomes sql 'x = @0' which is fine - unless they are nullable types,
|
||||
// because sql 'x = NULL' is always false and the 'IS NULL' syntax is required,
|
||||
// so for comparing nullable types, we use x.NEquals(y, fb) where fb is a fallback
|
||||
// so for comparing nullable types, we use x.SqlNullableEquals(y, fb) where fb is a fallback
|
||||
// value which will be used when values are null - turning the comparison into
|
||||
// sql 'COALESCE(x,fb) = COALESCE(y,fb)' - of course, fb must be a value outside
|
||||
// of x and y range - and if that is not possible, then a manual comparison need
|
||||
// to be written
|
||||
//TODO support NEquals with 0 parameters, using the full syntax below
|
||||
case "NEquals":
|
||||
//TODO support SqlNullableEquals with 0 parameters, using the full syntax below
|
||||
case "SqlNullableEquals":
|
||||
var compareTo = Visit(m.Arguments[1]);
|
||||
var fallback = Visit(m.Arguments[2]);
|
||||
// that would work without a fallback value but is more cumbersome
|
||||
|
||||
@@ -762,7 +762,7 @@ AND umbracoNode.id <> @id",
|
||||
///
|
||||
private void CopyTagData(int? sourceLanguageId, int? targetLanguageId, IReadOnlyCollection<int> propertyTypeIds, IReadOnlyCollection<int> contentTypeIds = null)
|
||||
{
|
||||
// note: important to use NEquals for nullable types, cannot directly compare language identifiers
|
||||
// note: important to use SqlNullableEquals for nullable types, cannot directly compare language identifiers
|
||||
|
||||
// fixme - should we batch then?
|
||||
var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0);
|
||||
@@ -784,7 +784,7 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
sqlTagToDelete
|
||||
.WhereIn<TagRelationshipDto>(x => x.PropertyTypeId, propertyTypeIds)
|
||||
.Where<TagDto>(x => x.LanguageId.NEquals(targetLanguageId, -1));
|
||||
.Where<TagDto>(x => x.LanguageId.SqlNullableEquals(targetLanguageId, -1));
|
||||
|
||||
var sqlDeleteRel = Sql()
|
||||
.Delete<TagRelationshipDto>()
|
||||
@@ -811,7 +811,7 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
sqlSelect
|
||||
.InnerJoin<TagRelationshipDto>().On<TagDto, TagRelationshipDto>((tag, rel) => tag.Id == rel.TagId)
|
||||
.LeftJoin<TagDto>("xtags").On<TagDto, TagDto>((tag, xtag) => tag.Text == xtag.Text && tag.Group == xtag.Group && tag.LanguageId.NEquals(targetLanguageId, -1), aliasRight: "xtags");
|
||||
.LeftJoin<TagDto>("xtags").On<TagDto, TagDto>((tag, xtag) => tag.Text == xtag.Text && tag.Group == xtag.Group && tag.LanguageId.SqlNullableEquals(targetLanguageId, -1), aliasRight: "xtags");
|
||||
|
||||
if (contentTypeIds != null)
|
||||
sqlSelect
|
||||
@@ -825,7 +825,7 @@ AND umbracoNode.id <> @id",
|
||||
sqlSelect
|
||||
.WhereIn<ContentDto>(x => x.ContentTypeId, contentTypeIds);
|
||||
|
||||
sqlSelect.Where<TagDto>(x => x.LanguageId.NEquals(sourceLanguageId, -1));
|
||||
sqlSelect.Where<TagDto>(x => x.LanguageId.SqlNullableEquals(sourceLanguageId, -1));
|
||||
|
||||
var cols = Sql().Columns<TagDto>(x => x.Text, x => x.Group, x => x.LanguageId);
|
||||
var sqlInsertTag = Sql($"INSERT INTO {TagDto.TableName} ({cols})").Append(sqlSelect);
|
||||
@@ -840,8 +840,8 @@ AND umbracoNode.id <> @id",
|
||||
.AndSelect<TagDto>("otag", x => x.Id)
|
||||
.From<TagRelationshipDto>()
|
||||
.InnerJoin<TagDto>().On<TagRelationshipDto, TagDto>((rel, tag) => rel.TagId == tag.Id)
|
||||
.InnerJoin<TagDto>("otag").On<TagDto, TagDto>((tag, otag) => tag.Text == otag.Text && tag.Group == otag.Group && otag.LanguageId.NEquals(targetLanguageId, -1), aliasRight: "otag")
|
||||
.Where<TagDto>(x => x.LanguageId.NEquals(sourceLanguageId, -1));
|
||||
.InnerJoin<TagDto>("otag").On<TagDto, TagDto>((tag, otag) => tag.Text == otag.Text && tag.Group == otag.Group && otag.LanguageId.SqlNullableEquals(targetLanguageId, -1), aliasRight: "otag")
|
||||
.Where<TagDto>(x => x.LanguageId.SqlNullableEquals(sourceLanguageId, -1));
|
||||
|
||||
var cols2 = Sql().Columns<TagRelationshipDto>(x => x.NodeId, x => x.PropertyTypeId, x => x.TagId);
|
||||
var sqlInsertRel = Sql($"INSERT INTO {TagRelationshipDto.TableName} ({cols2})").Append(sqlFoo);
|
||||
@@ -864,7 +864,7 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
sqlTagToDelete
|
||||
.WhereIn<TagRelationshipDto>(x => x.PropertyTypeId, propertyTypeIds)
|
||||
.Where<TagDto>(x => !x.LanguageId.NEquals(targetLanguageId, -1));
|
||||
.Where<TagDto>(x => !x.LanguageId.SqlNullableEquals(targetLanguageId, -1));
|
||||
|
||||
sqlDeleteRel = Sql()
|
||||
.Delete<TagRelationshipDto>()
|
||||
@@ -891,7 +891,7 @@ AND umbracoNode.id <> @id",
|
||||
/// <param name="contentTypeIds">The content type identifiers.</param>
|
||||
private void CopyPropertyData(int? sourceLanguageId, int? targetLanguageId, IReadOnlyCollection<int> propertyTypeIds, IReadOnlyCollection<int> contentTypeIds = null)
|
||||
{
|
||||
// note: important to use NEquals for nullable types, cannot directly compare language identifiers
|
||||
// note: important to use SqlNullableEquals for nullable types, cannot directly compare language identifiers
|
||||
//
|
||||
// fixme - should we batch then?
|
||||
var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0);
|
||||
@@ -920,7 +920,7 @@ AND umbracoNode.id <> @id",
|
||||
sqlDelete.WhereIn<PropertyDataDto>(x => x.VersionId, inSql);
|
||||
}
|
||||
|
||||
sqlDelete.Where<PropertyDataDto>(x => x.LanguageId.NEquals(targetLanguageId, -1));
|
||||
sqlDelete.Where<PropertyDataDto>(x => x.LanguageId.SqlNullableEquals(targetLanguageId, -1));
|
||||
|
||||
sqlDelete
|
||||
.WhereIn<PropertyDataDto>(x => x.PropertyTypeId, propertyTypeIds);
|
||||
@@ -944,7 +944,7 @@ AND umbracoNode.id <> @id",
|
||||
.InnerJoin<ContentVersionDto>().On<PropertyDataDto, ContentVersionDto>((pdata, cversion) => pdata.VersionId == cversion.Id)
|
||||
.InnerJoin<ContentDto>().On<ContentVersionDto, ContentDto>((cversion, c) => cversion.NodeId == c.NodeId);
|
||||
|
||||
sqlSelectData.Where<PropertyDataDto>(x => x.LanguageId.NEquals(sourceLanguageId, -1));
|
||||
sqlSelectData.Where<PropertyDataDto>(x => x.LanguageId.SqlNullableEquals(sourceLanguageId, -1));
|
||||
|
||||
sqlSelectData
|
||||
.WhereIn<PropertyDataDto>(x => x.PropertyTypeId, propertyTypeIds);
|
||||
|
||||
@@ -52,14 +52,14 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
.Where<PropertyDataDto>(x => (nid == null && x.LanguageId == null) || (nid != null && x.LanguageId == nid));
|
||||
Assert.AreEqual("SELECT *\nFROM [umbracoPropertyData]\nWHERE ((((@0 is null) AND ([umbracoPropertyData].[languageId] is null)) OR ((@1 is not null) AND ([umbracoPropertyData].[languageId] = @2))))", sql.SQL, sql.SQL);
|
||||
|
||||
// new NEquals method does it automatically
|
||||
// new SqlNullableEquals method does it automatically
|
||||
// 'course it would be nicer if '==' could do it
|
||||
// see note in ExpressionVisitorBase for NEquals
|
||||
// see note in ExpressionVisitorBase for SqlNullableEquals
|
||||
|
||||
//sql = new Sql<ISqlContext>(SqlContext)
|
||||
// .Select("*")
|
||||
// .From<PropertyDataDto>()
|
||||
// .Where<PropertyDataDto>(x => x.LanguageId.NEquals(nid));
|
||||
// .Where<PropertyDataDto>(x => x.LanguageId.SqlNullableEquals(nid));
|
||||
//Assert.AreEqual("SELECT *\nFROM [umbracoPropertyData]\nWHERE ((((@0 is null) AND ([umbracoPropertyData].[languageId] is null)) OR ((@0 is not null) AND ([umbracoPropertyData].[languageId] = @0))))", sql.SQL, sql.SQL);
|
||||
|
||||
// but, the expression above fails with SQL CE, 'specified argument for the function is not valid' in 'isnull' function
|
||||
@@ -68,22 +68,22 @@ namespace Umbraco.Tests.Persistence.NPocoTests
|
||||
sql = new Sql<ISqlContext>(SqlContext)
|
||||
.Select("*")
|
||||
.From<PropertyDataDto>()
|
||||
.Where<PropertyDataDto>(x => x.LanguageId.NEquals(nid, -1));
|
||||
.Where<PropertyDataDto>(x => x.LanguageId.SqlNullableEquals(nid, -1));
|
||||
Assert.AreEqual("SELECT *\nFROM [umbracoPropertyData]\nWHERE ((COALESCE([umbracoPropertyData].[languageId],@0) = COALESCE(@1,@0)))", sql.SQL, sql.SQL);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NEqualsTest()
|
||||
public void SqlNullableEqualsTest()
|
||||
{
|
||||
int? a, b;
|
||||
a = b = null;
|
||||
Assert.IsTrue(a.NEquals(b, -1));
|
||||
Assert.IsTrue(a.SqlNullableEquals(b, -1));
|
||||
b = 2;
|
||||
Assert.IsFalse(a.NEquals(b, -1));
|
||||
Assert.IsFalse(a.SqlNullableEquals(b, -1));
|
||||
a = 2;
|
||||
Assert.IsTrue(a.NEquals(b, -1));
|
||||
Assert.IsTrue(a.SqlNullableEquals(b, -1));
|
||||
b = null;
|
||||
Assert.IsFalse(a.NEquals(b, -1));
|
||||
Assert.IsFalse(a.SqlNullableEquals(b, -1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user