Skip to content

Commit

Permalink
Bug Fix: Wrong results when using OR condition with nullable attribut…
Browse files Browse the repository at this point in the history
…es (#3308) (#3367)

Fixed the bug on nullable attributes by refactoring the query condition so that nullable attributes are processed at the same time as the cell values. I also wrote test cases that test on complex query conditions with nullable attributes.

TYPE:BUG
DESC: Bug Fix: Wrong results when using OR condition with nullable attributes

Co-authored-by: Abigale Kim <abigale.kim@tiledb.com>
  • Loading branch information
github-actions[bot] and abigalekim committed Jul 14, 2022
1 parent d19380a commit a3e7709
Show file tree
Hide file tree
Showing 5 changed files with 736 additions and 122 deletions.
1 change: 1 addition & 0 deletions test/regression/CMakeLists.txt
Expand Up @@ -30,6 +30,7 @@ find_package(Catch_EP REQUIRED)
set(SOURCES
targets/sc-12024.cc
targets/sc-15387.cc
targets/sc-18836.cc
)

if (TILEDB_SERIALIZATION)
Expand Down
114 changes: 114 additions & 0 deletions test/regression/targets/sc-18836.cc
@@ -0,0 +1,114 @@
#include <string>
#include <iostream>
#include <tiledb/tiledb>
#include <future>

#include "catch.hpp"

using namespace tiledb;

float a2_fill_value = 0.0f;
const std::string array_name = "cpp_qc_nullable_array";

void create_array(){
Context ctx;

// Create dimension
auto dim = tiledb::Dimension::create<int32_t>(ctx, "dim", {{1, 9}}, 2);

Domain domain(ctx);
domain.add_dimension(dim);

Attribute a1(ctx, "a1", TILEDB_INT32);
a1.set_nullable(true);
Attribute a2(ctx, "a2", TILEDB_FLOAT32);
a2.set_fill_value(&a2_fill_value, sizeof(float));

ArraySchema schema(ctx, TILEDB_DENSE);
schema.set_domain(domain);
schema.add_attribute(a1).add_attribute(a2);

Array::create(array_name, schema);

// Prepare some data for the array
std::vector<int> data1 = {8, 9, 10, 11, 12, 13, 14, 15, 16};
std::vector<uint8_t> a1_validity_buf = {0, 1, 1, 1, 1, 0, 1, 1, 0};

std::vector<float> data2 = {13.2f, 14.1f, 14.2f, 15.1f, 15.2f, 15.3f, 16.1f, 18.3f, 19.1f};

// Set the subarray to write into
std::vector<int> subarray = {1, 9};

// Open array for writing
Array array(ctx, array_name, TILEDB_WRITE);

Query query(ctx, array);
query.set_layout(TILEDB_ROW_MAJOR)
.set_buffer("a1", data1)
.set_validity_buffer("a1", a1_validity_buf)
.set_buffer("a2", data2)
.set_subarray(subarray);

query.submit();
array.close();
}

TEST_CASE("Query Condition CPP API: Query Condition OR with nullable attributes (sc-18836)", "[QueryCondition]"){
Context ctx;
VFS vfs(ctx);

if (vfs.is_dir(array_name))
vfs.remove_dir(array_name);

create_array();

// Prepare the array for reading
Array array(ctx, array_name, TILEDB_READ);

const std::vector<int> subarray = {1, 9};

// Prepare the vectors that will hold the results
std::vector<int> a1_buffer(9);
std::vector<float> a2_buffer(9);
std::vector<uint8_t> a1_validity_buf(9);

// Prepare the query
Query query(ctx, array, TILEDB_READ);
query.set_subarray(subarray)
.set_layout(TILEDB_ROW_MAJOR)
.set_buffer("a1", a1_buffer)
.set_validity_buffer("a1", a1_validity_buf)
.set_buffer("a2", a2_buffer);

QueryCondition qc1(ctx);
float val = 15.1f;
qc1.init("a2", &val, sizeof(float), TILEDB_EQ);
QueryCondition qc2(ctx);
qc2.init("a1", nullptr, 0, TILEDB_EQ);
QueryCondition qc(ctx);

SECTION("Ordering q1, q2") {
qc = qc1.combine(qc2, TILEDB_OR);
}

SECTION("Ordering q2, q1") {
qc = qc2.combine(qc1, TILEDB_OR);
}

query.set_condition(qc);
query.submit();
array.close();

// Print out the results.
int m = std::numeric_limits<int>::min();
std::vector<int> a1_expected = {8, m, m, 11, m, 13, m, m, 16};
std::vector<float> a2_expected = {13.2f, 0.0f, 0.0f, 15.1f, 0.0f, 15.3f, 0.0f, 0.0f, 19.1f};
auto result_num = (int)query.result_buffer_elements()["a1"].second;
for (int r = 0; r < result_num; r++) {
CHECK(a1_buffer[r] == a1_expected[r]);
CHECK(a2_buffer[r] == a2_expected[r]);
}

if (vfs.is_dir(array_name))
vfs.remove_dir(array_name);
}

0 comments on commit a3e7709

Please sign in to comment.