Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit d01df15

Browse files
committed
support rewriting sql for dictionary params + use same paramIndex for entire sql
1 parent 8cd546b commit d01df15

7 files changed

+102
-62
lines changed

src/ServiceStack.OrmLite/Async/OrmLiteReadCommandExtensionsAsync.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ internal static Task<List<TModel>> SelectAsync<TModel>(this IDbCommand dbCmd, Ty
5656

5757
internal static Task<List<TModel>> SelectAsync<TModel>(this IDbCommand dbCmd, Type fromTableType, string sqlFilter, object anonType, CancellationToken token)
5858
{
59-
if (anonType != null) dbCmd.SetParameters(fromTableType, anonType, excludeDefaults: false, sql: ref sqlFilter);
60-
var sql = OrmLiteReadCommandExtensions.ToSelect<TModel>(dbCmd.GetDialectProvider(), fromTableType, sqlFilter);
59+
if (anonType != null) dbCmd.SetParameters(fromTableType, anonType, excludeDefaults: false, sql: ref sqlFilter);
60+
var sql = OrmLiteReadCommandExtensions.ToSelect<TModel>(dbCmd.GetDialectProvider(), fromTableType, sqlFilter);
6161
return dbCmd.ConvertToListAsync<TModel>(sql, token);
6262
}
6363

6464
internal static Task<List<T>> SelectByIdsAsync<T>(this IDbCommand dbCmd, IEnumerable idValues, CancellationToken token)
6565
{
66-
var sqlIn = dbCmd.SetIdsInSqlParams(idValues);
67-
return string.IsNullOrEmpty(sqlIn)
66+
var sqlIn = dbCmd.SetIdsInSqlParams(idValues);
67+
return string.IsNullOrEmpty(sqlIn)
6868
? new List<T>().InTask()
6969
: SelectAsync<T>(dbCmd, dbCmd.GetDialectProvider().GetQuotedColumnName(ModelDefinition<T>.PrimaryKeyName) + " IN (" + sqlIn + ")", (object)null, token);
7070
}
@@ -137,7 +137,7 @@ internal static Task<List<T>> SelectAsync<T>(this IDbCommand dbCmd, string sql,
137137

138138
internal static Task<List<T>> SelectAsync<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict, CancellationToken token)
139139
{
140-
dbCmd.SetParameters(dict, excludeDefaults: false).CommandText = dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql);
140+
dbCmd.SetParameters(dict, excludeDefaults: false, sql:ref sql).CommandText = dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql);
141141
return dbCmd.ConvertToListAsync<T>(null, token);
142142
}
143143

@@ -155,7 +155,7 @@ internal static Task<List<T>> SqlListAsync<T>(this IDbCommand dbCmd, string sql,
155155

156156
internal static Task<List<T>> SqlListAsync<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict, CancellationToken token)
157157
{
158-
dbCmd.SetParameters(dict, excludeDefaults: false).CommandText = sql;
158+
dbCmd.SetParameters(dict, excludeDefaults: false, sql:ref sql).CommandText = sql;
159159
return dbCmd.ConvertToListAsync<T>(null, token);
160160
}
161161

@@ -175,13 +175,13 @@ internal static Task<List<T>> SqlColumnAsync<T>(this IDbCommand dbCmd, string sq
175175

176176
internal static Task<List<T>> SqlColumnAsync<T>(this IDbCommand dbCmd, string sql, object anonType, CancellationToken token)
177177
{
178-
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false).CommandText = sql;
178+
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false, sql:ref sql).CommandText = sql;
179179
return dbCmd.ConvertToListAsync<T>(null, token);
180180
}
181181

182182
internal static Task<List<T>> SqlColumnAsync<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict, CancellationToken token)
183183
{
184-
dbCmd.SetParameters(dict, excludeDefaults: false).CommandText = sql;
184+
dbCmd.SetParameters(dict, excludeDefaults: false, sql:ref sql).CommandText = sql;
185185
return dbCmd.ConvertToListAsync<T>(null, token);
186186
}
187187

@@ -197,7 +197,7 @@ internal static Task<T> SqlScalarAsync<T>(this IDbCommand dbCmd, string sql, obj
197197

198198
internal static Task<T> SqlScalarAsync<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict, CancellationToken token)
199199
{
200-
return dbCmd.SetParameters(dict, excludeDefaults: false).ScalarAsync<T>(sql, token);
200+
return dbCmd.SetParameters(dict, excludeDefaults: false, sql:ref sql).ScalarAsync<T>(sql, token);
201201
}
202202

203203
internal static Task<List<T>> SelectNonDefaultsAsync<T>(this IDbCommand dbCmd, object filter, CancellationToken token)
@@ -274,7 +274,7 @@ internal static Task<HashSet<T>> ColumnDistinctAsync<T>(this IDataReader reader,
274274
internal static Task<Dictionary<K, List<V>>> LookupAsync<K, V>(this IDbCommand dbCmd, string sql, object anonType, CancellationToken token)
275275
{
276276
if (anonType != null)
277-
dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false);
277+
dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false, sql:ref sql);
278278

279279
return dbCmd.LookupAsync<K, V>(sql, token);
280280
}
@@ -300,7 +300,7 @@ internal static Task<Dictionary<K, List<V>>> LookupAsync<K, V>(this IDataReader
300300
internal static Task<Dictionary<K, V>> DictionaryAsync<K, V>(this IDbCommand dbCmd, string sql, object anonType, CancellationToken token)
301301
{
302302
if (anonType != null)
303-
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false);
303+
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false, sql:ref sql);
304304

305305
return dbCmd.DictionaryAsync<K, V>(sql, token);
306306
}
@@ -319,16 +319,17 @@ internal static Task<Dictionary<K, V>> DictionaryAsync<K, V>(this IDataReader re
319319

320320
internal static Task<bool> ExistsAsync<T>(this IDbCommand dbCmd, object anonType, CancellationToken token)
321321
{
322-
if (anonType != null) dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: true);
322+
string sql = null;
323+
if (anonType != null) dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: true, sql:ref sql);
323324

324-
var sql = dbCmd.GetFilterSql<T>();
325+
sql = dbCmd.GetFilterSql<T>();
325326

326327
return dbCmd.ScalarAsync(sql, token).Then(x => x != null);
327328
}
328329

329330
internal static Task<bool> ExistsAsync<T>(this IDbCommand dbCmd, string sql, object anonType, CancellationToken token)
330331
{
331-
if (anonType != null) dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false);
332+
if (anonType != null) dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false, sql:ref sql);
332333

333334
return dbCmd.ScalarAsync(dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql), token)
334335
.Then(x => x != null);
@@ -397,8 +398,8 @@ internal static Task<List<TOutputModel>> SqlProcedureFmtAsync<TOutputModel>(this
397398

398399
internal static async Task<List<Into>> LoadListWithReferences<Into, From>(this IDbCommand dbCmd, SqlExpression<From> expr = null, string[] include = null, CancellationToken token = default(CancellationToken))
399400
{
400-
var loadList = new LoadListAsync<Into, From>(dbCmd, expr);
401-
401+
var loadList = new LoadListAsync<Into, From>(dbCmd, expr);
402+
402403
var fieldDefs = loadList.FieldDefs;
403404
if (!include.IsEmpty())
404405
{

src/ServiceStack.OrmLite/Async/OrmLiteResultsFilterExtensionsAsync.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static class OrmLiteResultsFilterExtensionsAsync
1616
public static Task<int> ExecNonQueryAsync(this IDbCommand dbCmd, string sql, object anonType, CancellationToken token = default(CancellationToken))
1717
{
1818
if (anonType != null)
19-
dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false);
19+
dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false, sql:ref sql);
2020

2121
dbCmd.CommandText = sql;
2222

@@ -29,7 +29,7 @@ public static class OrmLiteResultsFilterExtensionsAsync
2929
public static Task<int> ExecNonQueryAsync(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict, CancellationToken token = default(CancellationToken))
3030
{
3131
if (dict != null)
32-
dbCmd.SetParameters(dict, (bool)false);
32+
dbCmd.SetParameters(dict, (bool)false, sql:ref sql);
3333

3434
dbCmd.CommandText = sql;
3535

src/ServiceStack.OrmLite/Async/OrmLiteWriteCommandExtensionsAsync.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal static Task<int> ExecuteSqlAsync(this IDbCommand dbCmd, string sql, Can
3939
internal static Task<int> ExecuteSqlAsync(this IDbCommand dbCmd, string sql, object anonType, CancellationToken token)
4040
{
4141
if (anonType != null)
42-
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false);
42+
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false, sql:ref sql);
4343

4444
dbCmd.CommandText = sql;
4545

src/ServiceStack.OrmLite/Expressions/ReadExpressionCommandExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ internal static long RowCount<T>(this IDbCommand dbCmd, SqlExpression<T> express
204204
internal static long RowCount(this IDbCommand dbCmd, string sql, object anonType)
205205
{
206206
if (anonType != null)
207-
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false);
207+
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false, sql:ref sql);
208208

209209
return dbCmd.Scalar<long>(dbCmd.GetDialectProvider().ToRowCountStatement(sql));
210210
}

src/ServiceStack.OrmLite/OrmLiteReadCommandExtensions.cs

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,70 @@ enumerable is IEnumerable<KeyValuePair<string, object>> ||
138138
) ? enumerable : null;
139139
}
140140

141+
internal static IDbCommand SetParameters(this IDbCommand dbCmd, Dictionary<string, object> dict, bool excludeDefaults, ref string sql)
142+
{
143+
if (dict == null)
144+
return dbCmd;
145+
146+
dbCmd.Parameters.Clear();
147+
lastQueryType = null;
148+
var dialectProvider = dbCmd.GetDialectProvider();
149+
150+
var paramIndex = 0;
151+
var sqlCopy = sql; //C# doesn't allow changing ref params in lambda's
152+
153+
foreach (var kvp in dict)
154+
{
155+
var value = kvp.Value;
156+
var propName = kvp.Key;
157+
if (excludeDefaults && value == null) continue;
158+
159+
var inValues = sql != null ? GetMultiValues(value) : null;
160+
if (inValues != null)
161+
{
162+
var propType = value?.GetType() ?? typeof(object);
163+
var sb = StringBuilderCache.Allocate();
164+
foreach (var item in inValues)
165+
{
166+
var p = dbCmd.CreateParameter();
167+
p.ParameterName = "v" + paramIndex++;
168+
169+
if (sb.Length > 0)
170+
sb.Append(',');
171+
sb.Append(dialectProvider.ParamString + p.ParameterName);
172+
173+
p.Direction = ParameterDirection.Input;
174+
dialectProvider.InitDbParam(p, item.GetType());
175+
176+
dialectProvider.SetParamValue(p, item, propType);
177+
178+
dbCmd.Parameters.Add(p);
179+
}
180+
181+
var sqlIn = StringBuilderCache.ReturnAndFree(sb);
182+
if (string.IsNullOrEmpty(sqlIn))
183+
sqlIn = "NULL";
184+
sqlCopy = sqlCopy?.Replace(dialectProvider.ParamString + propName, sqlIn);
185+
if (dialectProvider.ParamString != "@")
186+
sqlCopy = sqlCopy?.Replace("@" + propName, sqlIn);
187+
}
188+
else
189+
{
190+
var p = dbCmd.CreateParameter();
191+
p.ParameterName = propName;
192+
193+
p.Direction = ParameterDirection.Input;
194+
p.Value = value ?? DBNull.Value;
195+
if (value != null)
196+
dialectProvider.InitDbParam(p, value.GetType());
197+
198+
dbCmd.Parameters.Add(p);
199+
}
200+
}
201+
202+
return dbCmd;
203+
}
204+
141205
internal static IDbCommand SetParameters(this IDbCommand dbCmd, Type type, object anonType, bool excludeDefaults, ref string sql)
142206
{
143207
if (anonType == null)
@@ -154,18 +218,18 @@ internal static IDbCommand SetParameters(this IDbCommand dbCmd, Type type, objec
154218

155219
var sqlCopy = sql; //C# doesn't allow changing ref params in lambda's
156220

221+
var paramIndex = 0;
157222
anonType.ToObjectDictionary().ForEachParam(modelDef, excludeDefaults, (propName, columnName, value) =>
158223
{
159224
var propType = value?.GetType() ?? typeof(object);
160225
var inValues = GetMultiValues(value);
161226
if (inValues != null)
162227
{
163-
var i = 0;
164228
var sb = StringBuilderCache.Allocate();
165229
foreach (var item in inValues)
166230
{
167231
var p = dbCmd.CreateParameter();
168-
p.ParameterName = "v" + i++;
232+
p.ParameterName = "v" + paramIndex++;
169233

170234
if (sb.Length > 0)
171235
sb.Append(',');
@@ -284,33 +348,6 @@ internal static Dictionary<string, object> NonDefaultsOnly(this Dictionary<strin
284348
return map;
285349
}
286350

287-
internal static IDbCommand SetParameters(this IDbCommand dbCmd, Dictionary<string, object> dict, bool excludeDefaults)
288-
{
289-
if (dict == null)
290-
return dbCmd;
291-
292-
dbCmd.Parameters.Clear();
293-
lastQueryType = null;
294-
var dialectProvider = dbCmd.GetDialectProvider();
295-
296-
foreach (var kvp in dict)
297-
{
298-
var value = kvp.Value;
299-
if (excludeDefaults && value == null) continue;
300-
var p = dbCmd.CreateParameter();
301-
p.ParameterName = kvp.Key;
302-
303-
p.Direction = ParameterDirection.Input;
304-
p.Value = value ?? DBNull.Value;
305-
if (value != null)
306-
dialectProvider.InitDbParam(p, value.GetType());
307-
308-
dbCmd.Parameters.Add(p);
309-
}
310-
311-
return dbCmd;
312-
}
313-
314351
public static IDbCommand SetFilters<T>(this IDbCommand dbCmd, object anonType)
315352
{
316353
return dbCmd.SetFilters<T>(anonType, excludeDefaults: false);
@@ -443,7 +480,7 @@ internal static List<T> Select<T>(this IDbCommand dbCmd, string sql, object anon
443480

444481
internal static List<T> Select<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
445482
{
446-
if (dict != null) SetParameters(dbCmd, dict, (bool)false);
483+
if (dict != null) SetParameters(dbCmd, dict, (bool)false, sql:ref sql);
447484
dbCmd.CommandText = dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql);
448485

449486
return dbCmd.ConvertToList<T>();
@@ -495,7 +532,7 @@ internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, object ano
495532

496533
internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
497534
{
498-
if (dict != null) SetParameters(dbCmd, dict, false);
535+
if (dict != null) SetParameters(dbCmd, dict, false, sql:ref sql);
499536
dbCmd.CommandText = sql;
500537

501538
return dbCmd.ConvertToList<T>();
@@ -523,7 +560,7 @@ internal static List<T> SqlColumn<T>(this IDbCommand dbCmd, string sql, object a
523560

524561
internal static List<T> SqlColumn<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
525562
{
526-
if (dict != null) SetParameters(dbCmd, dict, false);
563+
if (dict != null) SetParameters(dbCmd, dict, false, sql:ref sql);
527564
dbCmd.CommandText = sql;
528565

529566
return dbCmd.ConvertToList<T>();
@@ -543,7 +580,7 @@ internal static T SqlScalar<T>(this IDbCommand dbCmd, string sql, object anonTyp
543580

544581
internal static T SqlScalar<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
545582
{
546-
if (dict != null) SetParameters(dbCmd, dict, false);
583+
if (dict != null) SetParameters(dbCmd, dict, false, sql:ref sql);
547584

548585
return dbCmd.Scalar<T>(sql);
549586
}
@@ -766,7 +803,7 @@ internal static HashSet<T> ColumnDistinct<T>(this IDataReader reader, IOrmLiteDi
766803

767804
internal static Dictionary<K, List<V>> Lookup<K, V>(this IDbCommand dbCmd, string sql, object anonType = null)
768805
{
769-
return dbCmd.SetParameters(anonType.ToObjectDictionary(), false).Lookup<K, V>(sql);
806+
return dbCmd.SetParameters(anonType.ToObjectDictionary(), false, sql:ref sql).Lookup<K, V>(sql);
770807
}
771808

772809
internal static Dictionary<K, List<V>> Lookup<K, V>(this IDataReader reader, IOrmLiteDialectProvider dialectProvider)
@@ -791,7 +828,7 @@ internal static Dictionary<K, List<V>> Lookup<K, V>(this IDataReader reader, IOr
791828

792829
internal static Dictionary<K, V> Dictionary<K, V>(this IDbCommand dbCmd, string sql, object anonType = null)
793830
{
794-
if (anonType != null) SetParameters(dbCmd, anonType.ToObjectDictionary(), excludeDefaults: false);
831+
if (anonType != null) SetParameters(dbCmd, anonType.ToObjectDictionary(), excludeDefaults: false, sql:ref sql);
795832

796833
return dbCmd.Dictionary<K, V>(sql);
797834
}
@@ -813,17 +850,18 @@ internal static Dictionary<K, V> Dictionary<K, V>(this IDataReader reader, IOrmL
813850

814851
internal static bool Exists<T>(this IDbCommand dbCmd, object anonType)
815852
{
816-
if (anonType != null) SetParameters(dbCmd, anonType.ToObjectDictionary(), excludeDefaults: true);
853+
string sql = null;
854+
if (anonType != null) SetParameters(dbCmd, anonType.ToObjectDictionary(), excludeDefaults: true, sql:ref sql);
817855

818-
var sql = GetFilterSql<T>(dbCmd);
856+
sql = GetFilterSql<T>(dbCmd);
819857

820858
var result = dbCmd.Scalar(sql);
821859
return result != null;
822860
}
823861

824862
internal static bool Exists<T>(this IDbCommand dbCmd, string sql, object anonType = null)
825863
{
826-
if (anonType != null) SetParameters(dbCmd, anonType.ToObjectDictionary(), (bool)false);
864+
if (anonType != null) SetParameters(dbCmd, anonType.ToObjectDictionary(), (bool)false, sql:ref sql);
827865

828866
var result = dbCmd.Scalar(dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql));
829867
return result != null;
@@ -1020,7 +1058,8 @@ internal static IDbCommand SqlProc(this IDbCommand dbCmd, string name, object in
10201058
dbCmd.CommandType = CommandType.StoredProcedure;
10211059
dbCmd.CommandText = name;
10221060

1023-
dbCmd.SetParameters(inParams.ToObjectDictionary(), excludeDefaults);
1061+
string sql = null;
1062+
dbCmd.SetParameters(inParams.ToObjectDictionary(), excludeDefaults, sql:ref sql);
10241063

10251064
return dbCmd;
10261065
}

src/ServiceStack.OrmLite/OrmLiteResultsFilterExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static class OrmLiteResultsFilterExtensions
1717
public static int ExecNonQuery(this IDbCommand dbCmd, string sql, object anonType = null)
1818
{
1919
if (anonType != null)
20-
dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false);
20+
dbCmd.SetParameters(anonType.ToObjectDictionary(), (bool)false, sql:ref sql);
2121

2222
dbCmd.CommandText = sql;
2323

@@ -34,7 +34,7 @@ public static int ExecNonQuery(this IDbCommand dbCmd, string sql, Dictionary<str
3434
{
3535

3636
if (dict != null)
37-
dbCmd.SetParameters(dict, (bool)false);
37+
dbCmd.SetParameters(dict, (bool)false, sql:ref sql);
3838

3939
dbCmd.CommandText = sql;
4040

src/ServiceStack.OrmLite/OrmLiteWriteCommandExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ internal static int ExecuteSql(this IDbCommand dbCmd, string sql, IEnumerable<ID
235235
internal static int ExecuteSql(this IDbCommand dbCmd, string sql, object anonType)
236236
{
237237
if (anonType != null)
238-
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false);
238+
dbCmd.SetParameters(anonType.ToObjectDictionary(), excludeDefaults: false, sql:ref sql);
239239

240240
dbCmd.CommandText = sql;
241241

0 commit comments

Comments
 (0)