mirror of https://github.com/AMT-Cheif/drift.git
Better error handling when parsing multiple sql statements
This commit is contained in:
parent
867f953107
commit
ba772ef07f
|
@ -124,7 +124,14 @@ class DartTask extends FileTask<ParsedDartFile> {
|
|||
Future<List<SpecifiedTable>> resolveIncludes(Iterable<String> paths) {
|
||||
return Stream.fromFutures(paths.map(
|
||||
(path) => session.startMoorTask(backendTask, uri: Uri.parse(path))))
|
||||
.asyncMap((task) => task.compute())
|
||||
.asyncMap((task) async {
|
||||
final result = await task.compute();
|
||||
|
||||
// add errors from nested task to this task as well.
|
||||
task.errors.errors.forEach(reportError);
|
||||
|
||||
return result;
|
||||
})
|
||||
.expand((file) => file.declaredTables)
|
||||
.toList();
|
||||
}
|
||||
|
|
|
@ -151,9 +151,6 @@ abstract class ParserBase {
|
|||
WindowDefinition _windowDefinition();
|
||||
}
|
||||
|
||||
// todo better error handling and synchronisation, like it's done here:
|
||||
// https://craftinginterpreters.com/parsing-expressions.html#synchronizing-a-recursive-descent-parser
|
||||
|
||||
class Parser extends ParserBase
|
||||
with ExpressionParser, SchemaParser, CrudParser {
|
||||
Parser(List<Token> tokens, {bool useMoor = false}) : super(tokens, useMoor);
|
||||
|
@ -180,8 +177,19 @@ class Parser extends ParserBase
|
|||
List<Statement> statements() {
|
||||
final stmts = <Statement>[];
|
||||
while (!_isAtEnd) {
|
||||
try {
|
||||
stmts.add(statement(expectEnd: false));
|
||||
} on ParsingError catch (_) {
|
||||
// the error is added to the list errors, so ignore. We skip to the next
|
||||
// semicolon to parse the next statement.
|
||||
_synchronize();
|
||||
}
|
||||
}
|
||||
return stmts;
|
||||
}
|
||||
|
||||
void _synchronize() {
|
||||
// fast-forward to the token after th next semicolon
|
||||
while (!_isAtEnd && _advance().type != TokenType.semicolon) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import 'package:sqlparser/sqlparser.dart';
|
||||
import 'package:sqlparser/src/reader/parser/parser.dart';
|
||||
import 'package:sqlparser/src/reader/tokenizer/scanner.dart';
|
||||
import 'package:sqlparser/src/utils/ast_equality.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
test('can parse multiple statements', () {
|
||||
final sql = 'UPDATE tbl SET a = b; SELECT * FROM tbl;';
|
||||
final tokens = Scanner(sql).scanTokens();
|
||||
final statements = Parser(tokens).statements();
|
||||
|
||||
enforceEqual(
|
||||
statements[0],
|
||||
UpdateStatement(
|
||||
table: TableReference('tbl', null),
|
||||
set: [
|
||||
SetComponent(
|
||||
column: Reference(columnName: 'a'),
|
||||
expression: Reference(columnName: 'b'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
enforceEqual(
|
||||
statements[1],
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: [TableReference('tbl', null)],
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('recovers from invalid statements', () {
|
||||
final sql = 'UPDATE tbl SET a = * d; SELECT * FROM tbl;';
|
||||
final tokens = Scanner(sql).scanTokens();
|
||||
final statements = Parser(tokens).statements();
|
||||
|
||||
expect(statements, hasLength(1));
|
||||
enforceEqual(
|
||||
statements[0],
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: [TableReference('tbl', null)],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue