Skip to content

Commit 13b26d7

Browse files
authored
Merge pull request #2784 from finos/fix-filter-interned
Fix filter values for non-interned strings
2 parents 28a3101 + 926ea29 commit 13b26d7

File tree

7 files changed

+109
-7
lines changed

7 files changed

+109
-7
lines changed

cpp/perspective/src/cpp/data_table.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ t_data_table::filter_cpp(
512512
break;
513513
}
514514

515+
// TODO we can make this faster by not constructing these on
516+
// every iteration?
517+
515518
const auto& ft = fterms[cidx];
516519
bool tval;
517520

cpp/perspective/src/cpp/server.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,12 +1002,12 @@ calculate_num_hidden(const ErasedView& view, const t_view_config& config) {
10021002
template <typename A>
10031003
static t_tscalar
10041004
coerce_to(const t_dtype dtype, const A& val) {
1005-
if constexpr (std::is_same_v<A, std::string>) {
1005+
if constexpr (std::is_same_v<A, const char*>) {
10061006
t_tscalar scalar;
10071007
scalar.clear();
10081008
switch (dtype) {
10091009
case DTYPE_STR:
1010-
scalar.set(val.c_str());
1010+
scalar.set(val);
10111011
return scalar;
10121012
case DTYPE_BOOL:
10131013
scalar.set(val == "true");
@@ -1585,6 +1585,8 @@ ProtoServer::_handle_request(std::uint32_t client_id, const Request& req) {
15851585
));
15861586
}
15871587

1588+
t_vocab vocab;
1589+
vocab.init(false);
15881590
std::vector<
15891591
std::tuple<std::string, std::string, std::vector<t_tscalar>>>
15901592
filter;
@@ -1617,9 +1619,24 @@ ProtoServer::_handle_request(std::uint32_t client_id, const Request& req) {
16171619
"Filter column not in schema: " + f.column()
16181620
);
16191621
}
1620-
a = coerce_to(
1621-
schema->get_dtype(f.column()), arg.string()
1622-
);
1622+
1623+
if (!t_tscalar::can_store_inplace(
1624+
arg.string().c_str()
1625+
)) {
1626+
1627+
a = coerce_to(
1628+
schema->get_dtype(f.column()),
1629+
vocab.unintern_c(
1630+
vocab.get_interned(arg.string())
1631+
)
1632+
);
1633+
} else {
1634+
1635+
a = coerce_to(
1636+
schema->get_dtype(f.column()),
1637+
arg.string().c_str()
1638+
);
1639+
}
16231640
args.push_back(a);
16241641
break;
16251642
}
@@ -1715,6 +1732,7 @@ ProtoServer::_handle_request(std::uint32_t client_id, const Request& req) {
17151732
LOG_DEBUG("FILTER_OP: " << filter_op);
17161733

17171734
auto config = std::make_shared<t_view_config>(
1735+
vocab,
17181736
row_pivots,
17191737
column_pivots,
17201738
aggregates,
@@ -1906,7 +1924,7 @@ ProtoServer::_handle_request(std::uint32_t client_id, const Request& req) {
19061924
auto* f = proto_filter->Add();
19071925
f->set_column(filter.m_colname);
19081926
f->set_op(filter_op_to_str(filter.m_op));
1909-
auto vals = std::vector<t_tscalar>(filter.m_bag.size() + 1);
1927+
auto vals = std::vector<t_tscalar>(filter.m_bag.size());
19101928
if (filter.m_op != FILTER_OP_NOT_IN
19111929
&& filter.m_op != FILTER_OP_IN) {
19121930
vals.push_back(filter.m_threshold);
@@ -1915,6 +1933,7 @@ ProtoServer::_handle_request(std::uint32_t client_id, const Request& req) {
19151933
vals.push_back(scalar);
19161934
}
19171935
}
1936+
19181937
for (const auto& scalar : vals) {
19191938
auto* s = f->mutable_value()->Add();
19201939
switch (scalar.get_dtype()) {

cpp/perspective/src/cpp/view_config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace perspective {
1818

1919
t_view_config::t_view_config(
20+
t_vocab vocab,
2021
const std::vector<std::string>& row_pivots,
2122
const std::vector<std::string>& column_pivots,
2223
const tsl::ordered_map<std::string, std::vector<std::string>>& aggregates,
@@ -29,6 +30,7 @@ t_view_config::t_view_config(
2930
bool column_only
3031
) :
3132
m_init(false),
33+
m_vocab(std::move(vocab)),
3234
m_row_pivots(row_pivots),
3335
m_column_pivots(column_pivots),
3436
m_aggregates(aggregates),

cpp/perspective/src/include/perspective/view_config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class PERSPECTIVE_EXPORT t_view_config {
4545
* @param sort
4646
*/
4747
t_view_config(
48+
t_vocab vocab,
4849
const std::vector<std::string>& row_pivots,
4950
const std::vector<std::string>& column_pivots,
5051
const tsl::ordered_map<std::string, std::vector<std::string>>&
@@ -178,8 +179,12 @@ class PERSPECTIVE_EXPORT t_view_config {
178179
t_dtype dtype
179180
);
180181

182+
// Global dictionary for `t_tscalar` in filter terms.
183+
t_vocab m_vocab;
184+
181185
// containers for primitive data that does not need transformation into
182186
// abstractions
187+
183188
std::vector<std::string> m_row_pivots;
184189
std::vector<std::string> m_column_pivots;
185190
tsl::ordered_map<std::string, std::vector<std::string>> m_aggregates;

rust/bootstrap-runtime/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,16 @@ use alloc::vec::Vec;
3737

3838
use zune_inflate::DeflateDecoder;
3939

40+
const HEAP_SIZE: usize = if cfg!(debug_assertions) {
41+
512_000_000
42+
} else {
43+
64_000_000
44+
};
45+
4046
#[allow(unused_unsafe)]
4147
#[global_allocator]
4248
static ALLOCATOR: talc::Talck<talc::locking::AssumeUnlockable, talc::ClaimOnOom> = {
43-
static mut MEMORY: [u8; 64000000] = [0; 64000000];
49+
static mut MEMORY: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
4450
let span = unsafe { talc::Span::from_const_array(core::ptr::addr_of!(MEMORY)) };
4551
talc::Talc::new(unsafe { talc::ClaimOnOom::new(span) }).lock()
4652
};

rust/perspective-js/test/js/filters.spec.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,29 @@ const datetime_data_local = [
314314
table.delete();
315315
});
316316

317+
test("y == 'abcdefghijklmnopqrstuvwxyz' (interned)", async function () {
318+
const data = [
319+
{ x: 1, y: "a", z: true },
320+
{ x: 2, y: "b", z: false },
321+
{ x: 3, y: "c", z: true },
322+
{
323+
x: 4,
324+
y: "abcdefghijklmnopqrstuvwxyz",
325+
z: false,
326+
},
327+
];
328+
329+
const table = await perspective.table(data);
330+
const view = await table.view({
331+
filter: [["y", "==", "abcdefghijklmnopqrstuvwxyz"]],
332+
});
333+
334+
const json = await view.to_json();
335+
expect(json).toEqual([data[3]]);
336+
view.delete();
337+
table.delete();
338+
});
339+
317340
test("z == true", async function () {
318341
var table = await perspective.table(data);
319342
var view = await table.view({
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
10+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12+
13+
import { test, expect } from "@finos/perspective-test";
14+
import perspective from "./perspective_client";
15+
16+
((perspective) => {
17+
test.describe("View config", function () {
18+
test("Non-interned filter strings do not create corrupted view configs", async function () {
19+
const data = [
20+
{ x: 1, y: "a", z: true },
21+
{ x: 2, y: "b", z: false },
22+
{ x: 3, y: "c", z: true },
23+
{
24+
x: 4,
25+
y: "abcdefghijklmnopqrstuvwxyz",
26+
z: false,
27+
},
28+
];
29+
30+
const table = await perspective.table(data);
31+
const view = await table.view({
32+
filter: [["y", "==", "abcdefghijklmnopqrstuvwxyz"]],
33+
});
34+
35+
const config = await view.get_config();
36+
expect(config.filter).toEqual([
37+
["y", "==", "abcdefghijklmnopqrstuvwxyz"],
38+
]);
39+
40+
view.delete();
41+
table.delete();
42+
});
43+
});
44+
})(perspective);

0 commit comments

Comments
 (0)