Simple test for new query analyzer

This commit is contained in:
Simon Binder 2022-09-18 21:52:36 +02:00
parent b33ef8a220
commit dcdbcb7156
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
5 changed files with 104 additions and 10 deletions

View File

@ -19,6 +19,19 @@ class FileState {
String get extension => url.extension(ownUri.path);
Iterable<DriftAnalysisError> get allErrors sync* {
yield* errorsDuringDiscovery;
for (final entry in analysis.values) {
yield* entry.errorsDuringAnalysis;
}
final fileResults = fileAnalysis;
if (fileResults != null) {
yield* fileResults.analysisErrors;
}
}
bool get isFullyAnalyzed {
return discovery != null &&
discovery!.locallyDefinedElements

View File

@ -44,7 +44,7 @@ class FileAnalyzer {
final genericEngineForParsing = driver.newSqlEngine();
final source = await driver.backend.readAsString(state.ownUri);
final parsedFile =
genericEngineForParsing.parse(source).rootNode as DriftFile;
genericEngineForParsing.parseDriftFile(source).rootNode as DriftFile;
for (final elementAnalysis in state.analysis.values) {
final element = elementAnalysis.result;
@ -52,12 +52,13 @@ class FileAnalyzer {
final engine =
driver.typeMapping.newEngineWithTables(element.references);
final stmt = parsedFile.statements
.firstWhere((e) => e.firstPosition == element.sqlOffset)
as DeclaredStatement;
.whereType<DeclaredStatement>()
.firstWhere(
(e) => e.statement.firstPosition == element.sqlOffset);
final options = _createOptionsAndVars(engine, stmt);
final analysisResult =
engine.analyzeNode(stmt, source, stmtOptions: options.options);
final analysisResult = engine.analyzeNode(stmt.statement, source,
stmtOptions: options.options);
final analyzer = QueryAnalyzer(analysisResult, driver,
references: element.references,

View File

@ -0,0 +1,59 @@
import 'package:drift/drift.dart';
import 'package:test/test.dart';
import '../../test_utils.dart';
void main() {
test('select from view', () async {
final backend = TestBackend.inTest({
'foo|lib/a.drift': '''
CREATE TABLE artists (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name VARCHAR NOT NULL
);
CREATE TABLE albums (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
artist INTEGER NOT NULL REFERENCES artists (id)
);
CREATE TABLE tracks (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
album INTEGER NOT NULL REFERENCES albums (id),
duration_seconds INTEGER NOT NULL,
was_single BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE VIEW total_duration_by_artist_view AS
SELECT a.*, SUM(tracks.duration_seconds) AS duration
FROM artists a
INNER JOIN albums ON albums.artist = a.id
INNER JOIN tracks ON tracks.album = albums.id
GROUP BY a.id;
totalDurationByArtist:
SELECT * FROM total_duration_by_artist_view;
''',
});
final file =
await backend.driver.fullyAnalyze(Uri.parse('package:foo/a.drift'));
expect(file.allErrors, isEmpty);
final results = file.fileAnalysis!;
final query = results.resolvedQueries.values
.singleWhere((q) => q.name == 'totalDurationByArtist');
expect(
query,
returnsColumns({
'id': DriftSqlType.int,
'name': DriftSqlType.string,
'duration': DriftSqlType.int,
}),
);
});
}

View File

@ -9,10 +9,12 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:build/build.dart';
import 'package:drift/drift.dart';
import 'package:drift_dev/src/analysis/backend.dart';
import 'package:drift_dev/src/analysis/driver/driver.dart';
import 'package:drift_dev/src/analysis/driver/error.dart';
import 'package:drift_dev/src/analysis/driver/state.dart';
import 'package:drift_dev/src/analysis/results/results.dart';
import 'package:drift_dev/src/analyzer/options.dart';
import 'package:logging/logging.dart';
import 'package:package_config/package_config.dart';
@ -133,10 +135,29 @@ class TestBackend extends DriftBackend {
Future<void> dispose() async {}
}
Matcher get hasNoErrors => isA<FileState>()
.having((e) => e.errorsDuringDiscovery, 'errorsDuringDiscovery', isEmpty)
.having((e) => e.analysis.values.expand((e) => e.errorsDuringAnalysis),
'(errors in analyzed elements)', isEmpty);
Matcher get hasNoErrors =>
isA<FileState>().having((e) => e.allErrors, 'allErrors', isEmpty);
Matcher returnsColumns(Map<String, DriftSqlType> columns) {
return _HasInferredColumnTypes(columns);
}
class _HasInferredColumnTypes extends CustomMatcher {
_HasInferredColumnTypes(dynamic expected)
: super('Select query with inferred columns', 'columns', expected);
@override
Object? featureValueOf(dynamic actual) {
if (actual is! SqlSelectQuery) {
return actual;
}
final resultSet = actual.resultSet;
return {
for (final column in resultSet.columns) column.name: column.sqlType
};
}
}
TypeMatcher<DriftAnalysisError> isDriftError(dynamic message) {
return isA<DriftAnalysisError>().having((e) => e.message, 'message', message);

View File

@ -33,7 +33,7 @@ CREATE VIEW total_duration_by_artist_view AS
FROM artists a
INNER JOIN albums ON albums.artist = a.id
INNER JOIN tracks ON tracks.album = albums.id
GROUP BY artists.id;
GROUP BY a.id;
totalDurationByArtist:
SELECT * FROM total_duration_by_artist_view;