Skip to content

Commit 056e613

Browse files
little cleaning
1 parent e225c73 commit 056e613

File tree

10 files changed

+89
-85
lines changed

10 files changed

+89
-85
lines changed

QueryBuilder/ColumnAttribute.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public ColumnAttribute(string name)
1414
{
1515
throw new ArgumentNullException("Name parameter is required");
1616
}
17+
1718
Name = name;
1819
}
1920

QueryBuilder/Compilers/Compiler.Conditions.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ protected virtual string CompileCondition(SqlResult ctx, AbstractCondition claus
2626

2727
try
2828
{
29-
var result = methodInfo.Invoke(this, new object[] { ctx, clause });
29+
30+
var result = methodInfo.Invoke(this, new object[] {
31+
ctx,
32+
clause
33+
});
34+
3035
return result as string;
3136
}
3237
catch (Exception ex)

QueryBuilder/Compilers/Compiler.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public partial class Compiler
99
{
1010
private readonly ConditionsCompilerProvider _compileConditionMethodsProvider;
1111
protected virtual string parameterPlaceholder { get; set; } = "?";
12-
protected virtual string parameterPlaceholderPrefix { get; set; } = "@p";
12+
protected virtual string parameterPrefix { get; set; } = "@p";
1313
protected virtual string OpeningIdentifier { get; set; } = "\"";
1414
protected virtual string ClosingIdentifier { get; set; } = "\"";
1515
protected virtual string ColumnAsKeyword { get; set; } = "AS ";
@@ -48,13 +48,13 @@ protected Compiler()
4848
protected Dictionary<string, object> generateNamedBindings(object[] bindings)
4949
{
5050
return Helper.Flatten(bindings).Select((v, i) => new { i, v })
51-
.ToDictionary(x => parameterPlaceholderPrefix + x.i, x => x.v);
51+
.ToDictionary(x => parameterPrefix + x.i, x => x.v);
5252
}
5353

5454
protected SqlResult PrepareResult(SqlResult ctx)
5555
{
5656
ctx.NamedBindings = generateNamedBindings(ctx.Bindings.ToArray());
57-
ctx.Sql = Helper.ReplaceAll(ctx.RawSql, parameterPlaceholder, i => parameterPlaceholderPrefix + i);
57+
ctx.Sql = Helper.ReplaceAll(ctx.RawSql, parameterPlaceholder, i => parameterPrefix + i);
5858
return ctx;
5959
}
6060

@@ -79,7 +79,7 @@ private Query TransformAggregateQuery(Query query)
7979

8080
var outerClause = new AggregateClause()
8181
{
82-
Columns = new List<string> {"*"},
82+
Columns = new List<string> { "*" },
8383
Type = clause.Type
8484
};
8585

@@ -129,6 +129,13 @@ protected virtual SqlResult CompileRaw(Query query)
129129
return ctx;
130130
}
131131

132+
/// <summary>
133+
/// Add the passed operator(s) to the white list so they can be used with
134+
/// the Where/Having methods, this prevent passing arbitrary operators
135+
/// that opens the door for SQL injections.
136+
/// </summary>
137+
/// <param name="operators"></param>
138+
/// <returns></returns>
132139
public Compiler Whitelist(params string[] operators)
133140
{
134141
foreach (var op in operators)
@@ -300,9 +307,10 @@ protected virtual SqlResult CompileInsertQuery(Query query)
300307

301308
if (inserts[0] is InsertClause insertClause)
302309
{
303-
ctx.RawSql = $"INSERT INTO {table}"
304-
+ " (" + string.Join(", ", WrapArray(insertClause.Columns)) + ") "
305-
+ "VALUES (" + string.Join(", ", Parameterize(ctx, insertClause.Values)) + ")";
310+
var columns = string.Join(", ", WrapArray(insertClause.Columns));
311+
var values = string.Join(", ", Parameterize(ctx, insertClause.Values));
312+
313+
ctx.RawSql = $"INSERT INTO {table} ({columns}) VALUES ({values})";
306314

307315
if (insertClause.ReturnId && !string.IsNullOrEmpty(LastId))
308316
{
@@ -817,11 +825,11 @@ public virtual string WrapIdentifiers(string input)
817825
return input
818826

819827
// deprecated
820-
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"{", this.OpeningIdentifier)
821-
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"}", this.ClosingIdentifier)
828+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter, "{", this.OpeningIdentifier)
829+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter, "}", this.ClosingIdentifier)
822830

823-
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"[", this.OpeningIdentifier)
824-
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"]", this.ClosingIdentifier);
831+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter, "[", this.OpeningIdentifier)
832+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter, "]", this.ClosingIdentifier);
825833
}
826834
}
827835
}

QueryBuilder/Compilers/CteFinder.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class CteFinder
88
private readonly string engineCode;
99
private HashSet<string> namesOfPreviousCtes;
1010
private List<AbstractFrom> orderedCteList;
11-
11+
1212
public CteFinder(Query query, string engineCode)
1313
{
1414
this.query = query;
@@ -21,21 +21,21 @@ public List<AbstractFrom> Find()
2121
return orderedCteList;
2222

2323
namesOfPreviousCtes = new HashSet<string>();
24-
25-
orderedCteList = FindInternal(query);
26-
24+
25+
orderedCteList = findInternal(query);
26+
2727
namesOfPreviousCtes.Clear();
2828
namesOfPreviousCtes = null;
2929

3030
return orderedCteList;
3131
}
3232

33-
private List<AbstractFrom> FindInternal(Query queryToSearch)
33+
private List<AbstractFrom> findInternal(Query queryToSearch)
3434
{
3535
var cteList = queryToSearch.GetComponents<AbstractFrom>("cte", engineCode);
3636

3737
var resultList = new List<AbstractFrom>();
38-
38+
3939
foreach (var cte in cteList)
4040
{
4141
if (namesOfPreviousCtes.Contains(cte.Alias))
@@ -46,7 +46,7 @@ private List<AbstractFrom> FindInternal(Query queryToSearch)
4646

4747
if (cte is QueryFromClause queryFromClause)
4848
{
49-
resultList.InsertRange(0, FindInternal(queryFromClause.Query));
49+
resultList.InsertRange(0, findInternal(queryFromClause.Query));
5050
}
5151
}
5252

QueryBuilder/Compilers/OracleCompiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public OracleCompiler()
99
{
1010
ColumnAsKeyword = "";
1111
TableAsKeyword = "";
12-
parameterPlaceholderPrefix = ":p";
12+
parameterPrefix = ":p";
1313
}
1414

1515
public override string EngineCode { get; } = EngineCodes.Oracle;

QueryBuilder/Compilers/SqliteCompiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class SqliteCompiler : Compiler
88
{
99
public override string EngineCode { get; } = EngineCodes.Sqlite;
1010
protected override string parameterPlaceholder { get; set; } = "?";
11-
protected override string parameterPlaceholderPrefix { get; set; } = "@p";
11+
protected override string parameterPrefix { get; set; } = "@p";
1212
protected override string OpeningIdentifier { get; set; } = "\"";
1313
protected override string ClosingIdentifier { get; set; } = "\"";
1414
protected override string LastId { get; set; } = "select last_insert_rowid()";

QueryBuilder/IgnoreAttribute.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,22 @@
33
namespace SqlKata
44
{
55
/// <summary>
6-
/// This class is used as metadata to ignore a property on an object in order to exclude it from query
6+
/// This class is used as metadata to ignore a property on insert and update queries
77
/// </summary>
88
/// <example>
99
/// <code>
10-
/// public class Person
11-
/// {
10+
/// public class Person
11+
/// {
1212
/// public string Name {get ;set;}
13+
///
1314
/// [Ignore]
1415
/// public string PhoneNumber {get ;set;}
1516
///
1617
/// }
1718
///
18-
/// output: SELECT [Name] FROM [Person]
19+
/// new Query("Table").Insert(new Person { Name = "User", PhoneNumber = "70123456" })
20+
///
21+
/// output: INSERT INTO [Table] ([Name]) VALUES('User')
1922
/// </code>
2023
/// </example>
2124
public class IgnoreAttribute : Attribute

QueryBuilder/Query.Insert.cs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,11 @@ public partial class Query
99
{
1010
public Query AsInsert(object data, bool returnId = false)
1111
{
12-
var dictionary = BuildDictionaryOnInsert(data);
12+
var dictionary = BuildDictionaryFromObject(data);
1313

1414
return AsInsert(dictionary, returnId);
1515
}
1616

17-
18-
private Dictionary<string, object> BuildDictionaryOnInsert(object data)
19-
{
20-
21-
var dictionary = new Dictionary<string, object>();
22-
var props = data.GetType().GetRuntimeProperties();
23-
24-
foreach (PropertyInfo property in props)
25-
{
26-
if (property.GetCustomAttribute(typeof(IgnoreAttribute)) != null)
27-
{
28-
continue;
29-
}
30-
31-
var value = property.GetValue(data);
32-
33-
var colAttr = property.GetCustomAttribute(typeof(ColumnAttribute)) as ColumnAttribute;
34-
var name = colAttr?.Name ?? property.Name;
35-
36-
dictionary.Add(name, value);
37-
}
38-
39-
return dictionary;
40-
}
41-
4217
public Query AsInsert(IEnumerable<string> columns, IEnumerable<object> values)
4318
{
4419
var columnsList = columns?.ToList();

QueryBuilder/Query.Update.cs

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,9 @@ public partial class Query
1111

1212
public Query AsUpdate(object data)
1313
{
14-
var dictionary = BuildDictionaryOnUpdate(data);
15-
return AsUpdate(dictionary);
16-
}
17-
18-
19-
private static Dictionary<Type, List<PropertyInfo>> CacheDictionaryProperties = new Dictionary<Type, List<PropertyInfo>>();
20-
21-
22-
private Dictionary<string, object> BuildDictionaryOnUpdate(object data)
23-
{
24-
25-
var dictionary = new Dictionary<string, object>();
26-
var props = data.GetType().GetRuntimeProperties();
27-
28-
foreach (PropertyInfo property in props)
29-
{
30-
if (property.GetCustomAttribute(typeof(IgnoreAttribute)) != null){
31-
continue;
32-
}
33-
34-
var value = property.GetValue(data);
35-
36-
var colAttr = property.GetCustomAttribute(typeof(ColumnAttribute)) as ColumnAttribute;
37-
var name = colAttr?.Name ?? property.Name;
38-
if(colAttr != null)
39-
{
40-
if((colAttr as KeyAttribute) != null)
41-
{
42-
this.Where(name, value);
43-
}
44-
}
45-
dictionary.Add(name, value);
46-
}
14+
var dictionary = BuildDictionaryFromObject(data, considerKeys: true);
4715

48-
return dictionary;
16+
return AsUpdate(dictionary);
4917
}
5018

5119
public Query AsUpdate(IEnumerable<string> columns, IEnumerable<object> values)

QueryBuilder/Query.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Reflection;
45

56
namespace SqlKata
67
{
@@ -310,5 +311,48 @@ public Query IncludeMany(string relationName, Query query, string foreignKey = n
310311
return Include(relationName, query, foreignKey, localKey, isMany: true);
311312
}
312313

314+
/// <summary>
315+
/// Build a dictionary from plain object, intended to be used with Insert and Update queries
316+
/// </summary>
317+
/// <param name="data">the plain C# object</param>
318+
/// <param name="considerKeys">
319+
/// When true it will search for properties with the [Key] attribute
320+
/// and add it automatically to the Where clause
321+
/// </param>
322+
/// <returns></returns>
323+
private Dictionary<string, object> BuildDictionaryFromObject(object data, bool considerKeys = false)
324+
{
325+
326+
var dictionary = new Dictionary<string, object>();
327+
var props = data.GetType().GetRuntimeProperties();
328+
329+
foreach (var property in props)
330+
{
331+
if (property.GetCustomAttribute(typeof(IgnoreAttribute)) != null)
332+
{
333+
continue;
334+
}
335+
336+
var value = property.GetValue(data);
337+
338+
var colAttr = property.GetCustomAttribute(typeof(ColumnAttribute)) as ColumnAttribute;
339+
340+
var name = colAttr?.Name ?? property.Name;
341+
342+
dictionary.Add(name, value);
343+
344+
if (considerKeys && colAttr != null)
345+
{
346+
if ((colAttr as KeyAttribute) != null)
347+
{
348+
this.Where(name, value);
349+
}
350+
}
351+
352+
}
353+
354+
return dictionary;
355+
}
356+
313357
}
314358
}

0 commit comments

Comments
 (0)