Skip to content

Commit 1a5a1ba

Browse files
committed
change SqlGenerator to use dialect specfic bitwise operations identified as "band", "bor", "bxor" and "bnot" which can be overriden by Subclasses of Dialect
1 parent bea9bc9 commit 1a5a1ba

File tree

5 files changed

+167
-16
lines changed

5 files changed

+167
-16
lines changed

src/NHibernate/Dialect/Dialect.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ protected Dialect()
113113
RegisterFunction("month", new SQLFunctionTemplate(NHibernateUtil.Int32, "extract(month from ?1)"));
114114
RegisterFunction("year", new SQLFunctionTemplate(NHibernateUtil.Int32, "extract(year from ?1)"));
115115

116+
//RegisterFunction("band", new SQLFunctionTemplate(NHibernateUtil.Int64, "?1 & ?2"));
117+
RegisterFunction("band", new NativeBitwiseOpetration("&"));
118+
RegisterFunction("bor", new NativeBitwiseOpetration("|"));
119+
RegisterFunction("bxor", new NativeBitwiseOpetration("^"));
120+
RegisterFunction("bnot", new NativeBitwiseOpetration("~"));
121+
116122
RegisterFunction("str", new SQLFunctionTemplate(NHibernateUtil.String, "cast(?1 as char)"));
117123

118124
// register hibernate types for default use in scalar sqlquery type auto detection
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System;
2+
using System.Collections;
3+
using NHibernate.Dialect.Function;
4+
using NHibernate.Engine;
5+
using NHibernate.SqlCommand;
6+
using NHibernate.Type;
7+
8+
namespace NHibernate.Dialect
9+
{
10+
[Serializable]
11+
public class NativeBitwiseOperation : ISQLFunction
12+
{
13+
private readonly string _sqlToken;
14+
private Queue _args;
15+
private SqlStringBuilder _sqlBuffer;
16+
17+
public NativeBitwiseOperation(string sqlToken)
18+
{
19+
_sqlToken = sqlToken;
20+
}
21+
22+
#region ISQLFunction Members
23+
24+
public IType ReturnType(IType columnType, IMapping mapping)
25+
{
26+
return NHibernateUtil.Int64;
27+
}
28+
29+
public bool HasArguments
30+
{
31+
get { return true; }
32+
}
33+
34+
public bool HasParenthesesIfNoArguments
35+
{
36+
get { return false; }
37+
}
38+
39+
public SqlString Render(IList args, ISessionFactoryImplementor factory)
40+
{
41+
Prepare(args);
42+
if (_sqlToken != "~")
43+
AddFirstArgument();
44+
AddToken();
45+
AddRestOfArguments();
46+
47+
return _sqlBuffer.ToSqlString();
48+
}
49+
50+
#endregion
51+
52+
private void Prepare(IList args)
53+
{
54+
_sqlBuffer = new SqlStringBuilder();
55+
_args = new Queue(args);
56+
}
57+
58+
private void AddFirstArgument()
59+
{
60+
AddToBuffer(_args.Dequeue());
61+
}
62+
63+
private void AddToken()
64+
{
65+
AddToBuffer(string.Format(" {0} ", _sqlToken));
66+
}
67+
68+
private void AddRestOfArguments()
69+
{
70+
while (_args.Count > 0)
71+
{
72+
AddToBuffer(_args.Dequeue());
73+
}
74+
}
75+
76+
private void AddToBuffer(object arg)
77+
{
78+
if (arg is Parameter || arg is SqlString)
79+
_sqlBuffer.AddObject(arg);
80+
else
81+
_sqlBuffer.Add(arg.ToString());
82+
}
83+
}
84+
}

src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.cs

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public partial class SqlGenerator : IErrorReporter
4141
private readonly SqlStringBuilder sqlStringBuilder = new SqlStringBuilder();
4242
private ISqlWriter writer;
4343

44-
public SqlGenerator(ISessionFactoryImplementor sfi, ITreeNodeStream input) : this(input)
44+
public SqlGenerator(ISessionFactoryImplementor sfi, ITreeNodeStream input)
45+
: this(input)
4546
{
4647
parseErrorHandler = new ErrorCounter();
4748
sessionFactory = sfi;
@@ -134,7 +135,7 @@ private void Out(IASTNode n)
134135
}
135136
else if (n is SqlNode)
136137
{
137-
Out(((SqlNode) n).RenderText(sessionFactory));
138+
Out(((SqlNode)n).RenderText(sessionFactory));
138139
}
139140
else
140141
{
@@ -147,7 +148,7 @@ private void Out(IASTNode n)
147148
}
148149
else if (n is IParameterContainer)
149150
{
150-
var parameterContainer = (IParameterContainer) n;
151+
var parameterContainer = (IParameterContainer)n;
151152
if (parameterContainer.HasEmbeddedParameters)
152153
{
153154
IParameterSpecification[] specifications = parameterContainer.GetEmbeddedParameters();
@@ -178,8 +179,8 @@ protected virtual void FromFragmentSeparator(IASTNode a)
178179
return;
179180
}
180181

181-
var left = (FromElement) a;
182-
var right = (FromElement) next;
182+
var left = (FromElement)a;
183+
var right = (FromElement)next;
183184

184185
///////////////////////////////////////////////////////////////////////
185186
// HACK ALERT !!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -192,7 +193,7 @@ protected virtual void FromFragmentSeparator(IASTNode a)
192193
// writes something to the SQL
193194
while (right != null && !HasText(right))
194195
{
195-
right = (FromElement) right.NextSibling;
196+
right = (FromElement)right.NextSibling;
196197
}
197198

198199
if (right == null)
@@ -235,8 +236,8 @@ protected virtual void NestedFromFragment(IASTNode d, IASTNode parent)
235236
if (parent != null && HasText(parent))
236237
{
237238
// again, both should be FromElements
238-
var left = (FromElement) parent;
239-
var right = (FromElement) d;
239+
var left = (FromElement)parent;
240+
var right = (FromElement)d;
240241
if (right.RealOrigin == left)
241242
{
242243
// right represents a joins originating from left...
@@ -268,7 +269,7 @@ private SqlStringBuilder GetStringBuilder()
268269

269270
private void BeginFunctionTemplate(IASTNode m, IASTNode i)
270271
{
271-
var methodNode = (MethodNode) m;
272+
var methodNode = (MethodNode)m;
272273
ISQLFunction template = methodNode.SQLFunction;
273274
if (template == null)
274275
{
@@ -286,7 +287,7 @@ private void BeginFunctionTemplate(IASTNode m, IASTNode i)
286287

287288
private void EndFunctionTemplate(IASTNode m)
288289
{
289-
var methodNode = (MethodNode) m;
290+
var methodNode = (MethodNode)m;
290291
ISQLFunction template = methodNode.SQLFunction;
291292
if (template == null)
292293
{
@@ -295,7 +296,7 @@ private void EndFunctionTemplate(IASTNode m)
295296
else
296297
{
297298
// this function has a template -> restore output, apply the template and write the result out
298-
var functionArguments = (FunctionArguments) writer; // TODO: Downcast to avoid using an interface? Yuck.
299+
var functionArguments = (FunctionArguments)writer; // TODO: Downcast to avoid using an interface? Yuck.
299300
writer = outputStack[0];
300301
outputStack.RemoveAt(0);
301302
Out(template.Render(functionArguments.Args, sessionFactory));
@@ -315,7 +316,7 @@ private void StartQuery()
315316

316317
private void EndQuery()
317318
{
318-
SqlString sqlString = GetSqlStringWithLimitsIfNeeded((QueryWriter) writer);
319+
SqlString sqlString = GetSqlStringWithLimitsIfNeeded((QueryWriter)writer);
319320

320321
writer = outputStack[0];
321322
outputStack.RemoveAt(0);
@@ -381,6 +382,28 @@ private void Take(IASTNode node)
381382
queryWriter.Take = Convert.ToInt32(node.Text);
382383
}
383384

385+
private void BeginBitwiseOp(string op)
386+
{
387+
var function = sessionFactory.SQLFunctionRegistry.FindSQLFunction(op.ToLowerInvariant());
388+
if (function == null)
389+
return;
390+
391+
outputStack.Insert(0, writer);
392+
writer = new BitwiseOperation();
393+
}
394+
395+
private void EndBitwiseOp(string op)
396+
{
397+
ISQLFunction function = sessionFactory.SQLFunctionRegistry.FindSQLFunction(op.ToLowerInvariant());
398+
if (function == null)
399+
return;
400+
401+
var functionArguments = (BitwiseOperation)writer;
402+
writer = outputStack[0];
403+
outputStack.RemoveAt(0);
404+
Out(function.Render(functionArguments.Args, sessionFactory));
405+
}
406+
384407
#region Nested type: DefaultWriter
385408

386409
/// <summary>
@@ -534,6 +557,43 @@ public void CommaBetweenParameters(string comma)
534557

535558
#endregion
536559

560+
#region Nested type: BitwiseOperation
561+
562+
private class BitwiseOperation : ISqlWriter
563+
{
564+
private readonly List<SqlString> _args = new List<SqlString>();
565+
566+
#region ISqlWriter Members
567+
568+
public void Clause(string clause)
569+
{
570+
Clause(SqlString.Parse(clause));
571+
}
572+
573+
public void Clause(SqlString clause)
574+
{
575+
_args.Add(clause);
576+
}
577+
578+
public void PushParameter(Parameter parameter)
579+
{
580+
_args.Add(new SqlString(parameter));
581+
}
582+
583+
public void CommaBetweenParameters(string comma)
584+
{
585+
}
586+
587+
#endregion
588+
589+
public IList Args
590+
{
591+
get { return _args; }
592+
}
593+
}
594+
595+
#endregion
596+
537597
#region Nested type: ISqlWriter
538598

539599
/// <summary>

src/NHibernate/Hql/Ast/ANTLR/SqlGenerator.g

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,10 @@ additiveExpr
305305
;
306306
307307
bitwiseExpr
308-
: ^(BAND expr { Out("&"); } nestedExpr)
309-
| ^(BOR expr { Out("|"); } nestedExpr)
310-
| ^(BXOR expr { Out("^"); } nestedExpr)
311-
| ^(BNOT { Out("~"); } nestedExpr)
308+
: ^(BAND { BeginBitwiseOp("band"); } expr nestedExpr { EndBitwiseOp("band"); })
309+
| ^(BOR { BeginBitwiseOp("bor"); } expr nestedExpr { EndBitwiseOp("bor"); })
310+
| ^(BXOR { BeginBitwiseOp("bxor"); } expr nestedExpr { EndBitwiseOp("bxor"); })
311+
| ^(BNOT { BeginBitwiseOp("bnot"); } nestedExpr { EndBitwiseOp("bnot"); })
312312
;
313313
314314
multiplicativeExpr

src/NHibernate/NHibernate.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
<Compile Include="Dialect\MySQL55InnoDBDialect.cs" />
157157
<Compile Include="Dialect\MySQL5InnoDBDialect.cs" />
158158
<Compile Include="Dialect\MySQLDialect.cs" />
159+
<Compile Include="Dialect\NativeBitwiseOperation.cs" />
159160
<Compile Include="Dialect\PostgreSQLDialect.cs" />
160161
<Compile Include="Dialect\Schema\PostgreSQLMetadata.cs" />
161162
<Compile Include="Dialect\Schema\SchemaHelper.cs" />

0 commit comments

Comments
 (0)