Skip to content

Support Guid ToString in all databases, add test for all DBs #4297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
40 changes: 40 additions & 0 deletions Source/LinqToDB/Sql/Sql.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace LinqToDB
using Linq;
using SqlQuery;
using LinqToDB.Common;
using System.Diagnostics.CodeAnalysis;

[PublicAPI]
public static partial class Sql
Expand Down Expand Up @@ -253,6 +254,45 @@ public static Guid NewGuid()
return Guid.NewGuid();
}

sealed class GuidToStringBuilder : IExtensionCallBuilder
{
public void Build(ISqExtensionBuilder builder)
{
var para = builder.GetExpression(0);
var toType = builder.Mapping.GetDbDataType(typeof(string));

builder.ResultExpression = PseudoFunctions.MakeToLower(PseudoFunctions.MakeMandatoryCast(para!, toType, SqlDataType.Guid));
}
}

/// <summary>
/// Converts a Guid to a normalized string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
/// means no brakets, lowercase, dashes
/// </summary>
/// <param name="guid">the guid to convert</param>
/// <returns>a formated string</returns>
[CLSCompliant(false)]
[Expression(PN.SQLite, "lower((substr(hex({0}), 7, 2) || substr(hex({0}), 5, 2) || substr(hex({0}), 3, 2) || substr(hex({0}), 1, 2) || '-' || substr(hex({0}), 11, 2) || substr(hex({0}), 9, 2) || '-' || substr(hex({0}), 15, 2) || substr(hex({0}), 13, 2) || '-' || substr(hex({0}), 17, 4) || '-' || substr(hex({0}), 21, 12)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.Access, "LCase(Mid(CStr({0}), 2, 36))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.PostgreSQL, "(Cast({0} as VarChar(36)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.MariaDB10, "Lower(Cast({0} as CHAR(36)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.MySql, "Lower(Cast({0} as CHAR(36)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.Informix, "Lower(To_Char({0}))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.DB2, "lower((substr(hex({0}), 7, 2) || substr(hex({0}), 5, 2) || substr(hex({0}), 3, 2) || substr(hex({0}), 1, 2) || '-' || substr(hex({0}), 11, 2) || substr(hex({0}), 9, 2) || '-' || substr(hex({0}), 15, 2) || substr(hex({0}), 13, 2) || '-' || substr(hex({0}), 17, 4) || '-' || substr(hex({0}), 21, 12)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.Oracle, "lower((substr(rawtohex({0}), 7, 2) || substr(rawtohex({0}), 5, 2) || substr(rawtohex({0}), 3, 2) || substr(rawtohex({0}), 1, 2) || '-' || substr(rawtohex({0}), 11, 2) || substr(rawtohex({0}), 9, 2) || '-' || substr(rawtohex({0}), 15, 2) || substr(rawtohex({0}), 13, 2) || '-' || substr(rawtohex({0}), 17, 4) || '-' || substr(rawtohex({0}), 21, 12)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.ClickHouse, "lower(toString({0}))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.SapHana, "Lower(Cast({0} as NVarChar(36)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.Sybase, "Lower(Convert(NVarChar(36), {0}))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Expression(PN.SqlServer, "LOWER(CAST({0} AS char(36)))", IsNullable = IsNullableType.IfAnyParameterNullable, PreferServerSide = true)]
[Extension("", BuilderType = typeof(GuidToStringBuilder), PreferServerSide = true)]
#if NET30_OR_GREATER || NETSTANDARD2_1_OR_GREATER
[return: NotNullIfNotNull(nameof(guid))]
#endif
public static string? GuidToNormalizedString(Guid? guid)
{
return guid == null ? null : guid.ToString();
}

#endregion

#region Convert Functions
Expand Down
70 changes: 70 additions & 0 deletions Tests/Linq/UserTests/Issue4295Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System.Linq;
using FluentAssertions;
using LinqToDB;
using LinqToDB.Mapping;
using NUnit.Framework;
using System.Linq.Dynamic.Core;
using System.Linq.Dynamic.Core.CustomTypeProviders;
using System.Collections.Generic;
using System;
using LinqToDB.Data;

namespace Tests.UserTests
{
[TestFixture]
public class Issue4295Tests : TestBase
{
[Table]
public class InfeedAdvicePositionDTO
{
[Column] public Guid Id { get; set; }
}

[Test]
public void TestGuidToString([DataSources] string context)
{
using (var db = GetDataContext(context))
using (db.CreateLocalTable<InfeedAdvicePositionDTO>())
{
var expected = "193AE7F4-5309-4EEE-A746-27B28C7E30F3".ToLowerInvariant();

var a = new InfeedAdvicePositionDTO() { Id = Guid.Parse(expected) };
db.Insert(a);

var id = (from infeed in db.GetTable<InfeedAdvicePositionDTO>()
select Sql.GuidToNormalizedString(infeed.Id)).First();

Assert.That(id, Is.EqualTo(expected));

var qryA = from infeed in db.GetTable<InfeedAdvicePositionDTO>()
where Sql.GuidToNormalizedString(infeed.Id)!.Contains("7f4-53")
select infeed;

var lA = qryA.ToList();
Assert.That(lA, Has.Count.EqualTo(1));

var qryB = from infeed in db.GetTable<InfeedAdvicePositionDTO>()
where Sql.GuidToNormalizedString(infeed.Id)!.StartsWith("193ae")
select infeed;

var lB = qryB.ToList();
Assert.That(lB, Has.Count.EqualTo(1));


var qryC = from infeed in db.GetTable<InfeedAdvicePositionDTO>()
where Sql.GuidToNormalizedString(infeed.Id)!.Contains("8f4-53")
select infeed;

var lC = qryC.ToList();
Assert.That(lC, Has.Count.EqualTo(0));

var qryD = from infeed in db.GetTable<InfeedAdvicePositionDTO>()
where Sql.GuidToNormalizedString(infeed.Id)!.ToLower().StartsWith("293ae")
select infeed;

var lD = qryD.ToList();
Assert.That(lD, Has.Count.EqualTo(0));
}
}
}
}
Loading