Add NamedResultSet type, adress review issues

This commit is contained in:
Markus Richter 2020-05-16 13:50:30 +02:00
parent 0bc2a7548d
commit df6f6fafa2
No known key found for this signature in database
GPG Key ID: D2EAD1C38ED66957
7 changed files with 80 additions and 66 deletions

View File

@ -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';

View File

@ -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.

View File

@ -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<Column> 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<Column> 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;
}
}

View File

@ -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<Column> 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<Column> 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<TableColumn> resolvedColumns;

View File

@ -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<ViewColumn> 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<ViewColumn> _createColumns(
List<Column> resolvedColumns, List<String> columnNames) {
final columns = List<ViewColumn>(resolvedColumns.length);
for (var i = 0; i < resolvedColumns.length; ++i) {
columns[i] = ViewColumn(resolvedColumns[i], columnNames?.elementAt(i));
static List<ViewColumn> _createColumns(
List<Column> resolvedColumns, List<String> columnNames) {
final columns = List<ViewColumn>(resolvedColumns.length);
for (var i = 0; i < resolvedColumns.length; ++i) {
columns[i] = ViewColumn(resolvedColumns[i], columnNames?.elementAt(i));
}
return columns;
}
return columns;
}

View File

@ -6,7 +6,7 @@ class TableNameDescription extends HintDescription {
@override
Iterable<Suggestion> 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);

View File

@ -12,7 +12,7 @@ import 'builtin_tables.dart';
class SqlEngine {
/// All tables registered with [registerTable].
final List<Table> knownTables = [];
final List<NamedResultSet> knownResultSets = [];
final List<Module> _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) {