From 732b7614b62a39f9de40a42d2baee68b122b8ee0 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Wed, 23 Apr 2025 21:53:24 -0400 Subject: [PATCH 1/4] Partial revert #2972, #2964 Signed-off-by: Andrew Stein --- cpp/perspective/src/cpp/base.cpp | 13 -- cpp/perspective/src/cpp/context_zero.cpp | 16 +- cpp/perspective/src/cpp/data_table.cpp | 17 +- cpp/perspective/src/cpp/flat_traversal.cpp | 22 --- cpp/perspective/src/cpp/gnode.cpp | 25 +-- cpp/perspective/src/cpp/gnode_state.cpp | 113 ++++-------- cpp/perspective/src/cpp/server.cpp | 8 +- cpp/perspective/src/cpp/table.cpp | 22 +-- .../src/include/perspective/base.h | 14 +- .../src/include/perspective/data_table.h | 173 +++++++----------- .../src/include/perspective/flat_traversal.h | 10 - .../src/include/perspective/gnode.h | 18 +- .../src/include/perspective/gnode_state.h | 12 +- .../src/include/perspective/scalar.h | 4 +- 14 files changed, 135 insertions(+), 332 deletions(-) diff --git a/cpp/perspective/src/cpp/base.cpp b/cpp/perspective/src/cpp/base.cpp index b206fdf05e..985f160cf1 100644 --- a/cpp/perspective/src/cpp/base.cpp +++ b/cpp/perspective/src/cpp/base.cpp @@ -799,19 +799,6 @@ type_to_dtype() { return DTYPE_OBJECT; } -std::ostream& -operator<<(std::ostream& os, const t_op& op) { -#define X(NAME) \ - case NAME: \ - os << #NAME; \ - break; - - switch (op) { FOREACH_T_OP(X) } -#undef X - - return os; -} - } // end namespace perspective namespace std { diff --git a/cpp/perspective/src/cpp/context_zero.cpp b/cpp/perspective/src/cpp/context_zero.cpp index 6a0fed23f3..c038eece4d 100644 --- a/cpp/perspective/src/cpp/context_zero.cpp +++ b/cpp/perspective/src/cpp/context_zero.cpp @@ -10,8 +10,6 @@ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -#include "perspective/base.h" -#include "perspective/raw_types.h" #include #include #include @@ -103,7 +101,6 @@ t_ctx0::notify( flattened.get_const_column("psp_pkey"); std::shared_ptr op_sptr = flattened.get_const_column("psp_op"); - auto old_pkey_col = flattened.get_column("psp_old_pkey"); const t_column* pkey_col = pkey_sptr.get(); const t_column* op_col = op_sptr.get(); @@ -176,20 +173,11 @@ t_ctx0::notify( m_symtable.get_interned_tscalar(pkey_col->get_scalar(idx)); std::uint8_t op_ = *(op_col->get_nth(idx)); t_op op = static_cast(op_); - const auto existed = *(existed_col->get_nth(idx)); - const auto old_pkey = old_pkey_col->get_scalar(idx); + bool existed = *(existed_col->get_nth(idx)); switch (op) { case OP_INSERT: { - if (old_pkey.is_valid()) { - m_traversal->move_row( - *m_gstate, - *(m_expression_tables->m_master), - m_config, - old_pkey, - pkey - ); - } else if (existed) { + if (existed) { m_traversal->update_row( *m_gstate, *(m_expression_tables->m_master), diff --git a/cpp/perspective/src/cpp/data_table.cpp b/cpp/perspective/src/cpp/data_table.cpp index 15da265b8a..272b2b91cf 100644 --- a/cpp/perspective/src/cpp/data_table.cpp +++ b/cpp/perspective/src/cpp/data_table.cpp @@ -23,12 +23,6 @@ #include #include namespace perspective { -std::ostream& -operator<<(std::ostream& os, const t_flatten_record& fr) { - os << "store_idx: " << fr.m_store_idx << ", bidx: " << fr.m_begin_idx - << ", eidx: " << fr.m_edge_idx; - return os; -} void t_data_table::set_capacity(t_uindex idx) { @@ -325,7 +319,7 @@ t_data_table::get_schema() const { } std::shared_ptr -t_data_table::flatten(t_uindex limit) const { +t_data_table::flatten() const { PSP_TRACE_SENTINEL(); PSP_VERBOSE_ASSERT(m_init, "touching uninited object"); PSP_VERBOSE_ASSERT(is_pkey_table(), "Not a pkeyed table"); @@ -333,7 +327,7 @@ t_data_table::flatten(t_uindex limit) const { "", "", m_schema, DEFAULT_EMPTY_CAPACITY, BACKING_STORE_MEMORY ); flattened->init(); - flatten_body>(flattened, limit); + flatten_body>(flattened); return flattened; } @@ -641,13 +635,6 @@ t_data_table::join(const std::shared_ptr& other_table) const { PSP_VERBOSE_ASSERT(m_init, "touching uninited object"); if (size() != other_table->size()) { -#if PSP_DEBUG - LOG_DEBUG("Joining current table:"); - pprint(); - LOG_DEBUG("on this this table:"); - other_table->pprint(); -#endif - std::stringstream ss; ss << "[t_data_table::join] Cannot join two tables of unequal sizes! " "Current size: " diff --git a/cpp/perspective/src/cpp/flat_traversal.cpp b/cpp/perspective/src/cpp/flat_traversal.cpp index 0a29f5c984..ed624fe874 100644 --- a/cpp/perspective/src/cpp/flat_traversal.cpp +++ b/cpp/perspective/src/cpp/flat_traversal.cpp @@ -388,28 +388,6 @@ t_ftrav::delete_row(t_tscalar pkey) { ++m_step_deletes; } -void -t_ftrav::move_row( - const t_gstate& gstate, - const t_data_table& expression_master_table, - const t_config& config, - t_tscalar old_pkey, - t_tscalar new_pkey -) { - auto old_pkiter = m_pkeyidx.find(old_pkey); - bool old_pkey_existed = old_pkiter != m_pkeyidx.end(); - if (!old_pkey_existed) { - LOG_DEBUG("Tried to move pkey that doesn't exist: " << old_pkey); - return; - } - LOG_DEBUG("Moving pkey from: " << old_pkey << " to: " << new_pkey); - - (*m_index)[old_pkiter->second].m_deleted = true; - t_mselem mselem; - fill_sort_elem(gstate, expression_master_table, config, new_pkey, mselem); - m_new_elems[new_pkey] = mselem; -} - std::vector t_ftrav::get_sort_by() const { return m_sortby; diff --git a/cpp/perspective/src/cpp/gnode.cpp b/cpp/perspective/src/cpp/gnode.cpp index c80210ddcb..e1292e4bad 100644 --- a/cpp/perspective/src/cpp/gnode.cpp +++ b/cpp/perspective/src/cpp/gnode.cpp @@ -10,7 +10,6 @@ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -#include "perspective/raw_types.h" #include #include #include @@ -49,9 +48,7 @@ calc_negate(t_tscalar val) { return val.negate(); } -t_gnode::t_gnode( - t_schema input_schema, t_schema output_schema, t_uindex limit -) : +t_gnode::t_gnode(t_schema input_schema, t_schema output_schema) : m_mode(NODE_PROCESSING_SIMPLE_DATAFLOW) #ifdef PSP_PARALLEL_FOR , @@ -63,7 +60,6 @@ t_gnode::t_gnode( m_output_schema(std::move(output_schema)), m_init(false), m_id(0), - m_limit(limit), m_last_input_port_id(0), m_pool_cleanup([]() {}) { PSP_TRACE_SENTINEL(); @@ -89,10 +85,6 @@ t_gnode::t_gnode( existed_schema }; m_epoch = std::chrono::high_resolution_clock::now(); - - m_input_schema.add_column( - "psp_old_pkey", m_input_schema.get_dtype("psp_pkey") - ); } t_gnode::~t_gnode() { @@ -105,8 +97,7 @@ void t_gnode::init() { PSP_TRACE_SENTINEL(); - m_gstate = - std::make_shared(m_input_schema, m_output_schema, m_limit); + m_gstate = std::make_shared(m_input_schema, m_output_schema); m_gstate->init(); // Create and store the main input port, which is always port 0. The next @@ -132,7 +123,7 @@ t_gnode::init() { for (const auto& iter : m_input_ports) { std::shared_ptr input_port = iter.second; - input_port->get_table()->flatten(m_limit); + input_port->get_table()->flatten(); } // Initialize expression-related state @@ -307,22 +298,16 @@ t_gnode::_process_table(t_uindex port_id) { } m_was_updated = true; - flattened = input_port->get_table()->flatten(m_limit); + flattened = input_port->get_table()->flatten(); PSP_GNODE_VERIFY_TABLE(flattened); PSP_GNODE_VERIFY_TABLE(get_table()); t_uindex flattened_num_rows = flattened->num_rows(); + std::vector row_lookup(flattened_num_rows); t_column* pkey_col = flattened->get_column("psp_pkey").get(); -#if PSP_DEBUG - LOG_DEBUG("m_mapping"); - for (const auto [k, v] : m_gstate->get_pkey_map()) { - LOG_DEBUG("KEY: " << k << " , VALUE: " << v); - } -#endif - for (t_uindex idx = 0; idx < flattened_num_rows; ++idx) { // See if each primary key in flattened already exist in the dataset t_tscalar pkey = pkey_col->get_scalar(idx); diff --git a/cpp/perspective/src/cpp/gnode_state.cpp b/cpp/perspective/src/cpp/gnode_state.cpp index 42c34d25f8..d03433b3ab 100644 --- a/cpp/perspective/src/cpp/gnode_state.cpp +++ b/cpp/perspective/src/cpp/gnode_state.cpp @@ -10,9 +10,6 @@ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -#include "perspective/raw_types.h" -#include -#include #include #include #include @@ -27,15 +24,10 @@ namespace perspective { -t_gstate::t_gstate( - t_schema input_schema, t_schema output_schema, t_uindex limit -) : +t_gstate::t_gstate(t_schema input_schema, t_schema output_schema) : m_input_schema(std::move(input_schema)), m_output_schema(std::move(output_schema)), - m_init(false), - m_limit(limit) - -{ + m_init(false) { LOG_CONSTRUCTOR("t_gstate"); } @@ -109,22 +101,21 @@ t_gstate::lookup_or_create(const t_tscalar& pkey) { return idx; } - t_uindex next_idx_original = m_table->size(); - t_uindex next_idx = next_idx_original % m_limit; - - if (next_idx + 1 <= m_limit) { - if (next_idx >= m_table->get_capacity() - 1) { - m_table->reserve(std::max( - (next_idx + 1), - static_cast( - m_table->get_capacity() * PSP_TABLE_GROW_RATIO - ) - )); - } - m_table->set_size(std::max(m_table->size() + 1, next_idx + 1)); + t_uindex nrows = m_table->num_rows(); + if (nrows >= m_table->get_capacity() - 1) { + m_table->reserve(std::max( + nrows + 1, + static_cast( + m_table->get_capacity() * PSP_TABLE_GROW_RATIO + ) + )); } - m_mapping[pkey_] = next_idx; - return next_idx_original; + + m_table->set_size(nrows + 1); + m_opcol->set_nth(nrows, OP_INSERT); + m_pkcol->set_scalar(nrows, pkey); + m_mapping[pkey_] = nrows; + return nrows; } void @@ -162,9 +153,8 @@ t_gstate::fill_master_table(const t_data_table* flattened) { m_pkcol = master_table->get_column("psp_pkey"); m_opcol = master_table->get_column("psp_op"); - master_table->set_capacity(std::min(flattened->get_capacity(), m_limit + 1) - ); - master_table->set_size(std::min(flattened->size(), m_limit + 1)); + master_table->set_capacity(flattened->get_capacity()); + master_table->set_size(flattened->size()); for (t_uindex idx = 0, loop_end = flattened->num_rows(); idx < loop_end; ++idx) { @@ -175,13 +165,12 @@ t_gstate::fill_master_table(const t_data_table* flattened) { switch (op) { case OP_INSERT: { // Write new primary keys into `m_mapping` - m_mapping[m_symtable.get_interned_tscalar(pkey)] = - idx % m_limit; - m_opcol->set_nth(idx % m_limit, OP_INSERT); - m_pkcol->set_scalar(idx % m_limit, pkey); + m_mapping[m_symtable.get_interned_tscalar(pkey)] = idx; + m_opcol->set_nth(idx, OP_INSERT); + m_pkcol->set_scalar(idx, pkey); } break; case OP_DELETE: { - _mark_deleted(idx % m_limit); + _mark_deleted(idx); } break; default: { PSP_COMPLAIN_AND_ABORT("Unexpected OP"); @@ -189,14 +178,6 @@ t_gstate::fill_master_table(const t_data_table* flattened) { } } -#if PSP_DEBUG - LOG_DEBUG("Flattened"); - flattened->pprint(); - - LOG_DEBUG("Master"); - m_table->pprint(); -#endif - #ifdef PSP_TABLE_VERIFY master_table->verify(); #endif @@ -212,43 +193,28 @@ t_gstate::update_master_table(const t_data_table* flattened) { // Update existing `m_table` const t_column* flattened_pkey_col = flattened->get_const_column("psp_pkey").get(); - t_column* flattened_old_pkey_col = - flattened->get_column("psp_old_pkey").get(); const t_column* flattened_op_col = flattened->get_const_column("psp_op").get(); t_data_table* master_table = m_table.get(); - std::vector master_table_indexes( - std::min(flattened->num_rows(), m_limit) - ); + std::vector master_table_indexes(flattened->num_rows()); - for (t_uindex flattened_idx = 0, loop_end = flattened->num_rows(); - flattened_idx < loop_end; - ++flattened_idx) { - t_tscalar pkey = flattened_pkey_col->get_scalar(flattened_idx); - const auto* op_ptr = - flattened_op_col->get_nth(flattened_idx); + for (t_uindex idx = 0, loop_end = flattened->num_rows(); idx < loop_end; + ++idx) { + t_tscalar pkey = flattened_pkey_col->get_scalar(idx); + const auto* op_ptr = flattened_op_col->get_nth(idx); t_op op = static_cast(*op_ptr); switch (op) { case OP_INSERT: { // Lookup/create the row index in `m_table` based on pkey - const auto new_idx = lookup_or_create(pkey); - master_table_indexes[flattened_idx % m_limit] = - new_idx % m_limit; - - if (new_idx >= m_limit - && m_pkcol->is_valid(new_idx % m_limit)) { - const auto old = m_pkcol->get_scalar(new_idx % m_limit); - m_mapping.erase(old); - flattened_old_pkey_col->set_scalar(flattened_idx, old); - flattened_old_pkey_col->set_valid(flattened_idx, true); - LOG_DEBUG("DELETING OLD PKEY: " << old); - } + master_table_indexes[idx] = lookup_or_create(pkey); // Write the op and pkey to `m_table` - m_opcol->set_nth(new_idx % m_limit, OP_INSERT); - m_pkcol->set_scalar(new_idx % m_limit, pkey); + m_opcol->set_nth( + master_table_indexes[idx], OP_INSERT + ); + m_pkcol->set_scalar(master_table_indexes[idx], pkey); } break; case OP_DELETE: { // Erase the pkey from the master table, but this does not @@ -261,13 +227,9 @@ t_gstate::update_master_table(const t_data_table* flattened) { } } - m_table->set_size(std::min(m_table->size(), m_limit)); - const t_schema& master_schema = m_table->get_schema(); t_uindex ncols = master_table->num_columns(); - LOG_DEBUG("Master Table Indices: " << master_table_indexes); - parallel_for( int(ncols), [flattened, @@ -284,24 +246,15 @@ t_gstate::update_master_table(const t_data_table* flattened) { if (!flattened_column) { return; } - update_master_column( master_column, flattened_column.get(), flattened_op_col, master_table_indexes, - std::min(flattened->num_rows(), m_limit) + flattened->num_rows() ); } ); - -#if PSP_DEBUG - LOG_DEBUG("Flattened"); - flattened->pprint(); - - LOG_DEBUG("Master"); - m_table->pprint(); -#endif } void diff --git a/cpp/perspective/src/cpp/server.cpp b/cpp/perspective/src/cpp/server.cpp index 20619e2745..afc3e20155 100644 --- a/cpp/perspective/src/cpp/server.cpp +++ b/cpp/perspective/src/cpp/server.cpp @@ -2141,11 +2141,11 @@ ProtoServer::_handle_request(std::uint32_t client_id, Request&& req) { auto tm = scalar.get(); std::stringstream ss; ss << std::setfill('0') << std::setw(4) << tm.year() + << "-" << std::setfill('0') << std::setw(2) + // Increment month by 1, as date::month is [1-12] but + // t_date::month() is [0-11] + << tm.month() + 1 << "-" << std::setfill('0') - << std::setw(2) - // Increment month by 1, as date::month is [1-12] - // but t_date::month() is [0-11] - << tm.month() + 1 << "-" << std::setfill('0') << std::setw(2) << tm.day(); s->set_string(ss.str()); break; diff --git a/cpp/perspective/src/cpp/table.cpp b/cpp/perspective/src/cpp/table.cpp index 8e7fcc92c6..585dc1c9e9 100644 --- a/cpp/perspective/src/cpp/table.cpp +++ b/cpp/perspective/src/cpp/table.cpp @@ -182,7 +182,7 @@ Table::validate_expressions( std::shared_ptr Table::make_gnode(const t_schema& in_schema) { t_schema out_schema = in_schema.drop({"psp_pkey", "psp_op"}); - auto gnode = std::make_shared(in_schema, out_schema, m_limit); + auto gnode = std::make_shared(in_schema, out_schema); gnode->init(); return gnode; } @@ -226,7 +226,7 @@ Table::remove_port(t_uindex port_id) const { void Table::calculate_offset(std::uint32_t row_count) { - m_offset = m_offset + row_count; + m_offset = (m_offset + row_count) % m_limit; } t_uindex @@ -948,7 +948,7 @@ Table::update_cols(const std::string_view& data, std::uint32_t port_id) { if (is_implicit && !document.GetObj().HasMember("__INDEX__")) { for (std::uint32_t ii = 0; ii < nrows; ii++) { - psp_pkey_col->set_nth(ii, m_offset + ii); + psp_pkey_col->set_nth(ii, (m_offset + ii) % m_limit); } } @@ -1088,8 +1088,8 @@ Table::from_cols( if (is_implicit) { for (t_uindex ii = 0; ii < nrows; ii++) { - psp_pkey_col->set_nth(ii, ii); - psp_okey_col->set_nth(ii, ii); + psp_pkey_col->set_nth(ii, ii % limit); + psp_okey_col->set_nth(ii, ii % limit); } } @@ -1158,7 +1158,7 @@ Table::update_rows(const std::string_view& data, std::uint32_t port_id) { // 3.) Fill table for (const auto& row : document.GetArray()) { if (is_implicit) { - psp_pkey_col->set_nth(ii, ii + m_offset); + psp_pkey_col->set_nth(ii, (ii + m_offset) % m_limit); } // col_count = m_column_names.size(); @@ -1336,8 +1336,8 @@ Table::from_rows( } if (is_implicit) { - psp_pkey_col->set_nth(ii, ii); - psp_okey_col->set_nth(ii, ii); + psp_pkey_col->set_nth(ii, ii % limit); + psp_okey_col->set_nth(ii, ii % limit); } ii++; @@ -1408,7 +1408,7 @@ Table::update_ndjson(const std::string_view& data, std::uint32_t port_id) { bool is_finished = false; while (!is_finished) { if (is_implicit) { - psp_pkey_col->set_nth(ii, ii + m_offset); + psp_pkey_col->set_nth(ii, (ii + m_offset) % m_limit); } for (const auto& it : document.GetObj()) { @@ -1588,8 +1588,8 @@ Table::from_ndjson( } if (is_implicit) { - psp_pkey_col->set_nth(ii, ii); - psp_okey_col->set_nth(ii, ii); + psp_pkey_col->set_nth(ii, ii % limit); + psp_okey_col->set_nth(ii, ii % limit); } ii++; diff --git a/cpp/perspective/src/include/perspective/base.h b/cpp/perspective/src/include/perspective/base.h index 9b3029d318..9e47ab81aa 100644 --- a/cpp/perspective/src/include/perspective/base.h +++ b/cpp/perspective/src/include/perspective/base.h @@ -12,7 +12,6 @@ #pragma once -#include #ifdef WIN32 #ifndef NOMINMAX #define NOMINMAX @@ -311,16 +310,7 @@ enum t_ctx_type { GROUPED_COLUMNS_CONTEXT }; -#define FOREACH_T_OP(X) \ - X(OP_INSERT) \ - X(OP_DELETE) \ - X(OP_CLEAR) - -#define X(NAME) NAME, -enum t_op { FOREACH_T_OP(X) }; -#undef X - -std::ostream& operator<<(std::ostream& os, const t_op& op); +enum t_op { OP_INSERT, OP_DELETE, OP_CLEAR }; enum t_value_transition { VALUE_TRANSITION_EQ_FF, // Value did not change, and row remains invalid @@ -465,7 +455,7 @@ struct PERSPECTIVE_EXPORT t_cmp_charptr { bool operator()(const char* a, const char* b) const { return std::strcmp(a, b) < 0; - } // namespace perspective + } }; template diff --git a/cpp/perspective/src/include/perspective/data_table.h b/cpp/perspective/src/include/perspective/data_table.h index 4d8cd1b6f7..b9bd9b02c8 100644 --- a/cpp/perspective/src/include/perspective/data_table.h +++ b/cpp/perspective/src/include/perspective/data_table.h @@ -11,7 +11,6 @@ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ #pragma once -#include "perspective/raw_types.h" #include #include #include @@ -34,23 +33,12 @@ struct t_rowpack { t_op m_op; }; -template -std::ostream& -operator<<(std::ostream& os, const t_rowpack& fr) { - os << "t_rowpack { m_pkey: " << fr.m_pkey - << ", m_pkey_is_valid: " << fr.m_pkey_is_valid << ", m_idx: " << fr.m_idx - << ", m_op: " << fr.m_op << "}"; - return os; -} - struct t_flatten_record { t_uindex m_store_idx; - t_uindex m_begin_idx; - t_uindex m_edge_idx; + t_uindex m_bidx; + t_uindex m_eidx; }; -std::ostream& operator<<(std::ostream& os, const t_flatten_record& fr); - class t_data_table; class PERSPECTIVE_EXPORT t_tabular {}; @@ -139,7 +127,7 @@ class PERSPECTIVE_EXPORT t_data_table { t_column* _get_column(std::string_view colname); - std::shared_ptr flatten(t_uindex limit) const; + std::shared_ptr flatten() const; bool is_pkey_table() const; bool is_same_shape(t_data_table& tbl) const; @@ -243,10 +231,10 @@ class PERSPECTIVE_EXPORT t_data_table { protected: template - void flatten_body(FLATTENED_T flattened, t_uindex limit) const; + void flatten_body(FLATTENED_T flattened) const; template - void flatten_helper_1(FLATTENED_T flattened, t_uindex limit) const; + void flatten_helper_1(FLATTENED_T flattened) const; template void flatten_helper_2( @@ -273,7 +261,7 @@ operator==(const t_data_table& lhs, const t_data_table& rhs); template void -t_data_table::flatten_body(FLATTENED_T flattened, t_uindex limit) const { +t_data_table::flatten_body(FLATTENED_T flattened) const { PSP_TRACE_SENTINEL(); PSP_VERBOSE_ASSERT(m_init, "touching uninited object"); PSP_VERBOSE_ASSERT(is_pkey_table(), "Not a pkeyed table"); @@ -281,43 +269,43 @@ t_data_table::flatten_body(FLATTENED_T flattened, t_uindex limit) const { t_dtype pkey_dtype = get_const_column("psp_pkey")->get_dtype(); switch (pkey_dtype) { case DTYPE_INT64: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_INT32: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_INT16: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_INT8: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_UINT64: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_UINT32: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_UINT16: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_UINT8: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_TIME: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_DATE: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_STR: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_FLOAT64: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; case DTYPE_FLOAT32: { - flatten_helper_1(flattened, limit); + flatten_helper_1(flattened); } break; default: { std::stringstream ss; @@ -336,28 +324,27 @@ void t_data_table::flatten_helper_2( ROWPACK_VEC_T& sorted, std::vector& fltrecs, - const t_column* source_col, - t_column* dest_col + const t_column* scol, + t_column* dcol ) const { for (const auto& rec : fltrecs) { - bool should_write = false; + bool added = false; t_index fragidx = 0; t_status status = STATUS_INVALID; - for (t_index spanidx = rec.m_edge_idx - 1; - spanidx >= t_index(rec.m_begin_idx); + for (t_index spanidx = rec.m_eidx - 1; spanidx >= t_index(rec.m_bidx); --spanidx) { const auto& sort_rec = sorted[spanidx]; fragidx = sort_rec.m_idx; - status = *(source_col->get_nth_status(fragidx)); + status = *(scol->get_nth_status(fragidx)); if (status != STATUS_INVALID) { - should_write = true; + added = true; break; } } - if (should_write) { - dest_col->set_nth( - rec.m_store_idx, *(source_col->get_nth(fragidx)), status + if (added) { + dcol->set_nth( + rec.m_store_idx, *(scol->get_nth(fragidx)), status ); } } @@ -365,9 +352,8 @@ t_data_table::flatten_helper_2( template void -t_data_table::flatten_helper_1(FLATTENED_T flattened, t_uindex limit) const { +t_data_table::flatten_helper_1(FLATTENED_T flattened) const { - // t_uindex frags_size = std::min(size(), limit); t_uindex frags_size = size(); PSP_VERBOSE_ASSERT(is_same_shape(*flattened), "Misaligned shaped found"); @@ -376,13 +362,13 @@ t_data_table::flatten_helper_1(FLATTENED_T flattened, t_uindex limit) const { return; } - std::vector source_columns; - std::vector dest_columns; + std::vector s_columns; + std::vector d_columns; for (const auto& colname : m_schema.m_columns) { if (colname != "psp_pkey" && colname != "psp_op") { - source_columns.push_back(get_const_column(colname).get()); - dest_columns.push_back(flattened->get_column(colname).get()); + s_columns.push_back(get_const_column(colname).get()); + d_columns.push_back(flattened->get_column(colname).get()); } } @@ -408,7 +394,7 @@ t_data_table::flatten_helper_1(FLATTENED_T flattened, t_uindex limit) const { operator()(const t_rowpack& a, const t_rowpack& b) const { return a.m_pkey < b.m_pkey - || (a.m_pkey == b.m_pkey && a.m_idx < b.m_idx); + || (!(b.m_pkey < a.m_pkey) && a.m_idx < b.m_idx); } }; @@ -418,9 +404,6 @@ t_data_table::flatten_helper_1(FLATTENED_T flattened, t_uindex limit) const { std::vector edges; edges.push_back(0); - // | pkey-1 | pkey-1 | pkey-2 | pkey-2 - // ^ Is this an edge? I think so. - // |-----------------| <- This is a span between those edges. for (t_index idx = 1, loop_end = sorted.size(); idx < loop_end; ++idx) { if ((sorted[idx].m_pkey_is_valid != sorted[idx - 1].m_pkey_is_valid) || (sorted[idx].m_pkey != sorted[idx - 1].m_pkey)) { @@ -434,147 +417,129 @@ t_data_table::flatten_helper_1(FLATTENED_T flattened, t_uindex limit) const { t_uindex store_idx = 0; - for (t_index frag_index = 0; frag_index < edges.size(); ++frag_index) { - t_index begin_edge_idx = edges[frag_index]; - bool edge_bool = frag_index == static_cast(edges.size() - 1); - t_index next_edge_idx = - edge_bool ? sorted.size() : edges[frag_index + 1]; + for (t_index fidx = 0, loop_end = edges.size(); fidx < loop_end; ++fidx) { + t_index bidx = edges[fidx]; + bool edge_bool = fidx == static_cast(edges.size() - 1); + t_index eidx = edge_bool ? sorted.size() : edges[fidx + 1]; bool delete_encountered = false; - for (t_index spanidx = begin_edge_idx; spanidx < next_edge_idx; - ++spanidx) { + for (t_index spanidx = bidx; spanidx < eidx; ++spanidx) { if (sorted[spanidx].m_op == OP_DELETE) { - begin_edge_idx = spanidx; + bidx = spanidx; delete_encountered = true; } } - const auto& sort_rec = sorted[begin_edge_idx]; + const auto& sort_rec = sorted[bidx]; if (delete_encountered) { - d_pkey_col->set_nth( - store_idx % limit, + d_pkey_col->push_back( sort_rec.m_pkey, sort_rec.m_pkey_is_valid ? t_status::STATUS_VALID : t_status::STATUS_INVALID ); std::uint8_t op8 = OP_DELETE; - d_op_col->set_nth(store_idx % limit, op8); + d_op_col->push_back(op8); ++store_idx; } - const auto single_element_span = (begin_edge_idx + 1 == next_edge_idx); - // if there are no deletes in the span, flatten. - // if there are deletes but the span is larger than 1 op, flatten. - if (!delete_encountered || !single_element_span) { + if (!delete_encountered || (bidx + 1 != eidx)) { t_flatten_record rec; - rec.m_store_idx = store_idx % limit; - rec.m_begin_idx = begin_edge_idx; - rec.m_edge_idx = next_edge_idx; + rec.m_store_idx = store_idx; + rec.m_bidx = bidx; + rec.m_eidx = eidx; fltrecs.push_back(rec); - d_pkey_col->set_nth( - store_idx % limit, + d_pkey_col->push_back( sort_rec.m_pkey, sort_rec.m_pkey_is_valid ? t_status::STATUS_VALID : t_status::STATUS_INVALID ); std::uint8_t op8 = OP_INSERT; - d_op_col->set_nth(store_idx % limit, op8); + d_op_col->push_back(op8); ++store_idx; } } - flattened->set_size(std::min(store_idx, limit)); - t_uindex ndata_cols = dest_columns.size(); - -#if PSP_DEBUG - LOG_DEBUG("sorted: "); - for (const auto& sort : sorted) { - LOG_DEBUG(sort); - } - LOG_DEBUG("fltrecs: "); - for (const auto& fltrec : fltrecs) { - LOG_DEBUG(fltrec); - } -#endif + flattened->set_size(store_idx); + t_uindex ndata_cols = d_columns.size(); parallel_for( int(ndata_cols), - [&source_columns, &sorted, &dest_columns, &fltrecs, this](int colidx) { - const auto* source_col = source_columns[colidx]; - auto* dest_col = dest_columns[colidx]; + [&s_columns, &sorted, &d_columns, &fltrecs, this](int colidx) { + auto scol = s_columns[colidx]; + auto dcol = d_columns[colidx]; - switch (source_col->get_dtype()) { + switch (scol->get_dtype()) { case DTYPE_INT64: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_INT32: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_INT16: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_INT8: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_UINT64: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_UINT32: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_UINT16: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_UINT8: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_FLOAT64: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_FLOAT32: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_BOOL: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_TIME: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_DATE: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_STR: { this->flatten_helper_2( - sorted, fltrecs, source_col, dest_col + sorted, fltrecs, scol, dcol ); } break; case DTYPE_OBJECT: diff --git a/cpp/perspective/src/include/perspective/flat_traversal.h b/cpp/perspective/src/include/perspective/flat_traversal.h index f7221da621..0b10ecd84c 100644 --- a/cpp/perspective/src/include/perspective/flat_traversal.h +++ b/cpp/perspective/src/include/perspective/flat_traversal.h @@ -117,16 +117,6 @@ class PERSPECTIVE_EXPORT t_ftrav { void delete_row(t_tscalar pkey); - // Moves a row under a new primary key and deletes references to old primary - // key. - void move_row( - const t_gstate& gstate, - const t_data_table& expression_master_table, - const t_config& config, - t_tscalar old_pkey, - t_tscalar new_pkey - ); - std::vector get_sort_by() const; bool empty_sort_by() const; diff --git a/cpp/perspective/src/include/perspective/gnode.h b/cpp/perspective/src/include/perspective/gnode.h index a73797ece9..5db5910a20 100644 --- a/cpp/perspective/src/include/perspective/gnode.h +++ b/cpp/perspective/src/include/perspective/gnode.h @@ -11,7 +11,6 @@ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ #pragma once -#include "perspective/raw_types.h" #include #include #include @@ -94,11 +93,7 @@ class PERSPECTIVE_EXPORT t_gnode { * @param input_schema * @param output_schema */ - t_gnode( - t_schema input_schema, - t_schema output_schema, - t_uindex limit = std::numeric_limits::max() - ); + t_gnode(t_schema input_schema, t_schema output_schema); ~t_gnode(); void init(); @@ -386,7 +381,6 @@ class PERSPECTIVE_EXPORT t_gnode { bool m_init; t_uindex m_id; - t_uindex m_limit; // Input ports mapped by integer id tsl::ordered_map> m_input_ports; @@ -517,18 +511,8 @@ t_gnode::update_context_from_state( // together and pass it to the context. std::shared_ptr ctx_expression_tables = ctx->get_expression_tables(); -#if PSP_DEBUG - LOG_DEBUG("FLATTENED"); - flattened->pprint(); - LOG_DEBUG("EXPRESSION_TABLE"); - ctx_expression_tables->m_flattened->pprint(); -#endif std::shared_ptr joined_flattened = flattened->join(ctx_expression_tables->m_flattened); -#if PSP_DEBUG - LOG_DEBUG("JOINED"); - joined_flattened->pprint(); -#endif ctx->notify(*joined_flattened); } else { // Just use the table from the gnode diff --git a/cpp/perspective/src/include/perspective/gnode_state.h b/cpp/perspective/src/include/perspective/gnode_state.h index 68d0b50ef7..52c797df31 100644 --- a/cpp/perspective/src/include/perspective/gnode_state.h +++ b/cpp/perspective/src/include/perspective/gnode_state.h @@ -31,8 +31,9 @@ class PERSPECTIVE_EXPORT t_gstate { /** * @brief A mapping of `t_tscalar` primary keys to `t_uindex` row indices. */ - using t_mapping = tsl::hopscotch_map; - using t_free_items = tsl::hopscotch_set; + typedef tsl::hopscotch_map t_mapping; + + typedef tsl::hopscotch_set t_free_items; /** * @brief Construct a new `t_gstate`, which manages the canonical state of @@ -46,11 +47,7 @@ class PERSPECTIVE_EXPORT t_gstate { * @param input_schema * @param output_schema */ - t_gstate( - t_schema input_schema, - t_schema output_schema, - t_uindex limit = std::numeric_limits::max() - ); + t_gstate(t_schema input_schema, t_schema output_schema); ~t_gstate(); @@ -292,7 +289,6 @@ class PERSPECTIVE_EXPORT t_gstate { t_schema m_output_schema; // tblschema bool m_init; - t_uindex m_limit; std::shared_ptr m_table; t_mapping m_mapping; t_free_items m_free; diff --git a/cpp/perspective/src/include/perspective/scalar.h b/cpp/perspective/src/include/perspective/scalar.h index 3ec1aac20d..b7591bb221 100644 --- a/cpp/perspective/src/include/perspective/scalar.h +++ b/cpp/perspective/src/include/perspective/scalar.h @@ -40,7 +40,7 @@ struct PERSPECTIVE_EXPORT t_const_char_comparator { COMPARER_T cmp; int cmpval = std::strcmp(s1, s2); return cmp(cmpval, 0); - } // namespace perspective + } }; #ifdef PSP_SSO_SCALAR @@ -202,7 +202,7 @@ struct PERSPECTIVE_EXPORT t_tscalar { t_tscalar coerce_numeric_dtype(t_dtype dtype) const; t_scalar_u m_data; - t_dtype m_type; + unsigned char m_type; t_status m_status; #ifdef PSP_SSO_SCALAR bool m_inplace; From 909b708978378a1898593ff8fc8899ed7f4a81a9 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Wed, 23 Apr 2025 21:51:01 -0400 Subject: [PATCH 2/4] Impl based on OP_DELETE Signed-off-by: Andrew Stein --- cpp/perspective/src/cpp/arrow_loader.cpp | 5 +- cpp/perspective/src/cpp/gnode.cpp | 32 ++++----- cpp/perspective/src/cpp/table.cpp | 68 ++++++++----------- .../src/include/perspective/arrow_loader.h | 2 - rust/perspective-js/test/js/updates.spec.js | 2 +- .../tests/table/test_table_limit.py | 14 +++- 6 files changed, 61 insertions(+), 62 deletions(-) diff --git a/cpp/perspective/src/cpp/arrow_loader.cpp b/cpp/perspective/src/cpp/arrow_loader.cpp index 961fc85f4c..d6ef38d572 100644 --- a/cpp/perspective/src/cpp/arrow_loader.cpp +++ b/cpp/perspective/src/cpp/arrow_loader.cpp @@ -236,7 +236,6 @@ ArrowLoader::fill_table( const t_schema& input_schema, const std::string& index, std::uint32_t offset, - std::uint32_t limit, bool is_update ) { bool implicit_index = false; @@ -280,8 +279,8 @@ ArrowLoader::fill_table( auto* okey_col = tbl.add_column("psp_okey", DTYPE_INT32, true); for (std::uint32_t ridx = 0; ridx < tbl.size(); ++ridx) { - key_col->set_nth(ridx, (ridx + offset) % limit); - okey_col->set_nth(ridx, (ridx + offset) % limit); + key_col->set_nth(ridx, (ridx + offset)); + okey_col->set_nth(ridx, (ridx + offset)); } } else { if (!input_schema.has_column(index)) { diff --git a/cpp/perspective/src/cpp/gnode.cpp b/cpp/perspective/src/cpp/gnode.cpp index e1292e4bad..5237c9099b 100644 --- a/cpp/perspective/src/cpp/gnode.cpp +++ b/cpp/perspective/src/cpp/gnode.cpp @@ -1202,10 +1202,10 @@ t_gnode::_compute_expressions( expression_regex_mapping ); ctx->get_expression_tables()->set_flattened( - m_gstate->get_pkeyed_table( - ctx->get_expression_tables()->m_master->get_schema(), - ctx->get_expression_tables()->m_master - ) + // m_gstate->get_pkeyed_table( + // ctx->get_expression_tables()->m_master->get_schema(), + ctx->get_expression_tables()->m_master + // ) ); } break; case ONE_SIDED_CONTEXT: { @@ -1217,10 +1217,10 @@ t_gnode::_compute_expressions( expression_regex_mapping ); ctx->get_expression_tables()->set_flattened( - m_gstate->get_pkeyed_table( - ctx->get_expression_tables()->m_master->get_schema(), - ctx->get_expression_tables()->m_master - ) + // m_gstate->get_pkeyed_table( + // ctx->get_expression_tables()->m_master->get_schema(), + ctx->get_expression_tables()->m_master + // ) ); } break; case ZERO_SIDED_CONTEXT: { @@ -1232,10 +1232,10 @@ t_gnode::_compute_expressions( expression_regex_mapping ); ctx->get_expression_tables()->set_flattened( - m_gstate->get_pkeyed_table( - ctx->get_expression_tables()->m_master->get_schema(), - ctx->get_expression_tables()->m_master - ) + // m_gstate->get_pkeyed_table( + // ctx->get_expression_tables()->m_master->get_schema(), + ctx->get_expression_tables()->m_master + // ) ); } break; case GROUPED_PKEY_CONTEXT: { @@ -1247,10 +1247,10 @@ t_gnode::_compute_expressions( expression_regex_mapping ); ctx->get_expression_tables()->set_flattened( - m_gstate->get_pkeyed_table( - ctx->get_expression_tables()->m_master->get_schema(), - ctx->get_expression_tables()->m_master - ) + // m_gstate->get_pkeyed_table( + // ctx->get_expression_tables()->m_master->get_schema(), + ctx->get_expression_tables()->m_master + // ) ); } break; case UNIT_CONTEXT: diff --git a/cpp/perspective/src/cpp/table.cpp b/cpp/perspective/src/cpp/table.cpp index 585dc1c9e9..ec3b4edf3e 100644 --- a/cpp/perspective/src/cpp/table.cpp +++ b/cpp/perspective/src/cpp/table.cpp @@ -226,7 +226,7 @@ Table::remove_port(t_uindex port_id) const { void Table::calculate_offset(std::uint32_t row_count) { - m_offset = (m_offset + row_count) % m_limit; + m_offset = m_offset + row_count; } t_uindex @@ -350,9 +350,7 @@ Table::update_csv(const std::string_view& data, std::uint32_t port_id) { t_data_table data_table(get_schema()); data_table.init(); data_table.extend(row_count); - arrow_loader.fill_table( - data_table, get_schema(), m_index, m_offset, m_limit, true - ); + arrow_loader.fill_table(data_table, get_schema(), m_index, m_offset, true); process_op_column(data_table, t_op::OP_INSERT); calculate_offset(row_count); m_pool->send(get_gnode()->get_id(), port_id, data_table); @@ -395,7 +393,7 @@ Table::from_csv( auto _ = std::move(data); auto loader = std::move(arrow_loader); data_table->extend(row_count); - loader.fill_table(*data_table, input_schema, index, 0, limit, false); + loader.fill_table(*data_table, input_schema, index, 0, false); } auto pool = std::make_shared(); pool->init(); @@ -948,7 +946,7 @@ Table::update_cols(const std::string_view& data, std::uint32_t port_id) { if (is_implicit && !document.GetObj().HasMember("__INDEX__")) { for (std::uint32_t ii = 0; ii < nrows; ii++) { - psp_pkey_col->set_nth(ii, (m_offset + ii) % m_limit); + psp_pkey_col->set_nth(ii, (m_offset + ii)); } } @@ -1088,8 +1086,8 @@ Table::from_cols( if (is_implicit) { for (t_uindex ii = 0; ii < nrows; ii++) { - psp_pkey_col->set_nth(ii, ii % limit); - psp_okey_col->set_nth(ii, ii % limit); + psp_pkey_col->set_nth(ii, ii); + psp_okey_col->set_nth(ii, ii); } } @@ -1158,7 +1156,7 @@ Table::update_rows(const std::string_view& data, std::uint32_t port_id) { // 3.) Fill table for (const auto& row : document.GetArray()) { if (is_implicit) { - psp_pkey_col->set_nth(ii, (ii + m_offset) % m_limit); + psp_pkey_col->set_nth(ii, (ii + m_offset)); } // col_count = m_column_names.size(); @@ -1199,23 +1197,7 @@ Table::update_rows(const std::string_view& data, std::uint32_t port_id) { } } - // // Check if this row "overflows", wrapping around due to a `m_limit` - // // value, as partial updates are not allowed in this case. - // if (!supports_partial && col_count != 0) { - // std::cout << col_count << std::endl; - // PSP_COMPLAIN_AND_ABORT( - // "Inconsistent row count in update - `Table` partial updates " - // "require an `index`" - // ); - // } - is_first_row = false; - if (ii + m_offset >= m_limit) { - for (auto& col_name : missing_columns) { - data_table.get_column(col_name)->unset(ii); - } - } - ii++; } @@ -1336,8 +1318,8 @@ Table::from_rows( } if (is_implicit) { - psp_pkey_col->set_nth(ii, ii % limit); - psp_okey_col->set_nth(ii, ii % limit); + psp_pkey_col->set_nth(ii, ii); + psp_okey_col->set_nth(ii, ii); } ii++; @@ -1408,7 +1390,7 @@ Table::update_ndjson(const std::string_view& data, std::uint32_t port_id) { bool is_finished = false; while (!is_finished) { if (is_implicit) { - psp_pkey_col->set_nth(ii, (ii + m_offset) % m_limit); + psp_pkey_col->set_nth(ii, (ii + m_offset)); } for (const auto& it : document.GetObj()) { @@ -1449,11 +1431,6 @@ Table::update_ndjson(const std::string_view& data, std::uint32_t port_id) { } is_first_row = false; - if (ii + m_offset >= m_limit) { - for (auto& col_name : missing_columns) { - data_table.get_column(col_name)->unset(ii); - } - } ii++; @@ -1588,8 +1565,8 @@ Table::from_ndjson( } if (is_implicit) { - psp_pkey_col->set_nth(ii, ii % limit); - psp_okey_col->set_nth(ii, ii % limit); + psp_pkey_col->set_nth(ii, ii); + psp_okey_col->set_nth(ii, ii); } ii++; @@ -1676,9 +1653,7 @@ Table::update_arrow(const std::string_view& data, std::uint32_t port_id) { } } - arrow_loader.fill_table( - data_table, input_schema, m_index, m_offset, m_limit, true - ); + arrow_loader.fill_table(data_table, input_schema, m_index, m_offset, true); process_op_column(data_table, t_op::OP_INSERT); calculate_offset(row_count); @@ -1722,7 +1697,7 @@ Table::from_arrow( auto loader = std::move(arrow_loader); auto row_count = loader.row_count(); data_table->extend(row_count); - loader.fill_table(*data_table, input_schema, index, 0, limit, false); + loader.fill_table(*data_table, input_schema, index, 0, false); } // Make Table @@ -1795,6 +1770,21 @@ Table::process_op_column(t_data_table& data_table, const t_op op) { } break; default: { op_col->raw_fill(OP_INSERT); + const auto size = data_table.size(); + if (m_offset + size >= m_limit) { + const auto& psp_pkey_col = data_table.get_column("psp_pkey"); + const auto d_rows = + size - std::max(0, m_limit - m_offset); + data_table.extend(size + d_rows); + auto* op_col = + data_table.add_column("psp_op", DTYPE_UINT8, false); + auto old_key = std::max(0, m_offset - m_limit); + for (auto i = 0; i < d_rows; i++) { + psp_pkey_col->set_nth(size + i, old_key); + op_col->set_nth(size + i, OP_DELETE); + old_key += 1; + } + } } } } diff --git a/cpp/perspective/src/include/perspective/arrow_loader.h b/cpp/perspective/src/include/perspective/arrow_loader.h index f0d4c4d972..87b3c4db5d 100644 --- a/cpp/perspective/src/include/perspective/arrow_loader.h +++ b/cpp/perspective/src/include/perspective/arrow_loader.h @@ -62,7 +62,6 @@ namespace apachearrow { * @param input_schema * @param index * @param offset - * @param limit * @param is_update */ void fill_table( @@ -70,7 +69,6 @@ namespace apachearrow { const t_schema& input_schema, const std::string& index, std::uint32_t offset, - std::uint32_t limit, bool is_update ); diff --git a/rust/perspective-js/test/js/updates.spec.js b/rust/perspective-js/test/js/updates.spec.js index 9d0058d78a..86ff46e678 100644 --- a/rust/perspective-js/test/js/updates.spec.js +++ b/rust/perspective-js/test/js/updates.spec.js @@ -3381,7 +3381,7 @@ async function match_delta(perspective, delta, expected) { ); for (let i = 0; i < 3; i++) { - await tbl.update({ + tbl.update({ index: ["a", "d", "b"], x: ["abc", "def", "acc"], }); diff --git a/rust/perspective-python/perspective/tests/table/test_table_limit.py b/rust/perspective-python/perspective/tests/table/test_table_limit.py index 7ae2de625c..c1bfd6b9cd 100644 --- a/rust/perspective-python/perspective/tests/table/test_table_limit.py +++ b/rust/perspective-python/perspective/tests/table/test_table_limit.py @@ -17,6 +17,18 @@ class TestTableInfer(object): + def test_table_limit_wraparound_does_not_respect_partial_none(self): + t = Table({"a": "float", "b": "float"}, limit=3) + t.update([{"a": 10}, {"b": 1}, {"a": 20}, {"a": None, "b": 2}]) + d1 = t.view().to_json() + + t2 = Table({"a": "float", "b": "float"}, limit=3) + t2.update([{"a": 10}, {"b": 1}, {"a": 20}, {"b": 2}]) + d2 = t2.view().to_json() + + assert d1[0] == d2[0] + assert d1[1:] == d2[1:] + def test_table_limit_wraparound_does_not_respect_partial(self): t = Table({"a": "float", "b": "float"}, limit=3) t.update([{"a": 10}, {"b": 1}, {"a": 20}, {"a": 10, "b": 2}]) @@ -26,7 +38,7 @@ def test_table_limit_wraparound_does_not_respect_partial(self): t2.update([{"a": 10}, {"b": 1}, {"a": 20}, {"b": 2}]) d2 = t2.view().to_columns() - assert d1 == d2 + assert d1 != d2 def test_table_limit_with_json(self): t = Table({"a": [1, 2, 3]}, limit=1) From 12d4a722522df7e2a9bdefd317c6fa4d86e570b9 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Thu, 24 Apr 2025 02:56:42 -0400 Subject: [PATCH 3/4] Handle errors in poll() Signed-off-by: Andrew Stein --- cpp/perspective/src/cpp/binding_api.cpp | 4 +- cpp/perspective/src/cpp/server.cpp | 57 ++++++++++++++++--- .../src/include/perspective/server.h | 2 +- rust/perspective-js/src/ts/wasm/engine.ts | 2 +- rust/perspective-server/src/ffi.rs | 6 +- rust/perspective-server/src/local_session.rs | 2 +- 6 files changed, 56 insertions(+), 17 deletions(-) diff --git a/cpp/perspective/src/cpp/binding_api.cpp b/cpp/perspective/src/cpp/binding_api.cpp index 40c08e36d3..5628d9c498 100644 --- a/cpp/perspective/src/cpp/binding_api.cpp +++ b/cpp/perspective/src/cpp/binding_api.cpp @@ -96,8 +96,8 @@ psp_handle_request( PERSPECTIVE_EXPORT EncodedApiEntries* -psp_poll(ProtoServer* server) { - auto responses = server->poll(); +psp_poll(ProtoServer* server, std::uint32_t client_id) { + auto responses = server->poll(client_id); return encode_api_responses(responses); } diff --git a/cpp/perspective/src/cpp/server.cpp b/cpp/perspective/src/cpp/server.cpp index afc3e20155..7180287b80 100644 --- a/cpp/perspective/src/cpp/server.cpp +++ b/cpp/perspective/src/cpp/server.cpp @@ -799,13 +799,52 @@ ProtoServer::handle_request( } std::vector> -ProtoServer::poll() { +ProtoServer::poll(std::uint32_t client_id) { std::vector> out; - for (auto& resp : _poll()) { + try { + const auto& responses = _poll(); + for (const auto& resp : responses) { + ProtoServerResp str_resp; + str_resp.data = resp.data.SerializeAsString(); + str_resp.client_id = resp.client_id; + out.emplace_back(str_resp); + } + + } catch (const PerspectiveException& e) { + proto::Response resp; + auto* err = resp.mutable_server_error()->mutable_message(); + *err = std::string(e.what()); + ProtoServerResp str_resp; + str_resp.data = resp.SerializeAsString(); + str_resp.client_id = client_id; + out.emplace_back(std::move(str_resp)); + } catch (const PerspectiveViewNotFoundException& e) { + proto::Response resp; + auto* err = resp.mutable_server_error(); + err->set_status_code(proto::StatusCode::VIEW_NOT_FOUND); + auto* msg = err->mutable_message(); + *msg = std::string(e.what()); + ProtoServerResp str_resp; + str_resp.data = resp.SerializeAsString(); + str_resp.client_id = client_id; + out.emplace_back(std::move(str_resp)); + } catch (const std::exception& e) { + proto::Response resp; + auto* err = resp.mutable_server_error()->mutable_message(); + *err = std::string(e.what()); + ProtoServerResp str_resp; + str_resp.data = resp.SerializeAsString(); + str_resp.client_id = client_id; + out.emplace_back(std::move(str_resp)); + } catch (...) { + proto::Response resp; + auto* err = resp.mutable_server_error()->mutable_message(); + std::exception_ptr p = std::current_exception(); + *err = "Unknown exception"; ProtoServerResp str_resp; - str_resp.data = resp.data.SerializeAsString(); - str_resp.client_id = resp.client_id; - out.emplace_back(str_resp); + str_resp.data = resp.SerializeAsString(); + str_resp.client_id = client_id; + out.emplace_back(std::move(str_resp)); } return out; @@ -2141,11 +2180,11 @@ ProtoServer::_handle_request(std::uint32_t client_id, Request&& req) { auto tm = scalar.get(); std::stringstream ss; ss << std::setfill('0') << std::setw(4) << tm.year() - << "-" << std::setfill('0') << std::setw(2) - // Increment month by 1, as date::month is [1-12] but - // t_date::month() is [0-11] - << tm.month() + 1 << "-" << std::setfill('0') + << std::setw(2) + // Increment month by 1, as date::month is [1-12] + // but t_date::month() is [0-11] + << tm.month() + 1 << "-" << std::setfill('0') << std::setw(2) << tm.day(); s->set_string(ss.str()); break; diff --git a/cpp/perspective/src/include/perspective/server.h b/cpp/perspective/src/include/perspective/server.h index 8d36ddc15a..d05195aa6b 100644 --- a/cpp/perspective/src/include/perspective/server.h +++ b/cpp/perspective/src/include/perspective/server.h @@ -625,7 +625,7 @@ namespace server { void close_session(std::uint32_t); std::vector> handle_request(std::uint32_t client_id, const std::string_view& data); - std::vector> poll(); + std::vector> poll(std::uint32_t client_id); private: void handle_process_table( diff --git a/rust/perspective-js/src/ts/wasm/engine.ts b/rust/perspective-js/src/ts/wasm/engine.ts index a035cebbca..4f4f077431 100644 --- a/rust/perspective-js/src/ts/wasm/engine.ts +++ b/rust/perspective-js/src/ts/wasm/engine.ts @@ -79,7 +79,7 @@ export class PerspectiveSession { } poll() { - const polled = this.mod._psp_poll(this.server as any); + const polled = this.mod._psp_poll(this.server as any, this.client_id); decode_api_responses(this.mod, polled, async (msg: ApiResponse) => { await this.client_map.get(msg.client_id)!(msg.data); }); diff --git a/rust/perspective-server/src/ffi.rs b/rust/perspective-server/src/ffi.rs index 7d004b5961..1aaa11a70a 100644 --- a/rust/perspective-server/src/ffi.rs +++ b/rust/perspective-server/src/ffi.rs @@ -35,7 +35,7 @@ unsafe extern "C" { buffer_ptr: *const u8, buffer_len: usize, ) -> ResponseBatch; - fn psp_poll(server: *const u8) -> ResponseBatch; + fn psp_poll(server: *const u8, client_id: u32) -> ResponseBatch; fn psp_close_session(server: *const u8, client_id: u32); } @@ -122,8 +122,8 @@ impl Server { unsafe { psp_handle_request(self.0, client_id, request.0, request.1) } } - pub fn poll(&self) -> ResponseBatch { - unsafe { psp_poll(self.0) } + pub fn poll(&self, client_id: u32) -> ResponseBatch { + unsafe { psp_poll(self.0, client_id) } } pub fn close_session(&self, session_id: u32) { diff --git a/rust/perspective-server/src/local_session.rs b/rust/perspective-server/src/local_session.rs index bdb4dc5569..f98f3f37d7 100644 --- a/rust/perspective-server/src/local_session.rs +++ b/rust/perspective-server/src/local_session.rs @@ -57,7 +57,7 @@ impl Session for LocalSession { } async fn poll(&self) -> Result<(), ServerError> { - let responses = self.server.server.poll(); + let responses = self.server.server.poll(self.id); for response in responses.iter_responses() { let cb = self .server From a7a9d1f9d17a39eafa9903eb7be184899ca3ed4e Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Thu, 24 Apr 2025 14:36:32 -0400 Subject: [PATCH 4/4] v3.6.0 Signed-off-by: Andrew Stein --- CHANGELOG.md | 8 ++++++++ Cargo.lock | 12 ++++++------ cpp/perspective/package.json | 2 +- docs/package.json | 2 +- examples/blocks/package.json | 2 +- examples/esbuild-example/package.json | 2 +- examples/esbuild-remote/package.json | 2 +- examples/python-aiohttp/package.json | 2 +- examples/python-starlette/package.json | 2 +- examples/python-tornado-streaming/package.json | 2 +- examples/python-tornado/package.json | 2 +- examples/react-example/package.json | 2 +- examples/rust-axum/Cargo.toml | 2 +- examples/rust-axum/package.json | 2 +- examples/vite-example/package.json | 2 +- examples/webpack-example/package.json | 2 +- package.json | 2 +- packages/perspective-cli/package.json | 2 +- packages/perspective-jupyterlab/package.json | 2 +- packages/perspective-viewer-d3fc/package.json | 2 +- packages/perspective-viewer-datagrid/package.json | 2 +- packages/perspective-viewer-openlayers/package.json | 2 +- packages/perspective-workspace/package.json | 2 +- rust/perspective-client/Cargo.toml | 2 +- rust/perspective-client/package.json | 2 +- rust/perspective-js/Cargo.toml | 4 ++-- rust/perspective-js/package.json | 2 +- rust/perspective-python/Cargo.toml | 6 +++--- rust/perspective-python/package.json | 2 +- rust/perspective-python/perspective/__init__.py | 2 +- rust/perspective-python/pyproject.toml | 2 +- rust/perspective-server/Cargo.toml | 4 ++-- rust/perspective-viewer/Cargo.toml | 6 +++--- rust/perspective-viewer/package.json | 2 +- rust/perspective/Cargo.toml | 6 +++--- rust/perspective/package.json | 2 +- tools/perspective-bench/basic_suite.mjs | 2 +- tools/perspective-esbuild-plugin/package.json | 2 +- tools/perspective-scripts/package.json | 2 +- tools/perspective-test/package.json | 2 +- 40 files changed, 60 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a347c28ba4..887b254186 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [v3.6.0](https://github.com/finos/perspective/releases/tag/v3.6.0) + +_24 April 2025_ ([Full changelog](https://github.com/finos/perspective/compare/v3.5.1...v3.6.0)) + +**Breaking** + +- Fix `limit` overflow bug [#2983](https://github.com/finos/perspective/pull/2983) + # [v3.5.1](https://github.com/finos/perspective/releases/tag/v3.5.1) _11 April 2025_ ([Full changelog](https://github.com/finos/perspective/compare/v3.5.0...v3.5.1)) diff --git a/Cargo.lock b/Cargo.lock index a31943509d..206579816f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2021,7 +2021,7 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "perspective" -version = "3.5.1" +version = "3.6.0" dependencies = [ "async-lock", "axum", @@ -2060,7 +2060,7 @@ dependencies = [ [[package]] name = "perspective-client" -version = "3.5.1" +version = "3.6.0" dependencies = [ "async-lock", "futures", @@ -2081,7 +2081,7 @@ dependencies = [ [[package]] name = "perspective-js" -version = "3.5.1" +version = "3.6.0" dependencies = [ "anyhow", "base64 0.13.1", @@ -2133,7 +2133,7 @@ dependencies = [ [[package]] name = "perspective-python" -version = "3.5.1" +version = "3.6.0" dependencies = [ "async-lock", "cmake", @@ -2156,7 +2156,7 @@ dependencies = [ [[package]] name = "perspective-server" -version = "3.5.1" +version = "3.6.0" dependencies = [ "async-lock", "cmake", @@ -2170,7 +2170,7 @@ dependencies = [ [[package]] name = "perspective-viewer" -version = "3.5.1" +version = "3.6.0" dependencies = [ "anyhow", "async-lock", diff --git a/cpp/perspective/package.json b/cpp/perspective/package.json index 223062c756..a2b2d35ce7 100644 --- a/cpp/perspective/package.json +++ b/cpp/perspective/package.json @@ -3,7 +3,7 @@ "private": true, "author": "The Perspective Authors", "license": "Apache-2.0", - "version": "3.5.1", + "version": "3.6.0", "main": "./dist/esm/perspective.cpp.js", "files": [ "dist/esm/**/*", diff --git a/docs/package.json b/docs/package.json index 348ee64513..cf47069522 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-docs", - "version": "3.5.1", + "version": "3.6.0", "private": true, "scripts": { "build": "node build.js && docusaurus build", diff --git a/examples/blocks/package.json b/examples/blocks/package.json index 1d8ab93f8e..40d51eedc2 100644 --- a/examples/blocks/package.json +++ b/examples/blocks/package.json @@ -1,7 +1,7 @@ { "name": "blocks", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "A collection of simple client-side Perspective examples for `http://bl.ocks.org`.", "scripts": { "start": "mkdirp dist && node --experimental-wasm-memory64 --experimental-modules server.mjs", diff --git a/examples/esbuild-example/package.json b/examples/esbuild-example/package.json index 624b23a128..11623d716e 100644 --- a/examples/esbuild-example/package.json +++ b/examples/esbuild-example/package.json @@ -1,7 +1,7 @@ { "name": "esbuild-example", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An esbuild example app built using `@finos/perspective-viewer`.", "scripts": { "build": "node build.js", diff --git a/examples/esbuild-remote/package.json b/examples/esbuild-remote/package.json index 149e0ed3be..e9ca9ce53c 100644 --- a/examples/esbuild-remote/package.json +++ b/examples/esbuild-remote/package.json @@ -1,7 +1,7 @@ { "name": "esbuild-remote", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example of 2 Perspectives, one client and one server, streaming via Apache Arrow.", "scripts": { "start": "node build.js && node server/index.mjs" diff --git a/examples/python-aiohttp/package.json b/examples/python-aiohttp/package.json index 5d1c978217..528e310485 100644 --- a/examples/python-aiohttp/package.json +++ b/examples/python-aiohttp/package.json @@ -1,7 +1,7 @@ { "name": "python-aiohttp", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example of editing a `perspective-python` server from the browser.", "scripts": { "start": "PYTHONPATH=../../python/perspective python3 server.py" diff --git a/examples/python-starlette/package.json b/examples/python-starlette/package.json index f6f2b2007d..3dde38e668 100644 --- a/examples/python-starlette/package.json +++ b/examples/python-starlette/package.json @@ -1,7 +1,7 @@ { "name": "python-starlette", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example of editing a `perspective-python` server from the browser.", "scripts": { "start": "PYTHONPATH=../../python/perspective python3 server.py" diff --git a/examples/python-tornado-streaming/package.json b/examples/python-tornado-streaming/package.json index 0dda8b0ad4..b0fd728642 100644 --- a/examples/python-tornado-streaming/package.json +++ b/examples/python-tornado-streaming/package.json @@ -1,7 +1,7 @@ { "name": "python-tornado-streaming", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example of streaming a `perspective-python` server to the browser.", "scripts": { "start": "PYTHONPATH=../../python/perspective python3 server.py" diff --git a/examples/python-tornado/package.json b/examples/python-tornado/package.json index ab2c65c12f..377c392468 100644 --- a/examples/python-tornado/package.json +++ b/examples/python-tornado/package.json @@ -1,7 +1,7 @@ { "name": "python-tornado", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example of editing a `perspective-python` server from the browser.", "scripts": { "start": "PYTHONPATH=../../python/perspective python3 server.py" diff --git a/examples/react-example/package.json b/examples/react-example/package.json index 720d298652..aa77824812 100644 --- a/examples/react-example/package.json +++ b/examples/react-example/package.json @@ -1,7 +1,7 @@ { "name": "react-example", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example app built using `@finos/perspective-viewer`.", "scripts": { "build": "node build.js", diff --git a/examples/rust-axum/Cargo.toml b/examples/rust-axum/Cargo.toml index 070b4d7e7e..662b16edde 100644 --- a/examples/rust-axum/Cargo.toml +++ b/examples/rust-axum/Cargo.toml @@ -17,7 +17,7 @@ edition = "2024" publish = false [dependencies] -perspective = { version = "3.5.1" } +perspective = { version = "3.6.0" } axum = { version = ">=0.7,<2", features = ["ws"] } futures = "0.3" tokio = { version = "1.0", features = ["full"] } diff --git a/examples/rust-axum/package.json b/examples/rust-axum/package.json index 7110d0b8b1..1c2f904cd1 100644 --- a/examples/rust-axum/package.json +++ b/examples/rust-axum/package.json @@ -1,7 +1,7 @@ { "name": "rust-axum", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example of a Rust/Axum virtual Perspective server", "scripts": { "start": "cargo run --target=$(rustc -vV | sed -n 's|host: ||p')" diff --git a/examples/vite-example/package.json b/examples/vite-example/package.json index b2bd7a7c0a..64601dcaac 100644 --- a/examples/vite-example/package.json +++ b/examples/vite-example/package.json @@ -1,7 +1,7 @@ { "name": "vite-example", "private": true, - "version": "3.5.1", + "version": "3.6.0", "type": "module", "scripts": { "start": "vite", diff --git a/examples/webpack-example/package.json b/examples/webpack-example/package.json index 1e7bcbcf79..5993fb91c2 100644 --- a/examples/webpack-example/package.json +++ b/examples/webpack-example/package.json @@ -1,7 +1,7 @@ { "name": "webpack-example", "private": true, - "version": "3.5.1", + "version": "3.6.0", "description": "An example app built using `@finos/perspective-viewer`.", "scripts": { "webpack_build": "webpack", diff --git a/package.json b/package.json index cba2eb6ae3..800c502489 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "git", "url": "https://github.com/finos/perspective" }, - "version": "3.5.1", + "version": "3.6.0", "changelog": { "labels": { "enhancement": "Added", diff --git a/packages/perspective-cli/package.json b/packages/perspective-cli/package.json index c2f204e741..13f91177e0 100644 --- a/packages/perspective-cli/package.json +++ b/packages/perspective-cli/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-cli", - "version": "3.5.1", + "version": "3.6.0", "description": "Perspective.js CLI", "main": "src/js/index.js", "publishConfig": { diff --git a/packages/perspective-jupyterlab/package.json b/packages/perspective-jupyterlab/package.json index 722d634454..d931353010 100644 --- a/packages/perspective-jupyterlab/package.json +++ b/packages/perspective-jupyterlab/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-jupyterlab", - "version": "3.5.1", + "version": "3.6.0", "description": "A Jupyterlab extension for the Perspective library, designed to be used with perspective-python.", "files": [ "dist/**/*", diff --git a/packages/perspective-viewer-d3fc/package.json b/packages/perspective-viewer-d3fc/package.json index 0cbcb7a6ee..f9117d4e98 100644 --- a/packages/perspective-viewer-d3fc/package.json +++ b/packages/perspective-viewer-d3fc/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-viewer-d3fc", - "version": "3.5.1", + "version": "3.6.0", "description": "Perspective.js D3FC Plugin", "unpkg": "./dist/cdn/perspective-viewer-d3fc.js", "jsdelivr": "./dist/cdn/perspective-viewer-d3fc.js", diff --git a/packages/perspective-viewer-datagrid/package.json b/packages/perspective-viewer-datagrid/package.json index dfc0d3edb6..b55166203e 100644 --- a/packages/perspective-viewer-datagrid/package.json +++ b/packages/perspective-viewer-datagrid/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-viewer-datagrid", - "version": "3.5.1", + "version": "3.6.0", "description": "Perspective datagrid plugin based on `regular-table`", "unpkg": "dist/cdn/perspective-viewer-datagrid.js", "jsdelivr": "dist/cdn/perspective-viewer-datagrid.js", diff --git a/packages/perspective-viewer-openlayers/package.json b/packages/perspective-viewer-openlayers/package.json index bdc287389b..70efeb3b51 100644 --- a/packages/perspective-viewer-openlayers/package.json +++ b/packages/perspective-viewer-openlayers/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-viewer-openlayers", - "version": "3.5.1", + "version": "3.6.0", "unpkg": "dist/cdn/perspective-viewer-openlayers.js", "jsdelivr": "dist/cdn/perspective-viewer-openlayers.js", "exports": { diff --git a/packages/perspective-workspace/package.json b/packages/perspective-workspace/package.json index 9ab2e3f5e4..b9c628cce5 100644 --- a/packages/perspective-workspace/package.json +++ b/packages/perspective-workspace/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-workspace", - "version": "3.5.1", + "version": "3.6.0", "description": "Perspective Workspace", "files": [ "dist/**/*", diff --git a/rust/perspective-client/Cargo.toml b/rust/perspective-client/Cargo.toml index e662fc4480..e645fcd6f2 100644 --- a/rust/perspective-client/Cargo.toml +++ b/rust/perspective-client/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "perspective-client" -version = "3.5.1" +version = "3.6.0" authors = ["Andrew Stein "] edition = "2024" description = "A data visualization and analytics component, especially well-suited for large and/or streaming datasets." diff --git a/rust/perspective-client/package.json b/rust/perspective-client/package.json index 365a8eee0e..9142d45750 100644 --- a/rust/perspective-client/package.json +++ b/rust/perspective-client/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-client", - "version": "3.5.1", + "version": "3.6.0", "description": "", "private": true, "repository": { diff --git a/rust/perspective-js/Cargo.toml b/rust/perspective-js/Cargo.toml index c1a2cc2a3e..849043bdb3 100644 --- a/rust/perspective-js/Cargo.toml +++ b/rust/perspective-js/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "perspective-js" -version = "3.5.1" +version = "3.6.0" authors = ["Andrew Stein "] edition = "2024" description = "A data visualization and analytics component, especially well-suited for large and/or streaming datasets." @@ -49,7 +49,7 @@ wasm-bindgen-test = "0.3.13" [dependencies] macro_rules_attribute = "0.2.0" -perspective-client = { version = "3.5.1" } +perspective-client = { version = "3.6.0" } base64 = "0.13.0" chrono = "0.4" extend = "1.1.2" diff --git a/rust/perspective-js/package.json b/rust/perspective-js/package.json index f352eb84e9..a4ca8e8b0f 100644 --- a/rust/perspective-js/package.json +++ b/rust/perspective-js/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective", - "version": "3.5.1", + "version": "3.6.0", "description": "", "repository": { "type": "git", diff --git a/rust/perspective-python/Cargo.toml b/rust/perspective-python/Cargo.toml index 86c94588a0..be9bd1163b 100644 --- a/rust/perspective-python/Cargo.toml +++ b/rust/perspective-python/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "perspective-python" -version = "3.5.1" +version = "3.6.0" edition = "2024" description = "A data visualization and analytics component, especially well-suited for large and/or streaming datasets." repository = "https://github.com/finos/perspective" @@ -60,8 +60,8 @@ pyo3-build-config = "0.22.6" python-config-rs = "0.1.2" [dependencies] -perspective-client = { version = "3.5.1" } -perspective-server = { version = "3.5.1" } +perspective-client = { version = "3.6.0" } +perspective-server = { version = "3.6.0" } macro_rules_attribute = "0.2.0" async-lock = "2.5.0" pollster = "0.3.0" diff --git a/rust/perspective-python/package.json b/rust/perspective-python/package.json index bf29dc9943..9f9998d7ad 100644 --- a/rust/perspective-python/package.json +++ b/rust/perspective-python/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-python", - "version": "3.5.1", + "version": "3.6.0", "description": "", "private": true, "repository": { diff --git a/rust/perspective-python/perspective/__init__.py b/rust/perspective-python/perspective/__init__.py index 6a4f8cd4f7..f9c58ce9ec 100644 --- a/rust/perspective-python/perspective/__init__.py +++ b/rust/perspective-python/perspective/__init__.py @@ -10,7 +10,7 @@ # ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -__version__ = "3.5.1" +__version__ = "3.6.0" __all__ = [ "_jupyter_labextension_paths", "Server", diff --git a/rust/perspective-python/pyproject.toml b/rust/perspective-python/pyproject.toml index 826576bfd4..8f1e4c4400 100644 --- a/rust/perspective-python/pyproject.toml +++ b/rust/perspective-python/pyproject.toml @@ -44,7 +44,7 @@ starlette = ["starlette<1"] [tool.maturin] module-name = "perspective" -data = "perspective_python-3.5.1.data" +data = "perspective_python-3.6.0.data" features = ["pyo3/extension-module"] include = [ { path = "perspective/*libpsp.so", format = "wheel" }, diff --git a/rust/perspective-server/Cargo.toml b/rust/perspective-server/Cargo.toml index c125af6879..66e018da98 100644 --- a/rust/perspective-server/Cargo.toml +++ b/rust/perspective-server/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "perspective-server" -version = "3.5.1" +version = "3.6.0" authors = ["Andrew Stein "] edition = "2024" description = "A data visualization and analytics component, especially well-suited for large and/or streaming datasets." @@ -45,7 +45,7 @@ shlex = "1.3.0" [dependencies] link-cplusplus = "1.0.9" -perspective-client = { version = "3.5.1" } +perspective-client = { version = "3.6.0" } async-lock = "2.5.0" tracing = { version = ">=0.1.36" } futures = "0.3" diff --git a/rust/perspective-viewer/Cargo.toml b/rust/perspective-viewer/Cargo.toml index 45e7c59e0d..f1ece6ce56 100644 --- a/rust/perspective-viewer/Cargo.toml +++ b/rust/perspective-viewer/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "perspective-viewer" -version = "3.5.1" +version = "3.6.0" authors = ["Andrew Stein "] edition = "2024" description = "A data visualization and analytics component, especially well-suited for large and/or streaming datasets." @@ -46,8 +46,8 @@ anyhow = "1.0.66" wasm-bindgen-test = "0.3.13" [dependencies] -perspective-client = { version = "3.5.1" } -perspective-js = { version = "3.5.1" } +perspective-client = { version = "3.6.0" } +perspective-js = { version = "3.6.0" } # Provides async `Mutex` for locked sections such as `render` async-lock = "2.5.0" diff --git a/rust/perspective-viewer/package.json b/rust/perspective-viewer/package.json index 30b19c6f77..95a5ae2c74 100644 --- a/rust/perspective-viewer/package.json +++ b/rust/perspective-viewer/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-viewer", - "version": "3.5.1", + "version": "3.6.0", "description": "The `` Custom Element, frontend for Perspective.js", "repository": { "type": "git", diff --git a/rust/perspective/Cargo.toml b/rust/perspective/Cargo.toml index 2aa788cec3..ef33b1f614 100644 --- a/rust/perspective/Cargo.toml +++ b/rust/perspective/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "perspective" -version = "3.5.1" +version = "3.6.0" authors = ["Andrew Stein "] edition = "2024" description = "A data visualization and analytics component, especially well-suited for large and/or streaming datasets." @@ -38,8 +38,8 @@ external-cpp = [ [dependencies] async-lock = "2.5.0" -perspective-client = { version = "3.5.1" } -perspective-server = { version = "3.5.1" } +perspective-client = { version = "3.6.0" } +perspective-server = { version = "3.6.0" } tracing = { version = ">=0.1.36" } axum = { version = ">=0.7,<0.8", features = ["ws"], optional = true } tokio = { version = "~1", features = ["full"], optional = true } diff --git a/rust/perspective/package.json b/rust/perspective/package.json index f0560d9255..29dd39b252 100644 --- a/rust/perspective/package.json +++ b/rust/perspective/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-rs", - "version": "3.5.1", + "version": "3.6.0", "description": "", "private": true, "repository": { diff --git a/tools/perspective-bench/basic_suite.mjs b/tools/perspective-bench/basic_suite.mjs index b060b67b07..4ae3446e2f 100644 --- a/tools/perspective-bench/basic_suite.mjs +++ b/tools/perspective-bench/basic_suite.mjs @@ -43,7 +43,7 @@ perspective_bench.suite( const { default: perspective } = await import("@finos/perspective"); client = await perspective.websocket(path); metadata = { - version: "3.5.1", + version: "3.6.0", version_idx, }; } else { diff --git a/tools/perspective-esbuild-plugin/package.json b/tools/perspective-esbuild-plugin/package.json index 2492f96a1b..3e446f950b 100644 --- a/tools/perspective-esbuild-plugin/package.json +++ b/tools/perspective-esbuild-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-esbuild-plugin", - "version": "3.5.1", + "version": "3.6.0", "description": "esbuild plugin for Perspective", "author": "", "license": "Apache-2.0", diff --git a/tools/perspective-scripts/package.json b/tools/perspective-scripts/package.json index 208af49165..b5cec5a004 100644 --- a/tools/perspective-scripts/package.json +++ b/tools/perspective-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-scripts", - "version": "3.5.1", + "version": "3.6.0", "description": "Build scripts based on perspective", "private": true, "files": [ diff --git a/tools/perspective-test/package.json b/tools/perspective-test/package.json index 5a3aa251eb..63c8340b79 100644 --- a/tools/perspective-test/package.json +++ b/tools/perspective-test/package.json @@ -1,6 +1,6 @@ { "name": "@finos/perspective-test", - "version": "3.5.1", + "version": "3.6.0", "description": "Test utility based on perspective", "private": true, "main": "src/js/index.ts",