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};
}
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