tiledb_ctx_alloc(NULL, &ctx);
// Open a 2D array for reading
tiledb_array_alloc(ctx, "<array-uri>", &array);
tiledb_array_open(ctx, array, TILEDB_READ);
// Slice only rows 1, 2 and cols 2, 3, 4
int subarray[] = {1, 2, 2, 4};
// Prepare the vectors that will hold the results
uint64_t d1_size = sizeof(d1);
uint64_t d2_size = sizeof(d2);
uint64_t a_size = sizeof(a);
uint64_t a_validity_size = sizeof(a_validity);
tiledb_query_alloc(ctx, array, TILEDB_READ, &query);
tiledb_query_set_subarray(ctx, query, subarray);
tiledb_query_set_layout(ctx, query, TILEDB_ROW_MAJOR);
tiledb_query_set_buffer(ctx, query, "d1", d1, &d1_size);
tiledb_query_set_buffer(ctx, query, "d2", d2, &d2_size);
tiledb_query_set_buffer_nullable(
ctx, query, "a", a, &a_size, a_validity, &a_validity_size);
// NOTE: although not recommended (for performance reasons),
// you can get the coordinates even when slicing dense arrays.
// NOTE: The layout could have also been TILEDB_COL_MAJOR or
tiledb_query_submit(ctx, query);
tiledb_array_close(ctx, array);
// NOTE: a_size, a_validity_size, d1_size and d2_size now reflect
// the result size, i.e., TileDB changes those values so that you
// know how many results were retrieved (in bytes)
tiledb_array_free(&array);
tiledb_query_free(&query);