Skip to content

Commit 36062d4

Browse files
committed
SQLite: Fix string.Length translation and implement PadLeft/PadRight operations
1 parent 5165b4b commit 36062d4

File tree

1 file changed

+38
-1
lines changed
  • Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3

1 file changed

+38
-1
lines changed

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(EmulateLpadOrRpad(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 EmulateLpadOrRpad(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>

0 commit comments

Comments
 (0)