mirror of https://github.com/AMT-Cheif/drift.git
Generate query implementations for insert statements
This commit is contained in:
parent
a4b256f8a5
commit
241baed0c3
|
@ -2,7 +2,10 @@ import 'package:moor/moor.dart';
|
|||
|
||||
part 'custom_tables.g.dart';
|
||||
|
||||
@UseMoor(include: {'tables.moor'})
|
||||
@UseMoor(
|
||||
include: {'tables.moor'},
|
||||
queries: {'writeConfig': 'REPLACE INTO config VALUES (:key, :value)'},
|
||||
)
|
||||
class CustomTablesDb extends _$CustomTablesDb {
|
||||
CustomTablesDb(QueryExecutor e) : super(e);
|
||||
|
||||
|
|
|
@ -812,6 +812,21 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
|||
Config get config => _config ??= Config(this);
|
||||
Mytable _mytable;
|
||||
Mytable get mytable => _mytable ??= Mytable(this);
|
||||
Future<int> writeConfig(
|
||||
String key,
|
||||
String value,
|
||||
{@Deprecated('No longer needed with Moor 1.6 - see the changelog for details')
|
||||
QueryEngine operateOn}) {
|
||||
return (operateOn ?? this).customInsert(
|
||||
'REPLACE INTO config VALUES (:key, :value)',
|
||||
variables: [
|
||||
Variable.withString(key),
|
||||
Variable.withString(value),
|
||||
],
|
||||
updates: {config},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<TableInfo> get allTables =>
|
||||
[noIds, withDefaults, withConstraints, config, mytable];
|
||||
|
|
|
@ -51,9 +51,11 @@ class SqlSelectQuery extends SqlQuery {
|
|||
|
||||
class UpdatingQuery extends SqlQuery {
|
||||
final List<SpecifiedTable> updates;
|
||||
final bool isInsert;
|
||||
|
||||
UpdatingQuery(String name, AnalysisContext fromContext,
|
||||
List<FoundVariable> variables, this.updates)
|
||||
List<FoundVariable> variables, this.updates,
|
||||
{this.isInsert = false})
|
||||
: super(name, fromContext, variables);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,4 +52,10 @@ class UpdatedTablesVisitor extends RecursiveVisitor<void> {
|
|||
_addIfResolved(e.table);
|
||||
visitChildren(e);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInsertStatement(InsertStatement e) {
|
||||
_addIfResolved(e.table);
|
||||
visitChildren(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ class QueryHandler {
|
|||
|
||||
if (root is SelectStatement) {
|
||||
return _handleSelect();
|
||||
} else if (root is UpdateStatement || root is DeleteStatement) {
|
||||
} else if (root is UpdateStatement ||
|
||||
root is DeleteStatement ||
|
||||
root is InsertStatement) {
|
||||
return _handleUpdate();
|
||||
} else {
|
||||
throw StateError(
|
||||
|
@ -39,8 +41,11 @@ class QueryHandler {
|
|||
context.root.accept(updatedFinder);
|
||||
_foundTables = updatedFinder.foundTables;
|
||||
|
||||
final isInsert = context.root is InsertStatement;
|
||||
|
||||
return UpdatingQuery(name, context, _foundVariables,
|
||||
_foundTables.map(mapper.tableToMoor).toList());
|
||||
_foundTables.map(mapper.tableToMoor).toList(),
|
||||
isInsert: isInsert);
|
||||
}
|
||||
|
||||
SqlSelectQuery _handleSelect() {
|
||||
|
|
|
@ -155,6 +155,8 @@ class QueryWriter {
|
|||
return customUpdate('', variables: [], updates: {});
|
||||
}
|
||||
*/
|
||||
final implName = _update.isInsert ? 'customInsert' : 'customUpdate';
|
||||
|
||||
buffer.write('Future<int> ${query.name}(');
|
||||
_writeParameters(buffer);
|
||||
buffer.write(') {\n');
|
||||
|
@ -162,7 +164,7 @@ class QueryWriter {
|
|||
_writeExpandedDeclarations(buffer);
|
||||
buffer
|
||||
..write('return (operateOn ?? this).')
|
||||
..write('customUpdate(${_queryCode()},');
|
||||
..write('$implName(${_queryCode()},');
|
||||
|
||||
_writeVariables(buffer);
|
||||
buffer.write(',');
|
||||
|
|
|
@ -326,8 +326,10 @@ mixin ExpressionParser on ParserBase {
|
|||
break;
|
||||
case TokenType.colon:
|
||||
final colon = token;
|
||||
final identifier = _consume(TokenType.identifier,
|
||||
'Expected an identifier for the named variable') as IdentifierToken;
|
||||
final identifier = _consumeIdentifier(
|
||||
'Expected an identifier for the named variable',
|
||||
lenient: true);
|
||||
|
||||
final content = identifier.identifier;
|
||||
return ColonNamedVariable(':$content')..setSpan(colon, identifier);
|
||||
default:
|
||||
|
@ -392,6 +394,7 @@ mixin ExpressionParser on ParserBase {
|
|||
)..setSpan(name, _previous);
|
||||
}
|
||||
|
||||
@override
|
||||
TupleExpression _consumeTuple() {
|
||||
final firstToken =
|
||||
_consume(TokenType.leftParen, 'Expected opening parenthesis for tuple');
|
||||
|
|
|
@ -123,7 +123,13 @@ abstract class ParserBase {
|
|||
_error(message);
|
||||
}
|
||||
|
||||
IdentifierToken _consumeIdentifier(String message) {
|
||||
/// Consumes an identifier. If [lenient] is true and the next token is not
|
||||
/// an identifier but rather a [KeywordToken], that token will be converted
|
||||
/// to an identifier.
|
||||
IdentifierToken _consumeIdentifier(String message, {bool lenient = false}) {
|
||||
if (lenient && _peek is KeywordToken) {
|
||||
return (_advance() as KeywordToken).convertToIdentifier();
|
||||
}
|
||||
return _consume(TokenType.identifier, message) as IdentifierToken;
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,11 @@ class IdentifierToken extends Token {
|
|||
/// Whether this identifier was escaped by putting it in "double ticks".
|
||||
final bool escaped;
|
||||
|
||||
/// Whether this identifier token is synthetic. We sometimes convert
|
||||
/// [KeywordToken]s to identifiers if they're unambiguous, in which case
|
||||
/// [synthetic] will be true on this token because it was not scanned as such.
|
||||
final bool synthetic;
|
||||
|
||||
String get identifier {
|
||||
if (escaped) {
|
||||
return lexeme.substring(1, lexeme.length - 1);
|
||||
|
@ -276,7 +281,7 @@ class IdentifierToken extends Token {
|
|||
}
|
||||
}
|
||||
|
||||
const IdentifierToken(this.escaped, FileSpan span)
|
||||
const IdentifierToken(this.escaped, FileSpan span, {this.synthetic = false})
|
||||
: super(TokenType.identifier, span);
|
||||
}
|
||||
|
||||
|
@ -295,7 +300,16 @@ class InlineDartToken extends Token {
|
|||
/// additional properties to ease syntax highlighting, as it allows us to find
|
||||
/// the keywords easily.
|
||||
class KeywordToken extends Token {
|
||||
/// Whether this token has been used as an identifier while parsing.
|
||||
bool isIdentifier;
|
||||
|
||||
KeywordToken(TokenType type, FileSpan span) : super(type, span);
|
||||
|
||||
IdentifierToken convertToIdentifier() {
|
||||
isIdentifier = true;
|
||||
|
||||
return IdentifierToken(false, span, synthetic: false);
|
||||
}
|
||||
}
|
||||
|
||||
class TokenizerError {
|
||||
|
|
Loading…
Reference in New Issue