mirror of https://github.com/AMT-Cheif/drift.git
Build options to enable types2 inference
This commit is contained in:
parent
523eabaa2a
commit
70259c8f83
|
@ -52,6 +52,9 @@ At the moment, moor supports these options:
|
||||||
column constraint (e.g. `user_name VARCHAR NOT NULL JSON KEY userName`)
|
column constraint (e.g. `user_name VARCHAR NOT NULL JSON KEY userName`)
|
||||||
* `generate_connect_constructor`: Generate necessary code to support the [isolate runtime]({{< relref "isolates.md" >}}).
|
* `generate_connect_constructor`: Generate necessary code to support the [isolate runtime]({{< relref "isolates.md" >}}).
|
||||||
This is a build option because isolates are still experimental. This will be the default option eventually.
|
This is a build option because isolates are still experimental. This will be the default option eventually.
|
||||||
|
* `use_experimental_inference`: Use a new, experimental type inference algorithm when analyzing sql statements. The
|
||||||
|
algorithm is designed to yield more accurate results on nullability and complex constructs. Note that it's in a
|
||||||
|
preview state at the moment, which means that generated code might change after a minor update.
|
||||||
* `sqlite_modules`: This list can be used to enable sqlite extensions, like those for json or full-text search.
|
* `sqlite_modules`: This list can be used to enable sqlite extensions, like those for json or full-text search.
|
||||||
Modules have to be enabled explicitly because they're not supported on all platforms. See the following section for
|
Modules have to be enabled explicitly because they're not supported on all platforms. See the following section for
|
||||||
details.
|
details.
|
||||||
|
|
|
@ -54,6 +54,12 @@ class MoorOptions {
|
||||||
@JsonKey(name: 'generate_connect_constructor', defaultValue: false)
|
@JsonKey(name: 'generate_connect_constructor', defaultValue: false)
|
||||||
final bool generateConnectConstructor;
|
final bool generateConnectConstructor;
|
||||||
|
|
||||||
|
/// Whether the new, experimental type inference engine should be used.
|
||||||
|
///
|
||||||
|
/// The new engine is experimental at the moment.
|
||||||
|
@JsonKey(name: 'use_experimental_inference', defaultValue: false)
|
||||||
|
final bool useExperimentalInference;
|
||||||
|
|
||||||
@JsonKey(name: 'sqlite_modules', defaultValue: [])
|
@JsonKey(name: 'sqlite_modules', defaultValue: [])
|
||||||
final List<SqlModule> modules;
|
final List<SqlModule> modules;
|
||||||
|
|
||||||
|
@ -68,6 +74,7 @@ class MoorOptions {
|
||||||
this.useDataClassNameForCompanions = false,
|
this.useDataClassNameForCompanions = false,
|
||||||
this.useColumnNameAsJsonKeyWhenDefinedInMoorFile = false,
|
this.useColumnNameAsJsonKeyWhenDefinedInMoorFile = false,
|
||||||
this.generateConnectConstructor = false,
|
this.generateConnectConstructor = false,
|
||||||
|
this.useExperimentalInference,
|
||||||
this.modules = const []});
|
this.modules = const []});
|
||||||
|
|
||||||
factory MoorOptions.fromJson(Map<String, dynamic> json) =>
|
factory MoorOptions.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|
|
@ -16,6 +16,7 @@ MoorOptions _$MoorOptionsFromJson(Map<String, dynamic> json) {
|
||||||
'use_data_class_name_for_companions',
|
'use_data_class_name_for_companions',
|
||||||
'use_column_name_as_json_key_when_defined_in_moor_file',
|
'use_column_name_as_json_key_when_defined_in_moor_file',
|
||||||
'generate_connect_constructor',
|
'generate_connect_constructor',
|
||||||
|
'use_experimental_inference',
|
||||||
'sqlite_modules'
|
'sqlite_modules'
|
||||||
]);
|
]);
|
||||||
final val = MoorOptions(
|
final val = MoorOptions(
|
||||||
|
@ -42,6 +43,9 @@ MoorOptions _$MoorOptionsFromJson(Map<String, dynamic> json) {
|
||||||
generateConnectConstructor: $checkedConvert(
|
generateConnectConstructor: $checkedConvert(
|
||||||
json, 'generate_connect_constructor', (v) => v as bool) ??
|
json, 'generate_connect_constructor', (v) => v as bool) ??
|
||||||
false,
|
false,
|
||||||
|
useExperimentalInference: $checkedConvert(
|
||||||
|
json, 'use_experimental_inference', (v) => v as bool) ??
|
||||||
|
false,
|
||||||
modules: $checkedConvert(
|
modules: $checkedConvert(
|
||||||
json,
|
json,
|
||||||
'sqlite_modules',
|
'sqlite_modules',
|
||||||
|
@ -61,6 +65,7 @@ MoorOptions _$MoorOptionsFromJson(Map<String, dynamic> json) {
|
||||||
'useColumnNameAsJsonKeyWhenDefinedInMoorFile':
|
'useColumnNameAsJsonKeyWhenDefinedInMoorFile':
|
||||||
'use_column_name_as_json_key_when_defined_in_moor_file',
|
'use_column_name_as_json_key_when_defined_in_moor_file',
|
||||||
'generateConnectConstructor': 'generate_connect_constructor',
|
'generateConnectConstructor': 'generate_connect_constructor',
|
||||||
|
'useExperimentalInference': 'use_experimental_inference',
|
||||||
'modules': 'sqlite_modules'
|
'modules': 'sqlite_modules'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,16 @@ class MoorSession {
|
||||||
|
|
||||||
/// Creates a properly configured [SqlEngine].
|
/// Creates a properly configured [SqlEngine].
|
||||||
SqlEngine spawnEngine() {
|
SqlEngine spawnEngine() {
|
||||||
return SqlEngine(
|
final sqlOptions = EngineOptions(
|
||||||
useMoorExtensions: true,
|
useMoorExtensions: true,
|
||||||
enableJson1Module: options.hasModule(SqlModule.json1),
|
enableJson1: options.hasModule(SqlModule.json1),
|
||||||
enableFts5: options.hasModule(SqlModule.fts5),
|
enabledExtensions: [
|
||||||
|
if (options.hasModule(SqlModule.fts5)) const Fts5Extension(),
|
||||||
|
],
|
||||||
|
enableExperimentalTypeInference: options.useExperimentalInference,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return SqlEngine.withOptions(sqlOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileType _findFileType(String path) {
|
FileType _findFileType(String path) {
|
||||||
|
|
|
@ -3,7 +3,9 @@ library sqlparser;
|
||||||
|
|
||||||
export 'src/analysis/analysis.dart';
|
export 'src/analysis/analysis.dart';
|
||||||
export 'src/ast/ast.dart';
|
export 'src/ast/ast.dart';
|
||||||
|
export 'src/engine/module/fts5.dart' show Fts5Extension;
|
||||||
export 'src/engine/module/module.dart';
|
export 'src/engine/module/module.dart';
|
||||||
|
export 'src/engine/options.dart';
|
||||||
export 'src/engine/sql_engine.dart';
|
export 'src/engine/sql_engine.dart';
|
||||||
export 'src/reader/parser/parser.dart' show ParsingError;
|
export 'src/reader/parser/parser.dart' show ParsingError;
|
||||||
export 'src/reader/syntactic_entity.dart';
|
export 'src/reader/syntactic_entity.dart';
|
||||||
|
|
|
@ -7,6 +7,9 @@ import 'package:sqlparser/src/engine/options.dart';
|
||||||
import 'package:sqlparser/src/reader/tokenizer/token.dart';
|
import 'package:sqlparser/src/reader/tokenizer/token.dart';
|
||||||
import 'package:sqlparser/src/utils/meta.dart';
|
import 'package:sqlparser/src/utils/meta.dart';
|
||||||
|
|
||||||
|
import 'types2/types.dart';
|
||||||
|
export 'types2/types.dart' show TypeInferenceResults;
|
||||||
|
|
||||||
part 'context.dart';
|
part 'context.dart';
|
||||||
part 'error.dart';
|
part 'error.dart';
|
||||||
part 'schema/column.dart';
|
part 'schema/column.dart';
|
||||||
|
|
|
@ -25,12 +25,28 @@ class AnalysisContext {
|
||||||
/// [ResultSet.resolvedColumns] of a select statement.
|
/// [ResultSet.resolvedColumns] of a select statement.
|
||||||
/* late final */ TypeResolver types;
|
/* late final */ TypeResolver types;
|
||||||
|
|
||||||
|
/// Experimental new type resolver with better support for nullability and
|
||||||
|
/// complex structures.
|
||||||
|
///
|
||||||
|
/// By using [TypeInferenceResults.typeOf], the type of an [Expression],
|
||||||
|
/// a [Variable] and [ResultSet.resolvedColumns] may be resolved or inferred.
|
||||||
|
///
|
||||||
|
/// This field is null when experimental type inference is disabled.
|
||||||
|
///
|
||||||
|
/// Please note that types2 is experimental at the moment. Changes to how
|
||||||
|
/// [types] resolves types are considered breaking and are handled
|
||||||
|
/// accordingly. [types2] may change results in any update.
|
||||||
|
@experimental
|
||||||
|
TypeInferenceResults types2;
|
||||||
|
|
||||||
/// Constructs a new analysis context from the AST and the source sql.
|
/// Constructs a new analysis context from the AST and the source sql.
|
||||||
AnalysisContext(this.root, this.sql, EngineOptions options,
|
AnalysisContext(this.root, this.sql, EngineOptions options,
|
||||||
{AnalyzeStatementOptions stmtOptions, this.schemaSupport})
|
{AnalyzeStatementOptions stmtOptions, this.schemaSupport})
|
||||||
: stmtOptions = stmtOptions ?? const AnalyzeStatementOptions() {
|
: stmtOptions = stmtOptions ?? const AnalyzeStatementOptions() {
|
||||||
|
if (!options.enableExperimentalTypeInference) {
|
||||||
types = TypeResolver(this, options);
|
types = TypeResolver(this, options);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reports an analysis error.
|
/// Reports an analysis error.
|
||||||
void reportError(AnalysisError error) {
|
void reportError(AnalysisError error) {
|
||||||
|
|
|
@ -11,8 +11,11 @@ part 'resolving_visitor.dart';
|
||||||
class TypeInferenceSession {
|
class TypeInferenceSession {
|
||||||
final TypeGraph graph = TypeGraph();
|
final TypeGraph graph = TypeGraph();
|
||||||
final AnalysisContext context;
|
final AnalysisContext context;
|
||||||
|
TypeInferenceResults results;
|
||||||
|
|
||||||
TypeInferenceSession(this.context);
|
TypeInferenceSession(this.context) {
|
||||||
|
results = TypeInferenceResults._(this);
|
||||||
|
}
|
||||||
|
|
||||||
void markTypeResolved(Typeable t, ResolvedType r) {
|
void markTypeResolved(Typeable t, ResolvedType r) {
|
||||||
graph[t] = r;
|
graph[t] = r;
|
||||||
|
@ -42,3 +45,16 @@ class TypeInferenceSession {
|
||||||
graph.performResolve();
|
graph.performResolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apis to view results of a type inference session.
|
||||||
|
class TypeInferenceResults {
|
||||||
|
final TypeInferenceSession session;
|
||||||
|
|
||||||
|
TypeInferenceResults._(this.session);
|
||||||
|
|
||||||
|
/// Finds the resolved type of [t], or `null` if the type of [t] could not
|
||||||
|
/// be inferred.
|
||||||
|
ResolvedType typeOf(Typeable t) {
|
||||||
|
return session.typeOf(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,14 +9,21 @@ class EngineOptions {
|
||||||
/// Enables functions declared in the `json1` module for analysis
|
/// Enables functions declared in the `json1` module for analysis
|
||||||
final bool enableJson1;
|
final bool enableJson1;
|
||||||
|
|
||||||
|
/// Enables the new, experimental type inference.
|
||||||
|
final bool enableExperimentalTypeInference;
|
||||||
|
|
||||||
/// All [Extension]s that have been enabled in this sql engine.
|
/// All [Extension]s that have been enabled in this sql engine.
|
||||||
final List<Extension> enabledExtensions;
|
final List<Extension> enabledExtensions;
|
||||||
|
|
||||||
final List<FunctionHandler> _addedFunctionHandlers = [];
|
final List<FunctionHandler> _addedFunctionHandlers = [];
|
||||||
final Map<String, FunctionHandler> addedFunctions = {};
|
final Map<String, FunctionHandler> addedFunctions = {};
|
||||||
|
|
||||||
EngineOptions(
|
EngineOptions({
|
||||||
this.useMoorExtensions, this.enableJson1, this.enabledExtensions);
|
this.useMoorExtensions = false,
|
||||||
|
this.enableJson1 = false,
|
||||||
|
this.enabledExtensions = const [],
|
||||||
|
this.enableExperimentalTypeInference = false,
|
||||||
|
});
|
||||||
|
|
||||||
void addFunctionHandler(FunctionHandler handler) {
|
void addFunctionHandler(FunctionHandler handler) {
|
||||||
_addedFunctionHandlers.add(handler);
|
_addedFunctionHandlers.add(handler);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:sqlparser/sqlparser.dart';
|
import 'package:sqlparser/sqlparser.dart';
|
||||||
|
import 'package:sqlparser/src/analysis/types2/types.dart' as t2;
|
||||||
import 'package:sqlparser/src/engine/module/fts5.dart';
|
import 'package:sqlparser/src/engine/module/fts5.dart';
|
||||||
import 'package:sqlparser/src/engine/options.dart';
|
import 'package:sqlparser/src/engine/options.dart';
|
||||||
import 'package:sqlparser/src/reader/parser/parser.dart';
|
import 'package:sqlparser/src/reader/parser/parser.dart';
|
||||||
|
@ -20,14 +21,18 @@ class SqlEngine {
|
||||||
|
|
||||||
SchemaFromCreateTable _schemaReader;
|
SchemaFromCreateTable _schemaReader;
|
||||||
|
|
||||||
|
@Deprecated('Use SqlEngine.withOptions instead')
|
||||||
SqlEngine(
|
SqlEngine(
|
||||||
{bool useMoorExtensions = false,
|
{bool useMoorExtensions = false,
|
||||||
bool enableJson1Module = false,
|
bool enableJson1Module = false,
|
||||||
bool enableFts5 = false})
|
bool enableFts5 = false})
|
||||||
: options = _constructOptions(
|
: this.withOptions(_constructOptions(
|
||||||
moor: useMoorExtensions,
|
moor: useMoorExtensions,
|
||||||
json1: enableJson1Module,
|
json1: enableJson1Module,
|
||||||
fts5: enableFts5) {
|
fts5: enableFts5,
|
||||||
|
));
|
||||||
|
|
||||||
|
SqlEngine.withOptions(this.options) {
|
||||||
for (final extension in options.enabledExtensions) {
|
for (final extension in options.enabledExtensions) {
|
||||||
extension.register(this);
|
extension.register(this);
|
||||||
}
|
}
|
||||||
|
@ -188,9 +193,19 @@ class SqlEngine {
|
||||||
|
|
||||||
node
|
node
|
||||||
..acceptWithoutArg(ColumnResolver(context))
|
..acceptWithoutArg(ColumnResolver(context))
|
||||||
..acceptWithoutArg(ReferenceResolver(context))
|
..acceptWithoutArg(ReferenceResolver(context));
|
||||||
..acceptWithoutArg(TypeResolvingVisitor(context))
|
|
||||||
..acceptWithoutArg(LintingVisitor(options, context));
|
if (options.enableExperimentalTypeInference) {
|
||||||
|
final session = t2.TypeInferenceSession(context);
|
||||||
|
final resolver = t2.TypeResolver(session);
|
||||||
|
node.acceptWithoutArg(resolver);
|
||||||
|
session.finish();
|
||||||
|
context.types2 = session.results;
|
||||||
|
} else {
|
||||||
|
node.acceptWithoutArg(TypeResolvingVisitor(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
node.acceptWithoutArg(LintingVisitor(options, context));
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +225,11 @@ class SqlEngine {
|
||||||
final extensions = [
|
final extensions = [
|
||||||
if (fts5) const Fts5Extension(),
|
if (fts5) const Fts5Extension(),
|
||||||
];
|
];
|
||||||
return EngineOptions(moor, json1, extensions);
|
return EngineOptions(
|
||||||
|
useMoorExtensions: moor,
|
||||||
|
enableJson1: json1,
|
||||||
|
enabledExtensions: extensions,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue