polardbxengine/plugin/polarx_rpc/executor/parse.h

147 lines
3.8 KiB
C++

#pragma once
#include <unordered_map>
#include "error.h"
#include "../coders/protocol_fwd.h"
namespace rpc_executor {
using MysqlxScalar = ::Polarx::Datatypes::Scalar;
using ScalarList = ::google::protobuf::RepeatedPtrField<MysqlxScalar>;
using ParamsList = ScalarList;
using Placeholder = ::google::protobuf::uint32;
using FieldIndex = ::google::protobuf::uint32;
extern thread_local const ParamsList *tls_params;
inline const MysqlxScalar &real(const MysqlxScalar &scalar) {
if (scalar.type() == MysqlxScalar::V_PLACEHOLDER) {
return tls_params->Get(scalar.v_position());
} else {
return scalar;
}
}
// scalar type should be ensured by caller
inline const std::string &pb2str(const MysqlxScalar &scalar) {
return real(scalar).v_string().value();
}
// scalar type should be ensured by caller
inline const char *pb2ptr(const MysqlxScalar &scalar) {
return real(scalar).v_string().value().data();
}
template<typename M>
inline const char *parse_index_name(M &msg) {
return msg.has_index_info() ? pb2ptr(msg.index_info().name()) : "PRIMARY";
}
// Server representation of Mysqlx.Datatypes.Scalar
// should be able to convert to and from Mysqlx.Datatypes.Scalar.Type
class DataRep {
public:
enum DataType {
SIGNED_INT = 1,
UNSIGNED_INT = 2,
NULL_TYPE = 3,
DOUBLE = 5,
FLOAT = 6,
BOOL = 7,
STRING = 8,
PLACEHOLDER = 9,
};
DataType type_;
union {
int64_t v_int_;
uint64_t v_uint_;
double v_double_;
float v_float_;
bool v_bool_;
const std::string *v_string_;
};
int32_t size_;
int init(const MysqlxScalar &scalar) {
int ret = HA_EXEC_SUCCESS;
type_ = static_cast<DataRep::DataType>(scalar.type());
switch (type_) {
case DataRep::SIGNED_INT:
v_int_ = scalar.v_signed_int();
size_ = sizeof(scalar.v_signed_int());
break;
case DataRep::UNSIGNED_INT:
v_uint_ = scalar.v_unsigned_int();
size_ = sizeof(scalar.v_unsigned_int());
break;
case DataRep::NULL_TYPE:
size_ = 0;
break;
case DataRep::DOUBLE:
v_double_ = scalar.v_double();
size_ = sizeof(scalar.v_double());
break;
case DataRep::FLOAT:
v_float_ = scalar.v_float();
size_ = sizeof(scalar.v_float());
break;
case DataRep::BOOL:
v_bool_ = scalar.v_bool();
size_ = sizeof(scalar.v_bool());
break;
case DataRep::STRING:
v_string_ = &(scalar.v_string().value());
size_ = scalar.v_string().value().size();
break;
case DataRep::PLACEHOLDER:
ret = init(real(scalar));
break;
default:
ret = HA_ERR_UNSUPPORTED;
}
return ret;
}
};
// Server representation of GetExpr which is an array of (field_name, value)
// Convert the array to a map
class ExecKeyMap {
public:
int init(const Polarx::ExecPlan::GetExpr &mysqlx_key) {
int ret = HA_EXEC_SUCCESS;
int32_t key_parts_offered = mysqlx_key.keys().size();
key_field_map_.reserve(key_parts_offered);
DataRep temp_data;
auto &field_expr_list = mysqlx_key.keys();
for (int32_t i = 0; i < key_parts_offered; ++i) {
const std::string &field_name = pb2str(field_expr_list.Get(i).field());
if ((ret = temp_data.init(field_expr_list.Get(i).value()))) {
break;
}
key_field_map_.emplace(field_name, temp_data);
}
return ret;
}
int get_field(const std::string &field_name, DataRep &data) const {
int ret = HA_EXEC_SUCCESS;
auto iter = key_field_map_.find(field_name);
if (key_field_map_.end() == iter) {
ret = HA_ERR_KEY_NOT_FOUND;
} else {
data = iter->second;
}
return ret;
}
int64_t parts() const {
return key_field_map_.size();
}
private:
std::unordered_map<std::string, DataRep> key_field_map_;
};
} // namespace executor