diff --git a/drift/lib/src/runtime/query_builder/expressions/text.dart b/drift/lib/src/runtime/query_builder/expressions/text.dart index 57f345cc..84fca918 100644 --- a/drift/lib/src/runtime/query_builder/expressions/text.dart +++ b/drift/lib/src/runtime/query_builder/expressions/text.dart @@ -137,10 +137,31 @@ extension StringExpressionOperators on Expression { /// and [length] can be negative to return a section of the string before /// [start]. Expression substr(int start, [int? length]) { + return substrExpr( + Constant(start), length != null ? Constant(length) : null); + } + + /// Calls the [`substr`](https://sqlite.org/lang_corefunc.html#substr) + /// function with arbitrary expressions as arguments. + /// + /// For instance, this call uses [substrExpr] to remove the last 5 characters + /// from a column. As this depends on its [StringExpressionOperators.length], + /// it needs to use expressions: + /// + /// ```dart + /// update(table).write(TableCompanion.custom( + /// column: column.substrExpr(Variable(1), column.length - Variable(5)) + /// )); + /// ``` + /// + /// When both [start] and [length] are Dart values (e.g. [Variable]s or + /// [Constant]s), consider using [substr] instead. + Expression substrExpr(Expression start, + [Expression? length]) { return FunctionCallExpression('SUBSTR', [ this, - Constant(start), - if (length != null) Constant(length), + start, + if (length != null) length, ]); } } diff --git a/drift/test/database/expressions/expressions_integration_test.dart b/drift/test/database/expressions/expressions_integration_test.dart index 0b92d8a8..ef3f2403 100644 --- a/drift/test/database/expressions/expressions_integration_test.dart +++ b/drift/test/database/expressions/expressions_integration_test.dart @@ -125,7 +125,11 @@ void main() { }); test('substring', () { - expect(eval(Constant('hello world').substr(7)), completion('world')); + final input = Constant('hello world'); + expect(eval(input.substr(7)), completion('world')); + + expect(eval(input.substrExpr(Variable(1), input.length - Variable(6))), + completion('hello')); }); }); diff --git a/drift/test/database/expressions/text_test.dart b/drift/test/database/expressions/text_test.dart index c63342d0..fdda38b0 100644 --- a/drift/test/database/expressions/text_test.dart +++ b/drift/test/database/expressions/text_test.dart @@ -52,5 +52,8 @@ void main() { test('substr', () { expect(expression.substr(10), generates('SUBSTR(col, 10)')); expect(expression.substr(10, 2), generates('SUBSTR(col, 10, 2)')); + + expect(expression.substrExpr(Variable(1), expression.length - Variable(5)), + generates('SUBSTR(col, ?, LENGTH(col) - ?)', [1, 5])); }); }