Commit d6c6f79f authored by Sergei Petrunia's avatar Sergei Petrunia Committed by Sergei Golubchik

MDEV-26996 Reverse-ordered indexes: remove SEL_ARG::is_ascending

Instead, Get the "is_ascending" value from the array of KEY_PART
structures that describes the [pseudo-]index that is being analyzed.
parent cbfe6a5e
...@@ -1084,7 +1084,7 @@ Item_func_spatial_rel::get_mm_leaf(RANGE_OPT_PARAM *param, ...@@ -1084,7 +1084,7 @@ Item_func_spatial_rel::get_mm_leaf(RANGE_OPT_PARAM *param,
field->get_key_image(str, key_part->length, key_part->image_type); field->get_key_image(str, key_part->length, key_part->image_type);
SEL_ARG *tree; SEL_ARG *tree;
if (!(tree= new (param->mem_root) SEL_ARG(field, true, str, str))) if (!(tree= new (param->mem_root) SEL_ARG(field, str, str)))
DBUG_RETURN(0); // out of memory DBUG_RETURN(0); // out of memory
switch (type) { switch (type) {
......
This diff is collapsed.
...@@ -306,11 +306,6 @@ class SEL_ARG :public Sql_alloc ...@@ -306,11 +306,6 @@ class SEL_ARG :public Sql_alloc
uint8 min_flag,max_flag,maybe_flag; uint8 min_flag,max_flag,maybe_flag;
uint8 part; // Which key part uint8 part; // Which key part
uint8 maybe_null; uint8 maybe_null;
/*
Whether the keypart is ascending or descending.
See HowRangeOptimizerHandlesDescKeyparts for details.
*/
uint8 is_ascending;
/* /*
The ordinal number the least significant component encountered in The ordinal number the least significant component encountered in
the ranges of the SEL_ARG tree (the first component has number 1) the ranges of the SEL_ARG tree (the first component has number 1)
...@@ -361,14 +356,14 @@ class SEL_ARG :public Sql_alloc ...@@ -361,14 +356,14 @@ class SEL_ARG :public Sql_alloc
SEL_ARG() {} SEL_ARG() {}
SEL_ARG(SEL_ARG &); SEL_ARG(SEL_ARG &);
SEL_ARG(Field *, bool is_asc, const uchar *, const uchar *); SEL_ARG(Field *, const uchar *, const uchar *);
SEL_ARG(Field *field, uint8 part, bool is_asc, SEL_ARG(Field *field, uint8 part,
uchar *min_value, uchar *max_value, uchar *min_value, uchar *max_value,
uint8 min_flag, uint8 max_flag, uint8 maybe_flag); uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
/* This is used to construct degenerate SEL_ARGS like ALWAYS, IMPOSSIBLE, etc */ /* This is used to construct degenerate SEL_ARGS like ALWAYS, IMPOSSIBLE, etc */
SEL_ARG(enum Type type_arg) SEL_ARG(enum Type type_arg)
:min_flag(0), is_ascending(false), :min_flag(0),
max_part_no(0) /* first key part means 1. 0 mean 'no parts'*/, max_part_no(0) /* first key part means 1. 0 mean 'no parts'*/,
elements(1),use_count(1),left(0),right(0), elements(1),use_count(1),left(0),right(0),
next_key_part(0), color(BLACK), type(type_arg), weight(1) next_key_part(0), color(BLACK), type(type_arg), weight(1)
...@@ -447,20 +442,20 @@ class SEL_ARG :public Sql_alloc ...@@ -447,20 +442,20 @@ class SEL_ARG :public Sql_alloc
{ {
new_max=arg->max_value; flag_max=arg->max_flag; new_max=arg->max_value; flag_max=arg->max_flag;
} }
return new (thd->mem_root) SEL_ARG(field, part, is_ascending, return new (thd->mem_root) SEL_ARG(field, part,
new_min, new_max, flag_min, new_min, new_max, flag_min,
flag_max, flag_max,
MY_TEST(maybe_flag && arg->maybe_flag)); MY_TEST(maybe_flag && arg->maybe_flag));
} }
SEL_ARG *clone_first(SEL_ARG *arg) SEL_ARG *clone_first(SEL_ARG *arg)
{ // min <= X < arg->min { // min <= X < arg->min
return new SEL_ARG(field, part, is_ascending, min_value, arg->min_value, return new SEL_ARG(field, part, min_value, arg->min_value,
min_flag, arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX, min_flag, arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX,
maybe_flag | arg->maybe_flag); maybe_flag | arg->maybe_flag);
} }
SEL_ARG *clone_last(SEL_ARG *arg) SEL_ARG *clone_last(SEL_ARG *arg)
{ // min <= X <= key_max { // min <= X <= key_max
return new SEL_ARG(field, part, is_ascending, min_value, arg->max_value, return new SEL_ARG(field, part, min_value, arg->max_value,
min_flag, arg->max_flag, maybe_flag | arg->maybe_flag); min_flag, arg->max_flag, maybe_flag | arg->maybe_flag);
} }
SEL_ARG *clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG **next); SEL_ARG *clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG **next);
...@@ -544,44 +539,45 @@ class SEL_ARG :public Sql_alloc ...@@ -544,44 +539,45 @@ class SEL_ARG :public Sql_alloc
} }
/* Save minimum and maximum, taking index order into account */ /* Save minimum and maximum, taking index order into account */
void store_min_max(uint length, void store_min_max(KEY_PART *kp,
uint length,
uchar **min_key, uint min_flag, uchar **min_key, uint min_flag,
uchar **max_key, uint max_flag, uchar **max_key, uint max_flag,
int *min_part, int *max_part) int *min_part, int *max_part)
{ {
if (is_ascending) { if (kp[part].flag & HA_REVERSE_SORT) {
*min_part += store_min(length, min_key, min_flag);
*max_part += store_max(length, max_key, max_flag);
} else {
*max_part += store_min(length, max_key, min_flag); *max_part += store_min(length, max_key, min_flag);
*min_part += store_max(length, min_key, max_flag); *min_part += store_max(length, min_key, max_flag);
} else {
*min_part += store_min(length, min_key, min_flag);
*max_part += store_max(length, max_key, max_flag);
} }
} }
/* /*
Get the flag for range's starting endpoint, taking index order into Get the flag for range's starting endpoint, taking index order into
account. account.
*/ */
uint get_min_flag() uint get_min_flag(KEY_PART *kp)
{ {
return (is_ascending ? min_flag : invert_max_flag(max_flag)); return (kp[part].flag & HA_REVERSE_SORT)? invert_max_flag(max_flag) : min_flag;
} }
/* /*
Get the flag for range's starting endpoint, taking index order into Get the flag for range's starting endpoint, taking index order into
account. account.
*/ */
uint get_max_flag() uint get_max_flag(KEY_PART *kp)
{ {
return (is_ascending ? max_flag : invert_min_flag(min_flag)); return (kp[part].flag & HA_REVERSE_SORT)? invert_min_flag(min_flag) : max_flag ;
} }
/* Get the previous interval, taking index order into account */ /* Get the previous interval, taking index order into account */
inline SEL_ARG* index_order_prev() inline SEL_ARG* index_order_prev(KEY_PART *kp)
{ {
return is_ascending? prev: next; return (kp[part].flag & HA_REVERSE_SORT)? next : prev;
} }
/* Get the next interval, taking index order into account */ /* Get the next interval, taking index order into account */
inline SEL_ARG* index_order_next() inline SEL_ARG* index_order_next(KEY_PART *kp)
{ {
return is_ascending? next: prev; return (kp[part].flag & HA_REVERSE_SORT)? prev : next;
} }
/* /*
...@@ -621,7 +617,7 @@ class SEL_ARG :public Sql_alloc ...@@ -621,7 +617,7 @@ class SEL_ARG :public Sql_alloc
nkp->part == key_tree->part+1 && nkp->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN))) !(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)))
{ {
const bool asc = nkp->is_ascending; const bool asc = !(key[key_tree->part].flag & HA_REVERSE_SORT);
if (start_key == asc) if (start_key == asc)
{ {
res+= nkp->store_min_key(key, range_key, range_key_flag, last_part, res+= nkp->store_min_key(key, range_key, range_key_flag, last_part,
...@@ -657,7 +653,7 @@ class SEL_ARG :public Sql_alloc ...@@ -657,7 +653,7 @@ class SEL_ARG :public Sql_alloc
nkp->part == key_tree->part+1 && nkp->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX))) !(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
{ {
const bool asc = nkp->is_ascending; const bool asc = !(key[key_tree->part].flag & HA_REVERSE_SORT);
if ((!start_key && asc) || (start_key && !asc)) if ((!start_key && asc) || (start_key && !asc))
{ {
res += nkp->store_max_key(key, range_key, range_key_flag, last_part, res += nkp->store_max_key(key, range_key, range_key_flag, last_part,
...@@ -785,9 +781,6 @@ class SEL_ARG :public Sql_alloc ...@@ -785,9 +781,6 @@ class SEL_ARG :public Sql_alloc
Range Optimizer handles this as follows: Range Optimizer handles this as follows:
The SEL_ARG object has SEL_ARG::is_ascending which specifies whether the
keypart is ascending.
Other than that, the SEL_ARG graph is built without any regard to DESC Other than that, the SEL_ARG graph is built without any regard to DESC
keyparts. keyparts.
...@@ -799,7 +792,7 @@ class SEL_ARG :public Sql_alloc ...@@ -799,7 +792,7 @@ class SEL_ARG :public Sql_alloc
kp1 BETWEEN 10 and 20 (RANGE-1) kp1 BETWEEN 10 and 20 (RANGE-1)
the SEL_ARG will have min_value=10, max_value=20, is_ascending=false. the SEL_ARG will have min_value=10, max_value=20
The ordering of key parts is taken into account when SEL_ARG graph is The ordering of key parts is taken into account when SEL_ARG graph is
linearized to ranges, in sel_arg_range_seq_next() and get_quick_keys(). linearized to ranges, in sel_arg_range_seq_next() and get_quick_keys().
...@@ -850,7 +843,7 @@ class SEL_ARG_IMPOSSIBLE: public SEL_ARG ...@@ -850,7 +843,7 @@ class SEL_ARG_IMPOSSIBLE: public SEL_ARG
{ {
public: public:
SEL_ARG_IMPOSSIBLE(Field *field) SEL_ARG_IMPOSSIBLE(Field *field)
:SEL_ARG(field, false, 0, 0) :SEL_ARG(field, 0, 0)
{ {
type= SEL_ARG::IMPOSSIBLE; type= SEL_ARG::IMPOSSIBLE;
} }
......
...@@ -47,6 +47,7 @@ typedef struct st_sel_arg_range_seq ...@@ -47,6 +47,7 @@ typedef struct st_sel_arg_range_seq
uint keyno; /* index of used tree in SEL_TREE structure */ uint keyno; /* index of used tree in SEL_TREE structure */
uint real_keyno; /* Number of the index in tables */ uint real_keyno; /* Number of the index in tables */
PARAM *param; PARAM *param;
KEY_PART *key_parts;
SEL_ARG *start; /* Root node of the traversed SEL_ARG* graph */ SEL_ARG *start; /* Root node of the traversed SEL_ARG* graph */
RANGE_SEQ_ENTRY stack[MAX_REF_PARTS]; RANGE_SEQ_ENTRY stack[MAX_REF_PARTS];
...@@ -106,13 +107,13 @@ static void step_down_to(SEL_ARG_RANGE_SEQ *arg, SEL_ARG *key_tree) ...@@ -106,13 +107,13 @@ static void step_down_to(SEL_ARG_RANGE_SEQ *arg, SEL_ARG *key_tree)
uint16 stor_length= arg->param->key[arg->keyno][key_tree->part].store_length; uint16 stor_length= arg->param->key[arg->keyno][key_tree->part].store_length;
key_tree->store_min_max(stor_length, key_tree->store_min_max(arg->key_parts, stor_length,
&cur->min_key, prev->min_key_flag, &cur->min_key, prev->min_key_flag,
&cur->max_key, prev->max_key_flag, &cur->max_key, prev->max_key_flag,
&cur->min_key_parts, &cur->max_key_parts); &cur->min_key_parts, &cur->max_key_parts);
cur->min_key_flag= prev->min_key_flag | key_tree->get_min_flag(); cur->min_key_flag= prev->min_key_flag | key_tree->get_min_flag(arg->key_parts);
cur->max_key_flag= prev->max_key_flag | key_tree->get_max_flag(); cur->max_key_flag= prev->max_key_flag | key_tree->get_max_flag(arg->key_parts);
if (key_tree->is_null_interval()) if (key_tree->is_null_interval())
cur->min_key_flag |= NULL_RANGE; cur->min_key_flag |= NULL_RANGE;
...@@ -166,12 +167,13 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range) ...@@ -166,12 +167,13 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
/* Ok, we're at some "full tuple" position in the tree */ /* Ok, we're at some "full tuple" position in the tree */
/* Step down if we can */ /* Step down if we can */
if (key_tree->index_order_next() && key_tree->index_order_next() != &null_element) if (key_tree->index_order_next(seq->key_parts) &&
key_tree->index_order_next(seq->key_parts) != &null_element)
{ {
//step down; (update the tuple, we'll step right and stay there) //step down; (update the tuple, we'll step right and stay there)
seq->i--; seq->i--;
step_down_to(seq, key_tree->index_order_next()); step_down_to(seq, key_tree->index_order_next(seq->key_parts));
key_tree= key_tree->index_order_next(); key_tree= key_tree->index_order_next(seq->key_parts);
seq->is_ror_scan= FALSE; seq->is_ror_scan= FALSE;
goto walk_right_n_up; goto walk_right_n_up;
} }
...@@ -186,12 +188,13 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range) ...@@ -186,12 +188,13 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
key_tree= seq->stack[seq->i].key_tree; key_tree= seq->stack[seq->i].key_tree;
/* Step down if we can */ /* Step down if we can */
if (key_tree->index_order_next() && key_tree->index_order_next() != &null_element) if (key_tree->index_order_next(seq->key_parts) &&
key_tree->index_order_next(seq->key_parts) != &null_element)
{ {
// Step down; update the tuple // Step down; update the tuple
seq->i--; seq->i--;
step_down_to(seq, key_tree->index_order_next()); step_down_to(seq, key_tree->index_order_next(seq->key_parts));
key_tree= key_tree->index_order_next(); key_tree= key_tree->index_order_next(seq->key_parts);
break; break;
} }
} }
...@@ -230,11 +233,11 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range) ...@@ -230,11 +233,11 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
key_tree= key_tree->next_key_part; key_tree= key_tree->next_key_part;
walk_up_n_right: walk_up_n_right:
while (key_tree->index_order_prev() && while (key_tree->index_order_prev(seq->key_parts) &&
key_tree->index_order_prev() != &null_element) key_tree->index_order_prev(seq->key_parts) != &null_element)
{ {
/* Step up */ /* Step up */
key_tree= key_tree->index_order_prev(); key_tree= key_tree->index_order_prev(seq->key_parts);
} }
step_down_to(seq, key_tree); step_down_to(seq, key_tree);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment