summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc163
1 files changed, 132 insertions, 31 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 549fbb653d1..73bdf63511f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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;
+}
/**