Case-insensitive tag names with SQLite provider (#14012)

* Ensure case insensitivity in tag name queries.

Use LIKE instead of = to ignore collation rules.

* Add integration test for creating tag relations with mixed casing.

(cherry picked from commit 37d737f9bc)
This commit is contained in:
Lewis Hazell
2023-03-31 19:36:25 +01:00
committed by Sebastiaan Janssen
parent d1975ee2cf
commit bb7752c483
2 changed files with 42 additions and 2 deletions

View File

@@ -131,7 +131,7 @@ internal class TagRepository : EntityRepositoryBase<int, ITag>, ITagRepository
var sql1 = $@"INSERT INTO cmsTags (tag, {group}, languageId)
SELECT tagSet.tag, tagSet.{group}, tagSet.languageId
FROM {tagSetSql}
LEFT OUTER JOIN cmsTags ON (tagSet.tag = cmsTags.tag AND tagSet.{group} = cmsTags.{group} AND COALESCE(tagSet.languageId, -1) = COALESCE(cmsTags.languageId, -1))
LEFT OUTER JOIN cmsTags ON (tagSet.tag LIKE cmsTags.tag AND tagSet.{group} = cmsTags.{group} AND COALESCE(tagSet.languageId, -1) = COALESCE(cmsTags.languageId, -1))
WHERE cmsTags.id IS NULL";
Database.Execute(sql1);
@@ -321,7 +321,7 @@ WHERE r.tagId IS NULL";
Sql<ISqlContext> sql = GetTaggedEntitiesSql(objectType, culture);
sql = sql
.Where<TagDto>(dto => dto.Text == tag);
.WhereLike<TagDto>(dto => dto.Text, tag);
if (group.IsNullOrWhiteSpace() == false)
{

View File

@@ -13,6 +13,7 @@ using Umbraco.Cms.Infrastructure.Scoping;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Testing;
using Umbraco.Cms.Tests.Integration.Testing;
using static Umbraco.Cms.Core.Constants.Conventions;
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositories;
@@ -98,6 +99,45 @@ public class TagRepositoryTest : UmbracoIntegrationTest
}
}
[Test]
public void Can_Create_Tag_Relations_With_Mixed_Casing()
{
var provider = ScopeProvider;
using (ScopeProvider.CreateScope())
{
var template = TemplateBuilder.CreateTextPageTemplate();
FileService.SaveTemplate(template);
var contentType =
ContentTypeBuilder.CreateSimpleContentType("test", "Test", defaultTemplateId: template.Id);
ContentTypeRepository.Save(contentType);
var content1 = ContentBuilder.CreateSimpleContent(contentType);
var content2 = ContentBuilder.CreateSimpleContent(contentType);
DocumentRepository.Save(content1);
DocumentRepository.Save(content2);
var repository = CreateRepository(provider);
Tag[] tags1 = { new Tag { Text = "tag1", Group = "test" } };
repository.Assign(
content1.Id,
contentType.PropertyTypes.First().Id,
tags1,
false);
// Note the casing is different from tags1, but both should be considered equivalent
Tag[] tags2 = { new Tag { Text = "TAG1", Group = "test" } };
repository.Assign(
content2.Id,
contentType.PropertyTypes.First().Id,
tags2,
false);
// The template should have only one tag, despite case differences
Assert.AreEqual(1, repository.GetTaggedEntitiesByTag(TaggableObjectTypes.Content, "tag1").Count());
}
}
[Test]
public void Can_Append_Tag_Relations()
{