Skip to content

Commit 6b33184

Browse files
committed
NH-3480 - Use ANSI "join" for UPDATE statement
1 parent f5cc06e commit 6b33184

File tree

2 files changed

+22
-45
lines changed

2 files changed

+22
-45
lines changed

src/NHibernate/Persister/Collection/OneToManyPersister.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ protected override SqlCommandInfo GenerateDeleteString()
7575
else
7676
{
7777
var ownerPersister = (IOuterJoinLoadable)OwnerEntityPersister;
78-
update.SetJoin(ownerPersister.TableName, JoinColumnNames, ownerPersister.GetPropertyColumnNames(CollectionType.LHSPropertyName));
79-
update.SetIdentityColumn(ownerPersister.TableName, KeyColumnNames, KeyType);
78+
update.SetJoin(ownerPersister.TableName, KeyColumnNames, KeyType, JoinColumnNames, ownerPersister.GetPropertyColumnNames(CollectionType.LHSPropertyName));
8079
}
8180

8281
if (HasIndex)

src/NHibernate/SqlCommand/SqlUpdateBuilder.cs

Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System.Collections.Generic;
2-
2+
using System.Linq;
33
using NHibernate.Engine;
44
using NHibernate.SqlTypes;
55
using NHibernate.Type;
@@ -20,9 +20,7 @@ public class SqlUpdateBuilder : SqlBaseBuilder, ISqlStringBuilder
2020
// columns-> (ColumnName, Value) or (ColumnName, SqlType) for parametrized column
2121
private readonly LinkedHashMap<string, object> columns = new LinkedHashMap<string, object>();
2222

23-
private SqlString join = null;
24-
25-
private List<SqlString> whereStrings = new List<SqlString>();
23+
private List<SqlString> whereStrings = new List<SqlString>();
2624
private readonly List<SqlType> whereParameterTypes = new List<SqlType>();
2725
private SqlString assignments;
2826

@@ -130,25 +128,30 @@ public SqlUpdateBuilder AppendAssignmentFragment(SqlString fragment)
130128
return this;
131129
}
132130

133-
public SqlUpdateBuilder SetJoin(string joinTableName, string[] lhsColumnNames, string[] rhsColumnNames)
131+
public SqlUpdateBuilder SetJoin(string joinTableName, string[] keyColumnNames, IType identityType, string[] lhsColumnNames, string[] rhsColumnNames)
134132
{
135-
SqlStringBuilder joinStringBuilder = new SqlStringBuilder();
133+
var sqlBuilder = new SqlStringBuilder()
134+
.Add("EXISTS (SELECT * FROM ")
135+
.Add(joinTableName)
136+
.Add(" WHERE ")
137+
.Add(ToWhereString(joinTableName, keyColumnNames));
136138

137-
joinStringBuilder.Add(" INNER JOIN ");
138-
joinStringBuilder.Add(joinTableName);
139-
joinStringBuilder.Add(" ON ");
140-
bool andNeeded = false;
141139
for (int columnIndex = 0; columnIndex < lhsColumnNames.Length; columnIndex++)
142140
{
143-
if (andNeeded)
144-
{
145-
joinStringBuilder.Add(" AND ");
146-
}
147-
joinStringBuilder.Add(tableName + StringHelper.Dot + lhsColumnNames[columnIndex] + " = " + joinTableName + StringHelper.Dot + rhsColumnNames[columnIndex]);
148-
andNeeded = true;
141+
sqlBuilder.Add(" AND ")
142+
.Add(tableName)
143+
.Add(StringHelper.Dot.ToString())
144+
.Add(lhsColumnNames[columnIndex])
145+
.Add("=")
146+
.Add(joinTableName)
147+
.Add(StringHelper.Dot.ToString())
148+
.Add(rhsColumnNames[columnIndex]);
149149
}
150+
sqlBuilder.Add(")");
151+
152+
whereStrings.Add(sqlBuilder.ToSqlString());
153+
whereParameterTypes.AddRange(identityType.SqlTypes(Mapping));
150154

151-
join = joinStringBuilder.ToSqlString();
152155
return this;
153156
}
154157

@@ -174,20 +177,6 @@ public SqlUpdateBuilder SetIdentityColumn(string[] columnNames, IType identityTy
174177
return this;
175178
}
176179

177-
/// <summary>
178-
/// Sets the IdentityColumn for the <c>UPDATE</c> sql to use.
179-
/// </summary>
180-
/// <param name="tableName">Table name to prepend to the columns.</param>
181-
/// <param name="columnNames">An array of the column names for the Property</param>
182-
/// <param name="identityType">The IType of the Identity Property.</param>
183-
/// <returns>The SqlUpdateBuilder.</returns>
184-
public SqlUpdateBuilder SetIdentityColumn(string tableName, string[] columnNames, IType identityType)
185-
{
186-
whereStrings.Add(ToWhereString(tableName, columnNames));
187-
whereParameterTypes.AddRange(identityType.SqlTypes(Mapping));
188-
return this;
189-
}
190-
191180
/// <summary>
192181
/// Sets the VersionColumn for the <c>UPDATE</c> sql to use.
193182
/// </summary>
@@ -271,19 +260,14 @@ public SqlString ToSqlString()
271260
initialCapacity += (columns.Count - 1) + (columns.Count * 3);
272261
}
273262

274-
// 3 - JOIN
275-
if (join != null)
276-
initialCapacity += 3;
277-
278263
// 1 = "WHERE"
279264
initialCapacity++;
280265

281266
// the "AND" before all but the first whereString
282267
if (whereStrings.Count > 0)
283268
{
284269
initialCapacity += (whereStrings.Count - 1);
285-
foreach (SqlString whereString in whereStrings)
286-
initialCapacity += whereString.Count;
270+
initialCapacity += whereStrings.Sum(x => x.Count);
287271
}
288272

289273
if (!string.IsNullOrEmpty(comment))
@@ -325,12 +309,6 @@ public SqlString ToSqlString()
325309
sqlBuilder.Add(assignments);
326310
}
327311

328-
if (join != null)
329-
{
330-
sqlBuilder.Add(" FROM ");
331-
sqlBuilder.Add(tableName);
332-
sqlBuilder.Add(join);
333-
}
334312

335313
sqlBuilder.Add(" WHERE ");
336314
bool andNeeded = false;

0 commit comments

Comments
 (0)