mirror of https://github.com/AMT-Cheif/drift.git
Report lints about invalid Dart Templates in SQL
This commit is contained in:
parent
3abfbd5963
commit
25ceda3505
|
@ -17,8 +17,9 @@ class _FakeDb extends GeneratedDatabase {
|
||||||
},
|
},
|
||||||
beforeOpen: (details) async {
|
beforeOpen: (details) async {
|
||||||
// this fake select query is verified via mocks
|
// this fake select query is verified via mocks
|
||||||
await customSelect(
|
await customSelectQuery(
|
||||||
'opened: ${details.versionBefore} to ${details.versionNow}');
|
'opened: ${details.versionBefore} to ${details.versionNow}')
|
||||||
|
.get();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ import 'package:sqlparser/sqlparser.dart';
|
||||||
|
|
||||||
import '../query_handler.dart';
|
import '../query_handler.dart';
|
||||||
|
|
||||||
|
/// Provides additional hints that aren't implemented in the sqlparser because
|
||||||
|
/// they're specific to moor.
|
||||||
class Linter {
|
class Linter {
|
||||||
final QueryHandler handler;
|
final QueryHandler handler;
|
||||||
final List<AnalysisError> lints = [];
|
final List<AnalysisError> lints = [];
|
||||||
|
@ -18,6 +20,39 @@ class _LintingVisitor extends RecursiveVisitor<void> {
|
||||||
|
|
||||||
_LintingVisitor(this.linter);
|
_LintingVisitor(this.linter);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void visitResultColumn(ResultColumn e) {
|
||||||
|
super.visitResultColumn(e);
|
||||||
|
|
||||||
|
if (e is ExpressionResultColumn) {
|
||||||
|
// The generated code will be invalid if knowing the expression is needed
|
||||||
|
// to know the column name (e.g. it's a Dart template without an AS), or
|
||||||
|
// if the type is unknown.
|
||||||
|
final expression = e.expression;
|
||||||
|
final resolveResult = linter.handler.context.typeOf(expression);
|
||||||
|
|
||||||
|
if (resolveResult.type == null) {
|
||||||
|
linter.lints.add(AnalysisError(
|
||||||
|
type: AnalysisErrorType.other,
|
||||||
|
message: 'Expression has an unknown type, the generated code can be'
|
||||||
|
' inaccurate.',
|
||||||
|
relevantNode: expression,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
final dependsOnPlaceholder = e.as == null &&
|
||||||
|
expression.allDescendants.whereType<DartPlaceholder>().isNotEmpty;
|
||||||
|
if (dependsOnPlaceholder) {
|
||||||
|
linter.lints.add(AnalysisError(
|
||||||
|
type: AnalysisErrorType.other,
|
||||||
|
message: 'The name of this column depends on a Dart template, which '
|
||||||
|
'breaks generated code. Try adding an `AS` alias to fix this.',
|
||||||
|
relevantNode: e,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void visitInsertStatement(InsertStatement e) {
|
void visitInsertStatement(InsertStatement e) {
|
||||||
final targeted = e.resolvedTargetColumns;
|
final targeted = e.resolvedTargetColumns;
|
||||||
|
|
|
@ -82,11 +82,11 @@ class QueryHandler {
|
||||||
final type = context.typeOf(column).type;
|
final type = context.typeOf(column).type;
|
||||||
final moorType = mapper.resolvedToMoor(type);
|
final moorType = mapper.resolvedToMoor(type);
|
||||||
UsedTypeConverter converter;
|
UsedTypeConverter converter;
|
||||||
if (type.hint is TypeConverterHint) {
|
if (type?.hint is TypeConverterHint) {
|
||||||
converter = (type.hint as TypeConverterHint).converter;
|
converter = (type.hint as TypeConverterHint).converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
columns.add(ResultColumn(column.name, moorType, type.nullable,
|
columns.add(ResultColumn(column.name, moorType, type?.nullable ?? true,
|
||||||
converter: converter));
|
converter: converter));
|
||||||
|
|
||||||
final table = _tableOfColumn(column);
|
final table = _tableOfColumn(column);
|
||||||
|
|
|
@ -113,7 +113,8 @@ class QueryWriter {
|
||||||
String _readingCode(ResultColumn column) {
|
String _readingCode(ResultColumn column) {
|
||||||
final readMethod = readFromMethods[column.type];
|
final readMethod = readFromMethods[column.type];
|
||||||
|
|
||||||
var code = "row.$readMethod('${column.name}')";
|
final dartLiteral = asDartLiteral(column.name);
|
||||||
|
var code = 'row.$readMethod($dartLiteral)';
|
||||||
|
|
||||||
if (column.converter != null) {
|
if (column.converter != null) {
|
||||||
final converter = column.converter;
|
final converter = column.converter;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import 'package:moor_generator/src/analyzer/sql_queries/query_handler.dart';
|
||||||
|
import 'package:moor_generator/src/analyzer/sql_queries/type_mapping.dart';
|
||||||
|
import 'package:sqlparser/sqlparser.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final engine = SqlEngine(useMoorExtensions: true);
|
||||||
|
final mapper = TypeMapper();
|
||||||
|
|
||||||
|
test('warns when a result column is unresolved', () {
|
||||||
|
final result = engine.analyze('SELECT ?;');
|
||||||
|
final moorQuery = QueryHandler('query', result, mapper).handle();
|
||||||
|
|
||||||
|
expect(moorQuery.lints,
|
||||||
|
anyElement((AnalysisError q) => q.message.contains('unknown type')));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('warns when the result depends on a Dart template', () {
|
||||||
|
final result = engine.analyze(r"SELECT 'string' = $expr;");
|
||||||
|
final moorQuery = QueryHandler('query', result, mapper).handle();
|
||||||
|
|
||||||
|
expect(moorQuery.lints,
|
||||||
|
anyElement((AnalysisError q) => q.message.contains('Dart template')));
|
||||||
|
});
|
||||||
|
}
|
|
@ -62,7 +62,7 @@ class TypeResolver {
|
||||||
// todo probably needs to be nullable when coming from a join?
|
// todo probably needs to be nullable when coming from a join?
|
||||||
return ResolveResult(column.type);
|
return ResolveResult(column.type);
|
||||||
} else if (column is ExpressionColumn) {
|
} else if (column is ExpressionColumn) {
|
||||||
return resolveExpression(column.expression);
|
return resolveOrInfer(column.expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw StateError('Unknown column $column');
|
throw StateError('Unknown column $column');
|
||||||
|
|
Loading…
Reference in New Issue