Skip to content

Commit f2c706a

Browse files
Merge branch 'master' of github.com:sqlkata/querybuilder into master
2 parents f6a9e19 + b762ed9 commit f2c706a

File tree

6 files changed

+152
-7
lines changed

6 files changed

+152
-7
lines changed

QueryBuilder.Tests/GeneralTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,5 +401,39 @@ public void Where_Nested()
401401

402402
Assert.Equal("SELECT * FROM [table] WHERE ([a] = 1 OR [a] = 2)", c[EngineCodes.SqlServer].ToString());
403403
}
404+
405+
[Fact]
406+
public void UnsafeLiteral_Insert()
407+
{
408+
var query = new Query("Table").AsInsert(new
409+
{
410+
Count = new UnsafeLiteral("Count + 1")
411+
});
412+
413+
var engines = new[] {
414+
EngineCodes.SqlServer,
415+
};
416+
417+
var c = Compilers.Compile(engines, query);
418+
419+
Assert.Equal("INSERT INTO [Table] ([Count]) VALUES (Count + 1)", c[EngineCodes.SqlServer].ToString());
420+
}
421+
422+
[Fact]
423+
public void UnsafeLiteral_Update()
424+
{
425+
var query = new Query("Table").AsUpdate(new
426+
{
427+
Count = new UnsafeLiteral("Count + 1")
428+
});
429+
430+
var engines = new[] {
431+
EngineCodes.SqlServer,
432+
};
433+
434+
var c = Compilers.Compile(engines, query);
435+
436+
Assert.Equal("UPDATE [Table] SET [Count] = Count + 1", c[EngineCodes.SqlServer].ToString());
437+
}
404438
}
405439
}

QueryBuilder.Tests/UpdateTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,5 +283,37 @@ public void UpdateUsingExpandoObject()
283283
"UPDATE [Table] SET [Name] = 'The User', [Age] = '2018-01-01'",
284284
c[EngineCodes.SqlServer]);
285285
}
286+
287+
[Fact]
288+
public void IncrementUpdate()
289+
{
290+
var query = new Query("Table").AsIncrement("Total");
291+
var c = Compile(query);
292+
Assert.Equal("UPDATE [Table] SET [Total] = [Total] + 1", c[EngineCodes.SqlServer]);
293+
}
294+
295+
[Fact]
296+
public void IncrementUpdateWithValue()
297+
{
298+
var query = new Query("Table").AsIncrement("Total", 2);
299+
var c = Compile(query);
300+
Assert.Equal("UPDATE [Table] SET [Total] = [Total] + 2", c[EngineCodes.SqlServer]);
301+
}
302+
303+
[Fact]
304+
public void IncrementUpdateWithWheres()
305+
{
306+
var query = new Query("Table").Where("Name", "A").AsIncrement("Total", 2);
307+
var c = Compile(query);
308+
Assert.Equal("UPDATE [Table] SET [Total] = [Total] + 2 WHERE [Name] = 'A'", c[EngineCodes.SqlServer]);
309+
}
310+
311+
[Fact]
312+
public void DecrementUpdate()
313+
{
314+
var query = new Query("Table").Where("Name", "A").AsDecrement("Total", 2);
315+
var c = Compile(query);
316+
Assert.Equal("UPDATE [Table] SET [Total] = [Total] - 2 WHERE [Name] = 'A'", c[EngineCodes.SqlServer]);
317+
}
286318
}
287319
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace SqlKata
2+
{
3+
public class IncrementClause : InsertClause
4+
{
5+
public string Column { get; set; }
6+
public int Value { get; set; } = 1;
7+
8+
public override AbstractClause Clone()
9+
{
10+
return new IncrementClause
11+
{
12+
Engine = Engine,
13+
Component = Component,
14+
Column = Column,
15+
Value = Value
16+
};
17+
}
18+
}
19+
}

QueryBuilder/Compilers/Compiler.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -285,25 +285,48 @@ protected virtual SqlResult CompileUpdateQuery(Query query)
285285
throw new InvalidOperationException("Invalid table expression");
286286
}
287287

288-
var toUpdate = ctx.Query.GetOneComponent<InsertClause>("update", EngineCode);
288+
// check for increment statements
289+
var clause = ctx.Query.GetOneComponent("update", EngineCode);
290+
291+
string wheres;
292+
293+
if (clause != null && clause is IncrementClause increment)
294+
{
295+
var column = Wrap(increment.Column);
296+
var value = Parameter(ctx, Math.Abs(increment.Value));
297+
var sign = increment.Value >= 0 ? "+" : "-";
298+
299+
wheres = CompileWheres(ctx);
289300

301+
if (!string.IsNullOrEmpty(wheres))
302+
{
303+
wheres = " " + wheres;
304+
}
305+
306+
ctx.RawSql = $"UPDATE {table} SET {column} = {column} {sign} {value}{wheres}";
307+
308+
return ctx;
309+
}
310+
311+
312+
var toUpdate = ctx.Query.GetOneComponent<InsertClause>("update", EngineCode);
290313
var parts = new List<string>();
291314

292315
for (var i = 0; i < toUpdate.Columns.Count; i++)
293316
{
294317
parts.Add(Wrap(toUpdate.Columns[i]) + " = " + Parameter(ctx, toUpdate.Values[i]));
295318
}
296319

297-
var where = CompileWheres(ctx);
320+
var sets = string.Join(", ", parts);
298321

299-
if (!string.IsNullOrEmpty(where))
322+
wheres = CompileWheres(ctx);
323+
324+
if (!string.IsNullOrEmpty(wheres))
300325
{
301-
where = " " + where;
326+
wheres = " " + wheres;
302327
}
303328

304-
var sets = string.Join(", ", parts);
305-
306-
ctx.RawSql = $"UPDATE {table} SET {sets}{where}";
329+
ctx.RawSql = $"UPDATE {table} SET {sets}{wheres}";
307330

308331
return ctx;
309332
}

QueryBuilder/Query.Update.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,22 @@ public Query AsUpdate(IEnumerable<KeyValuePair<string, object>> values)
5454

5555
return this;
5656
}
57+
58+
public Query AsIncrement(string column, int value = 1)
59+
{
60+
Method = "update";
61+
AddOrReplaceComponent("update", new IncrementClause
62+
{
63+
Column = column,
64+
Value = value
65+
});
66+
67+
return this;
68+
}
69+
70+
public Query AsDecrement(string column, int value = 1)
71+
{
72+
return AsIncrement(column, -value);
73+
}
5774
}
5875
}

SqlKata.Execution/Query.Extensions.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,26 @@ public static async Task<int> UpdateAsync(this Query query, object data, IDbTran
245245
return await CreateQueryFactory(query).ExecuteAsync(query.AsUpdate(data), transaction, timeout, cancellationToken);
246246
}
247247

248+
public static int Increment(this Query query, string column, int value = 1, IDbTransaction transaction = null, int? timeout = null)
249+
{
250+
return CreateQueryFactory(query).Execute(query.AsIncrement(column, value), transaction, timeout);
251+
}
252+
253+
public static async Task<int> IncrementAsync(this Query query, string column, int value = 1, IDbTransaction transaction = null, int? timeout = null, CancellationToken cancellationToken = default)
254+
{
255+
return await CreateQueryFactory(query).ExecuteAsync(query.AsIncrement(column, value), transaction, timeout, cancellationToken);
256+
}
257+
258+
public static int Decrement(this Query query, string column, int value = 1, IDbTransaction transaction = null, int? timeout = null)
259+
{
260+
return CreateQueryFactory(query).Execute(query.AsDecrement(column, value), transaction, timeout);
261+
}
262+
263+
public static async Task<int> DecrementAsync(this Query query, string column, int value = 1, IDbTransaction transaction = null, int? timeout = null, CancellationToken cancellationToken = default)
264+
{
265+
return await CreateQueryFactory(query).ExecuteAsync(query.AsDecrement(column, value), transaction, timeout, cancellationToken);
266+
}
267+
248268
public static int Delete(this Query query, IDbTransaction transaction = null, int? timeout = null)
249269
{
250270
return CreateQueryFactory(query).Execute(query.AsDelete(), transaction, timeout);

0 commit comments

Comments
 (0)