Skip to content

Commit 841d447

Browse files
jp-darkmojaveazure
andauthored
Add Profile API to TileDB-R (#856)
* (WIP) Add internal RCpp functions for Profile * Fix optional string conversion and export typo * Add Profile R code * Clean-up return types Co-authored-by: Paul Hoffman <[email protected]> * Update Profile Roxygen2 and fix typo * Fix typo in Rcpp::export * Add basic profile test * Add test for using profile in config * Fix test * Fix test for windows paths * Update pkgdown index * Properly normalize paths in tests Co-authored-by: Paul Hoffman <[email protected]> * Normalize expected dir in test as well * Fix update to pkgdown yaml Co-authored-by: Paul Hoffman <[email protected]> * Update roxygen docs * Fix pkgdown.yml * Add Profile S4 methods to pkgdown index * Update version and news --------- Co-authored-by: Paul Hoffman <[email protected]>
1 parent 0cb7689 commit 841d447

21 files changed

+671
-1
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: tiledb
22
Type: Package
3-
Version: 0.33.1
3+
Version: 0.33.1.1
44
Title: Modern Database Engine for Complex Data Based on Multi-Dimensional Arrays
55
Authors@R: c(
66
person("TileDB, Inc.", role = c("aut", "cph")),

NAMESPACE

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,14 @@ export(tiledb_object_mv)
240240
export(tiledb_object_rm)
241241
export(tiledb_object_type)
242242
export(tiledb_object_walk)
243+
export(tiledb_profile)
244+
export(tiledb_profile_dir)
245+
export(tiledb_profile_get_param)
246+
export(tiledb_profile_load)
247+
export(tiledb_profile_name)
248+
export(tiledb_profile_remove)
249+
export(tiledb_profile_save)
250+
export(tiledb_profile_set_param)
243251
export(tiledb_put_metadata)
244252
export(tiledb_query)
245253
export(tiledb_query_add_range)
@@ -342,6 +350,7 @@ exportClasses(tiledb_filter_list)
342350
exportClasses(tiledb_fragment_info)
343351
exportClasses(tiledb_group)
344352
exportClasses(tiledb_ndrectangle)
353+
exportClasses(tiledb_profile)
345354
exportClasses(tiledb_query)
346355
exportClasses(tiledb_query_condition)
347356
exportClasses(tiledb_subarray)

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# tiledb (development version)
22

3+
## Improvements
4+
5+
* Add support for creating, loading, saving, and removing Profiles ([#856](https://github.com/TileDB-Inc/TileDB-R/pull/856))
6+
37
# tiledb 0.33.1
48

59
* This release of the R package builds against [TileDB 2.29.1](https://github.com/TileDB-Inc/TileDB/releases/tag/2.29.1), and has also been tested against earlier releases as well as the development version

R/Profile.R

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#
2+
# Copyright (c) TileDB Inc. under the MIT License
3+
#
4+
5+
#' An S4 class for a TileDB Profile object
6+
#'
7+
#' @slot ptr An external pointer to the underlying implementation
8+
#' @exportClass tiledb_profile
9+
setClass("tiledb_profile",
10+
slots = list(ptr = "externalptr")
11+
)
12+
13+
#' Raw display of a profile object
14+
#'
15+
#' This method uses the display method provided by the underlying library.
16+
#'
17+
#' @param object A profile object
18+
#' @export
19+
setMethod(
20+
"raw_dump",
21+
signature(object = "tiledb_profile"),
22+
definition = function(object) libtiledb_profile_dump(object@ptr)
23+
)
24+
25+
#' Create a 'tiledb_profile' object
26+
#'
27+
#' @param name (optional) Name for the profile
28+
#' @param dir (optional) Directory to create the profile in
29+
#' @return A new 'tiledb_profile' object
30+
#' @export
31+
tiledb_profile <- function(name = NULL, dir = NULL) {
32+
stopifnot(`The 'name' for the profile must be null or a character type` = is.null(name) || is.character(name))
33+
stopifnot(`The 'dir' for the profile must be null or a character type` = is.null(name) || is.character(name))
34+
ptr <- libtiledb_profile_new(name, dir)
35+
profile <- new("tiledb_profile", ptr = ptr)
36+
return(profile)
37+
}
38+
39+
#' Load a saved 'tiledb_profile' object
40+
#'
41+
#' @param name (optional) Name of the profile to load
42+
#' @param dir (optional) Directory where the profile to load is saved
43+
#' @return The loaded 'tiledb_profile' object
44+
#' @export
45+
tiledb_profile_load <- function(name = NULL, dir = NULL) {
46+
stopifnot(`The 'name' for the profile must be null or a character type` = is.null(name) || is.character(name))
47+
stopifnot(`The 'dir' for the profile must be null or a character type` = is.null(name) || is.character(name))
48+
ptr <- libtiledb_profile_load(name, dir)
49+
profile <- new("tiledb_profile", ptr = ptr)
50+
return(profile)
51+
}
52+
53+
#' Remove a saved 'tiledb_profile'
54+
#'
55+
#' @param name (optional) Name of the profile to remove
56+
#' @param dir (optional) Directory where the profile to remove is saved
57+
#' @export
58+
tiledb_profile_remove <- function(name = NULL, dir = NULL) {
59+
stopifnot(`The 'name' for the profile must be null or a character type` = is.null(name) || is.character(name))
60+
stopifnot(`The 'dir' for the profile must be null or a character type` = is.null(name) || is.character(name))
61+
libtiledb_profile_remove(name, dir)
62+
return(invisible(NULL))
63+
}
64+
65+
#' Get the name of a 'tiledb_profile' object
66+
#'
67+
#' @param profile A TileDB profile object
68+
#' @return The name of the 'tiledb_profile' object
69+
#' @export
70+
tiledb_profile_name <- function(profile) {
71+
stopifnot(`The 'profile' argument must be a tiledb_profile object` = is(profile, "tiledb_profile"))
72+
name <- libtiledb_profile_name(profile@ptr)
73+
return(name)
74+
}
75+
76+
#' Get the directory of a 'tiledb_profile' object
77+
#'
78+
#' @param profile A TileDB profile object
79+
#' @return The directory of the 'tiledb_profile' object
80+
#' @export
81+
tiledb_profile_dir <- function(profile) {
82+
stopifnot(`The 'profile' argument must be a tiledb_profile object` = is(profile, "tiledb_profile"))
83+
dir <- libtiledb_profile_dir(profile@ptr)
84+
return(dir)
85+
}
86+
87+
#' Set a parameter on the 'tiledb_profile' object
88+
#'
89+
#' @param profile A TileDB profile object
90+
#' @param param The key for the new parameter
91+
#' @param value The value for the new parameter
92+
#' @export
93+
tiledb_profile_set_param <- function(profile, param, value) {
94+
stopifnot(`The 'profile' argument must be a tiledb_profile object` = is(profile, "tiledb_profile"))
95+
stopifnot(`The 'param' arugment must have character type` = is.character(param))
96+
stopifnot(`The 'value' arugment must have character type` = is.character(value))
97+
libtiledb_profile_set_param(profile@ptr, param, value)
98+
return(invisible(NULL))
99+
}
100+
101+
#' Get the value of a parameter set on the 'tiledb_profile' object
102+
#'
103+
#' @param profile A TileDB profile object
104+
#' @param param The key for the parameter to fetch
105+
#' @return The value of the requested parameter or NULL if no such parameter exists
106+
#' @export
107+
tiledb_profile_get_param <- function(profile, param) {
108+
stopifnot(`The 'profile' argument must be a tiledb_profile object` = is(profile, "tiledb_profile"))
109+
stopifnot(`The 'param' arugment must have character type` = is.character(param))
110+
value <- libtiledb_profile_get_param(profile@ptr, param)
111+
return(value)
112+
}
113+
114+
#' Save the 'tiledb_profile' object
115+
#'
116+
#' This will save the 'tiledb_profile' with the name and directory set at creation.
117+
#'
118+
#' @param profile The 'tiledb_profile' object to save
119+
#' @export
120+
tiledb_profile_save <- function(profile) {
121+
stopifnot(`The 'profile' argument must be a tiledb_profile object` = is(profile, "tiledb_profile"))
122+
libtiledb_profile_save(profile@ptr)
123+
return(invisible(NULL))
124+
}

R/RcppExports.R

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,42 @@ libtiledb_current_domain_is_empty <- function(cd) {
12331233
.Call(`_tiledb_libtiledb_current_domain_is_empty`, cd)
12341234
}
12351235

1236+
libtiledb_profile_new <- function(name = NULL, dir = NULL) {
1237+
.Call(`_tiledb_libtiledb_profile_new`, name, dir)
1238+
}
1239+
1240+
libtiledb_profile_load <- function(name = NULL, dir = NULL) {
1241+
.Call(`_tiledb_libtiledb_profile_load`, name, dir)
1242+
}
1243+
1244+
libtiledb_profile_remove <- function(name = NULL, dir = NULL) {
1245+
invisible(.Call(`_tiledb_libtiledb_profile_remove`, name, dir))
1246+
}
1247+
1248+
libtiledb_profile_name <- function(profile) {
1249+
.Call(`_tiledb_libtiledb_profile_name`, profile)
1250+
}
1251+
1252+
libtiledb_profile_dir <- function(profile) {
1253+
.Call(`_tiledb_libtiledb_profile_dir`, profile)
1254+
}
1255+
1256+
libtiledb_profile_set_param <- function(profile, param, value) {
1257+
invisible(.Call(`_tiledb_libtiledb_profile_set_param`, profile, param, value))
1258+
}
1259+
1260+
libtiledb_profile_get_param <- function(profile, param) {
1261+
.Call(`_tiledb_libtiledb_profile_get_param`, profile, param)
1262+
}
1263+
1264+
libtiledb_profile_save <- function(profile) {
1265+
invisible(.Call(`_tiledb_libtiledb_profile_save`, profile))
1266+
}
1267+
1268+
libtiledb_profile_dump <- function(profile) {
1269+
.Call(`_tiledb_libtiledb_profile_dump`, profile)
1270+
}
1271+
12361272
vecbuf_to_shmem <- function(dir, name, buf, sz, numvar) {
12371273
invisible(.Call(`_tiledb_vecbuf_to_shmem`, dir, name, buf, sz, numvar))
12381274
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
library(tinytest)
2+
library(tiledb)
3+
4+
# Use base directory to prevent over-writing user profiles.
5+
name <- "test_profile"
6+
dir <- file.path(tempdir(), "tiledb_config_profile/")
7+
8+
# Create profile
9+
profile <- tiledb_profile(name, dir)
10+
11+
# Set some parameters
12+
token <- "12345"
13+
server_address <- "https://profile_address.com"
14+
tiledb_profile_set_param(profile, "rest.token", token)
15+
tiledb_profile_set_param(profile, "rest.server_address", server_address)
16+
17+
# Save the profile
18+
tiledb_profile_save(profile)
19+
20+
21+
# Create a config and set the profile directory
22+
config <- tiledb_config(c(profile_name = name, profile_dir = dir))
23+
config_profile_name <- config["profile_name"]
24+
config_profile_dir <- config["profile_dir"]
25+
config_rest_token <- config["rest.token"]
26+
config_rest_server_address <- config["rest.server_address"]
27+
28+
# Test that the config parameters are set correctly
29+
expect_equal(config["profile_name"], c(profile_name = name))
30+
expect_equal(config["profile_dir"], c(profile_dir = dir))
31+
expect_equal(config["rest.token"], c(rest.token = token))
32+
expect_equal(config["rest.server_address"], c(rest.server_address = server_address))
33+
34+
35+
# Remove the profile
36+
tiledb_profile_remove(name, dir)

inst/tinytest/test_profile.R

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
library(tinytest)
2+
library(tiledb)
3+
4+
# Use base directory to prevent over-writing user profiles.
5+
base_dir <- tempdir()
6+
dir1 <- file.path(base_dir, "tiledb_profile")
7+
8+
9+
# 1. Test creating profiles.
10+
profile1 <- tiledb_profile()
11+
profile2 <- tiledb_profile("profile2")
12+
profile3 <- tiledb_profile(dir=dir1)
13+
profile4 <- tiledb_profile("profile4", dir1)
14+
15+
expect_equal(tiledb_profile_name(profile1), "default")
16+
expect_equal(tiledb_profile_name(profile2), "profile2")
17+
expect_equal(tiledb_profile_name(profile3), "default")
18+
expect_equal(tiledb_profile_name(profile4), "profile4")
19+
20+
# Skipping checks for default directory since it is platform dependent.
21+
# Normalize paths on Windows to UNIX-style
22+
expected_dir <- normalizePath(
23+
path = dir1,
24+
winslash = "/",
25+
mustWork = FALSE
26+
)
27+
actual_dir_profile3 <- normalizePath(
28+
path = tiledb_profile_dir(profile3),
29+
winslash = "/",
30+
mustWork = FALSE
31+
)
32+
expect_identical(
33+
# trim trailing slashes
34+
current = sub(pattern = "/+$", replacement = "", x = actual_dir_profile3),
35+
target = expected_dir
36+
)
37+
actual_dir_profile4 <- normalizePath(
38+
path = tiledb_profile_dir(profile4),
39+
winslash = "/",
40+
mustWork = FALSE
41+
)
42+
expect_identical(
43+
current = sub(pattern = "/+$", replacement = "", x = actual_dir_profile4),
44+
target = expected_dir
45+
)
46+
47+
48+
# 2. Test setting/getting profile parameters.
49+
key1 <- "username"
50+
key2 <- "server_address"
51+
key3 <- "rest.token"
52+
expected_value1 <- "my_username"
53+
expected_value2 <- "https://my.address"
54+
expected_value3 <- "123456"
55+
56+
tiledb_profile_set_param(profile4, key1, expected_value1)
57+
tiledb_profile_set_param(profile4, key2, expected_value2)
58+
tiledb_profile_set_param(profile4, key3, expected_value3)
59+
60+
actual_value1 <- tiledb_profile_get_param(profile4, key1)
61+
actual_value2 <- tiledb_profile_get_param(profile4, key2)
62+
actual_value3 <- tiledb_profile_get_param(profile4, key3)
63+
actual_non_value <- tiledb_profile_get_param(profile4, "not_a_parameter")
64+
65+
expect_equal(actual_value1, expected_value1)
66+
expect_equal(actual_value2, expected_value2)
67+
expect_equal(actual_value3, expected_value3)
68+
expect_true(is.null(actual_non_value))
69+
70+
# 3. Test save, load, and remove.
71+
# IMPORTANT: Do not save a profile to a location that might over-write an actual profile.
72+
tiledb_profile_save(profile3)
73+
tiledb_profile_save(profile4)
74+
75+
# -- Check can load profile3
76+
profile_loaded <- tiledb_profile_load(dir=dir1)
77+
78+
# -- Remove profile2. Check can no longer load.
79+
tiledb_profile_remove(dir=dir1)
80+
expect_error(tiledb_profile_load(dir=dir1))
81+
82+
# -- Check loaded profile4
83+
profile_loaded <- tiledb_profile_load("profile4", dir1)
84+
expect_equal(tiledb_profile_name(profile_loaded), "profile4")
85+
expect_equal(tiledb_profile_name(profile_loaded), "profile4")
86+
loaded_value1 <- tiledb_profile_get_param(profile_loaded, key1)
87+
loaded_value2 <- tiledb_profile_get_param(profile_loaded, key2)
88+
loaded_value3 <- tiledb_profile_get_param(profile_loaded, key3)
89+
loaded_non_value <- tiledb_profile_get_param(profile_loaded, "not_a_parameter")
90+
expect_equal(loaded_value1, expected_value1)
91+
expect_equal(loaded_value2, expected_value2)
92+
expect_equal(loaded_value3, expected_value3)
93+
expect_true(is.null(loaded_non_value))
94+
95+
# -- Remove profile4
96+
tiledb_profile_remove("profile4", dir1)
97+
98+
# -- Check cannot load profile2 or profile4.
99+
expect_error(tiledb_profile_load(dir=dir1))
100+
expect_error(tiledb_profile_load("profile4", dir1))

man/raw_dump-tiledb_profile-method.Rd

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/tiledb_profile-class.Rd

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/tiledb_profile.Rd

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)