diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 11 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 | ||||
-rw-r--r-- | sql/sql_select.h | 9 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 3 |
6 files changed, 27 insertions, 6 deletions
diff --git a/sql/item.cc b/sql/item.cc index d6785461a7d..593915ef172 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1082,9 +1082,9 @@ bool Item_sp_variable::is_null() Item_splocal::Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, enum_field_types sp_var_type, - uint pos_in_q) + uint pos_in_q, uint len_in_q) :Item_sp_variable(sp_var_name.str, sp_var_name.length), - m_var_idx(sp_var_idx), pos_in_query(pos_in_q) + m_var_idx(sp_var_idx), pos_in_query(pos_in_q), len_in_query(len_in_q) { maybe_null= TRUE; diff --git a/sql/item.h b/sql/item.h index 5f4e0117d02..ab39505bf5f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1054,9 +1054,18 @@ public: SP variable in query text. */ uint pos_in_query; + /* + Byte length of SP variable name in the statement (see pos_in_query). + The value of this field may differ from the name_length value because + name_length contains byte length of UTF8-encoded item name, but + the query string (see sp_instr_stmt::m_query) is currently stored with + a charset from the SET NAMES statement. + */ + uint len_in_query; Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, - enum_field_types sp_var_type, uint pos_in_q= 0); + enum_field_types sp_var_type, + uint pos_in_q= 0, uint len_in_q= 0); bool is_splocal() { return 1; } /* Needed for error checking */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a5ad5043985..7b2073b8de3 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -927,7 +927,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) /* append the text between sp ref occurences */ res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); - prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; + prev_pos= (*splocal)->pos_in_query + (*splocal)->len_in_query; /* append the spvar substitute */ res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6a381c1f367..192709cea55 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1134,6 +1134,7 @@ JOIN::optimize() order=0; // The output has only one row simple_order=1; select_distinct= 0; // No need in distinct for 1 row + group_optimized_away= 1; } calc_group_buffer(this, group_list); @@ -11742,7 +11743,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!join->first_record || end_of_records || (idx=test_if_group_changed(join->group_fields)) >= 0) { - if (join->first_record || (end_of_records && !join->group)) + if (join->first_record || + (end_of_records && !join->group && !join->group_optimized_away)) { if (join->procedure) join->procedure->end_group(); diff --git a/sql/sql_select.h b/sql/sql_select.h index 98f2a7829dd..64173a91162 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -321,6 +321,14 @@ public: ROLLUP rollup; // Used with rollup bool select_distinct; // Set if SELECT DISTINCT + /* + If we have the GROUP BY statement in the query, + but the group_list was emptied by optimizer, this + flag is TRUE. + It happens when fields in the GROUP BY are from + constant table + */ + bool group_optimized_away; /* simple_xxxxx is set if ORDER/GROUP BY doesn't include any references @@ -429,6 +437,7 @@ public: zero_result_cause= 0; optimized= 0; cond_equal= 0; + group_optimized_away= 0; all_fields= fields_arg; fields_list= fields_arg; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 468c3305c57..855c8dede5f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9505,7 +9505,8 @@ simple_ident: Item_splocal *splocal; splocal= new Item_splocal($1, spv->offset, spv->type, lip->get_tok_start_prev() - - lex->sphead->m_tmp_query); + lex->sphead->m_tmp_query, + lip->get_tok_end() - lip->get_tok_start_prev()); #ifndef DBUG_OFF if (splocal) splocal->m_sp= lex->sphead; |