From df6f6fafa2f8300929e2cdac4d26f1f8524c4bc7 Mon Sep 17 00:00:00 2001 From: Markus Richter <8398165+mqus@users.noreply.github.com> Date: Sat, 16 May 2020 13:50:30 +0200 Subject: [PATCH] Add NamedResultSet type, adress review issues --- sqlparser/lib/src/analysis/analysis.dart | 1 + sqlparser/lib/src/analysis/schema/column.dart | 4 +- .../lib/src/analysis/schema/resultset.dart | 49 +++++++++++++++++++ sqlparser/lib/src/analysis/schema/table.dart | 40 +-------------- sqlparser/lib/src/analysis/schema/view.dart | 30 ++++-------- .../autocomplete/descriptions/references.dart | 2 +- sqlparser/lib/src/engine/sql_engine.dart | 20 ++++++-- 7 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 sqlparser/lib/src/analysis/schema/resultset.dart diff --git a/sqlparser/lib/src/analysis/analysis.dart b/sqlparser/lib/src/analysis/analysis.dart index 9de7d220..f3dd9cb6 100644 --- a/sqlparser/lib/src/analysis/analysis.dart +++ b/sqlparser/lib/src/analysis/analysis.dart @@ -16,6 +16,7 @@ part 'error.dart'; part 'schema/column.dart'; part 'schema/from_create_table.dart'; part 'schema/references.dart'; +part 'schema/resultset.dart'; part 'schema/table.dart'; part 'schema/view.dart'; part 'steps/column_resolver.dart'; diff --git a/sqlparser/lib/src/analysis/schema/column.dart b/sqlparser/lib/src/analysis/schema/column.dart index ab56927c..3a82d163 100644 --- a/sqlparser/lib/src/analysis/schema/column.dart +++ b/sqlparser/lib/src/analysis/schema/column.dart @@ -114,8 +114,8 @@ class ViewColumn extends Column with DelegatedColumn { /// The view this column belongs to. View view; - /// Creates a view column wrapping a [Column] from the select statement used to - /// create the view. + /// Creates a view column wrapping a [Column] from the select statement used + /// to create the view. /// /// The optional name parameter can be used to override the name for this column. /// By default, the name of the [innerColumn] will be used. diff --git a/sqlparser/lib/src/analysis/schema/resultset.dart b/sqlparser/lib/src/analysis/schema/resultset.dart new file mode 100644 index 00000000..be471c38 --- /dev/null +++ b/sqlparser/lib/src/analysis/schema/resultset.dart @@ -0,0 +1,49 @@ +part of '../analysis.dart'; + +/// Something that will resolve to an [ResultSet] when referred to via +/// the [ReferenceScope]. +abstract class ResolvesToResultSet with Referencable { + ResultSet get resultSet; +} + +/// Something that returns a set of columns when evaluated. +abstract class ResultSet implements ResolvesToResultSet { + /// The columns that will be returned when evaluating this query. + List get resolvedColumns; + + @override + ResultSet get resultSet => this; + + @override + bool get visibleToChildren => false; + + Column findColumn(String name) { + return resolvedColumns.firstWhere((c) => c.name == name, + orElse: () => null); + } +} + +/// A custom result set that has columns but isn't a table. +class CustomResultSet with ResultSet { + @override + final List resolvedColumns; + + CustomResultSet(this.resolvedColumns); +} + +/// Something that returns a set of Columns and can be referenced by a name, +/// such as a table or a view. +abstract class NamedResultSet extends ResultSet{ + /// The name of this result set, as it appears in sql statements. This should + /// be the raw name, not an escaped version. + /// + /// To obtain an escaped name, use [escapedName]. + String get name; + + /// If [name] is a reserved sql keyword, wraps it in double ticks. Otherwise + /// just returns the [name] directly. + String get escapedName { + return isKeywordLexeme(name) ? '"$name"' : name; + } + +} \ No newline at end of file diff --git a/sqlparser/lib/src/analysis/schema/table.dart b/sqlparser/lib/src/analysis/schema/table.dart index 71eef9e9..275acec4 100644 --- a/sqlparser/lib/src/analysis/schema/table.dart +++ b/sqlparser/lib/src/analysis/schema/table.dart @@ -4,52 +4,16 @@ part of '../analysis.dart'; /// https://www.sqlite.org/lang_createtable.html#rowid const aliasesForRowId = ['rowid', 'oid', '_rowid_']; -/// Something that will resolve to an [ResultSet] when referred to via -/// the [ReferenceScope]. -abstract class ResolvesToResultSet with Referencable { - ResultSet get resultSet; -} - -/// Something that returns a set of columns when evaluated. -abstract class ResultSet implements ResolvesToResultSet { - /// The columns that will be returned when evaluating this query. - List get resolvedColumns; - - @override - ResultSet get resultSet => this; - - @override - bool get visibleToChildren => false; - - Column findColumn(String name) { - return resolvedColumns.firstWhere((c) => c.name == name, - orElse: () => null); - } -} - -/// A custom result set that has columns but isn't a table. -class CustomResultSet with ResultSet { - @override - final List resolvedColumns; - - CustomResultSet(this.resolvedColumns); -} - /// A database table. The information stored here will be used to resolve /// references and for type inference. -class Table with ResultSet, HasMetaMixin implements HumanReadable { +class Table extends NamedResultSet with HasMetaMixin implements HumanReadable { /// The name of this table, as it appears in sql statements. This should be /// the raw name, not an escaped version. /// /// To obtain an escaped name, use [escapedName]. + @override final String name; - /// If [name] is a reserved sql keyword, wraps it in double ticks. Otherwise - /// just returns the [name] directly. - String get escapedName { - return isKeywordLexeme(name) ? '"$name"' : name; - } - @override final List resolvedColumns; diff --git a/sqlparser/lib/src/analysis/schema/view.dart b/sqlparser/lib/src/analysis/schema/view.dart index 035b2be4..6d07a2e3 100644 --- a/sqlparser/lib/src/analysis/schema/view.dart +++ b/sqlparser/lib/src/analysis/schema/view.dart @@ -2,28 +2,16 @@ part of '../analysis.dart'; /// A database view. The information stored here will be used to resolve /// references and for type inference. -class View with HasMetaMixin, ResultSet implements HumanReadable { - /// The name of this view, as it appears in sql statements. This should be - /// the raw name, not an escaped version. - /// - /// To obtain an escaped name, use [escapedName]. +class View extends NamedResultSet with HasMetaMixin implements HumanReadable { + @override final String name; - /// If [name] is a reserved sql keyword, wraps it in double ticks. Otherwise - /// just returns the [name] directly. - String get escapedName { - return isKeywordLexeme(name) ? '"$name"' : name; - } - @override final List resolvedColumns; /// The ast node that created this table final CreateViewStatement definition; - @override - bool get visibleToChildren => true; - /// Constructs a view from the known [name] and [selectColumns]. View({ @required this.name, @@ -42,13 +30,13 @@ class View with HasMetaMixin, ResultSet implements HumanReadable { String humanReadableDescription() { return name; } -} -List _createColumns( - List resolvedColumns, List columnNames) { - final columns = List(resolvedColumns.length); - for (var i = 0; i < resolvedColumns.length; ++i) { - columns[i] = ViewColumn(resolvedColumns[i], columnNames?.elementAt(i)); + static List _createColumns( + List resolvedColumns, List columnNames) { + final columns = List(resolvedColumns.length); + for (var i = 0; i < resolvedColumns.length; ++i) { + columns[i] = ViewColumn(resolvedColumns[i], columnNames?.elementAt(i)); + } + return columns; } - return columns; } diff --git a/sqlparser/lib/src/engine/autocomplete/descriptions/references.dart b/sqlparser/lib/src/engine/autocomplete/descriptions/references.dart index 8e65277f..f9261ad2 100644 --- a/sqlparser/lib/src/engine/autocomplete/descriptions/references.dart +++ b/sqlparser/lib/src/engine/autocomplete/descriptions/references.dart @@ -6,7 +6,7 @@ class TableNameDescription extends HintDescription { @override Iterable suggest(CalculationRequest request) { - final tableNames = request.engine.knownTables.map((t) => t.escapedName); + final tableNames = request.engine.knownResultSets.map((t) => t.escapedName); return tableNames.map((t) { return Suggestion(t, 1); diff --git a/sqlparser/lib/src/engine/sql_engine.dart b/sqlparser/lib/src/engine/sql_engine.dart index c5942ada..65a95f3b 100644 --- a/sqlparser/lib/src/engine/sql_engine.dart +++ b/sqlparser/lib/src/engine/sql_engine.dart @@ -12,7 +12,7 @@ import 'builtin_tables.dart'; class SqlEngine { /// All tables registered with [registerTable]. - final List knownTables = []; + final List knownResultSets = []; final List _knownModules = []; /// Internal options for this sql engine. @@ -43,7 +43,19 @@ class SqlEngine { /// Registers the [table], which means that it can later be used in sql /// statements. void registerTable(Table table) { - knownTables.add(table); + registerResultSet(table); + } + + /// Registers the [view], which means that it can later be used in sql + /// statements. + void registerView(View view) { + registerResultSet(view); + } + + /// Registers an arbitrary [namedResultSet], which means that it can later + /// be used in sql statements. + void registerResultSet(NamedResultSet namedResultSet) { + knownResultSets.add(namedResultSet); } /// Registers the [module], which means that it can be used as a function in @@ -67,8 +79,8 @@ class SqlEngine { ReferenceScope _constructRootScope({ReferenceScope parent}) { final scope = parent == null ? ReferenceScope(null) : parent.createChild(); - for (final table in knownTables) { - scope.register(table.name, table); + for (final resultSet in knownResultSets) { + scope.register(resultSet.name, resultSet); } for (final module in _knownModules) {