@@ -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+
452527int 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
0 commit comments