diff options
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | sql/filesort.cc | 3 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item_sum.cc | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/sql_class.h | 37 | ||||
-rw-r--r-- | sql/sql_delete.cc | 551 | ||||
-rw-r--r-- | sql/sql_lex.cc | 10 | ||||
-rw-r--r-- | sql/sql_lex.h | 50 | ||||
-rw-r--r-- | sql/sql_parse.cc | 270 | ||||
-rw-r--r-- | sql/sql_select.cc | 12 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 247 | ||||
-rw-r--r-- | sql/uniques.cc | 22 |
14 files changed, 970 insertions, 245 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 11ad15ceb0b..040324b8f8c 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -15,3 +15,4 @@ serg@serg.mysql.com tim@threads.polyesthetic.msg tim@work.mysql.com tonu@x3.internalnet +Sinisa@sinisa.nasamreza.org diff --git a/sql/filesort.cc b/sql/filesort.cc index e5e6c7d97c8..d0146e5e56a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -739,7 +739,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, buffpek=(BUFFPEK*) queue_top(&queue); 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; memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length); } diff --git a/sql/item.cc b/sql/item.cc index b268c5eb928..44bbf9a9cbc 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -561,7 +561,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) { 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; max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 879c27178e5..c42b934297e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -883,7 +883,7 @@ bool Item_sum_count_distinct::setup(THD *thd) tmp_table_param->cleanup(); } 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; table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->no_rows=1; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c4967372bb0..dbe2ab78c60 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -667,7 +667,7 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length); 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) { @@ -675,11 +675,11 @@ inline bool add_value_to_list(Item *value) } 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) { - 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) { diff --git a/sql/sql_class.h b/sql/sql_class.h index d32fa0ed743..19ac075697b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -465,6 +465,32 @@ public: 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 { protected: @@ -578,19 +604,18 @@ class Unique :public Sql_alloc public: 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(); inline bool Unique::unique_add(gptr ptr) { if (tree.elements_in_tree > max_elements && flush()) return 1; - return tree_insert(&tree,ptr,0); + return !tree_insert(&tree,ptr,0); } bool get(TABLE *table); - friend int unique_write_to_file(gptr key, Unique *unique, - element_count count); - friend int unique_write_to_ptrs(gptr key, Unique *unique, - element_count count); + friend int unique_write_to_file(gptr key, element_count count, Unique *unique); + friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique); }; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 85b1c947460..4f3fe80473e 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -150,8 +150,8 @@ int mysql_delete(THD *thd, (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))); #ifdef HAVE_INNOBASE_DB /* We need to add code to not generate table based on the table type */ - if (!innodb_skip) - use_generate_table=0; // Innodb can't use re-generate table + if (!innobase_skip) + use_generate_table=0; // Innobase can't use re-generate table #endif if (use_generate_table && ! thd->open_tables) { @@ -186,7 +186,7 @@ int mysql_delete(THD *thd, /* If running in safe sql mode, don't allow updates without 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) { delete select; @@ -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; + +} diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0a1ee0649c4..19f904939f0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -142,11 +142,11 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->next_state=STATE_START; lex->end_of_query=(lex->ptr=buf)+length; lex->yylineno = 1; - lex->create_refs=lex->in_comment=0; + lex->select->create_refs=lex->in_comment=0; lex->length=0; - lex->in_sum_expr=0; - lex->expr_list.empty(); - lex->ftfunc_list.empty(); + lex->select->in_sum_expr=0; + lex->select->expr_list.empty(); + lex->select->ftfunc_list.empty(); lex->convert_set=(lex->thd=thd)->convert_set; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->client_capabilities & CLIENT_IGNORE_SPACE); @@ -155,7 +155,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) 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_yyvs); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8c83e6e587a..14efa039fad 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -54,7 +54,8 @@ enum enum_sql_command { SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, 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, @@ -94,39 +95,57 @@ typedef struct st_lex_master_info ulonglong pos; } 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 */ typedef struct st_lex { uint yylineno,yytoklen; /* Simulate lex */ LEX_YYSTYPE yylval; + SELECT_LEX select_lex, *select; uchar *ptr,*tok_start,*tok_end,*end_of_query; char *length,*dec,*change,*name; - char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ char *backup_dir; /* For RESTORE/BACKUP */ char* to_log; /* For PURGE MASTER LOGS TO */ String *wild; 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<Alter_drop> drop_list; List<Alter_column> alter_list; - List<String> interval_list,use_index,*use_index_ptr, - ignore_index, *ignore_index_ptr; + List<String> interval_list; List<st_lex_user> users_list; List<LEX_COLUMN> columns; List<Key> key_list; List<create_field> create_list; - List<Item> item_list,*insert_list,field_list,value_list; - List<Item_func_match> ftfunc_list; - SQL_LIST order_list,table_list,group_list,proc_list; + List<Item> *insert_list,field_list,value_list; + List<List_item> many_values; + SQL_LIST proc_list, auxilliary_table_list; TYPELIB *interval; create_field *last_field; - - Item *where,*having,*default_value; + Item *default_value; CONVERT *convert_set; LEX_USER *grant_user; gptr yacc_yyss,yacc_yyvs; @@ -136,7 +155,6 @@ typedef struct st_lex { HA_CREATE_INFO create_info; LEX_MASTER_INFO mi; // used by CHANGE MASTER ulong thread_id,type; - ulong options; ulong gemini_spin_retries; enum_sql_command sql_command; enum lex_states next_state; @@ -145,9 +163,9 @@ typedef struct st_lex { enum enum_ha_read_modes ha_read_mode; enum ha_rkey_function ha_rkey_mode; 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; - 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; } LEX; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7742df4a2bf..1dbce659d18 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -760,7 +760,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thread_running++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->set_time(); - thd->lex.options=0; // We store status here + thd->lex.select_lex.options=0; // We store status here switch (command) { case COM_INIT_DB: if (!mysql_change_db(thd,packet)) @@ -1027,7 +1027,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->proc_info="logging slow query"; 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)) && (specialflag & SPECIAL_LONG_LOG_FORMAT))) { @@ -1058,7 +1058,8 @@ mysql_execute_command(void) int res=0; THD *thd=current_thd; 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"); if(table_rules_on && thd->slave_thread && tables && !tables_ok(thd,tables)) @@ -1070,7 +1071,7 @@ mysql_execute_command(void) case SQLCOM_SELECT: { select_result *result; - if (lex->options & SELECT_DESCRIBE) + if (Select->options & SELECT_DESCRIBE) lex->exchange=0; if (tables) { @@ -1088,12 +1089,12 @@ mysql_execute_command(void) break; // Error message is given } - thd->offset_limit=lex->offset_limit; - thd->select_limit=lex->select_limit+lex->offset_limit; - if (thd->select_limit < lex->select_limit) + thd->offset_limit=Select->offset_limit; + thd->select_limit=Select->select_limit+Select->offset_limit; + if (thd->select_limit < Select->select_limit) thd->select_limit= HA_POS_ERROR; // no limit if (thd->select_limit == HA_POS_ERROR) - lex->options&= ~OPTION_FOUND_ROWS; + Select->options&= ~OPTION_FOUND_ROWS; if (lex->exchange) { @@ -1118,8 +1119,8 @@ mysql_execute_command(void) { res= -1; #ifdef DELETE_ITEMS - delete lex->having; - delete lex->where; + delete Select->having; + delete Select->where; #endif break; } @@ -1137,22 +1138,22 @@ mysql_execute_command(void) if (!(res=open_and_lock_tables(thd,tables))) { - res=mysql_select(thd,tables,lex->item_list, - lex->where, - lex->ftfunc_list, - (ORDER*) lex->order_list.first, - (ORDER*) lex->group_list.first, - lex->having, + res=mysql_select(thd,tables,Select->item_list, + Select->where, + Select->ftfunc_list, + (ORDER*) Select->order_list.first, + (ORDER*) Select->group_list.first, + Select->having, (ORDER*) lex->proc_list.first, - lex->options | thd->options, + Select->options | thd->options, result); if (res) result->abort(); } delete result; #ifdef DELETE_ITEMS - delete lex->having; - delete lex->where; + delete Select->having; + delete Select->where; #endif break; } @@ -1271,7 +1272,7 @@ mysql_execute_command(void) res=0; break; } - if (lex->item_list.elements) // With select + if (Select->item_list.elements) // With select { select_result *result; @@ -1289,9 +1290,9 @@ mysql_execute_command(void) for (table = tables->next ; table ; table=table->next) table->lock_type= lex->lock_option; } - thd->offset_limit=lex->offset_limit; - thd->select_limit=lex->select_limit+lex->offset_limit; - if (thd->select_limit < lex->select_limit) + thd->offset_limit=Select->offset_limit; + thd->select_limit=Select->select_limit+Select->offset_limit; + if (thd->select_limit < Select->select_limit) thd->select_limit= HA_POS_ERROR; // No limit if (!(res=open_and_lock_tables(thd,tables->next))) @@ -1300,16 +1301,16 @@ mysql_execute_command(void) tables->real_name, &lex->create_info, lex->create_list, lex->key_list, - lex->item_list,lex->duplicates))) + Select->item_list,lex->duplicates))) { - res=mysql_select(thd,tables->next,lex->item_list, - lex->where, - lex->ftfunc_list, - (ORDER*) lex->order_list.first, - (ORDER*) lex->group_list.first, - lex->having, + res=mysql_select(thd,tables->next,Select->item_list, + Select->where, + Select->ftfunc_list, + (ORDER*) Select->order_list.first, + (ORDER*) Select->group_list.first, + Select->having, (ORDER*) lex->proc_list.first, - lex->options | thd->options, + Select->options | thd->options, result); if (res) result->abort(); @@ -1364,10 +1365,10 @@ mysql_execute_command(void) } if (!tables->db) tables->db=thd->db; - if (!lex->db) - lex->db=tables->db; + if (!Select->db) + Select->db=tables->db; 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, (TABLE_LIST *) lex->create_info.merge_list.first)) @@ -1383,7 +1384,7 @@ mysql_execute_command(void) TABLE_LIST tmp_table; bzero((char*) &tmp_table,sizeof(tmp_table)); tmp_table.real_name=lex->name; - tmp_table.db=lex->db; + tmp_table.db=Select->db; tmp_table.grant.privilege=priv; if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables)) goto error; @@ -1393,11 +1394,11 @@ mysql_execute_command(void) if (end_active_trans(thd)) res= -1; else - res= mysql_alter_table(thd, lex->db, lex->name, + res= mysql_alter_table(thd, Select->db, lex->name, &lex->create_info, tables, lex->create_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->alter_keys_onoff, lex->simple_alter); break; @@ -1517,22 +1518,22 @@ mysql_execute_command(void) goto error; if (grant_option && check_grant(thd,UPDATE_ACL,tables)) 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); DBUG_VOID_RETURN; } res = mysql_update(thd,tables, - lex->item_list, + Select->item_list, lex->value_list, - lex->where, - (ORDER *) lex->order_list.first, - lex->select_limit, + Select->where, + (ORDER *) Select->order_list.first, + Select->select_limit, lex->duplicates, lex->lock_option); #ifdef DELETE_ITEMS - delete lex->where; + delete Select->where; #endif break; case SQLCOM_INSERT: @@ -1576,9 +1577,9 @@ mysql_execute_command(void) } select_result *result; - thd->offset_limit=lex->offset_limit; - thd->select_limit=lex->select_limit+lex->offset_limit; - if (thd->select_limit < lex->select_limit) + thd->offset_limit=Select->offset_limit; + thd->select_limit=Select->select_limit+Select->offset_limit; + if (thd->select_limit < Select->select_limit) thd->select_limit= HA_POS_ERROR; // No limit if (check_dup(thd,tables->db,tables->real_name,tables->next)) @@ -1598,14 +1599,14 @@ mysql_execute_command(void) lex->sql_command == SQLCOM_REPLACE_SELECT ? DUP_REPLACE : DUP_IGNORE))) { - res=mysql_select(thd,tables->next,lex->item_list, - lex->where, - lex->ftfunc_list, - (ORDER*) lex->order_list.first, - (ORDER*) lex->group_list.first, - lex->having, + res=mysql_select(thd,tables->next,Select->item_list, + Select->where, + Select->ftfunc_list, + (ORDER*) Select->order_list.first, + (ORDER*) Select->group_list.first, + Select->having, (ORDER*) lex->proc_list.first, - lex->options | thd->options, + Select->options | thd->options, result); delete result; } @@ -1613,14 +1614,14 @@ mysql_execute_command(void) res= -1; } #ifdef DELETE_ITEMS - delete lex->having; - delete lex->where; + delete Select->having; + delete Select->where; #endif break; } case SQLCOM_TRUNCATE: - lex->where=0; - lex->select_limit=HA_POS_ERROR; + Select->where=0; + Select->select_limit=HA_POS_ERROR; /* Fall through */ case SQLCOM_DELETE: { @@ -1634,10 +1635,103 @@ mysql_execute_command(void) if (lex->sql_command == SQLCOM_TRUNCATE && end_active_trans(thd)) res= -1; else - res = mysql_delete(thd,tables, lex->where, (ORDER*)lex->order_list.first, - lex->select_limit, lex->lock_option, lex->options); + res = mysql_delete(thd,tables, Select->where, (ORDER*)Select->order_list.first, + 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; + } case SQLCOM_DROP_TABLE: { if (check_table_access(thd,DROP_ACL,tables)) @@ -1703,7 +1797,7 @@ mysql_execute_command(void) DBUG_VOID_RETURN; #else { - char *db=lex->db ? lex->db : thd->db; + char *db=Select->db ? Select->db : thd->db; if (!db) { send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ @@ -1718,7 +1812,7 @@ mysql_execute_command(void) if (check_access(thd,SELECT_ACL,db,&thd->col_access)) goto error; /* purecov: inspected */ /* grant is checked in mysqld_show_tables */ - if (lex->options & SELECT_DESCRIBE) + if (Select->options & SELECT_DESCRIBE) res= mysqld_extend_show_tables(thd,db, (lex->wild ? lex->wild->ptr() : NullS)); else @@ -1783,7 +1877,7 @@ mysql_execute_command(void) } #endif case SQLCOM_CHANGE_DB: - mysql_change_db(thd,lex->db); + mysql_change_db(thd,Select->db); break; case SQLCOM_LOAD: { @@ -1807,10 +1901,10 @@ mysql_execute_command(void) case SQLCOM_SET_OPTION: { uint org_options=thd->options; - thd->options=lex->options; + thd->options=Select->options; thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ? 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; if (thd->gemini_spin_retries != lex->gemini_spin_retries) { @@ -1821,7 +1915,7 @@ mysql_execute_command(void) thd->options,(long) thd->default_select_limit)); /* 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)) { @@ -1869,6 +1963,8 @@ mysql_execute_command(void) } if (check_db_used(thd,tables) || end_active_trans(thd)) goto error; + if (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL,tables)) + goto error; thd->in_lock_tables=1; if (!(res=open_and_lock_tables(thd,tables))) { @@ -1929,7 +2025,7 @@ mysql_execute_command(void) if (tables && !tables->db) tables->db=thd->db; 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 ? 0 : 1)) goto error; @@ -1981,7 +2077,7 @@ mysql_execute_command(void) res=1; } 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); if(!res) { @@ -2029,8 +2125,8 @@ mysql_execute_command(void) if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables)) goto error; res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir, - lex->insert_list, lex->ha_rkey_mode, lex->where, - lex->select_limit, lex->offset_limit); + lex->insert_list, lex->ha_rkey_mode, Select->where, + Select->select_limit, Select->offset_limit); break; case SQLCOM_BEGIN: @@ -2291,13 +2387,13 @@ static void mysql_init_query(THD *thd) { DBUG_ENTER("mysql_init_query"); - thd->lex.item_list.empty(); + thd->lex.select_lex.item_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->lex.table_list.first=0; - thd->lex.table_list.next= (byte**) &thd->lex.table_list.first; + thd->lex.select = &thd->lex.select_lex; + thd->lex.select_lex.table_list.first=0; + thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first; thd->fatal_error=0; // Safety thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0; thd->sent_row_count=thd->examined_row_count=0; @@ -2307,17 +2403,19 @@ mysql_init_query(THD *thd) void mysql_init_select(LEX *lex) { - lex->where=lex->having=0; - lex->select_limit=current_thd->default_select_limit; - lex->offset_limit=0L; - lex->options=0; - lex->exchange = 0; + SELECT_LEX *Select = lex->select; + Select->where=Select->having=0; + Select->select_limit=current_thd->default_select_limit; + Select->offset_limit=0L; + Select->options=0; Select->linkage=UNSPECIFIED_TYPE; + Select->select_number = 0; lex->exchange = 0; lex->proc_list.first=0; - lex->order_list.elements=lex->group_list.elements=0; - lex->order_list.first=0; - lex->order_list.next= (byte**) &lex->order_list.first; - lex->group_list.first=0; - lex->group_list.next= (byte**) &lex->group_list.first; + Select->order_list.elements=Select->group_list.elements=0; + Select->order_list.first=0; + Select->order_list.next= (byte**) &Select->order_list.first; + Select->group_list.first=0; + 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, 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) { if (!strcmp(alias_str,tables->name) && @@ -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); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 90b3c6eefaf..f1ae2f90860 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2478,7 +2478,7 @@ make_join_readinfo(JOIN *join,uint options) /* These init changes read_record */ 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; statistic_increment(select_range_check_count, &LOCK_status); } @@ -2493,7 +2493,7 @@ make_join_readinfo(JOIN *join,uint options) } 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); } } @@ -2505,7 +2505,7 @@ make_join_readinfo(JOIN *join,uint options) } 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); } } @@ -3920,7 +3920,7 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error, thd->proc_info="converting HEAP to MyISAM"; if (create_myisam_tmp_table(&new_table,param, - thd->lex.options | thd->options)) + thd->lex.select_lex.options | thd->options)) goto err2; if (open_tmp_table(&new_table)) goto err1; @@ -6647,7 +6647,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, DBUG_ENTER("select_describe"); /* 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("type",10)); field_list.push_back(item=new Item_empty_string("possible_keys", @@ -6806,7 +6806,7 @@ static void describe_info(THD *thd, const char *info) String *packet= &thd->packet; /* 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)); if (send_fields(thd,field_list,1)) return; /* purecov: inspected */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b6b22ecbc99..bdcc6c00b19 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -128,7 +128,7 @@ int mysql_update(THD *thd, /* If running in safe sql mode, don't allow updates without 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) { delete select; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ed17a2dedf4..bdfa75ab9d7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -21,6 +21,7 @@ #define YYINITDEPTH 100 #define YYMAXDEPTH 3200 /* Because of 64K stack */ #define Lex current_lex +#define Select Lex->select #include "mysql_priv.h" #include "slave.h" #include "sql_acl.h" @@ -526,7 +527,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); select_item_list select_item values_list no_braces limit_clause delete_limit_clause fields opt_values values procedure_list procedure_list2 procedure_item - when_list2 expr_list2 handler + when_list2 expr_list2 handler opt_precision opt_ignore opt_column opt_restrict grant revoke set lock unlock string_list field_options field_option field_opt_list opt_binary table_lock_list table_lock varchar @@ -541,7 +542,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); opt_mi_check_type opt_to mi_check_types normal_join table_to_table_list table_to_table opt_table_list opt_as 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> '-' '+' '*' '/' '%' '(' ')' @@ -762,12 +764,12 @@ create_table_option: { /* Move the union list to the merge_list */ LEX *lex=Lex; - TABLE_LIST *table_list= (TABLE_LIST*) lex->table_list.first; - lex->create_info.merge_list= lex->table_list; + TABLE_LIST *table_list= (TABLE_LIST*) Select->table_list.first; + lex->create_info.merge_list= Select->table_list; lex->create_info.merge_list.elements--; lex->create_info.merge_list.first= (byte*) (table_list->next); - lex->table_list.elements=1; - lex->table_list.next= (byte**) &(table_list->next); + Select->table_list.elements=1; + Select->table_list.next= (byte**) &(table_list->next); table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } @@ -1062,10 +1064,10 @@ alter: lex->col_list.empty(); lex->drop_list.empty(); lex->alter_list.empty(); - lex->order_list.elements=0; - lex->order_list.first=0; - lex->order_list.next= (byte**) &lex->order_list.first; - lex->db=lex->name=0; + Select->order_list.elements=0; + Select->order_list.first=0; + Select->order_list.next= (byte**) &Select->order_list.first; + Select->db=lex->name=0; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= DB_TYPE_DEFAULT; lex->alter_keys_onoff=LEAVE_AS_IS; @@ -1116,7 +1118,7 @@ alter_list_item: | ALTER opt_column field_ident DROP DEFAULT { Lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0)); Lex->simple_alter=0; } | 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; } | order_clause { Lex->simple_alter=0; } @@ -1277,13 +1279,13 @@ select_option_list: | 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; } - | DISTINCT { Lex->options|= SELECT_DISTINCT; } - | SQL_SMALL_RESULT { Lex->options|= SELECT_SMALL_RESULT; } - | SQL_BIG_RESULT { Lex->options|= SELECT_BIG_RESULT; } - | SQL_BUFFER_RESULT { Lex->options|= OPTION_BUFFER_RESULT; } - | SQL_CALC_FOUND_ROWS { Lex->options|= OPTION_FOUND_ROWS; } + | DISTINCT { Select->options|= SELECT_DISTINCT; } + | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } + | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } + | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; } + | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; } | ALL {} select_lock_type: @@ -1470,10 +1472,10 @@ simple_expr: | '(' expr ')' { $$= $2; } | '{' ident expr '}' { $$= $3; } | MATCH '(' ident_list ')' AGAINST '(' expr ')' - { Lex->ftfunc_list.push_back( + { Select->ftfunc_list.push_back( (Item_func_match *)($$=new Item_func_match(*$3,$7))); } | MATCH ident_list AGAINST '(' expr ')' - { Lex->ftfunc_list.push_back( + { Select->ftfunc_list.push_back( (Item_func_match *)($$=new Item_func_match(*$2,$5))); } | BINARY expr %prec NEG { $$= new Item_func_binary($2); } | CASE_SYM opt_expr WHEN_SYM when_list opt_else END @@ -1704,30 +1706,30 @@ sum_expr: { $$=new Item_sum_sum($3); } in_sum_expr: - { Lex->in_sum_expr++ } + { Select->in_sum_expr++ } expr { - Lex->in_sum_expr--; + Select->in_sum_expr--; $$=$2; } expr_list: - { Lex->expr_list.push_front(new List<Item>); } + { Select->expr_list.push_front(new List<Item>); } expr_list2 - { $$= Lex->expr_list.pop(); } + { $$= Select->expr_list.pop(); } expr_list2: - expr { Lex->expr_list.head()->push_back($1); } - | expr_list2 ',' expr { Lex->expr_list.head()->push_back($3); } + expr { Select->expr_list.head()->push_back($1); } + | expr_list2 ',' expr { Select->expr_list.head()->push_back($3); } ident_list: - { Lex->expr_list.push_front(new List<Item>); } + { Select->expr_list.push_front(new List<Item>); } ident_list2 - { $$= Lex->expr_list.pop(); } + { $$= Select->expr_list.pop(); } ident_list2: - simple_ident { Lex->expr_list.head()->push_back($1); } - | ident_list2 ',' simple_ident { Lex->expr_list.head()->push_back($3); } + simple_ident { Select->expr_list.head()->push_back($1); } + | ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); } opt_expr: /* empty */ { $$= NULL; } @@ -1738,20 +1740,20 @@ opt_else: | ELSE expr { $$= $2; } when_list: - { Lex->when_list.push_front(new List<Item>) } + { Select->when_list.push_front(new List<Item>) } when_list2 - { $$= Lex->when_list.pop(); } + { $$= Select->when_list.pop(); } when_list2: expr THEN_SYM expr { - Lex->when_list.head()->push_back($1); - Lex->when_list.head()->push_back($3); + Select->when_list.head()->push_back($1); + Select->when_list.head()->push_back($3); } | when_list2 WHEN_SYM expr THEN_SYM expr { - Lex->when_list.head()->push_back($3); - Lex->when_list.head()->push_back($5); + Select->when_list.head()->push_back($3); + Select->when_list.head()->push_back($5); } opt_pad: @@ -1766,15 +1768,15 @@ join_table_list: | join_table_list INNER_SYM JOIN_SYM join_table ON expr { add_join_on($4,$6); $$=$4; } | join_table_list INNER_SYM JOIN_SYM join_table - { Lex->db1=$1->db; Lex->table1=$1->name; - Lex->db2=$4->db; Lex->table2=$4->name; } + { Select->db1=$1->db; Select->table1=$1->name; + Select->db2=$4->db; Select->table2=$4->name; } USING '(' using_list ')' { add_join_on($4,$8); $$=$4; } | join_table_list LEFT opt_outer JOIN_SYM join_table ON expr { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | join_table_list LEFT opt_outer JOIN_SYM join_table - { Lex->db1=$1->db; Lex->table1=$1->name; - Lex->db2=$5->db; Lex->table2=$5->name; } + { Select->db1=$1->db; Select->table1=$1->name; + Select->db2=$5->db; Select->table2=$5->name; } USING '(' using_list ')' { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table @@ -1782,8 +1784,8 @@ join_table_list: | join_table_list RIGHT opt_outer JOIN_SYM join_table ON expr { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } | join_table_list RIGHT opt_outer JOIN_SYM join_table - { Lex->db1=$1->db; Lex->table1=$1->name; - Lex->db2=$5->db; Lex->table2=$5->name; } + { Select->db1=$1->db; Select->table1=$1->name; + Select->db2=$5->db; Select->table2=$5->name; } USING '(' using_list ')' { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; } | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table @@ -1797,10 +1799,10 @@ normal_join: | CROSS JOIN_SYM {} 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 - { if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, Lex->use_index_ptr, - Lex->ignore_index_ptr))) YYABORT; } + { if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, Select->use_index_ptr, + Select->ignore_index_ptr))) YYABORT; } | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}' { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } @@ -1811,30 +1813,30 @@ opt_outer: opt_key_definition: /* empty */ {} | 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 - { 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_or_index { Lex->interval_list.empty() } '(' key_usage_list2 ')' - { $$= &Lex->interval_list; } + key_or_index { Select->interval_list.empty() } '(' key_usage_list2 ')' + { $$= &Select->interval_list; } key_usage_list2: 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 - { 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 - { Lex->interval_list.push_back(new String("PRIMARY",7)); } + { Select->interval_list.push_back(new String("PRIMARY",7)); } using_list: 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; } | 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; } @@ -1865,13 +1867,13 @@ opt_table_alias: where_clause: - /* empty */ { Lex->where= 0; } - | WHERE expr { Lex->where= $2; } + /* empty */ { Select->where= 0; } + | WHERE expr { Select->where= $2; } having_clause: /* empty */ - | HAVING { Lex->create_refs=1; } expr - { Lex->having= $3; Lex->create_refs=0; } + | HAVING { Select->create_refs=1; } expr + { Select->having= $3; Select->create_refs=0; } opt_escape: ESCAPE_SYM TEXT_STRING { $$= $2.str; } @@ -1901,7 +1903,7 @@ opt_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_ident order_dir @@ -1911,29 +1913,29 @@ order_list: order_dir: /* empty */ { $$ = 1; } - | ASC { $$ = Lex->sort_default=1; } - | DESC { $$ = Lex->sort_default=0; } + | ASC { $$ = Select->sort_default=1; } + | DESC { $$ = Select->sort_default=0; } limit_clause: /* 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; - Lex->offset_limit= 0L; + Select->offset_limit= 0L; } | LIMIT ULONG_NUM - { Lex->select_limit= $2; Lex->offset_limit=0L; } + { Select->select_limit= $2; Select->offset_limit=0L; } | LIMIT ULONG_NUM ',' ULONG_NUM - { Lex->select_limit= $4; Lex->offset_limit=$2; } + { Select->select_limit= $4; Select->offset_limit=$2; } delete_limit_clause: /* empty */ { - Lex->select_limit= HA_POS_ERROR; + Select->select_limit= HA_POS_ERROR; } | LIMIT ULONGLONG_NUM - { Lex->select_limit= (ha_rows) $2; } + { Select->select_limit= (ha_rows) $2; } ULONG_NUM: NUM { $$= strtoul($1.str,NULL,10); } @@ -2156,9 +2158,9 @@ update: delete_limit_clause { Lex->sql_command = SQLCOM_UPDATE; - Lex->order_list.elements=0; - Lex->order_list.first=0; - Lex->order_list.next= (byte**) &Lex->order_list.first; + Select->order_list.elements=0; + Select->order_list.first=0; + Select->order_list.next= (byte**) &Select->order_list.first; } update_list: @@ -2182,22 +2184,49 @@ opt_low_priority: delete: DELETE_SYM { - Lex->sql_command= SQLCOM_DELETE; Lex->options=0; - Lex->lock_option= current_thd->update_lock_default; - Lex->order_list.elements=0; - Lex->order_list.first=0; - Lex->order_list.next= (byte**) &Lex->order_list.first; - } - opt_delete_options FROM table_name - where_clause opt_order_clause delete_limit_clause - + Lex->sql_command= SQLCOM_DELETE; Select->options=0; + Lex->lock_option= current_thd->update_lock_default; + Select->order_list.elements=0; + Select->order_list.first=0; + Select->order_list.next= (byte**) &Select->order_list.first; + } + opt_delete_options single_multi {} + +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: /* empty */ {} | opt_delete_option opt_delete_options {} opt_delete_option: - QUICK { Lex->options|= OPTION_QUICK; } + QUICK { Select->options|= OPTION_QUICK; } | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } truncate: @@ -2205,17 +2234,17 @@ truncate: { LEX* lex = Lex; lex->sql_command= SQLCOM_TRUNCATE; - lex->options=0; - lex->order_list.elements=0; - lex->order_list.first=0; - lex->order_list.next= (byte**) &lex->order_list.first; + Select->options=0; + Select->order_list.elements=0; + Select->order_list.first=0; + Select->order_list.next= (byte**) &Select->order_list.first; lex->lock_option= current_thd->update_lock_default; } opt_table_sym: /* empty */ | TABLE_SYM - + /* Show things */ show: SHOW { Lex->wild=0;} show_param @@ -2224,16 +2253,16 @@ show_param: DATABASES wild { Lex->sql_command= SQLCOM_SHOW_DATABASES; } | 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 { Lex->sql_command= SQLCOM_SHOW_TABLES; - Lex->options|= SELECT_DESCRIBE; - Lex->db= $3; + Select->options|= SELECT_DESCRIBE; + Select->db= $3; } | OPEN_SYM TABLES opt_db wild { Lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; - Lex->db= $3; - Lex->options=0; + Select->db= $3; + Select->options=0; } | opt_full COLUMNS FROM table_ident opt_db wild { @@ -2304,7 +2333,7 @@ describe: YYABORT; } opt_describe_column - | describe_command select { Lex->options|= SELECT_DESCRIBE }; + | describe_command select { Select->options|= SELECT_DESCRIBE }; describe_command: @@ -2375,7 +2404,7 @@ kill: /* change database */ 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 */ @@ -2503,13 +2532,13 @@ order_ident: simple_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 - { $$ = !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 - { $$ = !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 - { $$ = !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: @@ -2682,8 +2711,8 @@ set: { THD *thd=current_thd; Lex->sql_command= SQLCOM_SET_OPTION; - Lex->options=thd->options; - Lex->select_limit=thd->default_select_limit; + Select->options=thd->options; + Select->select_limit=thd->default_select_limit; Lex->gemini_spin_retries=thd->gemini_spin_retries; Lex->tx_isolation=thd->tx_isolation; } @@ -2701,30 +2730,30 @@ option_value: set_option equal NUM { if (atoi($3.str) == 0) - Lex->options&= ~$1; + Select->options&= ~$1; else - Lex->options|= $1; + Select->options|= $1; } | set_isolation | AUTOCOMMIT equal NUM { if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */ - Lex->options&= ~(OPTION_NOT_AUTO_COMMIT); + Select->options&= ~(OPTION_NOT_AUTO_COMMIT); else - Lex->options|= OPTION_NOT_AUTO_COMMIT; + Select->options|= OPTION_NOT_AUTO_COMMIT; } | SQL_SELECT_LIMIT equal ULONG_NUM { - Lex->select_limit= $3; + Select->select_limit= $3; } | SQL_SELECT_LIMIT equal DEFAULT { - Lex->select_limit= HA_POS_ERROR; + Select->select_limit= HA_POS_ERROR; } | SQL_MAX_JOIN_SIZE equal ULONG_NUM { current_thd->max_join_size= $3; - Lex->options&= ~OPTION_BIG_SELECTS; + Select->options&= ~OPTION_BIG_SELECTS; } | SQL_MAX_JOIN_SIZE equal DEFAULT { @@ -2952,7 +2981,7 @@ revoke: Lex->users_list.empty(); Lex->columns.empty(); Lex->grant= Lex->grant_tot_col=0; - Lex->db=0; + Select->db=0; } grant_privileges ON opt_table FROM user_list @@ -2963,7 +2992,7 @@ grant: Lex->users_list.empty(); Lex->columns.empty(); Lex->grant= Lex->grant_tot_col=0; - Lex->db=0; + Select->db=0; } grant_privileges ON opt_table TO_SYM user_list grant_option @@ -3003,7 +3032,7 @@ grant_privilege: opt_table: '*' { - Lex->db=current_thd->db; + Select->db=current_thd->db; if (Lex->grant == UINT_MAX) Lex->grant = DB_ACLS & ~GRANT_ACL; else if (Lex->columns.elements) @@ -3014,7 +3043,7 @@ opt_table: } | ident '.' '*' { - Lex->db = $1.str; + Select->db = $1.str; if (Lex->grant == UINT_MAX) Lex->grant = DB_ACLS & ~GRANT_ACL; else if (Lex->columns.elements) @@ -3025,7 +3054,7 @@ opt_table: } | '*' '.' '*' { - Lex->db = NULL; + Select->db = NULL; if (Lex->grant == UINT_MAX) Lex->grant = GLOBAL_ACLS & ~GRANT_ACL; else if (Lex->columns.elements) diff --git a/sql/uniques.cc b/sql/uniques.cc index 78fd8fe6e60..36a395dfa5d 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -34,11 +34,14 @@ #include "mysql_priv.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) { my_b_clear(&file); 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 */ init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size); @@ -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; } -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); unique->record_pointers+=unique->tree.size_of_element; @@ -109,7 +114,7 @@ bool Unique::get(TABLE *table) IO_CACHE *outfile=table->io_cache, tempfile; BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer; - uint maxbuffer= file_ptrs.elements; + uint maxbuffer= file_ptrs.elements - 1; // I added -1 ..... uchar *sort_buffer; my_off_t save_pos; bool error=1; @@ -117,18 +122,21 @@ bool Unique::get(TABLE *table) my_b_clear(&tempfile); /* Open cached file if it isn't open */ + if (!outfile) outfile= (IO_CACHE *) sql_calloc(sizeof(IO_CACHE)); if (! my_b_inited(outfile) && open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME))) return 1; 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_length=sort_param.ref_length=tree.size_of_element; sort_param.keys= max_in_memory_size / sort_param.sort_length; - if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * + if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * sort_param.sort_length, MYF(0)))) return 1; |