dbCreateUpdate function

Future<void> dbCreateUpdate(
  1. String table,
  2. Map<String, dynamic> objek, [
  3. List<String>? indexFields,
  4. Database? dbContext,
])

origin: kt_ifm_gtid_mob/lib/db.dart union-of: simlpu_mob/lib/db.dart (databaseCreateUpdate) author: anovsiradj, opencode-go/glm-5.2 version: 2025-03-04, revised: 2026-08-17

Generic upsert: merge existing row with new contents then INSERT OR REPLACE. indexFields = match keys (default ['rowid']); existing row merged so omitted fields stay intact.

Implementation

Future<void> dbCreateUpdate(String table, Map<String, dynamic> objek, [List<String>? indexFields, Database? dbContext]) async {
  dbContext ??= db;
  indexFields ??= ['rowid'];

  final tableFields = await dbTableFields(table);
  objek.removeWhere((key, val) {
    if (!tableFields.contains(key)) return true;
    if (val is Uint8List) return false;
    if (val is Map || val is List) return true;
    return false;
  });

  if (indexFields.isNotEmpty && indexFields.every((keyField) => objek.keys.contains(keyField))) {
    final wheres = <String>[];
    final alters = <dynamic>[];

    for (final keyField in indexFields) {
      final valField = objek[keyField];
      if (valField == null) {
        wheres.add('"$keyField" is NULL');
      } else {
        wheres.add('"$keyField"=?');
        alters.add(valField);
      }
    }

    final savedObjek = await dbRawOne("select *,rowid from $table where ${wheres.join(' AND ')}", alters);
    if (savedObjek != null) {
      savedObjek.forEach((key, value) {
        objek[key] ??= value;
      });
    }
  }

  final keys = objek.keys.join('","').toString();
  final vals = List.filled(objek.keys.length, '?').join(',');
  final command = 'INSERT OR REPLACE INTO $table ("$keys") VALUES ($vals)';
  await dbContext.execute(command, objek.values.toList());
}