Skip to content

Commit 85c954a

Browse files
authored
Merge pull request #350 from servicetitan/mergeUpstream
Merge upstream
2 parents ba9a060 + b915f07 commit 85c954a

File tree

10 files changed

+589
-155
lines changed

10 files changed

+589
-155
lines changed

ChangeLog/7.2.0-Beta-2-dev.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
[main] Upgrade hints change names of constructors' string parameters for better understanding of what suppose to be in them.
1+
[main] Upgrade hints change names of constructors' string parameters for better understanding of what suppose to be in them.
2+
[main] Improved string operations Trim/TrimStart/TrimEnd support
3+
[mysql] SqlDml.NullIf function now correctly translated
4+
[mysql] Improved support for string.PadLeft/PadRight opertaions
5+
[sqlite] Fixed string.Lenght translation
6+
[sqlite] Added support for string.PadLeft/PadRight operations

Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public override void Visit(SqlFunctionCall node)
160160
return;
161161
case SqlFunctionType.PadLeft:
162162
case SqlFunctionType.PadRight:
163-
SqlHelper.GenericPad(node).AcceptVisitor(this);
163+
SqlHelper.GenericPad(node, true).AcceptVisitor(this);
164164
return;
165165
case SqlFunctionType.Rand:
166166
SqlDml.FunctionCall(translator.TranslateToString(SqlFunctionType.Rand)).AcceptVisitor(this);

Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ public override void Translate(IOutput output, SqlFunctionType type)
9393
case SqlFunctionType.CurrentUser:
9494
_ = output.Append("CURRENT_USER()"); break;
9595
case SqlFunctionType.SessionUser: _ = output.Append("SESSION_USER()"); break;
96-
case SqlFunctionType.NullIf: _ = output.Append("IFNULL"); break;
9796
//datetime/timespan
9897
case SqlFunctionType.DateTimeTruncate: _ = output.Append("DATE"); break;
9998
case SqlFunctionType.CurrentDate: _ = output.Append("CURDATE()"); break;

Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,11 @@ public override void Visit(SqlFunctionCall node)
151151
var arguments = node.Arguments;
152152
switch (node.FunctionType) {
153153
case SqlFunctionType.CharLength:
154-
(SqlDml.FunctionCall("LENGTH", arguments) / 2).AcceptVisitor(this);
154+
SqlDml.FunctionCall("LENGTH", arguments).AcceptVisitor(this);
155155
return;
156156
case SqlFunctionType.PadLeft:
157157
case SqlFunctionType.PadRight:
158+
Visit(EmulateLpadRpad(arguments, node.FunctionType is SqlFunctionType.PadLeft));
158159
return;
159160
case SqlFunctionType.Concat:
160161
var nod = arguments[0];
@@ -631,6 +632,42 @@ private static SqlDateTimePart ConvertDateTimeOffsetPartToDateTimePart(SqlDateTi
631632
};
632633
}
633634

635+
private static SqlCase EmulateLpadRpad(IReadOnlyList<SqlExpression> arguments, bool isLpad)
636+
{
637+
var operand = arguments[0];
638+
var charcount = arguments[1];
639+
if (charcount is not SqlLiteral<int> intWidth) {
640+
// Since we emulate function with contatination, we need to know total width
641+
// to calculate prefix
642+
throw SqlHelper.NotSupported("PadLeft/PadRight with expressions as total width.");
643+
}
644+
var totalWidth = intWidth.Value;
645+
646+
var padChar = arguments switch {
647+
_ when arguments.Count == 3 && arguments[2] is SqlLiteral<char> charLiteral => charLiteral.Value,
648+
_ when arguments.Count == 2 => ' ',
649+
_ => throw new NotSupportedException()
650+
};
651+
652+
var paddingString = SqlDml.Literal(new string(Enumerable.Repeat(padChar, intWidth.Value).ToArray()));
653+
654+
var padExpression = isLpad
655+
? SqlDml.Substring(
656+
SqlDml.Concat(paddingString, operand),
657+
SqlDml.Literal(-totalWidth - 1),// handles '+1' operation in translation of substring function call
658+
SqlDml.Literal(totalWidth))
659+
: SqlDml.Substring(
660+
SqlDml.Concat(operand, paddingString),
661+
SqlDml.Literal(0), // handles '+1' operation in translation of substring function call
662+
SqlDml.Literal(totalWidth));
663+
664+
var @case = SqlDml.Case();
665+
_ = @case.Add(SqlDml.CharLength(operand) >= charcount, operand);
666+
@case.Else = padExpression;
667+
return @case;
668+
}
669+
670+
634671
// Constructors
635672

636673
/// <param name="driver">The driver.</param>

Orm/Xtensive.Orm.Tests/Linq/SelectTest.cs

Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -768,118 +768,6 @@ where invoice.InvoiceId > 0 && invoice.InvoiceId < 50
768768
}
769769
}
770770

771-
[Test]
772-
public void SelectStringIndexerTest()
773-
{
774-
var result =
775-
Session.Query.All<Customer>()
776-
.Select(c => new {
777-
String = c.CustomerId,
778-
Char0 = c.Email[0],
779-
Char1 = c.Email[1],
780-
Char2 = c.Email[2],
781-
Char3 = c.Email[3],
782-
Char4 = c.Email[4],
783-
})
784-
.ToArray()
785-
.OrderBy(item => item.String)
786-
.ToArray();
787-
var expected = Customers
788-
.Select(c => new {
789-
String = c.CustomerId,
790-
Char0 = c.Email[0],
791-
Char1 = c.Email[1],
792-
Char2 = c.Email[2],
793-
Char3 = c.Email[3],
794-
Char4 = c.Email[4],
795-
})
796-
.OrderBy(item => item.String)
797-
.ToArray();
798-
Assert.AreEqual(expected.Length, result.Length);
799-
for (var i = 0; i < expected.Length; i++) {
800-
Assert.AreEqual(expected[0].String, result[0].String);
801-
Assert.AreEqual(expected[0].Char0, result[0].Char0);
802-
Assert.AreEqual(expected[0].Char1, result[0].Char1);
803-
Assert.AreEqual(expected[0].Char2, result[0].Char2);
804-
Assert.AreEqual(expected[0].Char3, result[0].Char3);
805-
Assert.AreEqual(expected[0].Char4, result[0].Char4);
806-
}
807-
}
808-
809-
[Test]
810-
public void SelectIndexOfTest()
811-
{
812-
var _char = 'A';
813-
var result =
814-
Session.Query.All<Customer>()
815-
.Select(c => new {
816-
String = c.FirstName,
817-
IndexOfChar = c.FirstName.IndexOf(_char),
818-
IndexOfCharStart = c.FirstName.IndexOf(_char, 1),
819-
IndexOfCharStartCount = c.FirstName.IndexOf(_char, 1, 1),
820-
IndexOfString = c.FirstName.IndexOf(_char.ToString()),
821-
IndexOfStringStart = c.FirstName.IndexOf(_char.ToString(), 1),
822-
IndexOfStringStartCount = c.FirstName.IndexOf(_char.ToString(), 1, 1)
823-
})
824-
.ToArray()
825-
.OrderBy(item => item.String)
826-
.ToArray();
827-
var expected = Customers
828-
.Select(c => new {
829-
String = c.FirstName,
830-
IndexOfChar = c.FirstName.IndexOf(_char),
831-
IndexOfCharStart = c.FirstName.IndexOf(_char, 1),
832-
IndexOfCharStartCount = c.FirstName.IndexOf(_char, 1, 1),
833-
IndexOfString = c.FirstName.IndexOf(_char.ToString()),
834-
IndexOfStringStart = c.FirstName.IndexOf(_char.ToString(), 1),
835-
IndexOfStringStartCount = c.FirstName.IndexOf(_char.ToString(), 1, 1)
836-
})
837-
.OrderBy(item => item.String)
838-
.ToArray();
839-
Assert.AreEqual(expected.Length, result.Length);
840-
for (var i = 0; i < expected.Length; i++) {
841-
Assert.AreEqual(expected[i].String, result[i].String);
842-
Assert.AreEqual(expected[i].IndexOfChar, result[i].IndexOfChar);
843-
Assert.AreEqual(expected[i].IndexOfCharStart, result[i].IndexOfCharStart);
844-
Assert.AreEqual(expected[i].IndexOfCharStartCount, result[i].IndexOfCharStartCount);
845-
Assert.AreEqual(expected[i].IndexOfString, result[i].IndexOfString);
846-
Assert.AreEqual(expected[i].IndexOfStringStart, result[i].IndexOfStringStart);
847-
Assert.AreEqual(expected[i].IndexOfStringStartCount, result[i].IndexOfStringStartCount);
848-
}
849-
}
850-
851-
[Test]
852-
public void SelectStringContainsTest1()
853-
{
854-
Require.ProviderIs(StorageProvider.Sqlite | StorageProvider.SqlServer | StorageProvider.MySql);
855-
var result =
856-
Session.Query.All<Customer>()
857-
.Where(c => c.FirstName.Contains('L'))
858-
.OrderBy(c => c.CustomerId)
859-
.ToArray();
860-
var expected = Customers
861-
.Where(c => c.FirstName.Contains('L') || c.FirstName.Contains('l'))
862-
.OrderBy(c => c.CustomerId)
863-
.ToArray();
864-
Assert.IsTrue(expected.SequenceEqual(result));
865-
}
866-
867-
[Test]
868-
public void SelectStringContainsTest2()
869-
{
870-
Require.ProviderIsNot(StorageProvider.Sqlite | StorageProvider.SqlServer | StorageProvider.MySql);
871-
var result =
872-
Session.Query.All<Customer>()
873-
.Where(c => c.FirstName.Contains('L'))
874-
.OrderBy(c => c.CustomerId)
875-
.ToArray();
876-
var expected = Customers
877-
.Where(c => c.FirstName.Contains('L'))
878-
.OrderBy(c => c.CustomerId)
879-
.ToArray();
880-
Assert.IsTrue(expected.SequenceEqual(result));
881-
}
882-
883771
[Test]
884772
public void SelectDateTimeTimeSpanTest()
885773
{

0 commit comments

Comments
 (0)