Find variables reliably

This commit is contained in:
Simon Binder 2023-08-01 11:20:05 +02:00
parent 2cca2f517e
commit 1a4ac27415
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
3 changed files with 45 additions and 30 deletions

View File

@ -894,8 +894,27 @@ class FoundVariable extends FoundElement implements HasType {
/// three [Variable]s in its AST, but only two [FoundVariable]s, where the
/// `?` will have index 1 and (both) `:xyz` variables will have index 2. We
/// only report one [FoundVariable] per index.
///
/// This [index] might change in the generator as variables are moved around.
/// See [originalIndex] for the original index and a further discussion of
/// this.
int index;
/// The original index this variable had in the SQL string written by the
/// user.
///
/// In the generator, we might have to shuffle variable indices around a bit
/// to support array variables which occupy a dynamic amount of variable
/// indices at runtime.
/// For instance, consider `SELECT * FROM foo WHERE a = :a OR b IN :b OR c = :c`.
/// Here, `:c` will have an original index of 3. Since `:b` is an array
/// variable though, the actual query sent to the database system at runtime
/// will look like `SELECT * FROM foo WHERE a = ?1 OR b IN (?3, ?4) OR c = ?2`
/// when a size-2 list is passed for `b`. All non-array variables have been
/// given indices that appear before the array to support this, so the [index]
/// of `c` would then be `2`.
final int originalIndex;
/// The name of this variable, or null if it's not a named variable.
@override
String? name;
@ -939,7 +958,8 @@ class FoundVariable extends FoundElement implements HasType {
this.isArray = false,
this.isRequired = false,
this.typeConverter,
}) : hidden = false,
}) : originalIndex = index,
hidden = false,
syntacticOrigin = variable,
forCaptured = null;
@ -949,7 +969,8 @@ class FoundVariable extends FoundElement implements HasType {
required this.sqlType,
required Variable variable,
required this.forCaptured,
}) : typeConverter = null,
}) : originalIndex = index,
typeConverter = null,
nullable = false,
isArray = false,
isRequired = true,

View File

@ -103,12 +103,12 @@ class SqlWriter extends NodeSqlBuilder {
return dialect.escape(identifier);
}
FoundVariable? _findMoorVar(Variable target) {
FoundVariable? _findVariable(Variable target) {
return query!.variables
.firstWhereOrNull((f) => f.index == target.resolvedIndex);
.firstWhereOrNull((f) => f.originalIndex == target.resolvedIndex);
}
void _writeMoorVariable(FoundVariable variable) {
void _writeAnalyzedVariable(FoundVariable variable) {
if (variable.isArray) {
_writeRawInSpaces('(\$${expandedName(variable)})');
} else {
@ -175,9 +175,9 @@ class SqlWriter extends NodeSqlBuilder {
@override
void visitNamedVariable(ColonNamedVariable e, void arg) {
final moor = _findMoorVar(e);
if (moor != null) {
_writeMoorVariable(moor);
final found = _findVariable(e);
if (found != null) {
_writeAnalyzedVariable(found);
} else {
super.visitNamedVariable(e, arg);
}
@ -185,9 +185,9 @@ class SqlWriter extends NodeSqlBuilder {
@override
void visitNumberedVariable(NumberedVariable e, void arg) {
final moor = _findMoorVar(e);
if (moor != null) {
_writeMoorVariable(moor);
final found = _findVariable(e);
if (found != null) {
_writeAnalyzedVariable(found);
} else {
super.visitNumberedVariable(e, arg);
}

View File

@ -169,9 +169,8 @@ void main() {
expect(generated, contains('.toList()'));
});
group('generates correct code for expanded arrays', () {
Future<void> runTest(DriftOptions options, Matcher expectation) async {
final result = await generateForQueryInDriftFile('''
test('generates correct code for expanded arrays', () async {
final result = await generateForQueryInDriftFile('''
CREATE TABLE tbl (
a TEXT,
b TEXT,
@ -179,22 +178,17 @@ CREATE TABLE tbl (
);
query: SELECT * FROM tbl WHERE a = :a AND b IN :b AND c = :c;
''', options: options);
expect(result, expectation);
}
test('with the new query generator', () {
return runTest(
const DriftOptions.defaults(),
allOf(
contains(r'var $arrayStartIndex = 3;'),
contains(r'SELECT * FROM tbl WHERE a = ?1 AND b IN ($expandedb) '
'AND c = ?2'),
contains(r'variables: [Variable<String>(a), Variable<String>(c), '
r'for (var $ in b) Variable<String>($)], readsFrom: {tbl'),
),
);
});
''');
expect(
result,
allOf(
contains(r'var $arrayStartIndex = 3;'),
contains(r'SELECT * FROM tbl WHERE a = ?1 AND b IN ($expandedb) '
'AND c = ?2'),
contains(r'variables: [Variable<String>(a), Variable<String>(c), '
r'for (var $ in b) Variable<String>($)], readsFrom: {tbl'),
),
);
});
test(