validate method

void validate(
  1. Map<String, dynamic> row
)

Validate row values against schema, coercing types where safe.

Coercion rules (to avoid spurious errors from SQL string literals): intType : int | double→int | String→int | bool→0/1 realType : num | String→double | bool→0.0/1.0 boolType : bool | int(0/1) | String('true'/'false'/'0'/'1') textType : anything → toString() (never fails)

After coercion the value is written back into row so callers always store the correctly-typed value.

Implementation

void validate(Map<String, dynamic> row) {
  for (final col in columns) {
    final raw = row[col.name];
    if (raw == null) {
      if (!col.isNullable && !col.isPrimaryKey) {
        throw Exception('Column "${col.name}" cannot be null');
      }
      continue;
    }
    switch (col.type) {
      case DataType.intType:
        if (raw is int) break;
        if (raw is double) { row[col.name] = raw.toInt(); break; }
        if (raw is bool)   { row[col.name] = raw ? 1 : 0; break; }
        if (raw is String) {
          final n = int.tryParse(raw) ??
                    double.tryParse(raw)?.toInt();
          if (n != null) { row[col.name] = n; break; }
        }
        // Keep value as-is — don't throw, just warn
        break;

      case DataType.realType:
        if (raw is double) break;
        if (raw is int)    { row[col.name] = raw.toDouble(); break; }
        if (raw is bool)   { row[col.name] = raw ? 1.0 : 0.0; break; }
        if (raw is String) {
          final n = double.tryParse(raw) ??
                    int.tryParse(raw)?.toDouble();
          if (n != null) { row[col.name] = n; break; }
        }
        break;

      case DataType.boolType:
        if (raw is bool)   break;
        // FIX: SQLite/NebulaDB stores booleans as INTEGER 0/1.
        // Both int and double (e.g. 0.0 / 1.0) must be coerced.
        if (raw is int)    { row[col.name] = raw != 0; break; }
        if (raw is double) { row[col.name] = raw != 0.0; break; }
        if (raw is String) {
          final lo = raw.toLowerCase();
          if (lo == 'true'  || lo == '1') { row[col.name] = true;  break; }
          if (lo == 'false' || lo == '0') { row[col.name] = false; break; }
        }
        break;

      case DataType.textType:
        if (raw is! String) { row[col.name] = raw.toString(); }
        break;
    }
  }
}