mirror of https://github.com/AMT-Cheif/drift.git
Fix converters on `int64` breaking inference
This commit is contained in:
parent
89b5fbb371
commit
eb03ac5ff0
|
@ -1,6 +1,7 @@
|
|||
## 2.12.2-dev
|
||||
## 2.13.0-dev
|
||||
|
||||
- Fix indices not being created for Dart tables from different tables.
|
||||
- Fix indices not being created for Dart tables from different files.
|
||||
- Fix type converters on `int64` columns not propagating properly.
|
||||
|
||||
## 2.12.1
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class _LintingVisitor extends RecursiveVisitor<void, void> {
|
|||
final type = result.type;
|
||||
return type != null &&
|
||||
type.type == BasicType.text &&
|
||||
type.hint is IsDateTime;
|
||||
type.hint<IsDateTime>() != null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -124,9 +124,9 @@ class _LintingVisitor extends RecursiveVisitor<void, void> {
|
|||
@override
|
||||
void visitNumericLiteral(NumericLiteral e, void arg) {
|
||||
final type = linter._context.typeOf(e);
|
||||
final hint = type.type?.hint;
|
||||
final hint = type.type?.hint<TypeConverterHint>();
|
||||
|
||||
if (hint is TypeConverterHint && hint.converter.isDriftEnumTypeConverter) {
|
||||
if (hint != null && hint.converter.isDriftEnumTypeConverter) {
|
||||
final enumElement =
|
||||
(hint.converter.dartType as InterfaceType).element as EnumElement;
|
||||
final entryCount =
|
||||
|
@ -303,9 +303,9 @@ class _LintingVisitor extends RecursiveVisitor<void, void> {
|
|||
@override
|
||||
void visitStringLiteral(StringLiteral e, void arg) {
|
||||
final type = linter._context.typeOf(e);
|
||||
final hint = type.type?.hint;
|
||||
final hint = type.type?.hint<TypeConverterHint>();
|
||||
|
||||
if (hint is TypeConverterHint && hint.converter.isDriftEnumTypeConverter) {
|
||||
if (hint != null && hint.converter.isDriftEnumTypeConverter) {
|
||||
final enumElement =
|
||||
(hint.converter.dartType as InterfaceType).element as EnumElement;
|
||||
final field = enumElement.getField(e.value);
|
||||
|
|
|
@ -73,39 +73,34 @@ class TypeMapping {
|
|||
}
|
||||
|
||||
ResolvedType _columnType(DriftColumn column) {
|
||||
return _driftTypeToParser(column.sqlType,
|
||||
overrideHint: column.typeConverter != null
|
||||
? TypeConverterHint(column.typeConverter!)
|
||||
: null)
|
||||
.withNullable(column.nullable);
|
||||
final type =
|
||||
_driftTypeToParser(column.sqlType).withNullable(column.nullable);
|
||||
|
||||
if (column.typeConverter case final AppliedTypeConverter c) {
|
||||
return type.addHint(TypeConverterHint(c));
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
ResolvedType _driftTypeToParser(DriftSqlType type, {TypeHint? overrideHint}) {
|
||||
switch (type) {
|
||||
case DriftSqlType.int:
|
||||
return ResolvedType(type: BasicType.int, hint: overrideHint);
|
||||
case DriftSqlType.bigInt:
|
||||
return ResolvedType(
|
||||
type: BasicType.int, hint: overrideHint ?? const IsBigInt());
|
||||
case DriftSqlType.string:
|
||||
return ResolvedType(type: BasicType.text, hint: overrideHint);
|
||||
case DriftSqlType.bool:
|
||||
return ResolvedType(
|
||||
type: BasicType.int, hint: overrideHint ?? const IsBoolean());
|
||||
case DriftSqlType.dateTime:
|
||||
return ResolvedType(
|
||||
ResolvedType _driftTypeToParser(DriftSqlType type) {
|
||||
return switch (type) {
|
||||
DriftSqlType.int => const ResolvedType(type: BasicType.int),
|
||||
DriftSqlType.bigInt =>
|
||||
const ResolvedType(type: BasicType.int, hints: [IsBigInt()]),
|
||||
DriftSqlType.string => const ResolvedType(type: BasicType.text),
|
||||
DriftSqlType.bool =>
|
||||
const ResolvedType(type: BasicType.int, hints: [IsBoolean()]),
|
||||
DriftSqlType.dateTime => ResolvedType(
|
||||
type: driver.options.storeDateTimeValuesAsText
|
||||
? BasicType.text
|
||||
: BasicType.int,
|
||||
hint: overrideHint ?? const IsDateTime(),
|
||||
);
|
||||
case DriftSqlType.blob:
|
||||
return ResolvedType(type: BasicType.blob, hint: overrideHint);
|
||||
case DriftSqlType.double:
|
||||
return ResolvedType(type: BasicType.real, hint: overrideHint);
|
||||
case DriftSqlType.any:
|
||||
return ResolvedType(type: BasicType.any, hint: overrideHint);
|
||||
}
|
||||
hints: const [IsDateTime()],
|
||||
),
|
||||
DriftSqlType.blob => const ResolvedType(type: BasicType.blob),
|
||||
DriftSqlType.double => const ResolvedType(type: BasicType.real),
|
||||
DriftSqlType.any => const ResolvedType(type: BasicType.any),
|
||||
};
|
||||
}
|
||||
|
||||
DriftSqlType sqlTypeToDrift(ResolvedType? type) {
|
||||
|
@ -118,12 +113,12 @@ class TypeMapping {
|
|||
case BasicType.nullType:
|
||||
return DriftSqlType.string;
|
||||
case BasicType.int:
|
||||
if (type.hint is IsBoolean) {
|
||||
if (type.hint<IsBoolean>() != null) {
|
||||
return DriftSqlType.bool;
|
||||
} else if (!driver.options.storeDateTimeValuesAsText &&
|
||||
type.hint is IsDateTime) {
|
||||
type.hint<IsDateTime>() != null) {
|
||||
return DriftSqlType.dateTime;
|
||||
} else if (type.hint is IsBigInt) {
|
||||
} else if (type.hint<IsBigInt>() != null) {
|
||||
return DriftSqlType.bigInt;
|
||||
}
|
||||
return DriftSqlType.int;
|
||||
|
@ -131,7 +126,7 @@ class TypeMapping {
|
|||
return DriftSqlType.double;
|
||||
case BasicType.text:
|
||||
if (driver.options.storeDateTimeValuesAsText &&
|
||||
type.hint is IsDateTime) {
|
||||
type.hint<IsDateTime>() != null) {
|
||||
return DriftSqlType.dateTime;
|
||||
}
|
||||
|
||||
|
@ -158,14 +153,16 @@ TypeFromText enumColumnFromText(
|
|||
if (type != null) {
|
||||
return ResolvedType(
|
||||
type: isStoredAsName ? BasicType.text : BasicType.int,
|
||||
hint: TypeConverterHint(
|
||||
readEnumConverter(
|
||||
(_) {},
|
||||
type,
|
||||
isStoredAsName ? EnumType.textEnum : EnumType.intEnum,
|
||||
helper,
|
||||
)..owningColumn = null,
|
||||
),
|
||||
hints: [
|
||||
TypeConverterHint(
|
||||
readEnumConverter(
|
||||
(_) {},
|
||||
type,
|
||||
isStoredAsName ? EnumType.textEnum : EnumType.intEnum,
|
||||
helper,
|
||||
)..owningColumn = null,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,8 +62,8 @@ class DriftViewResolver extends DriftElementResolver<DiscoveredDriftView> {
|
|||
}
|
||||
}
|
||||
|
||||
if (type != null && type.hint is TypeConverterHint) {
|
||||
converter ??= (type.hint as TypeConverterHint).converter;
|
||||
if (type?.hint<TypeConverterHint>() case final TypeConverterHint h) {
|
||||
converter ??= h.converter;
|
||||
ownsConverter = converter.owningColumn == null;
|
||||
}
|
||||
|
||||
|
|
|
@ -293,8 +293,8 @@ class QueryAnalyzer {
|
|||
final mappedBy = source?.mappedBy;
|
||||
AppliedTypeConverter? converter;
|
||||
|
||||
if (type?.hint is TypeConverterHint) {
|
||||
converter = (type!.hint as TypeConverterHint).converter;
|
||||
if (type?.hint<TypeConverterHint>() case final TypeConverterHint h) {
|
||||
converter = h.converter;
|
||||
} else if (mappedBy != null) {
|
||||
final dartExpression = _resolvedExpressions[mappedBy.mapper.dartCode];
|
||||
if (dartExpression != null) {
|
||||
|
@ -668,9 +668,11 @@ class QueryAnalyzer {
|
|||
|
||||
// Recognizing type converters on variables is opt-in since it would
|
||||
// break existing code.
|
||||
if (driver.options.applyConvertersOnVariables &&
|
||||
internalType.type?.hint is TypeConverterHint) {
|
||||
converter = (internalType.type!.hint as TypeConverterHint).converter;
|
||||
if (driver.options.applyConvertersOnVariables) {
|
||||
if (internalType.type?.hint<TypeConverterHint>()
|
||||
case final TypeConverterHint h) {
|
||||
converter = h.converter;
|
||||
}
|
||||
}
|
||||
|
||||
addNewElement(FoundVariable(
|
||||
|
|
|
@ -134,13 +134,12 @@ class SqlWriter extends NodeSqlBuilder {
|
|||
);
|
||||
|
||||
final type = schema.resolveColumnType(e.typeName);
|
||||
final hint = type.hint;
|
||||
|
||||
String? overriddenTypeName;
|
||||
|
||||
if (hint is IsDateTime) {
|
||||
if (type.hint<IsDateTime>() != null) {
|
||||
overriddenTypeName = options.storeDateTimeValuesAsText ? 'TEXT' : 'INT';
|
||||
} else if (hint is IsBoolean) {
|
||||
} else if (type.hint<IsBoolean>() != null) {
|
||||
overriddenTypeName = 'INT';
|
||||
} else {
|
||||
final enumMatch = FoundReferencesInSql.enumRegex.firstMatch(e.typeName);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: drift_dev
|
||||
description: Dev-dependency for users of drift. Contains the generator and development tools.
|
||||
version: 2.12.1
|
||||
version: 2.13.0-dev
|
||||
repository: https://github.com/simolus3/drift
|
||||
homepage: https://drift.simonbinder.eu/
|
||||
issue_tracker: https://github.com/simolus3/drift/issues
|
||||
|
@ -32,7 +32,7 @@ dependencies:
|
|||
# Drift-specific analysis and apis
|
||||
drift: '>=2.13.0 <2.14.0'
|
||||
sqlite3: '>=0.1.6 <3.0.0'
|
||||
sqlparser: '^0.31.2'
|
||||
sqlparser: '^0.32.0'
|
||||
|
||||
# Dart analysis
|
||||
analyzer: '>=5.12.0 <7.0.0'
|
||||
|
|
|
@ -96,8 +96,8 @@ sqlite:
|
|||
isA<ResolvedType>().having((e) => e.type, 'type', BasicType.int),
|
||||
isA<ResolvedType>()
|
||||
.having((e) => e.type, 'type', BasicType.int)
|
||||
.having((e) => e.hint, 'hint', const IsBoolean())
|
||||
.having((e) => e.nullable, 'nullable', true),
|
||||
.having((e) => e.hints, 'hints', [IsBoolean()]).having(
|
||||
(e) => e.nullable, 'nullable', true),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -325,6 +325,44 @@ TypeConverter<Object, int> myConverter() => throw UnimplementedError();
|
|||
);
|
||||
});
|
||||
|
||||
test('can restore types from multiple hints', () async {
|
||||
final result = await emulateDriftBuild(
|
||||
inputs: {
|
||||
'a|lib/a.drift': '''
|
||||
import 'table.dart';
|
||||
|
||||
CREATE VIEW my_view AS SELECT foo FROM my_table;
|
||||
''',
|
||||
'a|lib/table.dart': '''
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class MyTable extends Table {
|
||||
Int64Column get foo => int64().map(myConverter())();
|
||||
}
|
||||
|
||||
enum MyEnum {
|
||||
foo, bar
|
||||
}
|
||||
|
||||
TypeConverter<Object, BigInt> myConverter() => throw UnimplementedError();
|
||||
''',
|
||||
},
|
||||
modularBuild: true,
|
||||
logger: loggerThat(neverEmits(anything)),
|
||||
);
|
||||
|
||||
checkOutputs(
|
||||
{
|
||||
'a|lib/a.drift.dart': decodedMatches(contains(
|
||||
'foo: i2.\$MyTableTable.\$converterfoo.fromSql(attachedDatabase.typeMapping\n'
|
||||
' .read(i0.DriftSqlType.bigInt')),
|
||||
'a|lib/table.drift.dart': decodedMatches(anything),
|
||||
},
|
||||
result.dartOutputs,
|
||||
result.writer,
|
||||
);
|
||||
});
|
||||
|
||||
test('supports @create queries in modular generation', () async {
|
||||
final result = await emulateDriftBuild(
|
||||
inputs: {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
## 0.32.0-dev
|
||||
|
||||
- Turn `ResolvedType.hints` into a list, supporting multiple type hints.
|
||||
|
||||
## 0.31.3
|
||||
|
||||
- Fix star columns expanding to more columns than they should.
|
||||
|
|
|
@ -88,7 +88,7 @@ class TableColumn extends Column implements ColumnWithType {
|
|||
///
|
||||
/// The [hint] will then be reflected in the [type].
|
||||
void applyTypeHint(TypeHint hint) {
|
||||
_type = _type.copyWith(hint: hint);
|
||||
_type = _type.addHint(hint);
|
||||
}
|
||||
|
||||
/// Whether this column is an alias for the rowid, as defined in
|
||||
|
|
|
@ -180,7 +180,7 @@ class SchemaFromCreateTable {
|
|||
if (upper.contains('DATE')) {
|
||||
return ResolvedType(
|
||||
type: driftUseTextForDateTime ? BasicType.text : BasicType.int,
|
||||
hint: const IsDateTime(),
|
||||
hints: const [IsDateTime()],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:sqlparser/src/engine/sql_engine.dart';
|
||||
|
||||
/// Something that has a type.
|
||||
|
@ -19,12 +20,14 @@ enum BasicType {
|
|||
}
|
||||
|
||||
class ResolvedType {
|
||||
static const _hintEquality = ListEquality<TypeHint>();
|
||||
|
||||
final BasicType? type;
|
||||
|
||||
/// We set hints for additional information that might be useful for
|
||||
/// applications but aren't covered by just exposing a [BasicType]. See the
|
||||
/// comment on [TypeHint] for examples.
|
||||
final TypeHint? hint;
|
||||
final List<TypeHint> hints;
|
||||
|
||||
/// Whether this type is nullable. A `null` value for [nullable] indicates
|
||||
/// that nullability is unknown.
|
||||
|
@ -34,15 +37,21 @@ class ResolvedType {
|
|||
final bool isArray;
|
||||
|
||||
const ResolvedType(
|
||||
{this.type, this.hint, this.nullable = false, this.isArray = false});
|
||||
{this.type,
|
||||
this.hints = const [],
|
||||
this.nullable = false,
|
||||
this.isArray = false});
|
||||
const ResolvedType.bool({bool? nullable = false})
|
||||
: this(type: BasicType.int, hint: const IsBoolean(), nullable: nullable);
|
||||
: this(
|
||||
type: BasicType.int,
|
||||
hints: const [IsBoolean()],
|
||||
nullable: nullable);
|
||||
|
||||
ResolvedType get withoutNullabilityInfo {
|
||||
return nullable == null
|
||||
? this
|
||||
: ResolvedType(
|
||||
type: type, hint: hint, isArray: isArray, nullable: null);
|
||||
type: type, hints: hints, isArray: isArray, nullable: null);
|
||||
}
|
||||
|
||||
ResolvedType withNullable(bool nullable) {
|
||||
|
@ -53,33 +62,42 @@ class ResolvedType {
|
|||
return copyWith(isArray: array);
|
||||
}
|
||||
|
||||
ResolvedType copyWith({TypeHint? hint, bool? nullable, bool? isArray}) {
|
||||
ResolvedType copyWith(
|
||||
{List<TypeHint>? hints, bool? nullable, bool? isArray}) {
|
||||
return ResolvedType(
|
||||
type: type,
|
||||
hint: hint ?? this.hint,
|
||||
hints: hints ?? this.hints,
|
||||
nullable: nullable ?? this.nullable,
|
||||
isArray: isArray ?? this.isArray,
|
||||
);
|
||||
}
|
||||
|
||||
T? hint<T extends TypeHint>() {
|
||||
return hints.whereType<T>().firstOrNull;
|
||||
}
|
||||
|
||||
ResolvedType addHint(TypeHint hint) {
|
||||
return copyWith(hints: [...hints, hint]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
other is ResolvedType &&
|
||||
other.type == type &&
|
||||
other.hint == hint &&
|
||||
_hintEquality.equals(other.hints, hints) &&
|
||||
other.nullable == nullable &&
|
||||
other.isArray == isArray;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return type.hashCode + hint.hashCode + nullable.hashCode;
|
||||
return type.hashCode + _hintEquality.hash(hints) + nullable.hashCode;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ResolvedType($type, hint: $hint, nullable: $nullable, '
|
||||
return 'ResolvedType($type, hints: $hints, nullable: $nullable, '
|
||||
'array: $isArray)';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -284,12 +284,10 @@ extension ResolvedTypeUtils on ResolvedType {
|
|||
case CastMode.numeric:
|
||||
case CastMode.numericPreferInt:
|
||||
if (type == BasicType.int || type == BasicType.real) {
|
||||
final newHint = dropTypeHint ? null : hint;
|
||||
|
||||
if (newHint != hint) {
|
||||
if (dropTypeHint && hints.isNotEmpty) {
|
||||
return ResolvedType(
|
||||
type: type,
|
||||
hint: newHint,
|
||||
hints: const [],
|
||||
nullable: nullable,
|
||||
isArray: isArray,
|
||||
);
|
||||
|
|
|
@ -581,7 +581,7 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
|
|||
case 'timediff':
|
||||
return _textType;
|
||||
case 'datetime':
|
||||
return _textType.copyWith(hint: const IsDateTime(), nullable: true);
|
||||
return _textType.copyWith(hints: const [IsDateTime()], nullable: true);
|
||||
case 'changes':
|
||||
case 'last_insert_rowid':
|
||||
case 'random':
|
||||
|
@ -655,7 +655,7 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
|
|||
return null;
|
||||
case 'unixepoch':
|
||||
return const ResolvedType(
|
||||
type: BasicType.int, nullable: true, hint: IsDateTime());
|
||||
type: BasicType.int, nullable: true, hints: [IsDateTime()]);
|
||||
}
|
||||
|
||||
final extensionHandler = _functionHandlerFor(e);
|
||||
|
@ -710,7 +710,7 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
|
|||
param,
|
||||
const ExactTypeExpectation(ResolvedType(
|
||||
type: BasicType.text,
|
||||
hint: IsDateTime(),
|
||||
hints: [IsDateTime()],
|
||||
)));
|
||||
visited.add(param);
|
||||
}
|
||||
|
|
|
@ -28,10 +28,10 @@ class TypeInferenceSession {
|
|||
if (expectation is ExactTypeExpectation) {
|
||||
final expectedType = expectation.type;
|
||||
|
||||
if (expectedType.hint != null &&
|
||||
r.hint == null &&
|
||||
if (expectedType.hints.isNotEmpty &&
|
||||
r.hints.isEmpty &&
|
||||
expectedType.type == r.type) {
|
||||
r = r.copyWith(hint: expectedType.hint);
|
||||
r = r.copyWith(hints: expectedType.hints);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: sqlparser
|
||||
description: Parses sqlite statements and performs static analysis on them
|
||||
version: 0.31.3
|
||||
version: 0.32.0-dev
|
||||
homepage: https://github.com/simolus3/drift/tree/develop/sqlparser
|
||||
repository: https://github.com/simolus3/drift
|
||||
#homepage: https://drift.simonbinder.eu/
|
||||
|
|
|
@ -20,7 +20,7 @@ final Table demoTable = Table(
|
|||
final TableColumn anotherId =
|
||||
TableColumn('id', const ResolvedType(type: BasicType.int));
|
||||
final TableColumn dateTime = TableColumn(
|
||||
'date', const ResolvedType(type: BasicType.int, hint: IsDateTime()));
|
||||
'date', const ResolvedType(type: BasicType.int, hints: [IsDateTime()]));
|
||||
|
||||
final Table anotherTable = Table(
|
||||
name: 'tbl',
|
||||
|
|
|
@ -110,10 +110,10 @@ void main() {
|
|||
final table = const SchemaFromCreateTable(driftExtensions: true)
|
||||
.read(stmt as CreateTableStatement);
|
||||
expect(table.resolvedColumns.map((c) => c.type), const [
|
||||
ResolvedType(type: BasicType.int, hint: IsBoolean(), nullable: true),
|
||||
ResolvedType(type: BasicType.int, hint: IsDateTime(), nullable: true),
|
||||
ResolvedType(type: BasicType.int, hint: IsDateTime(), nullable: true),
|
||||
ResolvedType(type: BasicType.int, hint: IsBoolean(), nullable: false),
|
||||
ResolvedType(type: BasicType.int, hints: [IsBoolean()], nullable: true),
|
||||
ResolvedType(type: BasicType.int, hints: [IsDateTime()], nullable: true),
|
||||
ResolvedType(type: BasicType.int, hints: [IsDateTime()], nullable: true),
|
||||
ResolvedType(type: BasicType.int, hints: [IsBoolean()], nullable: false),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ const Map<String, ResolvedType?> _types = {
|
|||
'SELECT * FROM demo WHERE content IN (?)':
|
||||
ResolvedType(type: BasicType.text, isArray: false),
|
||||
'SELECT * FROM demo JOIN tbl ON demo.id = tbl.id WHERE date = ?':
|
||||
ResolvedType(type: BasicType.int, hint: IsDateTime()),
|
||||
ResolvedType(type: BasicType.int, hints: [IsDateTime()]),
|
||||
'SELECT row_number() OVER (RANGE ? PRECEDING)':
|
||||
ResolvedType(type: BasicType.int),
|
||||
'SELECT ?;': null,
|
||||
|
@ -55,9 +55,9 @@ const Map<String, ResolvedType?> _types = {
|
|||
'SELECT MAX(id, ?) FROM demo': ResolvedType(type: BasicType.int),
|
||||
'SELECT SUM(id = 2) = ? FROM demo': ResolvedType(type: BasicType.int),
|
||||
"SELECT unixepoch('now') = ?":
|
||||
ResolvedType(type: BasicType.int, nullable: true, hint: IsDateTime()),
|
||||
ResolvedType(type: BasicType.int, nullable: true, hints: [IsDateTime()]),
|
||||
"SELECT datetime('now') = ?":
|
||||
ResolvedType(type: BasicType.text, nullable: true, hint: IsDateTime()),
|
||||
ResolvedType(type: BasicType.text, nullable: true, hints: [IsDateTime()]),
|
||||
'SELECT CAST(NULLIF(1, 2) AS INTEGER) = ?': ResolvedType(
|
||||
type: BasicType.int,
|
||||
nullable: true,
|
||||
|
|
|
@ -108,7 +108,7 @@ void main() {
|
|||
|
||||
test('infers condition', () {
|
||||
expect(resolveFirstVariable('SELECT IIF(?, 0, 1)'),
|
||||
const ResolvedType(type: BasicType.int, hint: IsBoolean()));
|
||||
const ResolvedType(type: BasicType.int, hints: [IsBoolean()]));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -183,7 +183,7 @@ void main() {
|
|||
|
||||
expect(resultType, const ResolvedType(type: BasicType.text));
|
||||
expect(argType,
|
||||
const ResolvedType(type: BasicType.text, hint: IsDateTime()));
|
||||
const ResolvedType(type: BasicType.text, hints: [IsDateTime()]));
|
||||
});
|
||||
|
||||
test('octet_length', () {
|
||||
|
@ -298,7 +298,7 @@ WITH RECURSIVE
|
|||
});
|
||||
|
||||
test('resolves type hints from between expressions', () {
|
||||
const dateTime = ResolvedType(type: BasicType.int, hint: IsDateTime());
|
||||
const dateTime = ResolvedType(type: BasicType.int, hints: [IsDateTime()]);
|
||||
final session = obtainResolver(
|
||||
'SELECT 1 WHERE :date BETWEEN :start AND :end',
|
||||
options: const AnalyzeStatementOptions(
|
||||
|
|
Loading…
Reference in New Issue