diff --git a/drift_dev/lib/src/analyzer/sql_queries/nested_queries.dart b/drift_dev/lib/src/analyzer/sql_queries/nested_queries.dart index 695a6bc7..8dbde3c2 100644 --- a/drift_dev/lib/src/analyzer/sql_queries/nested_queries.dart +++ b/drift_dev/lib/src/analyzer/sql_queries/nested_queries.dart @@ -1,3 +1,4 @@ +import 'package:drift_dev/src/model/model.dart'; import 'package:sqlparser/sqlparser.dart'; /// Analysis support for nested queries. @@ -112,35 +113,10 @@ class _AnalyzerState { _AnalyzerState(this.container); - void _process() => container._processAfterVisit(actualAndAddedVariables); -} - -/// Something that can contain nested queries. -/// -/// This contains the root select statement and all nested queries that appear -/// in a nested queries container. -class NestedQueriesContainer { - final SelectStatement select; - final Map nestedQueries = {}; - - NestedQueriesContainer(this.select); - - /// Columns that should be added to the [select] statement to read variables - /// captured by children. - /// - /// These columns aren't mounted to the same syntax tree as [select], they - /// will be mounted into the tree returned by [addHelperNodes]. - final List addedColumns = []; - - Iterable get variablesCapturedByChildren { - return nestedQueries.values - .expand((nested) => nested.capturedVariables.values); - } - - void _processAfterVisit(List variables) { - // Add necessary columns - for (final variable in variablesCapturedByChildren) { - addedColumns.add( + void _process() { + // Add necessary columns to select variables read by inner nested queries. + for (final variable in container.variablesCapturedByChildren) { + container.addedColumns.add( ExpressionResultColumn( expression: Reference( entityName: variable.reference.entityName, @@ -153,41 +129,7 @@ class NestedQueriesContainer { // Re-index variables, this time also considering the synthetic variables // that we'll insert in [addHelperNodes] later. - AstPreparingVisitor.resolveIndexOfVariables(variables); - } -} - -class NestedQuery extends NestedQueriesContainer { - final NestedQueryColumn queryColumn; - final NestedQueriesContainer parent; - - /// All references that read from a table only available in the outer - /// select statement. It will need to be transformed in a later step. - final Map capturedVariables = {}; - - NestedQuery(this.parent, this.queryColumn) : super(queryColumn.select); -} - -class CapturedVariable { - final Reference reference; - - /// A number uniquely identifying this captured variable in the select - /// statement analyzed. - /// - /// This is used to add the necessary helper column later. - final int queryGlobalId; - - /// The variable introduced to replace the original reference. - /// - /// This variable is not mounted to the same syntax tree as [reference], it - /// will be mounted into the tree returned by [addHelperNodes]. - final ColonNamedVariable introducedVariable; - - String get helperColumn => '\$n_$queryGlobalId'; - - CapturedVariable(this.reference, this.queryGlobalId) - : introducedVariable = ColonNamedVariable.synthetic(':r$queryGlobalId') { - introducedVariable.setMeta(this); + AstPreparingVisitor.resolveIndexOfVariables(actualAndAddedVariables); } } diff --git a/drift_dev/lib/src/analyzer/sql_queries/type_mapping.dart b/drift_dev/lib/src/analyzer/sql_queries/type_mapping.dart index 112df805..9017489a 100644 --- a/drift_dev/lib/src/analyzer/sql_queries/type_mapping.dart +++ b/drift_dev/lib/src/analyzer/sql_queries/type_mapping.dart @@ -4,7 +4,6 @@ import 'package:drift_dev/src/utils/type_converter_hint.dart'; import 'package:sqlparser/sqlparser.dart'; import 'package:sqlparser/utils/find_referenced_tables.dart' as s; -import 'nested_queries.dart'; import 'required_variables.dart'; /// Converts tables and types between the moor_generator and the sqlparser diff --git a/drift_dev/lib/src/model/sql_query.dart b/drift_dev/lib/src/model/sql_query.dart index 025ae0e9..4b72237c 100644 --- a/drift_dev/lib/src/model/sql_query.dart +++ b/drift_dev/lib/src/model/sql_query.dart @@ -240,6 +240,66 @@ class SqlSelectQuery extends SqlQuery { } } +/// Something that can contain nested queries. +/// +/// This contains the root select statement and all nested queries that appear +/// in a nested queries container. +class NestedQueriesContainer { + final SelectStatement select; + final Map nestedQueries = {}; + + NestedQueriesContainer(this.select); + + /// Columns that should be added to the [select] statement to read variables + /// captured by children. + /// + /// These columns aren't mounted to the same syntax tree as [select], they + /// will be mounted into the tree returned by [addHelperNodes]. + final List addedColumns = []; + + Iterable get variablesCapturedByChildren { + return nestedQueries.values + .expand((nested) => nested.capturedVariables.values); + } +} + +/// A nested query found in a SQL statement. +/// +/// See the `NestedQueryAnalyzer` for an overview on how nested queries work. +class NestedQuery extends NestedQueriesContainer { + final NestedQueryColumn queryColumn; + final NestedQueriesContainer parent; + + /// All references that read from a table only available in the outer + /// select statement. It will need to be transformed in a later step. + final Map capturedVariables = {}; + + NestedQuery(this.parent, this.queryColumn) : super(queryColumn.select); +} + +class CapturedVariable { + final Reference reference; + + /// A number uniquely identifying this captured variable in the select + /// statement analyzed. + /// + /// This is used to add the necessary helper column later. + final int queryGlobalId; + + /// The variable introduced to replace the original reference. + /// + /// This variable is not mounted to the same syntax tree as [reference], it + /// will be mounted into the tree returned by [addHelperNodes]. + final ColonNamedVariable introducedVariable; + + String get helperColumn => '\$n_$queryGlobalId'; + + CapturedVariable(this.reference, this.queryGlobalId) + : introducedVariable = ColonNamedVariable.synthetic(':r$queryGlobalId') { + introducedVariable.setMeta(this); + } +} + class UpdatingQuery extends SqlQuery { final List updates; final bool isInsert;