Only resolve columns declared in scope of a statement

Fixes #52
This commit is contained in:
Simon Binder 2019-07-02 12:28:54 +02:00
parent 2487c64c08
commit 316f9e1052
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
9 changed files with 44 additions and 11 deletions

View File

@ -29,6 +29,8 @@ dev_dependencies:
dependency_overrides:
moor_generator:
path: ../moor_generator
sqlparser:
path: ../sqlparser
# Temporarily use my fork because it can collect coverage when running tests with the test runner
coverage:
git: https://github.com/simolus3/coverage.git

View File

@ -1072,7 +1072,9 @@ abstract class _$TodoDb extends GeneratedDatabase {
return (operateOn ?? this)
.customUpdate('DELETE FROM todos WHERE id = ?', variables: [
Variable.withInt(var1),
], updates: {});
], updates: {
todosTable
});
}
@override

View File

@ -394,7 +394,9 @@ abstract class _$Database extends GeneratedDatabase {
variables: [
Variable.withInt(var1),
],
updates: {});
updates: {
todos
});
}
@override

View File

@ -27,6 +27,8 @@ dependency_overrides:
path: ../../moor_generator
moor:
path: ../../moor
sqlparser:
path: ../../sqlparser
flutter:
uses-material-design: true

View File

@ -43,7 +43,7 @@ class SqlParser {
for (var error in context.errors) {
state.errors.add(MoorError(
message: 'The sql query $sql is invalid: ${error.message}',
message: 'The sql query $sql is invalid: $error',
));
}

View File

@ -15,6 +15,20 @@ class ColumnResolver extends RecursiveVisitor<void> {
visitChildren(e);
}
@override
void visitUpdateStatement(UpdateStatement e) {
final table = _resolveTableReference(e.table);
e.scope.availableColumns = table.resolvedColumns;
visitChildren(e);
}
@override
void visitDeleteStatement(DeleteStatement e) {
final table = _resolveTableReference(e.from);
e.scope.availableColumns = table.resolvedColumns;
visitChildren(e);
}
void _handle(Queryable queryable, List<Column> availableColumns) {
queryable.when(
isTable: (table) {
@ -91,7 +105,7 @@ class ColumnResolver extends RecursiveVisitor<void> {
return span;
}
void _resolveTableReference(TableReference r) {
Table _resolveTableReference(TableReference r) {
final scope = r.scope;
final resolvedTable = scope.resolve<Table>(r.tableName, orElse: () {
context.reportError(AnalysisError(
@ -100,6 +114,6 @@ class ColumnResolver extends RecursiveVisitor<void> {
message: 'The table ${r.tableName} could not be found',
));
});
r.resolved = resolvedTable;
return r.resolved = resolvedTable;
}
}

View File

@ -41,11 +41,8 @@ class ReferenceResolver extends RecursiveVisitor<void> {
} else {
// find any column with the referenced name.
// todo special case for USING (...) in joins?
final tables = scope.allOf<ResolvesToResultSet>();
final columns = tables
.map((t) => t.resultSet.findColumn(e.columnName))
.where((c) => c != null)
.toSet();
final columns =
scope.availableColumns.where((c) => c?.name == e.columnName).toSet();
if (columns.isEmpty) {
context.reportError(AnalysisError(
@ -53,7 +50,10 @@ class ReferenceResolver extends RecursiveVisitor<void> {
} else {
if (columns.length > 1) {
context.reportError(AnalysisError(
type: AnalysisErrorType.ambiguousReference, relevantNode: e));
type: AnalysisErrorType.ambiguousReference,
relevantNode: e,
message: 'Could refer to any in ${columns.join(', ')}',
));
}
e.resolved = columns.first;

View File

@ -8,3 +8,12 @@ final demoTable = Table(
name: 'demo',
resolvedColumns: [id, content],
);
final anotherId = TableColumn('id', const ResolvedType(type: BasicType.int));
final dateTime = TableColumn(
'date', const ResolvedType(type: BasicType.int, hint: IsDateTime()));
final anotherTable = Table(
name: 'table',
resolvedColumns: [anotherId, dateTime],
);

View File

@ -13,6 +13,8 @@ void main() {
final select = context.root as SelectStatement;
final resolvedColumns = select.resolvedColumns;
expect(context.errors, isEmpty);
expect(resolvedColumns.map((c) => c.name),
['id', 'content', 'id', 'content', '3 + 4']);