Skip to content

Commit f084602

Browse files
committed
SQLiteDialect: Detect BinaryGuid setting and apply correct GUID-to-string expression.
Fixes GH-2110.
1 parent 404368b commit f084602

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

src/NHibernate/Cfg/Environment.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,18 @@ public static string Version
280280
/// </summary>
281281
public const string FirebirdDisableParameterCasting = "firebird.disable_parameter_casting";
282282

283+
/// <summary>
284+
/// <para>
285+
/// SQLite can store GUIDs in binary or text form, controlled by the BinaryGuid
286+
/// connection string parameter (default is 'true'). The BinaryGuid setting will affect
287+
/// how to cast GUID to string in SQL. NHibernate will attempt to detect this
288+
/// setting automatically from the connection string, but if the connection
289+
/// or connection string is being handled by the application instead of by NHibernate,
290+
/// you can use the 'sqlite.binaryguid' NHibernate setting to override the behavior.
291+
/// </para>
292+
/// </summary>
293+
public const string SqliteBinaryGuid = "sqlite.binaryguid";
294+
283295
/// <summary>
284296
/// <para>Set whether tracking the session id or not. When <see langword="true"/>, each session
285297
/// will have an unique <see cref="Guid"/> that can be retrieved by <see cref="ISessionImplementor.SessionId"/>,

src/NHibernate/Dialect/SQLiteDialect.cs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Data;
34
using System.Data.Common;
45
using System.Text;
@@ -18,6 +19,13 @@ namespace NHibernate.Dialect
1819
/// </remarks>
1920
public class SQLiteDialect : Dialect
2021
{
22+
/// <summary>
23+
/// The effective value of the BinaryGuid connection string parameter.
24+
/// The default value in SQLite is true.
25+
/// </summary>
26+
private bool _binaryGuid = true;
27+
28+
2129
/// <summary>
2230
///
2331
/// </summary>
@@ -94,8 +102,50 @@ protected virtual void RegisterFunctions()
94102

95103
// NH-3787: SQLite requires the cast in SQL too for not defaulting to string.
96104
RegisterFunction("transparentcast", new CastFunction());
97-
98-
RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "substr(hex(?1), 7, 2) || substr(hex(?1), 5, 2) || substr(hex(?1), 3, 2) || substr(hex(?1), 1, 2) || '-' || substr(hex(?1), 11, 2) || substr(hex(?1), 9, 2) || '-' || substr(hex(?1), 15, 2) || substr(hex(?1), 13, 2) || '-' || substr(hex(?1), 17, 4) || '-' || substr(hex(?1), 21) "));
105+
106+
if (_binaryGuid)
107+
RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "substr(hex(?1), 7, 2) || substr(hex(?1), 5, 2) || substr(hex(?1), 3, 2) || substr(hex(?1), 1, 2) || '-' || substr(hex(?1), 11, 2) || substr(hex(?1), 9, 2) || '-' || substr(hex(?1), 15, 2) || substr(hex(?1), 13, 2) || '-' || substr(hex(?1), 17, 4) || '-' || substr(hex(?1), 21) "));
108+
else
109+
RegisterFunction("strguid", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as char)"));
110+
}
111+
112+
113+
public override void Configure(IDictionary<string, string> settings)
114+
{
115+
base.Configure(settings);
116+
117+
ConfigureBinaryGuid(settings);
118+
119+
// Re-register functions depending on settings.
120+
RegisterFunctions();
121+
}
122+
123+
private void ConfigureBinaryGuid(IDictionary<string, string> settings)
124+
{
125+
// We can use a SQLite specific setting to force it, but in common cases it
126+
// should be detected automatically from the connection string below.
127+
settings.TryGetValue(Cfg.Environment.SqliteBinaryGuid, out var strBinaryGuid);
128+
129+
if (string.IsNullOrWhiteSpace(strBinaryGuid))
130+
{
131+
string connectionString = Cfg.Environment.GetConfiguredConnectionString(settings);
132+
if (!string.IsNullOrWhiteSpace(connectionString))
133+
{
134+
var builder = new DbConnectionStringBuilder {ConnectionString = connectionString};
135+
136+
strBinaryGuid = GetConnectionStringProperty(builder, "BinaryGuid");
137+
}
138+
}
139+
140+
// Note that "BinaryGuid=false" is supported by System.Data.SQLite but not Microsoft.Data.Sqlite.
141+
142+
_binaryGuid = string.IsNullOrWhiteSpace(strBinaryGuid) || bool.Parse(strBinaryGuid);
143+
}
144+
145+
private string GetConnectionStringProperty(DbConnectionStringBuilder builder, string propertyName)
146+
{
147+
builder.TryGetValue(propertyName, out object propertyValue);
148+
return (string) propertyValue;
99149
}
100150

101151
#region private static readonly string[] DialectKeywords = { ... }

0 commit comments

Comments
 (0)