---
title: "Low-level API"
author: "Michael Koohafkan"
date: 2021-06-09
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Low-level API}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

The `hdfqlr` package provides a high-level API for reading and 
writing HDF files. However, the package also provides access to 
the lower-level API provided by the HDFql R wrapper. 


```r
library(hdfqlr)
hql_load('path/to/hdfql-x.x.x')
```

To access the low-level API, simply `attach` the `hql$wrapper` 
environment to your workspace.


```r
attach(hql$wrapper)
```

```
## The following objects are masked from hql$wrapper (pos = 4):
## 
##     HDFQL_ARRAY, HDFQL_ASCII, HDFQL_ATTRIBUTE, HDFQL_BIG_ENDIAN,
##     HDFQL_BIGINT, HDFQL_BITFIELD, HDFQL_CHAR, HDFQL_CHUNKED,
##     HDFQL_COMPACT, HDFQL_COMPOUND, HDFQL_CONTIGUOUS, hdfql_cursor,
##     hdfql_cursor_, hdfql_cursor_absolute, hdfql_cursor_clear,
##     hdfql_cursor_clone, hdfql_cursor_first, hdfql_cursor_get_bigint,
##     hdfql_cursor_get_char, hdfql_cursor_get_count,
##     hdfql_cursor_get_data_type, hdfql_cursor_get_double,
##     hdfql_cursor_get_float, hdfql_cursor_get_int,
##     hdfql_cursor_get_position, hdfql_cursor_get_size,
##     hdfql_cursor_get_smallint, hdfql_cursor_get_tinyint,
##     hdfql_cursor_get_unsigned_bigint, hdfql_cursor_get_unsigned_int,
##     hdfql_cursor_get_unsigned_smallint,
##     hdfql_cursor_get_unsigned_tinyint, hdfql_cursor_initialize,
##     hdfql_cursor_last, hdfql_cursor_next, hdfql_cursor_previous,
##     hdfql_cursor_relative, hdfql_cursor_use, hdfql_cursor_use_default,
##     HDFQL_DATASET, HDFQL_DIRECTORY, HDFQL_DISABLED, HDFQL_DOUBLE,
##     HDFQL_EARLIEST, HDFQL_EARLY, HDFQL_ENABLED, HDFQL_ENUMERATION,
##     HDFQL_ERROR_AFTER_LAST, HDFQL_ERROR_ALREADY_EXISTS,
##     HDFQL_ERROR_BEFORE_FIRST, HDFQL_ERROR_DANGLING_LINK,
##     HDFQL_ERROR_EMPTY, HDFQL_ERROR_FULL, hdfql_error_get_line,
##     hdfql_error_get_message, hdfql_error_get_position,
##     HDFQL_ERROR_INVALID_FILE, HDFQL_ERROR_INVALID_REGULAR_EXPRESSION,
##     HDFQL_ERROR_NO_ACCESS, HDFQL_ERROR_NO_ADDRESS,
##     HDFQL_ERROR_NOT_ENOUGH_MEMORY, HDFQL_ERROR_NOT_ENOUGH_SPACE,
##     HDFQL_ERROR_NOT_FOUND, HDFQL_ERROR_NOT_OPEN,
##     HDFQL_ERROR_NOT_REGISTERED, HDFQL_ERROR_NOT_SUPPORTED,
##     HDFQL_ERROR_OUTSIDE_LIMIT, HDFQL_ERROR_PARSE,
##     HDFQL_ERROR_UNEXPECTED_DATA_TYPE,
##     HDFQL_ERROR_UNEXPECTED_STORAGE_TYPE, HDFQL_ERROR_UNEXPECTED_TYPE,
##     HDFQL_ERROR_UNKNOWN, hdfql_execute, hdfql_execute_get_status,
##     HDFQL_EXTERNAL_LINK, HDFQL_FILE, HDFQL_FILL_DEFAULT,
##     HDFQL_FILL_UNDEFINED, HDFQL_FILL_USER_DEFINED, HDFQL_FLOAT,
##     hdfql_get_canonical_path, HDFQL_GLOBAL, HDFQL_GROUP,
##     HDFQL_INCREMENTAL, HDFQL_INDEXED, HDFQL_INT, HDFQL_LATE,
##     HDFQL_LATEST, HDFQL_LITTLE_ENDIAN, HDFQL_LOCAL, hdfql_mpi_get_rank,
##     hdfql_mpi_get_size, HDFQL_NO, HDFQL_OPAQUE, HDFQL_REFERENCE,
##     hdfql_shared_library, HDFQL_SMALLINT, HDFQL_SOFT_LINK,
##     hdfql_subcursor_absolute, hdfql_subcursor_first,
##     hdfql_subcursor_get_bigint, hdfql_subcursor_get_char,
##     hdfql_subcursor_get_count, hdfql_subcursor_get_double,
##     hdfql_subcursor_get_float, hdfql_subcursor_get_int,
##     hdfql_subcursor_get_position, hdfql_subcursor_get_size,
##     hdfql_subcursor_get_smallint, hdfql_subcursor_get_tinyint,
##     hdfql_subcursor_get_unsigned_bigint,
##     hdfql_subcursor_get_unsigned_int,
##     hdfql_subcursor_get_unsigned_smallint,
##     hdfql_subcursor_get_unsigned_tinyint, hdfql_subcursor_last,
##     hdfql_subcursor_next, hdfql_subcursor_previous,
##     hdfql_subcursor_relative, HDFQL_SUCCESS, HDFQL_TINYINT,
##     HDFQL_TRACKED, HDFQL_UNDEFINED, HDFQL_UNLIMITED,
##     HDFQL_UNSIGNED_BIGINT, HDFQL_UNSIGNED_INT, HDFQL_UNSIGNED_SMALLINT,
##     HDFQL_UNSIGNED_TINYINT, HDFQL_UNSIGNED_VARBIGINT,
##     HDFQL_UNSIGNED_VARINT, HDFQL_UNSIGNED_VARSMALLINT,
##     HDFQL_UNSIGNED_VARTINYINT, HDFQL_UTF8, HDFQL_VARBIGINT,
##     HDFQL_VARCHAR, HDFQL_VARDOUBLE, HDFQL_VARFLOAT,
##     hdfql_variable_get_count, hdfql_variable_get_data_type,
##     hdfql_variable_get_dimension, hdfql_variable_get_dimension_count,
##     hdfql_variable_get_number, hdfql_variable_get_size,
##     hdfql_variable_register, hdfql_variable_transient_register,
##     hdfql_variable_unregister, hdfql_variable_unregister_all,
##     HDFQL_VARINT, HDFQL_VARSMALLINT, HDFQL_VARTINYINT, HDFQL_VERSION,
##     HDFQL_VERSION_18, HDFQL_YES
```

The HDFql wrapper functions can now be accessed directly. The 
example code from `hdfql-2.1.0/example/HDFqlExample.R`
is included below:


```r
example.h5 = shQuote(tempfile(fileext = ".h5"))
print(paste("HDFql version:", HDFQL_VERSION))
```

```
## [1] "HDFql version: 2.1.0"
```

```r
# create an HDF5 file named "example.h5" and use (i.e. open) it
hdfql_execute(paste("CREATE FILE", example.h5))
```

```
## [1] 0
```

```r
hdfql_execute(paste("USE FILE", example.h5))
```

```
## [1] 0
```

```r
# show (i.e. get) HDF5 file currently in use and populate HDFql default cursor with it
hdfql_execute("SHOW USE FILE")
```

```
## [1] 0
```

```r
# display HDF5 file currently in use
hdfql_cursor_first()
```

```
## [1] 0
```

```r
print(paste("File in use:", hdfql_cursor_get_char()))
```

```
## [1] "File in use: C:\\Users\\michael\\AppData\\Local\\Temp\\Rtmpyos7yO\\file2d6c30ba408e.h5"
```

```r
# create an attribute named "example_attribute" of data type float with an initial value of 12.4
hdfql_execute("CREATE ATTRIBUTE example_attribute AS FLOAT VALUES(12.4)")
```

```
## [1] 0
```

```r
# select (i.e. read) data from attribute "example_attribute" and populate HDFql default cursor with it
hdfql_execute("SELECT FROM example_attribute")
```

```
## [1] 0
```

```r
# display value of attribute "example_attribute"
hdfql_cursor_first()
```

```
## [1] 0
```

```r
print(paste("Attribute value:", hdfql_cursor_get_float()))
```

```
## [1] "Attribute value: 12.3999996185303"
```

```r
# create a dataset named "example_dataset" of data type int of two dimensions (size 3x2)
hdfql_execute("CREATE DATASET example_dataset AS INT(3, 2)")
```

```
## [1] 0
```

```r
# create variable "values" and populate it with certain values
values <- array(dim = c(3, 2))
for (x in 1:2) {
  for (y in 1:3) {
    values[y, x] <- as.integer(x * 3 + y - 3)
  }
}

# register variable "values" for subsequent use (by HDFql)
hdfql_variable_register(values)
```

```
## [1] 0
```

```r
# insert (i.e. write) values from variable "values" into dataset "example_dataset"
hdfql_execute(paste("INSERT INTO example_dataset VALUES FROM MEMORY", hdfql_variable_get_number(values)))
```

```
## [1] 0
```

```r
# unregister variable "values" as it is no longer used/needed (by HDFql)
hdfql_variable_unregister(values)
```

```
## [1] 0
```

```r
# populate variable "values" with zeros (i.e. reset variable)
for (x in 1:2) {
  for (y in 1:3) {
    values[y, x] <- as.integer(0)
  }
}

# register variable "values" for subsequent use (by HDFql)
hdfql_variable_register(values)
```

```
## [1] 0
```

```r
# select (i.e. read) data from dataset "example_dataset" and populate variable "values" with it
hdfql_execute(paste("SELECT FROM example_dataset INTO MEMORY", hdfql_variable_get_number(values)))
```

```
## [1] 0
```

```r
# unregister variable "values" as it is no longer used/needed (by HDFql)
hdfql_variable_unregister(values)
```

```
## [1] 0
```

```r
# display content of variable "values"
print("Dataset value (through variable):")
```

```
## [1] "Dataset value (through variable):"
```

```r
for (x in 1:2) {
  for (y in 1:3) {
    print(values[y, x])
  }
}
```

```
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
```

```r
# another way to select (i.e. read) data from dataset "example_dataset" using HDFql default cursor
hdfql_execute("SELECT FROM example_dataset")
```

```
## [1] 0
```

```r
# display content of HDFql default cursor
print("Dataset value (through cursor):")
```

```
## [1] "Dataset value (through cursor):"
```

```r
while (hdfql_cursor_next() == HDFQL_SUCCESS) {
  print(hdfql_cursor_get_int())
}
```

```
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
```

```r
# create cursor "my_cursor" and use it
my_cursor <- hdfql_cursor()
hdfql_cursor_use(my_cursor)
```

```
## [1] 0
```

```r
# show (i.e. get) size (in bytes) of dataset "example_dataset" and populate cursor "my_cursor" with it
hdfql_execute("SHOW SIZE example_dataset")
```

```
## [1] 0
```

```r
# display content of cursor "my_cursor"
hdfql_cursor_first()
```

```
## [1] 0
```

```r
print(paste("Dataset size (in bytes):", hdfql_cursor_get_bigint()))
```

```
## [1] "Dataset size (in bytes): 24"
```

```r
# close the file
hdfql_execute(paste("CLOSE FILE", example.h5))
```

```
## [1] 0
```


