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) {
|
Future<List<SpecifiedTable>> resolveIncludes(Iterable<String> paths) {
|
||||||
return Stream.fromFutures(paths.map(
|
return Stream.fromFutures(paths.map(
|
||||||
(path) => session.startMoorTask(backendTask, uri: Uri.parse(path))))
|
(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)
|
.expand((file) => file.declaredTables)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,9 +151,6 @@ abstract class ParserBase {
|
||||||
WindowDefinition _windowDefinition();
|
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
|
class Parser extends ParserBase
|
||||||
with ExpressionParser, SchemaParser, CrudParser {
|
with ExpressionParser, SchemaParser, CrudParser {
|
||||||
Parser(List<Token> tokens, {bool useMoor = false}) : super(tokens, useMoor);
|
Parser(List<Token> tokens, {bool useMoor = false}) : super(tokens, useMoor);
|
||||||
|
@ -180,8 +177,19 @@ class Parser extends ParserBase
|
||||||
List<Statement> statements() {
|
List<Statement> statements() {
|
||||||
final stmts = <Statement>[];
|
final stmts = <Statement>[];
|
||||||
while (!_isAtEnd) {
|
while (!_isAtEnd) {
|
||||||
stmts.add(statement(expectEnd: false));
|
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;
|
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