Var-length Attributes

Writing variable-length attribute values to an array involves passing two buffers to TileDB, one for the variable-length cell values and one for the starting offset of each value in the first buffer. We illustrate this in the code block below with a sparse write, but it is also applicable to dense writes.

C
C++
Python
R
Java
Go
C
#include <tiledb/tiledb.h>
// Create TileDB context
tiledb_ctx_t* ctx;
tiledb_ctx_alloc(NULL, &ctx);
// Open array for writing
tiledb_array_t* array;
tiledb_array_alloc(ctx, array_name, &array);
tiledb_array_open(ctx, array, TILEDB_WRITE);
// Prepare some data for the array
long long coords[] = {1, 2, 2, 1, 3, 3, 4, 4};
unsigned long long coords_size = sizeof(coords);
int data[] = {1, 1, 2, 3, 3, 3, 4};
unsigned long long data_size = sizeof(data);
unsigned long long data_off[] = {0, 8, 12, 24};
unsigned long long data_off_size = sizeof(data_off);
// Create the query
tiledb_query_t* query;
tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query);
tiledb_query_set_layout(ctx, query, TILEDB_UNORDERED);
tiledb_query_set_buffer(ctx, query, TILEDB_COORDS, coords, &coords_size);
tiledb_query_set_buffer_var(ctx, query, "a", data_off, data_off_size, data, &data_size);
// Submit query
tiledb_query_submit(ctx, query);
// Close array
tiledb_array_close(ctx, array);
// Clean up
tiledb_array_free(&array);
tiledb_query_free(&query);
tiledb_ctx_free(&ctx);
C++
#include <tiledb/tiledb>
// Creatre context
Context ctx;
// Prepare some data for the array
std::vector<int64_t> coords = {1, 2, 2, 1, 3, 3, 4, 4};
std::vector<int32_t> data = {1, 1, 2, 3, 3, 3, 4};
std::vector<uint64_t> data_off = {0, 8, 12, 24};
// Open array for writing
Array array(ctx, array_name, TILEDB_WRITE);
// Create the query
Query query(ctx, array);
query.set_layout(TILEDB_UNORDERED)
.set_coordinates(coords)
.set_buffer("a", data_off, data);
// Submit query
query.submit();
// Close the array
array.close();
Python
import tiledb
import numpy as np
# note: the Attribute must be created with `var=True`
# att = tiledb.Attr(dtype=dtype, var=True, ctx=ctx)
c1 = np.array([1,2,3,4])
c2 = np.array([2,1,3,2])
data = np.array([
np.array([1,1], dtype=np.int32),
np.array([2], dtype=np.int32),
np.array([3,3,3], dtype=np.int32),
np.array([4], dtype=np.int32)
], dtype='O')
with tiledb.SparseArray(array_name, 'w') as A:
A[c1, c2] = data
R
## Define array
## The array will be 4x4 with dimensions "rows" and "cols",
## with domain [1,4].
dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))
attr <- tiledb_attr("a1", type = "CHAR")
## set to variable length
tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)
## now set the schema
ctx <- tiledb_ctx()
schptr <- tiledb:::libtiledb_array_schema_create(ctx@ptr, "DENSE")
tiledb:::libtiledb_array_schema_set_domain(schptr, dom@ptr)
tiledb:::libtiledb_array_schema_set_cell_order(schptr, "ROW_MAJOR")
tiledb:::libtiledb_array_schema_set_tile_order(schptr, "ROW_MAJOR")
tiledb:::libtiledb_array_schema_add_attribute(schptr, attr@ptr)
## Create the (empty) array on disk.
tiledb:::libtiledb_array_create(uridensevar, schptr)
data <- "abbcccddeeefghhhijjjkklmnoop";
offsets <- c(0L, 1L, 3L, 6L, 8L, 11L, 12L, 13L, 16L, 17L, 20L, 22L,
23L, 24L, 25L, 27L)
ctx <- tiledb_ctx()
arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "WRITE")
qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
bufptr <- tiledb:::libtiledb_query_buffer_var_char_create(offsets, data)
qryptr <- tiledb:::libtiledb_query_set_buffer_var_char(qryptr, "a1", bufptr)
qryptr <- tiledb:::libtiledb_query_submit(qryptr)
tiledb:::libtiledb_array_close(arrptr)
#TODO Higher-level R support
Java
// Create context, array and query
try(Context ctx = new Context(),
Array array = new Array(ctx, array_name, TILEDB_WRITE),
Query query = new Query(ctx, array);) {
// Prepare some data for the array
NativeArray coords = new NativeArray(ctx, new long[] {1l, 2l, 2l, 1l, 3l, 3l, 4l, 4l}, Long.class);
NativeArray data_off =
new NativeArray(ctx, new long[] {0l, 8l, 12l, 24l}, Long.class);
NativeArray data = new NativeArray(ctx, new int[] {1, 1, 2, 3, 3, 3, 4}, Integer.class);
// Create the query
query.setLayout(TILEDB_ROW_MAJOR)
.setCoords(coords)
.setBuffer("a", data_off, data);
// Submit query
query.submit();
}
Go
import "github.com/TileDB-Inc/TileDB-Go"
// Create context
ctx, _ := tiledb.NewContext(nil)
// Prepare some data for the array
coords := []int64{1, 2, 2, 1, 3, 3, 4, 4}
data := []int32{1, 1, 2, 3, 3, 3, 4}
data_off := []uint64{0, 8, 12, 24}
// Open array for writing
array, _ := tiledb.NewArray(ctx, array_name)
array.Open(tiledb.TILEDB_WRITE)
// Create the query
query, _ := tiledb.NewQuery(ctx, array)
query.SetLayout(tiledb.TILEDB_ROW_MAJOR)
query.SetCoordinates(coords)
query.SetBufferVar("a", data_off, data)
// Submit query
query.Submit();
// Close the array
array.Close();

The code snippet above produces the following sparse fragment.