HDFql Reference Manual v2.6.0

6.5.1INSERT

Syntax

INSERT [DIRECTLY [MASK mask_value] [SIZE data_size]] INTO [DATASET | ATTRIBUTE] [file_name] object_name [[selection]] [, [file_name] object_name [[selection]]]*

[{IN PARALLEL [NO VALUES]} | {[IN PARALLEL] [VALUES {([value] [, [value]]*) | input_redirecting_option}]}]

selection := hyperslab | point | chunk

hyperslab := [start]:[stride]:[count]:[block] [, [start]:[stride]:[count]:[block]]* [{OR | AND | XOR | NOTA | NOTB} [start]:[stride]:[count]:[block] [, [start]:[stride]:[count]:[block]]*]*

point := coord [, coord]* [; coord [, coord]*]*

chunk := chunk_number [, chunk_number]*

Description

Insert (i.e. write) data into an HDF5 dataset or attribute named object_name. Multiple datasets or attributes can be written at once by separating their names with a comma (,). If object_name was not found or could not be written (due to unknown/unexpected reasons), no subsequent objects are written, and an error is raised. In case a dataset and an attribute with identical names (object_name) are stored in the same location (i.e. group) and neither the keyword DATASET nor ATTRIBUTE is specified, the object that will have data written into it is the dataset. To explicitly write data into an object according to its type, the keyword DATASET or ATTRIBUTE must be specified.

In case the keyword DIRECTLY38 is specified, HDFql writes data chunks directly into a dataset, bypassing several internal processing steps of the HDF5 library itself (e.g. data conversion, filter pipeline), which can lead to much faster writing.

By default, the entire object_name is written when performing an insert operation. To write only a slice (i.e. portion) of object_name, hyperslab and point selections can be used39. To enable a (regular) hyperslab selection, the start, stride, count, and block parameters may be specified and separated with a colon (:). For each dimension of object_name, a set of such parameters may be specified, and each set should be separated with a comma (,). Multiple hyperslab selections can be enabled at once (in this case, the hyperslab will be considered irregular). This is achieved by using the following boolean operators:

  • OR – adds the new selection to the existing selection.
  • AND – retains only the overlapping portions of the new selection and the existing selection.
  • XOR – retains only the elements that belong to either the new selection or the existing selection, excluding elements that belong to both selections.
  • NOTA – retains only the elements of the new selection that are not in the existing selection.
  • NOTB – retains only the elements of the existing selection that are not in the new selection.

To enable a point selection, a set of coordinates may be specified. Each coordinate is separated with a comma (,). More than one set of coordinates (i.e. points) may be specified, and each set should be separated with a semicolon (;). Of note, hyperslab and point selections cannot be used simultaneously (i.e. mixed) in an insert operation. Since hyperslab and point selections can be complicated to set up, it is recommended to first read https://support.hdfgroup.org/documentation/hdf5/latest/_h5_s__u_g.html and, eventually, enable the debug mechanism (through the operation SET DEBUG) when working with these, to obtain debug information in case of errors.

In case the keyword IN PARALLEL40 41 is specified, HDFql writes data into a dataset in parallel using all the processes associated with the default MPI communicator (MPI_COMM_WORLD) or with a user-defined MPI communicator (that may have been set through the function hdfql_mpi_use_communicator). Of note, a dataset may only be written in parallel if the HDF5 file was opened in parallel in the first place (please refer to the operation USE FILE for additional information). In case the keyword NO VALUES is specified, no data is actually written by the MPI process in question (which may be useful in certain situations), only forcing it to participate in the operation (as, when working in parallel, it is mandatory that all MPI processes work collectively).

HDFql provides several ways of writing data into a dataset or attribute, namely from a cursor (e.g. “INSERT INTO my_dataset”), using direct values (e.g. “INSERT INTO my_dataset VALUES(0, 2, 4, 6, 8)”), or using an input redirecting option (e.g. “INSERT INTO my_dataset VALUES FROM FILE my_file.txt”).

Parameter(s)

mask_value – optional integer that specifies which filters have been applied to the data chunk. A filter is skipped if the bit corresponding to the position of the filter in the pipeline is turned on. If mask_value is specified, it must be equal to or greater than zero (otherwise an error is raised). If not specified and in case the keyword DIRECTLY is specified, its default value is zero (meaning that all filters have been applied to the data chunk).

data_size – optional integer that specifies the size (in bytes) of the data to insert (i.e. write) into the HDF5 dataset. If data_size is specified, it must be greater than zero (otherwise an error is raised). If not specified and in case the keyword DIRECTLY is specified, HDFql will automatically calculate the size by multiplying all storage dimensions of the dataset by its data type size.

file_name – optional string that specifies the name of the HDF5 file storing the HDF5 dataset or attribute into which data is to be inserted (i.e. written). If file_name is specified, the file is opened on the fly, the data is inserted in the dataset or attribute, and the file is subsequently closed. If not specified, the file currently in use is used instead.

object_name – mandatory string that specifies the name of the HDF5 dataset or attribute to insert (i.e. write) data into.

start – optional integer that specifies the starting location of the hyperslab selection. If not specified, its default value is zero (i.e. the first position of the dimension in question). If negative, its value will be the last position of the dimension in question minus the absolute value of start.

stride – optional integer that specifies the number of elements to separate each block to be selected. If not specified, its default value is equal to the value of block.

count – optional integer that specifies the number of blocks to select along each dimension. If not specified, its default value is one.

block – optional integer that specifies the size of the block selected (i.e. number of elements) from the HDF5 dataset. If not specified, its default value is the size of the dimension in question minus the absolute value of start, divided by the value of count.

coord – optional integer that specifies the point of interest (i.e. the point at which to insert data) for the point selection. If negative, its value will be the last position of the dimension in question minus the absolute value of coord.

chunk_number – optional integer that specifies the number of the chunk to insert (i.e. write) data into. If chunk_number is specified, it must either be between 0 and the storage dimension in question - 1 (otherwise an error is raised) or negative (in this case, its value will be the last position of the storage dimension in question minus the absolute value of chunk_number). If not specified and in case the keyword DIRECTLY is specified, its default value is zero (i.e. first chunk of the storage dimension in question).

value – optional integer, float, or string to insert (i.e. write) into the HDF5 dataset or attribute. In case value is not specified, the element in question will be zeroed or emptied depending on whether the dataset/attribute is a number or a string, respectively.

input_redirecting_option – optional option that specifies the cursor in use, a (text, binary, or Excel) file, or memory (i.e. user-defined variable) to read data from in order to write it into an HDF5 dataset or attribute (please refer to the subsection FROM for additional information).

Return

Nothing

Example(s)

# create an HDF5 dataset named "my_dataset0" of data type short of one dimension (size 3) 
CREATE DATASET my_dataset0 AS SMALLINT(3)

# create an HDF5 dataset named "my_dataset1" of data type int of one dimension (size 5) 
CREATE DATASET my_dataset1 AS INT(5)

# insert (i.e. write) values 65, 66, and 67 into dataset "my_dataset0" 
INSERT INTO my_dataset0 VALUES(65, 66, 67)

# select (i.e. read) data from dataset "my_dataset0" and populate cursor in use with it (should populate with 65, 66, 67)
SELECT FROM my_dataset0

# insert (i.e. write) values into dataset "my_dataset1" from cursor in use (should write 65, 66, 67, 0, 0)
INSERT INTO my_dataset1

# create an HDF5 attribute named "my_attribute0" of data type short 
CREATE ATTRIBUTE my_attribute0 AS SMALLINT 

# insert (i.e. write) value 95 into attribute "my_attribute0" 
INSERT INTO my_attribute0 VALUES(95)

# create an HDF5 attribute named "my_attribute1" of data type unsigned short of one dimension (size 2)
CREATE ATTRIBUTE my_attribute1 AS UNSIGNED SMALLINT(2)

# insert (i.e. write) values 95 and 97 into attribute "my_attribute1" 
INSERT INTO my_attribute1 VALUES(95, 97)
# create an HDF5 dataset named "my_dataset2" of data type float of one dimension (size 512) 
CREATE DATASET my_dataset2 AS FLOAT(512)

# insert (i.e. write) values into dataset "my_dataset2" from a text file named "my_file0.txt" that has values separated with "," (i.e. default separator)
INSERT INTO my_dataset2 VALUES FROM FILE my_file0.txt

# insert (i.e. write) values into dataset "my_dataset2" from a text file named "my_file1.txt" that has a DOS-based end-of-line (EOL) terminator and values separated with "**"
INSERT INTO my_dataset2 VALUES FROM DOS TEXT FILE my_file1.txt SEPARATOR **

# insert (i.e. write) values into dataset "my_dataset2" from a binary file named "my_file.bin"
INSERT INTO my_dataset2 VALUES FROM BINARY FILE my_file.bin
# create an HDF5 dataset named "my_dataset3" of data type short of one dimension (size 5) 
CREATE DATASET my_dataset3 AS SMALLINT(5)

# insert (i.e. write) value 9 into position #3 of dataset "my_dataset3" using a hyperslab selection
INSERT INTO my_dataset3[3:::] VALUES(9)

# select (i.e. read) data from dataset "my_dataset3" and populate cursor in use with it (should populate with 0, 0, 0, 9, 0)
SELECT FROM my_dataset3

# insert (i.e. write) value 9 into position #4 of dataset "my_dataset3" using a hyperslab selection
INSERT INTO my_dataset3[-1:::] VALUES(7)

# select (i.e. read) data from dataset "my_dataset3" and populate cursor in use with it (should populate with 0, 0, 0, 9, 7)
SELECT FROM my_dataset3

# insert (i.e. write) values 5 and 3 into positions #1 and #2 of dataset "my_dataset3" using a hyperslab selection
INSERT INTO my_dataset3[1:::2] VALUES(5, 3)

# select (i.e. read) data from dataset "my_dataset3" and populate cursor in use with it (should populate with 0, 5, 3, 9, 7)
SELECT FROM my_dataset3

# create an HDF5 dataset named "my_dataset4" of data type int of two dimensions (size 3x3) 
CREATE DATASET my_dataset4 AS INT(3, 3)

# insert (i.e. write) value 8 into position #2 of the first dimension and position #1 of the second dimension of dataset "my_dataset4" using a hyperslab selection
INSERT INTO my_dataset4[2:::, 1:::] VALUES(8)

# select (i.e. read) data from dataset "my_dataset4" and populate cursor in use with it (should populate with 0, 0, 0, 0, 0, 0, 0, 8, 0)
SELECT FROM my_dataset4

# insert (i.e. write) value 4 into position #2 of the first dimension and position #0 of the second dimension, and value 6 into position #2 of the first dimension and position #2 of the second dimension of dataset "my_dataset4" using a hyperslab selection
INSERT INTO my_dataset4[2:::, 0:2:2:1] VALUES(4, 6)

# select (i.e. read) data from dataset "my_dataset4" and populate cursor in use with it (should populate with 0, 0, 0, 0, 0, 0, 4, 8, 6)
SELECT FROM my_dataset4

# create an HDF5 dataset named "my_dataset5" of data type short of one dimension (size 10) 
CREATE DATASET my_dataset5 AS SMALLINT(10)

# insert (i.e. write) values 90, 91, and 92 into positions #2, #3, and #4, respectively, value 93 into position #5, and values 94 and 95 into positions #7 and #8, respectively, of dataset "my_dataset5" using an irregular hyperslab selection
INSERT INTO my_dataset5[2::3:1 OR 4::2:1 OR 7::2:1] VALUES(90, 91, 92, 93, 94, 95)

# select (i.e. read) data from dataset "my_dataset5" and populate cursor in use with it (should populate with 0, 0, 90, 91, 92, 93, 0, 94, 95, 0)
SELECT FROM my_dataset5

# create an HDF5 dataset named "my_dataset6" of data type long long of one dimension (size 15)
CREATE DATASET my_dataset6 AS BIGINT(15)

# insert (i.e. write) values 75 and 77 into positions #5 and #6, respectively, of dataset "my_dataset6" using an irregular hyperslab selection
INSERT INTO my_dataset6[3::4:1 AND 5::3:1] VALUES(75, 77, 79, 81, 83, 85, 87)

# select (i.e. read) data from dataset "my_dataset6" and populate cursor in use with it (should populate with 0, 0, 0, 0, 0, 75, 77, 0, 0, 0, 0, 0, 0, 0, 0)
SELECT FROM my_dataset6

# create an HDF5 dataset named "my_dataset7" of data type float of one dimension (size 8) 
CREATE DATASET my_dataset7 AS FLOAT(8)

# insert (i.e. write) values 7.5, 7.7, and 7.9 into positions #2, #4, and #7, respectively, of dataset "my_dataset7" using a point selection
INSERT INTO my_dataset7[2; 4; 7] VALUES(7.5, 7.7, 7.9)

# select (i.e. read) data from dataset "my_dataset7" and populate cursor in use with it (should populate with 0, 0, 7.5, 0, 7.7, 0, 0, 7.9)
SELECT FROM my_dataset7

# create an HDF5 dataset named "my_dataset8" of data type double of two dimensions (size 4x3)
CREATE DATASET my_dataset8 AS DOUBLE(4, 3)

# insert (i.e. write) value 15.2 into position #1 of the first dimension and position #2 of the second dimension, and value 18.5 into position #3 of the first dimension and position #0 of the second dimension of dataset "my_dataset8" using a point selection
INSERT INTO my_dataset8[1, 2; 3, 0] VALUES(15.2, 18.5)

# select (i.e. read) data from dataset "my_dataset8" and populate cursor in use with it (should populate with 0, 0, 0, 0, 0, 15.2, 0, 0, 0, 18.5, 0, 0)
SELECT FROM my_dataset8
# use (i.e. open) an HDF5 file named "my_file.h5" 
USE FILE my_file.h5

# create an HDF5 dataset named "my_dataset9" of data type double in the HDF5 file currently in use (i.e. file "my_file.h5")
CREATE DATASET my_dataset9 AS DOUBLE

# insert (i.e. write) value 6.5 into dataset "my_dataset9" 
INSERT INTO my_dataset9 VALUES(6.5)

# select (i.e. read) data from dataset "my_dataset9" and populate cursor in use with it (should populate with 6.5)
SELECT FROM my_dataset9

# close HDF5 file currently in use (i.e. file "my_file.h5") 
CLOSE FILE 

# insert (i.e. write) value 3.2 into dataset "my_dataset9" in file "my_file.h5" 
INSERT INTO my_file.h5 my_dataset9 VALUES(3.2)

# select (i.e. read) data from dataset "my_dataset9" in file "my_file.h5" and populate cursor in use with it (should populate with 3.2)
SELECT FROM my_file.h5 my_dataset9
# create an HDF5 dataset named "my_dataset10" of data type enumeration composed of three members named "helium" (with value 0), "oxygen" (with value 1), and "argon" (with value 2)
CREATE DATASET my_dataset10 AS ENUMERATION(helium, oxygen, argon)

# insert (i.e. write) value 1 (i.e. "oxygen") into dataset "my_dataset10" 
INSERT INTO my_dataset10 VALUES(oxygen)

# select (i.e. read) data from dataset "my_dataset10" and populate cursor in use with it (should populate with 1 (i.e. "oxygen"))
SELECT FROM my_dataset10

# create an HDF5 attribute named "my_attribute2" of data type enumeration of one dimension (size 4) composed of three members named "red" (with value 0), "green" (with value 50), and "blue" (with value 51)
CREATE ATTRIBUTE my_attribute2 AS ENUMERATION(red, green AS 50, blue)(4)

# insert (i.e. write) values 51 (i.e. "blue"), "red" (i.e. 0), "green" (i.e. 50), and "blue" (i.e. 51) into attribute "my_attribute2"
INSERT INTO my_attribute2 VALUES(51, red, green, blue)

# select (i.e. read) data from attribute "my_attribute2" and populate cursor in use with it (should populate with 51 (i.e. "blue"), 0 (i.e. "red"), 50 (i.e. "green"), 51 (i.e. "blue"))
SELECT FROM my_attribute2
# create a chunked (size 2) HDF5 dataset named "my_dataset11" of data type int of one dimension (size 6)
CREATE CHUNKED(2) DATASET my_dataset11 AS INT(6)

# insert (i.e. write) values 60 and 61 directly into chunk #0 of dataset "my_dataset11" using a (filter) mask equal to 8
INSERT DIRECTLY MASK 8 INTO my_dataset11 VALUES(60, 61)

# insert (i.e. write) values 62 and 63 directly into chunk #1 of dataset "my_dataset11" using a (filter) mask equal to 255 (i.e. 0xFF)
INSERT DIRECTLY MASK 0xFF INTO my_dataset11[1] VALUES(62, 63)

# insert (i.e. write) values 64 and 65 directly into chunk #2 of dataset "my_dataset11" using a (filter) mask equal to 0 (i.e. default value)
INSERT DIRECTLY INTO my_dataset11[2] VALUES(64, 65)

# select (i.e. read) data from dataset "my_dataset11" and populate cursor in use with it (should populate with 60, 61, 62, 63, 64, 65)
SELECT FROM my_dataset11
// declare variables 
char script[1024];
double data[3];

// create an HDF5 dataset named "my_dataset12" of data type double of one dimension (size 3) 
hdfql_execute("CREATE DATASET my_dataset12 AS DOUBLE(3)");

// populate variable "data" with certain values 
data[0] = 21.1; 
data[1] = 18.8;
data[2] = 75.6;

// register variable "data" for subsequent use (by HDFql) 
hdfql_variable_register(data);

// prepare script to insert (i.e. write) values from variable "data" into dataset "my_dataset12"
sprintf(script, "INSERT INTO my_dataset12 VALUES FROM MEMORY %d", hdfql_variable_get_number(data));

// execute script 
hdfql_execute(script);

// unregister variable "data" as it is no longer used/needed (by HDFql) 
hdfql_variable_unregister(data); 
// declare variables 
char script[1024];
HDFQL_VARIABLE_LENGTH data[3];

// create an HDF5 dataset named "my_dataset13" of data type variable-length double of one dimension (size 3)
hdfql_execute("CREATE DATASET my_dataset13 AS VARDOUBLE(3)");

// allocate memory in variable "data" 
data[0].address = malloc(2 * sizeof(double)); 
data[0].count = 2;
data[1].address = malloc(3 * sizeof(double)); 
data[1].count = 3;
data[2].address = malloc(1 * sizeof(double)); 
data[2].count = 1;

// populate variable "data" with certain values 
*((double *) data[0].address + 0) = 3.2; 
*((double *) data[0].address + 1) = 1.3; 
*((double *) data[1].address + 0) = 0; 
*((double *) data[1].address + 1) = 0.2; 
*((double *) data[1].address + 2) = 9.1; 
*((double *) data[2].address + 0) = 6.5; 

// register variable "data" for subsequent use (by HDFql) 
hdfql_variable_register(data);

// prepare script to insert (i.e. write) values from variable "data" into dataset "my_dataset13"
sprintf(script, "INSERT INTO my_dataset13 VALUES FROM MEMORY %d", hdfql_variable_get_number(data));

// execute script 
hdfql_execute(script);

// unregister variable "data" as it is no longer used/needed (by HDFql) 
hdfql_variable_unregister(data); 

// select (i.e. read) data from dataset "my_dataset13" and populate cursor in use with it 
hdfql_execute("SELECT FROM my_dataset13");

// display content of cursor in use (should be 3.2, 1.3, 0, 0.2, 9.1, 6.5) 
while(hdfql_cursor_next(NULL) == HDFQL_SUCCESS)
{
    while(hdfql_subcursor_next(NULL) == HDFQL_SUCCESS)
    {
       printf("%f\n", *hdfql_subcursor_get_double(NULL));
    }
}

// release memory allocated in variable "data" 
free(data[0].address);
free(data[1].address);
free(data[2].address);
// declare variables 
char script[1024];
char *data[3];

// create an HDF5 dataset named "my_dataset14" of data type variable-length char of one dimension (size 3)
hdfql_execute("CREATE DATASET my_dataset14 AS VARCHAR(3)");

// allocate memory in variable "data" 
data[0] = malloc(13 * sizeof(char)); 
data[1] = malloc(5 * sizeof(char)); 
data[2] = malloc(7 * sizeof(char)); 

// populate variable "data" with certain values 
strcpy(data[0], "Hierarchical"); 
strcpy(data[1], "Data"); 
strcpy(data[2], "Format"); 

// register variable "data" for subsequent use (by HDFql) 
hdfql_variable_register(data);

// prepare script to insert (i.e. write) values from variable "data" into dataset "my_dataset14"
sprintf(script, "INSERT INTO my_dataset14 VALUES FROM MEMORY %d", hdfql_variable_get_number(data));

// execute script 
hdfql_execute(script);

// unregister variable "data" as it is no longer used/needed (by HDFql) 
hdfql_variable_unregister(data); 

// select (i.e. read) data from dataset "my_dataset14" and populate cursor in use with it 
hdfql_execute("SELECT FROM my_dataset14");

// display content of cursor in use (should be "Hierarchical", "Data", "Format") 
while(hdfql_cursor_next(NULL) == HDFQL_SUCCESS)
{
    printf("%s\n", hdfql_cursor_get_char(NULL));
}

// release memory allocated in variable "data" 
free(data[0]);
free(data[1]);
free(data[2]);
// declare structure 
struct coordinate
{
   double latitude; 
   double longitude; 
};

// declare variables 
char script[1024];
struct coordinate location;

// create an HDF5 attribute named "my_attribute3" of data type compound composed of two members named "latitude" (of data type double) and "longitude" (of data type double)
hdfql_execute("CREATE ATTRIBUTE my_attribute3 AS COMPOUND(latitude AS DOUBLE, longitude AS DOUBLE)");

// populate variable "location" with certain values 
location.latitude = 15.9803486587; 
location.longitude = 48.6352028395;

// prepare script to insert (i.e. write) values from variable "location" into attribute "my_attribute3"
sprintf(script, "INSERT INTO my_attribute3 VALUES FROM MEMORY %d", hdfql_variable_transient_register(&location));

// execute script 
hdfql_execute(script);
// declare structure 
struct data
{ 
   char description[7]; 
   int index; 
};

// declare variables 
char script[1024];
struct data cities[3]; 
int number;

// create an HDF5 dataset named "my_dataset15" of data type compound of one dimension (size 3) composed of two members named "description" (of data type char) and "index" (of data type int)
hdfql_execute("CREATE DATASET my_dataset15 AS COMPOUND(description AS CHAR(7), index AS INT)(3)");

// populate variable "cities" with certain values 
memcpy(cities[0].description, "Toronto", 7);
cities[0].index = 10; 
memcpy(cities[1].description, "Nairobi", 7);
cities[1].index = 12; 
memcpy(cities[2].description, "Caracas", 7);
cities[2].index = 11; 

// register variable "cities" for subsequent use (by HDFql) 
number = hdfql_variable_register(cities);

// prepare script to insert (i.e. write) values from variable "cities" into dataset "my_dataset15"
sprintf(script, "INSERT INTO my_dataset15 VALUES FROM MEMORY %d SIZE %d OFFSET(%d, %d)", number, sizeof(struct data), offsetof(struct data, description), offsetof(struct data, index));

// execute script 
hdfql_execute(script); 

// unregister variable "cities" as it is no longer used/needed (by HDFql) 
hdfql_variable_unregister(cities);
// assume that the following program is launched in parallel using four MPI processes (e.g. "mpiexec -n 4 ./my_program")

// declare variables 
char script[1024]; 
int rank;

// create an HDF5 file named "my_file.h5" in parallel 
hdfql_execute("CREATE FILE my_file.h5 IN PARALLEL");

// use (i.e. open) HDF5 file "my_file.h5" in parallel 
hdfql_execute("USE FILE my_file.h5 IN PARALLEL");

// create an HDF5 dataset named "my_dataset16" of data type int of one dimension (size 4) 
hdfql_execute("CREATE DATASET my_dataset16 AS INT(4)");

// get rank of the MPI process (should be between 0 and 3) 
rank = hdfql_mpi_get_rank();

// prepare script to insert (i.e. write) values 0, 10, 20, and 30 in parallel into positions #0 (by MPI process rank 0), #1 (by MPI process rank 1), #2 (by MPI process rank 2) and #3 (by MPI process rank 3), respectively, of dataset "my_dataset16" using a point selection
sprintf(script, "INSERT INTO my_dataset16[%d] IN PARALLEL VALUES(%d)", rank, rank * 10);

// execute script 
hdfql_execute(script); 

Notes

  1. Only available for HDF5 datasets as, by design, direct insert (i.e. write) for HDF5 attributes is not supported by the HDF5 library. Moreover, the library does not support writing data directly into a dataset of data type variable-length or compound with a member of data type variable-length. ↩
  2. Only available for HDF5 datasets as, by design, neither hyperslab nor point selections for HDF5 attributes are supported by the HDF5 library. ↩
  3. This option is not allowed on Windows as HDFql does not currently support the parallel HDF5 (PHDF5) library on this platform. ↩
  4. Only available for HDF5 datasets as, by design, inserting (i.e. writing) data into HDF5 attributes is not supported in parallel. Moreover, the library does not support writing data into a dataset of data type variable-length or compound with a member of data type variable-length in parallel. ↩