void cql_copyoutrow()

in sources/cqlrt_common.c [941:1138]


void cql_copyoutrow(
  sqlite3 *_Nullable db,
  cql_result_set_ref _Nonnull result_set,
  cql_int32 row,
  cql_int32 count, ...)
{
  cql_contract(result_set);

  va_list args;
  va_start(args, count);

  cql_int32 row_count = cql_result_set_get_count(result_set);

  if (row >= row_count || row < 0) {
    cql_multinull(count, &args);
    va_end(args);
    return;
  }

  bool got_decoder = false;
  cql_object_ref _Nullable encoder = NULL;

  // Find vault context column
  cql_result_set_meta *meta = cql_result_set_get_meta(result_set);
  cql_int32 encode_context_type = -1;
  char *encode_context_field = NULL;
  if (meta->encodeContextIndex >= 0) {
    encode_context_type = meta->dataTypes[meta->encodeContextIndex];
    encode_context_field = cql_address_of_col(result_set, row, meta->encodeContextIndex, &encode_context_type);
  }
  // sometimes the below usages resolve to do-noting macros and thus this gets
  // considered as unused. So to always give it a "usage" cast it to void here.
  (void)encode_context_field;

  for (cql_int32 column = 0; column < count; column++) {
    cql_int32 type = va_arg(args, cql_int32);
    cql_int32 core_data_type_and_not_null = CQL_CORE_DATA_TYPE_OF(type) | (type & CQL_DATA_TYPE_NOT_NULL);
    // This is important to document should_decode because it needs some clarification
    // that impact how the vault feature work in CQL.
    // This function copy raw values from a result set (out union). Therefore if we
    // detect that some of the fields read are encoded (should_decode == TRUE), then we
    // have to decode the value copied.
    // We never encode values read from result_set even though the type flag
    // is CQL_DATA_TYPE_ENCODED. The flag CQL_DATA_TYPE_ENCODED is used to encode fields
    // read from db (see cql_multifetch(...)) or to decode fields read from result_set (out union).
    bool should_decode = db && cql_result_set_get_is_encoded_col(result_set, column);

    if (should_decode && !got_decoder) {
      encoder = cql_copy_encoder(db);
      got_decoder = true;  // note the decoder might be null so we need a flag
    }

    switch (core_data_type_and_not_null) {
      case CQL_DATA_TYPE_INT32 | CQL_DATA_TYPE_NOT_NULL: {
        cql_int32 *int32_data = va_arg(args, cql_int32 *);
        *int32_data = cql_result_set_get_int32_col(result_set, row, column);
        if (should_decode) {
          *int32_data = cql_decode_int32(encoder, *int32_data, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_INT64 | CQL_DATA_TYPE_NOT_NULL: {
        cql_int64 *int64_data = va_arg(args, cql_int64 *);
        *int64_data = cql_result_set_get_int64_col(result_set, row, column);
        if (should_decode) {
          *int64_data = cql_decode_int64(encoder, *int64_data, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_DOUBLE | CQL_DATA_TYPE_NOT_NULL: {
        cql_double *double_data = va_arg(args, cql_double *);
        *double_data = cql_result_set_get_double_col(result_set, row, column);
        if (should_decode) {
          *double_data = cql_decode_double(encoder, *double_data, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_BOOL | CQL_DATA_TYPE_NOT_NULL: {
        cql_bool *bool_data = va_arg(args, cql_bool *);
        *bool_data = cql_result_set_get_bool_col(result_set, row, column);
        if (should_decode) {
          *bool_data = cql_decode_bool(encoder, *bool_data, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_STRING | CQL_DATA_TYPE_NOT_NULL: {
        cql_string_ref *str_ref = va_arg(args, cql_string_ref *);
        cql_set_string_ref(str_ref, cql_result_set_get_string_col(result_set, row, column));
        cql_string_ref new_str_ref = NULL;
        if (should_decode) {
          new_str_ref = cql_decode_string_ref_new(encoder, *str_ref, encode_context_type, encode_context_field);
          cql_set_string_ref(str_ref, new_str_ref);
          cql_string_release(new_str_ref);
        }
        break;
      }
      case CQL_DATA_TYPE_BLOB | CQL_DATA_TYPE_NOT_NULL: {
        cql_blob_ref *blob_ref = va_arg(args, cql_blob_ref *);
        cql_set_blob_ref(blob_ref, cql_result_set_get_blob_col(result_set, row, column));
        cql_blob_ref new_blob_ref = NULL;
        if (should_decode) {
          new_blob_ref = cql_decode_blob_ref_new(encoder, *blob_ref, encode_context_type, encode_context_field);
          cql_set_blob_ref(blob_ref, new_blob_ref);
          cql_blob_release(new_blob_ref);
        }
        break;
      }
      case CQL_DATA_TYPE_OBJECT | CQL_DATA_TYPE_NOT_NULL: {
        cql_object_ref *obj_ref = va_arg(args, cql_object_ref *);
        cql_set_object_ref(obj_ref, cql_result_set_get_object_col(result_set, row, column));
        break;
      }
      case CQL_DATA_TYPE_INT32: {
        cql_nullable_int32 *_Nonnull int32p = va_arg(args, cql_nullable_int32 *_Nonnull);
        if (cql_result_set_get_is_null_col(result_set, row, column)) {
          cql_set_null(*int32p);
        }
        else {
          cql_set_notnull(*int32p, cql_result_set_get_int32_col(result_set, row, column));
        }
        if (!int32p->is_null && should_decode) {
          int32p->value = cql_decode_int32(encoder, int32p->value, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_INT64: {
        cql_nullable_int64 *_Nonnull int64p = va_arg(args, cql_nullable_int64 *_Nonnull);
        if (cql_result_set_get_is_null_col(result_set, row, column)) {
          cql_set_null(*int64p);
        }
        else {
          cql_set_notnull(*int64p, cql_result_set_get_int64_col(result_set, row, column));
        }
        if (!int64p->is_null && should_decode) {
          int64p->value = cql_decode_int64(encoder, int64p->value, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_DOUBLE: {
        cql_nullable_double *_Nonnull doublep = va_arg(args, cql_nullable_double *_Nonnull);
        if (cql_result_set_get_is_null_col(result_set, row, column)) {
          cql_set_null(*doublep);
        }
        else {
          cql_set_notnull(*doublep, cql_result_set_get_double_col(result_set, row, column));
        }
        if (!doublep->is_null && should_decode) {
          doublep->value = cql_decode_double(encoder, doublep->value, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_BOOL: {
        cql_nullable_bool *_Nonnull boolp = va_arg(args, cql_nullable_bool *_Nonnull);
        if (cql_result_set_get_is_null_col(result_set, row, column)) {
          cql_set_null(*boolp);
        }
        else {
          cql_set_notnull(*boolp, cql_result_set_get_bool_col(result_set, row, column));
        }
        if (!boolp->is_null && should_decode) {
          boolp->value = cql_decode_bool(encoder, boolp->value, encode_context_type, encode_context_field);
        }
        break;
      }
      case CQL_DATA_TYPE_STRING: {
        cql_string_ref *str_ref = va_arg(args, cql_string_ref *);
        cql_set_string_ref(str_ref, cql_result_set_get_string_col(result_set, row, column));
        cql_string_ref new_str_ref = NULL;
        if (*str_ref && should_decode) {
          new_str_ref = cql_decode_string_ref_new(encoder, *str_ref, encode_context_type, encode_context_field);
          cql_set_string_ref(str_ref, new_str_ref);
          cql_string_release(new_str_ref);
        }
        break;
      }
      case CQL_DATA_TYPE_BLOB: {
        cql_blob_ref *blob_ref = va_arg(args, cql_blob_ref *);
        cql_set_blob_ref(blob_ref, cql_result_set_get_blob_col(result_set, row, column));
        cql_blob_ref new_blob_ref = NULL;
        if (*blob_ref && should_decode) {
          new_blob_ref = cql_decode_blob_ref_new(encoder, *blob_ref, encode_context_type, encode_context_field);
          cql_set_blob_ref(blob_ref, new_blob_ref);
          cql_blob_release(new_blob_ref);
        }
        break;
      }
      case CQL_DATA_TYPE_OBJECT: {
        cql_object_ref *obj_ref = va_arg(args, cql_object_ref *);
        cql_set_object_ref(obj_ref, cql_result_set_get_object_col(result_set, row, column));
        break;
      }
    }
  }

  cql_object_release(encoder);

  va_end(args);
}