Provide information about the sql dialect at runtime

This commit is contained in:
Simon Binder 2019-07-28 14:21:39 +02:00
parent 94a9b9e2bc
commit 7f79fd922b
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
9 changed files with 46 additions and 7 deletions

View File

@ -20,7 +20,7 @@ You'll need to import `package:moor_mysql/moor_mysql.dart`.
## Limitations
We're currently experimenting with other database engines - Moor was mainly designed for
sqlite and supporting advanced features of MySQL is not a priority right now.
- No migrations
- No migrations - you'll need to create your tables manually
- Some statements don't work
- Compiled custom queries don't work - we can only parse sqlite. Of course, runtime custom
queries with `customSelect` and `customUpdate` will work as expected.

View File

@ -71,6 +71,9 @@ class _MySqlDelegate extends DatabaseDelegate with _MySqlExecutor {
@override
TransactionDelegate get transactionDelegate => _TransactionOpener(this);
@override
SqlDialect get dialect => SqlDialect.mysql;
@override
Future<void> open([GeneratedDatabase db]) async {
_connection = await MySqlConnection.connect(_settings);

View File

@ -4,7 +4,7 @@ for details on how to use this feature.
- New `backends` api, making it easier to write database drivers that work with moor. Apart from
`moor_flutter`, new experimental backends can be checked out from git:
1. `encrypted_moor`: An encrypted moor database: https://github.com/simolus3/moor/tree/develop/extras/encryption
2. `moor_mysql`: Work in progress mysql backend for moor. https://github.com/simolus3/moor/tree/develop/extras/mysql
## 1.6.0
- Experimental web support! See [the documentation](https://moor.simonbinder.eu/web) for details.
- Make transactions easier to use: Thanks to some Dart async magic, you no longer need to run

View File

@ -2,6 +2,7 @@
/// with moor.
library backends;
export 'src/runtime/components/component.dart' show SqlDialect;
export 'src/runtime/executor/executor.dart';
export 'src/runtime/executor/helpers/delegates.dart';
export 'src/runtime/executor/helpers/engines.dart';

View File

@ -10,6 +10,11 @@ abstract class Component {
void writeInto(GenerationContext context);
}
/// An enumeration of database systems supported by moor. Only
/// [SqlDialect.sqlite] is officially supported, all others are in an
/// experimental state at the moment.
enum SqlDialect { sqlite, mysql }
/// Contains information about a query while it's being constructed.
class GenerationContext {
/// Whether the query obtained by this context operates on multiple tables.
@ -19,6 +24,7 @@ class GenerationContext {
bool hasMultipleTables = false;
final SqlTypeSystem typeSystem;
final SqlDialect dialect;
final QueryExecutor executor;
final List<dynamic> _boundVariables = [];
@ -32,9 +38,11 @@ class GenerationContext {
GenerationContext.fromDb(QueryEngine database)
: typeSystem = database.typeSystem,
executor = database.executor;
executor = database.executor,
dialect = database.executor.dialect;
GenerationContext(this.typeSystem, this.executor);
GenerationContext(this.typeSystem, this.executor,
{this.dialect = SqlDialect.sqlite});
/// Introduces a variable that will be sent to the database engine. Whenever
/// this method is called, a question mark should be added to the [buffer] so

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:moor/src/runtime/components/component.dart';
import 'package:moor/src/runtime/database.dart';
import 'package:moor/src/utils/hash.dart';
@ -8,11 +9,17 @@ import 'package:moor/src/utils/hash.dart';
/// return their results in a raw form.
///
/// This is an internal api of moor, which can break often. If you want to
/// implement custom database backends, consider using a delegate as described
/// [here](https://moor.simonbinder.eu/custom_backend)
/// implement custom database backends, consider using the new `backends` API.
/// The [moor_flutter implementation](https://github.com/simolus3/moor/blob/develop/moor_flutter/lib/moor_flutter.dart)
/// might be useful as a reference. If you want to write your own database
/// engine to use with moor and run into issues, please consider creating an
/// issue.
abstract class QueryExecutor {
GeneratedDatabase databaseInfo;
/// The [SqlDialect] to use for this database engine.
SqlDialect get dialect => SqlDialect.sqlite;
/// Performs the async [fn] after this executor is ready, or directly if it's
/// already ready.
Future<T> doWhenOpened<T>(FutureOr<T> fn(QueryExecutor e)) {

View File

@ -1,5 +1,6 @@
import 'dart:typed_data' show Uint8List;
import 'package:moor/moor.dart';
import 'package:moor/src/runtime/components/component.dart';
import 'package:moor/src/runtime/executor/helpers/results.dart';
/// An interface that supports sending database queries. Used as a backend for
@ -48,6 +49,9 @@ abstract class DatabaseDelegate implements QueryDelegate {
Future<void> close() async {
// default no-op implementation
}
/// The [SqlDialect] understood by this database engine.
SqlDialect get dialect => SqlDialect.sqlite;
}
/// An interface which can execute sql statements.

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'package:moor/moor.dart';
import 'package:moor/src/runtime/components/component.dart';
import 'package:pedantic/pedantic.dart';
import 'package:synchronized/synchronized.dart';
@ -204,6 +205,8 @@ class _BeforeOpeningExecutor extends QueryExecutor
}
}
/// A database engine (implements [QueryExecutor]) that delegated the relevant
/// work to a [DatabaseDelegate].
class DelegatedDatabase extends QueryExecutor with _ExecutorWithQueryDelegate {
final DatabaseDelegate delegate;
Completer<bool> _openingCompleter;
@ -216,6 +219,9 @@ class DelegatedDatabase extends QueryExecutor with _ExecutorWithQueryDelegate {
@override
QueryDelegate get impl => delegate;
@override
SqlDialect get dialect => delegate.dialect;
DelegatedDatabase(this.delegate,
{this.logStatements, this.isSequential = false}) {
// not using default value because it's commonly set to null

View File

@ -193,7 +193,17 @@ class GeneratedIntColumn extends GeneratedColumn<int, IntType>
void writeColumnDefinition(GenerationContext into) {
// todo make this work with custom constraints, default values, etc.
if (hasAutoIncrement) {
into.buffer.write('${$name} $typeName PRIMARY KEY AUTOINCREMENT');
String autoIncrementKeyword;
switch (into.dialect) {
case SqlDialect.sqlite:
autoIncrementKeyword = 'AUTOINCREMENT';
break;
case SqlDialect.mysql:
autoIncrementKeyword = 'AUTO INCREMENT';
break;
}
into.buffer.write('${$name} $typeName PRIMARY $autoIncrementKeyword');
} else {
super.writeColumnDefinition(into);
}