summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc6
-rw-r--r--sql/item_cmpfunc.cc11
-rw-r--r--sql/item_cmpfunc.h5
-rw-r--r--sql/mysqld.cc5
-rw-r--r--sql/sp_head.cc31
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_handler.cc4
-rw-r--r--sql/sql_select.cc43
-rw-r--r--sql/sql_show.cc9
-rw-r--r--sql/sql_yacc.yy4
10 files changed, 93 insertions, 27 deletions
diff --git a/sql/field.cc b/sql/field.cc
index d162b9e202b..37cab37f7d2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -9068,11 +9068,11 @@ uint32 Field_blob::max_length()
switch (packlength)
{
case 1:
- return 255;
+ return 255 * field_charset->mbmaxlen;
case 2:
- return 65535;
+ return 65535 * field_charset->mbmaxlen;
case 3:
- return 16777215;
+ return 16777215 * field_charset->mbmaxlen;
case 4:
return (uint32) 4294967295U;
default:
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 0d2056e9e99..3b4ca098d89 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3765,6 +3765,7 @@ void Item_equal::update_used_tables()
longlong Item_equal::val_int()
{
+ Item_field *item_field;
if (cond_false)
return 0;
List_iterator_fast<Item_field> it(fields);
@@ -3772,10 +3773,14 @@ longlong Item_equal::val_int()
if ((null_value= item->null_value))
return 0;
eval_item->store_value(item);
- while ((item= it++))
+ while ((item_field= it++))
{
- if ((null_value= item->null_value) || eval_item->cmp(item))
- return 0;
+ /* Skip fields of non-const tables. They haven't been read yet */
+ if (item_field->field->table->const_table)
+ {
+ if ((null_value= item_field->null_value) || eval_item->cmp(item_field))
+ return 0;
+ }
}
return 1;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index b4064fb45b8..98ccefd08ab 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1150,6 +1150,11 @@ public:
are deleted in the end of execution. All changes made to these
objects need not be registered in the list of changes of the parse
tree and do not harm PS/SP re-execution.
+
+ Item equal objects are employed only at the optimize phase. Usually they are
+ not supposed to be evaluated. Yet in some cases we call the method val_int()
+ for them. We have to take care of restricting the predicate such an
+ object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik.
*/
class Item_equal: public Item_bool_func
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 953d0847c4d..8bc005705c9 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3493,6 +3493,11 @@ int main(int argc, char **argv)
}
}
#endif
+#ifdef __NETWARE__
+ /* Increasing stacksize of threads on NetWare */
+
+ pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE);
+#endif
(void) thr_setconcurrency(concurrency); // 10 by default
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c1f05b0e35c..33eb652208f 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -3146,7 +3146,14 @@ sp_restore_security_context(THD *thd, Security_context *backup)
typedef struct st_sp_table
{
- LEX_STRING qname; /* Multi-set key: db_name\0table_name\0alias\0 */
+ /*
+ Multi-set key:
+ db_name\0table_name\0alias\0 - for normal tables
+ db_name\0table_name\0 - for temporary tables
+ Note that in both cases we don't take last '\0' into account when
+ we count length of key.
+ */
+ LEX_STRING qname;
uint db_length, table_name_length;
bool temp; /* true if corresponds to a temporary table */
thr_lock_type lock_type; /* lock type used for prelocking */
@@ -3216,10 +3223,14 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
tname[tlen]= '\0';
/*
- It is safe to store pointer to table list elements in hash,
- since they are supposed to have the same lifetime.
+ We ignore alias when we check if table was already marked as temporary
+ (and therefore should not be prelocked). Otherwise we will erroneously
+ treat table with same name but with different alias as non-temporary.
*/
- if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (byte *)tname, tlen)))
+ if ((tab= (SP_TABLE *)hash_search(&m_sptabs, (byte *)tname, tlen)) ||
+ ((tab= (SP_TABLE *)hash_search(&m_sptabs, (byte *)tname,
+ tlen - alen - 1)) &&
+ tab->temp))
{
if (tab->lock_type < table->lock_type)
tab->lock_type= table->lock_type; // Use the table with the highest lock type
@@ -3231,14 +3242,18 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
{
if (!(tab= (SP_TABLE *)thd->calloc(sizeof(SP_TABLE))))
return FALSE;
- tab->qname.length= tlen;
- tab->qname.str= (char*) thd->memdup(tname, tab->qname.length + 1);
- if (!tab->qname.str)
- return FALSE;
if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE &&
lex_for_tmp_check->query_tables == table &&
lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ {
tab->temp= TRUE;
+ tab->qname.length= tlen - alen - 1;
+ }
+ else
+ tab->qname.length= tlen;
+ tab->qname.str= (char*) thd->memdup(tname, tab->qname.length + 1);
+ if (!tab->qname.str)
+ return FALSE;
tab->table_name_length= table->table_name_length;
tab->db_length= table->db_length;
tab->lock_type= table->lock_type;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 85c5a481d47..d502562ec7c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2083,8 +2083,10 @@ static bool reopen_table(TABLE *table)
(*field)->table_name= &table->alias;
}
for (key=0 ; key < table->s->keys ; key++)
+ {
for (part=0 ; part < table->key_info[key].usable_key_parts ; part++)
table->key_info[key].key_part[part].field->table= table;
+ }
if (table->triggers)
table->triggers->set_table(table);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index f1bbf6f0f5e..78eacd02e56 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -424,7 +424,11 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (cond && ((!cond->fixed &&
cond->fix_fields(thd, &cond)) || cond->check_cols(1)))
+ {
+ if (table->query_id != thd->query_id)
+ cond->cleanup(); // File was reopened
goto err0;
+ }
if (keyname)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1a217df2878..ed468ce59bb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3508,13 +3508,32 @@ best_access_path(JOIN *join,
parts of the row from any of the used index.
This is because table scans uses index and we would not win
anything by using a table scan.
+
+ A word for word translation of the below if-statement in psergey's
+ understanding: we check if we should use table scan if:
+ (1) The found 'ref' access produces more records than a table scan
+ (or index scan, or quick select), or 'ref' is more expensive than
+ any of them.
+ (2) This doesn't hold: the best way to perform table scan is to to perform
+ 'range' access using index IDX, and the best way to perform 'ref'
+ access is to use the same index IDX, with the same or more key parts.
+ (note: it is not clear how this rule is/should be extended to
+ index_merge quick selects)
+ (3) See above note about InnoDB.
+ (4) NOT ("FORCE INDEX(...)" is used for table and there is 'ref' access
+ path, but there is no quick select)
+ If the condition in the above brackets holds, then the only possible
+ "table scan" access method is ALL/index (there is no quick select).
+ Since we have a 'ref' access path, and FORCE INDEX instructs us to
+ choose it over ALL/index, there is no need to consider a full table
+ scan.
*/
- if ((records >= s->found_records || best > s->read_time) &&
- !(s->quick && best_key && s->quick->index == best_key->key &&
- best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
- !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
- ! s->table->used_keys.is_clear_all() && best_key) &&
- !(s->table->force_index && best_key))
+ if ((records >= s->found_records || best > s->read_time) && // (1)
+ !(s->quick && best_key && s->quick->index == best_key->key && // (2)
+ best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
+ !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
+ ! s->table->used_keys.is_clear_all() && best_key) && // (3)
+ !(s->table->force_index && best_key && !s->quick)) // (4)
{ // Check full join
ha_rows rnd_records= s->found_records;
/*
@@ -4497,13 +4516,15 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
parts of the row from any of the used index.
This is because table scans uses index and we would not win
anything by using a table scan.
+ (see comment in best_access_path() for more details on the below
+ condition)
*/
if ((records >= s->found_records || best > s->read_time) &&
!(s->quick && best_key && s->quick->index == best_key->key &&
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
!((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
! s->table->used_keys.is_clear_all() && best_key) &&
- !(s->table->force_index && best_key))
+ !(s->table->force_index && best_key && !s->quick))
{ // Check full join
ha_rows rnd_records= s->found_records;
/*
@@ -8651,6 +8672,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
have null
*/
hidden_null_count=null_count;
+ /*
+ We need to update hidden_field_count as we may have stored group
+ functions with constant arguments
+ */
+ param->hidden_field_count= (uint) (reg_field - table->field);
null_count= 0;
}
}
@@ -8872,7 +8898,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
}
- if (distinct)
+ if (distinct && field_count != param->hidden_field_count)
{
/*
Create an unique key or an unique constraint over all columns
@@ -9938,6 +9964,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
int error;
READ_RECORD *info;
+ join_tab->table->null_row= 0;
if (!join_tab->cache.records)
return NESTED_LOOP_OK; /* Nothing to do */
if (skip_last)
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d6b04a9135c..5c1ec8b3a49 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2734,12 +2734,15 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type
field->real_type() == MYSQL_TYPE_STRING) // For binary type
{
+ uint32 octet_max_length= field->max_length();
+ if (octet_max_length != (uint32) 4294967295U)
+ octet_max_length /= field->charset()->mbmaxlen;
longlong char_max_len= is_blob ?
- (longlong) field->max_length() / field->charset()->mbminlen :
- (longlong) field->max_length() / field->charset()->mbmaxlen;
+ (longlong) octet_max_length / field->charset()->mbminlen :
+ (longlong) octet_max_length / field->charset()->mbmaxlen;
table->field[8]->store(char_max_len, TRUE);
table->field[8]->set_notnull();
- table->field[9]->store((longlong) field->max_length(), TRUE);
+ table->field[9]->store((longlong) octet_max_length, TRUE);
table->field[9]->set_notnull();
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f35683b5f76..fde014898f4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -6710,13 +6710,13 @@ join_table:
| table_ref LEFT opt_outer JOIN_SYM table_ref
ON
{
+ YYERROR_UNLESS($1 && $5);
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $5))
YYABORT;
}
expr
{
- YYERROR_UNLESS($1 && $5);
add_join_on($5,$8);
Lex->pop_context();
$5->outer_join|=JOIN_TYPE_LEFT;
@@ -6741,6 +6741,7 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_ref
ON
{
+ YYERROR_UNLESS($1 && $5);
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $5))
YYABORT;
@@ -6748,7 +6749,6 @@ join_table:
expr
{
LEX *lex= Lex;
- YYERROR_UNLESS($1 && $5);
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
add_join_on($$, $8);