Skip to content
Snippets Groups Projects
Verified Commit 29a928ca authored by Timm Fitschen's avatar Timm Fitschen
Browse files

WIP: SELECT for GRPC API

parent 2b342329
Branches
Tags
2 merge requests!45Release 0.2.2,!44F grpc select
Pipeline #29481 failed
......@@ -185,6 +185,54 @@ using TransactionResponseCase = caosdb::entity::v1::TransactionResponse::Transac
using caosdb::utility::get_arena;
using google::protobuf::Arena;
class ResultTableImpl;
class ResultTableColumn {
public:
/**
* Get the name of the column.
*/
[[nodiscard]] auto GetName() const noexcept -> const std::string &;
};
class ResultTable {
class HeaderIterator;
public:
/**
* Number of rows.
*
* The header is not counted as a row.
*/
[[nodiscard]] auto size() const noexcept -> int;
/**
* Get the header of this table, i.e. the list of columns.
*/
[[nodiscard]] auto GetHeader() const noexcept -> const HeaderIterator;
friend class ResultTableImpl;
private:
class HeaderIterator : std::iterator<std::output_iterator_tag, ResultTableColumn> {
public:
explicit HeaderIterator(const ResultTable *result_table, int index = 0);
auto operator*() const -> const ResultTableColumn &;
auto operator++() -> HeaderIterator &;
auto operator++(int) -> HeaderIterator;
auto operator!=(const HeaderIterator &rhs) const -> bool;
auto size() const noexcept -> int;
auto begin() const -> HeaderIterator;
auto end() const -> HeaderIterator;
private:
int current_index = 0;
const ResultTable *result_table;
};
explicit ResultTable(std::unique_ptr<ResultTableImpl> delegate);
std::unique_ptr<ResultTableImpl> delegate;
};
class Transaction;
/**
......@@ -422,6 +470,28 @@ public:
return *(this->result_set.get());
}
/**
* Return the ResultTable of a SELECT query.
*/
[[nodiscard]] inline auto GetResultTable() const noexcept -> const ResultTable & {
if (this->GetStatus().GetCode() < 0) {
CAOSDB_LOG_ERROR(logger_name)
<< "GetResultTable was called before the transaction has terminated. This is a programming "
"error of the code which uses the transaction.";
// TODO(tf) This is a really bad SegFault factory. When the transaction
// terminates and the result_set is being overriden, the unique_ptr
// created here will be deleted and any client of the return ResultTable
// will have a SegFault.
} else if (this->GetStatus().GetCode() == StatusCode::SPOILED) {
CAOSDB_LOG_ERROR(logger_name)
<< "GetResultTable was called on a \"spoiled\" transaction. That means "
"that the result table has already been released via "
"ReleaseResultTable(). This is a programming error of the code which "
"uses the transaction.";
}
return *(this->result_table.get());
}
/**
* Return the ResultSet of this transaction.
*
......@@ -547,6 +617,7 @@ private:
std::string error_message;
mutable long query_count;
mutable std::unique_ptr<ResultSet> result_set;
mutable std::unique_ptr<ResultTable> result_table;
};
template <class InputIterator>
......
......@@ -25,6 +25,7 @@
#include "caosdb/file_transmission/register_file_upload_handler.h" // for RegisterFileUploadHandler
#include "caosdb/file_transmission/upload_request_handler.h" // Upload...
#include "caosdb/logging.h" // for CAOSDB_LOG_FATAL
#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper
#include "caosdb/status_code.h" // for StatusCode
#include "caosdb/transaction_handler.h" // for EntityTransactionHandler
#include <algorithm> // for max
......@@ -51,12 +52,47 @@ using TransactionResponseCase = caosdb::entity::v1::TransactionResponse::Transac
using RetrieveResponseCase = caosdb::entity::v1::RetrieveResponse::RetrieveResponseCase;
using RetrieveResponse = caosdb::entity::v1::RetrieveResponse;
using ProtoEntity = caosdb::entity::v1::Entity;
using ProtoSelectQueryResult = caosdb::entity::v1::SelectQueryResult;
using caosdb::entity::v1::EntityRequest;
using caosdb::utility::ScalarProtoMessageWrapper;
using google::protobuf::Arena;
using NextStatus = grpc::CompletionQueue::NextStatus;
using RegistrationStatus = caosdb::entity::v1::RegistrationStatus;
class ResultTableImpl : public ScalarProtoMessageWrapper<ProtoSelectQueryResult> {
static auto create(ProtoSelectQueryResult *select_result) -> std::unique_ptr<ResultTable>;
ResultTableImpl();
explicit ResultTableImpl(ProtoSelectQueryResult *result_table);
friend class ResultTable;
friend auto ProcessSelectResponse(ProtoSelectQueryResult *select_result) -> std::unique_ptr<ResultTable>;
};
auto ResultTableImpl::create(ProtoSelectQueryResult *select_result) -> std::unique_ptr<ResultTable> {
return std::unique_ptr<ResultTable>(new ResultTable(std::unique_ptr<ResultTableImpl>(new ResultTableImpl(select_result))));
}
ResultTableImpl::ResultTableImpl(ProtoSelectQueryResult *result_table) : ScalarProtoMessageWrapper<ProtoSelectQueryResult>(result_table) {}
ResultTable::ResultTable(std::unique_ptr<ResultTableImpl> delegate) : delegate(std::move(delegate)) {}
auto ResultTable::size() const noexcept -> int {
// TODO
return 0;
}
ResultTable::HeaderIterator::HeaderIterator(const ResultTable *result_table_param, int index) : current_index(index), result_table(result_table_param) {}
auto ResultTable::GetHeader() const noexcept -> const HeaderIterator {
return HeaderIterator(this, 0);
}
auto ResultTable::HeaderIterator::size() const noexcept -> int {
return this->result_table->delegate->wrapped->header().columns_size();
}
ResultSet::iterator::iterator(const ResultSet *result_set_param, int index)
: current_index(index), result_set(result_set_param) {}
......@@ -318,6 +354,10 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode {
return StatusCode::EXECUTING;
}
auto ProcessSelectResponse(ProtoSelectQueryResult *select_result) -> std::unique_ptr<ResultTable> {
return ResultTableImpl::create(select_result);
}
auto Transaction::ProcessRetrieveResponse(RetrieveResponse *retrieve_response,
std::vector<std::unique_ptr<Entity>> *entities,
bool *set_error) const noexcept
......@@ -329,9 +369,7 @@ auto Transaction::ProcessRetrieveResponse(RetrieveResponse *retrieve_response,
result = std::make_unique<Entity>(retrieve_entity_response);
} break;
case RetrieveResponseCase::kSelectResult: {
CAOSDB_LOG_ERROR(logger_name) << "Results of a SELECT query cannot be "
"processed by this client yet.";
// TODO(tf) Select queries
this->result_table = ProcessSelectResponse(retrieve_response->mutable_select_result());
} break;
case RetrieveResponseCase::kCountResult: {
this->query_count = retrieve_response->count_result();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment