fix extracting wrong query range with mutable function
This commit is contained in:
		| @ -1711,18 +1711,21 @@ public: | ||||
|   int add_child_flags(const ObExprInfo &flags); | ||||
|   bool has_flag(ObExprInfoFlag flag) const; | ||||
|   int clear_flag(int32_t flag); | ||||
|   /**                                                   +-is_static_scalar_const_expr | ||||
|    *                               (1、1+2、sysdate)   |     (1,not for[1,2,3]) | ||||
|   /**                                                   +-is_immutable_const_expr-+ | ||||
|    *                               (1、1+2、sysdate)   |        (1、1+2) | ||||
|    *                             +-is_static_const_expr-+ | ||||
|    *                             | | ||||
|    * is_const_or_calculable_expr-+ | ||||
|    *    (1、1+2、2+?、sysdate)   | | ||||
|    *                             +-is_dynamic_const_expr | ||||
|    *                                 (2 + ?) | ||||
|    * immutable const: is const for all queries | ||||
|    * static const: is const in a query sql | ||||
|    * dynamic const: is const in a query block | ||||
|    */ | ||||
|   bool is_param_expr() const; | ||||
|   bool cnt_param_expr() const; | ||||
|   bool is_const_expr() const; | ||||
|   bool is_immutable_const_expr() const; | ||||
|   bool is_static_const_expr() const; | ||||
|   bool is_static_scalar_const_expr() const; | ||||
|   bool is_dynamic_const_expr() const; | ||||
| @ -1966,16 +1969,17 @@ inline bool ObRawExpr::is_param_expr() const | ||||
|   return has_flag(IS_STATIC_PARAM) || has_flag(IS_DYNAMIC_PARAM); | ||||
| } | ||||
|  | ||||
| inline bool ObRawExpr::cnt_param_expr() const | ||||
| { | ||||
|   return has_flag(CNT_STATIC_PARAM) || has_flag(CNT_DYNAMIC_PARAM); | ||||
| } | ||||
|  | ||||
| inline bool ObRawExpr::is_const_expr() const | ||||
| { | ||||
|   return has_flag(IS_CONST) || has_flag(IS_CONST_EXPR); | ||||
| } | ||||
|  | ||||
| inline bool ObRawExpr::is_immutable_const_expr() const | ||||
| { | ||||
|   // todo: support recognize 1+1 by introducing new expr flag like IS_MUTABLE_FUNC | ||||
|   return is_const_raw_expr() && !is_param_expr(); | ||||
| } | ||||
|  | ||||
| inline bool ObRawExpr::is_static_const_expr() const | ||||
| { | ||||
|   return is_const_expr() && | ||||
|  | ||||
| @ -1422,7 +1422,7 @@ int ObQueryRange::get_const_key_part(const ObRawExpr *l_expr, | ||||
|   if (OB_ISNULL(l_expr) || OB_ISNULL(r_expr) || (OB_ISNULL(escape_expr) && T_OP_LIKE == cmp_type)) { | ||||
|     ret = OB_INVALID_ARGUMENT; | ||||
|     LOG_WARN("invalid argument.", K(ret), KP(l_expr), KP(r_expr)); | ||||
|   } else if (l_expr->cnt_param_expr() || r_expr->cnt_param_expr()) { | ||||
|   } else if (!l_expr->is_immutable_const_expr() || !r_expr->is_immutable_const_expr()) { | ||||
|     GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part); | ||||
|   } else { | ||||
|     ObObj l_val; | ||||
| @ -1527,7 +1527,7 @@ int ObQueryRange::get_rowid_key_part(const ObRawExpr *l_expr, | ||||
|       c_type = cmp_type; | ||||
|       calc_urowid_expr = l_expr; | ||||
|     } | ||||
|     if (const_expr->cnt_param_expr()) { | ||||
|     if (!const_expr->is_immutable_const_expr()) { | ||||
|       query_range_ctx_->need_final_extract_ = true; | ||||
|     } | ||||
|     if (OB_SUCC(ret)) { | ||||
| @ -1557,7 +1557,7 @@ int ObQueryRange::get_rowid_key_part(const ObRawExpr *l_expr, | ||||
|       ObKeyPart *tmp_key_part = NULL; | ||||
|       ObKeyPartList key_part_list; | ||||
|       ObObj val; | ||||
|       if (!const_expr->cnt_param_expr()) { | ||||
|       if (const_expr->is_immutable_const_expr()) { | ||||
|         val = const_val; | ||||
|       } else { | ||||
|         if (OB_FAIL(get_final_expr_val(const_expr, val))) { | ||||
| @ -1722,7 +1722,7 @@ int ObQueryRange::get_column_key_part(const ObRawExpr *l_expr, | ||||
|       const_expr = r_expr; | ||||
|       c_type = cmp_type; | ||||
|     } | ||||
|     if (const_expr->cnt_param_expr()) { | ||||
|     if (!const_expr->is_immutable_const_expr()) { | ||||
|       query_range_ctx_->need_final_extract_ = true; | ||||
|     } | ||||
|     ObKeyPartId id(column_item->get_table_id(), column_item->get_column_id()); | ||||
| @ -1751,11 +1751,10 @@ int ObQueryRange::get_column_key_part(const ObRawExpr *l_expr, | ||||
|       out_key_part->id_ = id; | ||||
|       out_key_part->pos_ = *pos; | ||||
|       out_key_part->null_safe_ = (T_OP_NSEQ == c_type); | ||||
|       if ((!const_expr->cnt_param_expr() | ||||
|       if (const_expr->is_immutable_const_expr() | ||||
|           || (!const_expr->has_flag(CNT_DYNAMIC_PARAM) | ||||
|               && T_OP_LIKE == c_type | ||||
|               && NULL != query_range_ctx_->params_)) | ||||
|           && !const_expr->has_flag(CNT_LAST_INSERT_ID)) { | ||||
|               && NULL != query_range_ctx_->params_)) { | ||||
|         val = const_val; | ||||
|       } else { | ||||
|         if (OB_FAIL(get_final_expr_val(const_expr, val))) { | ||||
| @ -1775,14 +1774,15 @@ int ObQueryRange::get_column_key_part(const ObRawExpr *l_expr, | ||||
|             LOG_WARN("failed to get calculable expr val", K(ret)); | ||||
|           } else if (!is_valid) { | ||||
|             GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part); | ||||
|           } else if (const_expr->cnt_param_expr() || escape_expr->cnt_param_expr()) { | ||||
|           } else if (!const_expr->is_immutable_const_expr() || | ||||
|                      !escape_expr->is_immutable_const_expr()) { | ||||
|             if (OB_FAIL(out_key_part->create_like_key())) { | ||||
|               LOG_WARN("create like key part failed", K(ret)); | ||||
|             } else if (OB_FAIL(get_final_expr_val(const_expr, out_key_part->like_keypart_->pattern_))) { | ||||
|               LOG_WARN("failed to get final expr idx", K(ret)); | ||||
|             } else if (OB_FAIL(get_final_expr_val(escape_expr, out_key_part->like_keypart_->escape_))) { | ||||
|               LOG_WARN("failed to get final expr idx", K(ret)); | ||||
|             } else if (escape_expr->cnt_param_expr()) { | ||||
|             } else if (!escape_expr->is_immutable_const_expr()) { | ||||
|               query_range_ctx_->need_final_extract_ = true; | ||||
|             } else { | ||||
|               // do nothing | ||||
| @ -2894,8 +2894,7 @@ int ObQueryRange::get_multi_in_key_part(const ObOpRawExpr *l_expr, | ||||
|                 // TO HANDLE: (c1, 1) in ((1,2), (1,1)) | ||||
|                 ret = OB_SUCCESS; | ||||
|                 const ObRawExpr *l_param = l_expr->get_param_expr(j); | ||||
|                 if (!l_param->is_const_expr() || | ||||
|                     l_param->cnt_param_expr() || const_expr->cnt_param_expr()) { | ||||
|                 if (!l_param->is_immutable_const_expr() || !const_expr->is_immutable_const_expr()) { | ||||
|                   ret = not_key_idx.push_back(j); | ||||
|                 } else if (OB_FAIL(check_const_val_valid(l_param, | ||||
|                                                          const_expr, | ||||
| @ -3128,7 +3127,7 @@ int ObQueryRange::get_param_value(ObInKeyPart *in_key, | ||||
|   } else { | ||||
|     ObObj val; | ||||
|     bool is_valid = false; | ||||
|     if (!const_expr->cnt_param_expr()) { | ||||
|     if (const_expr->is_immutable_const_expr()) { | ||||
|       if (OB_FAIL(get_calculable_expr_val(const_expr, val, is_valid))) { | ||||
|         LOG_WARN("failed to get calculable expr val", K(ret)); | ||||
|       } else if (!is_valid) { | ||||
| @ -3537,7 +3536,7 @@ int ObQueryRange::pre_extract_const_op(const ObRawExpr *c_expr, | ||||
|     bool is_valid = false; | ||||
|     bool b_val = false; | ||||
|     query_range_ctx_->cur_expr_is_precise_ = false; | ||||
|     if (c_expr->cnt_param_expr()) { | ||||
|     if (!c_expr->is_immutable_const_expr()) { | ||||
|       GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part); | ||||
|     } else if (OB_FAIL(get_calculable_expr_val(c_expr, val, is_valid))) { | ||||
|       LOG_WARN("failed to get calculable expr val", K(ret)); | ||||
| @ -3647,7 +3646,7 @@ int ObQueryRange::pre_extract_geo_op(const ObOpRawExpr *geo_expr, | ||||
|           is_cellid_col = true; | ||||
|         } | ||||
|         if (OB_SUCC(ret)) { | ||||
|           if (const_item->cnt_param_expr()) { | ||||
|           if (!const_item->is_immutable_const_expr()) { | ||||
|             query_range_ctx_->need_final_extract_ = true; | ||||
|           } | ||||
|           ObKeyPartId key_part_id(column_item->get_table_id(), | ||||
| @ -3692,7 +3691,7 @@ int ObQueryRange::pre_extract_geo_op(const ObOpRawExpr *geo_expr, | ||||
|             } else if (!is_valid) { | ||||
|               GET_ALWAYS_TRUE_OR_FALSE(true, out_key_part); | ||||
|             } else { | ||||
|               if (const_item->cnt_param_expr()) { | ||||
|               if (!const_item->is_immutable_const_expr()) { | ||||
|                 ObObj val; | ||||
|                 out_key_part->geo_keypart_->geo_type_ = op_type; | ||||
|                 if (OB_FAIL(get_final_expr_val(const_item, out_key_part->geo_keypart_->wkb_))) { | ||||
|  | ||||
| @ -679,31 +679,31 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"a", collation:"utf8mb4_general_ci"};MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 45 col_type = 46 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 45 col_type = 63 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 46 col_type = 45 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 46 col_type = 46 | ||||
| is not min_to_max_range | ||||
| ranges.count() = 1 | ||||
| @ -711,31 +711,31 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"a", collation:"utf8mb4_bin"};MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 46 col_type = 63 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 63 col_type = 45 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 63 col_type = 46 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'a' and false--------------connection_collation = 63 col_type = 63 | ||||
| is not min_to_max_range | ||||
| ranges.count() = 1 | ||||
| @ -743,7 +743,7 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"a", collation:"binary"};MAX)"}] | ||||
|  | ||||
| [11] false and f > 'a' | ||||
| false and f > 'a'--------------connection_collation = 45 col_type = 45 | ||||
| @ -753,31 +753,31 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"a", collation:"utf8mb4_general_ci"};MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 45 col_type = 46 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 45 col_type = 63 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 46 col_type = 45 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 46 col_type = 46 | ||||
| is not min_to_max_range | ||||
| ranges.count() = 1 | ||||
| @ -785,31 +785,31 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"a", collation:"utf8mb4_bin"};MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 46 col_type = 63 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 63 col_type = 45 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 63 col_type = 46 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| false and f > 'a'--------------connection_collation = 63 col_type = 63 | ||||
| is not min_to_max_range | ||||
| ranges.count() = 1 | ||||
| @ -817,7 +817,7 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"a", collation:"binary"};MAX)"}] | ||||
|  | ||||
| [12] f < 'a' or f > 'b' or f > 'sda' and f > 'sds' or f = 'adas' | ||||
| f < 'a' or f > 'b' or f > 'sda' and f > 'sds' or f = 'adas'--------------connection_collation = 45 col_type = 45 | ||||
| @ -1375,13 +1375,13 @@ end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'B' and 'a' = 'A'--------------connection_collation = 46 col_type = 45 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'B' and 'a' = 'A'--------------connection_collation = 46 col_type = 46 | ||||
| is not min_to_max_range | ||||
| ranges.count() = 1 | ||||
| @ -1389,31 +1389,31 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"B", collation:"utf8mb4_bin"};MAX)"}] | ||||
| f > 'B' and 'a' = 'A'--------------connection_collation = 46 col_type = 63 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'B' and 'a' = 'A'--------------connection_collation = 63 col_type = 45 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'B' and 'a' = 'A'--------------connection_collation = 63 col_type = 46 | ||||
| is not min_to_max_range | ||||
| is min_to_max_range | ||||
| ranges.count() = 1 | ||||
| all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,(MIN;MAX)"}] | ||||
| f > 'B' and 'a' = 'A'--------------connection_collation = 63 col_type = 63 | ||||
| is not min_to_max_range | ||||
| ranges.count() = 1 | ||||
| @ -1421,7 +1421,7 @@ all_single_value_ranges = 0 | ||||
| star_border_flag[0] = 0 | ||||
| end_border_flag[0] = 0 | ||||
| count of rang columns = 1 | ||||
| [{"range":"table_id:3003,group_idx:0,(MAX;MIN)"}] | ||||
| [{"range":"table_id:3003,group_idx:0,({"VARCHAR":"B", collation:"binary"};MAX)"}] | ||||
|  | ||||
| [20] #(f, g) in (('a', 'b'), ('B', 'A')) | ||||
| [21] #(f, g) > ('a', 'b') and (f, g) < ('B', 'A') | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 yinyj17
					yinyj17