Prepare api for custom data classes

This commit is contained in:
Simon Binder 2021-04-09 21:17:28 +02:00
parent 58fdda482f
commit 65cdce342d
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
13 changed files with 53 additions and 47 deletions

View File

@ -1,6 +1,7 @@
import 'dart:typed_data' show Uint8List;
import 'package:meta/meta.dart';
import 'package:meta/meta_meta.dart';
import 'package:moor/moor.dart';
part 'columns.dart';

View File

@ -123,6 +123,7 @@ abstract class Table {
/// you might want to choose a different name, for which this annotation can be
/// used.
/// {@template}
@Target({TargetKind.classType})
class DataClassName {
/// The overridden name to use when generating the data class for a table.
/// {@macro moor_custom_data_class}
@ -132,3 +133,20 @@ class DataClassName {
/// {@macro moor_custom_data_class}
const DataClassName(this.name);
}
/// An annotation specifying an existing class to be used as a data class.
@Target({TargetKind.classType})
@experimental
class UseDataClass {
/// The existing class
///
/// This type must refer to an existing class. All other types, like functions
/// or types with arguments, are not allowed.
final Type type;
/// Customize the class used by moor to hold an instance of an annotated
/// table.
///
/// For details, see the overall documentation on [UseDataClass].
const UseDataClass(this.type);
}

View File

@ -36,8 +36,7 @@ class Batch {
///
/// See also:
/// - [InsertStatement.insert], which would be used outside a [Batch].
void insert<T extends Table, D extends DataClass>(
TableInfo<T, D> table, Insertable<D> row,
void insert<T extends Table, D>(TableInfo<T, D> table, Insertable<D> row,
{InsertMode? mode, DoUpdate<T, D>? onConflict}) {
_addUpdate(table, UpdateKind.insert);
final actualMode = mode ?? InsertMode.insert;
@ -58,7 +57,7 @@ class Batch {
/// checks.
/// [onConflict] can be used to create an upsert clause for engines that
/// support it. For details and examples, see [InsertStatement.insert].
void insertAll<T extends Table, D extends DataClass>(
void insertAll<T extends Table, D>(
TableInfo<T, D> table, List<Insertable<D>> rows,
{InsertMode? mode, DoUpdate<T, D>? onConflict}) {
for (final row in rows) {
@ -68,7 +67,7 @@ class Batch {
/// Equivalent of [InsertStatement.insertOnConflictUpdate] for multiple rows
/// that will be inserted in this batch.
void insertAllOnConflictUpdate<T extends Table, D extends DataClass>(
void insertAllOnConflictUpdate<T extends Table, D>(
TableInfo<T, D> table, List<Insertable<D>> rows) {
for (final row in rows) {
insert<T, D>(table, row, onConflict: DoUpdate((_) => row));
@ -80,8 +79,7 @@ class Batch {
///
/// For more details on how updates work in moor, check out
/// [UpdateStatement.write] or the [documentation with examples](https://moor.simonbinder.eu/docs/getting-started/writing_queries/#updates-and-deletes)
void update<T extends Table, D extends DataClass>(
TableInfo<T, D> table, Insertable<D> row,
void update<T extends Table, D>(TableInfo<T, D> table, Insertable<D> row,
{Expression<bool?> Function(T table)? where}) {
_addUpdate(table, UpdateKind.update);
final stmt = UpdateStatement(_user, table);
@ -98,7 +96,7 @@ class Batch {
/// See also:
/// - [UpdateStatement.replace], which is what would be used outside of a
/// [Batch].
void replace<T extends Table, D extends DataClass>(
void replace<T extends Table, D>(
TableInfo<T, D> table,
Insertable<D> row,
) {
@ -108,7 +106,7 @@ class Batch {
}
/// Helper that calls [replace] for all [rows].
void replaceAll<T extends Table, D extends DataClass>(
void replaceAll<T extends Table, D>(
TableInfo<T, D> table, List<Insertable<D>> rows) {
for (final row in rows) {
replace(table, row);
@ -120,8 +118,7 @@ class Batch {
/// See also:
/// - [DatabaseConnectionUser.delete]
/// - [DeleteStatement.delete]
void delete<T extends Table, D extends DataClass>(
TableInfo<T, D> table, Insertable<D> row) {
void delete<T extends Table, D>(TableInfo<T, D> table, Insertable<D> row) {
_addUpdate(table, UpdateKind.delete);
final stmt = DeleteStatement(_user, table)..whereSamePrimaryKey(row);
_addContext(stmt.constructQuery());
@ -131,7 +128,7 @@ class Batch {
///
/// See also:
/// - [DatabaseConnectionUser.delete]
void deleteWhere<T extends Table, D extends DataClass>(
void deleteWhere<T extends Table, D>(
TableInfo<T, D> table, Expression<bool?> Function(T tbl) filter) {
_addUpdate(table, UpdateKind.delete);
final stmt = DeleteStatement(_user, table)..where(filter);

View File

@ -69,8 +69,7 @@ abstract class DatabaseConnectionUser {
/// innerJoin(destination, routes.startPoint.equalsExp(destination.id)),
/// ]);
/// ```
T alias<T extends Table, D extends DataClass>(
TableInfo<T, D> table, String alias) {
T alias<T extends Table, D>(TableInfo<T, D> table, String alias) {
return table.createAlias(alias).asDslTable;
}
@ -127,15 +126,14 @@ abstract class DatabaseConnectionUser {
/// Starts an [InsertStatement] for a given table. You can use that statement
/// to write data into the [table] by using [InsertStatement.insert].
InsertStatement<T, D> into<T extends Table, D extends DataClass>(
TableInfo<T, D> table) {
InsertStatement<T, D> into<T extends Table, D>(TableInfo<T, D> table) {
return InsertStatement<T, D>(_resolvedEngine, table);
}
/// Starts an [UpdateStatement] for the given table. You can use that
/// statement to update individual rows in that table by setting a where
/// clause on that table and then use [UpdateStatement.write].
UpdateStatement<Tbl, R> update<Tbl extends Table, R extends DataClass>(
UpdateStatement<Tbl, R> update<Tbl extends Table, R>(
TableInfo<Tbl, R> table) =>
UpdateStatement(_resolvedEngine, table);
@ -163,8 +161,7 @@ abstract class DatabaseConnectionUser {
///
/// For more information on queries, see the
/// [documentation](https://moor.simonbinder.eu/docs/getting-started/writing_queries/).
SimpleSelectStatement<T, R> select<T extends Table, R extends DataClass>(
TableInfo<T, R> table,
SimpleSelectStatement<T, R> select<T extends Table, R>(TableInfo<T, R> table,
{bool distinct = false}) {
return SimpleSelectStatement<T, R>(_resolvedEngine, table,
distinct: distinct);
@ -200,7 +197,7 @@ abstract class DatabaseConnectionUser {
/// See also:
/// - the documentation on [aggregate expressions](https://moor.simonbinder.eu/docs/getting-started/expressions/#aggregate)
/// - the documentation on [group by](https://moor.simonbinder.eu/docs/advanced-features/joins/#group-by)
JoinedSelectStatement<T, R> selectOnly<T extends Table, R extends DataClass>(
JoinedSelectStatement<T, R> selectOnly<T extends Table, R>(
TableInfo<T, R> table, {
bool distinct = false,
}) {
@ -212,8 +209,7 @@ abstract class DatabaseConnectionUser {
///
/// See the [documentation](https://moor.simonbinder.eu/docs/getting-started/writing_queries/#updates-and-deletes)
/// for more details and example on how delete statements work.
DeleteStatement<T, D> delete<T extends Table, D extends DataClass>(
TableInfo<T, D> table) {
DeleteStatement<T, D> delete<T extends Table, D>(TableInfo<T, D> table) {
return DeleteStatement<T, D>(_resolvedEngine, table);
}

View File

@ -8,7 +8,7 @@ import 'package:moor/moor.dart';
/// database.
/// [D] is the associated data class.
@optionalTypeArgs
abstract class Insertable<D extends DataClass> {
abstract class Insertable<D> {
/// Converts this object into a map of column names to expressions to insert
/// or update.
///
@ -57,7 +57,7 @@ abstract class DataClass {
/// See also:
/// - the explanation in the changelog for 1.5
/// - https://github.com/simolus3/moor/issues/25
abstract class UpdateCompanion<D extends DataClass> implements Insertable<D> {
abstract class UpdateCompanion<D> implements Insertable<D> {
/// Constant constructor so that generated companion classes can be constant.
const UpdateCompanion();
@ -80,7 +80,7 @@ abstract class UpdateCompanion<D extends DataClass> implements Insertable<D> {
/// An [Insertable] implementation based on raw column expressions.
///
/// Mostly used in generated code.
class RawValuesInsertable<D extends DataClass> implements Insertable<D> {
class RawValuesInsertable<D> implements Insertable<D> {
/// A map from column names to a value that should be inserted or updated.
///
/// See also:

View File

@ -22,7 +22,7 @@ const Map<_JoinType, String> _joinKeywords = {
///
/// You should use [innerJoin], [leftOuterJoin] or [crossJoin] to obtain a
/// [Join] instance.
class Join<T extends Table, D extends DataClass> extends Component {
class Join<T extends Table, D> extends Component {
/// The [_JoinType] of this join.
final _JoinType type;
@ -70,8 +70,7 @@ class Join<T extends Table, D extends DataClass> extends Component {
/// See also:
/// - https://moor.simonbinder.eu/docs/advanced-features/joins/#joins
/// - http://www.sqlitetutorial.net/sqlite-inner-join/
Join innerJoin<T extends Table, D extends DataClass>(
TableInfo<T, D> other, Expression<bool?> on,
Join innerJoin<T extends Table, D>(TableInfo<T, D> other, Expression<bool?> on,
{bool? useColumns}) {
return Join._(_JoinType.inner, other, on, includeInResult: useColumns);
}
@ -84,7 +83,7 @@ Join innerJoin<T extends Table, D extends DataClass>(
/// See also:
/// - https://moor.simonbinder.eu/docs/advanced-features/joins/#joins
/// - http://www.sqlitetutorial.net/sqlite-left-join/
Join leftOuterJoin<T extends Table, D extends DataClass>(
Join leftOuterJoin<T extends Table, D>(
TableInfo<T, D> other, Expression<bool?> on,
{bool? useColumns}) {
return Join._(_JoinType.leftOuter, other, on, includeInResult: useColumns);

View File

@ -3,7 +3,7 @@ part of '../query_builder.dart';
/// Base class for generated classes. [TableDsl] is the type specified by the
/// user that extends [Table], [D] is the type of the data class
/// generated from the table.
mixin TableInfo<TableDsl extends Table, D extends DataClass> on Table
mixin TableInfo<TableDsl extends Table, D> on Table
implements DatabaseSchemaEntity {
/// Type system sugar. Implementations are likely to inherit from both
/// [TableInfo] and [TableDsl] and can thus just return their instance.
@ -95,8 +95,7 @@ mixin TableInfo<TableDsl extends Table, D extends DataClass> on Table
/// Additional interface for tables in a moor file that have been created with
/// an `CREATE VIRTUAL TABLE STATEMENT`.
mixin VirtualTableInfo<TableDsl extends Table, D extends DataClass>
on TableInfo<TableDsl, D> {
mixin VirtualTableInfo<TableDsl extends Table, D> on TableInfo<TableDsl, D> {
/// Returns the module name and the arguments that were used in the statement
/// that created this table. In that sense, `CREATE VIRTUAL TABLE <name>
/// USING <moduleAndArgs>;` can be used to create this table in sql.
@ -106,8 +105,7 @@ mixin VirtualTableInfo<TableDsl extends Table, D extends DataClass>
/// Static extension members for generated table classes.
///
/// Most of these are accessed internally by moor or by generated code.
extension TableInfoUtils<TableDsl extends Table, D extends DataClass>
on TableInfo<TableDsl, D> {
extension TableInfoUtils<TableDsl extends Table, D> on TableInfo<TableDsl, D> {
/// The table name, optionally suffixed with the alias if one exists. This
/// can be used in select statements, as it returns something like "users u"
/// for a table called users that has been aliased as "u".

View File

@ -1,7 +1,7 @@
part of '../query_builder.dart';
/// A `DELETE` statement in sql
class DeleteStatement<T extends Table, D extends DataClass> extends Query<T, D>
class DeleteStatement<T extends Table, D> extends Query<T, D>
with SingleTableQueryMixin<T, D> {
/// This constructor should be called by [DatabaseConnectionUser.delete] for
/// you.

View File

@ -1,7 +1,7 @@
part of '../query_builder.dart';
/// Represents an insert statement
class InsertStatement<T extends Table, D extends DataClass> {
class InsertStatement<T extends Table, D> {
/// The database to use then executing this statement
@protected
final DatabaseConnectionUser database;
@ -253,7 +253,7 @@ const _insertKeywords = <InsertMode, String>{
/// companion when the underlying companion already exists.
///
/// For an example, see [InsertStatement.insert].
class DoUpdate<T extends Table, D extends DataClass> {
class DoUpdate<T extends Table, D> {
final Insertable<D> Function(T old) _creator;
/// An optional list of columns to serve as an "conflict target", which

View File

@ -2,7 +2,7 @@ part of '../query_builder.dart';
/// Statement that operates with data that already exists (select, delete,
/// update).
abstract class Query<T extends Table, D extends DataClass> extends Component {
abstract class Query<T extends Table, D> extends Component {
/// The database this statement should be sent to.
@protected
DatabaseConnectionUser database;
@ -276,8 +276,7 @@ class _MappedSelectable<S, T> extends Selectable<T> {
}
/// Mixin for a [Query] that operates on a single primary table only.
mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
on Query<T, D> {
mixin SingleTableQueryMixin<T extends Table, D> on Query<T, D> {
/// Makes this statement only include rows that match the [filter].
///
/// For instance, if you have a table users with an id column, you could
@ -356,7 +355,7 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
}
/// Mixin to provide the high-level [limit] methods for users.
mixin LimitContainerMixin<T extends Table, D extends DataClass> on Query<T, D> {
mixin LimitContainerMixin<T extends Table, D> on Query<T, D> {
/// Limits the amount of rows returned by capping them at [limit]. If [offset]
/// is provided as well, the first [offset] rows will be skipped and not
/// included in the result.

View File

@ -13,8 +13,7 @@ abstract class BaseSelectStatement extends Component {
}
/// A select statement that doesn't use joins
class SimpleSelectStatement<T extends Table, D extends DataClass>
extends Query<T, D>
class SimpleSelectStatement<T extends Table, D> extends Query<T, D>
with SingleTableQueryMixin<T, D>, LimitContainerMixin<T, D>, Selectable<D>
implements BaseSelectStatement {
/// Whether duplicate rows should be eliminated from the result (this is a
@ -156,7 +155,7 @@ class TypedResult {
///
/// If this row does not contain non-null columns of the [table], this method
/// will throw an [ArgumentError]. Use [readTableOrNull] for nullable tables.
D readTable<T extends Table, D extends DataClass>(TableInfo<T, D> table) {
D readTable<T extends Table, D>(TableInfo<T, D> table) {
if (!_parsedData.containsKey(table)) {
throw ArgumentError(
'Invalid table passed to readTable: ${table.tableName}. This row '
@ -173,8 +172,7 @@ class TypedResult {
/// [table].
///
/// See also: [readTable], which throws instead of returning `null`.
D? readTableOrNull<T extends Table, D extends DataClass>(
TableInfo<T, D> table) {
D? readTableOrNull<T extends Table, D>(TableInfo<T, D> table) {
return _parsedData[table] as D?;
}

View File

@ -4,7 +4,7 @@ part of '../../query_builder.dart';
// this is called JoinedSelectStatement for legacy reasons - we also use it
// when custom expressions are used as result columns. Basically, it stores
// queries that are more complex than SimpleSelectStatement
class JoinedSelectStatement<FirstT extends Table, FirstD extends DataClass>
class JoinedSelectStatement<FirstT extends Table, FirstD>
extends Query<FirstT, FirstD>
with LimitContainerMixin, Selectable<TypedResult>
implements BaseSelectStatement {

View File

@ -1,7 +1,7 @@
part of '../query_builder.dart';
/// Represents an `UPDATE` statement in sql.
class UpdateStatement<T extends Table, D extends DataClass> extends Query<T, D>
class UpdateStatement<T extends Table, D> extends Query<T, D>
with SingleTableQueryMixin<T, D> {
/// Used internally by moor, construct an update statement
UpdateStatement(DatabaseConnectionUser database, TableInfo<T, D> table)