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/column.dart';
part 'schema/from_create_table.dart'; part 'schema/from_create_table.dart';
part 'schema/references.dart'; part 'schema/references.dart';
part 'schema/resultset.dart';
part 'schema/table.dart'; part 'schema/table.dart';
part 'schema/view.dart'; part 'schema/view.dart';
part 'steps/column_resolver.dart'; part 'steps/column_resolver.dart';

View File

@ -114,8 +114,8 @@ class ViewColumn extends Column with DelegatedColumn {
/// The view this column belongs to. /// The view this column belongs to.
View view; View view;
/// Creates a view column wrapping a [Column] from the select statement used to /// Creates a view column wrapping a [Column] from the select statement used
/// create the view. /// to create the view.
/// ///
/// The optional name parameter can be used to override the name for this column. /// The optional name parameter can be used to override the name for this column.
/// By default, the name of the [innerColumn] will be used. /// 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 /// https://www.sqlite.org/lang_createtable.html#rowid
const aliasesForRowId = ['rowid', 'oid', '_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 /// A database table. The information stored here will be used to resolve
/// references and for type inference. /// 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 name of this table, as it appears in sql statements. This should be
/// the raw name, not an escaped version. /// the raw name, not an escaped version.
/// ///
/// To obtain an escaped name, use [escapedName]. /// To obtain an escaped name, use [escapedName].
@override
final String name; 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 @override
final List<TableColumn> resolvedColumns; 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 /// A database view. The information stored here will be used to resolve
/// references and for type inference. /// references and for type inference.
class View with HasMetaMixin, ResultSet implements HumanReadable { class View extends NamedResultSet with HasMetaMixin implements HumanReadable {
/// The name of this view, as it appears in sql statements. This should be @override
/// the raw name, not an escaped version.
///
/// To obtain an escaped name, use [escapedName].
final String name; 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 @override
final List<ViewColumn> resolvedColumns; final List<ViewColumn> resolvedColumns;
/// The ast node that created this table /// The ast node that created this table
final CreateViewStatement definition; final CreateViewStatement definition;
@override
bool get visibleToChildren => true;
/// Constructs a view from the known [name] and [selectColumns]. /// Constructs a view from the known [name] and [selectColumns].
View({ View({
@required this.name, @required this.name,
@ -42,13 +30,13 @@ class View with HasMetaMixin, ResultSet implements HumanReadable {
String humanReadableDescription() { String humanReadableDescription() {
return name; return name;
} }
}
List<ViewColumn> _createColumns( static List<ViewColumn> _createColumns(
List<Column> resolvedColumns, List<String> columnNames) { List<Column> resolvedColumns, List<String> columnNames) {
final columns = List<ViewColumn>(resolvedColumns.length); final columns = List<ViewColumn>(resolvedColumns.length);
for (var i = 0; i < resolvedColumns.length; ++i) { for (var i = 0; i < resolvedColumns.length; ++i) {
columns[i] = ViewColumn(resolvedColumns[i], columnNames?.elementAt(i)); columns[i] = ViewColumn(resolvedColumns[i], columnNames?.elementAt(i));
}
return columns;
} }
return columns;
} }

View File

@ -6,7 +6,7 @@ class TableNameDescription extends HintDescription {
@override @override
Iterable<Suggestion> suggest(CalculationRequest request) { 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 tableNames.map((t) {
return Suggestion(t, 1); return Suggestion(t, 1);

View File

@ -12,7 +12,7 @@ import 'builtin_tables.dart';
class SqlEngine { class SqlEngine {
/// All tables registered with [registerTable]. /// All tables registered with [registerTable].
final List<Table> knownTables = []; final List<NamedResultSet> knownResultSets = [];
final List<Module> _knownModules = []; final List<Module> _knownModules = [];
/// Internal options for this sql engine. /// 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 /// Registers the [table], which means that it can later be used in sql
/// statements. /// statements.
void registerTable(Table table) { 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 /// Registers the [module], which means that it can be used as a function in
@ -67,8 +79,8 @@ class SqlEngine {
ReferenceScope _constructRootScope({ReferenceScope parent}) { ReferenceScope _constructRootScope({ReferenceScope parent}) {
final scope = parent == null ? ReferenceScope(null) : parent.createChild(); final scope = parent == null ? ReferenceScope(null) : parent.createChild();
for (final table in knownTables) { for (final resultSet in knownResultSets) {
scope.register(table.name, table); scope.register(resultSet.name, resultSet);
} }
for (final module in _knownModules) { for (final module in _knownModules) {