mirror of https://github.com/AMT-Cheif/drift.git
nits
This commit is contained in:
parent
1dc9282967
commit
7b35a0add5
|
@ -21,12 +21,7 @@ export 'src/runtime/query_builder/query_builder.dart'
|
|||
export 'src/runtime/types/converters.dart';
|
||||
export 'src/runtime/types/mapping.dart' hide BaseSqlType, UserDefinedSqlType;
|
||||
export 'src/runtime/manager/manager.dart'
|
||||
hide
|
||||
JoinBuilder,
|
||||
ComposerState,
|
||||
HasJoinBuilders,
|
||||
Composer,
|
||||
BaseTableManager;
|
||||
hide JoinBuilder, HasJoinBuilders, Composer, BaseTableManager;
|
||||
export 'src/utils/lazy_database.dart';
|
||||
|
||||
/// A [ListEquality] instance used by generated drift code for the `==` and
|
||||
|
|
|
@ -11,7 +11,8 @@ import 'package:drift/src/runtime/manager/manager.dart';
|
|||
/// execute a query on a table that is referenced by a foreign key.
|
||||
B composeWithJoins<RT extends Table, DB extends GeneratedDatabase,
|
||||
CT extends Table, QC extends Composer<DB, RT>, B extends HasJoinBuilders>({
|
||||
required ComposerState<DB, CT> $state,
|
||||
required DB $db,
|
||||
required CT $table,
|
||||
required GeneratedColumn Function(CT) getCurrentColumn,
|
||||
required RT referencedTable,
|
||||
required GeneratedColumn Function(RT) getReferencedColumn,
|
||||
|
@ -21,18 +22,18 @@ B composeWithJoins<RT extends Table, DB extends GeneratedDatabase,
|
|||
// The name of the alias will be created using the following logic:
|
||||
// "currentTableName__currentColumnName__referencedColumnName__referencedTableName"
|
||||
// This is to ensure that the alias is unique
|
||||
final currentColumn = getCurrentColumn($state.table);
|
||||
final currentColumn = getCurrentColumn($table);
|
||||
final tempReferencedColumn = getReferencedColumn(referencedTable);
|
||||
final aliasName =
|
||||
'${currentColumn.tableName}__${currentColumn.name}__${tempReferencedColumn.tableName}__${tempReferencedColumn.name}';
|
||||
final aliasedReferencedTable =
|
||||
$state.db.alias(referencedTable as TableInfo, aliasName);
|
||||
$db.alias(referencedTable as TableInfo, aliasName);
|
||||
final aliasedReferencedColumn =
|
||||
getReferencedColumn(aliasedReferencedTable as RT);
|
||||
|
||||
// Create a join builder for the referenced table
|
||||
final joinBuilder = JoinBuilder(
|
||||
currentTable: $state.table,
|
||||
currentTable: $table,
|
||||
currentColumn: currentColumn,
|
||||
referencedTable: aliasedReferencedTable,
|
||||
referencedColumn: aliasedReferencedColumn,
|
||||
|
@ -40,8 +41,7 @@ B composeWithJoins<RT extends Table, DB extends GeneratedDatabase,
|
|||
|
||||
// Get the query composer for the referenced table, passing in the aliased
|
||||
// table and all the join builders
|
||||
final referencedComposer =
|
||||
getReferencedComposer($state.db, aliasedReferencedTable);
|
||||
final referencedComposer = getReferencedComposer($db, aliasedReferencedTable);
|
||||
|
||||
// Run the user provided builder with the referencedQueryComposer
|
||||
// This may return a filter or ordering, but we only enforce that it's
|
||||
|
|
|
@ -411,7 +411,7 @@ class JsonKey {
|
|||
}
|
||||
|
||||
/// Annotation to use on reference columns inside of a [Table] to define the name
|
||||
/// of the filters and orderings for the reverse relation.
|
||||
/// that the manager will use when refering to this relation in the reverse.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
|
@ -424,11 +424,11 @@ class JsonKey {
|
|||
/// class Categories extends Table {
|
||||
/// IntColumn get id => integer().autoIncrement()();
|
||||
/// }
|
||||
/// /// Filter all Categories which contain a TodoEntries with a body of "Todo"
|
||||
/// /// The manager will now use the name `categories`
|
||||
/// categories.filter((f) => f.categories((f) => f.body("Todo")))
|
||||
///
|
||||
/// ```
|
||||
/// When these aren't specified, drift will use the referenced tables name followed by `Refs`.
|
||||
/// When these aren't specified, the manager will use the referenced tables name followed by `Refs`.
|
||||
/// If a reference name clashes with other fields on the table, the generator will show a warning,
|
||||
/// and filters and orderings wont be generated
|
||||
class ReferenceName {
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
part of 'manager.dart';
|
||||
|
||||
/// A class that holds the state for a query composer
|
||||
@internal
|
||||
class ComposerState<DB extends GeneratedDatabase, T extends Table> {
|
||||
/// The database that the query will be executed on
|
||||
final DB db;
|
||||
|
||||
/// The table that the query will be executed on
|
||||
final T table;
|
||||
ComposerState._(
|
||||
this.db,
|
||||
this.table,
|
||||
);
|
||||
}
|
||||
|
||||
/// Base class for all composers
|
||||
///
|
||||
/// Any class that can be composed using the `&` or `|` operator is called a composable.
|
||||
|
@ -27,14 +13,13 @@ class ComposerState<DB extends GeneratedDatabase, T extends Table> {
|
|||
/// `f` in this example is a [Composer] object, and `f.id.equals(1)` returns a [ComposableFilter] object.
|
||||
///
|
||||
/// The [Composer] class is responsible for creating joins between tables, and passing them down to the composable classes.
|
||||
///
|
||||
/// The [ComposerState] that is held in this class only holds temporary state, as the final state will be held in the composable classes.
|
||||
/// E.G. In the example above, only the resulting [ComposableFilter] object is returned, and the [FilterComposer] is discarded.
|
||||
///
|
||||
@internal
|
||||
sealed class Composer<DB extends GeneratedDatabase, CT extends Table> {
|
||||
/// The state of the composer
|
||||
final ComposerState<DB, CT> $state;
|
||||
/// The database that the query will be executed on
|
||||
final DB $db;
|
||||
|
||||
Composer(DB db, CT table) : $state = ComposerState._(db, table);
|
||||
/// The table that the query will be executed on
|
||||
final CT $table;
|
||||
|
||||
Composer(this.$db, this.$table);
|
||||
}
|
||||
|
|
|
@ -13,33 +13,31 @@ class ColumnFilters<T extends Object> {
|
|||
/// FitlerBuilder after2000() => isAfter(DateTime(2000));
|
||||
///}
|
||||
/// ```
|
||||
ColumnFilters(this.column);
|
||||
const ColumnFilters(this.column);
|
||||
|
||||
/// Column that this [ColumnFilters] wraps
|
||||
Expression<T> column;
|
||||
final Expression<T> column;
|
||||
|
||||
/// Create a filter that checks if the column is null.
|
||||
ComposableFilter isNull() => ComposableFilter.simple(column.isNull());
|
||||
ComposableFilter isNull() => ComposableFilter(column.isNull());
|
||||
|
||||
/// Create a filter that checks if the column is not null.
|
||||
ComposableFilter isNotNull() => ComposableFilter.simple(column.isNotNull());
|
||||
ComposableFilter isNotNull() => ComposableFilter(column.isNotNull());
|
||||
|
||||
/// Create a filter that checks if the column equals a value.
|
||||
ComposableFilter equals(T value) =>
|
||||
ComposableFilter.simple(column.equals(value));
|
||||
ComposableFilter equals(T value) => ComposableFilter(column.equals(value));
|
||||
|
||||
/// Create a filter that checks if the column is in a list of values.
|
||||
|
||||
ComposableFilter isIn(List<T> values) =>
|
||||
ComposableFilter.simple(column.isIn(values));
|
||||
ComposableFilter(column.isIn(values));
|
||||
|
||||
/// Create a filter that checks if the column is not in a list of values.
|
||||
ComposableFilter isNotIn(List<T> values) =>
|
||||
ComposableFilter.simple(column.isNotIn(values));
|
||||
ComposableFilter(column.isNotIn(values));
|
||||
|
||||
/// Shortcut for [equals]
|
||||
ComposableFilter call(T value) =>
|
||||
ComposableFilter.simple(column.equals(value));
|
||||
ComposableFilter call(T value) => ComposableFilter(column.equals(value));
|
||||
|
||||
/// Nested column for filtering on the count of a column
|
||||
ColumnFilters<int> get count => ColumnFilters(column.count());
|
||||
|
@ -48,39 +46,37 @@ class ColumnFilters<T extends Object> {
|
|||
/// Built in filters for bool columns
|
||||
extension BoolFilters on ColumnFilters<bool> {
|
||||
/// Create a filter to check if the column is bigger than a value
|
||||
ComposableFilter isTrue(bool value) =>
|
||||
ComposableFilter.simple(column.equals(true));
|
||||
ComposableFilter isTrue(bool value) => ComposableFilter(column.equals(true));
|
||||
|
||||
/// Create a filter to check if the column is small than a value
|
||||
ComposableFilter isFalse(bool value) =>
|
||||
ComposableFilter.simple(column.equals(true));
|
||||
ComposableFilter isFalse(bool value) => ComposableFilter(column.equals(true));
|
||||
}
|
||||
|
||||
/// Built in filters for int/double columns
|
||||
extension NumFilters<T extends num> on ColumnFilters<T> {
|
||||
/// Create a filter to check if the column is bigger than a value
|
||||
ComposableFilter isBiggerThan(T value) =>
|
||||
ComposableFilter.simple(column.isBiggerThanValue(value));
|
||||
ComposableFilter(column.isBiggerThanValue(value));
|
||||
|
||||
/// Create a filter to check if the column is small than a value
|
||||
ComposableFilter isSmallerThan(T value) =>
|
||||
ComposableFilter.simple(column.isSmallerThanValue(value));
|
||||
ComposableFilter(column.isSmallerThanValue(value));
|
||||
|
||||
/// Create a filter to check if the column is bigger or equal to a value
|
||||
ComposableFilter isBiggerOrEqualTo(T value) =>
|
||||
ComposableFilter.simple(column.isBiggerOrEqualValue(value));
|
||||
ComposableFilter(column.isBiggerOrEqualValue(value));
|
||||
|
||||
/// Create a filter to check if the column is small or equal to a value
|
||||
ComposableFilter isSmallerOrEqualTo(T value) =>
|
||||
ComposableFilter.simple(column.isSmallerOrEqualValue(value));
|
||||
ComposableFilter(column.isSmallerOrEqualValue(value));
|
||||
|
||||
/// Create a filter to check if the column is between two values
|
||||
ComposableFilter isBetween(T lower, T higher) =>
|
||||
ComposableFilter.simple(column.isBetweenValues(lower, higher));
|
||||
ComposableFilter(column.isBetweenValues(lower, higher));
|
||||
|
||||
/// Create a filter to check if the column is not between two values
|
||||
ComposableFilter isNotBetween(T lower, T higher) =>
|
||||
isBetween(lower, higher)._reversed();
|
||||
isBetween(lower, higher)._invert();
|
||||
|
||||
/// Nested column for filtering on the average of a column
|
||||
ColumnFilters<double> get avg => ColumnFilters(column.avg());
|
||||
|
@ -102,27 +98,27 @@ extension NumFilters<T extends num> on ColumnFilters<T> {
|
|||
extension BigIntFilters<T extends BigInt> on ColumnFilters<T> {
|
||||
/// Create a filter to check if the column is bigger than a value
|
||||
ComposableFilter isBiggerThan(T value) =>
|
||||
ComposableFilter.simple(column.isBiggerThanValue(value));
|
||||
ComposableFilter(column.isBiggerThanValue(value));
|
||||
|
||||
/// Create a filter to check if the column is small than a value
|
||||
ComposableFilter isSmallerThan(T value) =>
|
||||
ComposableFilter.simple(column.isSmallerThanValue(value));
|
||||
ComposableFilter(column.isSmallerThanValue(value));
|
||||
|
||||
/// Create a filter to check if the column is bigger or equal to a value
|
||||
ComposableFilter isBiggerOrEqualTo(T value) =>
|
||||
ComposableFilter.simple(column.isBiggerOrEqualValue(value));
|
||||
ComposableFilter(column.isBiggerOrEqualValue(value));
|
||||
|
||||
/// Create a filter to check if the column is small or equal to a value
|
||||
ComposableFilter isSmallerOrEqualTo(T value) =>
|
||||
ComposableFilter.simple(column.isSmallerOrEqualValue(value));
|
||||
ComposableFilter(column.isSmallerOrEqualValue(value));
|
||||
|
||||
/// Create a filter to check if the column is between two values
|
||||
ComposableFilter isBetween(T lower, T higher) =>
|
||||
ComposableFilter.simple(column.isBetweenValues(lower, higher));
|
||||
ComposableFilter(column.isBetweenValues(lower, higher));
|
||||
|
||||
/// Create a filter to check if the column is not between two values
|
||||
ComposableFilter isNotBetween(T lower, T higher) =>
|
||||
isBetween(lower, higher)._reversed();
|
||||
isBetween(lower, higher)._invert();
|
||||
|
||||
/// Nested column for filtering on the average of a column
|
||||
ColumnFilters<double> get avg => ColumnFilters(column.avg());
|
||||
|
@ -144,83 +140,74 @@ extension BigIntFilters<T extends BigInt> on ColumnFilters<T> {
|
|||
extension DateFilters<T extends DateTime> on ColumnFilters<T> {
|
||||
/// Create a filter to check if the column is after a [DateTime]
|
||||
ComposableFilter isAfter(T value) =>
|
||||
ComposableFilter.simple(column.isBiggerThanValue(value));
|
||||
ComposableFilter(column.isBiggerThanValue(value));
|
||||
|
||||
/// Create a filter to check if the column is before a [DateTime]
|
||||
ComposableFilter isBefore(T value) =>
|
||||
ComposableFilter.simple(column.isSmallerThanValue(value));
|
||||
ComposableFilter(column.isSmallerThanValue(value));
|
||||
|
||||
/// Create a filter to check if the column is on or after a [DateTime]
|
||||
ComposableFilter isAfterOrOn(T value) =>
|
||||
ComposableFilter.simple(column.isBiggerOrEqualValue(value));
|
||||
ComposableFilter(column.isBiggerOrEqualValue(value));
|
||||
|
||||
/// Create a filter to check if the column is before or on a [DateTime]
|
||||
ComposableFilter isBeforeOrOn(T value) =>
|
||||
ComposableFilter.simple(column.isSmallerOrEqualValue(value));
|
||||
ComposableFilter(column.isSmallerOrEqualValue(value));
|
||||
|
||||
/// Create a filter to check if the column is between 2 [DateTime]s
|
||||
|
||||
ComposableFilter isBetween(T lower, T higher) =>
|
||||
ComposableFilter.simple(column.isBetweenValues(lower, higher));
|
||||
ComposableFilter(column.isBetweenValues(lower, higher));
|
||||
|
||||
/// Create a filter to check if the column is not between 2 [DateTime]s
|
||||
ComposableFilter isNotBetween(T lower, T higher) =>
|
||||
isBetween(lower, higher)._reversed();
|
||||
isBetween(lower, higher)._invert();
|
||||
}
|
||||
|
||||
/// Defines a class which is used to wrap a column with a type converter to only expose filter functions
|
||||
class ColumnWithTypeConverterFilters<CUSTOM, T extends Object> {
|
||||
/// Similar to [ColumnFilters] but for columns with type converters\
|
||||
ColumnWithTypeConverterFilters(this.column);
|
||||
const ColumnWithTypeConverterFilters(this.column);
|
||||
|
||||
/// Column that this [ColumnWithTypeConverterFilters] wraps
|
||||
GeneratedColumnWithTypeConverter<CUSTOM, T> column;
|
||||
final GeneratedColumnWithTypeConverter<CUSTOM, T> column;
|
||||
|
||||
/// Create a filter that checks if the column is null.
|
||||
ComposableFilter isNull() => ComposableFilter.simple(column.isNull());
|
||||
ComposableFilter isNull() => ComposableFilter(column.isNull());
|
||||
|
||||
/// Create a filter that checks if the column is not null.
|
||||
ComposableFilter isNotNull() => ComposableFilter.simple(column.isNotNull());
|
||||
ComposableFilter isNotNull() => ComposableFilter(column.isNotNull());
|
||||
|
||||
/// Create a filter that checks if the column equals a value.
|
||||
ComposableFilter equals(CUSTOM value) =>
|
||||
ComposableFilter.simple(column.equalsValue(value));
|
||||
ComposableFilter(column.equalsValue(value));
|
||||
|
||||
/// Shortcut for [equals]
|
||||
ComposableFilter call(CUSTOM value) =>
|
||||
ComposableFilter.simple(column.equalsValue(value));
|
||||
ComposableFilter(column.equalsValue(value));
|
||||
}
|
||||
|
||||
/// Defines a class that can be used to compose filters for a column
|
||||
class ComposableFilter implements HasJoinBuilders {
|
||||
/// This class is wrapper on the expression class
|
||||
///
|
||||
/// It contains the expression, along with any joins that are required
|
||||
/// to execute the expression. See [HasJoinBuilders] for more information
|
||||
/// on how joins are stored
|
||||
class ComposableFilter extends HasJoinBuilders {
|
||||
@override
|
||||
final Set<JoinBuilder> joinBuilders;
|
||||
@override
|
||||
void addJoinBuilders(Set<JoinBuilder> builders) {
|
||||
joinBuilders.addAll(builders);
|
||||
}
|
||||
|
||||
/// The expression that will be applied to the query
|
||||
final Expression<bool> expression;
|
||||
|
||||
/// This class is wrapper on expression class
|
||||
///
|
||||
/// It contains the expression, along with any joins that are required
|
||||
/// to execute the expression
|
||||
///
|
||||
/// It also contains a list of aliases that were used in joins
|
||||
/// This will be used to ensure that the same alias isn't used twice
|
||||
ComposableFilter.withJoin(
|
||||
this.expression,
|
||||
this.joinBuilders,
|
||||
);
|
||||
/// Create a new [ComposableFilter] for a column without any joins
|
||||
ComposableFilter(this.expression) : joinBuilders = {};
|
||||
|
||||
// ignore: public_member_api_docs
|
||||
ComposableFilter.simple(this.expression) : joinBuilders = {};
|
||||
/// Create a new [ComposableFilter] for a column with joins
|
||||
ComposableFilter._(this.expression, this.joinBuilders);
|
||||
|
||||
/// Combine two filters with an AND
|
||||
ComposableFilter operator &(ComposableFilter other) {
|
||||
return ComposableFilter.withJoin(
|
||||
return ComposableFilter._(
|
||||
expression & other.expression,
|
||||
joinBuilders.union(other.joinBuilders),
|
||||
);
|
||||
|
@ -228,15 +215,15 @@ class ComposableFilter implements HasJoinBuilders {
|
|||
|
||||
/// Combine two filters with an OR
|
||||
ComposableFilter operator |(ComposableFilter other) {
|
||||
return ComposableFilter.withJoin(
|
||||
return ComposableFilter._(
|
||||
expression | other.expression,
|
||||
joinBuilders.union(other.joinBuilders),
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a copy of this filter with the expression reversed
|
||||
ComposableFilter _reversed() {
|
||||
return ComposableFilter.withJoin(
|
||||
ComposableFilter _invert() {
|
||||
return ComposableFilter._(
|
||||
expression.not(),
|
||||
joinBuilders,
|
||||
);
|
||||
|
@ -247,5 +234,5 @@ class ComposableFilter implements HasJoinBuilders {
|
|||
class FilterComposer<DB extends GeneratedDatabase, T extends Table>
|
||||
extends Composer<DB, T> {
|
||||
/// Create a filter composer with an empty state
|
||||
FilterComposer(super.db, super.table);
|
||||
FilterComposer(super.$db, super.$table);
|
||||
}
|
||||
|
|
|
@ -9,11 +9,10 @@ class JoinBuilder {
|
|||
/// The referenced table that will be joined
|
||||
final Table referencedTable;
|
||||
|
||||
/// The column of the current database which will be use to create the join
|
||||
/// The column of the [currentTable] which will be use to create the join
|
||||
final GeneratedColumn currentColumn;
|
||||
|
||||
/// The column of the referenced database which will be use to create the join
|
||||
|
||||
/// The column of the [referencedTable] which will be use to create the join
|
||||
final GeneratedColumn referencedColumn;
|
||||
|
||||
/// Class that describes how a ordering that is being
|
||||
|
@ -46,16 +45,34 @@ class JoinBuilder {
|
|||
/// Build a join from this join builder
|
||||
Join buildJoin() {
|
||||
return leftOuterJoin(
|
||||
referencedTable, currentColumn.equalsExp(referencedColumn));
|
||||
referencedTable, currentColumn.equalsExp(referencedColumn),
|
||||
useColumns: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// An interface for classes that hold join builders
|
||||
/// Typically used by classes whose composition requires joins
|
||||
/// to be created
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// categories.filter((f) => f.todos((f) => f.dueDate.isBefore(DateTime.now())))
|
||||
/// ```
|
||||
///
|
||||
/// In the above example, f.todos() returns a [ComposableFilter] object, which
|
||||
/// is a subclass of [HasJoinBuilders].
|
||||
/// This resulting where expression will require a join to be created
|
||||
/// between the `categories` and `todos` table.
|
||||
///
|
||||
/// This interface is used to ensure that the [ComposableFilter] object will have
|
||||
/// the information needed to create the join.
|
||||
@internal
|
||||
abstract interface class HasJoinBuilders {
|
||||
/// The join builders that are associated with this class
|
||||
Set<JoinBuilder> get joinBuilders;
|
||||
|
||||
/// Add a join builder to this class
|
||||
void addJoinBuilders(Set<JoinBuilder> builders);
|
||||
void addJoinBuilders(Set<JoinBuilder> builders) {
|
||||
joinBuilders.addAll(builders);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,14 @@ class _JoinedResult<T extends Table, DT extends DataClass>
|
|||
}
|
||||
|
||||
/// Defines a class that holds the state for a [BaseTableManager]
|
||||
///
|
||||
/// It holds the state for manager of [T] table in [DB] database, used to return [DT] data classes/rows.
|
||||
/// It holds the [FS] Filters and [OS] Orderings for the manager.
|
||||
///
|
||||
/// It also holds the [CI] and [CU] functions that are used to create companion builders for inserting and updating data.
|
||||
/// E.G Instead of `CategoriesCompanion.insert(name: "School")` you would use `(f) => f(name: "School")`
|
||||
///
|
||||
/// The [C] generic refers to the type of the child manager that will be created when a filter/ordering is applied
|
||||
class TableManagerState<
|
||||
DB extends GeneratedDatabase,
|
||||
T extends Table,
|
||||
|
@ -135,30 +143,23 @@ class TableManagerState<
|
|||
|
||||
/// Builds a select statement with the given target columns, or all columns if none are provided
|
||||
_StatementType<T, DT> _buildSelectStatement(
|
||||
{Iterable<Expression>? targetColumns,
|
||||
required bool addJoins,
|
||||
required bool applyFilters,
|
||||
required bool applyOrdering,
|
||||
required bool applyLimit}) {
|
||||
{Iterable<Expression>? targetColumns}) {
|
||||
final joins = joinBuilders.map((e) => e.buildJoin()).toList();
|
||||
|
||||
// If there are no joins and we are returning all columns, we can use a simple select statement
|
||||
if (targetColumns == null && !addJoins) {
|
||||
if (joins.isEmpty && targetColumns == null) {
|
||||
final simpleStatement =
|
||||
db.select(_tableAsTableInfo, distinct: distinct ?? false);
|
||||
// Apply the expression to the statement
|
||||
if (applyFilters && filter != null) {
|
||||
if (filter != null) {
|
||||
simpleStatement.where((_) => filter!);
|
||||
}
|
||||
// Add orderings
|
||||
if (applyOrdering) {
|
||||
simpleStatement.orderBy(
|
||||
orderingBuilders.map((e) => (_) => e.buildTerm()).toList());
|
||||
}
|
||||
// Set the limit and offset
|
||||
if (applyLimit && limit != null) {
|
||||
simpleStatement.limit(limit!, offset: offset);
|
||||
}
|
||||
// Apply orderings and limits
|
||||
|
||||
simpleStatement
|
||||
.orderBy(orderingBuilders.map((e) => (_) => e.buildTerm()).toList());
|
||||
simpleStatement.limit(limit!, offset: offset);
|
||||
|
||||
return _SimpleResult(simpleStatement);
|
||||
} else {
|
||||
JoinedSelectStatement<T, DT> joinedStatement;
|
||||
|
@ -168,45 +169,30 @@ class TableManagerState<
|
|||
(db.selectOnly(_tableAsTableInfo, distinct: distinct ?? false)
|
||||
..addColumns(targetColumns));
|
||||
// Add the joins to the statement
|
||||
if (addJoins) {
|
||||
joinedStatement =
|
||||
joinedStatement.join(joins) as JoinedSelectStatement<T, DT>;
|
||||
}
|
||||
joinedStatement =
|
||||
joinedStatement.join(joins) as JoinedSelectStatement<T, DT>;
|
||||
} else {
|
||||
joinedStatement = db
|
||||
.select(_tableAsTableInfo, distinct: distinct ?? false)
|
||||
.join(joins) as JoinedSelectStatement<T, DT>;
|
||||
}
|
||||
// Apply the expression to the statement
|
||||
if (applyFilters && filter != null) {
|
||||
if (filter != null) {
|
||||
joinedStatement.where(filter!);
|
||||
}
|
||||
// Add orderings
|
||||
if (applyOrdering) {
|
||||
joinedStatement
|
||||
.orderBy(orderingBuilders.map((e) => e.buildTerm()).toList());
|
||||
}
|
||||
// Set the limit and offset
|
||||
if (applyLimit && limit != null) {
|
||||
joinedStatement.limit(limit!, offset: offset);
|
||||
}
|
||||
// Apply orderings and limits
|
||||
|
||||
joinedStatement
|
||||
.orderBy(orderingBuilders.map((e) => e.buildTerm()).toList());
|
||||
joinedStatement.limit(limit!, offset: offset);
|
||||
|
||||
return _JoinedResult(joinedStatement);
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a select statement based on the manager state
|
||||
Selectable<DT> buildSelectStatement(
|
||||
{Iterable<Column>? targetColumns,
|
||||
bool addJoins = true,
|
||||
bool applyFilters = true,
|
||||
bool applyOrdering = true,
|
||||
bool applyLimit = true}) {
|
||||
final result = _buildSelectStatement(
|
||||
targetColumns: targetColumns,
|
||||
addJoins: addJoins,
|
||||
applyFilters: applyFilters,
|
||||
applyOrdering: applyOrdering,
|
||||
applyLimit: applyLimit);
|
||||
Selectable<DT> buildSelectStatement() {
|
||||
final result = _buildSelectStatement();
|
||||
return switch (result) {
|
||||
_SimpleResult() => result.statement,
|
||||
_JoinedResult() =>
|
||||
|
@ -225,12 +211,8 @@ class TableManagerState<
|
|||
} else {
|
||||
updateStatement = db.update(_tableAsTableInfo);
|
||||
for (var col in _tableAsTableInfo.primaryKey) {
|
||||
final subquery = _buildSelectStatement(
|
||||
targetColumns: [col],
|
||||
addJoins: true,
|
||||
applyFilters: true,
|
||||
applyOrdering: false,
|
||||
applyLimit: false) as _JoinedResult<T, DT>;
|
||||
final subquery =
|
||||
_buildSelectStatement(targetColumns: [col]) as _JoinedResult<T, DT>;
|
||||
updateStatement.where((tbl) => col.isInQuery(subquery.statement));
|
||||
}
|
||||
}
|
||||
|
@ -240,12 +222,8 @@ class TableManagerState<
|
|||
/// Count the number of rows that would be returned by the built statement
|
||||
Future<int> count() {
|
||||
final count = countAll();
|
||||
final result = _buildSelectStatement(
|
||||
targetColumns: [count],
|
||||
addJoins: true,
|
||||
applyFilters: true,
|
||||
applyOrdering: true,
|
||||
applyLimit: true) as _JoinedResult;
|
||||
final result =
|
||||
_buildSelectStatement(targetColumns: [count]) as _JoinedResult;
|
||||
return result.statement.map((row) => row.read(count)!).getSingle();
|
||||
}
|
||||
|
||||
|
@ -260,12 +238,8 @@ class TableManagerState<
|
|||
} else {
|
||||
deleteStatement = db.delete(_tableAsTableInfo);
|
||||
for (var col in _tableAsTableInfo.primaryKey) {
|
||||
final subquery = _buildSelectStatement(
|
||||
targetColumns: [col],
|
||||
addJoins: true,
|
||||
applyFilters: true,
|
||||
applyOrdering: true,
|
||||
applyLimit: true) as _JoinedResult<T, DT>;
|
||||
final subquery =
|
||||
_buildSelectStatement(targetColumns: [col]) as _JoinedResult<T, DT>;
|
||||
deleteStatement.where((tbl) => col.isInQuery(subquery.statement));
|
||||
}
|
||||
}
|
||||
|
@ -299,6 +273,12 @@ abstract class BaseTableManager<
|
|||
/// foreign key constraints).
|
||||
Future<int> delete() => $state.buildDeleteStatement().go();
|
||||
|
||||
/// Set the distinct flag on the statement to true
|
||||
/// This will ensure that only distinct rows are returned
|
||||
C distict() {
|
||||
return $state._getChildManagerBuilder($state.copyWith(distinct: true));
|
||||
}
|
||||
|
||||
/// Add ordering to the statement
|
||||
C orderBy(ComposableOrdering Function(OS o) o) {
|
||||
final orderings = o($state.orderingComposer);
|
||||
|
|
|
@ -5,12 +5,7 @@ class ColumnOrderings<T extends Object> {
|
|||
/// This class is a wrapper on top of the generated column class
|
||||
///
|
||||
/// It's used to expose ordering functions for a column
|
||||
///
|
||||
/// ```dart
|
||||
/// extension on FilterComposer<DateTime>{
|
||||
/// FitlerBuilder after2000() => isAfter(DateTime(2000));
|
||||
///}
|
||||
/// ```
|
||||
|
||||
ColumnOrderings(this.column);
|
||||
|
||||
/// Column that this [ColumnOrderings] wraps
|
||||
|
@ -20,13 +15,13 @@ class ColumnOrderings<T extends Object> {
|
|||
///
|
||||
/// 10 -> 1 | Z -> A | Dec 31 -> Jan 1
|
||||
ComposableOrdering asc() =>
|
||||
ComposableOrdering.simple({OrderingBuilder(OrderingMode.asc, column)});
|
||||
ComposableOrdering({OrderingBuilder(OrderingMode.asc, column)});
|
||||
|
||||
/// Sort this column in descending order
|
||||
///
|
||||
/// 1 -> 10 | A -> Z | Jan 1 -> Dec 31
|
||||
ComposableOrdering desc() =>
|
||||
ComposableOrdering.simple({OrderingBuilder(OrderingMode.desc, column)});
|
||||
ComposableOrdering({OrderingBuilder(OrderingMode.desc, column)});
|
||||
}
|
||||
|
||||
/// Defines a class which will hold the information needed to create an ordering
|
||||
|
@ -60,18 +55,16 @@ class OrderingBuilder {
|
|||
///
|
||||
/// Multiple orderings can be composed together using the `&` operator.
|
||||
/// The orderings will be executed from left to right.
|
||||
class ComposableOrdering implements HasJoinBuilders {
|
||||
/// See [HasJoinBuilders] for more information
|
||||
/// on how joins are stored
|
||||
class ComposableOrdering extends HasJoinBuilders {
|
||||
/// The orderings that are being composed
|
||||
final Set<OrderingBuilder> orderingBuilders;
|
||||
@override
|
||||
final Set<JoinBuilder> joinBuilders;
|
||||
@override
|
||||
void addJoinBuilders(Set<JoinBuilder> builders) {
|
||||
joinBuilders.addAll(builders);
|
||||
}
|
||||
|
||||
/// Create a new [ComposableOrdering] for a column without any joins
|
||||
ComposableOrdering.simple(this.orderingBuilders) : joinBuilders = {};
|
||||
ComposableOrdering(this.orderingBuilders) : joinBuilders = {};
|
||||
|
||||
/// Create a new [ComposableOrdering] for a column with joins
|
||||
ComposableOrdering._(this.orderingBuilders, this.joinBuilders);
|
||||
|
@ -92,5 +85,5 @@ class ComposableOrdering implements HasJoinBuilders {
|
|||
class OrderingComposer<DB extends GeneratedDatabase, T extends Table>
|
||||
extends Composer<DB, T> {
|
||||
/// Create an ordering composer with an empty state
|
||||
OrderingComposer(super.db, super.table);
|
||||
OrderingComposer(super.$db, super.$table);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class _RegularFilterWriter extends _FilterWriter {
|
|||
..writeDriftRef("ColumnFilters")
|
||||
..write("<$type> get $filterName =>")
|
||||
..writeDriftRef("ColumnFilters")
|
||||
..write("(\$state.table.$fieldGetter);");
|
||||
..write("(\$table.$fieldGetter);");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,15 +64,15 @@ class _FilterWithConverterWriter extends _FilterWriter {
|
|||
..writeDriftRef("ColumnWithTypeConverterFilters")
|
||||
..write("<$converterType,$type> get $filterName =>")
|
||||
..writeDriftRef("ColumnWithTypeConverterFilters")
|
||||
..writeln("(\$state.table.$fieldGetter);");
|
||||
..writeln("(\$table.$fieldGetter);");
|
||||
}
|
||||
}
|
||||
|
||||
class _ReferencedFilterWriter extends _FilterWriter {
|
||||
/// The full function used to get the referenced table
|
||||
///
|
||||
/// E.G `\$state.db.resultSet<$CategoryTable>('categories')`
|
||||
/// or `\$state.db.categories`
|
||||
/// E.G `\$db.resultSet<$CategoryTable>('categories')`
|
||||
/// or `\$db.categories`
|
||||
final String referencedTableField;
|
||||
|
||||
/// The getter for the column on the referenced table
|
||||
|
@ -105,7 +105,8 @@ class _ReferencedFilterWriter extends _FilterWriter {
|
|||
..writeUriRef(
|
||||
Uri.parse('package:drift/internal/manager.dart'), 'composeWithJoins')
|
||||
..writeln('(')
|
||||
..writeln("\$state: \$state,")
|
||||
..writeln("\$db: \$db,")
|
||||
..writeln("\$table: \$table,")
|
||||
..writeln("referencedTable: $referencedTableField,")
|
||||
..writeln("getCurrentColumn: (f) => f.$fieldGetter,")
|
||||
..writeln("getReferencedColumn: (f) => f.$referencedColumnGetter,")
|
||||
|
@ -150,15 +151,15 @@ class _RegularOrderingWriter extends _OrderingWriter {
|
|||
..writeDriftRef("ColumnOrderings")
|
||||
..write(" get $orderingName =>")
|
||||
..writeDriftRef("ColumnOrderings")
|
||||
..write("(\$state.table.$fieldGetter);");
|
||||
..write("(\$table.$fieldGetter);");
|
||||
}
|
||||
}
|
||||
|
||||
class _ReferencedOrderingWriter extends _OrderingWriter {
|
||||
/// The full function used to get the referenced table
|
||||
///
|
||||
/// E.G `\$state.db.resultSet<$CategoryTable>('categories')`
|
||||
/// or `\$state.db.categories`
|
||||
/// E.G `\$db.resultSet<$CategoryTable>('categories')`
|
||||
/// or `\$db.categories`
|
||||
final String referencedTableField;
|
||||
|
||||
/// The getter for the column on the referenced table
|
||||
|
@ -189,7 +190,8 @@ class _ReferencedOrderingWriter extends _OrderingWriter {
|
|||
..writeUriRef(
|
||||
Uri.parse('package:drift/internal/manager.dart'), 'composeWithJoins')
|
||||
..writeln('(')
|
||||
..writeln("\$state: \$state,")
|
||||
..writeln("\$db: \$db,")
|
||||
..writeln("\$table: \$table,")
|
||||
..writeln("referencedTable: $referencedTableField,")
|
||||
..writeln("getCurrentColumn: (f) => f.$fieldGetter,")
|
||||
..writeln("getReferencedColumn: (f) => f.$referencedColumnGetter,")
|
||||
|
@ -487,8 +489,8 @@ class _TableWriter {
|
|||
_TableWriter(referencedTable, scope, dbScope, databaseGenericName);
|
||||
final referencedColumnNames = _ColumnWriter(referencedCol.nameInDart);
|
||||
final String referencedTableField = scope.generationOptions.isModular
|
||||
? "\$state.db.resultSet<${referencedTableNames.tableClassName}>('${referencedTable.schemaName}')"
|
||||
: "\$state.db.${referencedTable.dbGetterName}";
|
||||
? "\$db.resultSet<${referencedTableNames.tableClassName}>('${referencedTable.schemaName}')"
|
||||
: "\$db.${referencedTable.dbGetterName}";
|
||||
|
||||
c.filters.add(_ReferencedFilterWriter(c.fieldGetter,
|
||||
fieldGetter: c.fieldGetter,
|
||||
|
@ -515,8 +517,8 @@ class _TableWriter {
|
|||
_TableWriter(ot, scope, dbScope, databaseGenericName);
|
||||
final referencedColumnNames = _ColumnWriter(oc.nameInDart);
|
||||
final String referencedTableField = scope.generationOptions.isModular
|
||||
? "\$state.db.resultSet<${referencedTableNames.tableClassName}>('${ot.schemaName}')"
|
||||
: "\$state.db.${ot.dbGetterName}";
|
||||
? "\$db.resultSet<${referencedTableNames.tableClassName}>('${ot.schemaName}')"
|
||||
: "\$db.${ot.dbGetterName}";
|
||||
|
||||
final filterName = oc.referenceName ??
|
||||
"${referencedTableNames.table.dbGetterName}Refs";
|
||||
|
|
Loading…
Reference in New Issue