Skip to content
This repository was archived by the owner on Feb 12, 2025. It is now read-only.

Commit b0d52e0

Browse files
authored
Add operation count query (#873)
* Add some index for transaction listing * Add count() to OperationQuery -> To get the number of operations, WD AccountController currently fetch all operations (sql) and then count the operations (scala). This PR adds a count() method, thus the counting is done by the database wich is much faster. It aims to fix a huge memory usage when fetching account information on huge accounts with thousands of transactions * minor improvements
1 parent 450969f commit b0d52e0

14 files changed

+311
-1
lines changed

core/idl/wallet/common/wallet.djinni

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ Block = record {
106106
height: i64;
107107
}
108108

109+
OperationCount = record {
110+
# Type of operation
111+
type: OperationType;
112+
# Count of operations
113+
count: i64;
114+
}
115+
109116
# Class representing an operation.
110117
Operation = interface +c {
111118
# Get id's operation.
@@ -265,6 +272,9 @@ OperationQuery = interface +c {
265272
# Execute query to retrieve operations.
266273
# @param callback, if execute method succeed, ListCallback object returning a List of Operation objects
267274
execute(callback: ListCallback<Operation>);
275+
# Count operations by type
276+
# @param callback, if execute method succeed, ListCallback object returning a List of OperationCount objects
277+
count(callback: ListCallback<OperationCount>);
268278
}
269279

270280
# Structure of informations needed for account creation.

core/src/api/OperationCount.hpp

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/api/OperationCountListCallback.hpp

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/api/OperationQuery.hpp

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/database/query/QueryBuilder.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ namespace ledger {
5151
query << sFilter;
5252
}
5353

54+
if (!_group.empty()) {
55+
query << " GROUP BY " << _group;
56+
}
57+
5458
if (!_order.empty()) {
5559
query << " ORDER BY ";
5660
for (auto it = _order.begin(); it != _order.end(); it++) {
@@ -133,5 +137,10 @@ namespace ledger {
133137
return *this;
134138
}
135139

140+
QueryBuilder &QueryBuilder::groupBy(std::string group) {
141+
_group = std::move(group);
142+
return *this;
143+
}
144+
136145
}
137146
}

core/src/database/query/QueryBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ namespace ledger {
5555
QueryBuilder& order(std::string&& keys, bool&& descending, std::string&& table);
5656
QueryBuilder& limit(int32_t limit);
5757
QueryBuilder& offset(int32_t offset);
58+
QueryBuilder& groupBy(std::string group);
5859
soci::details::prepare_temp_type execute(soci::session& sql);
5960

6061
private:
@@ -63,6 +64,7 @@ namespace ledger {
6364
std::string _keys;
6465
std::string _table;
6566
std::string _output;
67+
std::string _group;
6668
std::list<std::tuple<std::string, bool, std::string>> _order;
6769
std::vector<Option<LeftOuterJoin>> _outerJoins;
6870
std::shared_ptr<QueryFilter> _filter;

core/src/jni/jni/OperationCount.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file generated by Djinni from wallet.djinni
3+
4+
#include "OperationCount.hpp" // my header
5+
#include "Marshal.hpp"
6+
#include "OperationType.hpp"
7+
8+
namespace djinni_generated {
9+
10+
OperationCount::OperationCount() = default;
11+
12+
OperationCount::~OperationCount() = default;
13+
14+
auto OperationCount::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef<JniType> {
15+
const auto& data = ::djinni::JniClass<OperationCount>::get();
16+
auto r = ::djinni::LocalRef<JniType>{jniEnv->NewObject(data.clazz.get(), data.jconstructor,
17+
::djinni::get(::djinni_generated::OperationType::fromCpp(jniEnv, c.type)),
18+
::djinni::get(::djinni::I64::fromCpp(jniEnv, c.count)))};
19+
::djinni::jniExceptionCheck(jniEnv);
20+
return r;
21+
}
22+
23+
auto OperationCount::toCpp(JNIEnv* jniEnv, JniType j) -> CppType {
24+
::djinni::JniLocalScope jscope(jniEnv, 3);
25+
assert(j != nullptr);
26+
const auto& data = ::djinni::JniClass<OperationCount>::get();
27+
return {::djinni_generated::OperationType::toCpp(jniEnv, jniEnv->GetObjectField(j, data.field_type)),
28+
::djinni::I64::toCpp(jniEnv, jniEnv->GetLongField(j, data.field_count))};
29+
}
30+
31+
} // namespace djinni_generated

core/src/jni/jni/OperationCount.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file generated by Djinni from wallet.djinni
3+
4+
#ifndef DJINNI_GENERATED_OPERATIONCOUNT_HPP_JNI_
5+
#define DJINNI_GENERATED_OPERATIONCOUNT_HPP_JNI_
6+
7+
#include "../../api/OperationCount.hpp"
8+
#include "djinni_support.hpp"
9+
10+
namespace djinni_generated {
11+
12+
class OperationCount final {
13+
public:
14+
using CppType = ::ledger::core::api::OperationCount;
15+
using JniType = jobject;
16+
17+
using Boxed = OperationCount;
18+
19+
~OperationCount();
20+
21+
static CppType toCpp(JNIEnv* jniEnv, JniType j);
22+
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c);
23+
24+
private:
25+
OperationCount();
26+
friend ::djinni::JniClass<OperationCount>;
27+
28+
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("co/ledger/core/OperationCount") };
29+
const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "<init>", "(Lco/ledger/core/OperationType;J)V") };
30+
const jfieldID field_type { ::djinni::jniGetFieldID(clazz.get(), "type", "Lco/ledger/core/OperationType;") };
31+
const jfieldID field_count { ::djinni::jniGetFieldID(clazz.get(), "count", "J") };
32+
};
33+
34+
} // namespace djinni_generated
35+
#endif //DJINNI_GENERATED_OPERATIONCOUNT_HPP_JNI_
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file generated by Djinni from callback.djinni
3+
4+
#include "OperationCountListCallback.hpp" // my header
5+
#include "Error.hpp"
6+
#include "Marshal.hpp"
7+
#include "OperationCount.hpp"
8+
9+
namespace djinni_generated {
10+
11+
OperationCountListCallback::OperationCountListCallback() : ::djinni::JniInterface<::ledger::core::api::OperationCountListCallback, OperationCountListCallback>() {}
12+
13+
OperationCountListCallback::~OperationCountListCallback() = default;
14+
15+
OperationCountListCallback::JavaProxy::JavaProxy(JniType j) : Handle(::djinni::jniGetThreadEnv(), j) { }
16+
17+
OperationCountListCallback::JavaProxy::~JavaProxy() = default;
18+
19+
void OperationCountListCallback::JavaProxy::onCallback(const std::experimental::optional<std::vector<::ledger::core::api::OperationCount>> & c_result, const std::experimental::optional<::ledger::core::api::Error> & c_error) {
20+
auto jniEnv = ::djinni::jniGetThreadEnv();
21+
::djinni::JniLocalScope jscope(jniEnv, 10);
22+
const auto& data = ::djinni::JniClass<::djinni_generated::OperationCountListCallback>::get();
23+
jniEnv->CallVoidMethod(Handle::get().get(), data.method_onCallback,
24+
::djinni::get(::djinni::Optional<std::experimental::optional, ::djinni::List<::djinni_generated::OperationCount>>::fromCpp(jniEnv, c_result)),
25+
::djinni::get(::djinni::Optional<std::experimental::optional, ::djinni_generated::Error>::fromCpp(jniEnv, c_error)));
26+
::djinni::jniExceptionCheck(jniEnv);
27+
}
28+
29+
} // namespace djinni_generated
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// AUTOGENERATED FILE - DO NOT MODIFY!
2+
// This file generated by Djinni from callback.djinni
3+
4+
#ifndef DJINNI_GENERATED_OPERATIONCOUNTLISTCALLBACK_HPP_JNI_
5+
#define DJINNI_GENERATED_OPERATIONCOUNTLISTCALLBACK_HPP_JNI_
6+
7+
#include "../../api/OperationCountListCallback.hpp"
8+
#include "djinni_support.hpp"
9+
10+
namespace djinni_generated {
11+
12+
class OperationCountListCallback final : ::djinni::JniInterface<::ledger::core::api::OperationCountListCallback, OperationCountListCallback> {
13+
public:
14+
using CppType = std::shared_ptr<::ledger::core::api::OperationCountListCallback>;
15+
using CppOptType = std::shared_ptr<::ledger::core::api::OperationCountListCallback>;
16+
using JniType = jobject;
17+
18+
using Boxed = OperationCountListCallback;
19+
20+
~OperationCountListCallback();
21+
22+
static CppType toCpp(JNIEnv* jniEnv, JniType j) { return ::djinni::JniClass<OperationCountListCallback>::get()._fromJava(jniEnv, j); }
23+
static ::djinni::LocalRef<JniType> fromCppOpt(JNIEnv* jniEnv, const CppOptType& c) { return {jniEnv, ::djinni::JniClass<OperationCountListCallback>::get()._toJava(jniEnv, c)}; }
24+
static ::djinni::LocalRef<JniType> fromCpp(JNIEnv* jniEnv, const CppType& c) { return fromCppOpt(jniEnv, c); }
25+
26+
private:
27+
OperationCountListCallback();
28+
friend ::djinni::JniClass<OperationCountListCallback>;
29+
friend ::djinni::JniInterface<::ledger::core::api::OperationCountListCallback, OperationCountListCallback>;
30+
31+
class JavaProxy final : ::djinni::JavaProxyHandle<JavaProxy>, public ::ledger::core::api::OperationCountListCallback
32+
{
33+
public:
34+
JavaProxy(JniType j);
35+
~JavaProxy();
36+
37+
void onCallback(const std::experimental::optional<std::vector<::ledger::core::api::OperationCount>> & result, const std::experimental::optional<::ledger::core::api::Error> & error) override;
38+
39+
private:
40+
friend ::djinni::JniInterface<::ledger::core::api::OperationCountListCallback, ::djinni_generated::OperationCountListCallback>;
41+
};
42+
43+
const ::djinni::GlobalRef<jclass> clazz { ::djinni::jniFindClass("co/ledger/core/OperationCountListCallback") };
44+
const jmethodID method_onCallback { ::djinni::jniGetMethodID(clazz.get(), "onCallback", "(Ljava/util/ArrayList;Lco/ledger/core/Error;)V") };
45+
};
46+
47+
} // namespace djinni_generated
48+
#endif //DJINNI_GENERATED_OPERATIONCOUNTLISTCALLBACK_HPP_JNI_

0 commit comments

Comments
 (0)