Escape column names during insert

This commit is contained in:
Simon Binder 2019-12-02 21:40:41 +01:00
parent a0ce3421c9
commit 092f64d7cf
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 32 additions and 7 deletions

View File

@ -54,6 +54,7 @@ mixin TableInfo<TableDsl extends Table, D extends DataClass> on Table {
/// The keys should represent the column name in sql, the values the /// The keys should represent the column name in sql, the values the
/// corresponding values of the field. All fields of the [instance] which are /// corresponding values of the field. All fields of the [instance] which are
/// present will be written, absent fields will be omitted. /// present will be written, absent fields will be omitted.
/// Note that column names aren't escaped in the [Map.keys].
Map<String, Variable> entityToSql(covariant UpdateCompanion<D> instance); Map<String, Variable> entityToSql(covariant UpdateCompanion<D> instance);
/// Maps the given row returned by the database into the fitting data class. /// Maps the given row returned by the database into the fitting data class.

View File

@ -106,9 +106,11 @@ class InsertStatement<D extends DataClass> {
if (map.isEmpty) { if (map.isEmpty) {
ctx.buffer.write('DEFAULT VALUES'); ctx.buffer.write('DEFAULT VALUES');
} else { } else {
final columns = map.keys.map(escapeIfNeeded);
ctx.buffer ctx.buffer
..write('(') ..write('(')
..write(map.keys.join(', ')) ..write(columns.join(', '))
..write(') ') ..write(') ')
..write('VALUES ('); ..write('VALUES (');

View File

@ -56,7 +56,8 @@ class TableWithoutPK extends Table {
} }
class PureDefaults extends Table with AutoIncrement { class PureDefaults extends Table with AutoIncrement {
TextColumn get txt => text().nullable()(); // name after keyword to ensure it's escaped properly
TextColumn get txt => text().named('insert').nullable()();
} }
// example object used for custom mapping // example object used for custom mapping

View File

@ -1165,7 +1165,7 @@ class PureDefault extends DataClass implements Insertable<PureDefault> {
final stringType = db.typeSystem.forDartType<String>(); final stringType = db.typeSystem.forDartType<String>();
return PureDefault( return PureDefault(
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']), id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
txt: stringType.mapFromDatabaseResponse(data['${effectivePrefix}txt']), txt: stringType.mapFromDatabaseResponse(data['${effectivePrefix}insert']),
); );
} }
factory PureDefault.fromJson(Map<String, dynamic> json, factory PureDefault.fromJson(Map<String, dynamic> json,
@ -1257,7 +1257,7 @@ class $PureDefaultsTable extends PureDefaults
GeneratedTextColumn get txt => _txt ??= _constructTxt(); GeneratedTextColumn get txt => _txt ??= _constructTxt();
GeneratedTextColumn _constructTxt() { GeneratedTextColumn _constructTxt() {
return GeneratedTextColumn( return GeneratedTextColumn(
'txt', 'insert',
$tableName, $tableName,
true, true,
); );
@ -1303,7 +1303,7 @@ class $PureDefaultsTable extends PureDefaults
map['id'] = Variable<int, IntType>(d.id.value); map['id'] = Variable<int, IntType>(d.id.value);
} }
if (d.txt.present) { if (d.txt.present) {
map['txt'] = Variable<String, StringType>(d.txt.value); map['insert'] = Variable<String, StringType>(d.txt.value);
} }
return map; return map;
} }

View File

@ -157,4 +157,13 @@ void main() {
completion(42), completion(42),
); );
}); });
test('escaped when column name is keyword', () async {
await db
.into(db.pureDefaults)
.insert(PureDefaultsCompanion.insert(txt: const Value('foo')));
verify(executor
.runInsert('INSERT INTO pure_defaults (`insert`) VALUES (?)', ['foo']));
});
} }

View File

@ -3,6 +3,18 @@ import 'package:moor_generator/src/backends/build/moor_builder.dart';
import 'package:moor_generator/src/writer/database_writer.dart'; import 'package:moor_generator/src/writer/database_writer.dart';
import 'package:source_gen/source_gen.dart'; import 'package:source_gen/source_gen.dart';
const _ignoredLints = [
'unnecessary_brace_in_string_interps',
'unnecessary_this',
// more style rules from the Flutter repo we're violating. Should we fix
// those?
/*
'always_specify_types',
'implicit_dynamic_parameter',
'sort_constructors_first',
'lines_longer_than_80_chars',*/
];
class MoorGenerator extends Generator implements BaseGenerator { class MoorGenerator extends Generator implements BaseGenerator {
@override @override
MoorBuilder builder; MoorBuilder builder;
@ -13,8 +25,8 @@ class MoorGenerator extends Generator implements BaseGenerator {
final writer = builder.createWriter(); final writer = builder.createWriter();
if (parsed.declaredDatabases.isNotEmpty) { if (parsed.declaredDatabases.isNotEmpty) {
writer.leaf().write( final ignore = '// ignore_for_file: ${_ignoredLints.join(', ')}\n';
'// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this\n'); writer.leaf().write(ignore);
} }
for (var db in parsed.declaredDatabases) { for (var db in parsed.declaredDatabases) {