Moor: Support dynamic default values

Created on 23 Dec 2019  路  10Comments  路  Source: simolus3/moor

Hi,
I'm wondering how to generate a table that uses UUID's as primary key and with this is possible using moor. I think the PK part is right below, setting the default is something I don't understand.
Given the following code:

class User extends Table{

  IntColumn get id => text().withDefault();//Uuid().v4() should be used here
  TextColumn get firstName => text().withLength(min:3).withDefault( const Constant("Max"))();
  TextColumn get lastName => text().withLength(min:3).withDefault( const Constant("Power"))();
  TextColumn get email => text()();
  TextColumn get position => text()();

  @override
  Set<Column> get primaryKey => {id};
}
dart-dsl enhancement generator

All 10 comments

The primary key part looks correct to me. Unfortunately, default values must be constants at the moment. This is because we write them into the CREATE TABLE statement (so your table would generate something like first_name TEXT CHECK(LENGTH(first_name) >= 3) DEFAULT 'Max'). Of course, we can't support non-constant Dart expressions like Uuid().v4() with that approach.

Exposed for Kotlin has something called a clientDefault. It's a function that will be evaluated for each insert, the return value will then be used for the column. I can imagine a similar api in moor, so something like

IntColumn get id => text().clientDefault(() => Uuid().v4());

Thanks for the reply, I fully understand that if the code generates a SQL script the value has to be static. The client side check you mentioned sounds good to me, it could be an useful addition. I will go one with my checks, so far Moor looks really promising. When done I will check if I can find a quick workaround for this use case

Is it better to store UUID's as blobs? This is the converter I wrote.

class UUIDConverter extends TypeConverter<String, Uint8List> {
  const UUIDConverter();

  @override
  String mapToDart(Uint8List fromDb) =>
      fromDb != null ? Uuid().unparse(fromDb) : null;

  @override
  Uint8List mapToSql(String value) =>
      value != null ? Uint8List.fromList(Uuid().parse(value)) : null;
}

Is it better to store UUID's as blobs?

You save some bytes because the binary encoding is more efficient. The difference should be marginal though. I don't think there will be any performance difference apart from that.

clientDefault will be available in the next moor version. Thanks again for the idea!

TextColumn get id => text().clientDefault(() => uuid.v4())();

How can I retrieve the generated uuid?

You'd have to insert an object, get its id and load that. That will give you a full row which includes the computed fields.

What about an option to return the primary key value by default on insertion? Would it be hard to implement?

And thanks for the quick reply.

an option to return the primary key value by default on insertion

sqlite only gives us the rowid for inserts (which usually _is_ the primary key when using auto increment or having a single PK column of type int). That is what we return from the insert methods.
So there isn't really a way to load a row's primary key without loading the full row in a select.

Got it. Thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

johrpan picture johrpan  路  4Comments

tony123S picture tony123S  路  4Comments

Ltei picture Ltei  路  3Comments

VadimOsovsky picture VadimOsovsky  路  3Comments

omidraha picture omidraha  路  3Comments