Skip to content

Commit 7f27122

Browse files
Fix bitwise functions thread safety
Functions instances are hold in the dialect, shared among sessions spawned from the same factory. They must be thread safe. Implementation moved to its correct directory by the way.
1 parent 92de0b7 commit 7f27122

File tree

7 files changed

+191
-206
lines changed

7 files changed

+191
-206
lines changed
Lines changed: 6 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,16 @@
11
using System;
2-
using System.Collections;
3-
using NHibernate.Dialect.Function;
4-
using NHibernate.Engine;
5-
using NHibernate.SqlCommand;
6-
using NHibernate.Type;
72

83
namespace NHibernate.Dialect
94
{
10-
/// <summary>
11-
/// Treats bitwise operations as SQL function calls.
12-
/// </summary>
5+
/// <inheritdoc />
136
[Serializable]
14-
public class BitwiseFunctionOperation : ISQLFunction
7+
// Since 5.2
8+
[Obsolete("Use NHibernate.Dialect.Function.BitwiseFunctionOperation instead")]
9+
public class BitwiseFunctionOperation : Function.BitwiseFunctionOperation
1510
{
16-
private readonly string _functionName;
17-
private SqlStringBuilder _sqlBuffer;
18-
private Queue _args;
19-
20-
/// <summary>
21-
/// Creates an instance of this class using the provided function name
22-
/// </summary>
23-
/// <param name="functionName">
24-
/// The bitwise function name as defined by the SQL-Dialect
25-
/// </param>
26-
public BitwiseFunctionOperation(string functionName)
27-
{
28-
_functionName = functionName;
29-
}
30-
31-
#region ISQLFunction Members
32-
33-
public IType ReturnType(IType columnType, IMapping mapping)
34-
{
35-
return NHibernateUtil.Int64;
36-
}
37-
38-
public bool HasArguments
39-
{
40-
get { return true; }
41-
}
42-
43-
public bool HasParenthesesIfNoArguments
44-
{
45-
get { return true; }
46-
}
47-
48-
public SqlString Render(IList args, ISessionFactoryImplementor factory)
49-
{
50-
Prepare(args);
51-
52-
AddFunctionName();
53-
OpenParens();
54-
AddArguments();
55-
CloseParens();
56-
57-
return SqlResult();
58-
}
59-
60-
#endregion
61-
62-
private void Prepare(IList args)
63-
{
64-
_sqlBuffer = new SqlStringBuilder();
65-
_args = new Queue();
66-
foreach (var arg in args)
67-
{
68-
if (!IsParens(arg.ToString()))
69-
_args.Enqueue(arg);
70-
}
71-
}
72-
73-
private static bool IsParens(string candidate)
74-
{
75-
return candidate == "(" || candidate == ")";
76-
}
77-
78-
private void AddFunctionName()
79-
{
80-
_sqlBuffer.Add(_functionName);
81-
}
82-
83-
private void OpenParens()
84-
{
85-
_sqlBuffer.Add("(");
86-
}
87-
88-
private void AddArguments()
89-
{
90-
while (_args.Count > 0)
91-
{
92-
var arg = _args.Dequeue();
93-
if (arg is Parameter || arg is SqlString)
94-
_sqlBuffer.AddObject(arg);
95-
else
96-
_sqlBuffer.Add(arg.ToString());
97-
if (_args.Count > 0)
98-
_sqlBuffer.Add(", ");
99-
}
100-
}
101-
102-
private void CloseParens()
103-
{
104-
_sqlBuffer.Add(")");
105-
}
106-
107-
private SqlString SqlResult()
11+
/// <inheritdoc />
12+
public BitwiseFunctionOperation(string functionName): base(functionName)
10813
{
109-
return _sqlBuffer.ToSqlString();
11014
}
11115
}
11216
}
Lines changed: 8 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,21 @@
11
using System;
2-
using System.Collections;
3-
using NHibernate.Dialect.Function;
4-
using NHibernate.Engine;
5-
using NHibernate.SqlCommand;
6-
using NHibernate.Type;
72

83
namespace NHibernate.Dialect
94
{
10-
/// <summary>
11-
/// Treats bitwise operations as native operations.
12-
/// </summary>
5+
/// <inheritdoc />
136
[Serializable]
14-
public class BitwiseNativeOperation : ISQLFunction
7+
// Since 5.2
8+
[Obsolete("Use NHibernate.Dialect.Function.BitwiseNativeOperation instead")]
9+
public class BitwiseNativeOperation : Function.BitwiseNativeOperation
1510
{
16-
private readonly string _sqlOpToken;
17-
private readonly bool _isNot;
18-
private Queue _args;
19-
private SqlStringBuilder _sqlBuffer;
20-
21-
/// <summary>
22-
/// creates an instance using the giving token
23-
/// </summary>
24-
/// <param name="sqlOpToken">
25-
/// The operation token
26-
/// </param>
27-
/// <remarks>
28-
/// Use this constructor only if the token DOES NOT represent a NOT-Operation
29-
/// </remarks>
30-
public BitwiseNativeOperation(string sqlOpToken)
31-
: this(sqlOpToken, false)
32-
{
33-
}
34-
35-
/// <summary>
36-
/// creates an instance using the giving token and the flag indicating a NOT-Operation
37-
/// </summary>
38-
/// <param name="sqlOpToken"></param>
39-
/// <param name="isNot"></param>
40-
public BitwiseNativeOperation(string sqlOpToken, bool isNot)
41-
{
42-
_sqlOpToken = sqlOpToken;
43-
_isNot = isNot;
44-
}
45-
46-
#region ISQLFunction Members
47-
48-
public IType ReturnType(IType columnType, IMapping mapping)
49-
{
50-
return NHibernateUtil.Int64;
51-
}
52-
53-
public bool HasArguments
54-
{
55-
get { return true; }
56-
}
57-
58-
public bool HasParenthesesIfNoArguments
59-
{
60-
get { return false; }
61-
}
62-
63-
public SqlString Render(IList args, ISessionFactoryImplementor factory)
64-
{
65-
Prepare(args);
66-
if (_isNot == false)
67-
AddFirstArgument();
68-
AddToken();
69-
AddRestOfArguments();
70-
71-
return _sqlBuffer.ToSqlString();
72-
}
73-
74-
#endregion
75-
76-
private void Prepare(IList args)
77-
{
78-
_sqlBuffer = new SqlStringBuilder();
79-
_args = new Queue(args);
80-
}
81-
82-
private void AddFirstArgument()
83-
{
84-
AddToBuffer(_args.Dequeue());
85-
}
86-
87-
private void AddToken()
88-
{
89-
AddToBuffer(string.Format(" {0} ", _sqlOpToken));
90-
}
91-
92-
private void AddRestOfArguments()
11+
/// <inheritdoc />
12+
public BitwiseNativeOperation(string sqlOpToken) : base(sqlOpToken)
9313
{
94-
while (_args.Count > 0)
95-
{
96-
AddToBuffer(_args.Dequeue());
97-
}
9814
}
9915

100-
private void AddToBuffer(object arg)
16+
/// <inheritdoc />
17+
public BitwiseNativeOperation(string sqlOpToken, bool isNot) : base(sqlOpToken, isNot)
10118
{
102-
if (arg is Parameter || arg is SqlString)
103-
_sqlBuffer.AddObject(arg);
104-
else
105-
_sqlBuffer.Add(arg.ToString());
10619
}
10720
}
10821
}

src/NHibernate/Dialect/Dialect.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,10 @@ protected Dialect()
117117
RegisterFunction("year", new SQLFunctionTemplate(NHibernateUtil.Int32, "extract(year from ?1)"));
118118

119119
// Bitwise operations
120-
RegisterFunction("band", new BitwiseNativeOperation("&"));
121-
RegisterFunction("bor", new BitwiseNativeOperation("|"));
122-
RegisterFunction("bxor", new BitwiseNativeOperation("^"));
123-
RegisterFunction("bnot", new BitwiseNativeOperation("~", true));
120+
RegisterFunction("band", new Function.BitwiseNativeOperation("&"));
121+
RegisterFunction("bor", new Function.BitwiseNativeOperation("|"));
122+
RegisterFunction("bxor", new Function.BitwiseNativeOperation("^"));
123+
RegisterFunction("bnot", new Function.BitwiseNativeOperation("~", true));
124124

125125
RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as char)"));
126126

src/NHibernate/Dialect/FirebirdDialect.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,10 @@ private void OverrideStandardHQLFunctions()
422422
RegisterFunction("sysdate", new CastedFunction("today", NHibernateUtil.Date));
423423
RegisterFunction("date", new SQLFunctionTemplate(NHibernateUtil.Date, "cast(?1 as date)"));
424424
// Bitwise operations
425-
RegisterFunction("band", new BitwiseFunctionOperation("bin_and"));
426-
RegisterFunction("bor", new BitwiseFunctionOperation("bin_or"));
427-
RegisterFunction("bxor", new BitwiseFunctionOperation("bin_xor"));
428-
RegisterFunction("bnot", new BitwiseFunctionOperation("bin_not"));
425+
RegisterFunction("band", new Function.BitwiseFunctionOperation("bin_and"));
426+
RegisterFunction("bor", new Function.BitwiseFunctionOperation("bin_or"));
427+
RegisterFunction("bxor", new Function.BitwiseFunctionOperation("bin_xor"));
428+
RegisterFunction("bnot", new Function.BitwiseFunctionOperation("bin_not"));
429429
}
430430

431431
private void RegisterFirebirdServerEmbeddedFunctions()
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using System.Collections;
3+
using NHibernate.Engine;
4+
using NHibernate.SqlCommand;
5+
using NHibernate.Type;
6+
7+
namespace NHibernate.Dialect.Function
8+
{
9+
/// <summary>
10+
/// Treats bitwise operations as SQL function calls.
11+
/// </summary>
12+
[Serializable]
13+
public class BitwiseFunctionOperation : ISQLFunction
14+
{
15+
private readonly string _functionName;
16+
17+
/// <summary>
18+
/// Creates an instance of this class using the provided function name
19+
/// </summary>
20+
/// <param name="functionName">
21+
/// The bitwise function name as defined by the SQL-Dialect
22+
/// </param>
23+
public BitwiseFunctionOperation(string functionName)
24+
{
25+
_functionName = functionName;
26+
}
27+
28+
#region ISQLFunction Members
29+
30+
public IType ReturnType(IType columnType, IMapping mapping)
31+
{
32+
return NHibernateUtil.Int64;
33+
}
34+
35+
public bool HasArguments
36+
{
37+
get { return true; }
38+
}
39+
40+
public bool HasParenthesesIfNoArguments
41+
{
42+
get { return true; }
43+
}
44+
45+
public SqlString Render(IList args, ISessionFactoryImplementor factory)
46+
{
47+
var filteredArgs = new Queue();
48+
foreach (var arg in args)
49+
{
50+
if (!IsParens(arg.ToString()))
51+
filteredArgs.Enqueue(arg);
52+
}
53+
54+
var sqlBuffer = new SqlStringBuilder();
55+
56+
sqlBuffer.Add(_functionName);
57+
sqlBuffer.Add("(");
58+
while (filteredArgs.Count > 0)
59+
{
60+
var arg = filteredArgs.Dequeue();
61+
if (arg is Parameter || arg is SqlString)
62+
sqlBuffer.AddObject(arg);
63+
else
64+
sqlBuffer.Add(arg.ToString());
65+
if (filteredArgs.Count > 0)
66+
sqlBuffer.Add(", ");
67+
}
68+
69+
sqlBuffer.Add(")");
70+
71+
return sqlBuffer.ToSqlString();
72+
}
73+
74+
#endregion
75+
76+
private static bool IsParens(string candidate)
77+
{
78+
return candidate == "(" || candidate == ")";
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)