Commit e96fcbcf authored by unknown's avatar unknown

Fixed multi-table-delete

Optimize fixed length MyISAM rows to use pread/pwrite.


BUILD/compile-pentium-debug-max:
  Also build embedded server
libmysqld/lib_vio.c:
  Add vio_poll_read()
myisam/mi_statrec.c:
  Use pread()/pwrite() instead of seek+read/write
mysql-test/r/multi_update.result:
  Fix multi-table-delete test
mysql-test/t/multi_update.test:
  Fix multi-table-delete test
sql/filesort.cc:
  Fix multi-table-delete
sql/mysql_priv.h:
  Fix multi-table-delete
sql/sql_class.h:
  Fix multi-table-delete
sql/sql_delete.cc:
  Fix multi-table-delete
sql/sql_parse.cc:
  Fix multi-table-delete
sql/sql_select.cc:
  Fix multi-table-delete
sql/sql_table.cc:
  cleanup
sql/sql_unions.cc:
  cleanup
sql/sql_yacc.yy:
  cleanup/ optimize
sql/structs.h:
  Fix multi-table-delete
sql/uniques.cc:
  Fix multi-table-delete
parent 8d6348f6
...@@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings" ...@@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings" cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs" extra_configs="$pentium_configs $debug_configs"
extra_configs="$extra_configs --with-berkeley-db --with-innodb" extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server"
. "$path/FINISH.sh" . "$path/FINISH.sh"
...@@ -233,4 +233,9 @@ void vio_in_addr(Vio *vio, struct in_addr *in) ...@@ -233,4 +233,9 @@ void vio_in_addr(Vio *vio, struct in_addr *in)
{ {
} }
my_bool vio_poll_read(Vio *vio,uint timeout)
{
return 0;
}
#endif /* HAVE_VIO */ #endif /* HAVE_VIO */
...@@ -27,16 +27,15 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) ...@@ -27,16 +27,15 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
{ {
my_off_t filepos=info->s->state.dellink; my_off_t filepos=info->s->state.dellink;
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,info->s->state.dellink+1,MY_SEEK_SET,MYF(0))); if (my_pread(info->dfile,(char*) &temp[0],info->s->base.rec_reflength,
info->s->state.dellink+1,
if (my_read(info->dfile,(char*) &temp[0],info->s->base.rec_reflength,
MYF(MY_NABP))) MYF(MY_NABP)))
goto err; goto err;
info->s->state.dellink= _mi_rec_pos(info->s,temp); info->s->state.dellink= _mi_rec_pos(info->s,temp);
info->state->del--; info->state->del--;
info->state->empty-=info->s->base.pack_reclength; info->state->empty-=info->s->base.pack_reclength;
VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); if (my_pwrite(info->dfile, (char*) record, info->s->base.reclength,
if (my_write(info->dfile, (char*) record, info->s->base.reclength, filepos,
MYF(MY_NABP))) MYF(MY_NABP)))
goto err; goto err;
} }
...@@ -64,16 +63,18 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) ...@@ -64,16 +63,18 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
else else
{ {
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,info->state->data_file_length, if (my_pwrite(info->dfile,(char*) record,info->s->base.reclength,
MY_SEEK_SET,MYF(0))); info->state->data_file_length,
if (my_write(info->dfile,(char*) record,info->s->base.reclength,
info->s->write_flag)) info->s->write_flag))
goto err; goto err;
if (info->s->base.pack_reclength != info->s->base.reclength) if (info->s->base.pack_reclength != info->s->base.reclength)
{ {
uint length=info->s->base.pack_reclength - info->s->base.reclength; uint length=info->s->base.pack_reclength - info->s->base.reclength;
bzero((char*) temp,length); bzero((char*) temp,length);
if (my_write(info->dfile, (byte*) temp,length, info->s->write_flag)) if (my_pwrite(info->dfile, (byte*) temp,length,
info->state->data_file_length+
info->s->base.pack_reclength,
info->s->write_flag))
goto err; goto err;
} }
} }
...@@ -88,8 +89,9 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) ...@@ -88,8 +89,9 @@ int _mi_write_static_record(MI_INFO *info, const byte *record)
int _mi_update_static_record(MI_INFO *info, my_off_t pos, const byte *record) int _mi_update_static_record(MI_INFO *info, my_off_t pos, const byte *record)
{ {
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0))); return (my_pwrite(info->dfile,
return (my_write(info->dfile,(char*) record,info->s->base.reclength, (char*) record,info->s->base.reclength,
pos,
MYF(MY_NABP)) != 0); MYF(MY_NABP)) != 0);
} }
...@@ -104,9 +106,8 @@ int _mi_delete_static_record(MI_INFO *info) ...@@ -104,9 +106,8 @@ int _mi_delete_static_record(MI_INFO *info)
_mi_dpointer(info,temp+1,info->s->state.dellink); _mi_dpointer(info,temp+1,info->s->state.dellink);
info->s->state.dellink = info->lastpos; info->s->state.dellink = info->lastpos;
info->rec_cache.seek_not_done=1; info->rec_cache.seek_not_done=1;
VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0))); return (my_pwrite(info->dfile,(byte*) temp, 1+info->s->rec_reflength,
return (my_write(info->dfile,(byte*) temp, 1+info->s->rec_reflength, info->lastpos, MYF(MY_NABP)) != 0);
MYF(MY_NABP)) != 0);
} }
...@@ -129,8 +130,8 @@ int _mi_cmp_static_record(register MI_INFO *info, register const byte *old) ...@@ -129,8 +130,8 @@ int _mi_cmp_static_record(register MI_INFO *info, register const byte *old)
if ((info->opt_flag & READ_CHECK_USED)) if ((info->opt_flag & READ_CHECK_USED))
{ /* If check isn't disabled */ { /* If check isn't disabled */
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0))); if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength, info->lastpos,
MYF(MY_NABP))) MYF(MY_NABP)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (memcmp((byte*) info->rec_buff, (byte*) old, if (memcmp((byte*) info->rec_buff, (byte*) old,
...@@ -152,9 +153,8 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def, ...@@ -152,9 +153,8 @@ int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
DBUG_ENTER("_mi_cmp_static_unique"); DBUG_ENTER("_mi_cmp_static_unique");
info->rec_cache.seek_not_done=1; /* We have done a seek */ info->rec_cache.seek_not_done=1; /* We have done a seek */
VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0))); if (my_pread(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength, pos, MYF(MY_NABP)))
MYF(MY_NABP)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff, DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff,
def->null_are_equal)); def->null_are_equal));
......
id1 t id1 t
1 3 1 3
2 2 2 2
3 1
id2 t id2 t
3 3
3 2
3 1
2 3
2 2
2 1
1 3 1 3
1 2 1 2
1 1 1 1
id3 t id3 t
3 3
3 2
3 1
2 3 2 3
2 2 2 2
2 1 2 1
......
...@@ -16,10 +16,11 @@ while ($1) ...@@ -16,10 +16,11 @@ while ($1)
dec $1; dec $1;
} }
delete t1.*,t2.* from t1,t2 where t1.id1 = t2.id2 and t1.id1 = 3;
delete t3 from t3 left join t1 on (id1=id3) where t1.id1 is null;
delete t2 from t1,t2,t3 where id1=id2 and id2=id3 and id1=2;
select * from t1; select * from t1;
select * from t2; select * from t2;
select * from t3; select * from t3;
delete t1,t2 from t1,t2 where 1;
delete from t1,t2 where t1.id = t2.id and t1.id = 3; drop table t1,t2,t3;
select * from t1;
select * from t2;
...@@ -724,6 +724,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -724,6 +724,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
{ {
error=1; goto err; /* purecov: inspected */ error=1; goto err; /* purecov: inspected */
} }
buffpek->key+=sort_length;
queue_replaced(&queue); // Top element has been used
} }
else else
cmp=0; // Not unique cmp=0; // Not unique
......
...@@ -147,7 +147,7 @@ void kill_one_thread(THD *thd, ulong id); ...@@ -147,7 +147,7 @@ void kill_one_thread(THD *thd, ulong id);
#define SELECT_BIG_RESULT 16 #define SELECT_BIG_RESULT 16
#define OPTION_FOUND_ROWS 32 #define OPTION_FOUND_ROWS 32
#define SELECT_HIGH_PRIORITY 64 /* Intern */ #define SELECT_HIGH_PRIORITY 64 /* Intern */
#define SELECT_USE_CACHE 256 /* Intern */ #define SELECT_NO_JOIN_CACHE 256 /* Intern */
#define OPTION_BIG_TABLES 512 /* for SQL OPTION */ #define OPTION_BIG_TABLES 512 /* for SQL OPTION */
#define OPTION_BIG_SELECTS 1024 /* for SQL OPTION */ #define OPTION_BIG_SELECTS 1024 /* for SQL OPTION */
......
...@@ -600,7 +600,6 @@ public: ...@@ -600,7 +600,6 @@ public:
#else #else
Unique **tempfiles; Unique **tempfiles;
#endif #endif
byte * dup_checking;
THD *thd; THD *thd;
ha_rows deleted; ha_rows deleted;
uint num_of_tables; uint num_of_tables;
...@@ -608,12 +607,8 @@ public: ...@@ -608,12 +607,8 @@ public:
thr_lock_type lock_option; thr_lock_type lock_option;
bool do_delete; bool do_delete;
public: public:
multi_delete(TABLE_LIST *dt, thr_lock_type lock_option_arg, uint n) multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
: delete_tables (dt), deleted(0), num_of_tables(n), error(0), uint num_of_tables);
lock_option(lock_option_arg)
{
thd = current_thd; do_delete = false;
}
~multi_delete(); ~multi_delete();
int prepare(List<Item> &list); int prepare(List<Item> &list);
bool send_fields(List<Item> &list, bool send_fields(List<Item> &list,
......
...@@ -286,112 +286,157 @@ int mysql_delete(THD *thd, ...@@ -286,112 +286,157 @@ int mysql_delete(THD *thd,
} }
/*************************************************************************** /***************************************************************************
** delete multiple tables from join ** delete multiple tables from join
***************************************************************************/ ***************************************************************************/
#ifndef DBUG_OFF
#define MEM_STRIP_BUF_SIZE 2048 #define MEM_STRIP_BUF_SIZE 2048
#else
#define MEM_STRIP_BUF_SIZE sortbuffer_size
#endif
#ifndef SINISAS_STRIP #ifndef SINISAS_STRIP
int refposcmp2(void* arg, const void *a,const void *b) int refposcmp2(void* arg, const void *a,const void *b)
{ {
return memcmp(a,b,(int)arg); return memcmp(a,b,(int) arg);
} }
#endif #endif
int multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
multi_delete::prepare(List<Item> &values) thr_lock_type lock_option_arg,
uint num_of_tables_arg)
: delete_tables (dt), thd(thd_arg), deleted(0),
num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
do_delete(false)
{ {
DBUG_ENTER("multi_delete::prepare"); uint counter=0;
uint counter = 0;
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
tempfiles = (IO_CACHE **) sql_calloc(sizeof(IO_CACHE *)*(num_of_tables)); tempfiles = (IO_CACHE **) sql_calloc(sizeof(IO_CACHE *)* num_of_tables);
memory_lane = (byte *)sql_alloc(MAX_REFLENGTH*MEM_STRIP_BUF_SIZE); memory_lane = (byte *)sql_alloc(MAX_REFLENGTH*MEM_STRIP_BUF_SIZE);
#else #else
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables)); tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
#endif #endif
do_delete = true;
dup_checking = (byte *) sql_calloc(MAX_REFLENGTH * (num_of_tables + 1)); (void) dt->table->file->extra(HA_EXTRA_NO_READCHECK);
memset(dup_checking,'\xFF', MAX_REFLENGTH * (num_of_tables + 1)); /* Don't use key read with MULTI-TABLE-DELETE */
for (table_being_deleted=delete_tables; table_being_deleted; table_being_deleted=table_being_deleted->next, counter++) dt->table->used_keys=0;
{ for (dt=dt->next ; dt ; dt=dt->next,counter++)
TABLE *table=table_being_deleted->table;
if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
{ {
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0)); TABLE *table=dt->table;
DBUG_RETURN(1);
}
(void) table->file->extra(HA_EXTRA_NO_READCHECK); (void) table->file->extra(HA_EXTRA_NO_READCHECK);
if (counter < num_of_tables)
{
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
tempfiles[counter]=(IO_CACHE *)sql_alloc(sizeof(IO_CACHE)); tempfiles[counter]=(IO_CACHE *) sql_alloc(sizeof(IO_CACHE));
if (open_cached_file(tempfiles[counter], mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME))) if (open_cached_file(tempfiles[counter], mysql_tmpdir,TEMP_PREFIX,
DISK_BUFFER_SIZE, MYF(MY_WME)))
{ {
my_error(ER_CANT_OPEN_FILE,MYF(0),(tempfiles[counter])->file_name,errno); my_error(ER_CANT_OPEN_FILE,MYF(0),(tempfiles[counter])->file_name,errno);
DBUG_RETURN(1); thd->fatal_error=1;
return;
} }
#else #else
tempfiles[counter] = new Unique (refposcmp2,(void *)table->file->ref_length,table->file->ref_length,MEM_STRIP_BUF_SIZE); tempfiles[counter] = new Unique (refposcmp2,
(void *) table->file->ref_length,
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
#endif #endif
} }
}
int
multi_delete::prepare(List<Item> &values)
{
DBUG_ENTER("multi_delete::prepare");
do_delete = true;
thd->proc_info="deleting from main table";
if (thd->options & OPTION_SAFE_UPDATES)
{
TABLE_LIST *table_ref;
for (table_ref=delete_tables; table_ref; table_ref=table_ref->next)
{
TABLE *table=table_ref->table;
if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
{
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
DBUG_RETURN(1);
}
}
} }
thd->proc_info="updating";
DBUG_RETURN(0); DBUG_RETURN(0);
} }
multi_delete::~multi_delete() multi_delete::~multi_delete()
{ {
for (uint counter = 0; counter < num_of_tables; counter++)
/* Add back EXTRA_READCHECK; In 4.0.1 we shouldn't need this anymore */
for (table_being_deleted=delete_tables ;
table_being_deleted ;
table_being_deleted=table_being_deleted->next)
{
VOID(table_being_deleted->table->file->extra(HA_EXTRA_READCHECK));
}
for (uint counter = 0; counter < num_of_tables-1; counter++)
{
if (tempfiles[counter]) if (tempfiles[counter])
{
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
// end_io_cache(tempfiles[counter]); // end_io_cache(tempfiles[counter]);
#else #else
delete tempfiles[counter]; delete tempfiles[counter];
#endif #endif
// Here it crashes ... }
}
} }
bool multi_delete::send_data(List<Item> &values) bool multi_delete::send_data(List<Item> &values)
{ {
int secure_counter = -1; int secure_counter= -1;
for (table_being_deleted=delete_tables ; table_being_deleted ; table_being_deleted=table_being_deleted->next, secure_counter++) for (table_being_deleted=delete_tables ;
table_being_deleted ;
table_being_deleted=table_being_deleted->next, secure_counter++)
{ {
TABLE *table=table_being_deleted->table; TABLE *table=table_being_deleted->table;
table->file->position(table->record[0]); int rl = table->file->ref_length;
byte *dup_check = dup_checking + (secure_counter + 1)*MAX_REFLENGTH; /* Check if we are using outer join and we didn't find the row */
if (!table->null_row && memcmp(dup_check,table->file->ref, rl)) if (table->status & (STATUS_NULL_ROW | STATUS_DELETED))
{ continue;
memcpy(dup_check,table->file->ref,rl);
if (secure_counter == -1) table->file->position(table->record[0]);
int rl = table->file->ref_length;
if (secure_counter < 0)
{ {
table->status|= STATUS_DELETED;
if (!(error=table->file->delete_row(table->record[0]))) if (!(error=table->file->delete_row(table->record[0])))
deleted++; deleted++;
else else
{ {
send_error(error,"An error occured in deleting rows"); table->file->print_error(error,MYF(0));
return 1; return 1;
} }
} }
else else
{ {
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
if (my_b_write(tempfiles[secure_counter],table->file->ref,rl)) error=my_b_write(tempfiles[secure_counter],table->file->ref,rl);
#else #else
if (tempfiles[secure_counter]->unique_add(table->file->ref)) error=tempfiles[secure_counter]->unique_add(table->file->ref);
#endif #endif
if (error)
{ {
error=-1; error=-1;
return 1; return 1;
} }
} }
} }
}
return 0; return 0;
} }
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
static inline int COMP (byte *ml,uint len,unsigned int left, unsigned int right) static inline int COMP (byte *ml,uint len,unsigned int left, unsigned int right)
{ {
...@@ -712,14 +757,15 @@ static IO_CACHE *strip_duplicates_from_temp (byte *memory_lane, IO_CACHE *ptr, u ...@@ -712,14 +757,15 @@ static IO_CACHE *strip_duplicates_from_temp (byte *memory_lane, IO_CACHE *ptr, u
} }
} }
#endif #endif /* SINISAS_STRIP */
/* Return true if some table is not transaction safe */
static bool some_table_is_not_transaction_safe (TABLE_LIST *tl) static bool some_table_is_not_transaction_safe (TABLE_LIST *tl)
{ {
TABLE_LIST *deleting = tl; for (; tl ; tl=tl->next)
for (deleting=deleting->next; deleting ; deleting=deleting->next)
{ {
if (!(deleting->table->file->has_transactions())) if (!(tl->table->file->has_transactions()))
return true; return true;
} }
return false; return false;
...@@ -728,35 +774,52 @@ static bool some_table_is_not_transaction_safe (TABLE_LIST *tl) ...@@ -728,35 +774,52 @@ static bool some_table_is_not_transaction_safe (TABLE_LIST *tl)
void multi_delete::send_error(uint errcode,const char *err) void multi_delete::send_error(uint errcode,const char *err)
{ {
// First send error what ever it is ... /* First send error what ever it is ... */
::send_error(&thd->net,errcode,err); ::send_error(&thd->net,errcode,err);
// If nothing deleted return /* If nothing deleted return */
if (!deleted) return; if (!deleted)
// Below can happen when thread is killed ... return;
if (!table_being_deleted) table_being_deleted=delete_tables; /* Below can happen when thread is killed early ... */
// If rows from the first table only has been deleted and it is transactional, just do rollback if (!table_being_deleted)
// The same if all tables are transactional, regardless of where we are. In all other cases do attempt deletes ... table_being_deleted=delete_tables;
if ((table_being_deleted->table->file->has_transactions() && table_being_deleted == delete_tables) || !some_table_is_not_transaction_safe(delete_tables))
ha_rollback(current_thd); /*
If rows from the first table only has been deleted and it is transactional,
just do rollback.
The same if all tables are transactional, regardless of where we are.
In all other cases do attempt deletes ...
*/
if ((table_being_deleted->table->file->has_transactions() &&
table_being_deleted == delete_tables) ||
!some_table_is_not_transaction_safe(delete_tables->next))
ha_rollback(thd);
else if (do_delete) else if (do_delete)
VOID(do_deletes(true)); VOID(do_deletes(true));
} }
int multi_delete::do_deletes (bool from_send_error) int multi_delete::do_deletes (bool from_send_error)
{ {
TABLE *table;
int error = 0, counter = 0, count; int error = 0, counter = 0, count;
if (from_send_error) if (from_send_error)
{ {
for (TABLE_LIST *aux=delete_tables; aux != table_being_deleted; aux=aux->next) /* Found out table number for 'table_being_deleted' */
for (TABLE_LIST *aux=delete_tables;
aux != table_being_deleted;
aux=aux->next)
counter++; counter++;
} }
else else
table_being_deleted = delete_tables; table_being_deleted = delete_tables;
do_delete = false; do_delete = false;
for (table_being_deleted=table_being_deleted->next; table_being_deleted ; counter++, table_being_deleted=table_being_deleted->next) for (table_being_deleted=table_being_deleted->next;
table_being_deleted ;
table_being_deleted=table_being_deleted->next, counter++)
{ {
table = table_being_deleted->table; int rl = table->file->ref_length; TABLE *table = table_being_deleted->table;
int rl = table->file->ref_length;
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
int num_of_positions = (int)my_b_tell(tempfiles[counter])/rl; int num_of_positions = (int)my_b_tell(tempfiles[counter])/rl;
if (!num_of_positions) continue; if (!num_of_positions) continue;
...@@ -766,11 +829,20 @@ int multi_delete::do_deletes (bool from_send_error) ...@@ -766,11 +829,20 @@ int multi_delete::do_deletes (bool from_send_error)
error=1; break; error=1; break;
} }
#else #else
tempfiles[counter]->get(table); if (tempfiles[counter]->get(table))
{
error=1;
break;
}
#endif #endif
#if 0
if (num_of_positions == table->file->records) // nice little optimization .... #if USE_REGENERATE_TABLE
{ // but Monty has to fix generate_table... // nice little optimization ....
// but Monty has to fix generate_table...
// This will not work for transactional tables because for other types
// records is not absolute
if (num_of_positions == table->file->records)
{
TABLE_LIST table_list; TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list)); bzero((char*) &table_list,sizeof(table_list));
table_list.name=table->table_name; table_list.real_name=table_being_deleted->real_name; table_list.name=table->table_name; table_list.real_name=table_being_deleted->real_name;
...@@ -780,11 +852,12 @@ int multi_delete::do_deletes (bool from_send_error) ...@@ -780,11 +852,12 @@ int multi_delete::do_deletes (bool from_send_error)
error=generate_table(thd,&table_list,(TABLE *)0); error=generate_table(thd,&table_list,(TABLE *)0);
if (error <= 0) {error = 1; break;} if (error <= 0) {error = 1; break;}
deleted += num_of_positions; deleted += num_of_positions;
continue;
} }
else #endif /* USE_REGENERATE_TABLE */
{
#endif READ_RECORD info;
READ_RECORD info; error=0; error=0;
#ifdef SINISAS_STRIP #ifdef SINISAS_STRIP
SQL_SELECT *select= new SQL_SELECT; SQL_SELECT *select= new SQL_SELECT;
select->head=table; select->head=table;
...@@ -794,7 +867,8 @@ int multi_delete::do_deletes (bool from_send_error) ...@@ -794,7 +867,8 @@ int multi_delete::do_deletes (bool from_send_error)
init_read_record(&info,thd,table,NULL,0,0); init_read_record(&info,thd,table,NULL,0,0);
#endif #endif
bool not_trans_safe = some_table_is_not_transaction_safe(delete_tables); bool not_trans_safe = some_table_is_not_transaction_safe(delete_tables);
while (!(error=info.read_record(&info)) && (!thd->killed || from_send_error || not_trans_safe)) while (!(error=info.read_record(&info)) &&
(!thd->killed || from_send_error || not_trans_safe))
{ {
error=table->file->delete_row(table->record[0]); error=table->file->delete_row(table->record[0]);
if (error) if (error)
...@@ -811,38 +885,33 @@ int multi_delete::do_deletes (bool from_send_error) ...@@ -811,38 +885,33 @@ int multi_delete::do_deletes (bool from_send_error)
#endif #endif
if (error == -1) if (error == -1)
error = 0; error = 0;
#if 0
}
#endif
} }
return error; return error;
} }
bool multi_delete::send_eof() bool multi_delete::send_eof()
{ {
int error = 0; thd->proc_info="deleting from reference tables";
error = do_deletes(false); int error = do_deletes(false);
thd->proc_info="end"; thd->proc_info="end";
if (error && error != -1) if (error && error != -1)
{ {
::send_error(&thd->net); ::send_error(&thd->net);
return 1; return 1;
} }
for (table_being_deleted=delete_tables ; table_being_deleted ; table_being_deleted=table_being_deleted->next)
{ if (deleted &&
TABLE *table=table_being_deleted->table; (error <= 0 || some_table_is_not_transaction_safe(delete_tables)))
if (table)
VOID(table->file->extra(HA_EXTRA_READCHECK));
}
if (deleted && (error <= 0 || some_table_is_not_transaction_safe(delete_tables)))
{ {
mysql_update_log.write(thd,thd->query,thd->query_length); mysql_update_log.write(thd,thd->query,thd->query_length);
Query_log_event qinfo(thd, thd->query); Query_log_event qinfo(thd, thd->query);
if (mysql_bin_log.write(&qinfo) && !some_table_is_not_transaction_safe(delete_tables)) if (mysql_bin_log.write(&qinfo) &&
error=1; !some_table_is_not_transaction_safe(delete_tables))
error=1; // Rollback
VOID(ha_autocommit_or_rollback(thd,error >= 0)); VOID(ha_autocommit_or_rollback(thd,error >= 0));
} }
::send_ok(&thd->net,deleted); ::send_ok(&thd->net,deleted);
return 0; return 0;
} }
...@@ -1649,97 +1649,98 @@ mysql_execute_command(void) ...@@ -1649,97 +1649,98 @@ mysql_execute_command(void)
if (lex->sql_command == SQLCOM_TRUNCATE && end_active_trans(thd)) if (lex->sql_command == SQLCOM_TRUNCATE && end_active_trans(thd))
res= -1; res= -1;
else else
res = mysql_delete(thd,tables, select_lex->where, (ORDER*)select_lex->order_list.first, res = mysql_delete(thd,tables, select_lex->where,
select_lex->select_limit, lex->lock_option, select_lex->options); (ORDER*) select_lex->order_list.first,
select_lex->select_limit, lex->lock_option,
select_lex->options);
break; break;
} }
case SQLCOM_MULTI_DELETE: case SQLCOM_MULTI_DELETE:
{ {
TABLE_LIST *aux_tables=(TABLE_LIST *)thd->lex.auxilliary_table_list.first; TABLE_LIST *aux_tables=(TABLE_LIST *)thd->lex.auxilliary_table_list.first;
TABLE_LIST *auxi;
uint table_count=0;
multi_delete *result; multi_delete *result;
if (!tables || !aux_tables || /* sql_yacc guarantees that tables and aux_tables are not zero */
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
check_table_access(thd,SELECT_ACL, tables) || check_table_access(thd,SELECT_ACL, tables) ||
check_table_access(thd,DELETE_ACL,aux_tables)) check_table_access(thd,DELETE_ACL, aux_tables))
{
res=-1;
goto error; goto error;
}
if (!tables->db)
tables->db=thd->db;
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{ {
send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
res=1; goto error; goto error;
} }
uint howmuch=0; TABLE_LIST *walk, *auxi; for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next, howmuch++)
{ {
if (!auxi->db) table_count++;
auxi->db=thd->db; /* All tables in aux_tables must be found in FROM PART */
if (!auxi->real_name) TABLE_LIST *walk;
auxi->real_name=auxi->name;
for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next) for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next)
{ {
if (!walk->db) walk->db=thd->db; if (!strcmp(auxi->real_name,walk->real_name) &&
if (!strcmp(auxi->real_name,walk->real_name) && !strcmp(walk->db,auxi->db)) !strcmp(walk->db,auxi->db))
break; break;
} }
if (!walk) if (!walk)
{ {
net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name); net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name);
res=-2; goto error; goto error;
} }
else
{
auxi->lock_type=walk->lock_type=TL_WRITE; auxi->lock_type=walk->lock_type=TL_WRITE;
auxi->table= (TABLE *) walk; auxi->table= (TABLE *) walk; // Remember corresponding table
}
} }
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
if (add_item_to_list(new Item_null())) goto error; if (add_item_to_list(new Item_null()))
thd->proc_info="init";
if (open_and_lock_tables(thd,tables))
{ {
res=-1; goto error; res= -1;
break;
} }
thd->proc_info="init";
if ((res=open_and_lock_tables(thd,tables)))
break;
/* Fix tables-to-be-deleted-from list to point at opened tables */
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next) for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
auxi->table= ((TABLE_LIST*) auxi->table)->table; auxi->table= ((TABLE_LIST*) auxi->table)->table;
if ((result=new multi_delete(aux_tables,lex->lock_option,howmuch))) if ((result=new multi_delete(thd,aux_tables,lex->lock_option,
table_count)) && ! thd->fatal_error)
{ {
res=mysql_select(thd,tables,select_lex->item_list, res=mysql_select(thd,tables,select_lex->item_list,
select_lex->where,select_lex->ftfunc_list, select_lex->where,select_lex->ftfunc_list,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options, select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
result); result);
delete result;
} }
else else
res= -1; res= -1; // Error is not sent
delete result;
close_thread_tables(thd); close_thread_tables(thd);
break; break;
} }
case SQLCOM_UNION_SELECT: case SQLCOM_UNION_SELECT:
{ {
uint total_selects = select_lex->select_number; total_selects++;
SQL_LIST *total=(SQL_LIST *) thd->calloc(sizeof(SQL_LIST)); SQL_LIST *total=(SQL_LIST *) thd->calloc(sizeof(SQL_LIST));
if (select_lex->options & SELECT_DESCRIBE) if (select_lex->options & SELECT_DESCRIBE)
lex->exchange=0; lex->exchange=0;
res = link_in_large_list_and_check_acl(thd,lex,total); if ((res = link_in_large_list_and_check_acl(thd,lex,total)) == -1)
if (res == -1)
{ {
res=0; res=0;
break; break;
} }
if (res && (res=check_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, any_db))) if (res &&
(res=check_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
any_db)))
{ {
res=0; res=0;
break; break;
} }
if (!(res=open_and_lock_tables(thd,(TABLE_LIST *)total->first))) if (!(res=open_and_lock_tables(thd,(TABLE_LIST *)total->first)))
{ {
res=mysql_union(thd,lex,total_selects); res=mysql_union(thd,lex, select_lex->select_number+1);
if (res==-1) res=0; if (res==-1) res=0;
} }
break; break;
......
...@@ -484,8 +484,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -484,8 +484,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
(group && order) || (group && order) ||
test(select_options & OPTION_BUFFER_RESULT))); test(select_options & OPTION_BUFFER_RESULT)));
make_join_readinfo(&join, (select_options & SELECT_DESCRIBE) | // No cache for MATCH
(ftfuncs.elements ? 0 : SELECT_USE_CACHE)); // No cache for MATCH make_join_readinfo(&join,
(select_options & (SELECT_DESCRIBE |
SELECT_NO_JOIN_CACHE)) |
(ftfuncs.elements ? SELECT_NO_JOIN_CACHE : 0));
/* Need to tell Innobase that to play it safe, it should fetch all /* Need to tell Innobase that to play it safe, it should fetch all
columns of the tables: this is because MySQL columns of the tables: this is because MySQL
...@@ -2465,7 +2468,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2465,7 +2468,7 @@ make_join_readinfo(JOIN *join,uint options)
** if previous table use cache ** if previous table use cache
*/ */
table->status=STATUS_NO_RECORD; table->status=STATUS_NO_RECORD;
if (i != join->const_tables && (options & SELECT_USE_CACHE) && if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
tab->use_quick != 2 && !tab->on_expr) tab->use_quick != 2 && !tab->on_expr)
{ {
if ((options & SELECT_DESCRIBE) || if ((options & SELECT_DESCRIBE) ||
......
...@@ -59,9 +59,9 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -59,9 +59,9 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
pthread_mutex_unlock(&thd->mysys_var->mutex); pthread_mutex_unlock(&thd->mysys_var->mutex);
if(global_read_lock) if (global_read_lock)
{ {
if(thd->global_read_lock) if (thd->global_read_lock)
{ {
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0), my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
tables->real_name); tables->real_name);
......
...@@ -30,4 +30,5 @@ int mysql_union(THD *thd,LEX *lex,uint no_of_selects) ...@@ -30,4 +30,5 @@ int mysql_union(THD *thd,LEX *lex,uint no_of_selects)
for (sl=&lex->select_lex;sl;sl=sl->next) for (sl=&lex->select_lex;sl;sl=sl->next)
{ {
} }
return 0;
} }
...@@ -543,7 +543,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -543,7 +543,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_mi_check_type opt_to mi_check_types normal_join opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_rkey_mode handler_read_or_scan handler_rkey_function handler_rkey_mode handler_read_or_scan
single_multi table_multi_delete table_sini_wild union union_list single_multi table_wild_list table_wild_one opt_wild union union_list
precision
END_OF_INPUT END_OF_INPUT
%type <NONE> %type <NONE>
...@@ -650,7 +651,6 @@ master_def: ...@@ -650,7 +651,6 @@ master_def:
} }
/* create a table */ /* create a table */
create: create:
...@@ -674,36 +674,41 @@ create: ...@@ -674,36 +674,41 @@ create:
| CREATE opt_unique_or_fulltext INDEX ident ON table_ident | CREATE opt_unique_or_fulltext INDEX ident ON table_ident
{ {
Lex->sql_command= SQLCOM_CREATE_INDEX; LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
if (!add_table_to_list($6,NULL,1)) if (!add_table_to_list($6,NULL,1))
YYABORT; YYABORT;
Lex->create_list.empty(); lex->create_list.empty();
Lex->key_list.empty(); lex->key_list.empty();
Lex->col_list.empty(); lex->col_list.empty();
Lex->change=NullS; lex->change=NullS;
} }
'(' key_list ')' '(' key_list ')'
{ {
Lex->key_list.push_back(new Key($2,$4.str,Lex->col_list)); LEX *lex=Lex;
Lex->col_list.empty(); lex->key_list.push_back(new Key($2,$4.str,lex->col_list));
lex->col_list.empty();
} }
| CREATE DATABASE opt_if_not_exists ident | CREATE DATABASE opt_if_not_exists ident
{ {
Lex->sql_command=SQLCOM_CREATE_DB; LEX *lex=Lex;
Lex->name=$4.str; lex->sql_command=SQLCOM_CREATE_DB;
Lex->create_info.options=$3; lex->name=$4.str;
lex->create_info.options=$3;
} }
| CREATE udf_func_type UDF_SYM ident | CREATE udf_func_type UDF_SYM ident
{ {
Lex->sql_command = SQLCOM_CREATE_FUNCTION; LEX *lex=Lex;
Lex->udf.name=$4.str; lex->sql_command = SQLCOM_CREATE_FUNCTION;
Lex->udf.name_length=$4.length; lex->udf.name=$4.str;
Lex->udf.type= $2; lex->udf.name_length=$4.length;
lex->udf.type= $2;
} }
UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING
{ {
Lex->udf.returns=(Item_result) $7; LEX *lex=Lex;
Lex->udf.dl=$9.str; lex->udf.returns=(Item_result) $7;
lex->udf.dl=$9.str;
} }
create2: create2:
...@@ -714,8 +719,9 @@ create3: ...@@ -714,8 +719,9 @@ create3:
/* empty */ {} /* empty */ {}
| opt_duplicate opt_as SELECT_SYM | opt_duplicate opt_as SELECT_SYM
{ {
Lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; LEX *lex=Lex;
mysql_init_select(Lex); lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
} }
select_options select_item_list opt_select_from {} select_options select_item_list opt_select_from {}
...@@ -823,8 +829,9 @@ field_list_item: ...@@ -823,8 +829,9 @@ field_list_item:
} }
| key_type opt_ident '(' key_list ')' | key_type opt_ident '(' key_list ')'
{ {
Lex->key_list.push_back(new Key($1,$2,Lex->col_list)); LEX *lex=Lex;
Lex->col_list.empty(); /* Alloced by sql_alloc */ lex->key_list.push_back(new Key($1,$2,lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
} }
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
{ {
...@@ -842,16 +849,18 @@ opt_constraint: ...@@ -842,16 +849,18 @@ opt_constraint:
field_spec: field_spec:
field_ident field_ident
{ {
Lex->length=Lex->dec=0; Lex->type=0; Lex->interval=0; LEX *lex=Lex;
Lex->default_value=0; lex->length=lex->dec=0; lex->type=0; lex->interval=0;
lex->default_value=0;
} }
type opt_attribute type opt_attribute
{ {
LEX *lex=Lex;
if (add_field_to_list($1.str, if (add_field_to_list($1.str,
(enum enum_field_types) $3, (enum enum_field_types) $3,
Lex->length,Lex->dec,Lex->type, lex->length,lex->dec,lex->type,
Lex->default_value,Lex->change, lex->default_value,lex->change,
Lex->interval)) lex->interval))
YYABORT; YYABORT;
} }
...@@ -903,12 +912,14 @@ type: ...@@ -903,12 +912,14 @@ type:
{ $$=FIELD_TYPE_DECIMAL;} { $$=FIELD_TYPE_DECIMAL;}
| ENUM {Lex->interval_list.empty();} '(' string_list ')' | ENUM {Lex->interval_list.empty();} '(' string_list ')'
{ {
Lex->interval=typelib(Lex->interval_list); LEX *lex=Lex;
lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_ENUM; $$=FIELD_TYPE_ENUM;
} }
| SET { Lex->interval_list.empty();} '(' string_list ')' | SET { Lex->interval_list.empty();} '(' string_list ')'
{ {
Lex->interval=typelib(Lex->interval_list); LEX *lex=Lex;
lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_SET; $$=FIELD_TYPE_SET;
} }
...@@ -940,7 +951,14 @@ real_type: ...@@ -940,7 +951,14 @@ real_type:
float_options: float_options:
/* empty */ {} /* empty */ {}
| '(' NUM ')' { Lex->length=$2.str; } | '(' NUM ')' { Lex->length=$2.str; }
| '(' NUM ',' NUM ')' { Lex->length=$2.str; Lex->dec=$4.str; } | precision {}
precision:
'(' NUM ',' NUM ')'
{
LEX *lex=Lex;
lex->length=$2.str; lex->dec=$4.str;
}
field_options: field_options:
/* empty */ {} /* empty */ {}
...@@ -960,7 +978,7 @@ opt_len: ...@@ -960,7 +978,7 @@ opt_len:
opt_precision: opt_precision:
/* empty */ {} /* empty */ {}
| '(' NUM ',' NUM ')' { Lex->length=$2.str; Lex->dec=$4.str; } | precision {}
opt_attribute: opt_attribute:
/* empty */ {} /* empty */ {}
...@@ -1088,42 +1106,69 @@ add_column: ...@@ -1088,42 +1106,69 @@ add_column:
alter_list_item: alter_list_item:
add_column field_list_item opt_place { Lex->simple_alter=0; } add_column field_list_item opt_place { Lex->simple_alter=0; }
| add_column '(' field_list ')' { Lex->simple_alter=0; } | add_column '(' field_list ')' { Lex->simple_alter=0; }
| CHANGE opt_column field_ident { Lex->change= $3.str; Lex->simple_alter=0; } | CHANGE opt_column field_ident
{
LEX *lex=Lex;
lex->change= $3.str; lex->simple_alter=0;
}
field_spec field_spec
| MODIFY_SYM opt_column field_ident | MODIFY_SYM opt_column field_ident
{ {
Lex->length=Lex->dec=0; Lex->type=0; Lex->interval=0; LEX *lex=Lex;
Lex->default_value=0; lex->length=lex->dec=0; lex->type=0; lex->interval=0;
Lex->simple_alter=0; lex->default_value=0;
lex->simple_alter=0;
} }
type opt_attribute type opt_attribute
{ {
LEX *lex=Lex;
if (add_field_to_list($3.str, if (add_field_to_list($3.str,
(enum enum_field_types) $5, (enum enum_field_types) $5,
Lex->length,Lex->dec,Lex->type, lex->length,lex->dec,lex->type,
Lex->default_value, $3.str, lex->default_value, $3.str,
Lex->interval)) lex->interval))
YYABORT; YYABORT;
Lex->simple_alter=0; lex->simple_alter=0;
} }
| DROP opt_column field_ident opt_restrict | DROP opt_column field_ident opt_restrict
{ Lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN, {
$3.str)); Lex->simple_alter=0; } LEX *lex=Lex;
| DROP PRIMARY_SYM KEY_SYM { Lex->drop_primary=1; Lex->simple_alter=0; } lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
$3.str)); lex->simple_alter=0;
}
| DROP PRIMARY_SYM KEY_SYM
{
LEX *lex=Lex;
lex->drop_primary=1; lex->simple_alter=0;
}
| DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; } | DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; }
| DROP key_or_index field_ident | DROP key_or_index field_ident
{ Lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, {
$3.str)); Lex->simple_alter=0; } LEX *lex=Lex;
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
lex->simple_alter=0;
}
| DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; } | DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; }
| ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; } | ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; }
| ALTER opt_column field_ident SET DEFAULT literal | ALTER opt_column field_ident SET DEFAULT literal
{ Lex->alter_list.push_back(new Alter_column($3.str,$6)); Lex->simple_alter=0; } {
LEX *lex=Lex;
lex->alter_list.push_back(new Alter_column($3.str,$6));
lex->simple_alter=0;
}
| ALTER opt_column field_ident DROP DEFAULT | ALTER opt_column field_ident DROP DEFAULT
{ Lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0)); Lex->simple_alter=0; } {
LEX *lex=Lex;
lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0));
lex->simple_alter=0;
}
| RENAME opt_to table_alias table_ident | RENAME opt_to table_alias table_ident
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->select->db=$4->db.str ; lex->name= $4->table.str; lex->simple_alter=0; lex->select->db=$4->db.str;
lex->name= $4->table.str;
lex->simple_alter=0;
} }
| create_table_options { Lex->simple_alter=0; } | create_table_options { Lex->simple_alter=0; }
| order_clause { Lex->simple_alter=0; } | order_clause { Lex->simple_alter=0; }
...@@ -1154,14 +1199,16 @@ opt_to: ...@@ -1154,14 +1199,16 @@ opt_to:
slave: slave:
SLAVE START_SYM SLAVE START_SYM
{ {
Lex->sql_command = SQLCOM_SLAVE_START; LEX *lex=Lex;
Lex->type = 0; lex->sql_command = SQLCOM_SLAVE_START;
lex->type = 0;
} }
| |
SLAVE STOP_SYM SLAVE STOP_SYM
{ {
Lex->sql_command = SQLCOM_SLAVE_STOP; LEX *lex=Lex;
Lex->type = 0; lex->sql_command = SQLCOM_SLAVE_STOP;
lex->type = 0;
}; };
restore: restore:
...@@ -1187,8 +1234,9 @@ backup: ...@@ -1187,8 +1234,9 @@ backup:
repair: repair:
REPAIR table_or_tables REPAIR table_or_tables
{ {
Lex->sql_command = SQLCOM_REPAIR; LEX *lex=Lex;
Lex->check_opt.init(); lex->sql_command = SQLCOM_REPAIR;
lex->check_opt.init();
} }
table_list opt_mi_check_type table_list opt_mi_check_type
...@@ -1212,24 +1260,27 @@ mi_check_type: ...@@ -1212,24 +1260,27 @@ mi_check_type:
analyze: analyze:
ANALYZE_SYM table_or_tables ANALYZE_SYM table_or_tables
{ {
Lex->sql_command = SQLCOM_ANALYZE; LEX *lex=Lex;
Lex->check_opt.init(); lex->sql_command = SQLCOM_ANALYZE;
lex->check_opt.init();
} }
table_list opt_mi_check_type table_list opt_mi_check_type
check: check:
CHECK_SYM table_or_tables CHECK_SYM table_or_tables
{ {
Lex->sql_command = SQLCOM_CHECK; LEX *lex=Lex;
Lex->check_opt.init(); lex->sql_command = SQLCOM_CHECK;
lex->check_opt.init();
} }
table_list opt_mi_check_type table_list opt_mi_check_type
optimize: optimize:
OPTIMIZE table_or_tables OPTIMIZE table_or_tables
{ {
Lex->sql_command = SQLCOM_OPTIMIZE; LEX *lex=Lex;
Lex->check_opt.init(); lex->sql_command = SQLCOM_OPTIMIZE;
lex->check_opt.init();
} }
table_list opt_mi_check_type table_list opt_mi_check_type
...@@ -1753,13 +1804,15 @@ when_list: ...@@ -1753,13 +1804,15 @@ when_list:
when_list2: when_list2:
expr THEN_SYM expr expr THEN_SYM expr
{ {
Select->when_list.head()->push_back($1); SELECT_LEX *sel=Select;
Select->when_list.head()->push_back($3); sel->when_list.head()->push_back($1);
sel->when_list.head()->push_back($3);
} }
| when_list2 WHEN_SYM expr THEN_SYM expr | when_list2 WHEN_SYM expr THEN_SYM expr
{ {
Select->when_list.head()->push_back($3); SELECT_LEX *sel=Select;
Select->when_list.head()->push_back($5); sel->when_list.head()->push_back($3);
sel->when_list.head()->push_back($5);
} }
opt_pad: opt_pad:
...@@ -1774,15 +1827,21 @@ join_table_list: ...@@ -1774,15 +1827,21 @@ join_table_list:
| join_table_list INNER_SYM JOIN_SYM join_table ON expr | join_table_list INNER_SYM JOIN_SYM join_table ON expr
{ add_join_on($4,$6); $$=$4; } { add_join_on($4,$6); $$=$4; }
| join_table_list INNER_SYM JOIN_SYM join_table | join_table_list INNER_SYM JOIN_SYM join_table
{ Select->db1=$1->db; Select->table1=$1->name; {
Select->db2=$4->db; Select->table2=$4->name; } SELECT_LEX *sel=Select;
sel->db1=$1->db; sel->table1=$1->name;
sel->db2=$4->db; sel->table2=$4->name;
}
USING '(' using_list ')' USING '(' using_list ')'
{ add_join_on($4,$8); $$=$4; } { add_join_on($4,$8); $$=$4; }
| join_table_list LEFT opt_outer JOIN_SYM join_table ON expr | join_table_list LEFT opt_outer JOIN_SYM join_table ON expr
{ add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list LEFT opt_outer JOIN_SYM join_table | join_table_list LEFT opt_outer JOIN_SYM join_table
{ Select->db1=$1->db; Select->table1=$1->name; {
Select->db2=$5->db; Select->table2=$5->name; } SELECT_LEX *sel=Select;
sel->db1=$1->db; sel->table1=$1->name;
sel->db2=$5->db; sel->table2=$5->name;
}
USING '(' using_list ')' USING '(' using_list ')'
{ add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table
...@@ -1790,8 +1849,11 @@ join_table_list: ...@@ -1790,8 +1849,11 @@ join_table_list:
| join_table_list RIGHT opt_outer JOIN_SYM join_table ON expr | join_table_list RIGHT opt_outer JOIN_SYM join_table ON expr
{ add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
| join_table_list RIGHT opt_outer JOIN_SYM join_table | join_table_list RIGHT opt_outer JOIN_SYM join_table
{ Select->db1=$1->db; Select->table1=$1->name; {
Select->db2=$5->db; Select->table2=$5->name; } SELECT_LEX *sel=Select;
sel->db1=$1->db; sel->table1=$1->name;
sel->db2=$5->db; sel->table2=$5->name;
}
USING '(' using_list ')' USING '(' using_list ')'
{ add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
| join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table
...@@ -1805,10 +1867,16 @@ normal_join: ...@@ -1805,10 +1867,16 @@ normal_join:
| CROSS JOIN_SYM {} | CROSS JOIN_SYM {}
join_table: join_table:
{ Select->use_index_ptr=Select->ignore_index_ptr=0; } {
SELECT_LEX *sel=Select;
sel->use_index_ptr=sel->ignore_index_ptr=0;
}
table_ident opt_table_alias opt_key_definition table_ident opt_table_alias opt_key_definition
{ if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, Select->use_index_ptr, {
Select->ignore_index_ptr))) YYABORT; } SELECT_LEX *sel=Select;
if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr,
sel->ignore_index_ptr))) YYABORT;
}
| '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}' | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}'
{ add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
...@@ -1819,9 +1887,17 @@ opt_outer: ...@@ -1819,9 +1887,17 @@ opt_outer:
opt_key_definition: opt_key_definition:
/* empty */ {} /* empty */ {}
| USE_SYM key_usage_list | USE_SYM key_usage_list
{ Select->use_index= *$2; Select->use_index_ptr= &Select->use_index; } {
SELECT_LEX *sel=Select;
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
}
| IGNORE_SYM key_usage_list | IGNORE_SYM key_usage_list
{ Select->ignore_index= *$2; Select->ignore_index_ptr= &Select->ignore_index;} {
SELECT_LEX *sel=Select;
sel->ignore_index= *$2;
sel->ignore_index_ptr= &sel->ignore_index;
}
key_usage_list: key_usage_list:
key_or_index { Select->interval_list.empty() } '(' key_usage_list2 ')' key_or_index { Select->interval_list.empty() } '(' key_usage_list2 ')'
...@@ -1837,12 +1913,15 @@ key_usage_list2: ...@@ -1837,12 +1913,15 @@ key_usage_list2:
using_list: using_list:
ident ident
{ if (!($$= new Item_func_eq(new Item_field(Select->db1,Select->table1, $1.str), new Item_field(Select->db2,Select->table2,$1.str)))) {
SELECT_LEX *sel=Select;
if (!($$= new Item_func_eq(new Item_field(sel->db1,sel->table1, $1.str), new Item_field(sel->db2,sel->table2,$1.str))))
YYABORT; YYABORT;
} }
| using_list ',' ident | using_list ',' ident
{ {
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(Select->db1,Select->table1,$3.str), new Item_field(Select->db2,Select->table2,$3.str)), $1))) SELECT_LEX *sel=Select;
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
YYABORT; YYABORT;
} }
...@@ -1879,7 +1958,10 @@ where_clause: ...@@ -1879,7 +1958,10 @@ where_clause:
having_clause: having_clause:
/* empty */ /* empty */
| HAVING { Select->create_refs=1; } expr | HAVING { Select->create_refs=1; } expr
{ Select->having= $3; Select->create_refs=0; } {
SELECT_LEX *sel=Select;
sel->having= $3; sel->create_refs=0;
}
opt_escape: opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; } ESCAPE_SYM TEXT_STRING { $$= $2.str; }
...@@ -1926,14 +2008,21 @@ order_dir: ...@@ -1926,14 +2008,21 @@ order_dir:
limit_clause: limit_clause:
/* empty */ /* empty */
{ {
Select->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ? SELECT_LEX *sel=Select;
sel->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ?
1 : current_thd->default_select_limit; 1 : current_thd->default_select_limit;
Select->offset_limit= 0L; sel->offset_limit= 0L;
} }
| LIMIT ULONG_NUM | LIMIT ULONG_NUM
{ Select->select_limit= $2; Select->offset_limit=0L; } {
SELECT_LEX *sel=Select;
sel->select_limit= $2; sel->offset_limit=0L;
}
| LIMIT ULONG_NUM ',' ULONG_NUM | LIMIT ULONG_NUM ',' ULONG_NUM
{ Select->select_limit= $4; Select->offset_limit=$2; } {
SELECT_LEX *sel=Select;
sel->select_limit= $4; sel->offset_limit=$2;
}
delete_limit_clause: delete_limit_clause:
/* empty */ /* empty */
...@@ -2006,28 +2095,32 @@ opt_into: ...@@ -2006,28 +2095,32 @@ opt_into:
drop: drop:
DROP TABLE_SYM if_exists table_list opt_restrict DROP TABLE_SYM if_exists table_list opt_restrict
{ {
Lex->sql_command = SQLCOM_DROP_TABLE; LEX *lex=Lex;
Lex->drop_if_exists = $3; lex->sql_command = SQLCOM_DROP_TABLE;
lex->drop_if_exists = $3;
} }
| DROP INDEX ident ON table_ident {} | DROP INDEX ident ON table_ident {}
{ {
Lex->sql_command= SQLCOM_DROP_INDEX; LEX *lex=Lex;
Lex->drop_list.empty(); lex->sql_command= SQLCOM_DROP_INDEX;
Lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, lex->drop_list.empty();
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str)); $3.str));
if (!add_table_to_list($5,NULL, 1)) if (!add_table_to_list($5,NULL, 1))
YYABORT; YYABORT;
} }
| DROP DATABASE if_exists ident | DROP DATABASE if_exists ident
{ {
Lex->sql_command= SQLCOM_DROP_DB; LEX *lex=Lex;
Lex->drop_if_exists=$3; lex->sql_command= SQLCOM_DROP_DB;
Lex->name=$4.str; lex->drop_if_exists=$3;
lex->name=$4.str;
} }
| DROP UDF_SYM ident | DROP UDF_SYM ident
{ {
Lex->sql_command = SQLCOM_DROP_FUNCTION; LEX *lex=Lex;
Lex->udf.name=$3.str; lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->udf.name=$3.str;
} }
...@@ -2070,17 +2163,19 @@ insert2: ...@@ -2070,17 +2163,19 @@ insert2:
insert_table: insert_table:
table_name table_name
{ {
Lex->field_list.empty(); LEX *lex=Lex;
Lex->many_values.empty(); lex->field_list.empty();
Lex->insert_list=0; lex->many_values.empty();
lex->insert_list=0;
} }
insert_field_spec: insert_field_spec:
opt_field_spec insert_values {} opt_field_spec insert_values {}
| SET | SET
{ {
if (!(Lex->insert_list = new List_item) || LEX *lex=Lex;
Lex->many_values.push_back(Lex->insert_list)) if (!(lex->insert_list = new List_item) ||
lex->many_values.push_back(lex->insert_list))
YYABORT; YYABORT;
} }
ident_eq_list ident_eq_list
...@@ -2118,8 +2213,9 @@ ident_eq_list: ...@@ -2118,8 +2213,9 @@ ident_eq_list:
ident_eq_value: ident_eq_value:
simple_ident equal expr simple_ident equal expr
{ {
if (Lex->field_list.push_back($1) || LEX *lex=Lex;
Lex->insert_list->push_back($3)) if (lex->field_list.push_back($1) ||
lex->insert_list->push_back($3))
YYABORT; YYABORT;
} }
...@@ -2134,7 +2230,8 @@ no_braces: ...@@ -2134,7 +2230,8 @@ no_braces:
} }
opt_values ')' opt_values ')'
{ {
if (Lex->many_values.push_back(Lex->insert_list)) LEX *lex=Lex;
if (lex->many_values.push_back(lex->insert_list))
YYABORT; YYABORT;
} }
...@@ -2163,10 +2260,11 @@ update: ...@@ -2163,10 +2260,11 @@ update:
opt_order_clause opt_order_clause
delete_limit_clause delete_limit_clause
{ {
Lex->sql_command = SQLCOM_UPDATE; LEX *lex=Lex;
Select->order_list.elements=0; lex->sql_command = SQLCOM_UPDATE;
Select->order_list.first=0; lex->select->order_list.elements=0;
Select->order_list.next= (byte**) &Select->order_list.first; lex->select->order_list.first=0;
lex->select->order_list.next= (byte**) &lex->select->order_list.first;
} }
update_list: update_list:
...@@ -2190,17 +2288,18 @@ opt_low_priority: ...@@ -2190,17 +2288,18 @@ opt_low_priority:
delete: delete:
DELETE_SYM DELETE_SYM
{ {
Lex->sql_command= SQLCOM_DELETE; Select->options=0; LEX *lex=Lex;
Lex->lock_option= current_thd->update_lock_default; lex->sql_command= SQLCOM_DELETE; lex->select->options=0;
Select->order_list.elements=0; lex->lock_option= lex->thd->update_lock_default;
Select->order_list.first=0; lex->select->order_list.elements=0;
Select->order_list.next= (byte**) &Select->order_list.first; lex->select->order_list.first=0;
lex->select->order_list.next= (byte**) &lex->select->order_list.first;
} }
opt_delete_options single_multi {} opt_delete_options single_multi {}
single_multi: single_multi:
FROM table_name where_clause opt_order_clause delete_limit_clause {} FROM table_name where_clause opt_order_clause delete_limit_clause {}
| table_multi_delete | table_wild_list
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_MULTI_DELETE; lex->sql_command = SQLCOM_MULTI_DELETE;
...@@ -2212,23 +2311,33 @@ single_multi: ...@@ -2212,23 +2311,33 @@ single_multi:
} }
FROM FROM
{ {
current_thd->lex.auxilliary_table_list=current_thd->lex.select_lex.table_list; LEX *lex=Lex;
current_thd->lex.select->table_list.elements=0; lex->auxilliary_table_list=lex->select_lex.table_list;
current_thd->lex.select->table_list.first=0; lex->select->table_list.elements=0;
current_thd->lex.select->table_list.next= (byte**) &(current_thd->lex.select->table_list.first); lex->select->table_list.first=0;
lex->select->table_list.next= (byte**) &(lex->select->table_list.first);
} join_table_list where_clause } join_table_list where_clause
table_multi_delete:
table_sini_wild {}
| table_multi_delete ',' table_sini_wild {}
table_sini_wild: table_wild_list:
ident '.' '*' { if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE)) YYABORT; } table_wild_one {}
| ident '.' ident '.' '*' | table_wild_list ',' table_wild_one {}
{ if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE)) YYABORT;}
| ident { if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE)) YYABORT; } table_wild_one:
| ident '.' ident ident opt_wild
{ if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE)) YYABORT;} {
if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE))
YYABORT;
}
| ident '.' ident opt_wild
{
if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE))
YYABORT;
}
opt_wild:
/* empty */ {}
| '.' '*' {}
opt_delete_options: opt_delete_options:
...@@ -2244,11 +2353,10 @@ truncate: ...@@ -2244,11 +2353,10 @@ truncate:
{ {
LEX* lex = Lex; LEX* lex = Lex;
lex->sql_command= SQLCOM_TRUNCATE; lex->sql_command= SQLCOM_TRUNCATE;
Select->options=0; lex->select->options=0;
Select->order_list.elements=0; lex->select->order_list.elements=0;
Select->order_list.first=0; lex->select->order_list.first=0;
Select->order_list.next= (byte**) &Select->order_list.first; lex->select->order_list.next= (byte**) &lex->select->order_list.first;
lex->lock_option= current_thd->update_lock_default; } lex->lock_option= current_thd->update_lock_default; }
opt_table_sym: opt_table_sym:
...@@ -2263,16 +2371,24 @@ show_param: ...@@ -2263,16 +2371,24 @@ show_param:
DATABASES wild DATABASES wild
{ Lex->sql_command= SQLCOM_SHOW_DATABASES; } { Lex->sql_command= SQLCOM_SHOW_DATABASES; }
| TABLES opt_db wild | TABLES opt_db wild
{ Lex->sql_command= SQLCOM_SHOW_TABLES; Select->db= $2; Select->options=0;} {
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
lex->select->db= $2; lex->select->options=0;
}
| TABLE_SYM STATUS_SYM opt_db wild | TABLE_SYM STATUS_SYM opt_db wild
{ Lex->sql_command= SQLCOM_SHOW_TABLES; {
Select->options|= SELECT_DESCRIBE; LEX *lex=Lex;
Select->db= $3; lex->sql_command= SQLCOM_SHOW_TABLES;
lex->select->options|= SELECT_DESCRIBE;
lex->select->db= $3;
} }
| OPEN_SYM TABLES opt_db wild | OPEN_SYM TABLES opt_db wild
{ Lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; {
Select->db= $3; LEX *lex=Lex;
Select->options=0; lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
lex->select->db= $3;
lex->select->options=0;
} }
| opt_full COLUMNS FROM table_ident opt_db wild | opt_full COLUMNS FROM table_ident opt_db wild
{ {
...@@ -2307,8 +2423,12 @@ show_param: ...@@ -2307,8 +2423,12 @@ show_param:
| LOGS_SYM | LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; } { Lex->sql_command= SQLCOM_SHOW_LOGS; }
| GRANTS FOR_SYM user | GRANTS FOR_SYM user
{ Lex->sql_command= SQLCOM_SHOW_GRANTS; {
Lex->grant_user=$3; Lex->grant_user->password.str=NullS; } LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
lex->grant_user=$3;
lex->grant_user->password.str=NullS;
}
| CREATE TABLE_SYM table_ident | CREATE TABLE_SYM table_ident
{ {
Lex->sql_command = SQLCOM_SHOW_CREATE; Lex->sql_command = SQLCOM_SHOW_CREATE;
...@@ -2340,9 +2460,10 @@ opt_full: ...@@ -2340,9 +2460,10 @@ opt_full:
describe: describe:
describe_command table_ident describe_command table_ident
{ {
Lex->wild=0; LEX *lex=Lex;
Lex->verbose=0; lex->wild=0;
Lex->sql_command=SQLCOM_SHOW_FIELDS; lex->verbose=0;
lex->sql_command=SQLCOM_SHOW_FIELDS;
if (!add_table_to_list($2, NULL,0)) if (!add_table_to_list($2, NULL,0))
YYABORT; YYABORT;
} }
...@@ -2363,7 +2484,12 @@ opt_describe_column: ...@@ -2363,7 +2484,12 @@ opt_describe_column:
/* flush things */ /* flush things */
flush: flush:
FLUSH_SYM {Lex->sql_command= SQLCOM_FLUSH; Lex->type=0; } flush_options FLUSH_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_FLUSH; lex->type=0;
}
flush_options
flush_options: flush_options:
flush_options ',' flush_option flush_options ',' flush_option
...@@ -2384,8 +2510,11 @@ opt_table_list: ...@@ -2384,8 +2510,11 @@ opt_table_list:
| table_list {} | table_list {}
reset: reset:
RESET_SYM {Lex->sql_command= SQLCOM_RESET; Lex->type=0; } reset_options RESET_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_RESET; lex->type=0;
} reset_options
reset_options: reset_options:
reset_options ',' reset_option reset_options ',' reset_option
| reset_option | reset_option
...@@ -2395,7 +2524,12 @@ reset_option: ...@@ -2395,7 +2524,12 @@ reset_option:
| MASTER_SYM { Lex->type|= REFRESH_MASTER; } | MASTER_SYM { Lex->type|= REFRESH_MASTER; }
purge: purge:
PURGE { Lex->sql_command = SQLCOM_PURGE; Lex->type=0;} PURGE
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_PURGE;
lex->type=0;
}
MASTER_SYM LOGS_SYM TO_SYM TEXT_STRING MASTER_SYM LOGS_SYM TO_SYM TEXT_STRING
{ {
Lex->to_log = $6.str; Lex->to_log = $6.str;
...@@ -2406,29 +2540,34 @@ purge: ...@@ -2406,29 +2540,34 @@ purge:
kill: kill:
KILL_SYM expr KILL_SYM expr
{ {
if ($2->fix_fields(current_thd,0)) LEX *lex=Lex;
if ($2->fix_fields(lex->thd,0))
{ {
send_error(&current_thd->net, ER_SET_CONSTANTS_ONLY); send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;
} }
Lex->sql_command=SQLCOM_KILL; lex->sql_command=SQLCOM_KILL;
Lex->thread_id= (ulong) $2->val_int(); lex->thread_id= (ulong) $2->val_int();
} }
/* change database */ /* change database */
use: USE_SYM ident use: USE_SYM ident
{ Lex->sql_command=SQLCOM_CHANGE_DB; Select->db= $2.str; } {
LEX *lex=Lex;
lex->sql_command=SQLCOM_CHANGE_DB; lex->select->db= $2.str;
}
/* import, export of files */ /* import, export of files */
load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{ {
Lex->sql_command= SQLCOM_LOAD; LEX *lex=Lex;
Lex->local_file= $4; lex->sql_command= SQLCOM_LOAD;
if (!(Lex->exchange= new sql_exchange($6.str,0))) lex->local_file= $4;
if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT; YYABORT;
Lex->field_list.empty(); lex->field_list.empty();
} }
opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
opt_ignore_lines opt_field_spec opt_ignore_lines opt_field_spec
...@@ -2476,7 +2615,11 @@ field_term_list: ...@@ -2476,7 +2615,11 @@ field_term_list:
field_term: field_term:
TERMINATED BY text_string { Lex->exchange->field_term= $3;} TERMINATED BY text_string { Lex->exchange->field_term= $3;}
| OPTIONALLY ENCLOSED BY text_string | OPTIONALLY ENCLOSED BY text_string
{ Lex->exchange->enclosed= $4; Lex->exchange->opt_enclosed=1;} {
LEX *lex=Lex;
lex->exchange->enclosed= $4;
lex->exchange->opt_enclosed=1;
}
| ENCLOSED BY text_string { Lex->exchange->enclosed= $3;} | ENCLOSED BY text_string { Lex->exchange->enclosed= $3;}
| ESCAPED BY text_string { Lex->exchange->escaped= $3;} | ESCAPED BY text_string { Lex->exchange->escaped= $3;}
...@@ -2546,13 +2689,25 @@ order_ident: ...@@ -2546,13 +2689,25 @@ order_ident:
simple_ident: simple_ident:
ident ident
{ $$ = !Select->create_refs || Select->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); } {
SELECT_LEX *sel=Select;
$$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
}
| ident '.' ident | ident '.' ident
{ $$ = !Select->create_refs || Select->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); } {
SELECT_LEX *sel=Select;
$$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
}
| '.' ident '.' ident | '.' ident '.' ident
{ $$ = !Select->create_refs || Select->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str); } {
SELECT_LEX *sel=Select;
$$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
}
| ident '.' ident '.' ident | ident '.' ident '.' ident
{ $$ = !Select->create_refs || Select->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str); } {
SELECT_LEX *sel=Select;
$$ = !sel->create_refs || sel->in_sum_expr > 0 ? (Item*) new Item_field((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((current_thd->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
}
field_ident: field_ident:
...@@ -2569,10 +2724,11 @@ ident: ...@@ -2569,10 +2724,11 @@ ident:
IDENT { $$=$1; } IDENT { $$=$1; }
| keyword | keyword
{ {
LEX *lex;
$$.str=sql_strmake($1.str,$1.length); $$.str=sql_strmake($1.str,$1.length);
$$.length=$1.length; $$.length=$1.length;
if (Lex->next_state != STATE_END) if ((lex=Lex)->next_state != STATE_END)
Lex->next_state=STATE_OPERATOR_OR_IDENT; lex->next_state=STATE_OPERATOR_OR_IDENT;
} }
ident_or_text: ident_or_text:
...@@ -2724,12 +2880,12 @@ keyword: ...@@ -2724,12 +2880,12 @@ keyword:
set: set:
SET opt_option SET opt_option
{ {
THD *thd=current_thd; LEX *lex=Lex;
Lex->sql_command= SQLCOM_SET_OPTION; lex->sql_command= SQLCOM_SET_OPTION;
Select->options=thd->options; lex->select->options=lex->thd->options;
Select->select_limit=thd->default_select_limit; lex->select->select_limit=lex->thd->default_select_limit;
Lex->gemini_spin_retries=thd->gemini_spin_retries; lex->gemini_spin_retries=lex->thd->gemini_spin_retries;
Lex->tx_isolation=thd->tx_isolation; lex->tx_isolation=lex->thd->tx_isolation;
} }
option_value_list option_value_list
...@@ -2744,18 +2900,20 @@ option_value_list: ...@@ -2744,18 +2900,20 @@ option_value_list:
option_value: option_value:
set_option equal NUM set_option equal NUM
{ {
SELECT_LEX *sel=Select;
if (atoi($3.str) == 0) if (atoi($3.str) == 0)
Select->options&= ~$1; sel->options&= ~$1;
else else
Select->options|= $1; sel->options|= $1;
} }
| set_isolation | set_isolation
| AUTOCOMMIT equal NUM | AUTOCOMMIT equal NUM
{ {
SELECT_LEX *sel=Select;
if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */ if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */
Select->options&= ~(OPTION_NOT_AUTO_COMMIT); sel->options&= ~(OPTION_NOT_AUTO_COMMIT);
else else
Select->options|= OPTION_NOT_AUTO_COMMIT; sel->options|= OPTION_NOT_AUTO_COMMIT;
} }
| SQL_SELECT_LIMIT equal ULONG_NUM | SQL_SELECT_LIMIT equal ULONG_NUM
{ {
...@@ -2767,8 +2925,9 @@ option_value: ...@@ -2767,8 +2925,9 @@ option_value:
} }
| SQL_MAX_JOIN_SIZE equal ULONG_NUM | SQL_MAX_JOIN_SIZE equal ULONG_NUM
{ {
current_thd->max_join_size= $3; LEX *lex=Lex;
Select->options&= ~OPTION_BIG_SELECTS; lex->thd->max_join_size= $3;
lex->select->options&= ~OPTION_BIG_SELECTS;
} }
| SQL_MAX_JOIN_SIZE equal DEFAULT | SQL_MAX_JOIN_SIZE equal DEFAULT
{ {
...@@ -2891,7 +3050,10 @@ set_isolation: ...@@ -2891,7 +3050,10 @@ set_isolation:
default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation]; default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation];
} }
| SESSION_SYM tx_isolation | SESSION_SYM tx_isolation
{ current_thd->session_tx_isolation= Lex->tx_isolation= $2; } {
LEX *lex=Lex;
lex->thd->session_tx_isolation= lex->tx_isolation= $2;
}
| tx_isolation | tx_isolation
{ Lex->tx_isolation= $1; } { Lex->tx_isolation= $1; }
...@@ -2975,8 +3137,9 @@ handler_rkey_function: ...@@ -2975,8 +3137,9 @@ handler_rkey_function:
| LAST_SYM { Lex->ha_read_mode = RLAST; } | LAST_SYM { Lex->ha_read_mode = RLAST; }
| handler_rkey_mode | handler_rkey_mode
{ {
Lex->ha_read_mode = RKEY; LEX *lex=Lex;
if (!(Lex->insert_list = new List_item)) lex->ha_read_mode = RKEY;
if (!(lex->insert_list = new List_item))
YYABORT; YYABORT;
} '(' values ')' { } } '(' values ')' { }
...@@ -2992,22 +3155,24 @@ handler_rkey_mode: ...@@ -2992,22 +3155,24 @@ handler_rkey_mode:
revoke: revoke:
REVOKE REVOKE
{ {
Lex->sql_command = SQLCOM_REVOKE; LEX *lex=Lex;
Lex->users_list.empty(); lex->sql_command = SQLCOM_REVOKE;
Lex->columns.empty(); lex->users_list.empty();
Lex->grant= Lex->grant_tot_col=0; lex->columns.empty();
Select->db=0; lex->grant= lex->grant_tot_col=0;
lex->select->db=0;
} }
grant_privileges ON opt_table FROM user_list grant_privileges ON opt_table FROM user_list
grant: grant:
GRANT GRANT
{ {
Lex->sql_command = SQLCOM_GRANT; LEX *lex=Lex;
Lex->users_list.empty(); lex->sql_command = SQLCOM_GRANT;
Lex->columns.empty(); lex->users_list.empty();
Lex->grant= Lex->grant_tot_col=0; lex->columns.empty();
Select->db=0; lex->grant= lex->grant_tot_col=0;
lex->select->db=0;
} }
grant_privileges ON opt_table TO_SYM user_list grant_privileges ON opt_table TO_SYM user_list
grant_option grant_option
...@@ -3047,43 +3212,47 @@ grant_privilege: ...@@ -3047,43 +3212,47 @@ grant_privilege:
opt_table: opt_table:
'*' '*'
{ {
Select->db=current_thd->db; LEX *lex=Lex;
if (Lex->grant == UINT_MAX) lex->select->db=lex->thd->db;
Lex->grant = DB_ACLS & ~GRANT_ACL; if (lex->grant == UINT_MAX)
else if (Lex->columns.elements) lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{ {
net_printf(&current_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); net_printf(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT; YYABORT;
} }
} }
| ident '.' '*' | ident '.' '*'
{ {
Select->db = $1.str; LEX *lex=Lex;
if (Lex->grant == UINT_MAX) lex->select->db = $1.str;
Lex->grant = DB_ACLS & ~GRANT_ACL; if (lex->grant == UINT_MAX)
else if (Lex->columns.elements) lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{ {
net_printf(&current_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); net_printf(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT; YYABORT;
} }
} }
| '*' '.' '*' | '*' '.' '*'
{ {
Select->db = NULL; LEX *lex=Lex;
if (Lex->grant == UINT_MAX) lex->select->db = NULL;
Lex->grant = GLOBAL_ACLS & ~GRANT_ACL; if (lex->grant == UINT_MAX)
else if (Lex->columns.elements) lex->grant = GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{ {
net_printf(&current_thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); net_printf(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT; YYABORT;
} }
} }
| table_ident | table_ident
{ {
LEX *lex=Lex;
if (!add_table_to_list($1,NULL,0)) if (!add_table_to_list($1,NULL,0))
YYABORT; YYABORT;
if (Lex->grant == UINT_MAX) if (lex->grant == UINT_MAX)
Lex->grant = TABLE_ACLS & ~GRANT_ACL; lex->grant = TABLE_ACLS & ~GRANT_ACL;
} }
...@@ -3114,7 +3283,11 @@ grant_user: ...@@ -3114,7 +3283,11 @@ grant_user:
opt_column_list: opt_column_list:
/* empty */ { Lex->grant |= Lex->which_columns; } /* empty */
{
LEX *lex=Lex;
lex->grant |= lex->which_columns;
}
| '(' column_list ')' | '(' column_list ')'
column_list: column_list:
...@@ -3127,16 +3300,17 @@ column_list_id: ...@@ -3127,16 +3300,17 @@ column_list_id:
String *new_str = new String((const char*) $1.str,$1.length); String *new_str = new String((const char*) $1.str,$1.length);
List_iterator <LEX_COLUMN> iter(Lex->columns); List_iterator <LEX_COLUMN> iter(Lex->columns);
class LEX_COLUMN *point; class LEX_COLUMN *point;
LEX *lex=Lex;
while ((point=iter++)) while ((point=iter++))
{ {
if (!my_strcasecmp(point->column.ptr(),new_str->ptr())) if (!my_strcasecmp(point->column.ptr(),new_str->ptr()))
break; break;
} }
Lex->grant_tot_col|= Lex->which_columns; lex->grant_tot_col|= lex->which_columns;
if (point) if (point)
point->rights |= Lex->which_columns; point->rights |= lex->which_columns;
else else
Lex->columns.push_back(new LEX_COLUMN (*new_str,Lex->which_columns)); lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
} }
grant_option: grant_option:
......
...@@ -164,3 +164,4 @@ typedef struct st_lex_user { ...@@ -164,3 +164,4 @@ typedef struct st_lex_user {
#define STATUS_NOT_READ 8 /* Record isn't read */ #define STATUS_NOT_READ 8 /* Record isn't read */
#define STATUS_UPDATED 16 /* Record is updated by formula */ #define STATUS_UPDATED 16 /* Record is updated by formula */
#define STATUS_NULL_ROW 32 /* table->null_row is set */ #define STATUS_NULL_ROW 32 /* table->null_row is set */
#define STATUS_DELETED 64
...@@ -44,7 +44,8 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, ...@@ -44,7 +44,8 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
/* If the following fail's the next add will also fail */ /* If the following fail's the next add will also fail */
init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size); max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)); open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
MYF(MY_WME));
} }
...@@ -95,7 +96,7 @@ bool Unique::get(TABLE *table) ...@@ -95,7 +96,7 @@ bool Unique::get(TABLE *table)
SORTPARAM sort_param; SORTPARAM sort_param;
table->found_records=elements+tree.elements_in_tree; table->found_records=elements+tree.elements_in_tree;
if (!my_b_inited(&file)) if (my_b_tell(&file) == 0)
{ {
/* Whole tree is in memory; Don't use disk if you don't need to */ /* Whole tree is in memory; Don't use disk if you don't need to */
if ((record_pointers=table->record_pointers= (byte*) if ((record_pointers=table->record_pointers= (byte*)
...@@ -110,17 +111,16 @@ bool Unique::get(TABLE *table) ...@@ -110,17 +111,16 @@ bool Unique::get(TABLE *table)
if (flush()) if (flush())
return 1; return 1;
IO_CACHE *outfile=table->io_cache, tempfile; IO_CACHE *outfile=table->io_cache;
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer; BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
uint maxbuffer= file_ptrs.elements - 1; uint maxbuffer= file_ptrs.elements - 1;
uchar *sort_buffer; uchar *sort_buffer;
my_off_t save_pos; my_off_t save_pos;
bool error=1; bool error=1;
my_b_clear(&tempfile);
/* Open cached file if it isn't open */ /* Open cached file if it isn't open */
outfile=table->io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),MYF(MY_ZEROFILL)); outfile=table->io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_ZEROFILL));
if (!outfile || ! my_b_inited(outfile) && if (!outfile || ! my_b_inited(outfile) &&
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER, open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
...@@ -141,18 +141,17 @@ bool Unique::get(TABLE *table) ...@@ -141,18 +141,17 @@ bool Unique::get(TABLE *table)
sort_param.sort_length); sort_param.sort_length);
/* Merge the buffers to one file, removing duplicates */ /* Merge the buffers to one file, removing duplicates */
if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&tempfile)) if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&file))
goto err; goto err;
if (flush_io_cache(&tempfile) || if (flush_io_cache(&file) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) reinit_io_cache(&file,READ_CACHE,0L,0,0))
goto err; goto err;
if (merge_buffers(&sort_param, &tempfile, outfile, sort_buffer, file_ptr, if (merge_buffers(&sort_param, &file, outfile, sort_buffer, file_ptr,
file_ptr, file_ptr+maxbuffer,0)) file_ptr, file_ptr+maxbuffer,0))
goto err; goto err;
error=0; error=0;
err: err:
x_free((gptr) sort_buffer); x_free((gptr) sort_buffer);
close_cached_file(&tempfile);
if (flush_io_cache(outfile)) if (flush_io_cache(outfile))
error=1; error=1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment