Skip to content

Commit d632325

Browse files
Enable current domain on dense arrays. (#5303)
This PR enables the current domain feature in dense arrays --- TYPE: FEATURE DESC: Support current domain on dense arrays. --------- Co-authored-by: Theodore Tsirpanis <[email protected]>
1 parent 39c665a commit d632325

File tree

4 files changed

+256
-42
lines changed

4 files changed

+256
-42
lines changed

test/src/test-cppapi-current-domain.cc

Lines changed: 256 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,15 @@ TEST_CASE_METHOD(
153153
CurrentDomainFx,
154154
"C++ API: CurrentDomain - Add to ArraySchema",
155155
"[cppapi][ArraySchema][currentDomain]") {
156+
tiledb_array_type_t type = GENERATE(TILEDB_DENSE, TILEDB_SPARSE);
157+
156158
// Create domain.
157159
tiledb::Domain domain(ctx_);
158160
auto d = tiledb::Dimension::create<int32_t>(ctx_, "d", {{1, 999}}, 2);
159161
domain.add_dimension(d);
160162

161163
// Create array schema.
162-
tiledb::ArraySchema schema(ctx_, TILEDB_SPARSE);
164+
tiledb::ArraySchema schema(ctx_, type);
163165
schema.set_domain(domain);
164166
schema.add_attribute(tiledb::Attribute::create<int>(ctx_, "a"));
165167

@@ -191,6 +193,8 @@ TEST_CASE_METHOD(
191193
"[cppapi][ArraySchema][currentDomain]") {
192194
const std::string array_name = "test_current_domain_expansion";
193195

196+
tiledb_array_type_t type = GENERATE(TILEDB_DENSE, TILEDB_SPARSE);
197+
194198
tiledb::VFS vfs(ctx_);
195199
if (vfs.is_dir(array_name)) {
196200
vfs.remove_dir(array_name);
@@ -202,7 +206,7 @@ TEST_CASE_METHOD(
202206
domain.add_dimension(d);
203207

204208
// Create array schema.
205-
tiledb::ArraySchema schema(ctx_, TILEDB_SPARSE);
209+
tiledb::ArraySchema schema(ctx_, type);
206210
schema.set_domain(domain);
207211
schema.add_attribute(tiledb::Attribute::create<int>(ctx_, "a"));
208212

@@ -365,7 +369,7 @@ TEST_CASE_METHOD(
365369
TEST_CASE_METHOD(
366370
CurrentDomainFx,
367371
"C++ API: CurrentDomain - Read cells written outside of shape",
368-
"[cppapi][ArraySchema][currentDomain][luc]") {
372+
"[cppapi][ArraySchema][currentDomain]") {
369373
const std::string array_name = "test_current_domain_read";
370374

371375
tiledb::VFS vfs(ctx_);
@@ -488,3 +492,252 @@ TEST_CASE_METHOD(
488492
vfs.remove_dir(array_name);
489493
}
490494
}
495+
496+
TEST_CASE_METHOD(
497+
CurrentDomainFx,
498+
"C++ API: CurrentDomain - Dense array basic",
499+
"[cppapi][ArraySchema][currentDomain]") {
500+
const std::string array_name = "test_current_domain_read_dense";
501+
502+
tiledb::VFS vfs(ctx_);
503+
if (vfs.is_dir(array_name)) {
504+
vfs.remove_dir(array_name);
505+
}
506+
507+
// Create domain
508+
tiledb::Domain domain(ctx_);
509+
auto d1 = tiledb::Dimension::create<int32_t>(ctx_, "dim1", {{1, 10}}, 1);
510+
domain.add_dimension(d1);
511+
512+
// Create array schema.
513+
tiledb::ArraySchema schema(ctx_, TILEDB_DENSE);
514+
schema.set_domain(domain);
515+
schema.add_attribute(tiledb::Attribute::create<int>(ctx_, "a"));
516+
517+
// Create array
518+
tiledb::Array::create(array_name, schema);
519+
520+
tiledb::Array array_for_writes(ctx_, array_name, TILEDB_WRITE);
521+
// Populate array with data from 1 to 10. Some of the data here is outside of
522+
// the current domain we will set later.
523+
tiledb::Query query_for_writes(ctx_, array_for_writes);
524+
query_for_writes.set_layout(TILEDB_ROW_MAJOR);
525+
tiledb::Subarray sub_for_writes(ctx_, array_for_writes);
526+
sub_for_writes.set_subarray({1, 10});
527+
query_for_writes.set_subarray(sub_for_writes);
528+
std::vector<int32_t> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
529+
query_for_writes.set_data_buffer("a", data);
530+
query_for_writes.submit();
531+
array_for_writes.close();
532+
533+
// Read data to validate
534+
tiledb::Array array(ctx_, array_name, TILEDB_READ);
535+
tiledb::Subarray sub(ctx_, array);
536+
sub.set_subarray({1, 10});
537+
std::vector<int32_t> a(10);
538+
tiledb::Query query(ctx_, array, TILEDB_READ);
539+
query.set_subarray(sub).set_layout(TILEDB_ROW_MAJOR).set_data_buffer("a", a);
540+
query.submit();
541+
array.close();
542+
543+
// Check values
544+
for (int i = 0; i < 9; i++) {
545+
CHECK(a[i] == i + 1);
546+
}
547+
548+
// Create new currentDomain
549+
tiledb::CurrentDomain current_domain_ev(ctx_);
550+
int range_two[] = {2, 5};
551+
tiledb::NDRectangle ndrect_two(ctx_, domain);
552+
ndrect_two.set_range(0, range_two[0], range_two[1]);
553+
current_domain_ev.set_ndrectangle(ndrect_two);
554+
555+
// Schema evolution
556+
tiledb::ArraySchemaEvolution se(ctx_);
557+
se.expand_current_domain(current_domain_ev);
558+
se.array_evolve(array_name);
559+
560+
// Re-read data which is included in the current domain to validate
561+
tiledb::Array array_with_cd(ctx_, array_name, TILEDB_READ);
562+
tiledb::Subarray sub_for_cd(ctx_, array_with_cd);
563+
sub_for_cd.set_subarray({2, 5});
564+
std::vector<int32_t> a_with_cd(100);
565+
std::vector<int32_t> dim1_with_cd(100);
566+
tiledb::Query query_for_cd(ctx_, array_with_cd, TILEDB_READ);
567+
query_for_cd.set_subarray(sub_for_cd)
568+
.set_layout(TILEDB_ROW_MAJOR)
569+
.set_data_buffer("a", a_with_cd)
570+
.set_data_buffer("dim1", dim1_with_cd);
571+
query_for_cd.submit();
572+
array_with_cd.close();
573+
574+
// Validate we got four results.
575+
auto res = query_for_cd.result_buffer_elements();
576+
CHECK(res["a"].second == 4);
577+
CHECK(res["dim1"].second == 4);
578+
579+
// Try to read data outside the current domain and fail
580+
tiledb::Array array_with_cd2(ctx_, array_name, TILEDB_READ);
581+
tiledb::Subarray sub_for_cd_wrong(ctx_, array_with_cd2);
582+
sub_for_cd_wrong.set_subarray({2, 6});
583+
std::vector<int32_t> a_with_cd2(100);
584+
std::vector<int32_t> dim1_with_cd2(100);
585+
tiledb::Query query_for_cd2(ctx_, array_with_cd2, TILEDB_READ);
586+
query_for_cd2.set_subarray(sub_for_cd_wrong)
587+
.set_layout(TILEDB_ROW_MAJOR)
588+
.set_data_buffer("a", a_with_cd2)
589+
.set_data_buffer("dim1", dim1_with_cd2);
590+
auto matcher = Catch::Matchers::ContainsSubstring(
591+
"A range was set outside of the current domain.");
592+
REQUIRE_THROWS_WITH(query_for_cd2.submit(), matcher);
593+
array_with_cd2.close();
594+
595+
// Clean up.
596+
if (vfs.is_dir(array_name)) {
597+
vfs.remove_dir(array_name);
598+
}
599+
}
600+
601+
TEST_CASE_METHOD(
602+
CurrentDomainFx,
603+
"C++ API: CurrentDomain - Dense array current domain expand",
604+
"[cppapi][ArraySchema][currentDomain]") {
605+
const std::string array_name = "test_current_domain_read_dense";
606+
607+
std::string matcher_string;
608+
bool throws = false;
609+
bool shrink = false;
610+
SECTION("Expand outside domain bounds") {
611+
throws = true;
612+
shrink = false;
613+
matcher_string =
614+
"This array current domain has ranges past the boundaries of the array "
615+
"schema domain";
616+
}
617+
618+
SECTION("Shrink domain") {
619+
throws = true;
620+
shrink = true;
621+
matcher_string =
622+
"The current domain of an array can only be expanded, please adjust "
623+
"your new current domain object";
624+
}
625+
626+
SECTION("Expand correctly") {
627+
// do nothing
628+
}
629+
630+
tiledb::VFS vfs(ctx_);
631+
if (vfs.is_dir(array_name)) {
632+
vfs.remove_dir(array_name);
633+
}
634+
635+
// Create domain
636+
tiledb::Domain domain(ctx_);
637+
auto d1 = tiledb::Dimension::create<int32_t>(ctx_, "dim1", {{1, 10}}, 1);
638+
domain.add_dimension(d1);
639+
640+
// Create array schema.
641+
tiledb::ArraySchema schema(ctx_, TILEDB_DENSE);
642+
schema.set_domain(domain);
643+
schema.add_attribute(tiledb::Attribute::create<int>(ctx_, "a"));
644+
645+
// Create and set new currentDomain
646+
tiledb::CurrentDomain current_domain(ctx_);
647+
int range[] = {2, 5};
648+
tiledb::NDRectangle ndrect(ctx_, domain);
649+
ndrect.set_range(0, range[0], range[1]);
650+
current_domain.set_ndrectangle(ndrect);
651+
CHECK_NOTHROW(tiledb::ArraySchemaExperimental::set_current_domain(
652+
ctx_, schema, current_domain));
653+
654+
// Create array
655+
tiledb::Array::create(array_name, schema);
656+
657+
// Create new currentDomain to expand
658+
tiledb::CurrentDomain current_domain_ev(ctx_);
659+
std::vector<int> range_two;
660+
if (throws) {
661+
if (shrink) {
662+
range_two = {2, 3};
663+
} else {
664+
range_two = {2, 11};
665+
}
666+
} else {
667+
range_two = {2, 7};
668+
}
669+
tiledb::NDRectangle ndrect_two(ctx_, domain);
670+
ndrect_two.set_range(0, range_two[0], range_two[1]);
671+
current_domain_ev.set_ndrectangle(ndrect_two);
672+
673+
// Schema evolution
674+
tiledb::ArraySchemaEvolution se(ctx_);
675+
se.expand_current_domain(current_domain_ev);
676+
677+
// Check the correct exceptions are being thrown
678+
if (throws) {
679+
auto matcher = Catch::Matchers::ContainsSubstring(matcher_string);
680+
REQUIRE_THROWS_WITH(se.array_evolve(array_name), matcher);
681+
} else {
682+
REQUIRE_NOTHROW(se.array_evolve(array_name));
683+
}
684+
685+
// Clean up.
686+
if (vfs.is_dir(array_name)) {
687+
vfs.remove_dir(array_name);
688+
}
689+
}
690+
691+
TEST_CASE_METHOD(
692+
CurrentDomainFx,
693+
"C++ API: CurrentDomain - Dense array write outside current domain",
694+
"[cppapi][ArraySchema][currentDomain]") {
695+
const std::string array_name = "test_current_domain_read_dense";
696+
697+
tiledb::VFS vfs(ctx_);
698+
if (vfs.is_dir(array_name)) {
699+
vfs.remove_dir(array_name);
700+
}
701+
702+
// Create domain
703+
tiledb::Domain domain(ctx_);
704+
auto d1 = tiledb::Dimension::create<int32_t>(ctx_, "dim1", {{1, 10}}, 1);
705+
domain.add_dimension(d1);
706+
707+
// Create array schema.
708+
tiledb::ArraySchema schema(ctx_, TILEDB_DENSE);
709+
schema.set_domain(domain);
710+
schema.add_attribute(tiledb::Attribute::create<int>(ctx_, "a"));
711+
712+
// Create and set new currentDomain
713+
tiledb::CurrentDomain current_domain(ctx_);
714+
int range[] = {2, 5};
715+
tiledb::NDRectangle ndrect(ctx_, domain);
716+
ndrect.set_range(0, range[0], range[1]);
717+
current_domain.set_ndrectangle(ndrect);
718+
CHECK_NOTHROW(tiledb::ArraySchemaExperimental::set_current_domain(
719+
ctx_, schema, current_domain));
720+
721+
// Create array
722+
tiledb::Array::create(array_name, schema);
723+
724+
tiledb::Array array_for_writes(ctx_, array_name, TILEDB_WRITE);
725+
// Populate array with data from 1 to 10. Some of the data here is outside of
726+
// the current domain so we expect to fail.
727+
tiledb::Query query_for_writes(ctx_, array_for_writes);
728+
query_for_writes.set_layout(TILEDB_ROW_MAJOR);
729+
tiledb::Subarray sub_for_writes(ctx_, array_for_writes);
730+
sub_for_writes.set_subarray({1, 10});
731+
query_for_writes.set_subarray(sub_for_writes);
732+
std::vector<int32_t> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
733+
query_for_writes.set_data_buffer("a", data);
734+
auto matcher = Catch::Matchers::ContainsSubstring(
735+
"Cells are written outside of the defined current domain.");
736+
REQUIRE_THROWS_WITH(query_for_writes.submit(), matcher);
737+
array_for_writes.close();
738+
739+
// Clean up.
740+
if (vfs.is_dir(array_name)) {
741+
vfs.remove_dir(array_name);
742+
}
743+
}

tiledb/api/c_api/array_schema/array_schema_api_experimental.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ TILEDB_EXPORT capi_return_t tiledb_array_schema_add_enumeration(
101101
/**
102102
* Sets the current domain on the array schema.
103103
*
104-
* @pre The schema is sparse. current_domain is not yet supported on dense
105-
* arrays.
106-
*
107104
* **Example:**
108105
*
109106
* @code{.c}

tiledb/sm/array_schema/array_schema.cc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,12 +1668,6 @@ void ArraySchema::expand_current_domain(
16681668
"The argument specified for current domain expansion is nullptr.");
16691669
}
16701670

1671-
if (this->dense()) {
1672-
throw ArraySchemaException(
1673-
"Expanding the current domain on a TileDB dense array is not "
1674-
"supported.");
1675-
}
1676-
16771671
// Check that the new current domain expands the existing one and not shrinks
16781672
// it. Every current domain covers an empty current domain.
16791673
if (!current_domain_->empty() &&
@@ -1699,11 +1693,6 @@ void ArraySchema::set_current_domain(shared_ptr<CurrentDomain> current_domain) {
16991693
"The argument specified for setting the current domain on the "
17001694
"schema is nullptr.");
17011695
}
1702-
if (this->dense()) {
1703-
throw ArraySchemaException(
1704-
"Setting a current domain on a TileDB dense array is not supported.");
1705-
}
1706-
17071696
current_domain_ = current_domain;
17081697
}
17091698

tiledb/sm/array_schema/test/unit_current_domain.cc

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -286,31 +286,6 @@ shared_ptr<ArraySchema> CurrentDomainFx<T>::get_array_schema_latest() {
286286
return array_dir->load_array_schema_latest(enc_key_, memory_tracker_);
287287
}
288288

289-
TEST_CASE_METHOD(
290-
CurrentDomainFx<int32_t>,
291-
"Setting CurrentDomain not allowed on Dense",
292-
"[current_domain][dense]") {
293-
auto schema = create_schema(true);
294-
auto current_domain = create_current_domain({}, schema, nullptr, true);
295-
296-
auto matcher = Catch::Matchers::ContainsSubstring(
297-
"Setting a current domain on a TileDB dense array is not supported.");
298-
299-
REQUIRE_THROWS_WITH(schema->set_current_domain(current_domain), matcher);
300-
301-
Range r;
302-
std::vector<int32_t> rdata = {1, 1000};
303-
r = Range(rdata.data(), 2 * sizeof(int32_t));
304-
current_domain = create_current_domain({r, r}, schema, nullptr, false);
305-
auto ase = make_shared<ArraySchemaEvolution>(HERE(), this->memory_tracker_);
306-
ase->expand_current_domain(current_domain);
307-
308-
auto matcher2 = Catch::Matchers::ContainsSubstring(
309-
"Expanding the current domain on a TileDB dense array is not supported.");
310-
311-
REQUIRE_THROWS_WITH(ase->evolve_schema(schema), matcher2);
312-
}
313-
314289
TEST_CASE_METHOD(
315290
CurrentDomainFx<int32_t>,
316291
"Create Empty CurrentDomain",

0 commit comments

Comments
 (0)