Skip to content

Commit e96ba69

Browse files
authored
Expose the overwrite parameter in the profile-save functions of the C/C++ APIs (#5695)
This PR exposes the `overwrite` parameter in the profile save functions of the C and C++ APIs. This is good-to-have for high level APIs. Closes CORE-433 --- TYPE: C_API DESC: Expose the `overwrite` parameter in `tiledb_profile_save`. --- TYPE: CPP_API DESC: Expose the `overwrite` parameter in `Profile::save`.
1 parent 6358fe1 commit e96ba69

File tree

7 files changed

+139
-16
lines changed

7 files changed

+139
-16
lines changed

test/src/unit-cppapi-profile.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,31 @@ TEST_CASE(
374374
loaded_explicit_profile.get_param("rest.server_address") ==
375375
"https://explicit.server");
376376
}
377+
378+
TEST_CASE_METHOD(
379+
ProfileCPPFx,
380+
"C++ API: Profile::save with overwrite",
381+
"[cppapi][profile][save][overwrite]") {
382+
Profile p1(name_, tempdir_.path());
383+
p1.set_param("rest.token", "token1");
384+
p1.save();
385+
386+
// Attempt to save again without overwrite should fail
387+
Profile p2(name_, tempdir_.path());
388+
p2.set_param("rest.token", "token2");
389+
REQUIRE_THROWS_WITH(
390+
p2.save(false),
391+
Catch::Matchers::ContainsSubstring(
392+
"This profile already exists. Use the overwrite parameter"));
393+
394+
// Verify that the original profile is unchanged
395+
Profile loaded1 = Profile::load(name_, tempdir_.path());
396+
REQUIRE(loaded1.get_param("rest.token") == "token1");
397+
398+
// Save with overwrite=true should succeed
399+
REQUIRE_NOTHROW(p2.save(true));
400+
401+
// Verify that the profile was updated
402+
Profile loaded2 = Profile::load(name_, tempdir_.path());
403+
REQUIRE(loaded2.get_param("rest.token") == "token2");
404+
}

tiledb/api/c_api/profile/profile_api.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,10 @@ capi_return_t tiledb_profile_get_param(
102102
return TILEDB_OK;
103103
}
104104

105-
capi_return_t tiledb_profile_save(tiledb_profile_t* profile) {
105+
capi_return_t tiledb_profile_save(
106+
tiledb_profile_t* profile, uint8_t overwrite) {
106107
ensure_profile_is_valid(profile);
107-
profile->profile()->save_to_file();
108+
profile->profile()->save_to_file(overwrite != 0);
108109
return TILEDB_OK;
109110
}
110111

@@ -189,8 +190,12 @@ CAPI_INTERFACE(
189190
}
190191

191192
CAPI_INTERFACE(
192-
profile_save, tiledb_profile_t* profile, tiledb_error_t** error) {
193-
return api_entry_error<tiledb::api::tiledb_profile_save>(error, profile);
193+
profile_save,
194+
tiledb_profile_t* profile,
195+
uint8_t overwrite,
196+
tiledb_error_t** error) {
197+
return api_entry_error<tiledb::api::tiledb_profile_save>(
198+
error, profile, overwrite);
194199
}
195200

196201
CAPI_INTERFACE(

tiledb/api/c_api/profile/profile_api_experimental.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,15 @@ TILEDB_EXPORT capi_return_t tiledb_profile_get_param(
183183
* Saves the given profile to the local file.
184184
*
185185
* @param[in] profile The profile.
186+
* @param[in] overwrite If non-zero, overwrite the existing profile.
186187
* @param[out] error Error object returned upon error (`NULL` if there is no
187188
* error).
188189
* @return TILEDB_EXPORT
189190
*/
190191
TILEDB_EXPORT capi_return_t tiledb_profile_save(
191-
tiledb_profile_t* profile, tiledb_error_t** error) TILEDB_NOEXCEPT;
192+
tiledb_profile_t* profile,
193+
uint8_t overwrite,
194+
tiledb_error_t** error) TILEDB_NOEXCEPT;
192195

193196
/**
194197
* Loads a profile from the local file.

tiledb/api/c_api/profile/test/unit_capi_profile.cc

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,11 @@ TEST_CASE_METHOD(
229229
tiledb_profile_alloc(name_, dir_.c_str(), &profile, &err);
230230
REQUIRE(profile != nullptr);
231231
SECTION("success") {
232-
rc = tiledb_profile_save(profile, &err);
232+
rc = tiledb_profile_save(profile, 0, &err);
233233
REQUIRE(tiledb_status(rc) == TILEDB_OK);
234234
}
235235
SECTION("null profile") {
236-
rc = tiledb_profile_save(nullptr, &err);
236+
rc = tiledb_profile_save(nullptr, 0, &err);
237237
REQUIRE(tiledb_status(rc) == TILEDB_ERR);
238238
}
239239

@@ -249,7 +249,7 @@ TEST_CASE_METHOD(
249249
tiledb_error_t* err = nullptr;
250250
tiledb_profile_alloc(name_, dir_.c_str(), &profile, &err);
251251
REQUIRE(profile != nullptr);
252-
rc = tiledb_profile_save(profile, &err);
252+
rc = tiledb_profile_save(profile, 0, &err);
253253
REQUIRE(tiledb_status(rc) == TILEDB_OK);
254254
tiledb_profile_t* loaded_profile;
255255
// Use the same name and directory
@@ -275,7 +275,7 @@ TEST_CASE_METHOD(
275275
tiledb_profile_alloc(name_, dir_.c_str(), &profile, &err);
276276
REQUIRE(profile != nullptr);
277277
SECTION("success") {
278-
rc = tiledb_profile_save(profile, &err);
278+
rc = tiledb_profile_save(profile, 0, &err);
279279
REQUIRE(tiledb_status(rc) == TILEDB_OK);
280280
rc = tiledb_profile_remove(name_, dir_.c_str(), &err);
281281
REQUIRE(tiledb_status(rc) == TILEDB_OK);
@@ -309,3 +309,55 @@ TEST_CASE_METHOD(
309309

310310
tiledb_profile_free(&profile);
311311
}
312+
313+
TEST_CASE_METHOD(
314+
CAPINProfileFx,
315+
"C API: tiledb_profile_save with overwrite",
316+
"[capi][profile][save][overwrite]") {
317+
capi_return_t rc;
318+
tiledb_profile_t* p1;
319+
tiledb_error_t* err = nullptr;
320+
tiledb_profile_alloc(name_, dir_.c_str(), &p1, &err);
321+
tiledb_profile_set_param(p1, "rest.token", "token1", &err);
322+
rc = tiledb_profile_save(p1, 0, &err);
323+
REQUIRE(tiledb_status(rc) == TILEDB_OK);
324+
325+
// Attempt to save again without overwrite should fail
326+
tiledb_profile_t* p2;
327+
tiledb_profile_alloc(name_, dir_.c_str(), &p2, &err);
328+
tiledb_profile_set_param(p2, "rest.token", "token2", &err);
329+
rc = tiledb_profile_save(p2, 0, &err);
330+
REQUIRE(tiledb_status(rc) == TILEDB_ERR);
331+
REQUIRE(err != nullptr);
332+
tiledb_error_free(&err);
333+
334+
// Verify that the original profile is unchanged
335+
tiledb_profile_t* loaded1;
336+
tiledb_profile_alloc(name_, dir_.c_str(), &loaded1, &err);
337+
tiledb_profile_load(loaded1, &err);
338+
339+
tiledb_string_t* value;
340+
tiledb_profile_get_param(loaded1, "rest.token", &value, &err);
341+
const char* value_ptr;
342+
size_t value_len;
343+
tiledb_string_view(value, &value_ptr, &value_len);
344+
CHECK(std::string(value_ptr, value_len) == "token1");
345+
346+
// Save with overwrite=1 should succeed
347+
rc = tiledb_profile_save(p2, 1, &err);
348+
REQUIRE(tiledb_status(rc) == TILEDB_OK);
349+
350+
// Verify that the profile is updated
351+
tiledb_profile_t* loaded2;
352+
tiledb_profile_alloc(name_, dir_.c_str(), &loaded2, &err);
353+
tiledb_profile_load(loaded2, &err);
354+
tiledb_profile_get_param(loaded2, "rest.token", &value, &err);
355+
tiledb_string_view(value, &value_ptr, &value_len);
356+
CHECK(std::string(value_ptr, value_len) == "token2");
357+
358+
tiledb_string_free(&value);
359+
tiledb_profile_free(&p1);
360+
tiledb_profile_free(&p2);
361+
tiledb_profile_free(&loaded1);
362+
tiledb_profile_free(&loaded2);
363+
}

tiledb/sm/cpp_api/profile_experimental.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,15 @@ class Profile {
229229
return ret;
230230
}
231231

232-
/** Saves the profile to the local file. */
233-
void save() {
232+
/**
233+
* Saves the profile to the local file.
234+
*
235+
* @param overwrite If true, overwrite the existing profile.
236+
*/
237+
void save(bool overwrite = false) {
234238
tiledb_error_t* capi_error = nullptr;
235-
int rc = tiledb_profile_save(profile_.get(), &capi_error);
239+
int rc =
240+
tiledb_profile_save(profile_.get(), overwrite ? 1 : 0, &capi_error);
236241
if (rc != TILEDB_OK) {
237242
const char* msg_cstr;
238243
tiledb_error_message(capi_error, &msg_cstr);

tiledb/sm/rest/rest_profile.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ void RestProfile::save_to_file(const bool overwrite) {
219219
if (data.contains(name_) && !overwrite) {
220220
throw RestProfileException(
221221
"Failed to save '" + name_ +
222-
"'; This profile has already been saved "
223-
"and must be explicitly removed in order to be replaced.");
222+
"'; This profile already exists. "
223+
"Use the overwrite parameter to replace it.");
224224
}
225225

226226
if (overwrite) {

tiledb/sm/rest/test/unit_rest_profile.cc

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ TEST_CASE_METHOD(
196196
REQUIRE_THROWS_WITH(
197197
p2.save_to_file(),
198198
Catch::Matchers::Equals("RestProfile: Failed to save 'default'; This "
199-
"profile has already been saved and must be "
200-
"explicitly removed in order to be replaced."));
199+
"profile already exists. "
200+
"Use the overwrite parameter to replace it."));
201201
RestProfile::remove_profile(std::nullopt, dir_);
202202
p2.save_to_file();
203203

@@ -271,3 +271,33 @@ TEST_CASE_METHOD(
271271
Catch::Matchers::ContainsSubstring("Error parsing file"));
272272
}
273273
}
274+
275+
TEST_CASE_METHOD(
276+
RestProfileFx,
277+
"REST Profile: save_to_file with overwrite",
278+
"[rest_profile][save][overwrite]") {
279+
RestProfile p1(create_profile());
280+
p1.set_param("rest.token", "token1");
281+
p1.save_to_file();
282+
283+
// Attempt to save again without overwrite should fail
284+
RestProfile p2(create_profile());
285+
p2.set_param("rest.token", "token2");
286+
REQUIRE_THROWS_WITH(
287+
p2.save_to_file(false),
288+
Catch::Matchers::ContainsSubstring(
289+
"This profile already exists. Use the overwrite parameter"));
290+
291+
// Verify that the original profile is unchanged
292+
RestProfile loaded1(create_profile());
293+
loaded1.load_from_file();
294+
CHECK(*loaded1.get_param("rest.token") == "token1");
295+
296+
// Save with overwrite=true should succeed
297+
REQUIRE_NOTHROW(p2.save_to_file(true));
298+
299+
// Verify that the profile is updated
300+
RestProfile loaded2(create_profile());
301+
loaded2.load_from_file();
302+
CHECK(*loaded2.get_param("rest.token") == "token2");
303+
}

0 commit comments

Comments
 (0)