summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_ndbcluster.cc1
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/item.cc26
-rw-r--r--sql/item.h3
-rw-r--r--sql/item_cmpfunc.cc11
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/opt_range.cc3
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/protocol.h4
-rw-r--r--sql/protocol_cursor.cc23
-rw-r--r--sql/sp.cc8
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_base.cc20
-rw-r--r--sql/sql_class.cc15
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_handler.cc7
-rw-r--r--sql/sql_parse.cc27
-rw-r--r--sql/sql_prepare.cc27
-rw-r--r--sql/sql_select.cc71
-rw-r--r--sql/sql_table.cc37
-rw-r--r--sql/sql_trigger.cc7
-rw-r--r--sql/sql_update.cc7
-rw-r--r--sql/sql_view.cc9
-rw-r--r--sql/sql_yacc.yy3
26 files changed, 201 insertions, 130 deletions
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index d59ab919862..7878684718c 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -4015,6 +4015,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
(void)mysql_rm_table_part2(thd, &table_list,
/* if_exists */ TRUE,
/* drop_temporary */ FALSE,
+ /* drop_view */ FALSE,
/* dont_log_query*/ TRUE);
}
}
diff --git a/sql/handler.cc b/sql/handler.cc
index edb47865e8d..5b600719acd 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1427,7 +1427,7 @@ int ha_create_table_from_engine(THD* thd,
if ((error = writefrm(path, frmblob, frmlen)))
goto err_end;
- if (openfrm(path,"",0,(uint) READ_ALL, 0, &table))
+ if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table))
DBUG_RETURN(1);
update_create_info_from_table(&create_info, &table);
diff --git a/sql/item.cc b/sql/item.cc
index 7476f5af312..6730b0dd4a2 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -45,11 +45,11 @@ void item_init(void)
}
Item::Item():
- name_length(0), fixed(0)
+ name_length(0), fixed(0),
+ collation(default_charset(), DERIVATION_COERCIBLE)
{
marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0;
- collation.set(default_charset(), DERIVATION_COERCIBLE);
name= 0;
decimals= 0; max_length= 0;
@@ -1576,6 +1576,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(char*) cached_table->alias, (char*) field_name);
if (!rf)
return 1;
+ thd->change_item_tree(ref, rf);
/*
rf is Item_ref => never substitute other items (in this case)
during fix_fields() => we can use rf after fix_fields()
@@ -1654,6 +1655,7 @@ void Item_field::cleanup()
I.e. we can drop 'field'.
*/
field= result_field= 0;
+ DBUG_VOID_RETURN;
}
/*
@@ -1698,7 +1700,8 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
/*
- Set a pointer to the multiple equality the field reference belongs to (if any)
+ Set a pointer to the multiple equality the field reference belongs to
+ (if any)
SYNOPSIS
equal_fields_propagator()
@@ -1737,7 +1740,21 @@ Item *Item_field::equal_fields_propagator(byte *arg)
/*
- Set a pointer to the multiple equality the field reference belongs to (if any)
+ Mark the item to not be part of substitution if it's not a binary item
+ See comments in Arg_comparator::set_compare_func() for details
+*/
+
+Item *Item_field::set_no_const_sub(byte *arg)
+{
+ if (field->charset() != &my_charset_bin)
+ no_const_subst=1;
+ return this;
+}
+
+
+/*
+ Set a pointer to the multiple equality the field reference belongs to
+ (if any)
SYNOPSIS
replace_equal_field_processor()
@@ -1773,6 +1790,7 @@ bool Item_field::replace_equal_field_processor(byte *arg)
return 0;
}
+
void Item::init_make_field(Send_field *tmp_field,
enum enum_field_types field_type)
{
diff --git a/sql/item.h b/sql/item.h
index b39a95d796c..d3e53af1523 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -285,6 +285,7 @@ public:
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
virtual bool collect_item_field_processor(byte * arg) { return 0; }
virtual Item *equal_fields_propagator(byte * arg) { return this; }
+ virtual Item *set_no_const_sub(byte *arg) { return this; }
virtual bool replace_equal_field_processor(byte * arg) { return 0; }
virtual Item *this_item() { return this; } /* For SPs mostly. */
@@ -536,6 +537,7 @@ public:
void cleanup();
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item *equal_fields_propagator(byte *arg);
+ Item *set_no_const_sub(byte *arg);
bool replace_equal_field_processor(byte *arg);
inline uint32 max_disp_length() { return field->max_length(); }
Item_field *filed_for_view_update() { return this; }
@@ -1024,6 +1026,7 @@ public:
bool walk(Item_processor processor, byte *arg)
{ return (*ref)->walk(processor, arg); }
void print(String *str);
+ void cleanup();
};
class Item_in_subselect;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ab8acdd465f..467cd8313a4 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -320,6 +320,17 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
func= &Arg_comparator::compare_binary_string;
else if (func == &Arg_comparator::compare_e_string)
func= &Arg_comparator::compare_e_binary_string;
+
+ /*
+ As this is binary comparsion, mark all fields that they can't be
+ transformed. Otherwise we would get into trouble with comparisons
+ like:
+ WHERE col= 'j' AND col LIKE BINARY 'j'
+ which would be transformed to:
+ WHERE col= 'j'
+ */
+ (*a)->transform(&Item::set_no_const_sub, (byte*) 0);
+ (*b)->transform(&Item::set_no_const_sub, (byte*) 0);
}
}
else if (type == INT_RESULT)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 58ef44cc225..3cc0fd077a4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -292,7 +292,8 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument)
Item *new_item= (*arg)->transform(transformer, argument);
if (!new_item)
return 0;
- *arg= new_item;
+ if (*arg != new_item)
+ current_thd->change_item_tree(arg, new_item);
}
}
return (this->*transformer)(argument);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index a80b0e13df8..ee5af6ed1c0 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1543,7 +1543,7 @@ end:
updating query.
*/
return (thd->query_error ? thd->query_error :
- (thd->one_shot_set ? (rli->inc_event_relay_log_pos(get_event_len()),0) :
+ (thd->one_shot_set ? (rli->inc_event_relay_log_pos(),0) :
Log_event::exec_event(rli)));
}
#endif
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a339b61563a..5c0b47aca4a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -492,7 +492,7 @@ bool is_update_query(enum enum_sql_command command);
bool alloc_query(THD *thd, char *packet, ulong packet_length);
void mysql_init_select(LEX *lex);
void mysql_reset_thd_for_next_command(THD *thd);
-void mysql_init_query(THD *thd, uchar *buf, uint length, bool lexonly=0);
+void mysql_init_query(THD *thd, uchar *buf, uint length);
bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 10b9fc9fbfd..c2cdc39714b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -712,8 +712,9 @@ QUICK_SELECT_I::QUICK_SELECT_I()
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
bool no_alloc, MEM_ROOT *parent_alloc)
- :dont_free(0),sorted(0),error(0),free_file(0),cur_range(NULL),range(0)
+ :dont_free(0),error(0),free_file(0),cur_range(NULL),range(0)
{
+ sorted= 0;
index= key_nr;
head= table;
key_part_info= head->key_info[index].key_part;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 36296cea59b..051eaaf7bda 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -507,7 +507,7 @@ void Protocol::init(THD *thd_arg)
*/
#ifndef EMBEDDED_LIBRARY
-bool Protocol::send_fields(List<Item> *list, int flags)
+bool Protocol::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
diff --git a/sql/protocol.h b/sql/protocol.h
index 1a5896a3ae5..7d390242417 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -52,7 +52,7 @@ public:
void init(THD* thd_arg);
enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 };
- virtual bool send_fields(List<Item> *list, int flags);
+ virtual bool send_fields(List<Item> *list, uint flags);
bool send_records_num(List<Item> *list, ulonglong records);
bool store(I_List<i_string> *str_list);
@@ -166,7 +166,7 @@ public:
prev_record= &data;
return Protocol_simple::prepare_for_send(item_list);
}
- bool send_fields(List<Item> *list, int flags);
+ bool send_fields(List<Item> *list, uint flags);
bool write();
uint get_field_count() { return field_count; }
};
diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc
index 8904aba7b88..104457b3bcc 100644
--- a/sql/protocol_cursor.cc
+++ b/sql/protocol_cursor.cc
@@ -26,22 +26,21 @@
#include "mysql_priv.h"
#include <mysql.h>
-bool Protocol_cursor::send_fields(List<Item> *list, int flags)
+bool Protocol_cursor::send_fields(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
MYSQL_FIELD *client_field;
-
- DBUG_ENTER("send_fields");
+ DBUG_ENTER("Protocol_cursor::send_fields");
+
if (prepare_for_send(list))
- return FALSE;
+ return FALSE;
fields= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count);
if (!fields)
goto err;
- client_field= fields;
- while ((item= it++))
+ for (client_field= fields; (item= it++) ; client_field++)
{
Send_field server_field;
item->make_field(&server_field);
@@ -67,7 +66,7 @@ bool Protocol_cursor::send_fields(List<Item> *list, int flags)
if (INTERNAL_NUM_FIELD(client_field))
client_field->flags|= NUM_FLAG;
- if (flags & (int) Protocol::SEND_DEFAULTS)
+ if (flags & (uint) Protocol::SEND_DEFAULTS)
{
char buff[80];
String tmp(buff, sizeof(buff), default_charset_info), *res;
@@ -80,16 +79,18 @@ bool Protocol_cursor::send_fields(List<Item> *list, int flags)
else
client_field->def=0;
client_field->max_length= 0;
- ++client_field;
}
DBUG_RETURN(FALSE);
- err:
+
+err:
send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */
DBUG_RETURN(TRUE); /* purecov: inspected */
}
+
/* Get the length of next field. Change parameter to point at fieldstart */
+
bool Protocol_cursor::write()
{
byte *cp= (byte *)packet->ptr();
@@ -121,7 +122,7 @@ bool Protocol_cursor::write()
{
if ((long)len > (end_pos - cp))
{
-// TODO error signal send_error(thd, CR_MALFORMED_PACKET);
+ // TODO error signal send_error(thd, CR_MALFORMED_PACKET);
return TRUE;
}
*data_tmp= to;
@@ -141,6 +142,6 @@ bool Protocol_cursor::write()
row_count++;
return FALSE;
err:
-// TODO error signal send_error(thd, ER_OUT_OF_RESOURCES);
+ // TODO error signal send_error(thd, ER_OUT_OF_RESOURCES);
return TRUE;
}
diff --git a/sql/sp.cc b/sql/sp.cc
index e444a412760..a1e52ee1ca7 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -293,7 +293,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
*/
List<Item> vals= thd->lex->value_list;
- mysql_init_query(thd, (uchar*)defstr.c_ptr(), defstr.length(), TRUE);
+ lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
thd->lex->value_list= vals;
}
@@ -455,7 +455,7 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
if (ret == SP_OK)
{
store_record(table,record[1]);
- table->timestamp_on_update_now = 0; // Don't update create time now.
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
if (chistics->suid != SP_IS_DEFAULT_SUID)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
@@ -1055,6 +1055,10 @@ create_string(THD *thd, String *buf,
case SP_MODIFIES_SQL_DATA:
buf->append(" MODIFIES SQL DATA\n");
break;
+ case SP_DEFAULT_ACCESS:
+ case SP_CONTAINS_SQL:
+ /* Do nothing */
+ break;
}
if (chistics->detistic)
buf->append(" DETERMINISTIC\n", 18);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 82f8e88d889..8de1b6e906a 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -765,7 +765,7 @@ sp_head::reset_lex(THD *thd)
thd->lex= sublex= new st_lex;
/* Reset most stuff. The length arguments doesn't matter here. */
- mysql_init_query(thd,oldlex->buf, oldlex->end_of_query - oldlex->ptr, TRUE);
+ lex_start(thd, oldlex->buf, (ulong) (oldlex->end_of_query - oldlex->ptr));
/* We must reset ptr and end_of_query again */
sublex->ptr= oldlex->ptr;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index af6c4740e93..b3be1fc7338 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -958,7 +958,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
/* close handler tables which are marked for flush */
- mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
+ if (thd->handler_tables)
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ;
@@ -2095,11 +2096,14 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
*ref= trans[i];
else
{
- *ref= new Item_ref(trans + i, ref, table_list->view_name.str,
- item_name);
- /* as far as Item_ref have defined refernce it do not need tables */
- if (*ref)
+ Item_ref *item_ref= new Item_ref(trans + i, table_list->view_name.str,
+ item_name);
+ /* as far as Item_ref have defined reference it do not need tables */
+ if (item_ref)
+ {
+ thd->change_item_tree(ref, item_ref);
(*ref)->fix_fields(thd, 0, ref);
+ }
}
return (Field*) view_ref_found;
}
@@ -2823,7 +2827,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
RETURN
0 ok
'it' is updated to point at last inserted
- 1 error. The error message is sent to client
+ 1 error. Error message is generated but not sent to client
*/
bool
@@ -2999,9 +3003,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
during cleunup() this item will be put in list to replace
expression from VIEW
*/
- item->changed_during_fix_field= it->ref();
+ thd->nocheck_register_item_tree_change(it->ref(), item, &thd->mem_root);
}
-
}
/* All fields are used */
table->used_fields=table->fields;
@@ -3016,7 +3019,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
err:
- send_error(thd);
DBUG_RETURN(1);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9bf7cff85c0..f5283020b30 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -165,6 +165,9 @@ THD::THD()
in_lock_tables(0), bootstrap(0), spcont(NULL)
{
current_arena= this;
+#ifndef DBUG_OFF
+ backup_arena= 0;
+#endif
host= user= priv_user= db= ip= 0;
catalog= (char*)"std"; // the only catalog we have for now
host_or_ip= "connecting host";
@@ -795,10 +798,13 @@ void THD::rollback_item_tree_changes()
{
I_List_iterator<Item_change_record> it(change_list);
Item_change_record *change;
+ DBUG_ENTER("rollback_item_tree_changes");
+
while ((change= it++))
*change->place= change->old_value;
/* We can forget about changes memory: it's allocated in runtime memroot */
change_list.empty();
+ DBUG_VOID_RETURN;
}
@@ -1585,16 +1591,24 @@ void THD::end_statement()
void Item_arena::set_n_backup_item_arena(Item_arena *set, Item_arena *backup)
{
DBUG_ENTER("Item_arena::set_n_backup_item_arena");
+ DBUG_ASSERT(backup_arena == 0);
backup->set_item_arena(this);
set_item_arena(set);
+#ifndef DBUG_OFF
+ backup_arena= 1;
+#endif
DBUG_VOID_RETURN;
}
void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
{
+ DBUG_ENTER("Item_arena::restore_backup_item_arena");
set->set_item_arena(this);
set_item_arena(backup);
+#ifndef DBUG_OFF
+ backup_arena= 0;
+#endif
#ifdef NOT_NEEDED_NOW
/*
Reset backup mem_root to avoid its freeing.
@@ -1605,6 +1619,7 @@ void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
*/
clear_alloc_root(&backup->mem_root);
#endif
+ DBUG_VOID_RETURN;
}
void Item_arena::set_item_arena(Item_arena *set)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6e0aacc4fce..fcaebe64b43 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -516,6 +516,9 @@ public:
*/
Item *free_list;
MEM_ROOT mem_root;
+#ifndef DBUG_OFF
+ bool backup_arena;
+#endif
enum enum_state
{
INITIALIZED= 0, PREPARED= 1, EXECUTED= 3, CONVENTIONAL_EXECUTION= 2,
@@ -552,7 +555,7 @@ public:
inline bool is_first_stmt_execute() const { return state == PREPARED; }
inline bool is_stmt_execute() const
{ return state == PREPARED || state == EXECUTED; }
- inline bool is_conventional_execution() const
+ inline bool is_conventional() const
{ return state == CONVENTIONAL_EXECUTION; }
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
inline gptr calloc(unsigned int size)
@@ -1167,7 +1170,7 @@ public:
void change_item_tree(Item **place, Item *new_value)
{
/* TODO: check for OOM condition here */
- if (!current_arena->is_conventional_execution())
+ if (!current_arena->is_conventional())
nocheck_register_item_tree_change(place, *place, &mem_root);
*place= new_value;
}
@@ -1254,6 +1257,7 @@ public:
virtual bool initialize_tables (JOIN *join=0) { return 0; }
virtual void send_error(uint errcode,const char *err);
virtual bool send_eof()=0;
+ virtual bool simple_select() { return 0; }
virtual void abort() {}
/*
Cleanup instance of this class for next execution of a prepared
@@ -1283,6 +1287,7 @@ public:
bool send_fields(List<Item> &list, uint flags);
bool send_data(List<Item> &items);
bool send_eof();
+ bool simple_select() { return 1; }
};
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 61e57362bd4..edb895fd24a 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -288,7 +288,6 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
(*table_ptr)->file->ha_index_or_rnd_end();
VOID(pthread_mutex_lock(&LOCK_open));
- table->file->ha_index_or_rnd_end();
if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
@@ -532,11 +531,11 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
{
if (error == HA_ERR_RECORD_DELETED)
continue;
- if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE)
+ if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
sql_print_error("mysql_ha_read: Got error %d when reading table '%s'",
- err, tables->real_name);
- table->file->print_error(err,MYF(0));
+ error, tables->real_name);
+ table->file->print_error(error,MYF(0));
goto err;
}
goto ok;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 55e0d33cdde..77919329e16 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2809,7 +2809,8 @@ unsent_create_error:
break;
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
select_lex->item_list, lex->value_list,
- lex->duplicates);
+ (lex->value_list.elements ?
+ DUP_UPDATE : lex->duplicates));
if (thd->net.report_error)
res= -1;
if (first_table->view && !first_table->contain_auto_increment)
@@ -6241,9 +6242,9 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
LEX *lex= thd->lex;
DBUG_ENTER("insert_precheck");
- ulong privilege= INSERT_ACL |
- (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
- (lex->duplicates == DUP_UPDATE ? UPDATE_ACL : 0);
+ ulong privilege= (INSERT_ACL |
+ (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
+ (lex->value_list.elements ? UPDATE_ACL : 0));
if (check_one_table_access(thd, privilege, tables))
DBUG_RETURN(1);
@@ -6308,27 +6309,13 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables,
For temporary tables we don't have to check if the created table exists
*/
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- find_real_table_in_list(tables, create_table->db,
- create_table->real_name))
+ find_table_in_global_list(tables, create_table->db,
+ create_table->real_name))
{
net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
goto err;
}
- if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
- {
- TABLE_LIST *tab;
- for (tab= tables; tab; tab= tab->next)
- {
- if (find_real_table_in_list((TABLE_LIST*) lex->create_info.
- merge_list.first,
- tables->db, tab->real_name))
- {
- net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name);
- goto err;
- }
- }
- }
}
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
goto err;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index a9a81ed7b06..bb2362dd562 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -156,6 +156,8 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
{
NET *net= &stmt->thd->net;
char buff[9];
+ DBUG_ENTER("send_prep_stmt");
+
buff[0]= 0; /* OK packet indicator */
int4store(buff+1, stmt->id);
int2store(buff+5, columns);
@@ -164,13 +166,12 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
Send types and names of placeholders to the client
XXX: fix this nasty upcast from List<Item_param> to List<Item>
*/
- return my_net_write(net, buff, sizeof(buff)) ||
- (stmt->param_count &&
- stmt->thd->protocol_simple.send_fields((List<Item> *)
- &stmt->lex->param_list,
- Protocol::SEND_EOF)) ||
- net_flush(net);
- return 0;
+ DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) ||
+ (stmt->param_count &&
+ stmt->thd->protocol_simple.send_fields((List<Item> *)
+ &stmt->lex->param_list,
+ Protocol::SEND_EOF)) ||
+ net_flush(net));
}
#else
static bool send_prep_stmt(Prepared_statement *stmt,
@@ -1114,8 +1115,7 @@ static int mysql_test_select(Prepared_statement *stmt,
prepared in unit->prepare call above.
*/
if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
- thd->protocol_simple.send_fields(fields,
- Protocol::SEND_EOF)
+ lex->result->send_fields(fields, Protocol::SEND_EOF)
#ifndef EMBEDDED_LIBRARY
|| net_flush(&thd->net)
#endif
@@ -1682,11 +1682,13 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
DBUG_RETURN(!stmt);
}
+
/* Reinit statement before execution */
void reset_stmt_for_execute(THD *thd, LEX *lex)
{
SELECT_LEX *sl= lex->all_selects_list;
+ DBUG_ENTER("reset_stmt_for_execute");
if (lex->empty_field_list_on_rset)
{
@@ -1749,6 +1751,8 @@ void reset_stmt_for_execute(THD *thd, LEX *lex)
lex->current_select= &lex->select_lex;
if (lex->result)
lex->result->cleanup();
+
+ DBUG_VOID_RETURN;
}
@@ -1814,8 +1818,9 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
mysql_reset_thd_for_next_command(thd);
if (flags & (ulong) CURSOR_TYPE_READ_ONLY)
{
- if (stmt->lex->result)
+ if (!stmt->lex->result || !stmt->lex->result->simple_select())
{
+ DBUG_PRINT("info",("Cursor asked for not SELECT stmt"));
/*
If lex->result is set in the parser, this is not a SELECT
statement: we can't open a cursor for it.
@@ -1824,6 +1829,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
}
else
{
+ DBUG_PRINT("info",("Using READ_ONLY cursor"));
if (!stmt->cursor &&
!(stmt->cursor= new (&stmt->mem_root) Cursor()))
{
@@ -1885,6 +1891,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
cleanup_items(stmt->free_list);
reset_stmt_params(stmt);
close_thread_tables(thd); /* to close derived tables */
+ thd->rollback_item_tree_changes();
thd->cleanup_after_query();
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f4fbd03768d..2e1429feb3e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -91,7 +91,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
uint select_options, const char *info,
Item *having, Procedure *proc,
SELECT_LEX_UNIT *unit);
-static COND *build_equal_items(COND *cond,
+static COND *build_equal_items(THD *thd, COND *cond,
COND_EQUAL *inherited,
List<TABLE_LIST> *join_list,
COND_EQUAL **cond_equal_ref);
@@ -101,6 +101,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
COND *conds, bool top);
static COND *optimize_cond(JOIN *join, COND *conds,
+ List<TABLE_LIST> *join_list,
Item::cond_result *cond_value);
static bool resolve_nested_join (TABLE_LIST *table);
static COND *remove_eq_conds(THD *thd, COND *cond,
@@ -228,14 +229,11 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->options | thd->options,
result, unit, select_lex);
}
-
- /* Don't set res if it's -1 as we may want this later */
DBUG_PRINT("info",("res: %d report_error: %d", res,
thd->net.report_error));
- if (thd->net.report_error || res<0)
+ if (thd->net.report_error || res < 0)
{
- if (res > 0)
- result->send_error(0, NullS);
+ result->send_error(0, NullS);
result->abort();
res= 1; // Error sent to client
}
@@ -556,17 +554,7 @@ JOIN::optimize()
thd->restore_backup_item_arena(arena, &backup);
}
- /*
- Build all multiple equality predicates and eliminate equality
- predicates that can be inferred from these multiple equalities.
- For each reference of a field included into a multiple equality
- that occurs in a function set a pointer to the multiple equality
- predicate. Substitute a constant instead of this field if the
- multiple equality contains a constant.
- */
- conds= build_equal_items(conds, NULL, join_list, &cond_equal);
-
- conds= optimize_cond(this, conds,&cond_value);
+ conds= optimize_cond(this, conds, join_list, &cond_value);
if (thd->net.report_error)
{
error= 1;
@@ -684,6 +672,7 @@ JOIN::optimize()
{
conds= substitute_for_best_equal_field(conds, cond_equal, map2table);
conds->update_used_tables();
+ DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal"););
}
/*
Permorm the the optimization on fields evaluation mentioned above
@@ -1723,11 +1712,10 @@ int
Cursor::open(JOIN *join_arg)
{
join= join_arg;
-
THD *thd= join->thd;
-
/* First non-constant table */
JOIN_TAB *join_tab= join->join_tab + join->const_tables;
+ DBUG_ENTER("Cursor::open");
/*
Send fields description to the client; server_status is sent
@@ -1749,7 +1737,9 @@ Cursor::open(JOIN *join_arg)
join->fetch_limit= join->unit->offset_limit_cnt;
/* Disable JOIN CACHE as it is not working with cursors yet */
- for (JOIN_TAB *tab= join_tab; tab != join->join_tab + join->tables - 1; ++tab)
+ for (JOIN_TAB *tab= join_tab;
+ tab != join->join_tab + join->tables - 1;
+ tab++)
{
if (tab->next_select == sub_select_cache)
tab->next_select= sub_select;
@@ -1763,7 +1753,7 @@ Cursor::open(JOIN *join_arg)
*/
DBUG_ASSERT(join_tab->table->null_row == 0);
- return join_tab->read_first_record(join_tab);
+ DBUG_RETURN(join_tab->read_first_record(join_tab));
}
@@ -6028,7 +6018,7 @@ template class List_iterator<Item_func_match>;
find_item_equal()
cond_equal multiple equalities to search in
field field to look for
- inherited_fl :out set up to TRUE iff multiple equality is found
+ inherited_fl :out set up to TRUE if multiple equality is found
on upper levels (not on current level of cond_equal)
DESCRIPTION
@@ -6446,12 +6436,14 @@ static COND *build_equal_items_for_cond(COND *cond,
return cond;
}
+
/*
Build multiple equalities for a condition and all on expressions that
inherit these multiple equalities
SYNOPSIS
build_equal_items()
+ thd Thread handler
cond condition to build the multiple equalities for
inherited path to all inherited multiple equality items
join_list list of join tables to which the condition refers to
@@ -6503,7 +6495,7 @@ static COND *build_equal_items_for_cond(COND *cond,
pointer to the transformed condition containing multiple equalities
*/
-static COND *build_equal_items(COND *cond,
+static COND *build_equal_items(THD *thd, COND *cond,
COND_EQUAL *inherited,
List<TABLE_LIST> *join_list,
COND_EQUAL **cond_equal_ref)
@@ -6540,12 +6532,13 @@ static COND *build_equal_items(COND *cond,
{
if (table->on_expr)
{
+ Item *expr;
List<TABLE_LIST> *join_list= table->nested_join ?
&table->nested_join->join_list : NULL;
- table->on_expr= build_equal_items(table->on_expr,
- inherited,
- join_list,
- &table->cond_equal);
+ expr= build_equal_items(thd, table->on_expr, inherited, join_list,
+ &table->cond_equal);
+ if (expr != table->on_expr)
+ thd->change_item_tree(&table->on_expr, expr);
}
}
}
@@ -6553,6 +6546,7 @@ static COND *build_equal_items(COND *cond,
return cond;
}
+
/*
Compare field items by table order in the execution plan
@@ -6797,6 +6791,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
return cond;
}
+
/*
change field = field to field = const for each found field = const in the
and_level
@@ -7089,6 +7084,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
*/
if (table->on_expr)
{
+ Item *expr;
/*
If an on expression E is attached to the table,
check all null rejected predicates in this expression.
@@ -7097,8 +7093,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
the outer join is converted to an inner join and
the corresponding on expression is added to E.
*/
- table->on_expr= simplify_joins(join, &nested_join->join_list,
- table->on_expr, FALSE);
+ expr= simplify_joins(join, &nested_join->join_list,
+ table->on_expr, FALSE);
+ table->on_expr= expr;
}
nested_join->used_tables= (table_map) 0;
nested_join->not_null_tables=(table_map) 0;
@@ -7207,8 +7204,10 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
DBUG_RETURN(conds);
}
+
static COND *
-optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
+optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
+ Item::cond_result *cond_value)
{
THD *thd= join->thd;
SELECT_LEX *select= thd->lex->current_select;
@@ -7221,7 +7220,19 @@ optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
}
else
{
+ /*
+ Build all multiple equality predicates and eliminate equality
+ predicates that can be inferred from these multiple equalities.
+ For each reference of a field included into a multiple equality
+ that occurs in a function set a pointer to the multiple equality
+ predicate. Substitute a constant instead of this field if the
+ multiple equality contains a constant.
+ */
DBUG_EXECUTE("where", print_where(conds, "original"););
+ conds= build_equal_items(join->thd, conds, NULL, join_list,
+ &join->cond_equal);
+ DBUG_EXECUTE("where",print_where(conds,"after equal_items"););
+
/* change field = field to field = const for each found field = const */
propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
/*
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c359c0f5f54..d9626c760be 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1395,18 +1395,20 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
open_table().
TODO: create and open should be done atomic !
*/
- tmp_disable_binlog(thd);
- if (!mysql_create_table(thd, create_table->db, create_table->real_name,
- create_info, *extra_fields, *keys, 0,
- select_field_count))
{
- if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0)))
- quick_rm_table(create_info->db_type, create_table->db,
- table_case_name(create_info, create_table->real_name));
+ tmp_disable_binlog(thd);
+ if (!mysql_create_table(thd, create_table->db, create_table->real_name,
+ create_info, *extra_fields, *keys, 0,
+ select_field_count))
+ {
+ if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0)))
+ quick_rm_table(create_info->db_type, create_table->db,
+ table_case_name(create_info, create_table->real_name));
+ }
+ reenable_binlog(thd);
+ if (!table) // open failed
+ DBUG_RETURN(0);
}
- reenable_binlog(thd);
- if (!table) // open failed
- DBUG_RETURN(0);
table->reginfo.lock_type=TL_WRITE;
if (!((*lock)= mysql_lock_tables(thd, &table,1)))
@@ -3033,13 +3035,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->data_file_name=create_info->index_file_name=0;
/* We don't log the statement, it will be logged later. */
- tmp_disable_binlog(thd);
- error= mysql_create_table(thd, new_db, tmp_name,
- create_info,create_list,key_list,1,0);
- reenable_binlog(thd);
- if (error)
- DBUG_RETURN(error);
-
+ {
+ tmp_disable_binlog(thd);
+ error= mysql_create_table(thd, new_db, tmp_name,
+ create_info,create_list,key_list,1,0);
+ reenable_binlog(thd);
+ if (error)
+ DBUG_RETURN(error);
+ }
if (table->tmp_table)
{
TABLE_LIST tbl;
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index add4078ce8e..17f3bc48678 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -16,9 +16,9 @@ static const char * const triggers_file_ext= ".TRG";
*/
static File_option triggers_file_parameters[]=
{
- {{(char*)"triggers", 8}, offsetof(Table_triggers_list, definitions_list),
+ {{(char*)"triggers", 8}, offsetof(class Table_triggers_list, definitions_list),
FILE_OPTIONS_STRLIST},
- {{NULL, 0}, 0, FILE_OPTIONS_STRING}
+ {{0, 0}, 0, FILE_OPTIONS_STRING}
};
@@ -373,8 +373,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
while ((trg_create_str= it++))
{
- mysql_init_query(thd, (uchar*)trg_create_str->str,
- trg_create_str->length, true);
+ lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
lex.trg_table= table;
if (yyparse((void *)thd) || thd->is_fatal_error)
{
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 4d64455ab53..5e91e730079 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -80,8 +80,7 @@ static bool check_fields(THD *thd, List<Item> &items)
we make temporary copy of Item_field, to avoid influence of changing
result_field on Item_ref which refer on this field
*/
- it.replace(new Item_field(thd, field));
- field->register_item_tree_changing(it.ref());
+ thd->change_item_tree(it.ref(), new Item_field(thd, field));
}
return FALSE;
}
@@ -650,7 +649,7 @@ int mysql_multi_update_prepare(THD *thd)
// Only set timestamp column if this is not modified
if (table->timestamp_field &&
table->timestamp_field->query_id == thd->query_id)
- table->timestamp_on_update_now= 0;
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
if (!tl->updatable || check_key_in_view(thd, tl))
readonly_tables|= table->map;
@@ -689,6 +688,8 @@ int mysql_multi_update(THD *thd,
multi_update *result;
DBUG_ENTER("mysql_multi_update");
+ /* QQ: This should be fixed soon to get lower granularity locks */
+ select_lex->set_lock_for_tables(thd->lex->multi_lock_option);
if ((res= open_and_lock_tables(thd, table_list)))
DBUG_RETURN(res);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 4cdbfe9728b..f8994148ffc 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -28,7 +28,8 @@ const char *updatable_views_with_limit_names[]= { "NO", "YES", NullS };
TYPELIB updatable_views_with_limit_typelib=
{
array_elements(updatable_views_with_limit_names)-1, "",
- updatable_views_with_limit_names
+ updatable_views_with_limit_names,
+ 0
};
@@ -347,7 +348,7 @@ static File_option view_parameters[]=
FILE_OPTIONS_ULONGLONG},
{{(char*) "algorithm", 9}, offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_ULONGLONG},
- {{"with_check_option", 17}, offsetof(TABLE_LIST, with_check),
+ {{(char*) "with_check_option", 17}, offsetof(TABLE_LIST, with_check),
FILE_OPTIONS_ULONGLONG},
{{(char*) "revision", 8}, offsetof(TABLE_LIST, revision),
FILE_OPTIONS_REV},
@@ -357,7 +358,7 @@ static File_option view_parameters[]=
FILE_OPTIONS_ULONGLONG},
{{(char*) "source", 6}, offsetof(TABLE_LIST, source),
FILE_OPTIONS_ESTRING},
- {{NULL, 0}, 0,
+ {{NullS, 0}, 0,
FILE_OPTIONS_STRING}
};
@@ -586,7 +587,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
now Lex placed in statement memory
*/
table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local;
- mysql_init_query(thd, (uchar*)table->query.str, table->query.length, TRUE);
+ lex_start(thd, (uchar*)table->query.str, table->query.length);
lex->select_lex.select_number= ++thd->select_number;
old_lex->derived_tables|= DERIVED_VIEW;
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index bdda1f6fa07..c4ec8c84091 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -425,6 +425,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RETURN_SYM
%token RETURNS_SYM
%token UDF_SONAME_SYM
+%token UDF_RETURNS_SYM
%token FUNCTION_SYM
%token UNCOMMITTED_SYM
%token UNDEFINED_SYM
@@ -5730,7 +5731,6 @@ opt_insert_update:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- lex->duplicates= DUP_UPDATE;
}
KEY_SYM UPDATE_SYM update_list
;
@@ -6859,6 +6859,7 @@ keyword:
| EXPANSION_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
+ | FOUND_SYM {}
| DISABLE_SYM {}
| ENABLE_SYM {}
| FULL {}