Skip to content

Commit dcf7be6

Browse files
obdevob-robot
authored andcommitted
[CP] Fix the non-convergence issue in the transformation
1 parent d9bd543 commit dcf7be6

2 files changed

Lines changed: 115 additions & 11 deletions

File tree

src/sql/rewrite/ob_transformer_impl.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,13 +413,18 @@ int ObTransformerImpl::transform_rule_set(ObDMLStmt *&stmt,
413413
if (0 != (needed_types & needed_transform_types_)) {
414414
bool need_next_iteration = true;
415415
int64_t i = 0;
416+
ObSEArray<int32_t, 64> cur_enable_types_array;
417+
if (OB_FAIL(init_enable_types_cnt_array(needed_types, cur_enable_types_array))) {
418+
LOG_WARN("failed to init enable types cnt array", K(ret));
419+
}
416420
for (i = 0; OB_SUCC(ret) && need_next_iteration && i < iteration_count; ++i) {
417421
bool trans_happened_in_iteration = false;
418422
ctx_->iteration_level_ = i;
419423
LOG_TRACE("start to transform one iteration", K(i));
420424
OPT_TRACE("-- begin ", i, " iteration");
421425
if (OB_FAIL(transform_rule_set_in_one_iteration(stmt,
422426
needed_types,
427+
cur_enable_types_array,
423428
trans_happened_in_iteration))) {
424429
LOG_WARN("failed to do transformation one iteration", K(i), K(ret));
425430
} else if (!trans_happened_in_iteration) {
@@ -449,8 +454,79 @@ int ObTransformerImpl::transform_rule_set(ObDMLStmt *&stmt,
449454
return ret;
450455
}
451456

457+
int ObTransformerImpl::init_enable_types_cnt_array(uint64_t needed_types,
458+
ObIArray<int32_t> &enable_cnt_array)
459+
{
460+
int ret = OB_SUCCESS;
461+
if (OB_FAIL(enable_cnt_array.prepare_allocate(TRANSFORM_TYPE_COUNT_PLUS_ONE))) {
462+
LOG_WARN("failed to prepare allocate enable types array", K(ret));
463+
} else {
464+
for (int64_t idx = 0; OB_SUCC(ret) && idx < enable_cnt_array.count(); ++idx) {
465+
int32_t init_cnt = 0;
466+
if (0 != (needed_types & (1L << idx))) {
467+
// For most rules, enable count starts from 1 (enabled).
468+
// For PREDICATE_MOVE_AROUND, we start from 2 so it can happen at most twice
469+
// before being temporarily disabled (see update_enable_types()).
470+
init_cnt = (PREDICATE_MOVE_AROUND == idx)
471+
? PREDICATE_MOVE_AROUND_RESET_CNT
472+
: DEFAULT_ENABLE_TYPE_CNT;
473+
}
474+
enable_cnt_array.at(idx) = init_cnt;
475+
}
476+
}
477+
return ret;
478+
}
479+
480+
void ObTransformerImpl::enable_cnt_array_to_bitset(const ObIArray<int32_t> &arr, uint64_t &bitset)
481+
{
482+
bitset = 0;
483+
const int64_t cnt = arr.count();
484+
for (int64_t idx = 0; idx < cnt; ++idx) {
485+
if (arr.at(idx) > 0) {
486+
bitset |= (1L << idx);
487+
}
488+
}
489+
}
490+
491+
int ObTransformerImpl::update_enable_types(TRANSFORM_TYPE type,
492+
uint64_t &enable_types,
493+
ObIArray<int32_t> &enable_cnt_array)
494+
{
495+
int ret = OB_SUCCESS;
496+
int32_t cnt = 0;
497+
if (OB_UNLIKELY(type >= enable_cnt_array.count())) {
498+
ret = OB_INVALID_ARGUMENT;
499+
LOG_WARN("invalid argument", K(ret), K(type), K(TRANSFORM_TYPE_COUNT_PLUS_ONE));
500+
} else {
501+
int32_t &cnt = enable_cnt_array.at(type);
502+
if (PREDICATE_MOVE_AROUND == type) {
503+
// Non-convergence guard:
504+
// Predicate deduction (a.k.a. predicate move around) may oscillate with
505+
// constant propagation and expression simplification. To avoid rewrite
506+
// ping-pong within one iteration sequence, we only allow it to happen a
507+
// limited number of times (PREDICATE_MOVE_AROUND_RESET_CNT). After that,
508+
// we temporarily disable it until it is reset by other rewrite rules.
509+
cnt--;
510+
if (cnt <= 0) {
511+
enable_types &= ~(1L << type);
512+
}
513+
} else if (CONST_PROPAGATE == type || SIMPLIFY_EXPR == type) {
514+
// These rules are considered part of the "oscillation group" with predicate
515+
// deduction. If only these rules happen, we do NOT reset predicate deduction.
516+
/*do nothing*/
517+
} else {
518+
// Any other rewrite rule indicates progress in a different direction, so we
519+
// re-enable predicate deduction and reset its budget.
520+
ObTransformRule::add_trans_type(enable_types, PREDICATE_MOVE_AROUND);
521+
enable_cnt_array.at(PREDICATE_MOVE_AROUND) = PREDICATE_MOVE_AROUND_RESET_CNT;
522+
}
523+
}
524+
return ret;
525+
}
526+
452527
int ObTransformerImpl::transform_rule_set_in_one_iteration(ObDMLStmt *&stmt,
453528
uint64_t needed_types,
529+
ObIArray<int32_t> &cur_enable_types_array,
454530
bool &trans_happened)
455531
{
456532
int ret = OB_SUCCESS;
@@ -459,6 +535,10 @@ int ObTransformerImpl::transform_rule_set_in_one_iteration(ObDMLStmt *&stmt,
459535
ret = OB_INVALID_ARGUMENT;
460536
LOG_WARN("stmt is NULL", K(ret));
461537
} else {
538+
uint64_t cur_enable_types = 0;
539+
enable_cnt_array_to_bitset(cur_enable_types_array, cur_enable_types);
540+
// cur_enable_types may be updated after each rule happens to avoid rewrite
541+
// ping-pong (PREDICATE_MOVE_AROUND vs CONST_PROPAGATE / SIMPLIFY_EXPR).
462542
/*
463543
* The ordering to apply the following rules is important,
464544
* think carefully when new rules are added

src/sql/rewrite/ob_transformer_impl.h

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "lib/allocator/ob_allocator.h"
2121
#include "lib/container/ob_iarray.h"
22+
#include "lib/container/ob_se_array.h"
2223
#include "sql/parser/parse_node.h"
2324
#include "sql/rewrite/ob_transform_rule.h"
2425
#include "sql/resolver/dml/ob_select_stmt.h"
@@ -30,22 +31,36 @@ namespace sql
3031
class ObDMLStmt;
3132
class ObSelectStmt;
3233

33-
#define APPLY_RULE_IF_NEEDED(t, c) \
34-
do { \
35-
if (OB_FAIL(ret)) { \
36-
} else if (OB_FAIL(transform_one_rule<c>(stmt, \
37-
needed_types, \
38-
t, \
39-
#c, \
40-
trans_happened))) { \
41-
LOG_WARN("failed to transform one rule", K(ret)); \
42-
} \
34+
#define APPLY_RULE_IF_NEEDED(t, c) \
35+
do { \
36+
bool is_happened = false; \
37+
const uint64_t local_needed_types = needed_types & cur_enable_types; \
38+
if (OB_FAIL(ret)) { \
39+
} else if (OB_FAIL(transform_one_rule<c>(stmt, \
40+
local_needed_types, \
41+
t, \
42+
#c, \
43+
is_happened))) { \
44+
LOG_WARN("failed to transform one rule", K(ret)); \
45+
} else if (is_happened) { \
46+
if (OB_FAIL(update_enable_types(t, cur_enable_types, cur_enable_types_array))) { \
47+
LOG_WARN("failed to update enable types", K(ret)); \
48+
} else { \
49+
trans_happened |= is_happened; \
50+
} \
51+
} \
4352
} while (0);
4453

4554
class ObTransformerImpl
4655
{
4756
static const int64_t DEFAULT_ITERATION_COUNT = 10;
4857
static const int64_t MAX_RULE_COUNT = 64;
58+
static const int32_t DEFAULT_ENABLE_TYPE_CNT = 1;
59+
// Non-convergence guard for predicate deduction (PREDICATE_MOVE_AROUND):
60+
// Allow it to happen at most N times consecutively inside the same "rewrite phase"
61+
// (i.e. without being reset by other rewrite rules). Once the counter reaches 0,
62+
// we temporarily disable PREDICATE_MOVE_AROUND until another rule resets it.
63+
static const int32_t PREDICATE_MOVE_AROUND_RESET_CNT = 2;
4964
public:
5065
ObTransformerImpl(ObTransformerCtx *ctx)
5166
: ctx_(ctx),
@@ -68,6 +83,7 @@ class ObTransformerImpl
6883
bool &trans_happened);
6984
int transform_rule_set_in_one_iteration(ObDMLStmt *&stmt,
7085
uint64_t needed_types,
86+
ObIArray<int32_t> &cur_enable_types_array,
7187
bool &trans_happened);
7288
int do_after_transform(ObDMLStmt *stmt, const ObSQLSessionInfo *session);
7389
int get_all_stmts(ObDMLStmt *stmt,
@@ -111,6 +127,11 @@ class ObTransformerImpl
111127

112128
int choose_rewrite_rules(ObDMLStmt *stmt, uint64_t &need_types);
113129

130+
static int update_enable_types(TRANSFORM_TYPE type,
131+
uint64_t &enable_types,
132+
ObIArray<int32_t> &enable_cnt_array);
133+
static void enable_cnt_array_to_bitset(const ObIArray<int32_t> &arr, uint64_t &bitset);
134+
114135
struct StmtFunc {
115136
StmtFunc () :
116137
contain_sequence_(false),
@@ -154,11 +175,14 @@ class ObTransformerImpl
154175
inline ObTransformerCtx *get_trans_ctx() { return ctx_; }
155176
int set_transformation_parameters(ObQueryCtx *query_ctx);
156177
private:
157-
178+
158179
int collect_trans_stat(const ObTransformRule &rule);
159180
int get_stmt_trans_info(ObDMLStmt *stmt, bool is_root);
160181
void print_trans_stat();
161182

183+
static int init_enable_types_cnt_array(uint64_t needed_types,
184+
ObIArray<int32_t> &enable_cnt_array);
185+
162186
int finalize_exec_params(ObDMLStmt *stmt);
163187

164188
int finalize_exec_params(ObDMLStmt *stmt, ObIArray<ObExecParamRawExpr*> & exec_params);

0 commit comments

Comments
 (0)