summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-04-21 16:38:22 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2023-04-21 16:38:22 +0300
commitabe4c7bfd6d56dc0557d15eaa03185ada4149da7 (patch)
treea44ab54d96b7dd988fd87793af53522bee270d43 /sql
parent7e31a8e7fa97a87fc164381588d172bf0e76abb6 (diff)
parentc6e58a8d173b7e9689952d07678ba79702ba8021 (diff)
downloadmariadb-git-abe4c7bfd6d56dc0557d15eaa03185ada4149da7.tar.gz
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc14
-rw-r--r--sql/opt_range.cc46
2 files changed, 41 insertions, 19 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 5246d92138b..b3b22874735 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1824,7 +1824,19 @@ int ha_commit_trans(THD *thd, bool all)
ordering is normally done. Commit ordering must be done here.
*/
if (run_wsrep_hooks)
- error= wsrep_before_commit(thd, all);
+ {
+ // This commit involves more than one storage engine and requires
+ // two phases, but some engines don't support it.
+ // Issue a message to the client and roll back the transaction.
+ if (trans->no_2pc && rw_ha_count > 1)
+ {
+ my_message(ER_ERROR_DURING_COMMIT, "Transactional commit not supported "
+ "by involved engine(s)", MYF(0));
+ error= 1;
+ }
+ else
+ error= wsrep_before_commit(thd, all);
+ }
if (error)
{
ha_rollback_trans(thd, FALSE);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c845147e328..44cf08d9323 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -461,7 +461,7 @@ void print_range_for_non_indexed_field(String *out, Field *field,
static void print_min_range_operator(String *out, const ha_rkey_function flag);
static void print_max_range_operator(String *out, const ha_rkey_function flag);
-static bool is_field_an_unique_index(RANGE_OPT_PARAM *param, Field *field);
+static bool is_field_an_unique_index(Field *field);
/*
SEL_IMERGE is a list of possible ways to do index merge, i.e. it is
@@ -7752,8 +7752,13 @@ SEL_TREE *Item_func_ne::get_func_mm_tree(RANGE_OPT_PARAM *param,
If this condition is a "col1<>...", where there is a UNIQUE KEY(col1),
do not construct a SEL_TREE from it. A condition that excludes just one
row in the table is not selective (unless there are only a few rows)
+
+ Note: this logic must be in sync with code in
+ check_group_min_max_predicates(). That function walks an Item* condition
+ and checks if the range optimizer would produce an equivalent range for
+ it.
*/
- if (is_field_an_unique_index(param, field))
+ if (param->using_real_indexes && is_field_an_unique_index(field))
DBUG_RETURN(NULL);
DBUG_RETURN(get_ne_mm_tree(param, field, value, value));
}
@@ -7865,7 +7870,7 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param,
- if there are a lot of constants, the overhead of building and
processing enormous range list is not worth it.
*/
- if (is_field_an_unique_index(param, field))
+ if (param->using_real_indexes && is_field_an_unique_index(field))
DBUG_RETURN(0);
/* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */
@@ -8574,24 +8579,18 @@ SEL_TREE *Item_equal::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
In the future we could also add "almost unique" indexes where any value is
present only in a few rows (but necessarily exactly one row)
*/
-static bool is_field_an_unique_index(RANGE_OPT_PARAM *param, Field *field)
+static bool is_field_an_unique_index(Field *field)
{
DBUG_ENTER("is_field_an_unique_index");
-
- // The check for using_real_indexes is there because of the heuristics
- // this function is used for.
- if (param->using_real_indexes)
+ key_map::Iterator it(field->key_start);
+ uint key_no;
+ while ((key_no= it++) != key_map::Iterator::BITMAP_END)
{
- key_map::Iterator it(field->key_start);
- uint key_no;
- while ((key_no= it++) != key_map::Iterator::BITMAP_END)
+ KEY *key_info= &field->table->key_info[key_no];
+ if (key_info->user_defined_key_parts == 1 &&
+ (key_info->flags & HA_NOSAME))
{
- KEY *key_info= &field->table->key_info[key_no];
- if (key_info->user_defined_key_parts == 1 &&
- (key_info->flags & HA_NOSAME))
- {
- DBUG_RETURN(true);
- }
+ DBUG_RETURN(true);
}
}
DBUG_RETURN(false);
@@ -13475,7 +13474,7 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
- (C between const_i and const_j)
- C IS NULL
- C IS NOT NULL
- - C != const
+ - C != const (unless C is the primary key)
SA4. If Q has a GROUP BY clause, there are no other aggregate functions
except MIN and MAX. For queries with DISTINCT, aggregate functions
are allowed.
@@ -14358,6 +14357,17 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
if (!simple_pred(pred, args, &inv))
DBUG_RETURN(FALSE);
+ /*
+ Follow the logic in Item_func_ne::get_func_mm_tree(): condition
+ in form "tbl.primary_key <> const" is not used to produce intervals.
+
+ If the condition doesn't have an equivalent interval, this means we
+ fail LooseScan's condition SA3. Return FALSE to indicate this.
+ */
+ if (pred_type == Item_func::NE_FUNC &&
+ is_field_an_unique_index(min_max_arg_item->field))
+ DBUG_RETURN(FALSE);
+
if (args[0] && args[1]) // this is a binary function or BETWEEN
{
DBUG_ASSERT(pred->fixed_type_handler());