diff --git a/src/Searchlight/Exceptions/InvalidEngineSetting.cs b/src/Searchlight/Exceptions/InvalidEngineSetting.cs
new file mode 100644
index 0000000..b887489
--- /dev/null
+++ b/src/Searchlight/Exceptions/InvalidEngineSetting.cs
@@ -0,0 +1,27 @@
+namespace Searchlight.Exceptions
+{
+ ///
+ /// Exception to be thrown if the SearchlightEngine was configured incorrectly
+ ///
+ public class InvalidEngineSetting : SearchlightException
+ {
+ public string OriginalFilter { get; internal set; }
+
+ ///
+ /// Fields that are missing or incorrect
+ ///
+ public string[] Fields { get; set; }
+
+ public string ErrorMessage =>
+ $"These fields are either missing or are set incorrectly: {string.Join(",", Fields)}";
+
+ ///
+ /// Constructor
+ ///
+ ///
+ public InvalidEngineSetting(params string[] fields)
+ {
+ Fields = fields;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Searchlight/LinqExecutor.cs b/src/Searchlight/LinqExecutor.cs
index 4e16b9d..d9df3a1 100644
--- a/src/Searchlight/LinqExecutor.cs
+++ b/src/Searchlight/LinqExecutor.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using System.Runtime.CompilerServices;
using Searchlight.Parsing;
using Searchlight.Query;
@@ -149,6 +150,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
Expression field;
Expression value;
Expression result;
+ var comparison = src?.Engine?.StringComparison ?? StringComparison.OrdinalIgnoreCase;
var t = typeof(T);
@@ -179,7 +181,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
// ReSharper disable once AssignNullToNotNullAttribute
typeof(string).GetMethod("Equals",
new [] { typeof(string), typeof(string), typeof(StringComparison) }),
- field, value, Expression.Constant(StringComparison.OrdinalIgnoreCase));
+ field, value, Expression.Constant(comparison));
}
else
{
@@ -197,7 +199,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
{
typeof(string), typeof(string), typeof(StringComparison)
}),
- field, value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ field, value, Expression.Constant(comparison)),
Expression.Constant(0)));
}
else
@@ -216,7 +218,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
{
typeof(string), typeof(string), typeof(StringComparison)
}),
- field, value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ field, value, Expression.Constant(comparison)),
Expression.Constant(0)));
}
else
@@ -235,7 +237,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
{
typeof(string), typeof(string), typeof(StringComparison)
}),
- field, value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ field, value, Expression.Constant(comparison)),
Expression.Constant(0)));
}
else
@@ -254,7 +256,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
{
typeof(string), typeof(string), typeof(StringComparison)
}),
- field, value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ field, value, Expression.Constant(comparison)),
Expression.Constant(0)));
}
else
@@ -268,7 +270,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
// ReSharper disable once AssignNullToNotNullAttribute
typeof(string).GetMethod("StartsWith",
new [] { typeof(string), typeof(StringComparison) }),
- value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ value, Expression.Constant(comparison)),
Expression.MakeCatchBlock(typeof(Exception), null,
Expression.Constant(false, typeof(Boolean)), null)
);
@@ -280,7 +282,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
// ReSharper disable once AssignNullToNotNullAttribute
typeof(string).GetMethod("EndsWith",
new [] { typeof(string), typeof(StringComparison) }),
- value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ value, Expression.Constant(comparison)),
Expression.MakeCatchBlock(typeof(Exception), null,
Expression.Constant(false, typeof(Boolean)), null)
);
@@ -291,7 +293,7 @@ private static Expression BuildOneExpression(ParameterExpression select, Base
// ReSharper disable once AssignNullToNotNullAttribute
typeof(string).GetMethod("Contains",
new [] { typeof(string), typeof(StringComparison) }),
- value, Expression.Constant(StringComparison.OrdinalIgnoreCase)),
+ value, Expression.Constant(comparison)),
Expression.MakeCatchBlock(typeof(Exception), null,
Expression.Constant(false, typeof(Boolean)), null)
);
diff --git a/src/Searchlight/SearchlightEngine.cs b/src/Searchlight/SearchlightEngine.cs
index 24adce6..d19c01c 100644
--- a/src/Searchlight/SearchlightEngine.cs
+++ b/src/Searchlight/SearchlightEngine.cs
@@ -65,6 +65,23 @@ public class SearchlightEngine
///
public bool useNoCount { get; set; } = true;
+ ///
+ /// Whether or not to use case sensitive comparisons
+ ///
+ /// Note: Odd numbers in the StringComparison enum are case insensitive
+ ///
+ public bool CaseSensitiveComparison => (int)StringComparison % 2 == 0;
+
+ ///
+ /// The string comparison for the engine
+ ///
+ public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;
+
+ ///
+ /// The collation to use for case sensitive comparisons, must be specified for SQL Server
+ ///
+ public string Collation { get; set; } = string.Empty;
+
///
/// Adds a new class to the engine
///
diff --git a/src/Searchlight/SqlExecutor.cs b/src/Searchlight/SqlExecutor.cs
index e1eafb5..6b2c671 100644
--- a/src/Searchlight/SqlExecutor.cs
+++ b/src/Searchlight/SqlExecutor.cs
@@ -62,7 +62,7 @@ public static SqlQuery ToPostgresCommand(this SyntaxTree query)
private static SqlQuery CreateSql(SqlDialect dialect, SyntaxTree query, SearchlightEngine engine)
{
var sql = new SqlQuery() { Syntax = query };
- sql.WhereClause = RenderJoinedClauses(dialect, query.Filter, sql);
+ sql.WhereClause = RenderJoinedClauses(dialect, query.Filter, sql, engine);
sql.OrderByClause = RenderOrderByClause(query.OrderBy);
// Sanity test - is the query too complicated to be safe to run?
@@ -171,8 +171,9 @@ private static string RenderOrderByClause(List list)
///
///
///
+ ///
///
- private static string RenderJoinedClauses(SqlDialect dialect, List clause, SqlQuery sql)
+ private static string RenderJoinedClauses(SqlDialect dialect, List clause, SqlQuery sql, SearchlightEngine engine)
{
var sb = new StringBuilder();
for (var i = 0; i < clause.Count; i++)
@@ -193,7 +194,7 @@ private static string RenderJoinedClauses(SqlDialect dialect, List c
}
}
- sb.Append(RenderClause(dialect, clause[i], sql));
+ sb.Append(RenderClause(dialect, clause[i], sql, engine));
}
return sb.ToString();
@@ -205,9 +206,10 @@ private static string RenderJoinedClauses(SqlDialect dialect, List c
///
///
///
+ ///
///
///
- private static string RenderClause(SqlDialect dialect, BaseClause clause, SqlQuery sql)
+ private static string RenderClause(SqlDialect dialect, BaseClause clause, SqlQuery sql, SearchlightEngine engine)
{
switch (clause)
{
@@ -215,7 +217,7 @@ private static string RenderClause(SqlDialect dialect, BaseClause clause, SqlQue
return
$"{bc.Column.OriginalName} {(bc.Negated ? "NOT " : "")}BETWEEN {sql.AddParameter(bc.LowerValue.GetValue(), bc.Column.FieldType)} AND {sql.AddParameter(bc.UpperValue.GetValue(), bc.Column.FieldType)}";
case CompoundClause compoundClause:
- return $"({RenderJoinedClauses(dialect, compoundClause.Children, sql)})";
+ return $"({RenderJoinedClauses(dialect, compoundClause.Children, sql, engine)})";
case CriteriaClause cc:
var rawValue = cc.Value.GetValue();
switch (cc.Operation)
@@ -226,7 +228,8 @@ private static string RenderClause(SqlDialect dialect, BaseClause clause, SqlQue
case OperationType.LessThan:
case OperationType.LessThanOrEqual:
case OperationType.NotEqual:
- return RenderComparisonClause(cc.Column.OriginalName, cc.Negated, cc.Operation, sql.AddParameter(rawValue, cc.Column.FieldType));
+ return RenderComparisonClause(dialect, cc,
+ sql.AddParameter(rawValue, cc.Column.FieldType), engine);
case OperationType.Contains:
return RenderLikeClause(dialect, cc, sql, rawValue, "%", "%");
case OperationType.StartsWith:
@@ -257,15 +260,51 @@ private static string RenderClause(SqlDialect dialect, BaseClause clause, SqlQue
{ OperationType.GreaterThanOrEqual, new Tuple(">=", "<") },
};
- private static string RenderComparisonClause(string column, bool negated, OperationType op, string parameter)
+ private static string RenderComparisonClause(SqlDialect dialect, CriteriaClause cc, string parameter, SearchlightEngine engine)
{
+ var op = cc.Operation;
+ var negated = cc.Negated;
+ var column = cc.Column.OriginalName;
+ var fieldType = cc.Column.FieldType;
+
if (!CanonicalOps.TryGetValue(op, out var opstrings))
{
throw new Exception($"Invalid comparison type {op}");
}
var operationSymbol = negated ? opstrings.Item2 : opstrings.Item1;
- return $"{column} {operationSymbol} {parameter}";
+
+ if (engine.CaseSensitiveComparison)
+ {
+ switch (dialect)
+ {
+ case SqlDialect.MicrosoftSqlServer:
+ if (string.IsNullOrEmpty(engine.Collation))
+ {
+ throw new InvalidEngineSetting(nameof(SearchlightEngine.Collation));
+ }
+
+ return $"{column} {operationSymbol} {parameter} COLLATE {engine.Collation}";
+ case SqlDialect.MySql:
+ return $"{column} {operationSymbol} BINARY {parameter}";
+ case SqlDialect.PostgreSql:
+ default:
+ return $"{column} {operationSymbol} {parameter}";
+ }
+ }
+
+ // Case insensitive comparison
+ switch (dialect)
+ {
+ case SqlDialect.PostgreSql:
+ return fieldType == typeof(string)
+ ? $"LOWER({column}) {operationSymbol} LOWER({parameter})"
+ : $"{column} {operationSymbol} {parameter}";
+ case SqlDialect.MySql:
+ case SqlDialect.MicrosoftSqlServer:
+ default:
+ return $"{column} {operationSymbol} {parameter}";
+ }
}
private static string RenderLikeClause(SqlDialect dialect, CriteriaClause clause, SqlQuery sql, object rawValue,
@@ -285,8 +324,29 @@ private static string RenderLikeClause(SqlDialect dialect, CriteriaClause clause
var escapeCommand = dialect == SqlDialect.MicrosoftSqlServer ? " ESCAPE '\\'" : string.Empty;
var notCommand = clause.Negated ? "NOT " : "";
var likeValue = prefix + EscapeLikeValue(stringValue) + suffix;
- return
- $"{clause.Column.OriginalName} {notCommand}{likeCommand} {sql.AddParameter(likeValue, clause.Column.FieldType)}{escapeCommand}";
+
+ if (!(sql.Syntax?.Source?.Engine?.CaseSensitiveComparison ?? false))
+ return
+ $"{clause.Column.OriginalName} {notCommand}{likeCommand} {sql.AddParameter(likeValue, clause.Column.FieldType)}{escapeCommand}";
+
+ switch (dialect)
+ {
+ case SqlDialect.MySql:
+ return
+ $"{clause.Column.OriginalName} {notCommand}{likeCommand} BINARY {sql.AddParameter(likeValue, clause.Column.FieldType)}{escapeCommand}";
+ case SqlDialect.MicrosoftSqlServer:
+ if (string.IsNullOrEmpty(sql.Syntax?.Source?.Engine?.Collation))
+ {
+ throw new InvalidEngineSetting(nameof(SearchlightEngine.Collation));
+ }
+
+ return
+ $"{clause.Column.OriginalName} {notCommand}{likeCommand} {sql.AddParameter(likeValue, clause.Column.FieldType)}{escapeCommand} COLLATE {sql.Syntax.Source.Engine.Collation}";
+ case SqlDialect.PostgreSql:
+ default:
+ return
+ $"{clause.Column.OriginalName} {notCommand}{likeCommand} {sql.AddParameter(likeValue, clause.Column.FieldType)}{escapeCommand}";
+ }
}
private static string EscapeLikeValue(string stringValue)
diff --git a/tests/Searchlight.Tests/Executors/EmployeeTestSuite.cs b/tests/Searchlight.Tests/Executors/EmployeeTestSuite.cs
index 0db1654..635be0a 100644
--- a/tests/Searchlight.Tests/Executors/EmployeeTestSuite.cs
+++ b/tests/Searchlight.Tests/Executors/EmployeeTestSuite.cs
@@ -16,6 +16,7 @@ public class EmployeeTestSuite
private readonly DataSource _src;
private readonly List _list;
private readonly Func>> _executor;
+ private readonly StringComparison _comparison;
private EmployeeTestSuite(DataSource src, List list,
Func>> executor)
@@ -23,6 +24,7 @@ private EmployeeTestSuite(DataSource src, List list,
_src = src;
_list = list;
_executor = executor;
+ _comparison = src?.Engine?.StringComparison ?? StringComparison.OrdinalIgnoreCase;
}
///
@@ -75,6 +77,23 @@ public static async Task CaseInsensitiveStringTestSuite(DataSource src, List
+ /// Validates correctness of this executor's ability to execute case insensitive string comparisons
+ ///
+ ///
+ ///
+ ///
+ public static async Task CaseSensitiveStringTestSuite(DataSource src, List list,
+ Func>> executor)
+ {
+ var suite = new EmployeeTestSuite(src, list, executor);
+ await suite.LessThanOrEqualQuery(true);
+ await suite.LessThanQuery(true);
+ await suite.GreaterThanQuery(true);
+ await suite.GreaterThanOrEqualQuery(true);
+ await suite.StringEqualsCaseSensitive();
+ }
private async Task QueryListCollection()
{
@@ -200,7 +219,7 @@ private async Task EndsWithQuery()
Assert.AreEqual(2, results.records.Length);
foreach (var e in results.records)
{
- Assert.IsTrue(e.name.EndsWith("s", StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(e.name.EndsWith("s", _comparison));
}
}
@@ -219,7 +238,7 @@ private async Task ContainsQuery()
Assert.AreEqual(9, results.records.Length);
foreach (var e in results.records)
{
- Assert.IsTrue(e != null && e.name.Contains('s', StringComparison.OrdinalIgnoreCase));
+ Assert.IsTrue(e != null && e.name.Contains('s', _comparison));
}
// Now test the opposite
@@ -229,7 +248,7 @@ private async Task ContainsQuery()
foreach (var e in results.records)
{
Assert.IsTrue(
- e != null && (e.name == null || !e.name.Contains('s', StringComparison.OrdinalIgnoreCase)));
+ e != null && (e.name == null || !e.name.Contains('s', _comparison)));
}
// Test for the presence of special characters that might cause problems for parsing
@@ -242,77 +261,81 @@ private async Task ContainsQuery()
}
}
- private async Task GreaterThanQuery()
+ private async Task GreaterThanQuery(bool caseSensitive = false)
{
- var syntax = _src.ParseFilter("name gt 'b'");
+ var parameter = caseSensitive ? "B" : "b";
+ var syntax = _src.ParseFilter($"name gt '{parameter}'");
Assert.AreEqual(1, syntax.Filter.Count);
Assert.AreEqual(ConjunctionType.NONE, syntax.Filter[0].Conjunction);
Assert.AreEqual("name", ((CriteriaClause)syntax.Filter[0]).Column.FieldName);
Assert.AreEqual(OperationType.GreaterThan, ((CriteriaClause)syntax.Filter[0]).Operation);
- Assert.AreEqual("b", ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
+ Assert.AreEqual(parameter, ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
// Execute the query and ensure that each result matches
var results = await _executor(syntax);
Assert.AreEqual(8, results.records.Length);
foreach (var e in results.records)
{
- Assert.IsTrue(string.Compare(e.name, "b", StringComparison.CurrentCultureIgnoreCase) > 0);
+ Assert.IsTrue(string.Compare(e.name, parameter, _comparison) > 0);
}
}
-
- private async Task GreaterThanOrEqualQuery()
+
+ private async Task GreaterThanOrEqualQuery(bool caseSensitive = false)
{
- var syntax = _src.ParseFilter("name ge 'bob rogers'");
+ var parameter = caseSensitive ? "Bob Rogers" : "bob rogers";
+ var syntax = _src.ParseFilter($"name ge '{parameter}'");
Assert.AreEqual(1, syntax.Filter.Count);
Assert.AreEqual(ConjunctionType.NONE, syntax.Filter[0].Conjunction);
Assert.AreEqual("name", ((CriteriaClause)syntax.Filter[0]).Column.FieldName);
Assert.AreEqual(OperationType.GreaterThanOrEqual, ((CriteriaClause)syntax.Filter[0]).Operation);
- Assert.AreEqual("bob rogers", ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
+ Assert.AreEqual(parameter, ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
// Execute the query and ensure that each result matches
var results = await _executor(syntax);
Assert.AreEqual(7, results.records.Length);
foreach (var e in results.records)
{
- Assert.IsTrue(string.Compare(e.name[.."bob rogers".Length], "bob rogers",
- StringComparison.CurrentCultureIgnoreCase) >= 0);
+ Assert.IsTrue(string.Compare(e.name[..parameter.Length], parameter,
+ _comparison) >= 0);
}
}
- private async Task LessThanQuery()
+ private async Task LessThanQuery(bool caseSensitive = false)
{
- var syntax = _src.ParseFilter("name lt 'b'");
+ var parameter = caseSensitive ? "B" : "b";
+ var syntax = _src.ParseFilter($"name lt '{parameter}'");
Assert.AreEqual(1, syntax.Filter.Count);
Assert.AreEqual(ConjunctionType.NONE, syntax.Filter[0].Conjunction);
Assert.AreEqual("name", ((CriteriaClause)syntax.Filter[0]).Column.FieldName);
Assert.AreEqual(OperationType.LessThan, ((CriteriaClause)syntax.Filter[0]).Operation);
- Assert.AreEqual("b", ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
+ Assert.AreEqual(parameter, ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
// Execute the query and ensure that each result matches
var results = await _executor(syntax);
Assert.AreEqual(1, results.records.Length);
foreach (var e in results.records)
{
- Assert.IsTrue(string.Compare(e.name, "b", StringComparison.CurrentCultureIgnoreCase) < 0);
+ Assert.IsTrue(string.Compare(e.name, parameter, _comparison) < 0);
}
}
- private async Task LessThanOrEqualQuery()
+ private async Task LessThanOrEqualQuery(bool caseSensitive = false)
{
- var syntax = _src.ParseFilter("name le 'bob rogers'");
+ var parameter = caseSensitive ? "Bob Rogers" : "bob rogers";
+ var syntax = _src.ParseFilter($"name le '{parameter}'");
Assert.AreEqual(1, syntax.Filter.Count);
Assert.AreEqual(ConjunctionType.NONE, syntax.Filter[0].Conjunction);
Assert.AreEqual("name", ((CriteriaClause)syntax.Filter[0]).Column.FieldName);
Assert.AreEqual(OperationType.LessThanOrEqual, ((CriteriaClause)syntax.Filter[0]).Operation);
- Assert.AreEqual("bob rogers", ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
+ Assert.AreEqual(parameter, ((CriteriaClause)syntax.Filter[0]).Value.GetValue());
// Execute the query and ensure that each result matches
var results = await _executor(syntax);
Assert.AreEqual(3, results.records.Length);
foreach (var e in results.records)
{
- Assert.IsTrue(string.Compare(e.name[.."bob rogers".Length], "bob rogers",
- StringComparison.CurrentCultureIgnoreCase) <= 0);
+ Assert.IsTrue(string.Compare(e.name[..parameter.Length], parameter,
+ _comparison) <= 0);
}
}
@@ -416,6 +439,22 @@ private async Task StringEqualsCaseInsensitive()
Assert.IsNotNull(result);
Assert.AreEqual(_list.Count - 1, result.records.Length);
}
+
+ private async Task StringEqualsCaseSensitive()
+ {
+ var syntax = _src.ParseFilter("name eq 'ALICE SMITH'");
+ var result = await _executor(syntax);
+
+ Assert.IsFalse(result.records.Any(p => p.name == "Alice Smith"));
+ Assert.IsNotNull(result);
+ Assert.AreEqual(0, result.records.Length);
+
+ syntax = _src.ParseFilter("name eq 'Alice Smith'");
+ result = await _executor(syntax);
+ Assert.IsTrue(result.records.Any(p => p.name == "Alice Smith"));
+ Assert.IsNotNull(result);
+ Assert.AreEqual(1, result.records.Length);
+ }
private async Task DefinedDateOperators()
{
diff --git a/tests/Searchlight.Tests/Executors/LinqExecutorTests.cs b/tests/Searchlight.Tests/Executors/LinqExecutorTests.cs
index c5d8738..4172d1c 100644
--- a/tests/Searchlight.Tests/Executors/LinqExecutorTests.cs
+++ b/tests/Searchlight.Tests/Executors/LinqExecutorTests.cs
@@ -39,7 +39,9 @@ public void SetupTests()
public async Task EmployeeTestSuite()
{
await Executors.EmployeeTestSuite.BasicTestSuite(_src, _list, _linq);
- await Executors.EmployeeTestSuite.CaseInsensitiveStringTestSuite(_src, _list, _linq);
+
+ _src.Engine = new SearchlightEngine { StringComparison = StringComparison.Ordinal };
+ await Executors.EmployeeTestSuite.CaseSensitiveStringTestSuite(_src, _list, _linq);
}
// =========================================================
diff --git a/tests/Searchlight.Tests/Executors/MysqlExecutorTests.cs b/tests/Searchlight.Tests/Executors/MysqlExecutorTests.cs
index 59b4fb3..c557ca7 100644
--- a/tests/Searchlight.Tests/Executors/MysqlExecutorTests.cs
+++ b/tests/Searchlight.Tests/Executors/MysqlExecutorTests.cs
@@ -118,5 +118,8 @@ public async Task Cleanup()
public async Task EmployeeTestSuite()
{
await Executors.EmployeeTestSuite.BasicTestSuite(_src, _list, _executor);
+
+ _src.Engine = new SearchlightEngine { StringComparison = StringComparison.Ordinal };
+ await Executors.EmployeeTestSuite.CaseSensitiveStringTestSuite(_src, _list, _executor);
}
}
\ No newline at end of file
diff --git a/tests/Searchlight.Tests/Executors/PostgresExecutorTests.cs b/tests/Searchlight.Tests/Executors/PostgresExecutorTests.cs
index c31d73d..5fc791a 100644
--- a/tests/Searchlight.Tests/Executors/PostgresExecutorTests.cs
+++ b/tests/Searchlight.Tests/Executors/PostgresExecutorTests.cs
@@ -146,5 +146,8 @@ public async Task Cleanup()
public async Task EmployeeTestSuite()
{
await Executors.EmployeeTestSuite.BasicTestSuite(_src, _list, _executor);
+
+ _src.Engine = new SearchlightEngine { StringComparison = StringComparison.Ordinal };
+ await Executors.EmployeeTestSuite.CaseSensitiveStringTestSuite(_src, _list, _executor);
}
}
\ No newline at end of file
diff --git a/tests/Searchlight.Tests/Executors/SqlServerExecutorTests.cs b/tests/Searchlight.Tests/Executors/SqlServerExecutorTests.cs
index c00de3a..72e7352 100644
--- a/tests/Searchlight.Tests/Executors/SqlServerExecutorTests.cs
+++ b/tests/Searchlight.Tests/Executors/SqlServerExecutorTests.cs
@@ -15,7 +15,7 @@ public class SqlServerExecutorTests
{
private DataSource _src;
private string _connectionString;
- private Func>> _postgres;
+ private Func>> _executor;
private List _list;
private MsSqlContainer _container;
@@ -60,7 +60,7 @@ public async Task SetupClient()
// Keep track of the correct result expectations and execution process
_list = EmployeeObj.GetTestList();
- _postgres = async syntax =>
+ _executor = async syntax =>
{
var sql = syntax.ToSqlServerCommand();
var result = new List();
@@ -158,6 +158,13 @@ public async Task CleanupMongo()
[TestMethod]
public async Task EmployeeTestSuite()
{
- await Executors.EmployeeTestSuite.BasicTestSuite(_src, _list, _postgres);
+ await Executors.EmployeeTestSuite.BasicTestSuite(_src, _list, _executor);
+
+ _src.Engine = new SearchlightEngine
+ {
+ StringComparison = StringComparison.Ordinal,
+ Collation = "SQL_Latin1_General_CP1_CS_AS"
+ };
+ await Executors.EmployeeTestSuite.CaseSensitiveStringTestSuite(_src, _list, _executor);
}
}
\ No newline at end of file