Fix generating variables with custom types

This commit is contained in:
Simon Binder 2023-12-10 14:23:19 +01:00
parent 5115bc1525
commit 417d1f59d9
11 changed files with 101 additions and 118 deletions

View File

@ -167,7 +167,7 @@ class WithDefault extends DataClass implements Insertable<WithDefault> {
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (!nullToAbsent || a != null) {
map['a'] = Variable<String>(a);
map['a'] = Variable<String>(a, const CustomTextType());
}
if (!nullToAbsent || b != null) {
map['b'] = Variable<int>(b);
@ -645,13 +645,12 @@ class Config extends DataClass implements Insertable<Config> {
map['config_value'] = Variable<DriftAny>(configValue);
}
if (!nullToAbsent || syncState != null) {
final converter = ConfigTable.$convertersyncStaten;
map['sync_state'] = Variable<int>(converter.toSql(syncState));
map['sync_state'] =
Variable<int>(ConfigTable.$convertersyncStaten.toSql(syncState));
}
if (!nullToAbsent || syncStateImplicit != null) {
final converter = ConfigTable.$convertersyncStateImplicitn;
map['sync_state_implicit'] =
Variable<int>(converter.toSql(syncStateImplicit));
map['sync_state_implicit'] = Variable<int>(
ConfigTable.$convertersyncStateImplicitn.toSql(syncStateImplicit));
}
return map;
}
@ -796,15 +795,13 @@ class ConfigCompanion extends UpdateCompanion<Config> {
map['config_value'] = Variable<DriftAny>(configValue.value);
}
if (syncState.present) {
final converter = ConfigTable.$convertersyncStaten;
map['sync_state'] = Variable<int>(converter.toSql(syncState.value));
map['sync_state'] = Variable<int>(
ConfigTable.$convertersyncStaten.toSql(syncState.value));
}
if (syncStateImplicit.present) {
final converter = ConfigTable.$convertersyncStateImplicitn;
map['sync_state_implicit'] =
Variable<int>(converter.toSql(syncStateImplicit.value));
map['sync_state_implicit'] = Variable<int>(ConfigTable
.$convertersyncStateImplicitn
.toSql(syncStateImplicit.value));
}
if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value);
@ -1747,12 +1744,10 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
return customSelect(
'SELECT config_key FROM config WHERE ${generatedpred.sql} AND(sync_state = ?1 OR sync_state_implicit IN ($expandedvar2))',
variables: [
Variable<int>(NullAwareTypeConverter.wrapToSql(
ConfigTable.$convertersyncState, var1)),
Variable<int>(ConfigTable.$convertersyncStaten.toSql(var1)),
...generatedpred.introducedVariables,
for (var $ in var2)
Variable<int>(NullAwareTypeConverter.wrapToSql(
ConfigTable.$convertersyncStateImplicit, $))
Variable<int>(ConfigTable.$convertersyncStateImplicitn.toSql($))
],
readsFrom: {
config,
@ -1893,7 +1888,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
return customSelect(
'SELECT"defaults"."a" AS "nested_0.a", "defaults"."b" AS "nested_0.b", defaults.b AS "\$n_0" FROM with_defaults AS defaults WHERE a = ?1',
variables: [
Variable<String>(var1)
Variable<String>(var1, const CustomTextType())
],
readsFrom: {
withConstraints,

View File

@ -119,8 +119,8 @@ class Category extends DataClass implements Insertable<Category> {
map['id'] = Variable<int>(id);
map['desc'] = Variable<String>(description);
{
final converter = $CategoriesTable.$converterpriority;
map['priority'] = Variable<int>(converter.toSql(priority));
map['priority'] =
Variable<int>($CategoriesTable.$converterpriority.toSql(priority));
}
return map;
}
@ -246,9 +246,8 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
map['desc'] = Variable<String>(description.value);
}
if (priority.present) {
final converter = $CategoriesTable.$converterpriority;
map['priority'] = Variable<int>(converter.toSql(priority.value));
map['priority'] = Variable<int>(
$CategoriesTable.$converterpriority.toSql(priority.value));
}
return map;
}
@ -423,8 +422,8 @@ class TodoEntry extends DataClass implements Insertable<TodoEntry> {
map['category'] = Variable<int>(category);
}
if (!nullToAbsent || status != null) {
final converter = $TodosTableTable.$converterstatusn;
map['status'] = Variable<String>(converter.toSql(status));
map['status'] =
Variable<String>($TodosTableTable.$converterstatusn.toSql(status));
}
return map;
}
@ -598,9 +597,8 @@ class TodosTableCompanion extends UpdateCompanion<TodoEntry> {
map['category'] = Variable<int>(category.value);
}
if (status.present) {
final converter = $TodosTableTable.$converterstatusn;
map['status'] = Variable<String>(converter.toSql(status.value));
map['status'] = Variable<String>(
$TodosTableTable.$converterstatusn.toSql(status.value));
}
return map;
}
@ -1270,9 +1268,8 @@ class TableWithoutPKCompanion extends UpdateCompanion<CustomRowClass> {
map['web_safe_int'] = Variable<BigInt>(webSafeInt.value);
}
if (custom.present) {
final converter = $TableWithoutPKTable.$convertercustom;
map['custom'] = Variable<String>(converter.toSql(custom.value));
map['custom'] = Variable<String>(
$TableWithoutPKTable.$convertercustom.toSql(custom.value));
}
if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value);
@ -1371,8 +1368,8 @@ class PureDefault extends DataClass implements Insertable<PureDefault> {
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (!nullToAbsent || txt != null) {
final converter = $PureDefaultsTable.$convertertxtn;
map['insert'] = Variable<String>(converter.toSql(txt));
map['insert'] =
Variable<String>($PureDefaultsTable.$convertertxtn.toSql(txt));
}
return map;
}
@ -1457,9 +1454,8 @@ class PureDefaultsCompanion extends UpdateCompanion<PureDefault> {
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
if (txt.present) {
final converter = $PureDefaultsTable.$convertertxtn;
map['insert'] = Variable<String>(converter.toSql(txt.value));
map['insert'] =
Variable<String>($PureDefaultsTable.$convertertxtn.toSql(txt.value));
}
if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value);
@ -1532,7 +1528,7 @@ class WithCustomTypeData extends DataClass
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
map['id'] = Variable<UuidValue>(id);
map['id'] = Variable<UuidValue>(id, const UuidType());
return map;
}

View File

@ -1,3 +1,8 @@
## 2.14.1
- Fix inconsistencies when generating `Variable` instances for columns with
custom types.
## 2.14.0
- __Breaking change__: The name of the generated row class derived from the name

View File

@ -25,6 +25,8 @@ class AnnotatedDartCode {
AnnotatedDartCode(this.elements)
: assert(elements.every((e) => e is String || e is DartTopLevelSymbol));
AnnotatedDartCode.text(String e) : elements = [e];
factory AnnotatedDartCode.ast(AstNode node) {
return AnnotatedDartCode.build(((builder) => builder.addAstNode(node)));
}

View File

@ -843,37 +843,22 @@ class _ExpandedVariableWriter {
// Variables without type converters are written as:
// `Variable<int>(x)`. When there's a type converter, we instead use
// `Variable<int>(typeConverter.toSql(x))`.
// Finally, if we're dealing with a list, we use a collection for to
// write all the variables sequentially.
// Finally, if we're dealing with a list, we use a collection for to write
// all the variables sequentially.
String constructVar(String dartExpr) {
// No longer an array here, we apply a for loop if necessary
final type = _emitter
.dartCode(_emitter.innerColumnType(element.sqlType, nullable: false));
final varType = _emitter.drift('Variable');
final buffer = StringBuffer('$varType<$type>(');
final capture = element.forCaptured;
final converter = element.typeConverter;
if (converter != null) {
// Apply the converter.
if (element.nullable && converter.canBeSkippedForNulls) {
final nullAware = _emitter.drift('NullAwareTypeConverter');
buffer.write('$nullAware.wrapToSql('
'${readConverter(_emitter, element.typeConverter!)}, $dartExpr)');
} else {
buffer.write(
'${readConverter(_emitter, element.typeConverter!)}.toSql($dartExpr)');
}
} else if (capture != null) {
buffer.write('row.read(${asDartLiteral(capture.helperColumn)})');
} else {
buffer.write(dartExpr);
if (capture != null) {
dartExpr = ('row.read(${asDartLiteral(capture.helperColumn)})');
}
buffer.write(')');
return buffer.toString();
final code = _emitter.wrapInVariable(
element,
AnnotatedDartCode.text(dartExpr),
// No longer an array here, we apply a for loop below and run this on
// individual values only.
ignoreArray: true,
);
return _emitter.dartCode(code);
}
final name = element.dartParameterName;

View File

@ -387,7 +387,6 @@ class RowMappingWriter {
extension WriteToColumns on TextEmitter {
void writeToColumnsOverride(Iterable<DriftColumn> columns) {
final expression = drift('Expression');
final variable = drift('Variable');
this
..write('@override\nMap<String, $expression> toColumns'
@ -409,28 +408,10 @@ extension WriteToColumns on TextEmitter {
}
if (needsScope) write('{');
final typeName = dartCode(variableTypeCode(column, nullable: false));
final mapSetter = 'map[${asDartLiteral(column.nameInSql)}] = '
'$variable<$typeName>';
if (column.typeConverter != null) {
// apply type converter before writing the variable
final converter = column.typeConverter!;
this
..write('final converter = ')
..writeDart(readConverter(converter, forNullable: column.nullable))
..writeln(';')
..write(mapSetter)
..write('(converter.toSql(${column.nameInDart}));');
} else {
// no type converter. Write variable directly
this
..write(mapSetter)
..write('(')
..write(column.nameInDart)
..write(');');
}
write('map[${asDartLiteral(column.nameInSql)}] = ');
writeDart(
wrapInVariable(column, AnnotatedDartCode.text(column.nameInDart)));
writeln(';');
// This one closes the optional if from before.
if (needsScope) write('}');

View File

@ -192,34 +192,13 @@ class UpdateCompanionWriter {
final getterName = thisIfNeeded(column.nameInDart, locals);
_buffer.writeln('if ($getterName.present) {');
final typeName =
_emitter.dartCode(_emitter.variableTypeCode(column, nullable: false));
final mapSetter = 'map[${asDartLiteral(column.nameInSql)}] = '
'${_emitter.drift('Variable')}<$typeName>';
_buffer.write('map[${asDartLiteral(column.nameInSql)}] = ');
var value = '$getterName.value';
final converter = column.typeConverter;
if (converter != null) {
// apply type converter before writing the variable
final fieldName = _emitter.dartCode(
_emitter.readConverter(converter, forNullable: column.nullable));
_buffer.writeln('final converter = $fieldName;\n');
value = 'converter.toSql($value)';
}
_emitter.writeDart(
_emitter.wrapInVariable(column, AnnotatedDartCode.text(value)));
_buffer
..write(mapSetter)
..write('($value');
if (column.sqlType.isCustom) {
// Also specify the custom type since it can't be inferred from the
// value passed to the variable.
_buffer
..write(', ')
..write(_emitter.dartCode(column.sqlType.custom!.expression));
}
_buffer.writeln(');}');
_buffer.writeln(';}');
}
_buffer.write('return map; \n}\n');

View File

@ -181,9 +181,10 @@ abstract class _NodeOrWriter {
/// The Dart type that matches the type of this column, ignoring type
/// converters.
///
/// This is the same as [dartType] but without custom types.
AnnotatedDartCode variableTypeCode(HasType type, {bool? nullable}) {
if (type.isArray) {
/// This is the same as [dartType] but without type converters.
AnnotatedDartCode variableTypeCode(HasType type,
{bool? nullable, bool ignoreArray = false}) {
if (type.isArray && !ignoreArray) {
final inner =
innerColumnType(type.sqlType, nullable: nullable ?? type.nullable);
return AnnotatedDartCode([
@ -217,6 +218,40 @@ abstract class _NodeOrWriter {
});
}
AnnotatedDartCode wrapInVariable(HasType column, AnnotatedDartCode expression,
{bool ignoreArray = false}) {
return AnnotatedDartCode.build((b) {
b
..addTopLevel(DartTopLevelSymbol.drift('Variable'))
..addText('<')
..addCode(
variableTypeCode(column, nullable: false, ignoreArray: ignoreArray))
..addText('>(');
final converter = column.typeConverter;
if (converter != null) {
// apply type converter before writing the variable
b
..addCode(readConverter(converter, forNullable: column.nullable))
..addText('.toSql(')
..addCode(expression)
..addText(')');
} else {
b.addCode(expression);
}
if (column.sqlType.isCustom) {
// Also specify the custom type since it can't be inferred from the
// value passed to the variable.
b
..addText(', ')
..addCode(column.sqlType.custom!.expression);
}
b.addText(')');
});
}
String refUri(Uri definition, String element) {
final prefix =
writer.generationOptions.imports.prefixFor(definition, element);

View File

@ -1,6 +1,6 @@
name: drift_dev
description: Dev-dependency for users of drift. Contains the generator and development tools.
version: 2.14.0
version: 2.14.1
repository: https://github.com/simolus3/drift
homepage: https://drift.simonbinder.eu/
issue_tracker: https://github.com/simolus3/drift/issues

View File

@ -8,6 +8,9 @@ part 'main.g.dart';
class Users extends Table {
UuidColumn get id => customType(PgTypes.uuid).withDefault(genRandomUuid())();
TextColumn get name => text()();
@override
Set<Column<Object>>? get primaryKey => {id};
}
@DriftDatabase(tables: [Users])
@ -38,5 +41,7 @@ void main() async {
UsersCompanion.insert(name: 'Simon', id: Value(Uuid().v4obj())));
print(user);
await database.users.deleteOne(user);
await database.close();
}

View File

@ -45,7 +45,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
}
@override
Set<GeneratedColumn> get $primaryKey => const {};
Set<GeneratedColumn> get $primaryKey => {id};
@override
User map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
@ -70,7 +70,7 @@ class User extends DataClass implements Insertable<User> {
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
map['id'] = Variable<UuidValue>(id);
map['id'] = Variable<UuidValue>(id, PgTypes.uuid);
map['name'] = Variable<String>(name);
return map;
}