Files
oceanbase/src/sql/engine/dml/ob_table_modify_op.h

255 lines
9.8 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 OCEANBASE_SQL_ENGINE_DML_OB_TABLE_MODIFY_OP_
#define OCEANBASE_SQL_ENGINE_DML_OB_TABLE_MODIFY_OP_
#include "sql/engine/ob_operator.h"
#include "sql/engine/dml/ob_dml_ctx_define.h"
#include "observer/ob_inner_sql_connection.h"
#include "sql/engine/ob_exec_context.h"
namespace oceanbase
{
namespace sql
{
class ForeignKeyHandle
{
public:
struct ObFkRowResInfo
{
ObExpr* rt_expr_;
ObDatum ori_datum_;
TO_STRING_KV(K_(rt_expr), K_(ori_datum));
};
static int do_handle(ObTableModifyOp &op,
const ObDMLBaseCtDef &dml_ctdef,
ObDMLBaseRtDef &dml_rtdef);
private:
static int value_changed(ObTableModifyOp &op,
const common::ObIArray<ObForeignKeyColumn> &columns,
const ObExprPtrIArray &old_row,
const ObExprPtrIArray &new_row,
bool &has_changed);
static int check_exist(ObTableModifyOp &modify_op, const ObForeignKeyArg &fk_arg,
const ObExprPtrIArray &row, bool expect_zero);
static int cascade(ObTableModifyOp &modify_op, const ObForeignKeyArg &fk_arg,
const ObExprPtrIArray &old_row, const ObExprPtrIArray &new_row);
static int gen_set(ObEvalCtx &eval_ctx, char *&buf, int64_t &len, int64_t &pos,
const common::ObIArray<ObForeignKeyColumn> &columns,
const ObExprPtrIArray &row, common::ObIAllocator &alloc,
const common::ObObjPrintParams &print_params);
static int gen_where(ObEvalCtx &eval_ctx, char *&buf, int64_t &len, int64_t &pos,
const common::ObIArray<ObForeignKeyColumn> &columns,
const ObExprPtrIArray &row, common::ObIAllocator &alloc,
const common::ObObjPrintParams &print_params);
static int gen_column_value(ObEvalCtx &ctx, char *&buf, int64_t &len, int64_t &pos,
const common::ObIArray<ObForeignKeyColumn> &columns,
const ObExprPtrIArray &row, const char *delimiter,
common::ObIAllocator &alloc,
const common::ObObjPrintParams &print_params, bool forbid_null);
static int is_self_ref_row(ObEvalCtx &ctx, const ObExprPtrIArray &row,
const ObForeignKeyArg &fk_arg, bool &is_self_ref);
};
class ObTableModifyOp;
class ObTableModifySpec : public ObOpSpec
{
OB_UNIS_VERSION_V(1);
public:
ObTableModifySpec(common::ObIAllocator &alloc, const ObPhyOperatorType type);
virtual ~ObTableModifySpec() {}
virtual bool is_dml_operator() const override { return true; }
//This interface is only allowed to be used in a single-table DML operator,
//it is invalid when multiple tables are modified in one DML operator
int get_single_table_loc_id(common::ObTableID &table_loc_id,
common::ObTableID &ref_table_id) const
{
const ObDMLBaseCtDef *dml_ctdef = nullptr;
int ret = get_single_dml_ctdef(dml_ctdef);
if (common::OB_SUCCESS == ret) {
table_loc_id = dml_ctdef->das_base_ctdef_.table_id_;
ref_table_id = dml_ctdef->das_base_ctdef_.index_tid_;
}
return ret;
}
//This interface is only allowed to be used in a single-table DML operator,
//it is invalid when multiple tables are modified in one DML operator
virtual int get_single_dml_ctdef(const ObDMLBaseCtDef *&dml_ctdef) const
{
UNUSED(dml_ctdef);
return common::OB_NOT_IMPLEMENT;
}
void set_table_location_uncertain(bool v) { table_location_uncertain_ = v; }
bool is_table_location_uncertain() const { return table_location_uncertain_; }
inline bool use_dist_das() const { return use_dist_das_; }
public:
// Expr frame info for partial expr serialization. (serialize is not need for it self)
ObExprFrameInfo *expr_frame_info_;
ObExpr *ab_stmt_id_; //mark the stmt id for array binding batch execution
union {
uint64_t flags_;
struct {
uint64_t is_ignore_ : 1;
uint64_t gi_above_ : 1;
uint64_t is_returning_ : 1;
uint64_t is_pdml_index_maintain_ : 1; // 表示当前dml算子是否是pdml中用于维护索引操作的算子(index maintain)
uint64_t table_location_uncertain_ : 1; // 目标访问分区位置不确定,需要全表访问
uint64_t use_dist_das_ : 1;
uint64_t has_instead_of_trigger_ : 1; // abandoned, don't use again
uint64_t is_pdml_update_split_ : 1; // 标记delete, insert op是否由update拆分而来
uint64_t reserved_ : 56;
};
};
private:
DISALLOW_COPY_AND_ASSIGN(ObTableModifySpec);
};
class ObTableModifyOpInput : public ObOpInput
{
public:
friend class ObTableModifyOp;
OB_UNIS_VERSION_V(1);
public:
ObTableModifyOpInput(ObExecContext &ctx, const ObOpSpec &spec)
: ObOpInput(ctx, spec),
table_loc_(nullptr),
tablet_loc_(nullptr)
{ }
virtual ~ObTableModifyOpInput() { }
virtual int init(ObTaskInfo &task_info) override { UNUSED(task_info); return common::OB_SUCCESS; }
virtual void reset()
{
table_loc_ = nullptr;
tablet_loc_ = nullptr;
}
inline void set_tablet_loc(ObDASTabletLoc *tablet_loc) { tablet_loc_ = tablet_loc; }
inline ObDASTabletLoc *get_tablet_loc() { return tablet_loc_; }
inline ObDASTableLoc *get_table_loc() { return table_loc_; }
const ObTableModifySpec &get_spec() const
{
return static_cast<const ObTableModifySpec &>(spec_);
}
TO_STRING_KV(KPC_(table_loc), KPC_(tablet_loc));
protected:
ObDASTableLoc *table_loc_;
ObDASTabletLoc *tablet_loc_; //for single table modify op
private:
DISALLOW_COPY_AND_ASSIGN(ObTableModifyOpInput);
};
class ObTableModifyOp: public ObOperator
{
public:
ObTableModifyOp(ObExecContext &ctx, const ObOpSpec &spec, ObOpInput *input);
virtual ~ObTableModifyOp() {}
virtual int inner_switch_iterator() override;
int is_valid();
sql::ObSQLSessionInfo::StmtSavedValue &get_saved_session()
{
if (NULL == saved_session_) {
saved_session_ = new (saved_session_buf_) sql::ObSQLSessionInfo::StmtSavedValue();
}
return *saved_session_;
}
const ObTableModifySpec &get_spec() const
{
return static_cast<const ObTableModifySpec &>(spec_);
}
ObTableModifyOpInput *get_input() const
{
return static_cast<ObTableModifyOpInput *>(input_);
}
virtual void destroy() override
{
dml_rtctx_.cleanup();
trigger_clear_exprs_.reset();
ObOperator::destroy();
}
public:
int open_inner_conn();
int close_inner_conn();
int begin_nested_session(bool skip_cur_stmt_tables);
int end_nested_session();
int set_foreign_key_cascade(bool is_cascade);
int get_foreign_key_cascade(bool &is_cascade) const;
int set_foreign_key_check_exist(bool is_check_exist);
int get_foreign_key_check_exist(bool &is_check_exist) const;
int execute_write(const char *sql);
int execute_read(const char *sql, common::ObMySQLProxy::MySQLResult &res);
int check_stack();
bool is_nested_session() { return is_nested_session_; }
void set_foreign_key_checks() { foreign_key_checks_ = true; }
bool need_foreign_key_checks() { return foreign_key_checks_; }
const ObObjPrintParams &get_obj_print_params() { return obj_print_params_; }
int init_foreign_key_operation();
void log_user_error_inner(int ret, int64_t col_idx, int64_t row_num,
const ObIArray<ColumnContent> &column_infos) const;
void log_user_error_inner(int ret, int64_t row_num, const ColumnContent &column_info) const;
void clear_dml_evaluated_flag();
void clear_dml_evaluated_flag(int64_t parent_cnt, ObExpr **parent_exprs);
void clear_dml_evaluated_flag(ObExpr *clear_expr);
protected:
OperatorOpenOrder get_operator_open_order() const;
virtual int inner_open();
virtual int inner_close();
int get_gi_task();
//It is used for the execution without routing through DAS.
//In this case, the DML operator only allows to modify a single table,
//and the table location is specified by the scheduling framework.
int calc_single_table_loc();
virtual int inner_rescan() override;
int submit_all_dml_task();
int init_das_dml_ctx();
//to merge array binding cusor info when array binding is executed in batch mode
int merge_implict_cursor(int64_t insert_rows,
int64_t update_rows,
int64_t delete_rows,
int64_t found_rows);
public:
common::ObMySQLProxy *sql_proxy_;
observer::ObInnerSQLConnection *inner_conn_;
uint64_t tenant_id_;
observer::ObInnerSQLConnection::SavedValue saved_conn_;
bool is_nested_session_;
bool foreign_key_checks_;
bool need_close_conn_;
ObObjPrintParams obj_print_params_;
bool iter_end_;
ObDMLRtCtx dml_rtctx_;
bool is_error_logging_;
ObErrLogRtDef err_log_rt_def_;
ObSEArray<ObExpr *, 4> trigger_clear_exprs_;
private:
ObSQLSessionInfo::StmtSavedValue *saved_session_;
char saved_session_buf_[sizeof(ObSQLSessionInfo::StmtSavedValue)] __attribute__((aligned (16)));;
// used by check_rowkey_whether_distinct
static const int64_t MIN_ROWKEY_DISTINCT_BUCKET_NUM = 1 * 1024;
static const int64_t MAX_ROWKEY_DISTINCT_BUCKET_NUM = 1 * 1024 * 1024;
};
} // namespace sql
} // namespace oceanbase
#endif