mirror of https://github.com/AMT-Cheif/drift.git
Fix nullability propagation for type analysis
This commit is contained in:
parent
a463476c44
commit
9c80fb047b
|
@ -35,7 +35,8 @@ class ResolvedType {
|
|||
ResolvedType get withoutNullabilityInfo {
|
||||
return nullable == null
|
||||
? this
|
||||
: ResolvedType(type: type, hint: hint, isArray: isArray);
|
||||
: ResolvedType(
|
||||
type: type, hint: hint, isArray: isArray, nullable: null);
|
||||
}
|
||||
|
||||
ResolvedType withNullable(bool nullable) {
|
||||
|
|
|
@ -41,6 +41,14 @@ class TypeGraph {
|
|||
bool knowsType(Typeable? t) =>
|
||||
_knownTypes.containsKey(variables.normalize(t));
|
||||
|
||||
bool knowsNullability(Typeable? t) {
|
||||
final normalized = variables.normalize(t);
|
||||
final knownType = _knownTypes[normalized];
|
||||
|
||||
return (knownType != null && knownType.nullable != null) ||
|
||||
_knownNullability.containsKey(normalized);
|
||||
}
|
||||
|
||||
void addRelation(TypeRelation relation) {
|
||||
_relations.add(relation);
|
||||
}
|
||||
|
|
|
@ -323,7 +323,7 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
|
|||
break;
|
||||
case TokenType.doublePipe:
|
||||
// string concatenation.
|
||||
session._checkAndResolve(e, _textType, arg);
|
||||
session._checkAndResolve(e, _textType.withoutNullabilityInfo, arg);
|
||||
session._addRelation(NullableIfSomeOtherIs(e, [e.left, e.right]));
|
||||
const childExpectation = ExactTypeExpectation.laxly(_textType);
|
||||
visit(e.left, childExpectation);
|
||||
|
@ -502,7 +502,7 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
|
|||
case 'trim':
|
||||
case 'upper':
|
||||
nullableIfChildIs();
|
||||
return _textType;
|
||||
return _textType.withoutNullabilityInfo;
|
||||
case 'group_concat':
|
||||
return _textType.withNullable(true);
|
||||
case 'date':
|
||||
|
@ -668,8 +668,15 @@ class TypeResolver extends RecursiveVisitor<TypeExpectation, void> {
|
|||
void _lazyCopy(Typeable to, Typeable? from, {bool makeNullable = false}) {
|
||||
if (session.graph.knowsType(from)) {
|
||||
var type = session.typeOf(from)!;
|
||||
if (makeNullable) type = type.withNullable(true);
|
||||
session._markTypeResolved(to, type);
|
||||
if (makeNullable) {
|
||||
type = type.withNullable(true);
|
||||
session._markTypeResolved(to, type);
|
||||
} else if (session.graph.knowsNullability(from)) {
|
||||
session._markTypeResolved(to, type);
|
||||
} else {
|
||||
session._markTypeResolved(to, type);
|
||||
session._addRelation(NullableIfSomeOtherIs(to, [from!]));
|
||||
}
|
||||
} else {
|
||||
session._addRelation(CopyTypeFrom(to, from, makeNullable: makeNullable));
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ WITH RECURSIVE
|
|||
SELECT x+1 FROM cnt
|
||||
LIMIT 1000000
|
||||
)
|
||||
SELECT x FROM cnt;
|
||||
SELECT x FROM cnt;
|
||||
''');
|
||||
|
||||
final expressions = content.root.allDescendants.whereType<Expression>();
|
||||
|
@ -92,4 +92,20 @@ WITH RECURSIVE
|
|||
everyElement(isNotNull),
|
||||
);
|
||||
});
|
||||
|
||||
test('concatenation is nullable when any part is', () {
|
||||
// https://github.com/simolus3/moor/issues/1719
|
||||
|
||||
final engine = SqlEngine()
|
||||
..registerTableFromSql('CREATE TABLE foobar (foo TEXT, bar TEXT);');
|
||||
|
||||
final content =
|
||||
engine.analyze("SELECT foo, bar, foo || ' ' || bar FROM foobar;");
|
||||
|
||||
final columns = (content.root as SelectStatement).resolvedColumns!;
|
||||
expect(
|
||||
columns.map(content.typeOf),
|
||||
everyElement(isA<ResolveResult>()
|
||||
.having((e) => e.type?.nullable, 'type.nullable', isTrue)));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue