Generate code for update and delete statements

This commit is contained in:
Simon Binder 2019-06-30 19:34:54 +02:00
parent baf3c9ce88
commit f5492b8bcb
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
7 changed files with 84 additions and 2 deletions

View File

@ -58,6 +58,7 @@ class TableWithoutPK extends Table {
queries: { queries: {
'allTodosWithCategory': 'SELECT t.*, c.id as catId, c."desc" as catDesc ' 'allTodosWithCategory': 'SELECT t.*, c.id as catId, c."desc" as catDesc '
'FROM todos t INNER JOIN categories c ON c.id = t.category', 'FROM todos t INNER JOIN categories c ON c.id = t.category',
'deleteTodoById': 'DELETE FROM todos WHERE id = ?'
}, },
) )
class TodoDb extends _$TodoDb { class TodoDb extends _$TodoDb {

View File

@ -1068,6 +1068,13 @@ abstract class _$TodoDb extends GeneratedDatabase {
}).map((rows) => rows.map(_rowToAllTodosWithCategoryResult).toList()); }).map((rows) => rows.map(_rowToAllTodosWithCategoryResult).toList());
} }
Future<int> deleteTodoById(int var1, {QueryEngine operateOn}) {
return (operateOn ?? this)
.customUpdate('DELETE FROM todos WHERE id = ?', variables: [
Variable.withInt(var1),
], updates: {});
}
@override @override
List<TableInfo> get allTables => List<TableInfo> get allTables =>
[todosTable, categories, users, sharedTodos, tableWithoutPK]; [todosTable, categories, users, sharedTodos, tableWithoutPK];

View File

@ -29,6 +29,14 @@ class SqlSelectQuery extends SqlQuery {
: super(name, sql, variables); : super(name, sql, variables);
} }
class UpdatingQuery extends SqlQuery {
final List<SpecifiedTable> updates;
UpdatingQuery(
String name, String sql, List<FoundVariable> variables, this.updates)
: super(name, sql, variables);
}
class InferredResultSet { class InferredResultSet {
/// If the result columns of a SELECT statement exactly match one table, we /// If the result columns of a SELECT statement exactly match one table, we
/// can just use the data class generated for that table. Otherwise, we'd have /// can just use the data class generated for that table. Otherwise, we'd have

View File

@ -2,7 +2,7 @@ import 'package:sqlparser/sqlparser.dart';
/// An AST-visitor that walks sql statements and finds all tables referenced in /// An AST-visitor that walks sql statements and finds all tables referenced in
/// them. /// them.
class AffectedTablesVisitor extends RecursiveVisitor<void> { class ReferencedTablesVisitor extends RecursiveVisitor<void> {
final Set<Table> foundTables = {}; final Set<Table> foundTables = {};
@override @override
@ -27,3 +27,29 @@ class AffectedTablesVisitor extends RecursiveVisitor<void> {
visitChildren(e); visitChildren(e);
} }
} }
/// Finds all tables that could be affected when executing a query. In
/// contrast to [ReferencedTablesVisitor], which finds all references, this
/// visitor only collects tables a query writes to.
class UpdatedTablesVisitor extends RecursiveVisitor<void> {
final Set<Table> foundTables = {};
void _addIfResolved(ResolvesToResultSet r) {
final resolved = r.resultSet;
if (resolved is Table) {
foundTables.add(resolved);
}
}
@override
void visitDeleteStatement(DeleteStatement e) {
_addIfResolved(e.from);
visitChildren(e);
}
@override
void visitUpdateStatement(UpdateStatement e) {
_addIfResolved(e.table);
visitChildren(e);
}
}

View File

@ -22,14 +22,25 @@ class QueryHandler {
if (root is SelectStatement) { if (root is SelectStatement) {
return _handleSelect(); return _handleSelect();
} else if (root is UpdateStatement || root is DeleteStatement) {
return _handleUpdate();
} else { } else {
throw StateError( throw StateError(
'Unexpected sql: Got $root, expected a select statement'); 'Unexpected sql: Got $root, expected a select statement');
} }
} }
UpdatingQuery _handleUpdate() {
final updatedFinder = UpdatedTablesVisitor();
context.root.accept(updatedFinder);
_foundTables = updatedFinder.foundTables;
return UpdatingQuery(name, context.sql, _foundVariables,
_foundTables.map(mapper.tableToMoor).toList());
}
SqlSelectQuery _handleSelect() { SqlSelectQuery _handleSelect() {
final tableFinder = AffectedTablesVisitor(); final tableFinder = ReferencedTablesVisitor();
_select.accept(tableFinder); _select.accept(tableFinder);
_foundTables = tableFinder.foundTables; _foundTables = tableFinder.foundTables;
final moorTables = _foundTables.map(mapper.tableToMoor).toList(); final moorTables = _foundTables.map(mapper.tableToMoor).toList();

View File

@ -43,6 +43,7 @@ class SharedState {
message: 'The type $type is not a moor table', message: 'The type $type is not a moor table',
affectedElement: initializedBy, affectedElement: initializedBy,
)); ));
return null;
} else { } else {
return tableParser.parse(type.element as ClassElement); return tableParser.parse(type.element as ClassElement);
} }

View File

@ -8,12 +8,15 @@ import 'package:recase/recase.dart';
class QueryWriter { class QueryWriter {
final SqlQuery query; final SqlQuery query;
SqlSelectQuery get _select => query as SqlSelectQuery; SqlSelectQuery get _select => query as SqlSelectQuery;
UpdatingQuery get _update => query as UpdatingQuery;
QueryWriter(this.query); QueryWriter(this.query);
void writeInto(StringBuffer buffer) { void writeInto(StringBuffer buffer) {
if (query is SqlSelectQuery) { if (query is SqlSelectQuery) {
_writeSelect(buffer); _writeSelect(buffer);
} else if (query is UpdatingQuery) {
_writeUpdatingQuery(buffer);
} }
} }
@ -81,6 +84,26 @@ class QueryWriter {
..write('\n}\n'); ..write('\n}\n');
} }
void _writeUpdatingQuery(StringBuffer buffer) {
/*
Future<int> test() {
return customUpdate('', variables: [], updates: {});
}
*/
buffer.write('Future<int> ${query.name}(');
_writeParameters(buffer);
buffer
..write(') {\n')
..write('return (operateOn ?? this).')
..write('customUpdate(${asDartLiteral(query.sql)},');
_writeVariables(buffer);
buffer.write(',');
_writeUpdates(buffer);
buffer..write(');\n}\n');
}
void _writeParameters(StringBuffer buffer, void _writeParameters(StringBuffer buffer,
{bool dontOverrideEngine = false}) { {bool dontOverrideEngine = false}) {
final paramList = query.variables final paramList = query.variables
@ -113,4 +136,9 @@ class QueryWriter {
final from = _select.readsFrom.map((t) => t.tableFieldName).join(', '); final from = _select.readsFrom.map((t) => t.tableFieldName).join(', ');
buffer..write('readsFrom: {')..write(from)..write('}'); buffer..write('readsFrom: {')..write(from)..write('}');
} }
void _writeUpdates(StringBuffer buffer) {
final from = _update.updates.map((t) => t.tableFieldName).join(', ');
buffer..write('updates: {')..write(from)..write('}');
}
} }