forked from nhibernate/nhibernate-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFirebirdClientDriver.cs
110 lines (96 loc) · 3.31 KB
/
FirebirdClientDriver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text.RegularExpressions;
using NHibernate.Dialect;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;
using NHibernate.Util;
namespace NHibernate.Driver
{
/// <summary>
/// A NHibernate Driver for using the Firebird data provider located in
/// <c>FirebirdSql.Data.FirebirdClient</c> assembly.
/// </summary>
public class FirebirdClientDriver : ReflectionBasedDriver
{
private const string SELECT_CLAUSE_EXP = @"(?<=\bselect|\bwhere).*";
private const string CAST_PARAMS_EXP = @"(?<![=<>]\s?|first\s?|skip\s?|between\s|between\s@\bp\w+\b\sand\s)@\bp\w+\b(?!\s?[=<>])";
private readonly Regex _statementRegEx = new Regex(SELECT_CLAUSE_EXP, RegexOptions.IgnoreCase);
private readonly Regex _castCandidateRegEx = new Regex(CAST_PARAMS_EXP, RegexOptions.IgnoreCase);
private readonly FirebirdDialect _fbDialect = new FirebirdDialect();
/// <summary>
/// Initializes a new instance of the <see cref="FirebirdClientDriver"/> class.
/// </summary>
/// <exception cref="HibernateException">
/// Thrown when the <c>FirebirdSql.Data.Firebird</c> assembly can not be loaded.
/// </exception>
public FirebirdClientDriver()
: base(
"FirebirdSql.Data.FirebirdClient",
"FirebirdSql.Data.FirebirdClient",
"FirebirdSql.Data.FirebirdClient.FbConnection",
"FirebirdSql.Data.FirebirdClient.FbCommand")
{
}
public override bool UseNamedPrefixInSql
{
get { return true; }
}
public override bool UseNamedPrefixInParameter
{
get { return true; }
}
public override string NamedPrefix
{
get { return "@"; }
}
protected override void InitializeParameter(DbParameter dbParam, string name, SqlType sqlType)
{
var convertedSqlType = sqlType;
if (convertedSqlType.DbType == DbType.Currency)
convertedSqlType = new SqlType(DbType.Decimal);
base.InitializeParameter(dbParam, name, convertedSqlType);
}
public override DbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes)
{
var command = base.GenerateCommand(type, sqlString, parameterTypes);
var expWithParams = GetStatementsWithCastCandidates(command.CommandText);
if (!string.IsNullOrWhiteSpace(expWithParams))
{
var candidates = GetCastCandidates(expWithParams);
var castParams = from DbParameter p in command.Parameters
where candidates.Contains(p.ParameterName)
select p;
foreach (var param in castParams)
{
TypeCastParam(param, command);
}
}
return command;
}
private string GetStatementsWithCastCandidates(string commandText)
{
return _statementRegEx.Match(commandText).Value;
}
private HashSet<string> GetCastCandidates(string statement)
{
var candidates =
_castCandidateRegEx
.Matches(statement)
.Cast<Match>()
.Select(match => match.Value);
return new HashSet<string>(candidates);
}
private void TypeCastParam(DbParameter param, DbCommand command)
{
var castType = GetFbTypeFromDbType(param.DbType);
command.CommandText = command.CommandText.ReplaceWholeWord(param.ParameterName, string.Format("cast({0} as {1})", param.ParameterName, castType));
}
private string GetFbTypeFromDbType(DbType dbType)
{
return _fbDialect.GetCastTypeName(new SqlType(dbType));
}
}
}