patch 4.0

This commit is contained in:
wangzelin.wzl
2022-10-24 10:34:53 +08:00
parent 4ad6e00ec3
commit 93a1074b0c
10533 changed files with 2588271 additions and 2299373 deletions

View File

@ -19,41 +19,69 @@ using namespace oceanbase::sql;
using namespace oceanbase::common;
using namespace oceanbase::sql::log_op_def;
namespace oceanbase {
namespace sql {
namespace oceanbase
{
namespace sql
{
ObLogLink::ObLogLink(ObLogPlan& plan)
: ObLogicalOperator(plan),
allocator_(plan.get_allocator()),
link_stmt_(plan.get_allocator(), output_exprs_),
stmt_fmt_buf_(NULL),
stmt_fmt_buf_len_(0),
stmt_fmt_len_(0),
param_infos_()
ObLogLink::ObLogLink(ObLogPlan &plan)
: ObLogicalOperator(plan),
allocator_(plan.get_allocator()),
stmt_fmt_buf_(NULL),
stmt_fmt_len_(0),
param_infos_()
{}
int ObLogLink::copy_without_child(ObLogicalOperator*& out)
int ObLogLink::est_cost()
{
int ret = OB_SUCCESS;
out = NULL;
ObLogicalOperator* op = NULL;
ObLogLink* link = NULL;
if (OB_FAIL(clone(op))) {
LOG_WARN("failed to clone ObLogTableScan", K(ret));
} else if (OB_ISNULL(link = static_cast<ObLogLink*>(op))) {
ObLogicalOperator *child = NULL;
if (OB_ISNULL(child = get_child(ObLogicalOperator::first_child))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to cast ObLogicalOpertor* to ObLogLink*", K(ret));
} else if (OB_FAIL(link->assign_stmt_fmt(stmt_fmt_buf_, stmt_fmt_len_))) {
LOG_WARN("failed to assign stmt fmt", K(ret));
} else if (OB_FAIL(link->assign_param_infos(param_infos_))) {
LOG_WARN("failed to assign param infos", K(ret));
LOG_WARN("get unexpected null", K(child), K(ret));
} else {
out = link;
card_ = child->get_card();
op_cost_ = 0;
cost_ = op_cost_ + child->get_cost();
}
return ret;
}
int ObLogLink::print_my_plan_annotation(char* buf, int64_t& buf_len, int64_t& pos, ExplainType type)
int ObLogLink::print_link_stmt(char *buf, int64_t buf_len)
{
int ret = OB_SUCCESS;
if (stmt_fmt_len_ > buf_len) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("print link stmt failed", K(ret), K(stmt_fmt_len_), K(buf_len));
} else {
MEMCPY(buf, stmt_fmt_buf_, stmt_fmt_len_);
char *ch = buf;
char *stmt_end = buf + stmt_fmt_len_ - 3;
while (ch < stmt_end) {
if (0 == ch[0] && 0 == ch[1]) {
uint16_t param_idx = *(uint16_t *)(ch + 2);
ch[0] = '$';
if (param_idx > 999) {
ch[1] = 'M';
ch[2] = 'A';
ch[3] = 'X';
} else {
ch[3] = static_cast<char>('0' + param_idx % 10);
param_idx /= 10;
ch[2] = static_cast<char>('0' + param_idx % 10);
param_idx /= 10;
ch[1] = static_cast<char>('0' + param_idx % 10);
}
ch += 4;
} else {
ch++;
}
}
}
return ret;
}
int ObLogLink::print_my_plan_annotation(char *buf, int64_t &buf_len, int64_t &pos, ExplainType type)
{
UNUSED(type);
int ret = OB_SUCCESS;
@ -62,188 +90,28 @@ int ObLogLink::print_my_plan_annotation(char* buf, int64_t& buf_len, int64_t& po
LOG_WARN("BUF_PRINTF failed", K(ret));
} else if (OB_FAIL(BUF_PRINTF("\n link_stmt="))) {
LOG_WARN("BUF_PRINTF failed", K(ret));
} else if ((len = link_stmt_.to_string(buf + pos, buf_len - pos)) <= 0) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("link stmt to string failed", K(ret), K(link_stmt_));
} else if (OB_FAIL(print_link_stmt(buf + pos, buf_len - pos))) {
LOG_WARN("failed to print link stmt", K(ret));
} else {
pos += len;
pos += stmt_fmt_len_;
}
return ret;
}
int ObLogLink::allocate_exchange_post(AllocExchContext* ctx)
int ObLogLink::generate_link_sql_post(GenLinkStmtPostContext &link_ctx)
{
int ret = OB_SUCCESS;
UNUSED(ctx);
return ret;
}
int ObLogLink::generate_link_sql_pre(GenLinkStmtContext& link_ctx)
{
/**
* TODO
* add database_name in select_strs, or in from_strs ?
* can not use "use db" because two tables in different database can join.
*/
/*
* OceanBase(ADMIN@TEST)>explain
* -> select (aa + 1) * (aa - 1), xx from (select a aa, x xx from test.t1@my_link1 lt1 union select c, y from
* test.t2@my_link1 lt2) tt; | ================================================ |ID|OPERATOR |NAME|EST.
* ROWS|COST |
* ------------------------------------------------
* |0 |LINK | |0 |371744|
* |1 | SUBPLAN SCAN |TT |200000 |371744|
* |2 | HASH UNION DISTINCT| |200000 |344139|
* |3 | TABLE SCAN |LT1 |100000 |61860 |
* |4 | TABLE SCAN |LT2 |100000 |61860 |
* ================================================
*
* Outputs & filters:
* -------------------------------------
* 0 - output([((TT.AA + 1) * (TT.AA - 1))], [TT.XX]), filter(nil), dblink_id=1100611139403793,
* link_stmt=select ((TT.AA + 1) * (TT.AA - 1)), TT.XX from ((select LT1.A AA, LT1.X XX from T1 LT1) union
* (select LT2.C, LT2.Y from T2 LT2)) TT 1 - output([TT.XX], [((TT.AA + 1) * (TT.AA - 1))]), filter(nil),
* access([TT.AA], [TT.XX])
* 2 - output([UNION(LT1.A, LT2.C)], [UNION(cast(LT1.X, VARCHAR(10 BYTE)), cast(LT2.Y, VARCHAR(10 BYTE)))]),
* filter(nil) 3 - output([LT1.A], [cast(LT1.X, VARCHAR(10 BYTE))]), filter(nil), access([LT1.A], [LT1.X]),
* partitions(p0) 4 - output([LT2.C], [cast(LT2.Y, VARCHAR(10 BYTE))]), filter(nil), access([LT2.C], [LT2.Y]),
* partitions(p0)
*
* that is why we must fill select clause in link, even if every log op will fill it if
* empty: the output of op 1 'SUBPLAN SCAN' is '[TT.XX], [((TT.AA + 1) * (TT.AA - 1))]',
* while we need 'select (TT.AA + 1) * (TT.AA - 1), TT.XX', the sequence of these two
* exprs is opposite.
* the sequence of output exprs in op 0 'LINK' is correct.
*
* here is another example, the sequence of op 0 'LINK' and op 1 'SORT' is correct, but
* op 2 'TABLE SCAN' is wrong.
*
* OceanBase(ADMIN@TEST)>explain basic
* -> select mod(a, 3), x from test.t1@my_link1 order by 1, 2;
*
* | ======================
* |ID|OPERATOR |NAME|
* ----------------------
* |0 |LINK | |
* |1 | SORT | |
* |2 | TABLE SCAN|T1 |
* ======================
*
* Outputs & filters:
* -------------------------------------
* 0 - output([(T1.A % 3)], [T1.X]), filter(nil), dblink_id=1100611139403793,
* link_stmt=select T1.X, MOD(T1.A, 3) from T1 order by 1 asc, 2 asc
* 1 - output([(T1.A % 3)], [T1.X]), filter(nil), sort_keys([(T1.A % 3), ASC], [T1.X, ASC])
* 2 - output([T1.X], [(T1.A % 3)]), filter(nil),
* access([T1.A], [T1.X]), partitions(p0)
*/
/*
* OceanBase(ADMIN@TEST)>explain
* -> select a - 3, concat(b, x) from t1 union select c, d from t2;
*
* | ============================================
* |ID|OPERATOR |NAME|EST. ROWS|COST|
* --------------------------------------------
* |0 |HASH UNION DISTINCT| |10 |85 |
* |1 | TABLE SCAN |T1 |5 |37 |
* |2 | TABLE SCAN |T2 |5 |37 |
* ============================================
*
* Outputs & filters:
* -------------------------------------
* 0 - output([UNION((T1.A - 3), cast(T2.C, DECIMAL(-1, -85)))], [UNION(CONCAT(T1.B, T1.X), cast(T2.D, VARCHAR(20
* BYTE)))]), filter(nil) 1 - output([(T1.A - 3)], [CONCAT(T1.B, T1.X)]), filter(nil), access([T1.A], [T1.B], [T1.X]),
* partitions(p0) 2 - output([cast(T2.C, DECIMAL(-1, -85))], [cast(T2.D, VARCHAR(20 BYTE))]), filter(nil),
* access([T2.C], [T2.D]), partitions(p0)
*
* OceanBase(ADMIN@TEST)>select T1.A - 3 from (select a - 3, concat(b, x) from t1 union select c, d from t2);
* ERROR-00904: invalid identifier 'T1.A' in 'field list'
*
* that is why we must NOT fill select clause if the child is set, even if we can extract
* 'T1.A - 3' from 'UNION((T1.A - 3), cast(T2.C, DECIMAL(-1, -85)))'.
* so just keep select clause empty.
* ps: set op include union / intersect / except / minus.
*/
/* merge-join
* / \
* table-scan link
* |
* merge-join
* / \
* sort sort
*
* that is why we must fill order by clause using the op_ordering of link rather
* than sort, the top merge-join need the 'op_ordering' of link.
*/
/*
* OceanBase(ADMIN@TEST)>explain
* -> select a - 3, x from test.t1@my_link1 union select c * 2, y from test.t2@my_link1 order by 1;
* | =================================================
* |ID|OPERATOR |NAME|EST. ROWS|COST |
* -------------------------------------------------
* |0 |LINK | |0 |1070149|
* |1 | MERGE UNION DISTINCT| |200000 |1070149|
* |2 | SORT | |100000 |496872 |
* |3 | TABLE SCAN |T1 |100000 |61860 |
* |4 | SORT | |100000 |496872 |
* |5 | TABLE SCAN |T2 |100000 |61860 |
* =================================================
*
* Outputs & filters:
* -------------------------------------
* 0 - output([UNION((T1.A - 3), (T2.C * 2))], [UNION(cast(T1.X, VARCHAR(10 BYTE)), cast(T2.Y, VARCHAR(10 BYTE)))]),
* filter(nil), dblink_id=1100611139403793, link_stmt=(select (T1.A - 3), T1.X from (select T1.A, T1.X from T1) T1)
* union (select (T2.C * 2), T2.Y from (select T2.C, T2.Y from T2) T2) order by 1 asc, 2 asc 1 - output([UNION((T1.A -
* 3), (T2.C * 2))], [UNION(cast(T1.X, VARCHAR(10 BYTE)), cast(T2.Y, VARCHAR(10 BYTE)))]), filter(nil) 2 -
* output([(T1.A - 3)], [cast(T1.X, VARCHAR(10 BYTE))]), filter(nil), sort_keys([(T1.A - 3), ASC], [cast(T1.X,
* VARCHAR(10 BYTE)), ASC]) 3 - output([(T1.A - 3)], [cast(T1.X, VARCHAR(10 BYTE))]), filter(nil), access([T1.A],
* [T1.X]), partitions(p0) 4 - output([(T2.C * 2)], [cast(T2.Y, VARCHAR(10 BYTE))]), filter(nil), sort_keys([(T2.C *
* 2), ASC], [cast(T2.Y, VARCHAR(10 BYTE)), ASC]) 5 - output([(T2.C * 2)], [cast(T2.Y, VARCHAR(10 BYTE))]),
* filter(nil), access([T2.C], [T2.Y]), partitions(p0)
*
* another reason that we must fill order by clause using the op_ordering of link
* rather than sort, the orig sort above union is pushed down to table scan.
*/
int ret = OB_SUCCESS;
if (OB_FAIL(link_stmt_.init(&link_ctx))) {
LOG_WARN("failed to init link stmt", K(ret), K(dblink_id_));
} else if (OB_FAIL(link_stmt_.fill_orderby_strs(get_op_ordering(), output_exprs_))) {
LOG_WARN("failed to fill link stmt orderby strs", K(ret), K(get_op_ordering()));
if (OB_FAIL(link_ctx.spell_link(static_cast<const ObSelectStmt *>(get_stmt()),
&stmt_fmt_buf_,
stmt_fmt_len_,
get_op_ordering(),
output_exprs_,
startup_exprs_,
filter_exprs_))) {
LOG_WARN("dblink fail to reverse spell link", K(dblink_id_), K(ret));
} else {
link_ctx.dblink_id_ = dblink_id_;
link_ctx.link_stmt_ = &link_stmt_;
}
return ret;
}
int ObLogLink::gen_link_stmt_fmt()
{
int ret = OB_SUCCESS;
if (!link_stmt_.is_inited()) {
ret = OB_NOT_INIT;
LOG_WARN("link stmt is not inited", K(ret));
} else if (OB_FAIL(gen_link_stmt_fmt_buf())) {
LOG_WARN("failed to gen link stmt fmt buf", K(ret), K(link_stmt_));
} else if (OB_FAIL(gen_link_stmt_param_infos())) {
LOG_WARN("failed to gen link stmt param infos", K(ret), K(link_stmt_));
}
return ret;
}
int ObLogLink::gen_link_stmt_fmt_buf()
{
int ret = OB_SUCCESS;
stmt_fmt_buf_len_ = link_stmt_.get_total_size();
if (OB_ISNULL(stmt_fmt_buf_ = static_cast<char*>(allocator_.alloc(stmt_fmt_buf_len_)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc stmt buf", K(ret), K(stmt_fmt_buf_len_));
} else if (OB_FAIL(link_stmt_.gen_stmt_fmt(stmt_fmt_buf_, stmt_fmt_buf_len_, stmt_fmt_len_))) {
LOG_WARN("failed to gen link stmt fmt", K(ret));
LOG_WARN("dblink stmt", K(ObString(stmt_fmt_len_, stmt_fmt_buf_)));
link_ctx.reset();
}
return ret;
}
@ -266,8 +134,8 @@ int ObLogLink::gen_link_stmt_param_infos()
LOG_WARN("failed to read next param", K(ret));
} else if (param_idx < 0) {
// skip.
} else if (OB_FAIL(param_infos_.push_back(
ObParamPosIdx(static_cast<int32_t>(param_pos), static_cast<int32_t>(param_idx))))) {
} else if (OB_FAIL(param_infos_.push_back(ObParamPosIdx(static_cast<int32_t>(param_pos),
static_cast<int32_t>(param_idx))))) {
LOG_WARN("failed to push back param pos idx", K(ret), K(param_pos), K(param_idx));
} else {
param_pos += param_len;
@ -276,34 +144,5 @@ int ObLogLink::gen_link_stmt_param_infos()
return ret;
}
int ObLogLink::assign_param_infos(const ObIArray<ObParamPosIdx>& param_infos)
{
int ret = OB_SUCCESS;
param_infos_.reset();
for (int64_t i = 0; OB_SUCC(ret) && i < param_infos.count(); i++) {
if (OB_FAIL(param_infos_.push_back(param_infos.at(i)))) {
LOG_WARN("failed to push back param info", K(ret), K(param_infos.at(i)));
}
}
return ret;
}
int ObLogLink::assign_stmt_fmt(const char* stmt_fmt_buf, int32_t stmt_fmt_len)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_fmt_buf) || stmt_fmt_len < 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("argument is invalid", K(ret), KP(stmt_fmt_buf), K(stmt_fmt_len));
} else if (OB_ISNULL(stmt_fmt_buf_ = static_cast<char*>(allocator_.alloc(stmt_fmt_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc stmt buf", K(ret), K(stmt_fmt_len));
} else {
MEMCPY(stmt_fmt_buf_, stmt_fmt_buf, stmt_fmt_len);
stmt_fmt_buf_len_ = stmt_fmt_len;
stmt_fmt_len_ = stmt_fmt_len;
}
return ret;
}
} // namespace sql
} // namespace oceanbase
} // namespace sql
} // namespace oceanbase