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);
}