From ffe4bb8c82182c84b15dccd6ccd4820a5715d6d7 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 16 Dec 2019 13:24:29 +0100 Subject: [PATCH] Don't crash when trying to resolve variables --- .../lib/src/analysis/types/resolver.dart | 26 ++++++++++--------- .../test/analysis/type_resolver_test.dart | 1 + 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/sqlparser/lib/src/analysis/types/resolver.dart b/sqlparser/lib/src/analysis/types/resolver.dart index 7d0bbe11..3a2fe6a5 100644 --- a/sqlparser/lib/src/analysis/types/resolver.dart +++ b/sqlparser/lib/src/analysis/types/resolver.dart @@ -125,9 +125,8 @@ class TypeResolver { if (_comparisonOperators.contains(operator)) { return const ResolveResult(ResolvedType.bool()); } else { - final type = _encapsulate(expr.childNodes.cast(), + return _encapsulate(expr.childNodes.cast(), [BasicType.int, BasicType.real, BasicType.text, BasicType.blob]); - return ResolveResult(type); } } else if (expr is CaseExpression) { return resolveExpression(expr.whens.first.then); @@ -141,7 +140,7 @@ class TypeResolver { } } - throw StateError('Unknown expression $expr'); + return const ResolveResult.unknown(); }, expr); } @@ -265,8 +264,8 @@ class TypeResolver { return justResolve(parameters.first); case 'coalesce': case 'ifnull': - return ResolveResult(_encapsulate(parameters, - [BasicType.int, BasicType.real, BasicType.text, BasicType.blob])); + return _encapsulate(parameters, + [BasicType.int, BasicType.real, BasicType.text, BasicType.blob]); case 'nullif': return justResolve(parameters.first).withNullable(true); case 'first_value': @@ -276,19 +275,19 @@ class TypeResolver { case 'nth_value': return justResolve(parameters.first); case 'max': - return ResolveResult(_encapsulate(parameters, [ + return _encapsulate(parameters, [ BasicType.int, BasicType.real, BasicType.text, BasicType.blob - ])).withNullable(true); + ]).withNullable(true); case 'min': - return ResolveResult(_encapsulate(parameters, [ + return _encapsulate(parameters, [ BasicType.blob, BasicType.text, BasicType.int, BasicType.real - ])).withNullable(true); + ]).withNullable(true); } if (options.enableJson1) { @@ -431,15 +430,18 @@ class TypeResolver { /// Returns the type of an expression in [expressions] that has the highest /// order in [types]. - ResolvedType _encapsulate( + ResolveResult _encapsulate( Iterable expressions, List types) { final argTypes = expressions .map((expr) => justResolve(expr).type) .where((t) => t != null); - final type = types.lastWhere((t) => argTypes.any((arg) => arg.type == t)); + final type = types.lastWhere((t) => argTypes.any((arg) => arg.type == t), + orElse: () => null); + if (type == null) return const ResolveResult.unknown(); + final notNull = argTypes.any((t) => !t.nullable); - return ResolvedType(type: type, nullable: !notNull); + return ResolveResult(ResolvedType(type: type, nullable: !notNull)); } } diff --git a/sqlparser/test/analysis/type_resolver_test.dart b/sqlparser/test/analysis/type_resolver_test.dart index a323a944..8d303d74 100644 --- a/sqlparser/test/analysis/type_resolver_test.dart +++ b/sqlparser/test/analysis/type_resolver_test.dart @@ -29,6 +29,7 @@ Map _types = { ResolvedType(type: BasicType.int, hint: IsDateTime())), 'SELECT row_number() OVER (RANGE ? PRECEDING)': const ResolveResult(ResolvedType(type: BasicType.int)), + 'SELECT ?;': const ResolveResult.unknown(), }; void main() {