Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions packages/brick_sqlite_generators/lib/src/sqlite_serialize.dart
Original file line number Diff line number Diff line change
Expand Up @@ -227,24 +227,33 @@ class SqliteSerialize<_Model extends SqliteModel> extends SqliteSerdesGenerator<
String generateUniqueSqliteFunction(Map<String, String> uniqueFields) {
final functionDeclaration =
'@override\nFuture<int?> primaryKeyByUniqueColumns(${element.name} instance, DatabaseExecutor executor) async';
final whereStatement = <String>[];
final valuesStatement = <String>[];
final selectStatement = <String>[];

for (final entry in uniqueFields.entries) {
whereStatement.add('${entry.value} = ?');
valuesStatement.add('instance.${entry.key}');
selectStatement.add(entry.value);
}

if (selectStatement.isEmpty && whereStatement.isEmpty) {
if (uniqueFields.isEmpty) {
return '$functionDeclaration => instance.primaryKey;';
}

return """$functionDeclaration {
final results = await executor.rawQuery('''
SELECT * FROM `$tableName` WHERE ${whereStatement.join(' OR ')} LIMIT 1''',
[${valuesStatement.join(',')}]
final where = <String>[];
final args = <Object?>[];

final fields = <String, Object?>{
${uniqueFields.entries.map((e) => "'${e.value}': instance.${e.key}").join(',\n ')}
};

for (final entry in fields.entries) {
if (entry.value != null) {
where.add('\${entry.key} = ?');
args.add(entry.value);
}
}

if (where.isEmpty) {
return null;
}

final results = await executor.rawQuery(
'SELECT * FROM `$tableName` WHERE ' + where.join(' OR ') + ' LIMIT 1',
args,
Comment on lines +236 to +256
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have no functional difference from what existed. Am I misreading something? Is it the where.isEmpty?

I'd prefer to have the statement precompiled by the generator rather than at runtime - it's ultimately less generated code in each implementation.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's different...

The change is not just structural — it ensures we don’t generate invalid SQL when fields are null (unique field can be null). SQLite treats = NULL as always false, so the previous implementation could fail to find existing rows when a unique field is null.

This version dynamically excludes null values, ensuring the query remains valid and behaves correctly.

While it adds a bit of runtime logic, it improves correctness and avoids edge cases that are hard to debug.

);

// SQFlite returns [{}] when no results are found
Expand Down
Loading