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';
|
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 {
|
class CustomTablesDb extends _$CustomTablesDb {
|
||||||
CustomTablesDb(QueryExecutor e) : super(e);
|
CustomTablesDb(QueryExecutor e) : super(e);
|
||||||
|
|
||||||
|
|
|
@ -812,6 +812,21 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||||
Config get config => _config ??= Config(this);
|
Config get config => _config ??= Config(this);
|
||||||
Mytable _mytable;
|
Mytable _mytable;
|
||||||
Mytable get mytable => _mytable ??= Mytable(this);
|
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
|
@override
|
||||||
List<TableInfo> get allTables =>
|
List<TableInfo> get allTables =>
|
||||||
[noIds, withDefaults, withConstraints, config, mytable];
|
[noIds, withDefaults, withConstraints, config, mytable];
|
||||||
|
|
|
@ -51,9 +51,11 @@ class SqlSelectQuery extends SqlQuery {
|
||||||
|
|
||||||
class UpdatingQuery extends SqlQuery {
|
class UpdatingQuery extends SqlQuery {
|
||||||
final List<SpecifiedTable> updates;
|
final List<SpecifiedTable> updates;
|
||||||
|
final bool isInsert;
|
||||||
|
|
||||||
UpdatingQuery(String name, AnalysisContext fromContext,
|
UpdatingQuery(String name, AnalysisContext fromContext,
|
||||||
List<FoundVariable> variables, this.updates)
|
List<FoundVariable> variables, this.updates,
|
||||||
|
{this.isInsert = false})
|
||||||
: super(name, fromContext, variables);
|
: super(name, fromContext, variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,4 +52,10 @@ class UpdatedTablesVisitor extends RecursiveVisitor<void> {
|
||||||
_addIfResolved(e.table);
|
_addIfResolved(e.table);
|
||||||
visitChildren(e);
|
visitChildren(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void visitInsertStatement(InsertStatement e) {
|
||||||
|
_addIfResolved(e.table);
|
||||||
|
visitChildren(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,9 @@ class QueryHandler {
|
||||||
|
|
||||||
if (root is SelectStatement) {
|
if (root is SelectStatement) {
|
||||||
return _handleSelect();
|
return _handleSelect();
|
||||||
} else if (root is UpdateStatement || root is DeleteStatement) {
|
} else if (root is UpdateStatement ||
|
||||||
|
root is DeleteStatement ||
|
||||||
|
root is InsertStatement) {
|
||||||
return _handleUpdate();
|
return _handleUpdate();
|
||||||
} else {
|
} else {
|
||||||
throw StateError(
|
throw StateError(
|
||||||
|
@ -39,8 +41,11 @@ class QueryHandler {
|
||||||
context.root.accept(updatedFinder);
|
context.root.accept(updatedFinder);
|
||||||
_foundTables = updatedFinder.foundTables;
|
_foundTables = updatedFinder.foundTables;
|
||||||
|
|
||||||
|
final isInsert = context.root is InsertStatement;
|
||||||
|
|
||||||
return UpdatingQuery(name, context, _foundVariables,
|
return UpdatingQuery(name, context, _foundVariables,
|
||||||
_foundTables.map(mapper.tableToMoor).toList());
|
_foundTables.map(mapper.tableToMoor).toList(),
|
||||||
|
isInsert: isInsert);
|
||||||
}
|
}
|
||||||
|
|
||||||
SqlSelectQuery _handleSelect() {
|
SqlSelectQuery _handleSelect() {
|
||||||
|
|
|
@ -155,6 +155,8 @@ class QueryWriter {
|
||||||
return customUpdate('', variables: [], updates: {});
|
return customUpdate('', variables: [], updates: {});
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
final implName = _update.isInsert ? 'customInsert' : 'customUpdate';
|
||||||
|
|
||||||
buffer.write('Future<int> ${query.name}(');
|
buffer.write('Future<int> ${query.name}(');
|
||||||
_writeParameters(buffer);
|
_writeParameters(buffer);
|
||||||
buffer.write(') {\n');
|
buffer.write(') {\n');
|
||||||
|
@ -162,7 +164,7 @@ class QueryWriter {
|
||||||
_writeExpandedDeclarations(buffer);
|
_writeExpandedDeclarations(buffer);
|
||||||
buffer
|
buffer
|
||||||
..write('return (operateOn ?? this).')
|
..write('return (operateOn ?? this).')
|
||||||
..write('customUpdate(${_queryCode()},');
|
..write('$implName(${_queryCode()},');
|
||||||
|
|
||||||
_writeVariables(buffer);
|
_writeVariables(buffer);
|
||||||
buffer.write(',');
|
buffer.write(',');
|
||||||
|
|
|
@ -326,8 +326,10 @@ mixin ExpressionParser on ParserBase {
|
||||||
break;
|
break;
|
||||||
case TokenType.colon:
|
case TokenType.colon:
|
||||||
final colon = token;
|
final colon = token;
|
||||||
final identifier = _consume(TokenType.identifier,
|
final identifier = _consumeIdentifier(
|
||||||
'Expected an identifier for the named variable') as IdentifierToken;
|
'Expected an identifier for the named variable',
|
||||||
|
lenient: true);
|
||||||
|
|
||||||
final content = identifier.identifier;
|
final content = identifier.identifier;
|
||||||
return ColonNamedVariable(':$content')..setSpan(colon, identifier);
|
return ColonNamedVariable(':$content')..setSpan(colon, identifier);
|
||||||
default:
|
default:
|
||||||
|
@ -392,6 +394,7 @@ mixin ExpressionParser on ParserBase {
|
||||||
)..setSpan(name, _previous);
|
)..setSpan(name, _previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
TupleExpression _consumeTuple() {
|
TupleExpression _consumeTuple() {
|
||||||
final firstToken =
|
final firstToken =
|
||||||
_consume(TokenType.leftParen, 'Expected opening parenthesis for tuple');
|
_consume(TokenType.leftParen, 'Expected opening parenthesis for tuple');
|
||||||
|
|
|
@ -123,7 +123,13 @@ abstract class ParserBase {
|
||||||
_error(message);
|
_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;
|
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".
|
/// Whether this identifier was escaped by putting it in "double ticks".
|
||||||
final bool escaped;
|
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 {
|
String get identifier {
|
||||||
if (escaped) {
|
if (escaped) {
|
||||||
return lexeme.substring(1, lexeme.length - 1);
|
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);
|
: super(TokenType.identifier, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +300,16 @@ class InlineDartToken extends Token {
|
||||||
/// additional properties to ease syntax highlighting, as it allows us to find
|
/// additional properties to ease syntax highlighting, as it allows us to find
|
||||||
/// the keywords easily.
|
/// the keywords easily.
|
||||||
class KeywordToken extends Token {
|
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);
|
KeywordToken(TokenType type, FileSpan span) : super(type, span);
|
||||||
|
|
||||||
|
IdentifierToken convertToIdentifier() {
|
||||||
|
isIdentifier = true;
|
||||||
|
|
||||||
|
return IdentifierToken(false, span, synthetic: false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TokenizerError {
|
class TokenizerError {
|
||||||
|
|
Loading…
Reference in New Issue