From 2cd568aea6ddc26939982007caafc0dbd2abac21 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Fri, 18 Oct 2024 21:43:39 +0200 Subject: [PATCH] Fix infering result type of fts5 functions --- .../resolver/drift/regression_3292_test.dart | 56 +++++++++++++++++++ sqlparser/lib/src/engine/module/fts5.dart | 4 +- sqlparser/lib/src/engine/sql_engine.dart | 6 +- sqlparser/test/engine/module/fts5_test.dart | 6 +- 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 drift_dev/test/analysis/resolver/drift/regression_3292_test.dart diff --git a/drift_dev/test/analysis/resolver/drift/regression_3292_test.dart b/drift_dev/test/analysis/resolver/drift/regression_3292_test.dart new file mode 100644 index 000000000..56debb42b --- /dev/null +++ b/drift_dev/test/analysis/resolver/drift/regression_3292_test.dart @@ -0,0 +1,56 @@ +import 'package:drift/drift.dart'; +import 'package:drift_dev/src/analysis/options.dart'; +import 'package:drift_dev/src/analysis/results/results.dart'; +import 'package:test/test.dart'; + +import '../../test_utils.dart'; + +void main() { + test('infers types for bm25 and snippet functions', () async { + final backend = await TestBackend.inTest({ + 'a|lib/a.drift': ''' +CREATE VIRTUAL TABLE songs_fts USING fts5(uuid, source_bank_id, title, lyrics, composer, poet, translator, pitch_field); + +song_fulltext_search(:match_string AS TEXT): + SELECT + BM25(songs_fts, 0.0, 0.0, 10.0, 0.5, 5.0, 5.0, 2.0, 0.0) AS rank + ,uuid + ,source_bank_id + ,pitch_field + ,SNIPPET(songs_fts, 2, '', '...', 30) AS match_title + ,SNIPPET(songs_fts, 3, '', '...', 30) AS match_lyrics + ,SNIPPET(songs_fts, 4, '', '...', 30) AS match_composer + ,SNIPPET(songs_fts, 5, '', '...', 30) AS match_poet + ,SNIPPET(songs_fts, 6, '', '...', 30) AS match_translator + FROM songs_fts + WHERE songs_fts MATCH :match_string + ORDER BY rank; +''', + }, options: DriftOptions.defaults(modules: [SqlModule.fts5])); + + final file = await backend.analyze('package:a/a.drift'); + backend.expectNoErrors(); + + final query = + file.fileAnalysis!.resolvedQueries.values.single as SqlSelectQuery; + expect( + query.resultSet.columns.map( + (e) => ( + e.dartGetterName(const []), + (e as ScalarResultColumn).sqlType.builtin + ), + ), + [ + ('rank', DriftSqlType.double), + ('uuid', DriftSqlType.string), + ('sourceBankId', DriftSqlType.string), + ('pitchField', DriftSqlType.string), + ('matchTitle', DriftSqlType.string), + ('matchLyrics', DriftSqlType.string), + ('matchComposer', DriftSqlType.string), + ('matchPoet', DriftSqlType.string), + ('matchTranslator', DriftSqlType.string), + ], + ); + }); +} diff --git a/sqlparser/lib/src/engine/module/fts5.dart b/sqlparser/lib/src/engine/module/fts5.dart index a84954a86..b6d0c2fae 100644 --- a/sqlparser/lib/src/engine/module/fts5.dart +++ b/sqlparser/lib/src/engine/module/fts5.dart @@ -157,7 +157,7 @@ class _Fts5Functions with ArgumentCountLinter implements FunctionHandler { if (argumentIndex == 0) { return const ResolveResult.unknown(); } else { - return const ResolveResult(ResolvedType(type: BasicType.int)); + return const ResolveResult(ResolvedType(type: BasicType.real)); } case 'highlight': @@ -184,7 +184,7 @@ class _Fts5Functions with ArgumentCountLinter implements FunctionHandler { @override ResolveResult inferReturnType(AnalysisContext context, SqlInvocation call, List expandedArgs) { - switch (call.name) { + switch (call.name.toLowerCase()) { case 'bm25': return const ResolveResult(ResolvedType(type: BasicType.real)); case 'highlight': diff --git a/sqlparser/lib/src/engine/sql_engine.dart b/sqlparser/lib/src/engine/sql_engine.dart index 819b14021..24ce6516f 100644 --- a/sqlparser/lib/src/engine/sql_engine.dart +++ b/sqlparser/lib/src/engine/sql_engine.dart @@ -264,11 +264,7 @@ class SqlEngine { AnalysisContext analyzeParsed(ParseResult result, {AnalyzeStatementOptions? stmtOptions}) { final node = result.rootNode; - - final context = _createContext(node, result.sql, stmtOptions); - _analyzeContext(context); - - return context; + return analyzeNode(node, result.sql, stmtOptions: stmtOptions); } /// Analyzes the given [node], which should be a [CrudStatement]. diff --git a/sqlparser/test/engine/module/fts5_test.dart b/sqlparser/test/engine/module/fts5_test.dart index 79408534d..a6801586d 100644 --- a/sqlparser/test/engine/module/fts5_test.dart +++ b/sqlparser/test/engine/module/fts5_test.dart @@ -167,6 +167,8 @@ void main() { final column = select.resolvedColumns!.singleWhere((c) => c.name == 'b'); expect(result.typeOf(column), const ResolveResult(ResolvedType(type: BasicType.real))); + expect(result.typeOf((column as ExpressionColumn).expression), + const ResolveResult(ResolvedType(type: BasicType.real))); }); test('return type of highlight()', () { @@ -245,8 +247,8 @@ void main() { checkVarTypes( 'SELECT bm25(fts, ?, ?) FROM fts;', [ - BasicType.int, - BasicType.int, + BasicType.real, + BasicType.real, ], ); });