These are actually two changesets. One for splitting LEX in two and

the other for multi-table delete
parent 73e6a690
...@@ -15,3 +15,4 @@ serg@serg.mysql.com ...@@ -15,3 +15,4 @@ serg@serg.mysql.com
tim@threads.polyesthetic.msg tim@threads.polyesthetic.msg
tim@work.mysql.com tim@work.mysql.com
tonu@x3.internalnet tonu@x3.internalnet
Sinisa@sinisa.nasamreza.org
...@@ -739,7 +739,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, ...@@ -739,7 +739,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);
if (cmp) // Remove duplicates if (cmp) // Remove duplicates
{ {
if (!cmp(&sort_length, param->unique_buff, (uchar*) buffpek->key)) // Was if (!cmp(&sort_length, param->unique_buff, (uchar**) buffpek->key))
if (!cmp(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key))
goto skip_duplicate; goto skip_duplicate;
memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length); memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length);
} }
......
...@@ -561,7 +561,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -561,7 +561,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables)
{ {
if (!ref) if (!ref)
{ {
if (!(ref=find_item_in_list(this,thd->lex.item_list))) if (!(ref=find_item_in_list(this,thd->lex.select->item_list)))
return 1; return 1;
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
......
...@@ -883,7 +883,7 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -883,7 +883,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
tmp_table_param->cleanup(); tmp_table_param->cleanup();
} }
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1, if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
0, 0, current_lex->options | thd->options))) 0, 0, current_lex->select->options | thd->options)))
return 1; return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1; table->no_rows=1;
......
...@@ -667,7 +667,7 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length); ...@@ -667,7 +667,7 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
inline bool add_item_to_list(Item *item) inline bool add_item_to_list(Item *item)
{ {
return current_lex->item_list.push_back(item); return current_lex->select->item_list.push_back(item);
} }
inline bool add_value_to_list(Item *value) inline bool add_value_to_list(Item *value)
{ {
...@@ -675,11 +675,11 @@ inline bool add_value_to_list(Item *value) ...@@ -675,11 +675,11 @@ inline bool add_value_to_list(Item *value)
} }
inline bool add_order_to_list(Item *item,bool asc) inline bool add_order_to_list(Item *item,bool asc)
{ {
return add_to_list(current_lex->order_list,item,asc); return add_to_list(current_lex->select->order_list,item,asc);
} }
inline bool add_group_to_list(Item *item,bool asc) inline bool add_group_to_list(Item *item,bool asc)
{ {
return add_to_list(current_lex->group_list,item,asc); return add_to_list(current_lex->select->group_list,item,asc);
} }
inline void mark_as_null_row(TABLE *table) inline void mark_as_null_row(TABLE *table)
{ {
......
...@@ -465,6 +465,32 @@ class select_dump :public select_result { ...@@ -465,6 +465,32 @@ class select_dump :public select_result {
bool send_eof(); bool send_eof();
}; };
class multi_delete : public select_result {
TABLE_LIST *delete_tables, *table_being_deleted;
IO_CACHE **tempfiles;
thr_lock_type lock_option;
ulong deleted;
byte *dup_checking, wrong_record[MAX_REFLENGTH], *memory_lane;
int num_of_tables, error;
bool do_delete;
THD *thd;
public:
multi_delete(TABLE_LIST *dt, thr_lock_type o, uint n)
: delete_tables (dt), lock_option(o), deleted(0), num_of_tables(n), error(0)
{
memset(wrong_record,'\xFF',MAX_REFLENGTH);
thd = current_thd; do_delete = false;
}
~multi_delete();
int prepare(List<Item> &list);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
int do_deletes (bool from_send_error);
bool send_eof();
};
class select_insert :public select_result { class select_insert :public select_result {
protected: protected:
...@@ -578,19 +604,18 @@ class Unique :public Sql_alloc ...@@ -578,19 +604,18 @@ class Unique :public Sql_alloc
public: public:
ulong elements; ulong elements;
Unique(qsort_cmp2 comp_func, uint size, ulong max_in_memory_size_arg); Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
uint size, ulong max_in_memory_size_arg);
~Unique(); ~Unique();
inline bool Unique::unique_add(gptr ptr) inline bool Unique::unique_add(gptr ptr)
{ {
if (tree.elements_in_tree > max_elements && flush()) if (tree.elements_in_tree > max_elements && flush())
return 1; return 1;
return tree_insert(&tree,ptr,0); return !tree_insert(&tree,ptr,0);
} }
bool get(TABLE *table); bool get(TABLE *table);
friend int unique_write_to_file(gptr key, Unique *unique, friend int unique_write_to_file(gptr key, element_count count, Unique *unique);
element_count count); friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique);
friend int unique_write_to_ptrs(gptr key, Unique *unique,
element_count count);
}; };
...@@ -150,8 +150,8 @@ int mysql_delete(THD *thd, ...@@ -150,8 +150,8 @@ int mysql_delete(THD *thd,
(OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))); (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)));
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
/* We need to add code to not generate table based on the table type */ /* We need to add code to not generate table based on the table type */
if (!innodb_skip) if (!innobase_skip)
use_generate_table=0; // Innodb can't use re-generate table use_generate_table=0; // Innobase can't use re-generate table
#endif #endif
if (use_generate_table && ! thd->open_tables) if (use_generate_table && ! thd->open_tables)
{ {
...@@ -186,7 +186,7 @@ int mysql_delete(THD *thd, ...@@ -186,7 +186,7 @@ int mysql_delete(THD *thd,
/* If running in safe sql mode, don't allow updates without keys */ /* If running in safe sql mode, don't allow updates without keys */
if (!table->quick_keys) if (!table->quick_keys)
{ {
thd->lex.options|=QUERY_NO_INDEX_USED; thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR) if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
{ {
delete select; delete select;
...@@ -286,3 +286,548 @@ int mysql_delete(THD *thd, ...@@ -286,3 +286,548 @@ int mysql_delete(THD *thd,
} }
/***************************************************************************
** delete multiple tables from join
***************************************************************************/
#define MEM_STRIP_BUF_SIZE 2048
int
multi_delete::prepare(List<Item> &values)
{
DBUG_ENTER("multi_delete::prepare");
tempfiles = (IO_CACHE **) sql_calloc(sizeof(IO_CACHE *)*(num_of_tables));
memory_lane = (byte *)sql_alloc(MAX_REFLENGTH*MEM_STRIP_BUF_SIZE); uint counter = 0;
dup_checking = (byte *) sql_calloc(MAX_REFLENGTH * (num_of_tables + 1));
memset(dup_checking,'\xFF', MAX_REFLENGTH * (num_of_tables + 1)); do_delete = true;
for (table_being_deleted=delete_tables; table_being_deleted; table_being_deleted=table_being_deleted->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));
DBUG_RETURN(1);
}
(void) table->file->extra(HA_EXTRA_NO_READCHECK);
if (counter < num_of_tables)
{
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)))
{
my_error(ER_CANT_OPEN_FILE,MYF(0),(tempfiles[counter])->file_name,errno);
DBUG_RETURN(1);
}
}
}
thd->proc_info="updating";
DBUG_RETURN(0);
}
multi_delete::~multi_delete()
{
for (uint counter = 0; counter < num_of_tables; counter++)
if (tempfiles[counter])
end_io_cache(tempfiles[counter]);
// Here it crashes ...
}
bool multi_delete::send_data(List<Item> &values)
{
int secure_counter = -1;
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->file->position(table->record[0]); int rl = table->file->ref_length;
byte *dup_check = dup_checking + (secure_counter + 1)*MAX_REFLENGTH;
if (!table->null_row && memcmp(dup_check,table->file->ref, rl) && memcmp(table->file->ref,wrong_record,rl))
{
memcpy(dup_check,table->file->ref,rl);
if (secure_counter == -1)
{
if (!(error=table->file->delete_row(table->record[0])))
deleted++;
else
{
send_error(error,"An error occured in deleting rows");
return 1;
}
}
else
{
if (my_b_write(tempfiles[secure_counter],table->file->ref,rl))
{
error=-1;
return 1;
}
}
}
}
return 0;
}
#ifdef SINISAS_STRIP
static inline int COMP (byte *ml,uint len,unsigned int left, unsigned int right)
{
return memcmp(ml + left*len,ml + right*len,len);
}
#define EX(ML,LEN,LLLEFT,RRRIGHT) \
ptr1 = ML + LLLEFT*LEN;\
ptr2 = ML + RRRIGHT*LEN;\
memcpy(tmp,ptr1,LEN);\
memcpy(ptr1,ptr2,LEN);\
memcpy(ptr2,tmp,LEN);\
static void qsort_mem_pieces(byte *ml, uint length, unsigned short pivotP, unsigned int nElem)
{
unsigned int leftP, rightP, pivotEnd, pivotTemp, leftTemp;
unsigned int lNum; byte tmp [MAX_REFLENGTH], *ptr1, *ptr2;
int retval;
tailRecursion:
if (nElem <= 1) return;
if (nElem == 2)
{
if (COMP(ml,length,pivotP, rightP = pivotP + 1) > 0)
{
EX(ml,length,pivotP, rightP);
}
return;
}
rightP = (nElem - 1) + pivotP;
leftP = (nElem >> 1) + pivotP;
/* sort the pivot, left, and right elements for "median of 3" */
if (COMP (ml,length,leftP, rightP) > 0)
{
EX (ml,length,leftP, rightP);
}
if (COMP (ml,length,leftP, pivotP) > 0)
{
EX (ml,length,leftP, pivotP);
}
else if (COMP (ml,length, pivotP, rightP) > 0)
{
EX (ml,length,pivotP, rightP);
}
if (nElem == 3) {
EX (ml,length,pivotP, leftP);
return;
}
/* now for the classic Hoare algorithm */
leftP = pivotEnd = pivotP + 1;
do {
while ((retval = COMP (ml,length, leftP, pivotP)) <= 0)
{
if (retval == 0) {
EX(ml,length,leftP, pivotEnd);
pivotEnd++;
}
if (leftP < rightP)
leftP++;
else
goto qBreak;
}
while (leftP < rightP) {
if ((retval = COMP(ml,length,pivotP, rightP)) < 0)
rightP--;
else
{
EX (ml,length,leftP, rightP);
if (retval != 0) {
leftP++;
rightP--;
}
break;
}
}
} while (leftP < rightP);
qBreak:
if (COMP(ml,length,leftP, pivotP) <= 0)
leftP++;
leftTemp = leftP - 1; pivotTemp = pivotP;
while ((pivotTemp < pivotEnd) && (leftTemp >= pivotEnd))
{
EX(ml,length,pivotTemp, leftTemp);
pivotTemp++; leftTemp--;
}
lNum = leftP - pivotEnd; nElem = (nElem + pivotP) - leftP;
/* Sort smaller partition first to reduce stack usage */
if (nElem < lNum)
{
qsort_mem_pieces(ml,length,leftP, nElem); nElem = lNum;
}
else
{
qsort_mem_pieces(ml,length,pivotP, lNum);
pivotP = leftP;
}
goto tailRecursion;
}
static byte * btree_search(byte *lane, byte *key,register int last, uint length)
{
register int first = 0;
if (last == first)
{
if (!memcmp(lane,key,length)) return lane;
return (byte *)0;
}
Recursion_is_too_slow:
if (last - first < 3)
{
if (!memcmp(lane + first*length,key,length)) return lane + first * length;
if (last == first + 1) return (byte *)0;
if (!memcmp(lane + last*length,key,length)) return lane + last * length;
return (byte *)0;
}
else
{
int half = first + (last - first)/2;
int result = memcmp(lane + half*length,key,length);
if (!result) return lane + half*length;
if (result < 0)
{
first = half + 1; goto Recursion_is_too_slow;
}
else
{
last = half + 1; goto Recursion_is_too_slow;
}
}
}
struct written_block {
byte first[MAX_REFLENGTH], last[MAX_REFLENGTH];
my_off_t offset;
uint how_many;
};
static IO_CACHE *strip_duplicates_from_temp (byte *memory_lane, IO_CACHE *ptr, uint ref_length, int *written)
{
byte *mem_ptr; my_off_t off = 0;
int read_error, write_error, how_many_to_read, total_to_read = *written, pieces_in_memory = 0, mem_count,written_rows;
int offset = written_rows=*written=0;
int mem_pool_size = MEM_STRIP_BUF_SIZE * MAX_REFLENGTH / ref_length;
IO_CACHE *tempptr = (IO_CACHE *) sql_alloc(sizeof(IO_CACHE));
byte dup_record[MAX_REFLENGTH]; memset(dup_record,'\xFF',MAX_REFLENGTH);
if (reinit_io_cache(ptr,READ_CACHE,0L,0,0))
return ptr;
if (open_cached_file(tempptr, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
return ptr;
DYNAMIC_ARRAY written_blocks;
VOID(init_dynamic_array(&written_blocks,sizeof(struct written_block),20,50));
for (;pieces_in_memory < total_to_read;)
{
how_many_to_read = total_to_read - pieces_in_memory; read_error=write_error=0;
if (how_many_to_read > mem_pool_size)
how_many_to_read = mem_pool_size;
if (my_b_read(ptr, memory_lane, (uint) how_many_to_read * ref_length))
{
read_error = 1;
break;
}
pieces_in_memory += how_many_to_read;
qsort_mem_pieces(memory_lane,0, how_many_to_read, ref_length);
byte *checking = dup_record, *cursor=NULL, *mem_end = memory_lane + how_many_to_read * ref_length;
int opt_unique_pieces, unique_pieces_in_memory=0; write_error=0;
for (mem_ptr=memory_lane; mem_ptr < mem_end ; mem_ptr += ref_length)
{
if (memcmp(mem_ptr,checking, ref_length))
{
if (cursor)
{
memmove(cursor,mem_ptr,mem_end - mem_ptr);
mem_end -= mem_ptr - cursor;
mem_ptr = cursor; cursor = NULL;
}
unique_pieces_in_memory++;
checking = mem_ptr;
}
else if (!cursor) cursor = mem_ptr;
}
opt_unique_pieces=unique_pieces_in_memory;
if (written_rows)
{
if (reinit_io_cache(tempptr,READ_CACHE,0L,0,0)) {write_error = -1; break;}
for (uint i=0 ; i < written_blocks.elements ; i++)
{
struct written_block *wbp=dynamic_element(&written_blocks,i,struct written_block*);
if ((memcmp(memory_lane,wbp->last,ref_length) == 1) || (memcmp(memory_lane + (unique_pieces_in_memory - 1) * ref_length, wbp->first, ref_length) == -1))
continue;
else
{
if (wbp->how_many < 3)
{
if ((mem_ptr=btree_search(memory_lane,wbp->first,unique_pieces_in_memory-1, ref_length)))
{
if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
memcpy(mem_ptr,dup_record,ref_length);
}
if (wbp->how_many == 2 && (mem_ptr=btree_search(memory_lane,wbp->last,unique_pieces_in_memory-1, ref_length)))
{
if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
memcpy(mem_ptr,dup_record,ref_length);
}
}
else
{
byte block[MAX_REFLENGTH * MEM_STRIP_BUF_SIZE]; // 16 K maximum and only temporary !!
if (my_b_read(tempptr, block, (uint) wbp->how_many * ref_length))
{
read_error = 1; goto skip_writting;
}
if (unique_pieces_in_memory < 3)
{
if ((mem_ptr=btree_search(block,memory_lane,wbp->how_many - 1, ref_length)))
{
if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
memcpy(memory_lane,dup_record,ref_length);
}
if (unique_pieces_in_memory == 2 && (mem_ptr=btree_search(block,memory_lane + ref_length,wbp->how_many - 1, ref_length)))
{
if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
memcpy(mem_ptr,dup_record,ref_length);
}
}
else
{
byte *cursor; bool do_check_past;
if (unique_pieces_in_memory < wbp->how_many)
{
do_check_past = (memcmp(memory_lane + (unique_pieces_in_memory - 1)*ref_length,wbp->last,ref_length) == 1);
for (cursor=memory_lane; cursor < memory_lane + unique_pieces_in_memory*ref_length; cursor += ref_length)
{
if ((mem_ptr=btree_search(block,cursor,wbp->how_many - 1, ref_length)))
{
if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
memcpy(cursor,dup_record,ref_length);
}
else if (do_check_past && (memcmp(cursor,wbp->last,ref_length) == 1)) break;
}
}
else
{
do_check_past = (memcmp(memory_lane + (unique_pieces_in_memory - 1)*ref_length,wbp->last,ref_length) == -1);
for (cursor=block; cursor < block + wbp->how_many*ref_length;cursor += ref_length)
{
if ((mem_ptr=btree_search(memory_lane,cursor,unique_pieces_in_memory-1, ref_length)))
{
if (!--opt_unique_pieces) goto skip_writting; // nice little optimization
memcpy(mem_ptr,dup_record,ref_length);
}
else if (do_check_past && (memcmp(cursor,memory_lane + (unique_pieces_in_memory - 1)*ref_length,ref_length) == 1)) break;
}
}
}
}
}
}
}
reinit_io_cache(tempptr, WRITE_CACHE,off,0,0);
struct written_block wb; wb.offset = off; wb.how_many=opt_unique_pieces; byte *last;
if (opt_unique_pieces < unique_pieces_in_memory)
{
for (mem_count=0, mem_ptr=memory_lane; mem_count<unique_pieces_in_memory;mem_count++, mem_ptr += ref_length)
{
if (memcmp(mem_ptr,dup_record,ref_length))
{
if (my_b_write(tempptr,mem_ptr,ref_length))
{
if (write_error == 9 || write_error == -1) write_error = 0;
if (write_error) break;
}
if (!mem_count) memcpy(wb.first,mem_ptr,ref_length);
last = mem_ptr;
written_rows++;
}
}
memcpy(wb.last,last,ref_length);
}
else
{
memcpy(wb.first,memory_lane,ref_length); memcpy(wb.last,memory_lane + (unique_pieces_in_memory -1)*ref_length,ref_length);
if (my_b_write(tempptr, memory_lane,unique_pieces_in_memory * ref_length))
{
write_error = 1; break;
}
written_rows += unique_pieces_in_memory;
}
off = my_b_tell(tempptr);
VOID(push_dynamic(&written_blocks,(gptr) &wb));
skip_writting:
if (write_error || read_error) break;
}
delete_dynamic(&written_blocks);
if (read_error || write_error)
{
close_cached_file(tempptr); end_io_cache(tempptr);
return ptr;
}
else
{
close_cached_file(ptr); *written=written_rows; end_io_cache(ptr);
reinit_io_cache(tempptr,READ_CACHE,0L,0,0);
return tempptr;
}
}
#else
int refposcmp2(void* arg, const void *a,const void *b)
{
return memcmp(a,b,(int)arg);
}
#endif
static bool some_table_is_not_transaction_safe (TABLE_LIST *tl)
{
TABLE_LIST *deleting = tl;
for (deleting=deleting->next; deleting ; deleting=deleting->next)
{
if (!(deleting->table->file->has_transactions()))
return true;
}
return false;
}
void multi_delete::send_error(uint errcode,const char *err)
{
::send_error(&thd->net,errcode,err);
if (!deleted) return;
if (!table_being_deleted) 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);
else if (do_delete)
VOID(do_deletes(true));
}
int multi_delete::do_deletes (bool from_send_error)
{
TABLE *table;
int error = 0, counter = 0, count;
if (from_send_error)
{
for (TABLE_LIST *aux=delete_tables; aux != table_being_deleted; aux=aux->next)
counter++;
}
else
table_being_deleted = delete_tables;
do_delete = false;
for (table_being_deleted=table_being_deleted->next; table_being_deleted ; counter++, table_being_deleted=table_being_deleted->next)
{
table = table_being_deleted->table; int rl = table->file->ref_length;
int num_of_positions = (int)my_b_tell(tempfiles[counter])/rl;
if (!num_of_positions) continue;
#ifdef SINISAS_STRIP
tempfiles[counter] = strip_duplicates_from_temp(memory_lane, tempfiles[counter],rl,&num_of_positions);
if (!num_of_positions)
{
error=1; break;
}
#else
Unique strip_it(refposcmp2,(void *)rl,rl,MEM_STRIP_BUF_SIZE);
if (reinit_io_cache(tempfiles[counter],READ_CACHE,0L,0,0))
{
error=1; break;
}
for (count = 0; count < num_of_positions; count++)
{
byte tmp [MAX_REFLENGTH];
if (my_b_read(tempfiles[counter], tmp, rl) || strip_it.unique_add(tmp))
{
error = 1;
break;
}
}
strip_it.get(table);
#endif
#if 0
if (num_of_positions == table->file->records) // nice little optimization ....
{ // but Monty has to fix generate_table...
TABLE_LIST 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.table=table;
table_list.grant=table->grant;
table_list.db = table_being_deleted->db;
error=generate_table(thd,&table_list,(TABLE *)0);
if (error <= 0) {error = 1; break;}
deleted += num_of_positions;
}
else
{
#endif
SQL_SELECT *select= new SQL_SELECT;
READ_RECORD info;
select->head=table;
select->file=*tempfiles[counter];
init_read_record(&info,thd,table,select,0,0); error=0;
while (!(error=info.read_record(&info)) && (!thd->killed || from_send_error))
{
error=table->file->delete_row(table->record[0]);
if (error)
{
table->file->print_error(error,MYF(0));
break;
}
else
deleted++;
}
end_read_record(&info); delete select;
if (error = -1) error = 0; // Monty, that is what read_record returns on end of the file !!
#if 0
}
#endif
}
return error;
}
bool multi_delete::send_eof()
{
int error = 0;
error = do_deletes(false);
thd->proc_info="end";
if (error && error != -1)
{
::send_error(&thd->net);
return 1;
}
for (table_being_deleted=delete_tables ; table_being_deleted ; table_being_deleted=table_being_deleted->next)
{
TABLE *table=table_being_deleted->table;
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);
Query_log_event qinfo(thd, thd->query);
if (mysql_bin_log.write(&qinfo) && !some_table_is_not_transaction_safe(delete_tables))
error=1;
VOID(ha_autocommit_or_rollback(thd,error >= 0));
}
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
::send_ok(&thd->net,deleted);
return 0;
}
...@@ -142,11 +142,11 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) ...@@ -142,11 +142,11 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->next_state=STATE_START; lex->next_state=STATE_START;
lex->end_of_query=(lex->ptr=buf)+length; lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1; lex->yylineno = 1;
lex->create_refs=lex->in_comment=0; lex->select->create_refs=lex->in_comment=0;
lex->length=0; lex->length=0;
lex->in_sum_expr=0; lex->select->in_sum_expr=0;
lex->expr_list.empty(); lex->select->expr_list.empty();
lex->ftfunc_list.empty(); lex->select->ftfunc_list.empty();
lex->convert_set=(lex->thd=thd)->convert_set; lex->convert_set=(lex->thd=thd)->convert_set;
lex->yacc_yyss=lex->yacc_yyvs=0; lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->client_capabilities & CLIENT_IGNORE_SPACE); lex->ignore_space=test(thd->client_capabilities & CLIENT_IGNORE_SPACE);
...@@ -155,7 +155,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) ...@@ -155,7 +155,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
void lex_end(LEX *lex) void lex_end(LEX *lex)
{ {
lex->expr_list.delete_elements(); // If error when parsing sql-varargs lex->select->expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss); x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs); x_free(lex->yacc_yyvs);
} }
......
...@@ -54,7 +54,8 @@ enum enum_sql_command { ...@@ -54,7 +54,8 @@ enum enum_sql_command {
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_MULTI_DELETE
}; };
enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
...@@ -94,39 +95,57 @@ typedef struct st_lex_master_info ...@@ -94,39 +95,57 @@ typedef struct st_lex_master_info
ulonglong pos; ulonglong pos;
} LEX_MASTER_INFO; } LEX_MASTER_INFO;
enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE};
/* The state of the lex parsing for selects */
typedef struct st_select_lex {
enum sub_select_type linkage;
uint select_number; /* For Item_select */
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
Item *where,*having;
ha_rows select_limit,offset_limit;
ulong options;
List<List_item> expr_list;
List<List_item> when_list;
SQL_LIST order_list,table_list,group_list;
List<Item> item_list;
List<String> interval_list,use_index, *use_index_ptr, ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list;
uint in_sum_expr, sort_default;
bool create_refs;
st_select_lex *next;
} SELECT_LEX;
/* The state of the lex parsing. This is saved in the THD struct */ /* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex { typedef struct st_lex {
uint yylineno,yytoklen; /* Simulate lex */ uint yylineno,yytoklen; /* Simulate lex */
LEX_YYSTYPE yylval; LEX_YYSTYPE yylval;
SELECT_LEX select_lex, *select;
uchar *ptr,*tok_start,*tok_end,*end_of_query; uchar *ptr,*tok_start,*tok_end,*end_of_query;
char *length,*dec,*change,*name; char *length,*dec,*change,*name;
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
char *backup_dir; /* For RESTORE/BACKUP */ char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */ char* to_log; /* For PURGE MASTER LOGS TO */
String *wild; String *wild;
sql_exchange *exchange; sql_exchange *exchange;
ha_rows select_limit,offset_limit;
List<List_item> expr_list;
List<List_item> when_list;
List<List_item> many_values;
List<key_part_spec> col_list; List<key_part_spec> col_list;
List<Alter_drop> drop_list; List<Alter_drop> drop_list;
List<Alter_column> alter_list; List<Alter_column> alter_list;
List<String> interval_list,use_index,*use_index_ptr, List<String> interval_list;
ignore_index, *ignore_index_ptr;
List<st_lex_user> users_list; List<st_lex_user> users_list;
List<LEX_COLUMN> columns; List<LEX_COLUMN> columns;
List<Key> key_list; List<Key> key_list;
List<create_field> create_list; List<create_field> create_list;
List<Item> item_list,*insert_list,field_list,value_list; List<Item> *insert_list,field_list,value_list;
List<Item_func_match> ftfunc_list; List<List_item> many_values;
SQL_LIST order_list,table_list,group_list,proc_list; SQL_LIST proc_list, auxilliary_table_list;
TYPELIB *interval; TYPELIB *interval;
create_field *last_field; create_field *last_field;
Item *default_value;
Item *where,*having,*default_value;
CONVERT *convert_set; CONVERT *convert_set;
LEX_USER *grant_user; LEX_USER *grant_user;
gptr yacc_yyss,yacc_yyvs; gptr yacc_yyss,yacc_yyvs;
...@@ -136,7 +155,6 @@ typedef struct st_lex { ...@@ -136,7 +155,6 @@ typedef struct st_lex {
HA_CREATE_INFO create_info; HA_CREATE_INFO create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER LEX_MASTER_INFO mi; // used by CHANGE MASTER
ulong thread_id,type; ulong thread_id,type;
ulong options;
ulong gemini_spin_retries; ulong gemini_spin_retries;
enum_sql_command sql_command; enum_sql_command sql_command;
enum lex_states next_state; enum lex_states next_state;
...@@ -145,9 +163,9 @@ typedef struct st_lex { ...@@ -145,9 +163,9 @@ typedef struct st_lex {
enum enum_ha_read_modes ha_read_mode; enum enum_ha_read_modes ha_read_mode;
enum ha_rkey_function ha_rkey_mode; enum ha_rkey_function ha_rkey_mode;
enum enum_enable_or_disable alter_keys_onoff; enum enum_enable_or_disable alter_keys_onoff;
uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default; uint grant,grant_tot_col,which_columns;
thr_lock_type lock_option; thr_lock_type lock_option;
bool create_refs,drop_primary,drop_if_exists,local_file; bool drop_primary,drop_if_exists,local_file;
bool in_comment,ignore_space,verbose,simple_alter; bool in_comment,ignore_space,verbose,simple_alter;
} LEX; } LEX;
......
...@@ -760,7 +760,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -760,7 +760,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thread_running++; thread_running++;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->set_time(); thd->set_time();
thd->lex.options=0; // We store status here thd->lex.select_lex.options=0; // We store status here
switch (command) { switch (command) {
case COM_INIT_DB: case COM_INIT_DB:
if (!mysql_change_db(thd,packet)) if (!mysql_change_db(thd,packet))
...@@ -1027,7 +1027,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1027,7 +1027,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->proc_info="logging slow query"; thd->proc_info="logging slow query";
if ((ulong) (thd->start_time - thd->time_after_lock) > long_query_time || if ((ulong) (thd->start_time - thd->time_after_lock) > long_query_time ||
((thd->lex.options & ((thd->lex.select_lex.options &
(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED)) && (QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED)) &&
(specialflag & SPECIAL_LONG_LOG_FORMAT))) (specialflag & SPECIAL_LONG_LOG_FORMAT)))
{ {
...@@ -1058,7 +1058,8 @@ mysql_execute_command(void) ...@@ -1058,7 +1058,8 @@ mysql_execute_command(void)
int res=0; int res=0;
THD *thd=current_thd; THD *thd=current_thd;
LEX *lex= &thd->lex; LEX *lex= &thd->lex;
TABLE_LIST *tables=(TABLE_LIST*) lex->table_list.first; TABLE_LIST *tables=(TABLE_LIST*) lex->select->table_list.first;
SELECT_LEX *Select = lex->select;
DBUG_ENTER("mysql_execute_command"); DBUG_ENTER("mysql_execute_command");
if(table_rules_on && thd->slave_thread && tables && !tables_ok(thd,tables)) if(table_rules_on && thd->slave_thread && tables && !tables_ok(thd,tables))
...@@ -1070,7 +1071,7 @@ mysql_execute_command(void) ...@@ -1070,7 +1071,7 @@ mysql_execute_command(void)
case SQLCOM_SELECT: case SQLCOM_SELECT:
{ {
select_result *result; select_result *result;
if (lex->options & SELECT_DESCRIBE) if (Select->options & SELECT_DESCRIBE)
lex->exchange=0; lex->exchange=0;
if (tables) if (tables)
{ {
...@@ -1088,12 +1089,12 @@ mysql_execute_command(void) ...@@ -1088,12 +1089,12 @@ mysql_execute_command(void)
break; // Error message is given break; // Error message is given
} }
thd->offset_limit=lex->offset_limit; thd->offset_limit=Select->offset_limit;
thd->select_limit=lex->select_limit+lex->offset_limit; thd->select_limit=Select->select_limit+Select->offset_limit;
if (thd->select_limit < lex->select_limit) if (thd->select_limit < Select->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR) if (thd->select_limit == HA_POS_ERROR)
lex->options&= ~OPTION_FOUND_ROWS; Select->options&= ~OPTION_FOUND_ROWS;
if (lex->exchange) if (lex->exchange)
{ {
...@@ -1118,8 +1119,8 @@ mysql_execute_command(void) ...@@ -1118,8 +1119,8 @@ mysql_execute_command(void)
{ {
res= -1; res= -1;
#ifdef DELETE_ITEMS #ifdef DELETE_ITEMS
delete lex->having; delete Select->having;
delete lex->where; delete Select->where;
#endif #endif
break; break;
} }
...@@ -1137,22 +1138,22 @@ mysql_execute_command(void) ...@@ -1137,22 +1138,22 @@ mysql_execute_command(void)
if (!(res=open_and_lock_tables(thd,tables))) if (!(res=open_and_lock_tables(thd,tables)))
{ {
res=mysql_select(thd,tables,lex->item_list, res=mysql_select(thd,tables,Select->item_list,
lex->where, Select->where,
lex->ftfunc_list, Select->ftfunc_list,
(ORDER*) lex->order_list.first, (ORDER*) Select->order_list.first,
(ORDER*) lex->group_list.first, (ORDER*) Select->group_list.first,
lex->having, Select->having,
(ORDER*) lex->proc_list.first, (ORDER*) lex->proc_list.first,
lex->options | thd->options, Select->options | thd->options,
result); result);
if (res) if (res)
result->abort(); result->abort();
} }
delete result; delete result;
#ifdef DELETE_ITEMS #ifdef DELETE_ITEMS
delete lex->having; delete Select->having;
delete lex->where; delete Select->where;
#endif #endif
break; break;
} }
...@@ -1271,7 +1272,7 @@ mysql_execute_command(void) ...@@ -1271,7 +1272,7 @@ mysql_execute_command(void)
res=0; res=0;
break; break;
} }
if (lex->item_list.elements) // With select if (Select->item_list.elements) // With select
{ {
select_result *result; select_result *result;
...@@ -1289,9 +1290,9 @@ mysql_execute_command(void) ...@@ -1289,9 +1290,9 @@ mysql_execute_command(void)
for (table = tables->next ; table ; table=table->next) for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option; table->lock_type= lex->lock_option;
} }
thd->offset_limit=lex->offset_limit; thd->offset_limit=Select->offset_limit;
thd->select_limit=lex->select_limit+lex->offset_limit; thd->select_limit=Select->select_limit+Select->offset_limit;
if (thd->select_limit < lex->select_limit) if (thd->select_limit < Select->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit thd->select_limit= HA_POS_ERROR; // No limit
if (!(res=open_and_lock_tables(thd,tables->next))) if (!(res=open_and_lock_tables(thd,tables->next)))
...@@ -1300,16 +1301,16 @@ mysql_execute_command(void) ...@@ -1300,16 +1301,16 @@ mysql_execute_command(void)
tables->real_name, &lex->create_info, tables->real_name, &lex->create_info,
lex->create_list, lex->create_list,
lex->key_list, lex->key_list,
lex->item_list,lex->duplicates))) Select->item_list,lex->duplicates)))
{ {
res=mysql_select(thd,tables->next,lex->item_list, res=mysql_select(thd,tables->next,Select->item_list,
lex->where, Select->where,
lex->ftfunc_list, Select->ftfunc_list,
(ORDER*) lex->order_list.first, (ORDER*) Select->order_list.first,
(ORDER*) lex->group_list.first, (ORDER*) Select->group_list.first,
lex->having, Select->having,
(ORDER*) lex->proc_list.first, (ORDER*) lex->proc_list.first,
lex->options | thd->options, Select->options | thd->options,
result); result);
if (res) if (res)
result->abort(); result->abort();
...@@ -1364,10 +1365,10 @@ mysql_execute_command(void) ...@@ -1364,10 +1365,10 @@ mysql_execute_command(void)
} }
if (!tables->db) if (!tables->db)
tables->db=thd->db; tables->db=thd->db;
if (!lex->db) if (!Select->db)
lex->db=tables->db; Select->db=tables->db;
if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) || if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) ||
check_access(thd,INSERT_ACL | CREATE_ACL,lex->db,&priv) || check_access(thd,INSERT_ACL | CREATE_ACL,Select->db,&priv) ||
check_merge_table_access(thd, tables->db, check_merge_table_access(thd, tables->db,
(TABLE_LIST *) (TABLE_LIST *)
lex->create_info.merge_list.first)) lex->create_info.merge_list.first))
...@@ -1383,7 +1384,7 @@ mysql_execute_command(void) ...@@ -1383,7 +1384,7 @@ mysql_execute_command(void)
TABLE_LIST tmp_table; TABLE_LIST tmp_table;
bzero((char*) &tmp_table,sizeof(tmp_table)); bzero((char*) &tmp_table,sizeof(tmp_table));
tmp_table.real_name=lex->name; tmp_table.real_name=lex->name;
tmp_table.db=lex->db; tmp_table.db=Select->db;
tmp_table.grant.privilege=priv; tmp_table.grant.privilege=priv;
if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables)) if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables))
goto error; goto error;
...@@ -1393,11 +1394,11 @@ mysql_execute_command(void) ...@@ -1393,11 +1394,11 @@ mysql_execute_command(void)
if (end_active_trans(thd)) if (end_active_trans(thd))
res= -1; res= -1;
else else
res= mysql_alter_table(thd, lex->db, lex->name, res= mysql_alter_table(thd, Select->db, lex->name,
&lex->create_info, &lex->create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
(ORDER *) lex->order_list.first, (ORDER *) Select->order_list.first,
lex->drop_primary, lex->duplicates, lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter); lex->alter_keys_onoff, lex->simple_alter);
break; break;
...@@ -1517,22 +1518,22 @@ mysql_execute_command(void) ...@@ -1517,22 +1518,22 @@ mysql_execute_command(void)
goto error; goto error;
if (grant_option && check_grant(thd,UPDATE_ACL,tables)) if (grant_option && check_grant(thd,UPDATE_ACL,tables))
goto error; goto error;
if (lex->item_list.elements != lex->value_list.elements) if (Select->item_list.elements != lex->value_list.elements)
{ {
send_error(&thd->net,ER_WRONG_VALUE_COUNT); send_error(&thd->net,ER_WRONG_VALUE_COUNT);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
res = mysql_update(thd,tables, res = mysql_update(thd,tables,
lex->item_list, Select->item_list,
lex->value_list, lex->value_list,
lex->where, Select->where,
(ORDER *) lex->order_list.first, (ORDER *) Select->order_list.first,
lex->select_limit, Select->select_limit,
lex->duplicates, lex->duplicates,
lex->lock_option); lex->lock_option);
#ifdef DELETE_ITEMS #ifdef DELETE_ITEMS
delete lex->where; delete Select->where;
#endif #endif
break; break;
case SQLCOM_INSERT: case SQLCOM_INSERT:
...@@ -1576,9 +1577,9 @@ mysql_execute_command(void) ...@@ -1576,9 +1577,9 @@ mysql_execute_command(void)
} }
select_result *result; select_result *result;
thd->offset_limit=lex->offset_limit; thd->offset_limit=Select->offset_limit;
thd->select_limit=lex->select_limit+lex->offset_limit; thd->select_limit=Select->select_limit+Select->offset_limit;
if (thd->select_limit < lex->select_limit) if (thd->select_limit < Select->select_limit)
thd->select_limit= HA_POS_ERROR; // No limit thd->select_limit= HA_POS_ERROR; // No limit
if (check_dup(thd,tables->db,tables->real_name,tables->next)) if (check_dup(thd,tables->db,tables->real_name,tables->next))
...@@ -1598,14 +1599,14 @@ mysql_execute_command(void) ...@@ -1598,14 +1599,14 @@ mysql_execute_command(void)
lex->sql_command == SQLCOM_REPLACE_SELECT ? lex->sql_command == SQLCOM_REPLACE_SELECT ?
DUP_REPLACE : DUP_IGNORE))) DUP_REPLACE : DUP_IGNORE)))
{ {
res=mysql_select(thd,tables->next,lex->item_list, res=mysql_select(thd,tables->next,Select->item_list,
lex->where, Select->where,
lex->ftfunc_list, Select->ftfunc_list,
(ORDER*) lex->order_list.first, (ORDER*) Select->order_list.first,
(ORDER*) lex->group_list.first, (ORDER*) Select->group_list.first,
lex->having, Select->having,
(ORDER*) lex->proc_list.first, (ORDER*) lex->proc_list.first,
lex->options | thd->options, Select->options | thd->options,
result); result);
delete result; delete result;
} }
...@@ -1613,14 +1614,14 @@ mysql_execute_command(void) ...@@ -1613,14 +1614,14 @@ mysql_execute_command(void)
res= -1; res= -1;
} }
#ifdef DELETE_ITEMS #ifdef DELETE_ITEMS
delete lex->having; delete Select->having;
delete lex->where; delete Select->where;
#endif #endif
break; break;
} }
case SQLCOM_TRUNCATE: case SQLCOM_TRUNCATE:
lex->where=0; Select->where=0;
lex->select_limit=HA_POS_ERROR; Select->select_limit=HA_POS_ERROR;
/* Fall through */ /* Fall through */
case SQLCOM_DELETE: case SQLCOM_DELETE:
{ {
...@@ -1634,8 +1635,101 @@ mysql_execute_command(void) ...@@ -1634,8 +1635,101 @@ 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, lex->where, (ORDER*)lex->order_list.first, res = mysql_delete(thd,tables, Select->where, (ORDER*)Select->order_list.first,
lex->select_limit, lex->lock_option, lex->options); Select->select_limit, lex->lock_option, Select->options);
break;
}
case SQLCOM_MULTI_DELETE:
{
TABLE_LIST *aux_tables=(TABLE_LIST *)thd->lex.auxilliary_table_list.first;
multi_delete *result;
if (!tables || !aux_tables ||
check_table_access(thd,SELECT_ACL, tables) ||
check_table_access(thd,DELETE_ACL,aux_tables))
{
res=-1;
goto error;
}
if (!tables->db)
tables->db=thd->db;
if (!aux_tables->db)
aux_tables->db=thd->db;
if ((thd->options & OPTION_SAFE_UPDATES) && !Select->where)
{
send_error(&thd->net,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
res=1; goto error;
}
uint howmuch=0; TABLE_LIST *walk, *auxi;
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next, howmuch++)
{
if (!auxi->db)
auxi->db=thd->db;
if (!auxi->real_name)
auxi->real_name=auxi->name;
for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next)
{
if (!walk->db) walk->db=thd->db;
if (!strcmp(auxi->real_name,walk->real_name) && !strcmp(walk->db,auxi->db))
break;
}
if (!walk)
{
net_printf(&thd->net,ER_NONUNIQ_TABLE,auxi->real_name);
res=-2; goto error;
}
else
auxi->lock_type=walk->lock_type=TL_WRITE;
TABLE form; char path[FN_REFLEN];
(void)sprintf(path,"%s/%s/%s",mysql_data_home,auxi->db,auxi->name);
if (openfrm(path,auxi->name,(uint)HA_TRY_READ_ONLY,COMPUTE_TYPES,0,&form))
{
res=-1; goto error;
}
char *field_name=sql_strdup(form.fieldnames.type_names[0]); VOID(closefrm(&form));
if (add_item_to_list(new Item_field(auxi->db,auxi->name,field_name)))
{
net_printf(&thd->net,ER_WRONG_TABLE_NAME,auxi->name);
res=-1; goto error;
}
}
if (!howmuch--)
{
my_error(ER_NO_TABLES_USED, MYF(0));
res=-2; goto error;
}
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
thd->proc_info="init";
if (open_and_lock_tables(thd,tables))
{
res=-1; goto error;
}
/* This double loop definitely looks like it could have been merged up. But not !!
* Problmes are that we have to first set lock for tables to be deleted to write
* and then to get auxi->table from tables, like below .....
*/
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
{
for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next)
{
if (!strcmp(auxi->real_name,walk->real_name) && !strcmp(walk->db,auxi->db))
break;
}
auxi->table = walk->table;
}
if ((result=new multi_delete(aux_tables,lex->lock_option,howmuch)))
{
res=mysql_select(thd,tables,Select->item_list,
Select->where,Select->ftfunc_list,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
(ORDER *)NULL,
Select->options | thd->options,
result);
delete result;
}
else
res= -1;
close_thread_tables(thd);
break; break;
} }
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
...@@ -1703,7 +1797,7 @@ mysql_execute_command(void) ...@@ -1703,7 +1797,7 @@ mysql_execute_command(void)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
#else #else
{ {
char *db=lex->db ? lex->db : thd->db; char *db=Select->db ? Select->db : thd->db;
if (!db) if (!db)
{ {
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */
...@@ -1718,7 +1812,7 @@ mysql_execute_command(void) ...@@ -1718,7 +1812,7 @@ mysql_execute_command(void)
if (check_access(thd,SELECT_ACL,db,&thd->col_access)) if (check_access(thd,SELECT_ACL,db,&thd->col_access))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
/* grant is checked in mysqld_show_tables */ /* grant is checked in mysqld_show_tables */
if (lex->options & SELECT_DESCRIBE) if (Select->options & SELECT_DESCRIBE)
res= mysqld_extend_show_tables(thd,db, res= mysqld_extend_show_tables(thd,db,
(lex->wild ? lex->wild->ptr() : NullS)); (lex->wild ? lex->wild->ptr() : NullS));
else else
...@@ -1783,7 +1877,7 @@ mysql_execute_command(void) ...@@ -1783,7 +1877,7 @@ mysql_execute_command(void)
} }
#endif #endif
case SQLCOM_CHANGE_DB: case SQLCOM_CHANGE_DB:
mysql_change_db(thd,lex->db); mysql_change_db(thd,Select->db);
break; break;
case SQLCOM_LOAD: case SQLCOM_LOAD:
{ {
...@@ -1807,10 +1901,10 @@ mysql_execute_command(void) ...@@ -1807,10 +1901,10 @@ mysql_execute_command(void)
case SQLCOM_SET_OPTION: case SQLCOM_SET_OPTION:
{ {
uint org_options=thd->options; uint org_options=thd->options;
thd->options=lex->options; thd->options=Select->options;
thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ? thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ?
TL_WRITE_LOW_PRIORITY : TL_WRITE); TL_WRITE_LOW_PRIORITY : TL_WRITE);
thd->default_select_limit=lex->select_limit; thd->default_select_limit=Select->select_limit;
thd->tx_isolation=lex->tx_isolation; thd->tx_isolation=lex->tx_isolation;
if (thd->gemini_spin_retries != lex->gemini_spin_retries) if (thd->gemini_spin_retries != lex->gemini_spin_retries)
{ {
...@@ -1821,7 +1915,7 @@ mysql_execute_command(void) ...@@ -1821,7 +1915,7 @@ mysql_execute_command(void)
thd->options,(long) thd->default_select_limit)); thd->options,(long) thd->default_select_limit));
/* Check if auto_commit mode changed */ /* Check if auto_commit mode changed */
if ((org_options ^ lex->options) & OPTION_NOT_AUTO_COMMIT) if ((org_options ^ Select->options) & OPTION_NOT_AUTO_COMMIT)
{ {
if ((org_options & OPTION_NOT_AUTO_COMMIT)) if ((org_options & OPTION_NOT_AUTO_COMMIT))
{ {
...@@ -1869,6 +1963,8 @@ mysql_execute_command(void) ...@@ -1869,6 +1963,8 @@ mysql_execute_command(void)
} }
if (check_db_used(thd,tables) || end_active_trans(thd)) if (check_db_used(thd,tables) || end_active_trans(thd))
goto error; goto error;
if (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL,tables))
goto error;
thd->in_lock_tables=1; thd->in_lock_tables=1;
if (!(res=open_and_lock_tables(thd,tables))) if (!(res=open_and_lock_tables(thd,tables)))
{ {
...@@ -1929,7 +2025,7 @@ mysql_execute_command(void) ...@@ -1929,7 +2025,7 @@ mysql_execute_command(void)
if (tables && !tables->db) if (tables && !tables->db)
tables->db=thd->db; tables->db=thd->db;
if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
tables && tables->db ? tables->db : lex->db, tables && tables->db ? tables->db : Select->db,
tables ? &tables->grant.privilege : 0, tables ? &tables->grant.privilege : 0,
tables ? 0 : 1)) tables ? 0 : 1))
goto error; goto error;
...@@ -1981,7 +2077,7 @@ mysql_execute_command(void) ...@@ -1981,7 +2077,7 @@ mysql_execute_command(void)
res=1; res=1;
} }
else else
res = mysql_grant(thd, lex->db, lex->users_list, lex->grant, res = mysql_grant(thd, Select->db, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE); lex->sql_command == SQLCOM_REVOKE);
if(!res) if(!res)
{ {
...@@ -2029,8 +2125,8 @@ mysql_execute_command(void) ...@@ -2029,8 +2125,8 @@ mysql_execute_command(void)
if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables)) if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables))
goto error; goto error;
res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir, res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir,
lex->insert_list, lex->ha_rkey_mode, lex->where, lex->insert_list, lex->ha_rkey_mode, Select->where,
lex->select_limit, lex->offset_limit); Select->select_limit, Select->offset_limit);
break; break;
case SQLCOM_BEGIN: case SQLCOM_BEGIN:
...@@ -2291,13 +2387,13 @@ static void ...@@ -2291,13 +2387,13 @@ static void
mysql_init_query(THD *thd) mysql_init_query(THD *thd)
{ {
DBUG_ENTER("mysql_init_query"); DBUG_ENTER("mysql_init_query");
thd->lex.item_list.empty(); thd->lex.select_lex.item_list.empty();
thd->lex.value_list.empty(); thd->lex.value_list.empty();
thd->lex.table_list.elements=0; thd->lex.select_lex.table_list.elements=0;
thd->free_list=0; thd->free_list=0;
thd->lex.select = &thd->lex.select_lex;
thd->lex.table_list.first=0; thd->lex.select_lex.table_list.first=0;
thd->lex.table_list.next= (byte**) &thd->lex.table_list.first; thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first;
thd->fatal_error=0; // Safety thd->fatal_error=0; // Safety
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0; thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
thd->sent_row_count=thd->examined_row_count=0; thd->sent_row_count=thd->examined_row_count=0;
...@@ -2307,17 +2403,19 @@ mysql_init_query(THD *thd) ...@@ -2307,17 +2403,19 @@ mysql_init_query(THD *thd)
void void
mysql_init_select(LEX *lex) mysql_init_select(LEX *lex)
{ {
lex->where=lex->having=0; SELECT_LEX *Select = lex->select;
lex->select_limit=current_thd->default_select_limit; Select->where=Select->having=0;
lex->offset_limit=0L; Select->select_limit=current_thd->default_select_limit;
lex->options=0; Select->offset_limit=0L;
lex->exchange = 0; Select->options=0; Select->linkage=UNSPECIFIED_TYPE;
Select->select_number = 0; lex->exchange = 0;
lex->proc_list.first=0; lex->proc_list.first=0;
lex->order_list.elements=lex->group_list.elements=0; Select->order_list.elements=Select->group_list.elements=0;
lex->order_list.first=0; Select->order_list.first=0;
lex->order_list.next= (byte**) &lex->order_list.first; Select->order_list.next= (byte**) &Select->order_list.first;
lex->group_list.first=0; Select->group_list.first=0;
lex->group_list.next= (byte**) &lex->group_list.first; Select->group_list.next= (byte**) &Select->group_list.first;
Select->next = (SELECT_LEX *)NULL;
} }
...@@ -2737,7 +2835,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -2737,7 +2835,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
if (flags != TL_IGNORE) if (flags != TL_IGNORE)
{ {
for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.table_list.first ; tables ; for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ; tables ;
tables=tables->next) tables=tables->next)
{ {
if (!strcmp(alias_str,tables->name) && if (!strcmp(alias_str,tables->name) &&
...@@ -2749,7 +2847,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -2749,7 +2847,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
} }
} }
} }
link_in_list(&thd->lex.table_list,(byte*) ptr,(byte**) &ptr->next); link_in_list(&thd->lex.select->table_list,(byte*) ptr,(byte**) &ptr->next);
DBUG_RETURN(ptr); DBUG_RETURN(ptr);
} }
......
...@@ -2478,7 +2478,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2478,7 +2478,7 @@ make_join_readinfo(JOIN *join,uint options)
/* These init changes read_record */ /* These init changes read_record */
if (tab->use_quick == 2) if (tab->use_quick == 2)
{ {
join->thd->lex.options|=QUERY_NO_GOOD_INDEX_USED; join->thd->lex.select_lex.options|=QUERY_NO_GOOD_INDEX_USED;
tab->read_first_record= join_init_quick_read_record; tab->read_first_record= join_init_quick_read_record;
statistic_increment(select_range_check_count, &LOCK_status); statistic_increment(select_range_check_count, &LOCK_status);
} }
...@@ -2493,7 +2493,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2493,7 +2493,7 @@ make_join_readinfo(JOIN *join,uint options)
} }
else else
{ {
join->thd->lex.options|=QUERY_NO_INDEX_USED; join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
statistic_increment(select_scan_count, &LOCK_status); statistic_increment(select_scan_count, &LOCK_status);
} }
} }
...@@ -2505,7 +2505,7 @@ make_join_readinfo(JOIN *join,uint options) ...@@ -2505,7 +2505,7 @@ make_join_readinfo(JOIN *join,uint options)
} }
else else
{ {
join->thd->lex.options|=QUERY_NO_INDEX_USED; join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
statistic_increment(select_full_join_count, &LOCK_status); statistic_increment(select_full_join_count, &LOCK_status);
} }
} }
...@@ -3920,7 +3920,7 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error, ...@@ -3920,7 +3920,7 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
thd->proc_info="converting HEAP to MyISAM"; thd->proc_info="converting HEAP to MyISAM";
if (create_myisam_tmp_table(&new_table,param, if (create_myisam_tmp_table(&new_table,param,
thd->lex.options | thd->options)) thd->lex.select_lex.options | thd->options))
goto err2; goto err2;
if (open_tmp_table(&new_table)) if (open_tmp_table(&new_table))
goto err1; goto err1;
...@@ -6647,7 +6647,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -6647,7 +6647,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
DBUG_ENTER("select_describe"); DBUG_ENTER("select_describe");
/* Don't log this into the slow query log */ /* Don't log this into the slow query log */
join->thd->lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED); join->thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
field_list.push_back(new Item_empty_string("table",NAME_LEN)); field_list.push_back(new Item_empty_string("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10)); field_list.push_back(new Item_empty_string("type",10));
field_list.push_back(item=new Item_empty_string("possible_keys", field_list.push_back(item=new Item_empty_string("possible_keys",
...@@ -6806,7 +6806,7 @@ static void describe_info(THD *thd, const char *info) ...@@ -6806,7 +6806,7 @@ static void describe_info(THD *thd, const char *info)
String *packet= &thd->packet; String *packet= &thd->packet;
/* Don't log this into the slow query log */ /* Don't log this into the slow query log */
thd->lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED); thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
field_list.push_back(new Item_empty_string("Comment",80)); field_list.push_back(new Item_empty_string("Comment",80));
if (send_fields(thd,field_list,1)) if (send_fields(thd,field_list,1))
return; /* purecov: inspected */ return; /* purecov: inspected */
......
...@@ -128,7 +128,7 @@ int mysql_update(THD *thd, ...@@ -128,7 +128,7 @@ int mysql_update(THD *thd,
/* If running in safe sql mode, don't allow updates without keys */ /* If running in safe sql mode, don't allow updates without keys */
if (!table->quick_keys) if (!table->quick_keys)
{ {
thd->lex.options|=QUERY_NO_INDEX_USED; thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR) if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
{ {
delete select; delete select;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define YYINITDEPTH 100 #define YYINITDEPTH 100
#define YYMAXDEPTH 3200 /* Because of 64K stack */ #define YYMAXDEPTH 3200 /* Because of 64K stack */
#define Lex current_lex #define Lex current_lex
#define Select Lex->select
#include "mysql_priv.h" #include "mysql_priv.h"
#include "slave.h" #include "slave.h"
#include "sql_acl.h" #include "sql_acl.h"
...@@ -541,7 +542,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -541,7 +542,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
END_OF_INPUT single_multi table_multi_delete table_sin_wild
END_OF_INPUT
%type <NONE> %type <NONE>
'-' '+' '*' '/' '%' '(' ')' '-' '+' '*' '/' '%' '(' ')'
...@@ -762,12 +764,12 @@ create_table_option: ...@@ -762,12 +764,12 @@ create_table_option:
{ {
/* Move the union list to the merge_list */ /* Move the union list to the merge_list */
LEX *lex=Lex; LEX *lex=Lex;
TABLE_LIST *table_list= (TABLE_LIST*) lex->table_list.first; TABLE_LIST *table_list= (TABLE_LIST*) Select->table_list.first;
lex->create_info.merge_list= lex->table_list; lex->create_info.merge_list= Select->table_list;
lex->create_info.merge_list.elements--; lex->create_info.merge_list.elements--;
lex->create_info.merge_list.first= (byte*) (table_list->next); lex->create_info.merge_list.first= (byte*) (table_list->next);
lex->table_list.elements=1; Select->table_list.elements=1;
lex->table_list.next= (byte**) &(table_list->next); Select->table_list.next= (byte**) &(table_list->next);
table_list->next=0; table_list->next=0;
lex->create_info.used_fields|= HA_CREATE_USED_UNION; lex->create_info.used_fields|= HA_CREATE_USED_UNION;
} }
...@@ -1062,10 +1064,10 @@ alter: ...@@ -1062,10 +1064,10 @@ alter:
lex->col_list.empty(); lex->col_list.empty();
lex->drop_list.empty(); lex->drop_list.empty();
lex->alter_list.empty(); lex->alter_list.empty();
lex->order_list.elements=0; Select->order_list.elements=0;
lex->order_list.first=0; Select->order_list.first=0;
lex->order_list.next= (byte**) &lex->order_list.first; Select->order_list.next= (byte**) &Select->order_list.first;
lex->db=lex->name=0; Select->db=lex->name=0;
bzero((char*) &lex->create_info,sizeof(lex->create_info)); bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.db_type= DB_TYPE_DEFAULT;
lex->alter_keys_onoff=LEAVE_AS_IS; lex->alter_keys_onoff=LEAVE_AS_IS;
...@@ -1116,7 +1118,7 @@ alter_list_item: ...@@ -1116,7 +1118,7 @@ alter_list_item:
| 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->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->db=$4->db.str ; Lex->name= $4->table.str; Lex->simple_alter=0; } { 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; }
...@@ -1277,13 +1279,13 @@ select_option_list: ...@@ -1277,13 +1279,13 @@ select_option_list:
| select_option | select_option
select_option: select_option:
STRAIGHT_JOIN { Lex->options|= SELECT_STRAIGHT_JOIN; } STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
| HIGH_PRIORITY { Lex->lock_option= TL_READ_HIGH_PRIORITY; } | HIGH_PRIORITY { Lex->lock_option= TL_READ_HIGH_PRIORITY; }
| DISTINCT { Lex->options|= SELECT_DISTINCT; } | DISTINCT { Select->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Lex->options|= SELECT_SMALL_RESULT; } | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { Lex->options|= SELECT_BIG_RESULT; } | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
| SQL_BUFFER_RESULT { Lex->options|= OPTION_BUFFER_RESULT; } | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; }
| SQL_CALC_FOUND_ROWS { Lex->options|= OPTION_FOUND_ROWS; } | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; }
| ALL {} | ALL {}
select_lock_type: select_lock_type:
...@@ -1470,10 +1472,10 @@ simple_expr: ...@@ -1470,10 +1472,10 @@ simple_expr:
| '(' expr ')' { $$= $2; } | '(' expr ')' { $$= $2; }
| '{' ident expr '}' { $$= $3; } | '{' ident expr '}' { $$= $3; }
| MATCH '(' ident_list ')' AGAINST '(' expr ')' | MATCH '(' ident_list ')' AGAINST '(' expr ')'
{ Lex->ftfunc_list.push_back( { Select->ftfunc_list.push_back(
(Item_func_match *)($$=new Item_func_match(*$3,$7))); } (Item_func_match *)($$=new Item_func_match(*$3,$7))); }
| MATCH ident_list AGAINST '(' expr ')' | MATCH ident_list AGAINST '(' expr ')'
{ Lex->ftfunc_list.push_back( { Select->ftfunc_list.push_back(
(Item_func_match *)($$=new Item_func_match(*$2,$5))); } (Item_func_match *)($$=new Item_func_match(*$2,$5))); }
| BINARY expr %prec NEG { $$= new Item_func_binary($2); } | BINARY expr %prec NEG { $$= new Item_func_binary($2); }
| CASE_SYM opt_expr WHEN_SYM when_list opt_else END | CASE_SYM opt_expr WHEN_SYM when_list opt_else END
...@@ -1704,30 +1706,30 @@ sum_expr: ...@@ -1704,30 +1706,30 @@ sum_expr:
{ $$=new Item_sum_sum($3); } { $$=new Item_sum_sum($3); }
in_sum_expr: in_sum_expr:
{ Lex->in_sum_expr++ } { Select->in_sum_expr++ }
expr expr
{ {
Lex->in_sum_expr--; Select->in_sum_expr--;
$$=$2; $$=$2;
} }
expr_list: expr_list:
{ Lex->expr_list.push_front(new List<Item>); } { Select->expr_list.push_front(new List<Item>); }
expr_list2 expr_list2
{ $$= Lex->expr_list.pop(); } { $$= Select->expr_list.pop(); }
expr_list2: expr_list2:
expr { Lex->expr_list.head()->push_back($1); } expr { Select->expr_list.head()->push_back($1); }
| expr_list2 ',' expr { Lex->expr_list.head()->push_back($3); } | expr_list2 ',' expr { Select->expr_list.head()->push_back($3); }
ident_list: ident_list:
{ Lex->expr_list.push_front(new List<Item>); } { Select->expr_list.push_front(new List<Item>); }
ident_list2 ident_list2
{ $$= Lex->expr_list.pop(); } { $$= Select->expr_list.pop(); }
ident_list2: ident_list2:
simple_ident { Lex->expr_list.head()->push_back($1); } simple_ident { Select->expr_list.head()->push_back($1); }
| ident_list2 ',' simple_ident { Lex->expr_list.head()->push_back($3); } | ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); }
opt_expr: opt_expr:
/* empty */ { $$= NULL; } /* empty */ { $$= NULL; }
...@@ -1738,20 +1740,20 @@ opt_else: ...@@ -1738,20 +1740,20 @@ opt_else:
| ELSE expr { $$= $2; } | ELSE expr { $$= $2; }
when_list: when_list:
{ Lex->when_list.push_front(new List<Item>) } { Select->when_list.push_front(new List<Item>) }
when_list2 when_list2
{ $$= Lex->when_list.pop(); } { $$= Select->when_list.pop(); }
when_list2: when_list2:
expr THEN_SYM expr expr THEN_SYM expr
{ {
Lex->when_list.head()->push_back($1); Select->when_list.head()->push_back($1);
Lex->when_list.head()->push_back($3); Select->when_list.head()->push_back($3);
} }
| when_list2 WHEN_SYM expr THEN_SYM expr | when_list2 WHEN_SYM expr THEN_SYM expr
{ {
Lex->when_list.head()->push_back($3); Select->when_list.head()->push_back($3);
Lex->when_list.head()->push_back($5); Select->when_list.head()->push_back($5);
} }
opt_pad: opt_pad:
...@@ -1766,15 +1768,15 @@ join_table_list: ...@@ -1766,15 +1768,15 @@ 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
{ Lex->db1=$1->db; Lex->table1=$1->name; { Select->db1=$1->db; Select->table1=$1->name;
Lex->db2=$4->db; Lex->table2=$4->name; } Select->db2=$4->db; Select->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
{ Lex->db1=$1->db; Lex->table1=$1->name; { Select->db1=$1->db; Select->table1=$1->name;
Lex->db2=$5->db; Lex->table2=$5->name; } Select->db2=$5->db; Select->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
...@@ -1782,8 +1784,8 @@ join_table_list: ...@@ -1782,8 +1784,8 @@ 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
{ Lex->db1=$1->db; Lex->table1=$1->name; { Select->db1=$1->db; Select->table1=$1->name;
Lex->db2=$5->db; Lex->table2=$5->name; } Select->db2=$5->db; Select->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
...@@ -1797,10 +1799,10 @@ normal_join: ...@@ -1797,10 +1799,10 @@ normal_join:
| CROSS JOIN_SYM {} | CROSS JOIN_SYM {}
join_table: join_table:
{ Lex->use_index_ptr=Lex->ignore_index_ptr=0; } { Select->use_index_ptr=Select->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, Lex->use_index_ptr, { if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, Select->use_index_ptr,
Lex->ignore_index_ptr))) YYABORT; } Select->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; }
...@@ -1811,30 +1813,30 @@ opt_outer: ...@@ -1811,30 +1813,30 @@ opt_outer:
opt_key_definition: opt_key_definition:
/* empty */ {} /* empty */ {}
| USE_SYM key_usage_list | USE_SYM key_usage_list
{ Lex->use_index= *$2; Lex->use_index_ptr= &Lex->use_index; } { Select->use_index= *$2; Select->use_index_ptr= &Select->use_index; }
| IGNORE_SYM key_usage_list | IGNORE_SYM key_usage_list
{ Lex->ignore_index= *$2; Lex->ignore_index_ptr= &Lex->ignore_index;} { Select->ignore_index= *$2; Select->ignore_index_ptr= &Select->ignore_index;}
key_usage_list: key_usage_list:
key_or_index { Lex->interval_list.empty() } '(' key_usage_list2 ')' key_or_index { Select->interval_list.empty() } '(' key_usage_list2 ')'
{ $$= &Lex->interval_list; } { $$= &Select->interval_list; }
key_usage_list2: key_usage_list2:
key_usage_list2 ',' ident key_usage_list2 ',' ident
{ Lex->interval_list.push_back(new String((const char*) $3.str,$3.length)); } { Select->interval_list.push_back(new String((const char*) $3.str,$3.length)); }
| ident | ident
{ Lex->interval_list.push_back(new String((const char*) $1.str,$1.length)); } { Select->interval_list.push_back(new String((const char*) $1.str,$1.length)); }
| PRIMARY_SYM | PRIMARY_SYM
{ Lex->interval_list.push_back(new String("PRIMARY",7)); } { Select->interval_list.push_back(new String("PRIMARY",7)); }
using_list: using_list:
ident ident
{ if (!($$= new Item_func_eq(new Item_field(Lex->db1,Lex->table1, $1.str), new Item_field(Lex->db2,Lex->table2,$1.str)))) { if (!($$= new Item_func_eq(new Item_field(Select->db1,Select->table1, $1.str), new Item_field(Select->db2,Select->table2,$1.str))))
YYABORT; YYABORT;
} }
| using_list ',' ident | using_list ',' ident
{ {
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(Lex->db1,Lex->table1,$3.str), new Item_field(Lex->db2,Lex->table2,$3.str)), $1))) 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)))
YYABORT; YYABORT;
} }
...@@ -1865,13 +1867,13 @@ opt_table_alias: ...@@ -1865,13 +1867,13 @@ opt_table_alias:
where_clause: where_clause:
/* empty */ { Lex->where= 0; } /* empty */ { Select->where= 0; }
| WHERE expr { Lex->where= $2; } | WHERE expr { Select->where= $2; }
having_clause: having_clause:
/* empty */ /* empty */
| HAVING { Lex->create_refs=1; } expr | HAVING { Select->create_refs=1; } expr
{ Lex->having= $3; Lex->create_refs=0; } { Select->having= $3; Select->create_refs=0; }
opt_escape: opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; } ESCAPE_SYM TEXT_STRING { $$= $2.str; }
...@@ -1901,7 +1903,7 @@ opt_order_clause: ...@@ -1901,7 +1903,7 @@ opt_order_clause:
| order_clause | order_clause
order_clause: order_clause:
ORDER_SYM BY { Lex->sort_default=1; } order_list ORDER_SYM BY { Select->sort_default=1; } order_list
order_list: order_list:
order_list ',' order_ident order_dir order_list ',' order_ident order_dir
...@@ -1911,29 +1913,29 @@ order_list: ...@@ -1911,29 +1913,29 @@ order_list:
order_dir: order_dir:
/* empty */ { $$ = 1; } /* empty */ { $$ = 1; }
| ASC { $$ = Lex->sort_default=1; } | ASC { $$ = Select->sort_default=1; }
| DESC { $$ = Lex->sort_default=0; } | DESC { $$ = Select->sort_default=0; }
limit_clause: limit_clause:
/* empty */ /* empty */
{ {
Lex->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ? Select->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ?
1 : current_thd->default_select_limit; 1 : current_thd->default_select_limit;
Lex->offset_limit= 0L; Select->offset_limit= 0L;
} }
| LIMIT ULONG_NUM | LIMIT ULONG_NUM
{ Lex->select_limit= $2; Lex->offset_limit=0L; } { Select->select_limit= $2; Select->offset_limit=0L; }
| LIMIT ULONG_NUM ',' ULONG_NUM | LIMIT ULONG_NUM ',' ULONG_NUM
{ Lex->select_limit= $4; Lex->offset_limit=$2; } { Select->select_limit= $4; Select->offset_limit=$2; }
delete_limit_clause: delete_limit_clause:
/* empty */ /* empty */
{ {
Lex->select_limit= HA_POS_ERROR; Select->select_limit= HA_POS_ERROR;
} }
| LIMIT ULONGLONG_NUM | LIMIT ULONGLONG_NUM
{ Lex->select_limit= (ha_rows) $2; } { Select->select_limit= (ha_rows) $2; }
ULONG_NUM: ULONG_NUM:
NUM { $$= strtoul($1.str,NULL,10); } NUM { $$= strtoul($1.str,NULL,10); }
...@@ -2156,9 +2158,9 @@ update: ...@@ -2156,9 +2158,9 @@ update:
delete_limit_clause delete_limit_clause
{ {
Lex->sql_command = SQLCOM_UPDATE; Lex->sql_command = SQLCOM_UPDATE;
Lex->order_list.elements=0; Select->order_list.elements=0;
Lex->order_list.first=0; Select->order_list.first=0;
Lex->order_list.next= (byte**) &Lex->order_list.first; Select->order_list.next= (byte**) &Select->order_list.first;
} }
update_list: update_list:
...@@ -2182,22 +2184,49 @@ opt_low_priority: ...@@ -2182,22 +2184,49 @@ opt_low_priority:
delete: delete:
DELETE_SYM DELETE_SYM
{ {
Lex->sql_command= SQLCOM_DELETE; Lex->options=0; Lex->sql_command= SQLCOM_DELETE; Select->options=0;
Lex->lock_option= current_thd->update_lock_default; Lex->lock_option= current_thd->update_lock_default;
Lex->order_list.elements=0; Select->order_list.elements=0;
Lex->order_list.first=0; Select->order_list.first=0;
Lex->order_list.next= (byte**) &Lex->order_list.first; Select->order_list.next= (byte**) &Select->order_list.first;
} }
opt_delete_options FROM table_name opt_delete_options single_multi {}
where_clause opt_order_clause delete_limit_clause
single_multi:
FROM table_name where_clause opt_order_clause delete_limit_clause {}
| table_multi_delete
{
LEX *lex=Lex;
Lex->sql_command = SQLCOM_MULTI_DELETE;
mysql_init_select(lex);
Select->select_limit=HA_POS_ERROR;
lex->auxilliary_table_list.elements=0;
lex->auxilliary_table_list.first=0;
lex->auxilliary_table_list.next= (byte**) &(lex->auxilliary_table_list.first);
}
FROM
{
current_thd->lex.auxilliary_table_list=current_thd->lex.select_lex.table_list;
current_thd->lex.select->table_list.elements=0;
current_thd->lex.select->table_list.first=0;
current_thd->lex.select->table_list.next= (byte**) &(current_thd->lex.select->table_list.first);
} join_table_list where_clause
table_multi_delete:
table_sin_wild {}
| table_multi_delete ',' table_sin_wild {}
table_sin_wild:
ident '.' '*' { if (!add_table_to_list(new Table_ident($1),NULL,1,TL_WRITE)) YYABORT; }
| ident '.' ident '.' '*'
{ if (!add_table_to_list(new Table_ident($1,$3,0),NULL,1,TL_WRITE)) YYABORT;}
opt_delete_options: opt_delete_options:
/* empty */ {} /* empty */ {}
| opt_delete_option opt_delete_options {} | opt_delete_option opt_delete_options {}
opt_delete_option: opt_delete_option:
QUICK { Lex->options|= OPTION_QUICK; } QUICK { Select->options|= OPTION_QUICK; }
| LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
truncate: truncate:
...@@ -2205,10 +2234,10 @@ truncate: ...@@ -2205,10 +2234,10 @@ truncate:
{ {
LEX* lex = Lex; LEX* lex = Lex;
lex->sql_command= SQLCOM_TRUNCATE; lex->sql_command= SQLCOM_TRUNCATE;
lex->options=0; Select->options=0;
lex->order_list.elements=0; Select->order_list.elements=0;
lex->order_list.first=0; Select->order_list.first=0;
lex->order_list.next= (byte**) &lex->order_list.first; Select->order_list.next= (byte**) &Select->order_list.first;
lex->lock_option= current_thd->update_lock_default; } lex->lock_option= current_thd->update_lock_default; }
...@@ -2224,16 +2253,16 @@ show_param: ...@@ -2224,16 +2253,16 @@ 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; Lex->db= $2; Lex->options=0;} { Lex->sql_command= SQLCOM_SHOW_TABLES; Select->db= $2; Select->options=0;}
| TABLE_SYM STATUS_SYM opt_db wild | TABLE_SYM STATUS_SYM opt_db wild
{ Lex->sql_command= SQLCOM_SHOW_TABLES; { Lex->sql_command= SQLCOM_SHOW_TABLES;
Lex->options|= SELECT_DESCRIBE; Select->options|= SELECT_DESCRIBE;
Lex->db= $3; Select->db= $3;
} }
| OPEN_SYM TABLES opt_db wild | OPEN_SYM TABLES opt_db wild
{ Lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; { Lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
Lex->db= $3; Select->db= $3;
Lex->options=0; Select->options=0;
} }
| opt_full COLUMNS FROM table_ident opt_db wild | opt_full COLUMNS FROM table_ident opt_db wild
{ {
...@@ -2304,7 +2333,7 @@ describe: ...@@ -2304,7 +2333,7 @@ describe:
YYABORT; YYABORT;
} }
opt_describe_column opt_describe_column
| describe_command select { Lex->options|= SELECT_DESCRIBE }; | describe_command select { Select->options|= SELECT_DESCRIBE };
describe_command: describe_command:
...@@ -2375,7 +2404,7 @@ kill: ...@@ -2375,7 +2404,7 @@ kill:
/* change database */ /* change database */
use: USE_SYM ident use: USE_SYM ident
{ Lex->sql_command=SQLCOM_CHANGE_DB; Lex->db= $2.str; } { Lex->sql_command=SQLCOM_CHANGE_DB; Select->db= $2.str; }
/* import, export of files */ /* import, export of files */
...@@ -2503,13 +2532,13 @@ order_ident: ...@@ -2503,13 +2532,13 @@ order_ident:
simple_ident: simple_ident:
ident ident
{ $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); } { $$ = !Select->create_refs || Select->in_sum_expr > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str); }
| ident '.' ident | ident '.' ident
{ $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str); } { $$ = !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); }
| '.' ident '.' ident | '.' ident '.' ident
{ $$ = !Lex->create_refs || Lex->in_sum_expr > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str); } { $$ = !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); }
| ident '.' ident '.' ident | ident '.' ident '.' ident
{ $$ = !Lex->create_refs || Lex->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->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); }
field_ident: field_ident:
...@@ -2682,8 +2711,8 @@ set: ...@@ -2682,8 +2711,8 @@ set:
{ {
THD *thd=current_thd; THD *thd=current_thd;
Lex->sql_command= SQLCOM_SET_OPTION; Lex->sql_command= SQLCOM_SET_OPTION;
Lex->options=thd->options; Select->options=thd->options;
Lex->select_limit=thd->default_select_limit; Select->select_limit=thd->default_select_limit;
Lex->gemini_spin_retries=thd->gemini_spin_retries; Lex->gemini_spin_retries=thd->gemini_spin_retries;
Lex->tx_isolation=thd->tx_isolation; Lex->tx_isolation=thd->tx_isolation;
} }
...@@ -2701,30 +2730,30 @@ option_value: ...@@ -2701,30 +2730,30 @@ option_value:
set_option equal NUM set_option equal NUM
{ {
if (atoi($3.str) == 0) if (atoi($3.str) == 0)
Lex->options&= ~$1; Select->options&= ~$1;
else else
Lex->options|= $1; Select->options|= $1;
} }
| set_isolation | set_isolation
| AUTOCOMMIT equal NUM | AUTOCOMMIT equal NUM
{ {
if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */ if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */
Lex->options&= ~(OPTION_NOT_AUTO_COMMIT); Select->options&= ~(OPTION_NOT_AUTO_COMMIT);
else else
Lex->options|= OPTION_NOT_AUTO_COMMIT; Select->options|= OPTION_NOT_AUTO_COMMIT;
} }
| SQL_SELECT_LIMIT equal ULONG_NUM | SQL_SELECT_LIMIT equal ULONG_NUM
{ {
Lex->select_limit= $3; Select->select_limit= $3;
} }
| SQL_SELECT_LIMIT equal DEFAULT | SQL_SELECT_LIMIT equal DEFAULT
{ {
Lex->select_limit= HA_POS_ERROR; Select->select_limit= HA_POS_ERROR;
} }
| SQL_MAX_JOIN_SIZE equal ULONG_NUM | SQL_MAX_JOIN_SIZE equal ULONG_NUM
{ {
current_thd->max_join_size= $3; current_thd->max_join_size= $3;
Lex->options&= ~OPTION_BIG_SELECTS; Select->options&= ~OPTION_BIG_SELECTS;
} }
| SQL_MAX_JOIN_SIZE equal DEFAULT | SQL_MAX_JOIN_SIZE equal DEFAULT
{ {
...@@ -2952,7 +2981,7 @@ revoke: ...@@ -2952,7 +2981,7 @@ revoke:
Lex->users_list.empty(); Lex->users_list.empty();
Lex->columns.empty(); Lex->columns.empty();
Lex->grant= Lex->grant_tot_col=0; Lex->grant= Lex->grant_tot_col=0;
Lex->db=0; Select->db=0;
} }
grant_privileges ON opt_table FROM user_list grant_privileges ON opt_table FROM user_list
...@@ -2963,7 +2992,7 @@ grant: ...@@ -2963,7 +2992,7 @@ grant:
Lex->users_list.empty(); Lex->users_list.empty();
Lex->columns.empty(); Lex->columns.empty();
Lex->grant= Lex->grant_tot_col=0; Lex->grant= Lex->grant_tot_col=0;
Lex->db=0; 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
...@@ -3003,7 +3032,7 @@ grant_privilege: ...@@ -3003,7 +3032,7 @@ grant_privilege:
opt_table: opt_table:
'*' '*'
{ {
Lex->db=current_thd->db; Select->db=current_thd->db;
if (Lex->grant == UINT_MAX) if (Lex->grant == UINT_MAX)
Lex->grant = DB_ACLS & ~GRANT_ACL; Lex->grant = DB_ACLS & ~GRANT_ACL;
else if (Lex->columns.elements) else if (Lex->columns.elements)
...@@ -3014,7 +3043,7 @@ opt_table: ...@@ -3014,7 +3043,7 @@ opt_table:
} }
| ident '.' '*' | ident '.' '*'
{ {
Lex->db = $1.str; Select->db = $1.str;
if (Lex->grant == UINT_MAX) if (Lex->grant == UINT_MAX)
Lex->grant = DB_ACLS & ~GRANT_ACL; Lex->grant = DB_ACLS & ~GRANT_ACL;
else if (Lex->columns.elements) else if (Lex->columns.elements)
...@@ -3025,7 +3054,7 @@ opt_table: ...@@ -3025,7 +3054,7 @@ opt_table:
} }
| '*' '.' '*' | '*' '.' '*'
{ {
Lex->db = NULL; Select->db = NULL;
if (Lex->grant == UINT_MAX) if (Lex->grant == UINT_MAX)
Lex->grant = GLOBAL_ACLS & ~GRANT_ACL; Lex->grant = GLOBAL_ACLS & ~GRANT_ACL;
else if (Lex->columns.elements) else if (Lex->columns.elements)
......
...@@ -34,11 +34,14 @@ ...@@ -34,11 +34,14 @@
#include "mysql_priv.h" #include "mysql_priv.h"
#include "sql_sort.h" #include "sql_sort.h"
Unique::Unique(qsort_cmp2 comp_func, uint size, ulong max_in_memory_size_arg)
Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
uint size, ulong max_in_memory_size_arg)
:max_in_memory_size(max_in_memory_size_arg),elements(0) :max_in_memory_size(max_in_memory_size_arg),elements(0)
{ {
my_b_clear(&file); my_b_clear(&file);
init_tree(&tree, max_in_memory_size / 16, size, comp_func, 0, 0); init_tree(&tree, max_in_memory_size / 16, size, comp_func, 0, 0);
tree.cmp_arg=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);
...@@ -69,12 +72,14 @@ bool Unique::flush() ...@@ -69,12 +72,14 @@ bool Unique::flush()
} }
int unique_write_to_file(gptr key, Unique *unique, element_count count) int unique_write_to_file(gptr key, element_count count, Unique *unique)
{ {
if (!my_b_inited(&unique->file) && open_cached_file(&unique->file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
return 1;
return my_b_write(&unique->file, key, unique->tree.size_of_element) ? 1 : 0; return my_b_write(&unique->file, key, unique->tree.size_of_element) ? 1 : 0;
} }
int unique_write_to_ptrs(gptr key, Unique *unique, element_count count) int unique_write_to_ptrs(gptr key, element_count count, Unique *unique)
{ {
memcpy(unique->record_pointers, key, unique->tree.size_of_element); memcpy(unique->record_pointers, key, unique->tree.size_of_element);
unique->record_pointers+=unique->tree.size_of_element; unique->record_pointers+=unique->tree.size_of_element;
...@@ -109,7 +114,7 @@ bool Unique::get(TABLE *table) ...@@ -109,7 +114,7 @@ bool Unique::get(TABLE *table)
IO_CACHE *outfile=table->io_cache, tempfile; IO_CACHE *outfile=table->io_cache, tempfile;
BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer; BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer;
uint maxbuffer= file_ptrs.elements; uint maxbuffer= file_ptrs.elements - 1; // I added -1 .....
uchar *sort_buffer; uchar *sort_buffer;
my_off_t save_pos; my_off_t save_pos;
bool error=1; bool error=1;
...@@ -117,13 +122,16 @@ bool Unique::get(TABLE *table) ...@@ -117,13 +122,16 @@ bool Unique::get(TABLE *table)
my_b_clear(&tempfile); my_b_clear(&tempfile);
/* Open cached file if it isn't open */ /* Open cached file if it isn't open */
if (!outfile) outfile= (IO_CACHE *) sql_calloc(sizeof(IO_CACHE));
if (! my_b_inited(outfile) && if (! 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,
MYF(MY_WME))) MYF(MY_WME)))
return 1; return 1;
reinit_io_cache(outfile,WRITE_CACHE,0L,0,0); reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
sort_param.keys=elements; // sort_param.keys=elements;
sort_param.max_rows= elements;
sort_param.examined_rows=0;
sort_param.sort_form=table; sort_param.sort_form=table;
sort_param.sort_length=sort_param.ref_length=tree.size_of_element; sort_param.sort_length=sort_param.ref_length=tree.size_of_element;
sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.keys= max_in_memory_size / sort_param.sort_length;
......
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