mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Manual merge from mysql-trunk-merge.
This commit is contained in:
@ -637,6 +637,18 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
MYF(0)); /* purecov: inspected */
|
||||
goto err; /* purecov: inspected */
|
||||
}
|
||||
if (thd->lex->derived_tables)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE",
|
||||
thd->lex->derived_tables & DERIVED_VIEW ?
|
||||
"view" : "subquery");
|
||||
goto err;
|
||||
}
|
||||
if (thd->lex->sql_command != SQLCOM_SELECT)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "non-SELECT");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!procedure && result && result->prepare(fields_list, unit_arg))
|
||||
@ -973,6 +985,12 @@ JOIN::optimize()
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields())
|
||||
{
|
||||
DBUG_PRINT("error", ("Error: rollup_process_fields() failed"));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* Remove distinct if only const tables */
|
||||
select_distinct= select_distinct && (const_tables != tables);
|
||||
thd_proc_info(thd, "preparing");
|
||||
@ -1103,7 +1121,7 @@ JOIN::optimize()
|
||||
join_tab[const_tables].select->quick->get_type() !=
|
||||
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
|
||||
{
|
||||
if (group_list &&
|
||||
if (group_list && rollup.state == ROLLUP::STATE_NONE &&
|
||||
list_contains_unique_index(join_tab[const_tables].table,
|
||||
find_field_in_order_list,
|
||||
(void *) group_list))
|
||||
@ -1147,7 +1165,8 @@ JOIN::optimize()
|
||||
if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE)
|
||||
select_distinct=0;
|
||||
}
|
||||
else if (select_distinct && tables - const_tables == 1)
|
||||
else if (select_distinct && tables - const_tables == 1 &&
|
||||
rollup.state == ROLLUP::STATE_NONE)
|
||||
{
|
||||
/*
|
||||
We are only using one table. In this case we change DISTINCT to a
|
||||
@ -3587,7 +3606,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
|
||||
{
|
||||
if (!(form->keys_in_use_for_query.is_set(key)))
|
||||
continue;
|
||||
if (form->key_info[key].flags & HA_FULLTEXT)
|
||||
if (form->key_info[key].flags & (HA_FULLTEXT | HA_SPATIAL))
|
||||
continue; // ToDo: ft-keys in non-ft queries. SerG
|
||||
|
||||
uint key_parts= (uint) form->key_info[key].key_parts;
|
||||
@ -9071,7 +9090,10 @@ static void restore_prev_nj_state(JOIN_TAB *last)
|
||||
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
|
||||
else if (last_emb->nested_join->join_list.elements-1 ==
|
||||
last_emb->nested_join->counter)
|
||||
{
|
||||
join->cur_embedding_map|= last_emb->nested_join->nj_map;
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
last_emb= last_emb->embedding;
|
||||
@ -9518,8 +9540,47 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
|
||||
new_field->set_derivation(item->collation.derivation);
|
||||
break;
|
||||
case DECIMAL_RESULT:
|
||||
new_field= Field_new_decimal::new_decimal_field(item);
|
||||
{
|
||||
uint8 dec= item->decimals;
|
||||
uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec;
|
||||
uint32 len= item->max_length;
|
||||
|
||||
/*
|
||||
Trying to put too many digits overall in a DECIMAL(prec,dec)
|
||||
will always throw a warning. We must limit dec to
|
||||
DECIMAL_MAX_SCALE however to prevent an assert() later.
|
||||
*/
|
||||
|
||||
if (dec > 0)
|
||||
{
|
||||
signed int overflow;
|
||||
|
||||
dec= min(dec, DECIMAL_MAX_SCALE);
|
||||
|
||||
/*
|
||||
If the value still overflows the field with the corrected dec,
|
||||
we'll throw out decimals rather than integers. This is still
|
||||
bad and of course throws a truncation warning.
|
||||
+1: for decimal point
|
||||
*/
|
||||
|
||||
const int required_length=
|
||||
my_decimal_precision_to_length(intg + dec, dec,
|
||||
item->unsigned_flag);
|
||||
|
||||
overflow= required_length - len;
|
||||
|
||||
if (overflow > 0)
|
||||
dec= max(0, dec - overflow); // too long, discard fract
|
||||
else
|
||||
/* Corrected value fits. */
|
||||
len= required_length;
|
||||
}
|
||||
|
||||
new_field= new Field_new_decimal(len, maybe_null, item->name,
|
||||
dec, item->unsigned_flag);
|
||||
break;
|
||||
}
|
||||
case ROW_RESULT:
|
||||
default:
|
||||
// This case should never be choosen
|
||||
@ -10321,6 +10382,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
for (; cur_group ; cur_group= cur_group->next, key_part_info++)
|
||||
{
|
||||
Field *field=(*cur_group->item)->get_tmp_table_field();
|
||||
DBUG_ASSERT(field->table == table);
|
||||
bool maybe_null=(*cur_group->item)->maybe_null;
|
||||
key_part_info->null_bit=0;
|
||||
key_part_info->field= field;
|
||||
@ -11302,6 +11364,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
bool not_used_in_distinct=join_tab->not_used_in_distinct;
|
||||
ha_rows found_records=join->found_records;
|
||||
COND *select_cond= join_tab->select_cond;
|
||||
bool select_cond_result= TRUE;
|
||||
|
||||
if (error > 0 || (join->thd->is_error())) // Fatal error
|
||||
return NESTED_LOOP_ERROR;
|
||||
@ -11313,7 +11376,17 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
return NESTED_LOOP_KILLED; /* purecov: inspected */
|
||||
}
|
||||
DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
|
||||
if (!select_cond || select_cond->val_int())
|
||||
|
||||
if (select_cond)
|
||||
{
|
||||
select_cond_result= test(select_cond->val_int());
|
||||
|
||||
/* check for errors evaluating the condition */
|
||||
if (join->thd->is_error())
|
||||
return NESTED_LOOP_ERROR;
|
||||
}
|
||||
|
||||
if (!select_cond || select_cond_result)
|
||||
{
|
||||
/*
|
||||
There is no select condition or the attached pushed down
|
||||
@ -15766,32 +15839,7 @@ bool JOIN::rollup_init()
|
||||
{
|
||||
item->maybe_null= 1;
|
||||
found_in_group= 1;
|
||||
if (item->const_item())
|
||||
{
|
||||
/*
|
||||
For ROLLUP queries each constant item referenced in GROUP BY list
|
||||
is wrapped up into an Item_func object yielding the same value
|
||||
as the constant item. The objects of the wrapper class are never
|
||||
considered as constant items and besides they inherit all
|
||||
properties of the Item_result_field class.
|
||||
This wrapping allows us to ensure writing constant items
|
||||
into temporary tables whenever the result of the ROLLUP
|
||||
operation has to be written into a temporary table, e.g. when
|
||||
ROLLUP is used together with DISTINCT in the SELECT list.
|
||||
Usually when creating temporary tables for a intermidiate
|
||||
result we do not include fields for constant expressions.
|
||||
*/
|
||||
Item* new_item= new Item_func_rollup_const(item);
|
||||
if (!new_item)
|
||||
return 1;
|
||||
new_item->fix_fields(thd, (Item **) 0);
|
||||
thd->change_item_tree(it.ref(), new_item);
|
||||
for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
|
||||
{
|
||||
if (*tmp->item == item)
|
||||
thd->change_item_tree(tmp->item, new_item);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item->type() == Item::FUNC_ITEM && !found_in_group)
|
||||
@ -15810,6 +15858,59 @@ bool JOIN::rollup_init()
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Wrap all constant Items in GROUP BY list.
|
||||
|
||||
For ROLLUP queries each constant item referenced in GROUP BY list
|
||||
is wrapped up into an Item_func object yielding the same value
|
||||
as the constant item. The objects of the wrapper class are never
|
||||
considered as constant items and besides they inherit all
|
||||
properties of the Item_result_field class.
|
||||
This wrapping allows us to ensure writing constant items
|
||||
into temporary tables whenever the result of the ROLLUP
|
||||
operation has to be written into a temporary table, e.g. when
|
||||
ROLLUP is used together with DISTINCT in the SELECT list.
|
||||
Usually when creating temporary tables for a intermidiate
|
||||
result we do not include fields for constant expressions.
|
||||
|
||||
@retval
|
||||
0 if ok
|
||||
@retval
|
||||
1 on error
|
||||
*/
|
||||
|
||||
bool JOIN::rollup_process_const_fields()
|
||||
{
|
||||
ORDER *group_tmp;
|
||||
Item *item;
|
||||
List_iterator<Item> it(all_fields);
|
||||
|
||||
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
|
||||
{
|
||||
if (!(*group_tmp->item)->const_item())
|
||||
continue;
|
||||
while ((item= it++))
|
||||
{
|
||||
if (*group_tmp->item == item)
|
||||
{
|
||||
Item* new_item= new Item_func_rollup_const(item);
|
||||
if (!new_item)
|
||||
return 1;
|
||||
new_item->fix_fields(thd, (Item **) 0);
|
||||
thd->change_item_tree(it.ref(), new_item);
|
||||
for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
|
||||
{
|
||||
if (*tmp->item == item)
|
||||
thd->change_item_tree(tmp->item, new_item);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
it.rewind();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user