From f78d17dc269ae1d109c1e3dc029179aefc59d4da Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 31 May 2021 15:32:35 +0200 Subject: [PATCH] Fix code generation for nullable arrays (#1237) --- moor_generator/lib/src/model/column.dart | 3 ++ moor_generator/lib/src/model/sql_query.dart | 7 ++-- moor_generator/lib/src/model/types.dart | 18 +++++++++-- .../writer/queries/query_writer_test.dart | 32 +++++++++++++++++++ 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 moor_generator/test/writer/queries/query_writer_test.dart diff --git a/moor_generator/lib/src/model/column.dart b/moor_generator/lib/src/model/column.dart index 62af182d..a66f1166 100644 --- a/moor_generator/lib/src/model/column.dart +++ b/moor_generator/lib/src/model/column.dart @@ -126,6 +126,9 @@ class MoorColumn implements HasDeclaration, HasType { ColumnType.real: 'GeneratedRealColumn', }[type]; + @override + bool get isArray => false; + MoorColumn({ this.type, this.dartGetterName, diff --git a/moor_generator/lib/src/model/sql_query.dart b/moor_generator/lib/src/model/sql_query.dart index 062c43c9..8c3040c8 100644 --- a/moor_generator/lib/src/model/sql_query.dart +++ b/moor_generator/lib/src/model/sql_query.dart @@ -358,6 +358,9 @@ class ResultColumn implements HasType { ResultColumn(this.name, this.type, this.nullable, {this.typeConverter, this.sqlParserColumn}); + @override + bool get isArray => false; + /// Hash-code that matching [compatibleTo], so that two compatible columns /// will have the same [compatibilityHashCode]. int get compatibilityHashCode { @@ -474,6 +477,7 @@ class FoundVariable extends FoundElement implements HasType { /// variables at runtime. We only accept queries where no explicitly numbered /// vars appear after an array. This means that we can expand array variables /// without having to look at other variables. + @override final bool isArray; final bool isRequired; @@ -500,8 +504,7 @@ class FoundVariable extends FoundElement implements HasType { @override String dartTypeCode([GenerationOptions options = const GenerationOptions()]) { - final withoutArray = OperationOnTypes(this).dartTypeCode(options); - return isArray ? 'List<$withoutArray>' : withoutArray; + return OperationOnTypes(this).dartTypeCode(options); } } diff --git a/moor_generator/lib/src/model/types.dart b/moor_generator/lib/src/model/types.dart index 065e63a4..89a4b116 100644 --- a/moor_generator/lib/src/model/types.dart +++ b/moor_generator/lib/src/model/types.dart @@ -10,6 +10,12 @@ abstract class HasType { /// Whether the type is nullable in Dart. bool get nullable; + /// Whether this type is an array in sql. + /// + /// In this case, [nullable] refers to the inner type as arrays are always + /// non-nullable. + bool get isArray; + /// The associated sql type. ColumnType get type; @@ -20,7 +26,7 @@ abstract class HasType { extension OperationOnTypes on HasType { /// Whether this type is nullable in Dart bool get nullableInDart { - return nullable || typeConverter?.hasNullableDartType == true; + return (nullable && !isArray) || typeConverter?.hasNullableDartType == true; } /// the Dart type of this column that can be handled by moors type mapping. @@ -36,8 +42,14 @@ extension OperationOnTypes on HasType { /// This is the same as [dartTypeCode] but without custom types. String variableTypeCode( [GenerationOptions options = const GenerationOptions()]) { - final hasSuffix = nullableInDart && options.nnbd; - return hasSuffix ? '$variableTypeName?' : variableTypeName; + final innerHasSuffix = nullable && options.nnbd; + final result = innerHasSuffix ? '$variableTypeName?' : variableTypeName; + + if (isArray) { + return 'List<$result>'; + } else { + return result; + } } /// The dart type that matches the values of this column. For instance, if a diff --git a/moor_generator/test/writer/queries/query_writer_test.dart b/moor_generator/test/writer/queries/query_writer_test.dart new file mode 100644 index 00000000..7fad13f9 --- /dev/null +++ b/moor_generator/test/writer/queries/query_writer_test.dart @@ -0,0 +1,32 @@ +// @dart=2.9 +import 'package:moor_generator/src/analyzer/options.dart'; +import 'package:moor_generator/src/analyzer/runner/results.dart'; +import 'package:moor_generator/writer.dart'; +import 'package:test/test.dart'; + +import '../../analyzer/utils.dart'; + +void main() { + test('generates correct parameter for nullable arrays', () async { + final state = TestState.withContent({ + 'a|lib/main.moor': ''' + CREATE TABLE tbl ( + id INTEGER NULL + ); + + query: SELECT * FROM tbl WHERE id IN :idList; + ''', + }, enableAnalyzer: false); + addTearDown(state.close); + + final file = await state.analyze('package:a/main.moor'); + final fileState = file.currentResult as ParsedMoorFile; + + final writer = Writer( + const MoorOptions.defaults(generateNamedParameters: true), + generationOptions: const GenerationOptions(nnbd: true)); + QueryWriter(fileState.resolvedQueries.single, writer.child()).write(); + + expect(writer.writeGenerated(), contains('required List idList')); + }); +}