diff --git a/bindings/builtinserver/config/config.go b/bindings/builtinserver/config/config.go
index 30ffe0516..8b3cf0783 100644
--- a/bindings/builtinserver/config/config.go
+++ b/bindings/builtinserver/config/config.go
@@ -14,10 +14,12 @@ type StorageConf struct {
}
type NetConf struct {
- HTTPAddr string `yaml:"httpaddr"`
- RPCAddr string `yaml:"rpcaddr"`
- WebRoot string `yaml:"webroot"`
- Security bool `yaml:"security"`
+ HTTPAddr string `yaml:"httpaddr"`
+ RPCAddr string `yaml:"rpcaddr"`
+ WebRoot string `yaml:"webroot"`
+ Security bool `yaml:"security"`
+ HttpReadTimeoutSec int `yaml:"http_read_timeout,omitempty"`
+ HttpWriteTimeoutSec int `yaml:"http_write_timeout,omitempty"`
}
type LoggerConf struct {
diff --git a/changelog.md b/changelog.md
index 9c3b0da69..479e723fb 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1905,5 +1905,3 @@
- [ref] EnableStorage method was deprecated
- [fix] Query builder did not reset opOR after InnerJoin
-## Misc
-
diff --git a/cjson/decoder.go b/cjson/decoder.go
index 3cc9bd183..dc9667ced 100644
--- a/cjson/decoder.go
+++ b/cjson/decoder.go
@@ -711,7 +711,7 @@ func (dec *Decoder) Decode(cjson []byte, dest interface{}) (err error) {
}
}()
- fieldsoutcnt := make([]int, 64, 64)
+ fieldsoutcnt := make([]int, MaxIndexes)
ctagsPath := make([]int, 0, 8)
dec.decodeValue(nil, ser, reflect.ValueOf(dest), fieldsoutcnt, ctagsPath)
diff --git a/cpp_src/CMakeLists.txt b/cpp_src/CMakeLists.txt
index df73c53cd..4fb239201 100644
--- a/cpp_src/CMakeLists.txt
+++ b/cpp_src/CMakeLists.txt
@@ -89,6 +89,10 @@ endif ()
set (EXTRA_FLAGS "")
+if (WITH_ASAN AND WITH_TSAN)
+ message(FATAL_ERROR "You cannot use the ASAN and TSAN options at the same time, CMake will exit.")
+endif()
+
if (WITH_ASAN)
set (EXTRA_FLAGS "-fsanitize=address")
add_definitions(-DREINDEX_WITH_ASAN)
@@ -695,6 +699,7 @@ if (NOT WIN32)
SET(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "server")
SET(DIST_INCLUDE_FILES
"tools/errors.h" "tools/serializer.h" "tools/varint.h" "tools/stringstools.h" "tools/customhash.h" "tools/assertrx.h" "tools/jsonstring.h"
+ "tools/verifying_updater.h"
"core/reindexer.h" "core/type_consts.h" "core/item.h" "core/payload/payloadvalue.h" "core/payload/payloadiface.h" "core/indexopts.h"
"core/namespacedef.h" "core/keyvalue/variant.h" "core/keyvalue/geometry.h" "core/sortingprioritiestable.h"
"core/rdxcontext.h" "core/activity_context.h" "core/type_consts_helpers.h" "core/payload/fieldsset.h" "core/payload/payloadtype.h"
@@ -702,8 +707,8 @@ if (NOT WIN32)
"core/query/query.h" "core/query/queryentry.h" "core/queryresults/queryresults.h" "core/indexdef.h" "core/queryresults/aggregationresult.h"
"core/queryresults/itemref.h" "core/namespace/stringsholder.h" "core/keyvalue/key_string.h" "core/key_value_type.h" "core/keyvalue/uuid.h"
"core/expressiontree.h" "core/lsn.h" "core/cjson/tagspath.h" "core/cjson/ctag.h"
- "estl/cow.h" "estl/overloaded.h" "estl/one_of.h" "estl/h_vector.h" "estl/mutex.h" "estl/intrusive_ptr.h" "estl/trivial_reverse_iterator.h"
- "estl/span.h" "estl/chunk.h" "estl/fast_hash_traits.h" "estl/debug_macros.h" "estl/defines.h"
+ "estl/cow.h" "estl/overloaded.h" "estl/one_of.h" "estl/h_vector.h" "estl/mutex.h" "estl/intrusive_ptr.h" "estl/trivial_reverse_iterator.h"
+ "estl/span.h" "estl/chunk.h" "estl/fast_hash_traits.h" "estl/debug_macros.h" "estl/defines.h"
"client/reindexer.h" "client/item.h" "client/reindexerconfig.h" "client/queryresults.h" "client/resultserializer.h"
"client/internalrdxcontext.h" "client/transaction.h"
"client/cororeindexer.h" "client/coroqueryresults.h" "client/corotransaction.h"
diff --git a/cpp_src/client/cororeindexer.cc b/cpp_src/client/cororeindexer.cc
index 4cb747cf5..4794f2ae6 100644
--- a/cpp_src/client/cororeindexer.cc
+++ b/cpp_src/client/cororeindexer.cc
@@ -33,7 +33,7 @@ CoroReindexer& CoroReindexer::operator=(CoroReindexer&& rdx) noexcept {
Error CoroReindexer::Connect(const std::string& dsn, dynamic_loop& loop, const client::ConnectOpts& opts) {
return impl_->Connect(dsn, loop, opts);
}
-Error CoroReindexer::Stop() { return impl_->Stop(); }
+void CoroReindexer::Stop() { impl_->Stop(); }
Error CoroReindexer::AddNamespace(const NamespaceDef& nsDef) { return impl_->AddNamespace(nsDef, ctx_); }
Error CoroReindexer::OpenNamespace(std::string_view nsName, const StorageOpts& storage) {
return impl_->OpenNamespace(nsName, ctx_, storage);
diff --git a/cpp_src/client/cororeindexer.h b/cpp_src/client/cororeindexer.h
index da211a6aa..9d9410902 100644
--- a/cpp_src/client/cororeindexer.h
+++ b/cpp_src/client/cororeindexer.h
@@ -46,7 +46,7 @@ class CoroReindexer {
/// @param opts - Connect options. May contaion any of
Error Connect(const std::string &dsn, dynamic_loop &loop, const client::ConnectOpts &opts = client::ConnectOpts());
/// Stop - shutdown connector
- Error Stop();
+ void Stop();
/// Open or create namespace
/// @param nsName - Name of namespace
/// @param opts - Storage options. Can be one of
diff --git a/cpp_src/client/cororpcclient.cc b/cpp_src/client/cororpcclient.cc
index 91ab0114b..9b3236b68 100644
--- a/cpp_src/client/cororpcclient.cc
+++ b/cpp_src/client/cororpcclient.cc
@@ -46,13 +46,12 @@ Error CoroRPCClient::Connect(const std::string& dsn, ev::dynamic_loop& loop, con
return errOK;
}
-Error CoroRPCClient::Stop() {
+void CoroRPCClient::Stop() {
terminate_ = true;
conn_.Stop();
resubWg_.wait();
loop_ = nullptr;
terminate_ = false;
- return errOK;
}
Error CoroRPCClient::AddNamespace(const NamespaceDef& nsDef, const InternalRdxContext& ctx) {
@@ -236,7 +235,7 @@ Error CoroRPCClient::Delete(const Query& query, CoroQueryResults& result, const
query.Serialize(ser);
NsArray nsArray;
- query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q._namespace)); });
+ query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); });
result = CoroQueryResults(&conn_, std::move(nsArray), 0, config_.FetchAmount, config_.RequestTimeout);
@@ -257,7 +256,7 @@ Error CoroRPCClient::Update(const Query& query, CoroQueryResults& result, const
query.Serialize(ser);
NsArray nsArray;
- query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q._namespace)); });
+ query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); });
result = CoroQueryResults(&conn_, std::move(nsArray), 0, config_.FetchAmount, config_.RequestTimeout);
@@ -322,7 +321,7 @@ Error CoroRPCClient::selectImpl(const Query& query, CoroQueryResults& result, se
}
NsArray nsArray;
query.Serialize(qser);
- query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q._namespace)); });
+ query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); });
h_vector vers;
for (auto& ns : nsArray) {
vers.push_back(ns->tagsMatcher_.version() ^ ns->tagsMatcher_.stateToken());
diff --git a/cpp_src/client/cororpcclient.h b/cpp_src/client/cororpcclient.h
index 8c217aa3d..50278e8fd 100644
--- a/cpp_src/client/cororpcclient.h
+++ b/cpp_src/client/cororpcclient.h
@@ -36,7 +36,7 @@ class CoroRPCClient {
~CoroRPCClient();
Error Connect(const std::string &dsn, ev::dynamic_loop &loop, const client::ConnectOpts &opts);
- Error Stop();
+ void Stop();
Error OpenNamespace(std::string_view nsName, const InternalRdxContext &ctx,
const StorageOpts &opts = StorageOpts().Enabled().CreateIfMissing());
diff --git a/cpp_src/client/item.h b/cpp_src/client/item.h
index 3f1bbd684..618398a5c 100644
--- a/cpp_src/client/item.h
+++ b/cpp_src/client/item.h
@@ -60,13 +60,13 @@ class Item {
/// Get status of item
/// @return data slice with JSON. Returned slice is allocated in temporary Item's buffer, and can be invalidated by any next operation
/// with Item
- Error Status() { return status_; }
+ Error Status() const noexcept { return status_; }
/// Get internal ID of item
/// @return ID of item
int GetID() const noexcept { return id_; }
- /// Get internal version of item
- /// @return version of item
- int NumFields();
+ /// Get count of indexed fields
+ /// @return count of indexed fields
+ int NumFields() const noexcept;
/// Set additional percepts for modify operation
/// @param precepts - strings in format "fieldName=Func()"
void SetPrecepts(const std::vector &precepts);
diff --git a/cpp_src/client/queryresults.cc b/cpp_src/client/queryresults.cc
index 7f0b070b1..83b1755c3 100644
--- a/cpp_src/client/queryresults.cc
+++ b/cpp_src/client/queryresults.cc
@@ -114,8 +114,6 @@ void QueryResults::fetchNextResults() {
rawResult_.assign(rawResult.begin() + ser.Pos(), rawResult.end());
}
-QueryResults::~QueryResults() {}
-
h_vector QueryResults::GetNamespaces() const {
h_vector ret;
ret.reserve(nsArray_.size());
@@ -310,8 +308,5 @@ QueryResults::Iterator &QueryResults::Iterator::operator++() {
return *this;
}
-bool QueryResults::Iterator::operator!=(const Iterator &other) const { return idx_ != other.idx_; }
-bool QueryResults::Iterator::operator==(const Iterator &other) const { return idx_ == other.idx_; }
-
} // namespace client
} // namespace reindexer
diff --git a/cpp_src/client/queryresults.h b/cpp_src/client/queryresults.h
index 97c2a1835..e8b059568 100644
--- a/cpp_src/client/queryresults.h
+++ b/cpp_src/client/queryresults.h
@@ -26,7 +26,7 @@ class QueryResults {
QueryResults(int fetchFlags = 0);
QueryResults(const QueryResults&) = delete;
QueryResults(QueryResults&&) noexcept;
- ~QueryResults();
+ ~QueryResults() = default;
QueryResults& operator=(const QueryResults&) = delete;
QueryResults& operator=(QueryResults&& obj) noexcept;
@@ -40,10 +40,10 @@ class QueryResults {
bool IsRaw();
std::string_view GetRaw();
Iterator& operator++();
- Error Status() { return qr_->status_; }
- bool operator!=(const Iterator&) const;
- bool operator==(const Iterator&) const;
- Iterator& operator*() { return *this; }
+ Error Status() const noexcept { return qr_->status_; }
+ bool operator==(const Iterator& other) const noexcept { return idx_ == other.idx_; }
+ bool operator!=(const Iterator& other) const noexcept { return !operator==(other); }
+ Iterator& operator*() noexcept { return *this; }
void readNext();
void getJSONFromCJSON(std::string_view cjson, WrSerializer& wrser, bool withHdrLen = true);
@@ -55,13 +55,15 @@ class QueryResults {
Iterator begin() const { return Iterator{this, 0, 0, 0, {}}; }
Iterator end() const { return Iterator{this, queryParams_.qcount, 0, 0, {}}; }
- size_t Count() const { return queryParams_.qcount; }
- int TotalCount() const { return queryParams_.totalcount; }
- bool HaveRank() const { return queryParams_.flags & kResultsWithRank; }
- bool NeedOutputRank() const { return queryParams_.flags & kResultsNeedOutputRank; }
- const std::string& GetExplainResults() const { return queryParams_.explainResults; }
- const std::vector& GetAggregationResults() const { return queryParams_.aggResults; }
- Error Status() { return status_; }
+ size_t Count() const noexcept { return queryParams_.qcount; }
+ int TotalCount() const noexcept { return queryParams_.totalcount; }
+ bool HaveRank() const noexcept { return queryParams_.flags & kResultsWithRank; }
+ bool NeedOutputRank() const noexcept { return queryParams_.flags & kResultsNeedOutputRank; }
+ const std::string& GetExplainResults() const& noexcept { return queryParams_.explainResults; }
+ const std::string& GetExplainResults() const&& = delete;
+ const std::vector& GetAggregationResults() const& noexcept { return queryParams_.aggResults; }
+ const std::vector& GetAggregationResults() const&& = delete;
+ Error Status() const noexcept { return status_; }
h_vector GetNamespaces() const;
bool IsCacheEnabled() const { return queryParams_.flags & kResultsWithItemID; }
diff --git a/cpp_src/client/reindexer.cc b/cpp_src/client/reindexer.cc
index e28041713..248b25cb0 100644
--- a/cpp_src/client/reindexer.cc
+++ b/cpp_src/client/reindexer.cc
@@ -29,7 +29,7 @@ Error Reindexer::Connect(const std::string& dsn, const client::ConnectOpts& opts
Error Reindexer::Connect(const std::vector>& connectData) {
return impl_->Connect(connectData);
}
-Error Reindexer::Stop() { return impl_->Stop(); }
+void Reindexer::Stop() { impl_->Stop(); }
Error Reindexer::AddNamespace(const NamespaceDef& nsDef) { return impl_->AddNamespace(nsDef, ctx_); }
Error Reindexer::OpenNamespace(std::string_view nsName, const StorageOpts& storage) { return impl_->OpenNamespace(nsName, ctx_, storage); }
Error Reindexer::DropNamespace(std::string_view nsName) { return impl_->DropNamespace(nsName, ctx_); }
diff --git a/cpp_src/client/reindexer.h b/cpp_src/client/reindexer.h
index 705de78e3..8a8780f2e 100644
--- a/cpp_src/client/reindexer.h
+++ b/cpp_src/client/reindexer.h
@@ -48,7 +48,7 @@ class Reindexer {
/// @param connectData - list of server dsn + it's ConnectOpts
Error Connect(const std::vector> &connectData);
/// Stop - shutdown connector
- Error Stop();
+ void Stop();
/// Open or create namespace
/// @param nsName - Name of namespace
/// @param opts - Storage options. Can be one of
diff --git a/cpp_src/client/rpcclient.cc b/cpp_src/client/rpcclient.cc
index 29b6f5ccc..3c7d7089c 100644
--- a/cpp_src/client/rpcclient.cc
+++ b/cpp_src/client/rpcclient.cc
@@ -76,8 +76,8 @@ Error RPCClient::Connect(const std::vector vers;
for (auto& ns : nsArray) {
shared_lock lck(ns->lck_);
diff --git a/cpp_src/client/rpcclient.h b/cpp_src/client/rpcclient.h
index 238b16a12..eefb2cf03 100644
--- a/cpp_src/client/rpcclient.h
+++ b/cpp_src/client/rpcclient.h
@@ -41,7 +41,7 @@ class RPCClient {
Error Connect(const std::string &dsn, const client::ConnectOpts &opts);
Error Connect(const std::vector> &connectData);
- Error Stop();
+ void Stop();
Error OpenNamespace(std::string_view nsName, const InternalRdxContext &ctx,
const StorageOpts &opts = StorageOpts().Enabled().CreateIfMissing());
diff --git a/cpp_src/client/rpcclientmock.cc b/cpp_src/client/rpcclientmock.cc
index f2cb5635e..5c0d4b6ef 100644
--- a/cpp_src/client/rpcclientmock.cc
+++ b/cpp_src/client/rpcclientmock.cc
@@ -37,7 +37,7 @@ Error RPCClientMock::Delete(const Query& query, QueryResults& result, const Inte
auto conn = getConn();
NsArray nsArray;
- query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q._namespace)); });
+ query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); });
result = QueryResults(conn, std::move(nsArray), nullptr, 0, config_.FetchAmount, config_.RequestTimeout);
@@ -69,7 +69,7 @@ Error RPCClientMock::Update(const Query& query, QueryResults& result, const Inte
auto conn = getConn();
NsArray nsArray;
- query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q._namespace)); });
+ query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); });
result = QueryResults(conn, std::move(nsArray), nullptr, 0, config_.FetchAmount, config_.RequestTimeout);
@@ -308,7 +308,7 @@ Error RPCClientMock::selectImpl(const Query& query, QueryResults& result, cproto
NsArray nsArray;
query.Serialize(qser);
- query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q._namespace)); });
+ query.WalkNested(true, true, [this, &nsArray](const Query& q) { nsArray.push_back(getNamespace(q.NsName())); });
h_vector vers;
for (auto& ns : nsArray) {
shared_lock lck(ns->lck_);
diff --git a/cpp_src/cmd/reindexer_server/test/test_storage_compatibility.sh b/cpp_src/cmd/reindexer_server/test/test_storage_compatibility.sh
new file mode 100644
index 000000000..2c014c6a5
--- /dev/null
+++ b/cpp_src/cmd/reindexer_server/test/test_storage_compatibility.sh
@@ -0,0 +1,194 @@
+#!/bin/bash
+# Task: https://github.com/restream/reindexer/-/issues/1188
+set -e
+
+function KillAndRemoveServer {
+ local pid=$1
+ kill $pid
+ wait $pid
+ yum remove -y 'reindexer*' > /dev/null
+}
+
+function WaitForDB {
+ # wait until DB is loaded
+ set +e # disable "exit on error" so the script won't stop when DB's not loaded yet
+ is_connected=$(reindexer_tool --dsn $ADDRESS --command '\databases list');
+ while [[ $is_connected != "test" ]]
+ do
+ sleep 2
+ is_connected=$(reindexer_tool --dsn $ADDRESS --command '\databases list');
+ done
+ set -e
+}
+
+function CompareNamespacesLists {
+ local ns_list_actual=$1
+ local ns_list_expected=$2
+ local pid=$3
+
+ diff=$(echo ${ns_list_actual[@]} ${ns_list_expected[@]} | tr ' ' '\n' | sort | uniq -u) # compare in any order
+ if [ "$diff" == "" ]; then
+ echo "## PASS: namespaces list not changed"
+ else
+ echo "##### FAIL: namespaces list was changed"
+ echo "expected: $ns_list_expected"
+ echo "actual: $ns_list_actual"
+ KillAndRemoveServer $pid;
+ exit 1
+ fi
+}
+
+function CompareMemstats {
+ local actual=$1
+ local expected=$2
+ local pid=$3
+ diff=$(echo ${actual[@]} ${expected[@]} | tr ' ' '\n' | sed 's/\(.*\),$/\1/' | sort | uniq -u) # compare in any order
+ if [ "$diff" == "" ]; then
+ echo "## PASS: memstats not changed"
+ else
+ echo "##### FAIL: memstats was changed"
+ echo "expected: $expected"
+ echo "actual: $actual"
+ KillAndRemoveServer $pid;
+ exit 1
+ fi
+}
+
+
+RX_SERVER_CURRENT_VERSION_RPM="$(basename build/reindexer-*server*.rpm)"
+VERSION_FROM_RPM=$(echo "$RX_SERVER_CURRENT_VERSION_RPM" | grep -o '.*server-..')
+VERSION=$(echo ${VERSION_FROM_RPM: -2:1}) # one-digit version
+
+if [ $VERSION == 3 ]; then
+ LATEST_RELEASE=$(curl -s http://repo.restream.ru/itv-api-ng/7/x86_64/ | grep -o '>reindexer-server-.*.rpm' | tail -n1 | cut -c 2-)
+ namespaces_list_expected=$'purchase_options_ext_dict\nchild_account_recommendations\n#config\n#activitystats\nradio_channels\ncollections\n#namespaces\nwp_imports_tasks\nepg_genres\nrecom_media_items_personal\nrecom_epg_archive_default\n#perfstats\nrecom_epg_live_default\nmedia_view_templates\nasset_video_servers\nwp_tasks_schedule\nadmin_roles\n#clientsstats\nrecom_epg_archive_personal\nrecom_media_items_similars\nmenu_items\naccount_recommendations\nkaraoke_items\nmedia_items\nbanners\n#queriesperfstats\nrecom_media_items_default\nrecom_epg_live_personal\nservices\n#memstats\nchannels\nmedia_item_recommendations\nwp_tasks_tasks\nepg'
+elif [ $VERSION == 4 ]; then
+ LATEST_RELEASE=$(curl -s http://repo.restream.ru/itv-api-ng/7/x86_64/ | grep -o '>reindexer-4-server-.*.rpm' | tail -n1 | cut -c 2-)
+ # replicationstats ns added for v4
+ namespaces_list_expected=$'purchase_options_ext_dict\nchild_account_recommendations\n#config\n#activitystats\n#replicationstats\nradio_channels\ncollections\n#namespaces\nwp_imports_tasks\nepg_genres\nrecom_media_items_personal\nrecom_epg_archive_default\n#perfstats\nrecom_epg_live_default\nmedia_view_templates\nasset_video_servers\nwp_tasks_schedule\nadmin_roles\n#clientsstats\nrecom_epg_archive_personal\nrecom_media_items_similars\nmenu_items\naccount_recommendations\nkaraoke_items\nmedia_items\nbanners\n#queriesperfstats\nrecom_media_items_default\nrecom_epg_live_personal\nservices\n#memstats\nchannels\nmedia_item_recommendations\nwp_tasks_tasks\nepg'
+else
+ echo "Unknown version"
+ exit 1
+fi
+
+echo "## downloading latest release rpm file: $LATEST_RELEASE"
+curl "http://repo.itv.restr.im/itv-api-ng/7/x86_64/$LATEST_RELEASE" --output $LATEST_RELEASE;
+echo "## downloading example DB"
+curl "https://git.restream.ru/MaksimKravchuk/reindexer_testdata/-/raw/master/big.zip" --output big.zip;
+unzip -o big.zip # unzips into mydb_big.rxdump;
+
+ADDRESS="cproto://127.0.0.1:6534/"
+DB_NAME="test"
+
+memstats_expected=$'[
+{"replication":{"data_hash":24651210926,"data_count":3}},
+{"replication":{"data_hash":6252344969,"data_count":1}},
+{"replication":{"data_hash":37734732881,"data_count":28}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":1024095024522,"data_count":1145}},
+{"replication":{"data_hash":8373644068,"data_count":1315}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":7404222244,"data_count":97}},
+{"replication":{"data_hash":94132837196,"data_count":4}},
+{"replication":{"data_hash":1896088071,"data_count":2}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":-672103903,"data_count":33538}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":6833710705,"data_count":1}},
+{"replication":{"data_hash":5858155773472,"data_count":4500}},
+{"replication":{"data_hash":-473221280268823592,"data_count":65448}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":8288213744,"data_count":3}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":0,"data_count":0}},
+{"replication":{"data_hash":354171024786967,"data_count":3941}},
+{"replication":{"data_hash":-6520334670,"data_count":35886}},
+{"replication":{"data_hash":112772074632,"data_count":281}},
+{"replication":{"data_hash":-12679568198538,"data_count":1623116}}
+]
+Returned 27 rows'
+
+echo "##### Forward compatibility test #####"
+
+DB_PATH=$(pwd)"/rx_db"
+
+echo "Database: "$DB_PATH
+
+echo "## installing latest release: $LATEST_RELEASE"
+yum install -y $LATEST_RELEASE > /dev/null;
+# run RX server with disabled logging
+reindexer_server -l warning --httplog=none --rpclog=none --db $DB_PATH &
+server_pid=$!
+sleep 2;
+
+reindexer_tool --dsn $ADDRESS$DB_NAME -f mydb_big.rxdump --createdb;
+sleep 1;
+
+namespaces_1=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list');
+echo $namespaces_1;
+CompareNamespacesLists "${namespaces_1[@]}" "${namespaces_list_expected[@]}" $server_pid;
+
+memstats_1=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats');
+CompareMemstats "${memstats_1[@]}" "${memstats_expected[@]}" $server_pid;
+
+KillAndRemoveServer $server_pid;
+
+echo "## installing current version: $RX_SERVER_CURRENT_VERSION_RPM"
+yum install -y build/*.rpm > /dev/null;
+reindexer_server -l0 --corelog=none --httplog=none --rpclog=none --db $DB_PATH &
+server_pid=$!
+sleep 2;
+
+WaitForDB
+
+namespaces_2=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list');
+echo $namespaces_2;
+CompareNamespacesLists "${namespaces_2[@]}" "${namespaces_1[@]}" $server_pid;
+
+memstats_2=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats');
+CompareMemstats "${memstats_2[@]}" "${memstats_1[@]}" $server_pid;
+
+KillAndRemoveServer $server_pid;
+rm -rf $DB_PATH;
+sleep 1;
+
+echo "##### Backward compatibility test #####"
+
+echo "## installing current version: $RX_SERVER_CURRENT_VERSION_RPM"
+yum install -y build/*.rpm > /dev/null;
+reindexer_server -l warning --httplog=none --rpclog=none --db $DB_PATH &
+server_pid=$!
+sleep 2;
+
+reindexer_tool --dsn $ADDRESS$DB_NAME -f mydb_big.rxdump --createdb;
+sleep 1;
+
+namespaces_3=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list');
+echo $namespaces_3;
+CompareNamespacesLists "${namespaces_3[@]}" "${namespaces_list_expected[@]}" $server_pid;
+
+memstats_3=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats');
+CompareMemstats "${memstats_3[@]}" "${memstats_expected[@]}" $server_pid;
+
+KillAndRemoveServer $server_pid;
+
+echo "## installing latest release: $LATEST_RELEASE"
+yum install -y $LATEST_RELEASE > /dev/null;
+reindexer_server -l warning --httplog=none --rpclog=none --db $DB_PATH &
+server_pid=$!
+sleep 2;
+
+WaitForDB
+
+namespaces_4=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command '\namespaces list');
+echo $namespaces_4;
+CompareNamespacesLists "${namespaces_4[@]}" "${namespaces_3[@]}" $server_pid;
+
+memstats_4=$(reindexer_tool --dsn $ADDRESS$DB_NAME --command 'select replication.data_hash, replication.data_count from #memstats');
+CompareMemstats "${memstats_4[@]}" "${memstats_3[@]}" $server_pid;
+
+KillAndRemoveServer $server_pid;
+rm -rf $DB_PATH;
diff --git a/cpp_src/cmd/reindexer_tool/commandsexecutor.cc b/cpp_src/cmd/reindexer_tool/commandsexecutor.cc
index 8509155f5..eee2a4f62 100644
--- a/cpp_src/cmd/reindexer_tool/commandsexecutor.cc
+++ b/cpp_src/cmd/reindexer_tool/commandsexecutor.cc
@@ -47,19 +47,18 @@ Error CommandsExecutor::Run(const std::string&
}
template
-void CommandsExecutor::GetSuggestions(const std::string& input, std::vector& suggestions) {
+Error CommandsExecutor::GetSuggestions(const std::string& input, std::vector& suggestions) {
OutParamCommand> cmd(
- [this, &input](std::vector& suggestions) {
- getSuggestions(input, suggestions);
- return errOK;
- },
- suggestions);
- execCommand(cmd);
+ [this, &input](std::vector& suggestions) { return getSuggestions(input, suggestions); }, suggestions);
+ return execCommand(cmd);
}
template
Error CommandsExecutor::Stop() {
- GenericCommand cmd([this] { return stop(true); });
+ GenericCommand cmd([this] {
+ stop(true);
+ return Error{};
+ });
auto err = execCommand(cmd);
if (err.ok() && executorThr_.joinable()) {
executorThr_.join();
@@ -475,15 +474,14 @@ Error CommandsExecutor::processImpl(const std::string& command) noe
}
template <>
-Error CommandsExecutor::stop(bool terminate) {
+void CommandsExecutor::stop(bool terminate) {
if (terminate) {
stopCh_.close();
}
- return Error();
}
template <>
-Error CommandsExecutor::stop(bool terminate) {
+void CommandsExecutor::stop(bool terminate) {
if (terminate) {
stopCh_.close();
}
@@ -491,11 +489,17 @@ Error CommandsExecutor::stop(bool terminate) {
}
template
-void CommandsExecutor::getSuggestions(const std::string& input, std::vector& suggestions) {
- if (!input.empty() && input[0] != '\\') db().GetSqlSuggestions(input, input.length() - 1, suggestions);
+Error CommandsExecutor::getSuggestions(const std::string& input, std::vector& suggestions) {
+ if (!input.empty() && input[0] != '\\') {
+ auto err = db().GetSqlSuggestions(input, input.length() - 1, suggestions);
+ if (!err.ok()) {
+ return err;
+ }
+ }
if (suggestions.empty()) {
addCommandsSuggestions(input, suggestions);
}
+ return {};
}
template
@@ -761,7 +765,8 @@ Error CommandsExecutor::commandDump(const std::string& command) {
return Error(errCanceled, "Canceled");
}
wrser << "\\UPSERT " << reindexer::escapeString(nsDef.name) << ' ';
- it.GetJSON(wrser, false);
+ err = it.GetJSON(wrser, false);
+ if (!err.ok()) return err;
wrser << '\n';
if (wrser.Len() > 0x100000) {
output_() << wrser.Slice();
@@ -847,9 +852,11 @@ Error CommandsExecutor::commandMeta(const std::string& command) {
auto nsName = reindexer::unescapeString(parser.NextToken());
std::vector allMeta;
auto err = db().EnumMeta(nsName, allMeta);
+ if (!err.ok()) return err;
for (auto& metaKey : allMeta) {
std::string metaData;
- db().GetMeta(nsName, metaKey, metaData);
+ err = db().GetMeta(nsName, metaKey, metaData);
+ if (!err.ok()) return err;
output_() << metaKey << " = " << metaData << std::endl;
}
return err;
@@ -917,15 +924,18 @@ Error CommandsExecutor::commandBench(const std::string& command) {
LineParser parser(command);
parser.NextToken();
- int benchTime = reindexer::stoi(parser.NextToken());
- if (benchTime == 0) benchTime = kBenchDefaultTime;
+ const std::string_view benchTimeToken = parser.NextToken();
+ const int benchTime = benchTimeToken.empty() ? kBenchDefaultTime : reindexer::stoi(benchTimeToken);
- db().DropNamespace(kBenchNamespace);
+ auto err = db().DropNamespace(kBenchNamespace);
+ if (!err.ok() && err.code() != errNotFound) {
+ return err;
+ }
NamespaceDef nsDef(kBenchNamespace);
nsDef.AddIndex("id", "hash", "int", IndexOpts().PK());
- auto err = db().AddNamespace(nsDef);
+ err = db().AddNamespace(nsDef);
if (!err.ok()) return err;
output_() << "Seeding " << kBenchItemsCount << " documents to bench namespace..." << std::endl;
@@ -1014,19 +1024,17 @@ Error CommandsExecutor::commandProcessDatabase
return Error();
} else if (subCommand == "use") {
std::string currentDsn = getCurrentDsn() + std::string(parser.NextToken());
- Error err = stop(false);
- if (!err.ok()) return err;
- err = db().Connect(currentDsn, loop_);
+ stop(false);
+ auto err = db().Connect(currentDsn, loop_);
if (err.ok()) err = db().Status();
if (err.ok()) output_() << "Succesfully connected to " << currentDsn << std::endl;
return err;
} else if (subCommand == "create") {
auto dbName = parser.NextToken();
std::string currentDsn = getCurrentDsn() + std::string(dbName);
- Error err = stop(false);
- if (!err.ok()) return err;
+ stop(false);
output_() << "Creating database '" << dbName << "'" << std::endl;
- err = db().Connect(currentDsn, loop_, reindexer::client::ConnectOpts().CreateDBIfMissing());
+ auto err = db().Connect(currentDsn, loop_, reindexer::client::ConnectOpts().CreateDBIfMissing());
if (!err.ok()) {
std::cerr << "Error on database '" << dbName << "' creation" << std::endl;
return err;
@@ -1145,11 +1153,14 @@ std::function CommandsExecutor
Error Run(const std::string& dsn, const Args&... args);
- void GetSuggestions(const std::string& input, std::vector& suggestions);
+ Error GetSuggestions(const std::string& input, std::vector& suggestions);
Error Stop();
Error Process(const std::string& command);
Error FromFile(std::istream& in);
@@ -78,8 +78,8 @@ class CommandsExecutor : public reindexer::IUpdatesObserver {
std::vector& suggestions);
Error processImpl(const std::string& command) noexcept;
- Error stop(bool terminate);
- void getSuggestions(const std::string& input, std::vector& suggestions);
+ void stop(bool terminate);
+ Error getSuggestions(const std::string& input, std::vector& suggestions);
Error commandSelect(const std::string& command);
Error commandUpsert(const std::string& command);
Error commandUpdateSQL(const std::string& command);
diff --git a/cpp_src/cmd/reindexer_tool/commandsprocessor.cc b/cpp_src/cmd/reindexer_tool/commandsprocessor.cc
index 17ce39931..f084ea387 100644
--- a/cpp_src/cmd/reindexer_tool/commandsprocessor.cc
+++ b/cpp_src/cmd/reindexer_tool/commandsprocessor.cc
@@ -3,8 +3,8 @@
#include
#include "client/cororeindexer.h"
#include "core/reindexer.h"
-#include "tableviewscroller.h"
#include "tools/fsops.h"
+#include "tools/terminalutils.h"
namespace reindexer_tool {
@@ -30,9 +30,13 @@ template
void CommandsProcessor::setCompletionCallback(T& rx, void (T::*set_completion_callback)(new_v_callback_t const&)) {
(rx.*set_completion_callback)([this](std::string const& input, int) -> replxx::Replxx::completions_t {
std::vector completions;
- executor_.GetSuggestions(input, completions);
+ const auto err = executor_.GetSuggestions(input, completions);
replxx::Replxx::completions_t result;
- for (const std::string& suggestion : completions) result.emplace_back(suggestion);
+ if (err.ok()) {
+ for (const std::string& suggestion : completions) {
+ result.emplace_back(suggestion);
+ }
+ }
return result;
});
}
@@ -43,7 +47,8 @@ void CommandsProcessor::setCompletionCallback(T& rx, void (T::*set_
(rx.*set_completion_callback)(
[this](std::string const& input, int, void*) -> replxx::Replxx::completions_t {
std::vector completions;
- executor_.GetSuggestions(input, completions);
+ const auto err = executor_.GetSuggestions(input, completions);
+ if (!err.ok()) return {};
return completions;
},
nullptr);
diff --git a/cpp_src/core/cjson/fieldextractor.h b/cpp_src/core/cjson/fieldextractor.h
index 6b11f179a..43ac72d64 100644
--- a/cpp_src/core/cjson/fieldextractor.h
+++ b/cpp_src/core/cjson/fieldextractor.h
@@ -16,7 +16,7 @@ class FieldsExtractor {
};
FieldsExtractor() = default;
- FieldsExtractor(VariantArray *va, KeyValueType expectedType, int expectedPathDepth, FieldsSet *filter = nullptr,
+ FieldsExtractor(VariantArray *va, KeyValueType expectedType, int expectedPathDepth, const FieldsSet *filter,
FieldParams *params = nullptr) noexcept
: values_(va), expectedType_(expectedType), expectedPathDepth_(expectedPathDepth), filter_(filter), params_(params) {}
FieldsExtractor(FieldsExtractor &&other) = default;
@@ -176,7 +176,7 @@ class FieldsExtractor {
VariantArray *values_ = nullptr;
KeyValueType expectedType_{KeyValueType::Undefined{}};
int expectedPathDepth_ = 0;
- FieldsSet *filter_;
+ const FieldsSet *filter_;
FieldParams *params_;
};
diff --git a/cpp_src/core/cjson/tagsmatcherimpl.h b/cpp_src/core/cjson/tagsmatcherimpl.h
index e96109868..07037b2ee 100644
--- a/cpp_src/core/cjson/tagsmatcherimpl.h
+++ b/cpp_src/core/cjson/tagsmatcherimpl.h
@@ -4,7 +4,6 @@
#include
#include
-#include "core/keyvalue/key_string.h"
#include "core/payload/payloadtype.h"
#include "core/payload/payloadtypeimpl.h"
#include "ctag.h"
@@ -75,25 +74,29 @@ class TagsMatcherImpl {
if (content == "*"sv) {
node.MarkAllItems(true);
} else {
- int index = stoi(content);
- if (index == 0 && content != "0"sv && ev) {
- VariantArray values = ev(content);
- if (values.size() != 1) {
- throw Error(errParams, "Index expression_ has wrong syntax: '%s'", content);
+ auto index = try_stoi(content);
+ if (!index) {
+ if (ev) {
+ VariantArray values = ev(content);
+ if (values.size() != 1) {
+ throw Error(errParams, "Index expression_ has wrong syntax: '%s'", content);
+ }
+ values.front().Type().EvaluateOneOf(
+ [](OneOf) noexcept {},
+ [&](OneOf) {
+ throw Error(errParams, "Wrong type of index: '%s'", content);
+ });
+ node.SetExpression(content);
+ index = values.front().As();
+ } else {
+ throw Error(errParams, "Can't convert '%s' to number", content);
}
- values.front().Type().EvaluateOneOf(
- [](OneOf) noexcept {},
- [&](OneOf) {
- throw Error(errParams, "Wrong type of index: '%s'", content);
- });
- node.SetExpression(content);
- index = values.front().As();
}
if (index < 0) {
throw Error(errLogic, "Array index value cannot be negative");
}
- node.SetIndex(index);
+ node.SetIndex(*index);
}
field = field.substr(0, openBracketPos);
}
diff --git a/cpp_src/core/comparator.cc b/cpp_src/core/comparator.cc
index 08d001339..c105f53f2 100644
--- a/cpp_src/core/comparator.cc
+++ b/cpp_src/core/comparator.cc
@@ -82,16 +82,11 @@ void Comparator::Bind(const PayloadType &type, int field) {
}
}
-void Comparator::BindEqualPosition(int field, const VariantArray &val, CondType cond) { cmpEqualPosition.BindField(field, val, cond); }
-
-void Comparator::BindEqualPosition(const TagsPath &tagsPath, const VariantArray &val, CondType cond) {
- cmpEqualPosition.BindField(tagsPath, val, cond);
-}
-
bool Comparator::isNumericComparison(const VariantArray &values) const {
if (valuesType_.Is() || values.empty()) return false;
const KeyValueType keyType{values.front().Type()};
- return !valuesType_.IsSame(keyType) && (valuesType_.Is() || keyType.Is());
+ return !valuesType_.IsSame(keyType) && ((valuesType_.Is() && !keyType.Is()) ||
+ (keyType.Is() && !valuesType_.Is()));
}
bool Comparator::Compare(const PayloadValue &data, int rowId) {
@@ -191,7 +186,7 @@ void Comparator::ExcludeDistinct(const PayloadValue &data, int rowId) {
} else {
// Exclude field from payload by offset (fast path)
- assertrx(!type_.Is());
+ assertrx_throw(!type_.Is());
// Check if we have column (rawData_), then go to fastest path with column
if (rawData_) return excludeDistinct(rawData_ + rowId * sizeof_);
diff --git a/cpp_src/core/comparator.h b/cpp_src/core/comparator.h
index 3760077c8..7b1a05445 100644
--- a/cpp_src/core/comparator.h
+++ b/cpp_src/core/comparator.h
@@ -15,8 +15,10 @@ class Comparator : public ComparatorVars {
bool Compare(const PayloadValue &lhs, int rowId);
void ExcludeDistinct(const PayloadValue &, int rowId);
void Bind(const PayloadType &type, int field);
- void BindEqualPosition(int field, const VariantArray &val, CondType cond);
- void BindEqualPosition(const TagsPath &tagsPath, const VariantArray &val, CondType cond);
+ template
+ void BindEqualPosition(F &&field, const VariantArray &val, CondType cond) {
+ cmpEqualPosition.BindField(std::forward(field), val, cond);
+ }
void ClearDistinct() {
cmpInt.ClearDistinct();
cmpBool.ClearDistinct();
@@ -116,7 +118,7 @@ class Comparator : public ComparatorVars {
ComparatorImpl cmpComposite;
ComparatorImpl cmpGeom;
ComparatorImpl cmpUuid;
- CompositeArrayComparator cmpEqualPosition;
+ EqualPositionComparator cmpEqualPosition;
KeyValueType valuesType_{KeyValueType::Undefined{}};
};
diff --git a/cpp_src/core/comparatorimpl.h b/cpp_src/core/comparatorimpl.h
index 41f0aa486..5da4466bc 100644
--- a/cpp_src/core/comparatorimpl.h
+++ b/cpp_src/core/comparatorimpl.h
@@ -349,10 +349,12 @@ class ComparatorImpl {
void SetValues(CondType cond, const VariantArray &values, const ComparatorVars &vars) {
if (cond == CondSet) {
valuesSet_.reset(new intrusive_atomic_rc_wrapper(
- values.size(), hash_composite(vars.payloadType_, vars.fields_), equal_composite(vars.payloadType_, vars.fields_)));
+ values.size(), hash_composite(PayloadType{vars.payloadType_}, FieldsSet{vars.fields_}),
+ equal_composite(PayloadType{vars.payloadType_}, FieldsSet{vars.fields_})));
} else if (cond == CondAllSet) {
valuesSet_.reset(new intrusive_atomic_rc_wrapper(
- values.size(), hash_composite(vars.payloadType_, vars.fields_), equal_composite(vars.payloadType_, vars.fields_)));
+ values.size(), hash_composite(PayloadType{vars.payloadType_}, FieldsSet{vars.fields_}),
+ equal_composite(PayloadType{vars.payloadType_}, FieldsSet{vars.fields_})));
allSetValuesSet_.reset(new intrusive_atomic_rc_wrapper>{});
}
diff --git a/cpp_src/core/compositearraycomparator.cc b/cpp_src/core/compositearraycomparator.cc
index 6e58fdf98..4ffb48e83 100644
--- a/cpp_src/core/compositearraycomparator.cc
+++ b/cpp_src/core/compositearraycomparator.cc
@@ -2,37 +2,29 @@
#include
namespace reindexer {
-CompositeArrayComparator::CompositeArrayComparator() {}
+void EqualPositionComparator::BindField(int field, const VariantArray &values, CondType cond) { bindField(field, values, cond); }
-void CompositeArrayComparator::BindField(int field, const VariantArray &values, CondType condType) {
+void EqualPositionComparator::BindField(const FieldsPath &fieldPath, const VariantArray &values, CondType cond) {
+ bindField(fieldPath, values, cond);
+}
+
+template
+void EqualPositionComparator::bindField(F field, const VariantArray &values, CondType cond) {
fields_.push_back(field);
Context &ctx = ctx_.emplace_back();
- ctx.cond = condType;
- ctx.cmpBool.SetValues(condType, values);
- ctx.cmpInt.SetValues(condType, values);
- ctx.cmpInt64.SetValues(condType, values);
- ctx.cmpString.SetValues(condType, values, CollateOpts());
- ctx.cmpDouble.SetValues(condType, values);
- ctx.cmpUuid.SetValues(condType, values);
+ ctx.cond = cond;
+ ctx.cmpBool.SetValues(cond, values);
+ ctx.cmpInt.SetValues(cond, values);
+ ctx.cmpInt64.SetValues(cond, values);
+ ctx.cmpString.SetValues(cond, values, CollateOpts());
+ ctx.cmpDouble.SetValues(cond, values);
+ ctx.cmpUuid.SetValues(cond, values);
assertrx(ctx_.size() == fields_.size());
}
-void CompositeArrayComparator::BindField(const TagsPath &tagsPath, const VariantArray &values, CondType condType) {
- fields_.push_back(tagsPath);
- Context &ctx = ctx_.emplace_back();
-
- ctx.cond = condType;
- ctx.cmpBool.SetValues(condType, values);
- ctx.cmpInt.SetValues(condType, values);
- ctx.cmpInt64.SetValues(condType, values);
- ctx.cmpString.SetValues(condType, values, CollateOpts());
- ctx.cmpDouble.SetValues(condType, values);
- ctx.cmpUuid.SetValues(condType, values);
-}
-
-bool CompositeArrayComparator::Compare(const PayloadValue &pv, const ComparatorVars &vars) {
+bool EqualPositionComparator::Compare(const PayloadValue &pv, const ComparatorVars &vars) {
ConstPayload pl(vars.payloadType_, pv);
size_t len = INT_MAX;
@@ -64,7 +56,7 @@ bool CompositeArrayComparator::Compare(const PayloadValue &pv, const ComparatorV
return false;
}
-bool CompositeArrayComparator::compareField(size_t field, const Variant &v, const ComparatorVars &vars) {
+bool EqualPositionComparator::compareField(size_t field, const Variant &v, const ComparatorVars &vars) {
return v.Type().EvaluateOneOf(
[&](KeyValueType::Bool) { return ctx_[field].cmpBool.Compare(ctx_[field].cond, static_cast(v)); },
[&](KeyValueType::Int) { return ctx_[field].cmpInt.Compare(ctx_[field].cond, static_cast(v)); },
diff --git a/cpp_src/core/compositearraycomparator.h b/cpp_src/core/compositearraycomparator.h
index d646ed6b4..a58735dc6 100644
--- a/cpp_src/core/compositearraycomparator.h
+++ b/cpp_src/core/compositearraycomparator.h
@@ -5,17 +5,19 @@
namespace reindexer {
-class CompositeArrayComparator {
+class EqualPositionComparator {
public:
- CompositeArrayComparator();
+ EqualPositionComparator() noexcept = default;
- void BindField(int field, const VariantArray &values, CondType condType);
- void BindField(const TagsPath &tagsPath, const VariantArray &values, CondType condType);
- bool Compare(const PayloadValue &pv, const ComparatorVars &vars);
+ void BindField(int field, const VariantArray &, CondType);
+ void BindField(const FieldsPath &, const VariantArray &, CondType);
+ bool Compare(const PayloadValue &, const ComparatorVars &);
bool IsBinded() { return !ctx_.empty(); }
private:
- bool compareField(size_t field, const Variant &v, const ComparatorVars &vars);
+ bool compareField(size_t field, const Variant &, const ComparatorVars &);
+ template
+ void bindField(F field, const VariantArray &, CondType);
struct Context {
CondType cond;
diff --git a/cpp_src/core/dbconfig.cc b/cpp_src/core/dbconfig.cc
index d2b4aa462..bd43caa6d 100644
--- a/cpp_src/core/dbconfig.cc
+++ b/cpp_src/core/dbconfig.cc
@@ -45,8 +45,7 @@ Error DBConfigProvider::FromJSON(const gason::JsonNode &root) {
LongTxLoggingParams{profilingNode["long_queries_logging"]["transaction"]["threshold_us"].As(),
profilingNode["long_queries_logging"]["transaction"]["avg_step_threshold_us"].As()});
}
- auto it = handlers_.find(ProfilingConf);
- if (it != handlers_.end()) (it->second)();
+ if (handlers_[ProfilingConf]) (handlers_[ProfilingConf])();
}
auto &namespacesNode = root["namespaces"];
@@ -75,8 +74,7 @@ Error DBConfigProvider::FromJSON(const gason::JsonNode &root) {
data.syncStorageFlushLimit = nsNode["sync_storage_flush_limit"].As(data.syncStorageFlushLimit, 0);
namespacesData_.emplace(nsNode["namespace"].As(), std::move(data)); // NOLINT(performance-move-const-arg)
}
- auto it = handlers_.find(NamespaceDataConf);
- if (it != handlers_.end()) (it->second)();
+ if (handlers_[NamespaceDataConf]) (handlers_[NamespaceDataConf])();
}
auto &replicationNode = root["replication"];
@@ -84,8 +82,7 @@ Error DBConfigProvider::FromJSON(const gason::JsonNode &root) {
auto err = replicationData_.FromJSON(replicationNode);
if (!err.ok()) return err;
- auto it = handlers_.find(ReplicationConf);
- if (it != handlers_.end()) (it->second)();
+ if (handlers_[ReplicationConf]) (handlers_[ReplicationConf])();
}
return errOK;
} catch (const Error &err) {
@@ -105,11 +102,11 @@ ReplicationConfigData DBConfigProvider::GetReplicationConfig() {
return replicationData_;
}
-bool DBConfigProvider::GetNamespaceConfig(const std::string &nsName, NamespaceConfigData &data) {
+bool DBConfigProvider::GetNamespaceConfig(std::string_view nsName, NamespaceConfigData &data) {
shared_lock lk(mtx_);
auto it = namespacesData_.find(nsName);
if (it == namespacesData_.end()) {
- it = namespacesData_.find("*");
+ it = namespacesData_.find(std::string_view("*"));
}
if (it == namespacesData_.end()) {
data = {};
diff --git a/cpp_src/core/dbconfig.h b/cpp_src/core/dbconfig.h
index cbb4b1bed..05d3745f3 100644
--- a/cpp_src/core/dbconfig.h
+++ b/cpp_src/core/dbconfig.h
@@ -2,7 +2,7 @@
#include
#include
-#include
+#include "estl/fast_hash_map.h"
#include "estl/fast_hash_set.h"
#include "estl/mutex.h"
#include "estl/shared_mutex.h"
@@ -18,7 +18,13 @@ class JsonBuilder;
class RdxContext;
class WrSerializer;
-enum ConfigType { ProfilingConf, NamespaceDataConf, ReplicationConf };
+enum ConfigType {
+ ProfilingConf = 0,
+ NamespaceDataConf,
+ ReplicationConf,
+ //
+ kConfigTypesTotalCount
+};
class LongQueriesLoggingParams {
public:
@@ -133,7 +139,7 @@ class DBConfigProvider {
void setHandler(ConfigType cfgType, std::function handler);
ReplicationConfigData GetReplicationConfig();
- bool GetNamespaceConfig(const std::string &nsName, NamespaceConfigData &data);
+ bool GetNamespaceConfig(std::string_view nsName, NamespaceConfigData &data);
LongQueriesLoggingParams GetSelectLoggingParams() const noexcept {
return profilingData_.longSelectLoggingParams.load(std::memory_order_relaxed);
}
@@ -150,8 +156,8 @@ class DBConfigProvider {
private:
ProfilingConfigData profilingData_;
ReplicationConfigData replicationData_;
- std::unordered_map namespacesData_;
- std::unordered_map> handlers_;
+ fast_hash_map namespacesData_;
+ std::array, kConfigTypesTotalCount> handlers_;
shared_timed_mutex mtx_;
};
diff --git a/cpp_src/core/defnsconfigs.h b/cpp_src/core/defnsconfigs.h
index 36bcd02b4..702604c84 100644
--- a/cpp_src/core/defnsconfigs.h
+++ b/cpp_src/core/defnsconfigs.h
@@ -114,7 +114,6 @@ const std::vector kSystemNsDefs = {
.AddIndex("last_sec_avg_lock_time_us", "-", "int64", IndexOpts().Dense())
.AddIndex("latency_stddev", "-", "double", IndexOpts().Dense()),
NamespaceDef(kNamespacesNamespace, StorageOpts()).AddIndex(kNsNameField, "hash", "string", IndexOpts().PK()),
- NamespaceDef(kPerfStatsNamespace, StorageOpts()).AddIndex(kNsNameField, "hash", "string", IndexOpts().PK()),
NamespaceDef(kMemStatsNamespace, StorageOpts())
.AddIndex(kNsNameField, "hash", "string", IndexOpts().PK())
.AddIndex("items_count", "-", "int64", IndexOpts().Dense())
diff --git a/cpp_src/core/expressiontree.h b/cpp_src/core/expressiontree.h
index 6f4147452..0eeaced61 100644
--- a/cpp_src/core/expressiontree.h
+++ b/cpp_src/core/expressiontree.h
@@ -283,9 +283,10 @@ class ExpressionTree {
};
public:
- Node() : storage_{SubTree{1}} {}
+ Node() : storage_{std::in_place_type, 1} {}
template
- Node(OperationType op, size_t s, Args&&... args) : storage_{SubTree{s, std::forward(args)...}}, operation{op} {}
+ Node(OperationType op, size_t s, Args&&... args)
+ : storage_{std::in_place_type, s, std::forward(args)...}, operation{op} {}
template
Node(OperationType op, T&& v) : storage_{std::forward(v)}, operation{op} {}
Node(const Node& other) : storage_{other.storage_}, operation{other.operation} {}
@@ -363,6 +364,10 @@ class ExpressionTree {
void SetValue(T&& v) {
storage_ = std::forward(v);
}
+ template
+ void Emplace(Args&&... args) {
+ storage_.template emplace(std::forward(args)...);
+ }
private:
Storage storage_;
@@ -443,6 +448,15 @@ class ExpressionTree {
}
container_.emplace_back(op, v);
}
+ /// Appends value to the last openned subtree
+ template
+ void Append(OperationType op, Args&&... args) {
+ for (unsigned i : activeBrackets_) {
+ assertrx(i < container_.size());
+ container_[i].Append();
+ }
+ container_.emplace_back(op, T{std::forward(args)...});
+ }
class const_iterator;
/// Appends all nodes from the interval to the last openned subtree
void Append(const_iterator begin, const_iterator end) {
diff --git a/cpp_src/core/idset.cc b/cpp_src/core/idset.cc
index c8576fc94..da7047de7 100644
--- a/cpp_src/core/idset.cc
+++ b/cpp_src/core/idset.cc
@@ -1,18 +1,8 @@
#include "core/idset.h"
-#include
#include "tools/errors.h"
namespace reindexer {
-void IdSet::Commit() {
- if (!size() && set_) {
- resize(0);
- for (auto id : *set_) push_back(id);
- }
-
- usingBtree_.store(false, std::memory_order_release);
-}
-
std::string IdSetPlain::Dump() const {
std::string buf = "[";
diff --git a/cpp_src/core/idset.h b/cpp_src/core/idset.h
index 6c193f9c4..81522fcef 100644
--- a/cpp_src/core/idset.h
+++ b/cpp_src/core/idset.h
@@ -74,7 +74,7 @@ class IdSetPlain : protected base_idset {
std::string Dump() const;
protected:
- IdSetPlain(base_idset &&idset) : base_idset(std::move(idset)) {}
+ IdSetPlain(base_idset &&idset) noexcept : base_idset(std::move(idset)) {}
};
std::ostream &operator<<(std::ostream &, const IdSetPlain &);
@@ -87,7 +87,7 @@ class IdSet : public IdSetPlain {
public:
using Ptr = intrusive_ptr>;
- IdSet() : usingBtree_(false) {}
+ IdSet() noexcept : usingBtree_(false) {}
IdSet(const IdSet &other)
: IdSetPlain(other), set_(!other.set_ ? nullptr : new base_idsetset(*other.set_)), usingBtree_(other.usingBtree_.load()) {}
IdSet(IdSet &&other) noexcept : IdSetPlain(std::move(other)), set_(std::move(other.set_)), usingBtree_(other.usingBtree_.load()) {}
@@ -194,18 +194,24 @@ class IdSet : public IdSetPlain {
base_idset::erase(d.first, d.second);
return d.second - d.first;
} else {
- resize(0);
+ clear();
usingBtree_.store(true, std::memory_order_release);
return set_->erase(id);
}
- return 0;
}
- void Commit();
- bool IsCommited() const { return !usingBtree_.load(std::memory_order_acquire); }
- bool IsEmpty() const { return empty() && (!set_ || set_->empty()); }
- size_t Size() const { return usingBtree_.load(std::memory_order_acquire) ? set_->size() : size(); }
- size_t BTreeSize() const { return set_ ? sizeof(*set_.get()) + set_->size() * sizeof(int) : 0; }
- const base_idsetset *BTree() const { return set_.get(); }
+ void Commit() {
+ if (!size() && set_) {
+ reserve(set_->size());
+ for (auto id : *set_) push_back(id);
+ }
+
+ usingBtree_.store(false, std::memory_order_release);
+ }
+ bool IsCommited() const noexcept { return !usingBtree_.load(std::memory_order_acquire); }
+ bool IsEmpty() const noexcept { return empty() && (!set_ || set_->empty()); }
+ size_t Size() const noexcept { return usingBtree_.load(std::memory_order_acquire) ? set_->size() : size(); }
+ size_t BTreeSize() const noexcept { return set_ ? sizeof(*set_.get()) + set_->size() * sizeof(int) : 0; }
+ const base_idsetset *BTree() const noexcept { return set_.get(); }
void ReserveForSorted(int sortedIdxCount) { reserve(((set_ ? set_->size() : size())) * (sortedIdxCount + 1)); }
protected:
@@ -214,7 +220,7 @@ class IdSet : public IdSetPlain {
template
friend class BtreeIndexReverseIteratorImpl;
- IdSet(base_idset &&idset) : IdSetPlain(std::move(idset)), usingBtree_(false) {}
+ IdSet(base_idset &&idset) noexcept : IdSetPlain(std::move(idset)), usingBtree_(false) {}
std::unique_ptr set_;
std::atomic usingBtree_;
diff --git a/cpp_src/core/index/index.cc b/cpp_src/core/index/index.cc
index 552033fc2..dcaeda32f 100644
--- a/cpp_src/core/index/index.cc
+++ b/cpp_src/core/index/index.cc
@@ -1,5 +1,4 @@
#include "index.h"
-#include "core/namespacedef.h"
#include "indexordered.h"
#include "indextext/fastindextext.h"
#include "indextext/fuzzyindextext.h"
@@ -10,8 +9,8 @@
namespace reindexer {
-Index::Index(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields)
- : type_(idef.Type()), name_(idef.name_), opts_(idef.opts_), payloadType_(std::move(payloadType)), fields_(fields) {
+Index::Index(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields)
+ : type_(idef.Type()), name_(idef.name_), opts_(idef.opts_), payloadType_(std::move(payloadType)), fields_(std::move(fields)) {
logPrintf(LogTrace, "Index::Index ('%s',%s,%s) %s%s%s", idef.name_, idef.indexType_, idef.fieldType_, idef.opts_.IsPK() ? ",pk" : "",
idef.opts_.IsDense() ? ",dense" : "", idef.opts_.IsArray() ? ",array" : "");
}
@@ -28,38 +27,38 @@ Index::Index(const Index& obj)
selectKeyType_(obj.selectKeyType_),
sortedIdxCount_(obj.sortedIdxCount_) {}
-std::unique_ptr Index::New(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields) {
+std::unique_ptr Index::New(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields) {
switch (idef.Type()) {
case IndexStrBTree:
case IndexIntBTree:
case IndexDoubleBTree:
case IndexInt64BTree:
case IndexCompositeBTree:
- return IndexOrdered_New(idef, std::move(payloadType), fields);
+ return IndexOrdered_New(idef, std::move(payloadType), std::move(fields));
case IndexStrHash:
case IndexIntHash:
case IndexInt64Hash:
case IndexCompositeHash:
- return IndexUnordered_New(idef, std::move(payloadType), fields);
+ return IndexUnordered_New(idef, std::move(payloadType), std::move(fields));
case IndexIntStore:
case IndexStrStore:
case IndexInt64Store:
case IndexDoubleStore:
case IndexBool:
case IndexUuidStore:
- return IndexStore_New(idef, std::move(payloadType), fields);
+ return IndexStore_New(idef, std::move(payloadType), std::move(fields));
case IndexFastFT:
case IndexCompositeFastFT:
- return FastIndexText_New(idef, std::move(payloadType), fields);
+ return FastIndexText_New(idef, std::move(payloadType), std::move(fields));
case IndexFuzzyFT:
case IndexCompositeFuzzyFT:
- return FuzzyIndexText_New(idef, std::move(payloadType), fields);
+ return FuzzyIndexText_New(idef, std::move(payloadType), std::move(fields));
case IndexTtl:
- return TtlIndex_New(idef, std::move(payloadType), fields);
+ return TtlIndex_New(idef, std::move(payloadType), std::move(fields));
case ::IndexRTree:
- return IndexRTree_New(idef, std::move(payloadType), fields);
+ return IndexRTree_New(idef, std::move(payloadType), std::move(fields));
case IndexUuidHash:
- return IndexUuid_New(idef, std::move(payloadType), fields);
+ return IndexUuid_New(idef, std::move(payloadType), std::move(fields));
}
throw Error(errParams, "Ivalid index type %d for index '%s'", idef.Type(), idef.name_);
}
diff --git a/cpp_src/core/index/index.h b/cpp_src/core/index/index.h
index 136a97fdf..b1d3f2d24 100644
--- a/cpp_src/core/index/index.h
+++ b/cpp_src/core/index/index.h
@@ -12,7 +12,6 @@
#include "core/payload/payloadiface.h"
#include "core/perfstatcounter.h"
#include "core/selectkeyresult.h"
-#include "core/type_consts_helpers.h"
#include "ft_preselect.h"
#include "indexiterator.h"
@@ -46,7 +45,7 @@ class Index {
using KeyEntry = reindexer::KeyEntry;
using KeyEntryPlain = reindexer::KeyEntry;
- Index(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields);
+ Index(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields);
Index(const Index&);
Index& operator=(const Index&) = delete;
virtual ~Index() = default;
@@ -82,20 +81,23 @@ class Index {
virtual bool IsDestroyPartSupported() const noexcept { return false; }
virtual void AddDestroyTask(tsl::detail_sparse_hash::ThreadTaskQueue&) {}
- const PayloadType& GetPayloadType() const { return payloadType_; }
- void UpdatePayloadType(PayloadType payloadType) { payloadType_ = std::move(payloadType); }
+ const PayloadType& GetPayloadType() const& { return payloadType_; }
+ const PayloadType& GetPayloadType() const&& = delete;
+ void UpdatePayloadType(PayloadType&& payloadType) { payloadType_ = std::move(payloadType); }
- static std::unique_ptr New(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields_);
+ static std::unique_ptr New(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields_);
KeyValueType KeyType() const { return keyType_; }
KeyValueType SelectKeyType() const { return selectKeyType_; }
- const FieldsSet& Fields() const { return fields_; }
- const std::string& Name() const { return name_; }
+ const FieldsSet& Fields() const& noexcept { return fields_; }
+ const FieldsSet& Fields() const&& = delete;
+ const std::string& Name() const& noexcept { return name_; }
+ const std::string& Name() const&& = delete;
IndexType Type() const { return type_; }
const std::vector& SortOrders() const { return sortOrders_; }
const IndexOpts& Opts() const { return opts_; }
virtual void SetOpts(const IndexOpts& opts) { opts_ = opts; }
- virtual void SetFields(FieldsSet&& fields) { fields_ = std::move(fields); }
+ void SetFields(FieldsSet&& fields) { fields_ = std::move(fields); }
[[nodiscard]] SortType SortId() const noexcept { return sortId_; }
virtual void SetSortedIdxCount(int sortedIdxCount) { sortedIdxCount_ = sortedIdxCount; }
virtual FtMergeStatuses GetFtMergeStatuses(const RdxContext&) {
@@ -140,8 +142,12 @@ class Index {
IndexOpts opts_;
// Payload type of items
mutable PayloadType payloadType_;
- // Fields in index. Valid only for composite indexes
+
+private:
+ // Fields in index
FieldsSet fields_;
+
+protected:
// Perfstat counter
PerfStatCounterMT commitPerfCounter_;
PerfStatCounterMT selectPerfCounter_;
diff --git a/cpp_src/core/index/indexordered.cc b/cpp_src/core/index/indexordered.cc
index 828030b1b..70ae1be0f 100644
--- a/cpp_src/core/index/indexordered.cc
+++ b/cpp_src/core/index/indexordered.cc
@@ -56,10 +56,6 @@ SelectKeyResults IndexOrdered::SelectKey(const VariantArray &keys, CondType c
return IndexUnordered::SelectKey(keys, condition, sortId, opts, ctx, rdxCtx);
}
- if (keys.size() < 1) {
- throw Error(errParams, "For condition required at least 1 argument, but provided 0");
- }
-
SelectKeyResult res;
auto startIt = this->idx_map.begin();
auto endIt = this->idx_map.end();
@@ -81,7 +77,6 @@ SelectKeyResults IndexOrdered::SelectKey(const VariantArray &keys, CondType c
if (startIt == this->idx_map.end()) startIt = this->idx_map.upper_bound(static_cast(key1));
break;
case CondRange: {
- if (keys.size() != 2) throw Error(errParams, "For ranged query reuqired 2 arguments, but provided %d", keys.size());
const auto &key2 = keys[1];
startIt = this->idx_map.find(static_cast(key1));
@@ -207,18 +202,19 @@ IndexIterator::Ptr IndexOrdered::CreateIterator() const {
}
template
-static std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields) {
+static std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields) {
switch (idef.Type()) {
case IndexIntBTree:
- return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), std::move(fields))};
case IndexInt64BTree:
- return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{
+ new IndexOrdered>(idef, std::move(payloadType), std::move(fields))};
case IndexStrBTree:
- return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), std::move(fields))};
case IndexDoubleBTree:
- return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), std::move(fields))};
case IndexCompositeBTree:
- return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexOrdered>(idef, std::move(payloadType), std::move(fields))};
case IndexStrHash:
case IndexIntHash:
case IndexInt64Hash:
@@ -242,9 +238,10 @@ static std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType
}
// NOLINTBEGIN(*cplusplus.NewDeleteLeaks)
-std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields) {
- return (idef.opts_.IsPK() || idef.opts_.IsDense()) ? IndexOrdered_New(idef, std::move(payloadType), fields)
- : IndexOrdered_New(idef, std::move(payloadType), fields);
+std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields) {
+ return (idef.opts_.IsPK() || idef.opts_.IsDense())
+ ? IndexOrdered_New(idef, std::move(payloadType), std::move(fields))
+ : IndexOrdered_New(idef, std::move(payloadType), std::move(fields));
}
// NOLINTEND(*cplusplus.NewDeleteLeaks)
diff --git a/cpp_src/core/index/indexordered.h b/cpp_src/core/index/indexordered.h
index e8dc6d229..96230f7cb 100644
--- a/cpp_src/core/index/indexordered.h
+++ b/cpp_src/core/index/indexordered.h
@@ -10,8 +10,8 @@ class IndexOrdered : public IndexUnordered {
using ref_type = typename IndexUnordered::ref_type;
using key_type = typename IndexUnordered::key_type;
- IndexOrdered(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields)
- : IndexUnordered(idef, std::move(payloadType), fields) {}
+ IndexOrdered(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields)
+ : IndexUnordered(idef, std::move(payloadType), std::move(fields)) {}
SelectKeyResults SelectKey(const VariantArray &keys, CondType condition, SortType stype, Index::SelectOpts opts,
const BaseFunctionCtx::Ptr &ctx, const RdxContext &) override;
@@ -22,6 +22,6 @@ class IndexOrdered : public IndexUnordered {
bool IsOrdered() const noexcept override { return true; }
};
-std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields);
+std::unique_ptr IndexOrdered_New(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields);
} // namespace reindexer
diff --git a/cpp_src/core/index/indexstore.cc b/cpp_src/core/index/indexstore.cc
index 27fe6239f..0ac5d6594 100644
--- a/cpp_src/core/index/indexstore.cc
+++ b/cpp_src/core/index/indexstore.cc
@@ -7,8 +7,8 @@
namespace reindexer {
template <>
-IndexStore::IndexStore(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields)
- : Index(idef, std::move(payloadType), fields) {
+IndexStore::IndexStore(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields)
+ : Index(idef, std::move(payloadType), std::move(fields)) {
keyType_ = selectKeyType_ = KeyValueType::Double{};
opts_.Array(true);
}
@@ -68,8 +68,8 @@ Variant IndexStore::Upsert(const Variant &key, IdType /*id*/, bool
template
Variant IndexStore::Upsert(const Variant &key, IdType id, bool & /*clearCache*/) {
- if (!opts_.IsArray() && !opts_.IsDense() && !opts_.IsSparse() && key.Type().Is()) {
- idx_data.resize(std::max(id + 1, int(idx_data.size())));
+ if (!opts_.IsArray() && !opts_.IsDense() && !opts_.IsSparse() && !key.Type().Is()) {
+ idx_data.resize(std::max(id + 1, IdType(idx_data.size())));
idx_data[id] = static_cast(key);
}
return Variant(key);
@@ -106,43 +106,8 @@ SelectKeyResults IndexStore::SelectKey(const VariantArray &keys, CondType con
if (condition == CondAny && !this->opts_.IsArray() && !this->opts_.IsSparse() && !sopts.distinct)
throw Error(errParams, "The 'NOT NULL' condition is suported only by 'sparse' or 'array' indexes");
- // TODO: it may be necessary to remove or change this switch after QueryEntry refactoring
- switch (condition) {
- case CondAny:
- if (!this->opts_.IsArray() && !this->opts_.IsSparse() && !sopts.distinct) {
- throw Error(errParams, "The 'NOT NULL' condition is suported only by 'sparse' or 'array' indexes");
- }
- break;
- case CondEmpty:
- if (!this->opts_.IsArray() && !this->opts_.IsSparse()) {
- throw Error(errParams, "The 'is NULL' condition is suported only by 'sparse' or 'array' indexes");
- }
- break;
- case CondAllSet:
- case CondSet:
- case CondEq:
- break;
- case CondRange:
- case CondDWithin:
- if (keys.size() != 2) {
- throw Error(errParams, "For condition %s required exactly 2 arguments, but provided %d", CondTypeToStr(condition),
- keys.size());
- }
- break;
- case CondLt:
- case CondLe:
- case CondGt:
- case CondGe:
- case CondLike:
- if (keys.size() != 1) {
- throw Error(errParams, "For condition %s required exactly 1 argument, but provided %d", CondTypeToStr(condition),
- keys.size());
- }
- break;
- }
-
- res.comparators_.push_back(Comparator(condition, KeyType(), keys, opts_.IsArray(), sopts.distinct, payloadType_, fields_,
- idx_data.size() ? idx_data.data() : nullptr, opts_.collateOpts_));
+ res.comparators_.emplace_back(condition, KeyType(), keys, opts_.IsArray(), bool(sopts.distinct), payloadType_, Fields(),
+ idx_data.size() ? idx_data.data() : nullptr, opts_.collateOpts_);
return SelectKeyResults(std::move(res));
}
@@ -183,20 +148,20 @@ void IndexStore::AddDestroyTask(tsl::detail_sparse_hash::ThreadTaskQueue &q)
(void)q;
}
-std::unique_ptr IndexStore_New(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields) {
+std::unique_ptr IndexStore_New(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields) {
switch (idef.Type()) {
case IndexBool:
- return std::unique_ptr{new IndexStore(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexStore(idef, std::move(payloadType), std::move(fields))};
case IndexIntStore:
- return std::unique_ptr{new IndexStore(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexStore(idef, std::move(payloadType), std::move(fields))};
case IndexInt64Store:
- return std::unique_ptr{new IndexStore(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexStore(idef, std::move(payloadType), std::move(fields))};
case IndexDoubleStore:
- return std::unique_ptr{new IndexStore(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexStore(idef, std::move(payloadType), std::move(fields))};
case IndexStrStore:
- return std::unique_ptr{new IndexStore(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexStore(idef, std::move(payloadType), std::move(fields))};
case IndexUuidStore:
- return std::unique_ptr{new IndexStore(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{new IndexStore(idef, std::move(payloadType), std::move(fields))};
case IndexStrHash:
case IndexStrBTree:
case IndexIntBTree:
diff --git a/cpp_src/core/index/indexstore.h b/cpp_src/core/index/indexstore.h
index 832c11a4f..457ae89e5 100644
--- a/cpp_src/core/index/indexstore.h
+++ b/cpp_src/core/index/indexstore.h
@@ -8,7 +8,8 @@ namespace reindexer {
template
class IndexStore : public Index {
public:
- IndexStore(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields) : Index(idef, std::move(payloadType), fields) {
+ IndexStore(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields)
+ : Index(idef, std::move(payloadType), std::move(fields)) {
static T a;
keyType_ = selectKeyType_ = Variant(a).Type();
}
@@ -46,8 +47,8 @@ class IndexStore : public Index {
};
template <>
-IndexStore::IndexStore(const IndexDef &, PayloadType, const FieldsSet &);
+IndexStore::IndexStore(const IndexDef &, PayloadType &&, FieldsSet &&);
-std::unique_ptr IndexStore_New(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields_);
+std::unique_ptr IndexStore_New(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&);
} // namespace reindexer
diff --git a/cpp_src/core/index/indextext/fastindextext.cc b/cpp_src/core/index/indextext/fastindextext.cc
index 36db2dc49..d69307131 100644
--- a/cpp_src/core/index/indextext/fastindextext.cc
+++ b/cpp_src/core/index/indextext/fastindextext.cc
@@ -135,7 +135,7 @@ IdSet::Ptr FastIndexText::Select(FtCtx::Ptr fctx, FtDSLQuery &&dsl, bool inTr
fctx->GetData()->extraWordSymbols_ = this->getConfig()->extraWordSymbols;
fctx->GetData()->isWordPositions_ = true;
- auto mergeData = this->holder_->Select(std::move(dsl), this->fields_.size(), fctx->NeedArea(), getConfig()->maxAreasInDoc,
+ auto mergeData = this->holder_->Select(std::move(dsl), this->Fields().size(), fctx->NeedArea(), getConfig()->maxAreasInDoc,
inTransaction, std::move(statuses.statuses), useExternSt, rdxCtx);
// convert vids(uniq documents id) to ids (real ids)
IdSet::Ptr mergedIds = make_intrusive>();
@@ -232,7 +232,7 @@ void FastIndexText::commitFulltextImpl() {
}
auto tm1 = high_resolution_clock::now();
- this->holder_->Process(this->fields_.size(), !this->opts_.IsDense());
+ this->holder_->Process(this->Fields().size(), !this->opts_.IsDense());
if (this->holder_->NeedClear(this->tracker_.isCompleteUpdated())) {
this->tracker_.clear();
}
@@ -373,12 +373,14 @@ reindexer::FtPreselectT FastIndexText::FtPreselect(const RdxContext &rdxCtx)
std::vector(holder_->rowId2Vdoc_.size(), false), &holder_->rowId2Vdoc_};
}
-std::unique_ptr FastIndexText_New(const IndexDef &idef, PayloadType payloadType, const FieldsSet &fields) {
+std::unique_ptr FastIndexText_New(const IndexDef &idef, PayloadType &&payloadType, FieldsSet &&fields) {
switch (idef.Type()) {
case IndexFastFT:
- return std::unique_ptr{new FastIndexText>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{
+ new FastIndexText>(idef, std::move(payloadType), std::move(fields))};
case IndexCompositeFastFT:
- return std::unique_ptr{new FastIndexText>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{
+ new FastIndexText>(idef, std::move(payloadType), std::move(fields))};
case IndexStrHash:
case IndexStrBTree:
case IndexIntBTree:
diff --git a/cpp_src/core/index/indextext/fastindextext.h b/cpp_src/core/index/indextext/fastindextext.h
index 5a6ebb50d..6a94d3f21 100644
--- a/cpp_src/core/index/indextext/fastindextext.h
+++ b/cpp_src/core/index/indextext/fastindextext.h
@@ -2,8 +2,6 @@
#include "core/ft/config/ftfastconfig.h"
#include "core/ft/ft_fast/dataholder.h"
-#include "core/ft/ft_fast/dataprocessor.h"
-#include "core/ft/typos.h"
#include "indextext.h"
namespace reindexer {
@@ -22,7 +20,8 @@ class FastIndexText : public IndexText {
this->CommitFulltext();
}
- FastIndexText(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields) : Base(idef, std::move(payloadType), fields) {
+ FastIndexText(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields)
+ : Base(idef, std::move(payloadType), std::move(fields)) {
initConfig();
}
std::unique_ptr Clone() const override { return std::unique_ptr{new FastIndexText(*this)}; }
@@ -40,7 +39,7 @@ class FastIndexText : public IndexText {
reindexer::FtPreselectT FtPreselect(const RdxContext& rdxCtx) override final;
bool EnablePreselectBeforeFt() const override final { return getConfig()->enablePreselectBeforeFt; }
-protected:
+private:
void commitFulltextImpl() override final;
FtFastConfig* getConfig() const noexcept { return dynamic_cast(this->cfg_.get()); }
void initConfig(const FtFastConfig* = nullptr);
@@ -53,6 +52,6 @@ class FastIndexText : public IndexText {
std::unique_ptr holder_;
};
-std::unique_ptr FastIndexText_New(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields);
+std::unique_ptr FastIndexText_New(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields);
} // namespace reindexer
diff --git a/cpp_src/core/index/indextext/fieldsgetter.h b/cpp_src/core/index/indextext/fieldsgetter.h
index 791932b27..3af05f79f 100644
--- a/cpp_src/core/index/indextext/fieldsgetter.h
+++ b/cpp_src/core/index/indextext/fieldsgetter.h
@@ -1,6 +1,5 @@
#pragma once
#include "core/ft/usingcontainer.h"
-#include "core/index/payload_map.h"
#include "core/payload/fieldsset.h"
#include "vendor/utf8cpp/utf8.h"
diff --git a/cpp_src/core/index/indextext/fuzzyindextext.cc b/cpp_src/core/index/indextext/fuzzyindextext.cc
index 339ac1252..9ccba834f 100644
--- a/cpp_src/core/index/indextext/fuzzyindextext.cc
+++ b/cpp_src/core/index/indextext/fuzzyindextext.cc
@@ -65,13 +65,14 @@ void FuzzyIndexText::CreateConfig(const FtFuzzyConfig* cfg) {
this->cfg_->parse(this->opts_.config, this->ftFields_);
}
-std::unique_ptr FuzzyIndexText_New(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields) {
+std::unique_ptr FuzzyIndexText_New(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields) {
switch (idef.Type()) {
case IndexFuzzyFT:
- return std::unique_ptr{new FuzzyIndexText>(idef, std::move(payloadType), fields)};
+ return std::unique_ptr{
+ new FuzzyIndexText>(idef, std::move(payloadType), std::move(fields))};
case IndexCompositeFuzzyFT:
return std::unique_ptr{
- new FuzzyIndexText>(idef, std::move(payloadType), fields)};
+ new FuzzyIndexText>(idef, std::move(payloadType), std::move(fields))};
case IndexStrHash:
case IndexStrBTree:
case IndexIntBTree:
diff --git a/cpp_src/core/index/indextext/fuzzyindextext.h b/cpp_src/core/index/indextext/fuzzyindextext.h
index d1a94780a..b536e4ef0 100644
--- a/cpp_src/core/index/indextext/fuzzyindextext.h
+++ b/cpp_src/core/index/indextext/fuzzyindextext.h
@@ -1,9 +1,6 @@
#pragma once
-#include "core/ft/config/ftfastconfig.h"
#include "core/ft/ft_fuzzy/searchengine.h"
-#include "core/ft/ftsetcashe.h"
-#include "core/ft/idrelset.h"
#include "indextext.h"
namespace reindexer {
@@ -15,7 +12,8 @@ class FuzzyIndexText : public IndexText {
public:
FuzzyIndexText(const FuzzyIndexText& other) : Base(other) { CreateConfig(other.getConfig()); }
- FuzzyIndexText(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields) : Base(idef, std::move(payloadType), fields) {
+ FuzzyIndexText(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields)
+ : Base(idef, std::move(payloadType), std::move(fields)) {
CreateConfig();
}
@@ -49,6 +47,6 @@ class FuzzyIndexText : public IndexText {
std::vector vdocs_;
};
-std::unique_ptr FuzzyIndexText_New(const IndexDef& idef, PayloadType payloadType, const FieldsSet& fields);
+std::unique_ptr FuzzyIndexText_New(const IndexDef& idef, PayloadType&& payloadType, FieldsSet&& fields);
} // namespace reindexer
diff --git a/cpp_src/core/index/indextext/indextext.cc b/cpp_src/core/index/indextext/indextext.cc
index 4a8a646db..5748ffe7a 100644
--- a/cpp_src/core/index/indextext/indextext.cc
+++ b/cpp_src/core/index/indextext/indextext.cc
@@ -19,16 +19,17 @@ void IndexText::initSearchers() {
size_t jsonPathIdx = 0;
if (this->payloadType_) {
- for (unsigned i = 0; i < this->fields_.size(); i++) {
- auto fieldIdx = this->fields_[i];
+ const auto &fields = this->Fields();
+ for (unsigned i = 0, s = fields.size(); i < s; i++) {
+ auto fieldIdx = fields[i];
if (fieldIdx == IndexValueType::SetByJsonPath) {
- assertrx(jsonPathIdx < this->fields_.getJsonPathsLength());
- ftFields_.emplace(this->fields_.getJsonPath(jsonPathIdx++), i);
+ assertrx(jsonPathIdx < fields.getJsonPathsLength());
+ ftFields_.emplace(fields.getJsonPath(jsonPathIdx++), i);
} else {
ftFields_.emplace(this->payloadType_->Field(fieldIdx).Name(), i);
}
}
- if rx_unlikely (ftFields_.size() != this->fields_.size()) {
+ if rx_unlikely (ftFields_.size() != fields.size()) {
throw Error(errParams, "Composite fulltext index '%s' contains duplicated fields", this->name_);
}
if rx_unlikely (ftFields_.size() > kMaxFtCompositeFields) {
@@ -178,7 +179,7 @@ SelectKeyResults IndexText