addFieldDefs method

  1. @override
void addFieldDefs(
  1. TSQLCursor cursor,
  2. TFieldDefs fieldDefs
)
override

Implementation

@override
void addFieldDefs(TSQLCursor cursor, TFieldDefs fieldDefs) {
  final c = cursor as TWapCursor;
  // @@@ Type inference: the gateway returns JSON rows with no field-type metadata,
  // @@@ so every row is scanned and the type is decided from the first non-null value; an all-null column is treated as
  // @@@ ftString. A string field's size is set to the actual maximum length seen (at least 255).
  if (c.rows.isEmpty) {
    // @@@ An empty result set: if there's columns metadata, builds ftString fields (type unknown,
    // @@@ uniformly treated as strings — an empty set never actually reads values anyway, what matters is that the field exists);
    // @@@ without it, fieldDefs stays empty (a backend limitation)
    final cols = c.columns;
    if (cols != null) {
      var no = 1;
      for (final n in cols) {
        addFieldDef(fieldDefs, no, n, TFieldType.ftString, 255, 0,
            false, false, false);
        no++;
      }
    }
    return;
  }
  final names = c.rows.first.keys.toList();
  var fieldNo = 1;
  for (final n in names) {
    dynamic sample;
    for (final row in c.rows) {
      if (row[n] != null) {
        sample = row[n];
        break;
      }
    }
    TFieldType ft;
    var size = 0;
    if (sample == null) {
      ft = TFieldType.ftString;
      size = 255;
    } else if (sample is int) {
      // @@@ A Dart-web trap: JS only has a `number` type, so `15000.0 is int` would
      // @@@ return true. If ftInteger were inferred from this, a subsequently-stored value with a decimal (like
      // @@@ 12345.67) would get rounded to 12345 by TLongintField. The pragmatic solution:
      // @@@ always infer ftFloat for numeric fields (it can losslessly hold integer values too); when integer
      // @@@ semantics are needed, the caller can convert via asInteger when reading it.
      // @@@ (On native platforms, an int also goes through this same ftFloat branch, so the behavior is consistent)
      ft = TFieldType.ftFloat;
    } else if (sample is double) {
      ft = TFieldType.ftFloat;
    } else if (sample is bool) {
      ft = TFieldType.ftBoolean;
    } else if (sample is DateTime) {
      ft = TFieldType.ftDateTime;
    } else if (sample is Uint8List) {
      ft = TFieldType.ftBlob;
      size = 0;
    } else {
      ft = TFieldType.ftString;
      var maxLen = 0;
      for (final row in c.rows) {
        final v = row[n];
        if (v != null && '$v'.length > maxLen) maxLen = '$v'.length;
      }
      size = maxLen < 255 ? 255 : maxLen;
    }
    addFieldDef(fieldDefs, fieldNo, n, ft, size, 0, false, false, false);
    fieldNo++;
  }
}