Files
oceanbase/src/share/table/ob_table.h

1029 lines
37 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef _OB_TABLE_TABLE_H
#define _OB_TABLE_TABLE_H 1
#include "lib/ob_define.h"
#include "lib/ob_errno.h"
#include "lib/string/ob_string.h"
#include "common/object/ob_object.h"
#include "common/rowkey/ob_rowkey.h"
#include "lib/container/ob_iarray.h"
#include "lib/container/ob_se_array.h"
#include "lib/hash/ob_hashmap.h"
#include "lib/list/ob_dlist.h"
#include "lib/net/ob_addr.h"
#include "common/ob_common_types.h"
#include "common/ob_range.h"
#include "rpc/obrpc/ob_poc_rpc_server.h"
#include "share/table/ob_table_ttl_common.h"
#include "common/rowkey/ob_rowkey.h"
#include "common/ob_role.h"
namespace oceanbase
{
namespace common
{
class ObNewRow;
}
namespace table
{
using common::ObString;
using common::ObRowkey;
using common::ObObj;
using common::ObIArray;
using common::ObSEArray;
////////////////////////////////////////////////////////////////
// structs of a table storage interface
////////////////////////////////////////////////////////////////
/// A Table Entity
class ObITableEntity: public common::ObDLinkBase<ObITableEntity>
{
OB_UNIS_VERSION_V(1);
public:
ObITableEntity()
:alloc_(NULL)
{}
virtual ~ObITableEntity() = default;
virtual void reset() = 0;
virtual bool is_empty() const { return 0 == get_rowkey_size() && 0 == get_properties_count(); }
//@{ primary key contains partition key. Note that all values are shallow copy.
virtual int set_rowkey(const ObRowkey &rowkey) = 0;
virtual int set_rowkey(const ObITableEntity &other) = 0;
virtual int set_rowkey_value(int64_t idx, const ObObj &value) = 0;
virtual int add_rowkey_value(const ObObj &value) = 0;
virtual int64_t get_rowkey_size() const = 0;
virtual int get_rowkey_value(int64_t idx, ObObj &value) const = 0;
virtual ObRowkey get_rowkey() const = 0;
virtual int64_t hash_rowkey() const = 0;
//@}
//@{ property is a key-value pair.
virtual int set_property(const ObString &prop_name, const ObObj &prop_value) = 0;
virtual int get_property(const ObString &prop_name, ObObj &prop_value) const = 0;
virtual int get_properties(ObIArray<std::pair<ObString, ObObj> > &properties) const = 0; // @todo property iterator
virtual int get_properties_names(ObIArray<ObString> &properties) const = 0;
virtual int get_properties_values(ObIArray<ObObj> &properties_values) const = 0;
virtual int64_t get_properties_count() const = 0;
//@}
virtual int deep_copy(common::ObIAllocator &allocator, const ObITableEntity &other);
int deep_copy_rowkey(common::ObIAllocator &allocator, const ObITableEntity &other);
int deep_copy_properties(common::ObIAllocator &allocator, const ObITableEntity &other);
virtual int add_retrieve_property(const ObString &prop_name);
void set_allocator(common::ObIAllocator *alloc) { alloc_ = alloc; }
common::ObIAllocator *get_allocator() { return alloc_; }
VIRTUAL_TO_STRING_KV("ITableEntity", "");
protected:
common::ObIAllocator *alloc_; // for deep copy in deserialize
};
class ObITableEntityFactory
{
public:
virtual ~ObITableEntityFactory() = default;
virtual ObITableEntity *alloc() = 0;
virtual void free(ObITableEntity *obj) = 0;
virtual void free_and_reuse() = 0;
virtual int64_t get_used_count() const = 0;
virtual int64_t get_free_count() const = 0;
virtual int64_t get_used_mem() const = 0;
virtual int64_t get_total_mem() const = 0;
};
/// An implementation for ObITableEntity
class ObTableEntity: public ObITableEntity
{
public:
ObTableEntity();
~ObTableEntity();
virtual int set_rowkey(const ObRowkey &rowkey) override;
virtual int set_rowkey(const ObITableEntity &other) override;
virtual int set_rowkey_value(int64_t idx, const ObObj &value) override;
virtual int add_rowkey_value(const ObObj &value) override;
virtual int64_t get_rowkey_size() const override { return rowkey_.count(); };
virtual int get_rowkey_value(int64_t idx, ObObj &value) const override;
virtual int64_t hash_rowkey() const override;
virtual int get_property(const ObString &prop_name, ObObj &prop_value) const override;
virtual int set_property(const ObString &prop_name, const ObObj &prop_value) override;
virtual int get_properties(ObIArray<std::pair<ObString, ObObj> > &properties) const override;
virtual int get_properties_names(ObIArray<ObString> &properties_names) const override;
virtual int get_properties_values(ObIArray<ObObj> &properties_values) const override;
virtual int64_t get_properties_count() const override;
virtual void reset() override;
virtual ObRowkey get_rowkey() const override;
const ObIArray<ObString> &get_properties_names() const { return properties_names_; }
const ObIArray<ObObj> &get_properties_values() const { return properties_values_; }
const ObSEArray<ObObj, 8> &get_rowkey_objs() const { return rowkey_; };
DECLARE_TO_STRING;
private:
bool has_exist_in_properties(const ObString &name, int64_t *idx = nullptr) const;
private:
ObSEArray<ObObj, 8> rowkey_;
ObSEArray<ObString, 8> properties_names_;
ObSEArray<ObObj, 8> properties_values_;
};
enum class ObTableEntityType
{
ET_DYNAMIC = 0,
ET_KV = 1,
ET_HKV = 2
};
// @note not thread-safe
template <typename T>
class ObTableEntityFactory: public ObITableEntityFactory
{
public:
ObTableEntityFactory(const char *label = common::ObModIds::TABLE_PROC, uint64_t tenant_id = OB_SERVER_TENANT_ID)
:alloc_(label, OB_MALLOC_NORMAL_BLOCK_SIZE, tenant_id)
{}
virtual ~ObTableEntityFactory();
virtual ObITableEntity *alloc() override;
virtual void free(ObITableEntity *obj) override;
virtual void free_and_reuse() override;
virtual int64_t get_free_count() const { return free_list_.get_size(); }
virtual int64_t get_used_count() const { return used_list_.get_size(); }
virtual int64_t get_used_mem() const { return alloc_.used(); }
virtual int64_t get_total_mem() const { return alloc_.total(); }
private:
void free_all();
private:
common::ObArenaAllocator alloc_;
common::ObDList<ObITableEntity> used_list_;
common::ObDList<ObITableEntity> free_list_;
};
template <typename T>
ObTableEntityFactory<T>::~ObTableEntityFactory()
{
free_all();
}
template <typename T>
ObITableEntity *ObTableEntityFactory<T>::alloc()
{
ObITableEntity *entity = free_list_.remove_first();
if (NULL == entity) {
void * ptr = alloc_.alloc(sizeof(T));
if (NULL == ptr) {
CLIENT_LOG_RET(WARN, common::OB_ALLOCATE_MEMORY_FAILED, "no memory for table entity");
} else {
entity = new(ptr) T();
used_list_.add_last(entity);
}
} else {
used_list_.add_last(entity);
}
return entity;
}
template <typename T>
void ObTableEntityFactory<T>::free(ObITableEntity *entity)
{
if (NULL != entity) {
entity->reset();
entity->set_allocator(NULL);
used_list_.remove(entity);
free_list_.add_last(entity);
}
}
template <typename T>
void ObTableEntityFactory<T>::free_and_reuse()
{
while (!used_list_.is_empty()) {
this->free(used_list_.get_first());
}
}
template <typename T>
void ObTableEntityFactory<T>::free_all()
{
ObITableEntity *entity = NULL;
while (NULL != (entity = used_list_.remove_first())) {
entity->~ObITableEntity();
}
while (NULL != (entity = free_list_.remove_first())) {
entity->~ObITableEntity();
}
}
enum class ObQueryOperationType : int {
QUERY_START = 0,
QUERY_NEXT = 1,
QUERY_MAX
};
/// Table Operation Type
struct ObTableOperationType
{
enum Type
{
GET = 0,
INSERT = 1,
DEL = 2,
UPDATE = 3,
INSERT_OR_UPDATE = 4,
REPLACE = 5,
INCREMENT = 6,
APPEND = 7,
SCAN = 8,
TTL = 9, // internal type for ttl executor cache key
INVALID = 15
};
};
/// A table operation
class ObTableOperation
{
OB_UNIS_VERSION(1);
public:
/**
* insert the entity.
* @return ObTableOperationResult
* In the case of insert success, the return errno is OB_SUCCESS, affected_rows is 1
* In the case of insert failed, the affected_rows is 0
* In the case of insert failed caused by primary key duplicated, the errno is OB_ERR_PRIMARY_KEY_DUPLICATE.
* If the option returning_affected_rows is false (default value), then the return value of affected_rows is undefined, but with better performance.
* Other common error code: OB_TIMEOUT indicates time out; OB_TRY_LOCK_ROW_CONFLICT indicate row lock conflict
*/
static ObTableOperation insert(const ObITableEntity &entity);
/**
* delete the entity.
* @return ObTableOperationResult
* In the case of delete success, the errno is OB_SUCCESS and the affeceted_row is 1.
* In the case of the row is NOT EXIST, the errno is OB_SUCCESS and the affected_row is 0.
* If the option returning_affected_rows is false (default value), then the return value of affected_rows is undefined, but with better performance.
* Other common error code: OB_TIMEOUT indicates time out; OB_TRY_LOCK_ROW_CONFLICT indicate row lock conflict
*/
static ObTableOperation del(const ObITableEntity &entity);
/**
* update the entity.
* @return ObTableOperationResult
* In the case of update success, the errno is OB_SUCCESS and the affeceted_row is 1.
* In the case of the row is NOT EXIST, the errno is OB_SUCCESS and the affected_row is 0.
* If the option returning_affected_rows is false (default value), then the return value of affected_rows is undefined, but with better performance.
* Other common error code: OB_TIMEOUT indicates time out; OB_TRY_LOCK_ROW_CONFLICT indicate row lock conflict
*/
static ObTableOperation update(const ObITableEntity &entity);
/**
* insert_or_update the entity.
* @return ObTableOperationResult
* If the row is NOT exist, then insert the row. In the case of success, the return errno is OB_SUCCESS and the affected_rows is 1.
* If the row is exist, then update the row. In the case of success, the return errno is OB_SUCCESS and the affected_rows i 1.
* If the option returning_affected_rows is false (default value), then the return value of affected_rows is undefined, but with better performance.
* Other common error code: OB_TIMEOUT; OB_TRY_LOCK_ROW_CONFLICT
*/
static ObTableOperation insert_or_update(const ObITableEntity &entity);
/**
* replace the entity.
* @return ObTableOperationResult
* If the row is NOT EXIST, then insert the row. In the case of success,
* the errno is OB_SUCCESS and the affected_row is 1.
* Otherwise the row is EXIST, then delete the old row and insert the new row. In the case of success,
* the errno is OB_SUCCESS and the affected_row is 1.
* Specially, if there is uniq index conflict, then delete all rows cause conflict and insert the new row.
* In the case of success, the errno is OB_SUCCESS and the affected_row >= 1.
* If the option returning_affected_rows is false (default value), then the return value of affected_rows is undefined, but with better performance.
* Other common error code: OB_TIMEOUT; OB_TRY_LOCK_ROW_CONFLICT
*/
static ObTableOperation replace(const ObITableEntity &entity);
/**
* retrieve the entity.
* @param entity Only return the given property
* @return ObTableOperationResult
* affected_rows is always 0
* If the row is exist, then return the ObTableOperationResult.entity
* Otherwise, entity is empty.
* Other common error code: OB_TIMEOUT
*/
static ObTableOperation retrieve(const ObITableEntity &entity);
/**
* Increase the value of given column.
* The type of the column MUST be integer.
* If the original value of given column is NULL, use the new value to replace it.
*/
static ObTableOperation increment(const ObITableEntity &entity);
/**
* Append the given string to original string.
* The type of the column MUST be string type, such as char, varchar, binary, varbinary or lob.
* If the original value of given column is NULL, use the new value to replace it.
*/
static ObTableOperation append(const ObITableEntity &entity);
public:
const ObITableEntity &entity() const { return *entity_; }
ObTableOperationType::Type type() const { return operation_type_; }
void set_entity(const ObITableEntity &entity) { entity_ = &entity; }
void set_type(ObTableOperationType::Type op_type) { operation_type_ = op_type; }
int get_entity(ObITableEntity *&entity);
uint64_t get_checksum();
TO_STRING_KV(K_(operation_type), "entity", to_cstring(entity_));
private:
const ObITableEntity *entity_;
ObTableOperationType::Type operation_type_;
};
class ObTableTTLOperation
{
public:
ObTableTTLOperation(uint64_t tenant_id, uint64_t table_id, const ObTTLTaskParam &para,
uint64_t del_row_limit, ObRowkey start_rowkey, uint64_t hbase_cur_version)
: tenant_id_(tenant_id), table_id_(table_id), max_version_(para.max_version_),
time_to_live_(para.ttl_), is_htable_(para.is_htable_), del_row_limit_(del_row_limit),
start_rowkey_(start_rowkey), hbase_cur_version_(hbase_cur_version)
{}
~ObTableTTLOperation() {}
bool is_valid() const
{
return common::OB_INVALID_TENANT_ID != tenant_id_ && common::OB_INVALID_ID != table_id_ &&
(!is_htable_ || max_version_ > 0 || time_to_live_ > 0) && del_row_limit_ > 0;
}
TO_STRING_KV(K_(tenant_id), K_(table_id), K_(max_version), K_(time_to_live), K_(is_htable), K_(del_row_limit), K_(start_rowkey));
public:
uint64_t tenant_id_;
uint64_t table_id_;
int32_t max_version_;
int32_t time_to_live_;
bool is_htable_;
uint64_t del_row_limit_;
ObRowkey start_rowkey_;
uint64_t hbase_cur_version_;
};
/// common result for ObTable
class ObTableResult
{
OB_UNIS_VERSION(1);
public:
ObTableResult()
:errno_(common::OB_ERR_UNEXPECTED)
{
sqlstate_[0] = '\0';
msg_[0] = '\0';
}
~ObTableResult() = default;
void set_errno(int err) { errno_ = err; }
int get_errno() const { return errno_; }
int assign(const ObTableResult &other);
void reset()
{
errno_ = common::OB_ERR_UNEXPECTED;
sqlstate_[0] = '\0';
msg_[0] = '\0';
}
TO_STRING_KV(K_(errno));
private:
static const int64_t MAX_MSG_SIZE = common::OB_MAX_ERROR_MSG_LEN;
protected:
int32_t errno_;
char sqlstate_[6]; // terminate with '\0'
char msg_[MAX_MSG_SIZE]; // terminate with '\0'
};
/// result for ObTableOperation
class ObTableOperationResult final: public ObTableResult
{
OB_UNIS_VERSION(1);
public:
ObTableOperationResult();
~ObTableOperationResult() = default;
void reset();
ObTableOperationType::Type type() const { return operation_type_; }
int get_entity(const ObITableEntity *&entity) const;
int get_entity(ObITableEntity *&entity);
ObITableEntity *get_entity() { return entity_; }
int64_t get_affected_rows() const { return affected_rows_; }
void set_entity(ObITableEntity &entity) { entity_ = &entity; }
void set_type(ObTableOperationType::Type op_type) { operation_type_ = op_type; }
void set_affected_rows(int64_t affected_rows) { affected_rows_ = affected_rows; }
int deep_copy(common::ObIAllocator &allocator, ObITableEntityFactory &entity_factory, const ObTableOperationResult &other);
DECLARE_TO_STRING;
private:
ObTableOperationType::Type operation_type_;
ObITableEntity *entity_;
int64_t affected_rows_;
};
class ObIRetryPolicy
{
public:
virtual bool need_retry(int32_t curr_retry_count, int last_errno, int64_t &retry_interval)
{
UNUSEDx(curr_retry_count, last_errno, retry_interval);
return false;
}
};
class ObLinearRetry : public ObIRetryPolicy
{};
class ObExponentialRetry : public ObIRetryPolicy
{};
class ObNoRetry : public ObIRetryPolicy
{};
/// consistency levels
enum class ObTableConsistencyLevel
{
STRONG = 0,
EVENTUAL = 1,
};
/// clog row image type
/// @see share::ObBinlogRowImage
enum class ObBinlogRowImageType
{
MINIMAL = 0,
NOBLOB = 1,
FULL = 2,
};
/// request options for all the table operations
class ObTableRequestOptions final
{
public:
ObTableRequestOptions();
~ObTableRequestOptions() = default;
void set_consistency_level(ObTableConsistencyLevel consistency_level) { consistency_level_ = consistency_level; }
ObTableConsistencyLevel consistency_level() const { return consistency_level_; }
void set_server_timeout(int64_t server_timeout_us) { server_timeout_us_ = server_timeout_us; }
int64_t server_timeout() const { return server_timeout_us_; }
void set_execution_time(int64_t max_execution_time_us) { max_execution_time_us_ = max_execution_time_us; }
int64_t max_execution_time() const { return max_execution_time_us_; }
void set_retry_policy(ObIRetryPolicy *retry_policy) { retry_policy_ = retry_policy; }
ObIRetryPolicy* retry_policy() { return retry_policy_; }
void set_returning_affected_rows(bool returning) { returning_affected_rows_ = returning; }
bool returning_affected_rows() const { return returning_affected_rows_; }
void set_returning_rowkey(bool returning) { returning_rowkey_ = returning; }
bool returning_rowkey() const { return returning_rowkey_; }
void set_returning_affected_entity(bool returning) { returning_affected_entity_ = returning; }
bool returning_affected_entity() const { return returning_affected_entity_; }
void set_batch_operation_as_atomic(bool atomic) { batch_operation_as_atomic_ = atomic; }
bool batch_operation_as_atomic() const { return batch_operation_as_atomic_; }
void set_binlog_row_image_type(ObBinlogRowImageType type) { binlog_row_image_type_ = type; }
ObBinlogRowImageType binlog_row_image_type() const { return binlog_row_image_type_; }
private:
ObTableConsistencyLevel consistency_level_;
int64_t server_timeout_us_;
int64_t max_execution_time_us_;
ObIRetryPolicy *retry_policy_;
bool returning_affected_rows_; // default: false
bool returning_rowkey_; // default: false
bool returning_affected_entity_; // default: false
bool batch_operation_as_atomic_; // default: false
// int route_policy
ObBinlogRowImageType binlog_row_image_type_; // default: FULL
};
/// A batch operation
class ObTableBatchOperation
{
OB_UNIS_VERSION(1);
public:
static const int64_t MAX_BATCH_SIZE = 1000;
static const int64_t COMMON_BATCH_SIZE = 8;
public:
ObTableBatchOperation()
:table_operations_(common::ObModIds::TABLE_BATCH_OPERATION, common::OB_MALLOC_NORMAL_BLOCK_SIZE),
is_readonly_(true),
is_same_type_(true),
is_same_properties_names_(true),
entity_factory_(NULL)
{}
~ObTableBatchOperation() = default;
void reset();
void set_entity_factory(ObITableEntityFactory *entity_factory) { entity_factory_ = entity_factory; }
/// insert the entity if not exists
int insert(const ObITableEntity &entity);
/// delete the entity if exists
int del(const ObITableEntity &entity);
/// update the entity if exists
int update(const ObITableEntity &entity);
/// insert the entity if not exists, otherwise update it
int insert_or_update(const ObITableEntity &entity);
/// insert the entity if not exists, otherwise replace it
int replace(const ObITableEntity &entity);
/// get the entity if exists
int retrieve(const ObITableEntity &entity);
/// add one table operation
int add(const ObTableOperation &table_operation);
/// increment the value
int increment(const ObITableEntity &entity);
/// append to the value
int append(const ObITableEntity &entity);
int64_t count() const { return table_operations_.count(); }
const ObTableOperation &at(int64_t idx) const { return table_operations_.at(idx); }
bool is_readonly() const { return is_readonly_; }
bool is_same_type() const { return is_same_type_; }
bool is_same_properties_names() const { return is_same_properties_names_; }
uint64_t get_checksum();
TO_STRING_KV(K_(is_readonly),
K_(is_same_type),
K_(is_same_properties_names),
"operatiton_count", table_operations_.count(),
K_(table_operations));
private:
ObSEArray<ObTableOperation, COMMON_BATCH_SIZE> table_operations_;
bool is_readonly_;
bool is_same_type_;
bool is_same_properties_names_;
// do not serialize
ObITableEntityFactory *entity_factory_;
};
/// result for ObTableBatchOperation
typedef ObIArray<ObTableOperationResult> ObITableBatchOperationResult;
class ObTableBatchOperationResult: public common::ObSEArrayImpl<ObTableOperationResult, ObTableBatchOperation::COMMON_BATCH_SIZE>
{
OB_UNIS_VERSION(1);
public:
ObTableBatchOperationResult()
:BaseType(common::ObModIds::TABLE_BATCH_OPERATION_RESULT, common::OB_MALLOC_NORMAL_BLOCK_SIZE),
entity_factory_(NULL),
alloc_(NULL)
{}
virtual ~ObTableBatchOperationResult() = default;
void set_entity_factory(ObITableEntityFactory *entity_factory) { entity_factory_ = entity_factory; }
ObITableEntityFactory *get_entity_factory() { return entity_factory_; }
void set_allocator(common::ObIAllocator *alloc) { alloc_ = alloc; }
common::ObIAllocator *get_allocator() { return alloc_; }
private:
typedef common::ObSEArrayImpl<ObTableOperationResult, ObTableBatchOperation::COMMON_BATCH_SIZE> BaseType;
ObITableEntityFactory *entity_factory_;
common::ObIAllocator *alloc_;
};
class ObHTableConstants
{
public:
static constexpr int64_t LATEST_TIMESTAMP = -INT64_MAX;
static constexpr int64_t OLDEST_TIMESTAMP = INT64_MAX;
static constexpr int64_t INITIAL_MIN_STAMP = 0;
static constexpr int64_t INITIAL_MAX_STAMP = INT64_MAX;
static const char* const ROWKEY_CNAME;
static const char* const CQ_CNAME;
static const char* const VERSION_CNAME;
static const char* const VALUE_CNAME;
static const ObString ROWKEY_CNAME_STR;
static const ObString CQ_CNAME_STR;
static const ObString VERSION_CNAME_STR;
static const ObString VALUE_CNAME_STR;
// create table t1$cf1 (K varbinary(1024), Q varchar(256), T bigint, V varbinary(1024), primary key(K, Q, T));
static const int64_t COL_IDX_K = 0;
static const int64_t COL_IDX_Q = 1;
static const int64_t COL_IDX_T = 2;
static const int64_t COL_IDX_V = 3;
private:
ObHTableConstants() = delete;
};
/// special filter for HTable
class ObHTableFilter final
{
OB_UNIS_VERSION(1);
public:
ObHTableFilter();
~ObHTableFilter() = default;
void reset();
void set_valid(bool valid) { is_valid_ = valid; }
bool is_valid() const { return is_valid_; }
/// Get the column with the specified qualifier.
int add_column(const ObString &qualifier);
/// Get versions of columns with the specified timestamp.
int set_timestamp(int64_t timestamp) { min_stamp_ = timestamp; max_stamp_ = timestamp + 1; return common::OB_SUCCESS; }
/// Get versions of columns only within the specified timestamp range, [minStamp, maxStamp).
int set_time_range(int64_t min_stamp, int64_t max_stamp);
/// Get up to the specified number of versions of each column.
int set_max_versions(int32_t versions);
/// Set the maximum number of values to return per row per Column Family
/// @param limit - the maximum number of values returned / row / CF
int set_max_results_per_column_family(int32_t limit);
/// Set offset for the row per Column Family.
/// @param offset - is the number of kvs that will be skipped.
int set_row_offset_per_column_family(int32_t offset);
/// Apply the specified server-side filter when performing the Query.
/// @param filter - a file string using the hbase filter language
/// @see the filter language at https://issues.apache.org/jira/browse/HBASE-4176
int set_filter(const ObString &filter);
const ObIArray<ObString> &get_columns() const { return select_column_qualifier_; }
bool with_latest_timestamp() const { return with_all_time() && 1 == max_versions_; }
bool with_timestamp() const { return min_stamp_ == max_stamp_ && min_stamp_ >= 0; }
bool with_all_time() const { return ObHTableConstants::INITIAL_MIN_STAMP == min_stamp_ && ObHTableConstants::INITIAL_MAX_STAMP == max_stamp_; }
int64_t get_min_stamp() const { return min_stamp_; }
int64_t get_max_stamp() const { return max_stamp_; }
int32_t get_max_versions() const { return max_versions_; }
int32_t get_max_results_per_column_family() const { return limit_per_row_per_cf_; }
int32_t get_row_offset_per_column_family() const { return offset_per_row_per_cf_; }
const ObString &get_filter() const { return filter_string_; }
void clear_columns() { select_column_qualifier_.reset(); }
uint64_t get_checksum() const;
int deep_copy(ObIAllocator &allocator, ObHTableFilter &dst) const;
TO_STRING_KV(K_(is_valid),
"column_qualifier", select_column_qualifier_,
K_(min_stamp),
K_(max_stamp),
K_(max_versions),
K_(limit_per_row_per_cf),
K_(offset_per_row_per_cf),
K_(filter_string));
private:
bool is_valid_;
ObSEArray<ObString, 16> select_column_qualifier_;
int64_t min_stamp_; // default -1
int64_t max_stamp_; // default -1
int32_t max_versions_; // default 1
int32_t limit_per_row_per_cf_; // default -1 means unlimited
int32_t offset_per_row_per_cf_; // default 0
ObString filter_string_;
};
enum ObTableAggregationType
{
INVAILD = 0,
MAX = 1,
MIN = 2,
COUNT = 3,
SUM = 4,
AVG = 5,
};
class ObTableAggregation
{
OB_UNIS_VERSION(1);
public:
ObTableAggregation()
: type_(ObTableAggregationType::INVAILD),
column_()
{}
ObTableAggregationType get_type() const { return type_; }
const common::ObString &get_column() const { return column_; }
bool is_agg_all_column() const { return column_ == "*"; };
int deep_copy(common::ObIAllocator &allocator, ObTableAggregation &dst) const;
TO_STRING_KV(K_(type), K_(column));
private:
ObTableAggregationType type_; // e.g. max
common::ObString column_; // e.g. age
};
/// A table query
/// 1. support multi range scan
/// 2. support reverse scan
/// 3. support secondary index scan
class ObTableQuery final
{
OB_UNIS_VERSION(1);
public:
ObTableQuery()
:deserialize_allocator_(NULL),
key_ranges_(),
select_columns_(),
filter_string_(),
limit_(-1),
offset_(0),
scan_order_(common::ObQueryFlag::Forward),
index_name_(),
batch_size_(-1),
max_result_size_(-1),
htable_filter_(),
scan_range_columns_(),
aggregations_()
{}
~ObTableQuery() = default;
void reset();
bool is_valid() const;
/// add a scan range, the number of scan ranges should be >=1.
int add_scan_range(common::ObNewRange &scan_range);
/// Scan order: Forward (By default) and Reverse.
int set_scan_order(common::ObQueryFlag::ScanOrder scan_order);
/// Set the index to scan, could be 'PRIMARY' (by default) or any other secondary index.
int set_scan_index(const ObString &index_name);
/// Add select columns.
int add_select_column(const ObString &columns);
/// Set the max rows to return. The value of -1 represents there is NO limit. The default value is -1.
/// For htable, set the limit of htable rows for this scan.
int set_limit(int32_t limit);
/// Set the offset to return. The default value is 0.
int set_offset(int32_t offset);
/// Add filter, currently NOT supported.
int set_filter(const ObString &filter);
/// Add filter only for htable.
ObHTableFilter& htable_filter() { return htable_filter_; }
/// Set max row count of each batch.
/// For htable, set the maximum number of cells to return for each call to next().
int set_batch(int32_t batch_size);
/// Set the maximum result size.
/// The default is -1; this means that no specific maximum result size will be set for this query.
/// @param max_result_size - The maximum result size in bytes.
int set_max_result_size(int64_t max_result_size);
const ObIArray<ObString> &get_select_columns() const { return select_columns_; }
const ObIArray<common::ObNewRange> &get_scan_ranges() const { return key_ranges_; }
int32_t get_limit() const { return limit_; }
int32_t get_offset() const { return offset_; }
common::ObQueryFlag::ScanOrder get_scan_order() const { return scan_order_; }
const ObString &get_index_name() const { return index_name_; }
const ObHTableFilter& get_htable_filter() const { return htable_filter_; }
int32_t get_batch() const { return batch_size_; }
int64_t get_max_result_size() const { return max_result_size_; }
int64_t get_range_count() const { return key_ranges_.count(); }
uint64_t get_checksum() const;
const ObString &get_filter_string() const { return filter_string_; }
void clear_scan_range() { key_ranges_.reset(); }
void set_deserialize_allocator(common::ObIAllocator *allocator) { deserialize_allocator_ = allocator; }
int deep_copy(ObIAllocator &allocator, ObTableQuery &dst) const;
const common::ObIArray<ObTableAggregation> &get_aggregations() const { return aggregations_; }
bool is_aggregate_query() const { return !aggregations_.empty(); }
TO_STRING_KV(K_(key_ranges),
K_(select_columns),
K_(filter_string),
K_(limit),
K_(offset),
K_(scan_order),
K_(index_name),
K_(batch_size),
K_(max_result_size),
K_(htable_filter),
K_(scan_range_columns),
K_(aggregations));
public:
static ObString generate_filter_condition(const ObString &column, const ObString &op, const ObObj &value);
static ObString combile_filters(const ObString &filter1, const ObString &op, const ObString &filter2);
static common::ObNewRange generate_prefix_scan_range(const ObRowkey &rowkey_prefix);
private:
common::ObIAllocator *deserialize_allocator_;
ObSEArray<common::ObNewRange, 16> key_ranges_;
ObSEArray<ObString, 16> select_columns_;
ObString filter_string_;
int32_t limit_; // default -1 means unlimited
int32_t offset_;
common::ObQueryFlag::ScanOrder scan_order_;
ObString index_name_;
int32_t batch_size_;
int64_t max_result_size_;
ObHTableFilter htable_filter_;
ObSEArray<ObString, 8> scan_range_columns_;
ObSEArray<ObTableAggregation, 8> aggregations_;
};
/// result for ObTableQuery
class ObTableEntityIterator
{
public:
ObTableEntityIterator() = default;
virtual ~ObTableEntityIterator();
/**
* fetch the next entity
* @return OB_ITER_END when finished
*/
virtual int get_next_entity(const ObITableEntity *&entity) = 0;
};
/// query and mutate the selected rows.
class ObTableQueryAndMutate final
{
OB_UNIS_VERSION(1);
public:
ObTableQueryAndMutate()
:return_affected_entity_(true)
{}
const ObTableQuery &get_query() const { return query_; }
ObTableQuery &get_query() { return query_; }
const ObTableBatchOperation &get_mutations() const { return mutations_; }
ObTableBatchOperation &get_mutations() { return mutations_; }
bool return_affected_entity() const { return return_affected_entity_; }
void set_deserialize_allocator(common::ObIAllocator *allocator);
void set_entity_factory(ObITableEntityFactory *entity_factory);
uint64_t get_checksum();
TO_STRING_KV(K_(query),
K_(mutations));
private:
ObTableQuery query_;
ObTableBatchOperation mutations_;
bool return_affected_entity_;
};
inline void ObTableQueryAndMutate::set_deserialize_allocator(common::ObIAllocator *allocator)
{
query_.set_deserialize_allocator(allocator);
}
inline void ObTableQueryAndMutate::set_entity_factory(ObITableEntityFactory *entity_factory)
{
mutations_.set_entity_factory(entity_factory);
}
class ObTableQueryResult: public ObTableEntityIterator
{
OB_UNIS_VERSION(1);
public:
ObTableQueryResult();
virtual ~ObTableQueryResult() {}
void reset();
void reset_except_property();
void rewind();
virtual int get_next_entity(const ObITableEntity *&entity) override;
int add_property_name(const ObString &name);
int assign_property_names(const common::ObIArray<common::ObString> &other);
// for aggregation
int deep_copy_property_names(const common::ObIArray<common::ObString> &other);
void reset_property_names() { properties_names_.reset(); }
int add_row(const common::ObNewRow &row);
int add_row(const common::ObIArray<ObObj> &row);
int add_all_property(const ObTableQueryResult &other);
int add_all_row(const ObTableQueryResult &other);
int64_t get_row_count() const { return row_count_; }
int64_t get_property_count() const { return properties_names_.count(); }
int64_t get_result_size();
int get_first_row(common::ObNewRow &row) const;
bool reach_batch_size_or_result_size(const int32_t batch_count,
const int64_t max_result_size);
const common::ObIArray<common::ObString>& get_select_columns() const { return properties_names_; };
static int64_t get_max_packet_buffer_length() { return obrpc::get_max_rpc_packet_size() - (1<<20); }
static int64_t get_max_buf_block_size() { return get_max_packet_buffer_length() - (1024*1024LL); }
TO_STRING_KV(K(properties_names_), K(row_count_), K(buf_.get_position()));
private:
static const int64_t DEFAULT_BUF_BLOCK_SIZE = common::OB_MALLOC_BIG_BLOCK_SIZE - (1024*1024LL);
int alloc_buf_if_need(const int64_t size);
private:
common::ObSEArray<ObString, 16> properties_names_; // serialize
int64_t row_count_; // serialize
common::ObDataBuffer buf_; // serialize
common::ObArenaAllocator allocator_;
common::ObArenaAllocator prop_name_allocator_;
int64_t fixed_result_size_;
// for deserialize and read
int64_t curr_idx_;
ObTableEntity curr_entity_;
};
class ObTableQueryAndMutateResult final
{
OB_UNIS_VERSION(1);
public:
TO_STRING_KV(K_(affected_rows));
public:
int64_t affected_rows_;
// If return_affected_entity_ in ObTableQueryAndMutate is set, then return the respond entity.
// In the case of delete and insert_or_update, return the old rows before modified.
// In the case of increment and append, return the new rows after modified.
ObTableQueryResult affected_entity_;
};
class ObTableQuerySyncResult: public ObTableQueryResult
{
OB_UNIS_VERSION(1);
public:
ObTableQuerySyncResult()
: is_end_(false),
query_session_id_(0)
{}
virtual ~ObTableQuerySyncResult() {}
public:
bool is_end_;
uint64_t query_session_id_; // from server gen
};
struct ObTableApiCredential final
{
OB_UNIS_VERSION(1);
public:
ObTableApiCredential();
~ObTableApiCredential();
public:
int64_t cluster_id_;
uint64_t tenant_id_;
uint64_t user_id_;
uint64_t database_id_;
int64_t expire_ts_;
uint64_t hash_val_;
public:
int hash(uint64_t &hash_val, uint64_t seed = 0) const;
TO_STRING_KV(K_(cluster_id),
K_(tenant_id),
K_(user_id),
K_(database_id),
K_(expire_ts),
K_(hash_val));
};
/// Table Direct Load Operation Type
enum class ObTableDirectLoadOperationType {
BEGIN = 0,
COMMIT = 1,
ABORT = 2,
GET_STATUS = 3,
INSERT = 4,
HEART_BEAT = 5,
MAX_TYPE
};
class ObTableTTLOperationResult
{
public:
ObTableTTLOperationResult()
: ttl_del_rows_(0),
max_version_del_rows_(0),
scan_rows_(0),
end_rowkey_(),
iter_end_ts_(0)
{}
~ObTableTTLOperationResult() {}
uint64_t get_ttl_del_row() { return ttl_del_rows_; }
uint64_t get_max_version_del_row() { return max_version_del_rows_; }
uint64_t get_del_row() { return ttl_del_rows_ + max_version_del_rows_; }
uint64_t get_scan_row() { return scan_rows_; }
common::ObString get_end_rowkey() { return end_rowkey_; }
int64_t get_end_ts() { return iter_end_ts_; }
TO_STRING_KV(K_(ttl_del_rows), K_(max_version_del_rows), K_(scan_rows), K_(end_rowkey), K_(iter_end_ts));
public:
uint64_t ttl_del_rows_;
uint64_t max_version_del_rows_;
uint64_t scan_rows_;
common::ObString end_rowkey_;
int64_t iter_end_ts_;
};
struct ObTableMoveReplicaInfo final
{
OB_UNIS_VERSION(1);
public:
ObTableMoveReplicaInfo()
: table_id_(common::OB_INVALID_ID),
schema_version_(common::OB_INVALID_VERSION),
tablet_id_(common::ObTabletID::INVALID_TABLET_ID),
role_(common::ObRole::INVALID_ROLE),
replica_type_(common::ObReplicaType::REPLICA_TYPE_MAX),
part_renew_time_(0),
reserved_(0)
{}
virtual ~ObTableMoveReplicaInfo() {}
TO_STRING_KV(K_(table_id),
K_(schema_version),
K_(part_renew_time),
K_(tablet_id),
K_(server),
K_(role),
K_(replica_type),
K_(reserved));
OB_INLINE void set_table_id(const uint64_t table_id) { table_id_ = table_id; }
OB_INLINE void set_schema_version(const uint64_t schema_version) { schema_version_ = schema_version; }
OB_INLINE void set_tablet_id(const common::ObTabletID &tablet_id) { tablet_id_ = tablet_id; }
public:
uint64_t table_id_;
uint64_t schema_version_;
common::ObTabletID tablet_id_;
common::ObAddr server_;
common::ObRole role_;
common::ObReplicaType replica_type_;
int64_t part_renew_time_;
uint64_t reserved_;
};
class ObTableMoveResult final
{
OB_UNIS_VERSION(1);
public:
ObTableMoveResult()
: reserved_(0)
{}
virtual ~ObTableMoveResult() {}
TO_STRING_KV(K_(replica_info),
K_(reserved));
OB_INLINE ObTableMoveReplicaInfo& get_replica_info() { return replica_info_; }
private:
ObTableMoveReplicaInfo replica_info_;
uint64_t reserved_;
};
} // end namespace table
} // end namespace oceanbase
#endif /* _OB_TABLE_TABLE_H */