Don't add an alias to subqueries

This commit is contained in:
Simon Binder 2021-08-12 13:15:52 +02:00
parent bcd8541a4b
commit c473779fba
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
3 changed files with 27 additions and 2 deletions

View File

@ -43,8 +43,11 @@ import 'package:moor/isolate.dart';
// This needs to be a top-level method because it's run on a background isolate
DatabaseConnection _backgroundConnection() {
// construct the database. You can also wrap the VmDatabase in a "LazyDatabase" if you need to run
// work before the database opens.
// Construct the database to use. This example uses a non-persistent in-memory database each
// time. You can use your existing VmDatabase with a file as well, or a `LazyDatabase` if you
// need to construct it asynchronously.
// When using a Flutter plugin like `path_provider` to determine the path, also see the
// "Initialization on the main thread" section below!
final database = VmDatabase.memory();
return DatabaseConnection.fromExecutor(database);
}

View File

@ -1,14 +1,24 @@
import 'package:sqlparser/sqlparser.dart';
/// A transformer adding explicit aliases to columns in a projection.
///
/// In sqlite3, the result name of columns without an alias is undefined. While
/// the names of direct column references (`SELECT foo FROM bar`) is unlikely
/// to change, we shouldn't assume that for more complex columns (`SELECT
/// MAX(id) * 14 FROM bar`). This transformer adds an alias to such columns
/// which avoids undefined behavior that might be different across sqlite3
/// versions.
class ExplicitAliasTransformer extends Transformer<bool> {
int _aliasCounter = 0;
final Map<Expression, String> _renamed = {};
/// Rewrites an SQL [node] to use explicit aliases for columns.
AstNode rewrite(AstNode node) {
node = transform(node, true)!;
return _PatchReferences(this).transform(node, null)!;
}
/// Obtain the new name for a [column] after an alias has been added.
String? newNameFor(Column column) {
while (column is CompoundSelectColumn) {
// In compound select statement, the first column determines the overall
@ -55,6 +65,14 @@ class ExplicitAliasTransformer extends Transformer<bool> {
return super.visitExpressionResultColumn(e, arg);
}
}
@override
AstNode? visitSubQuery(SubQuery e, bool arg) {
// Subquery expressions only have a single column, so the inner column
// doesn't matter. For instance, `SELECT (SELECT 1) AS foo` has no undefined
// behavior, even though the inner `1` has no alias.
return e..transformChildren(this, false);
}
}
class _PatchReferences extends Transformer<void> {

View File

@ -30,6 +30,10 @@ void main() {
'SELECT _c0 FROM (SELECT 1 + 2 AS _c0)');
});
test('does not rewrite subquery expressions', () {
_test('SELECT (SELECT 1)', 'SELECT (SELECT 1) AS _c0');
});
test('rewrites compound select statements', () {
_test("SELECT 1 + 2, 'foo' UNION ALL SELECT 3+ 4, 'bar'",
"SELECT 1 + 2 AS _c0, 'foo' AS _c1 UNION ALL SELECT 3 + 4, 'bar'");