diff options
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 101 |
1 files changed, 64 insertions, 37 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d8861390d87..0898ad4bffb 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,15 +1,15 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -78,7 +78,8 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, table_list.grant=table->grant; thd->dupp_field=0; - if (setup_tables(&table_list) || setup_fields(thd,&table_list,fields,1,0)) + if (setup_tables(&table_list) || + setup_fields(thd,&table_list,fields,1,0,0)) return -1; if (thd->dupp_field) { @@ -102,14 +103,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, int error; bool log_on= ((thd->options & OPTION_UPDATE_LOG) || !(thd->master_access & PROCESS_ACL)); - bool using_transactions; + bool using_transactions, bulk_insert=0; uint value_count; uint save_time_stamp; ulong counter = 1; ulonglong id; COPY_INFO info; TABLE *table; - List_iterator<List_item> its(values_list); + List_iterator_fast<List_item> its(values_list); List_item *values; char *query=thd->query; DBUG_ENTER("mysql_insert"); @@ -151,7 +152,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, save_time_stamp=table->time_stamp; values= its++; if (check_insert_fields(thd,table,fields,*values,1) || - setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0)) + setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0,0)) { table->time_stamp=save_time_stamp; goto abort; @@ -168,7 +169,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, table->time_stamp=save_time_stamp; goto abort; } - if (setup_fields(thd,table_list,*values,0,0)) + if (setup_fields(thd,table_list,*values,0,0,0)) { table->time_stamp=save_time_stamp; goto abort; @@ -192,6 +193,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, thd->proc_info="update"; if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + if ((bulk_insert= (values_list.elements > 1 && + lock_type != TL_WRITE_DELAYED && + !(specialflag & SPECIAL_SAFE_MODE)))) + { + table->file->extra(HA_EXTRA_WRITE_CACHE); + table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN); + } + while ((values = its++)) { if (fields.elements || !value_count) @@ -256,6 +265,25 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, } else { + if (bulk_insert) + { + if (table->file->extra(HA_EXTRA_NO_CACHE)) + { + if (!error) + { + table->file->print_error(my_errno,MYF(0)); + error=1; + } + } + if (table->file->extra(HA_EXTRA_BULK_INSERT_END)) + { + if (!error) + { + table->file->print_error(my_errno,MYF(0)); + error=1; + } + } + } if (id && values_list.elements != 1) thd->insert_id(id); // For update log else if (table->next_number_field) @@ -282,13 +310,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, } } thd->proc_info="end"; + if (info.copied || info.deleted) + query_cache.invalidate(table_list); table->time_stamp=save_time_stamp; // Restore auto timestamp ptr table->next_number_field=0; thd->count_cuted_fields=0; thd->next_insert_id=0; // Reset this if wrongly used if (duplic == DUP_IGNORE || duplic == DUP_REPLACE) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); - if (error) goto abort; @@ -335,18 +364,18 @@ int write_record(TABLE *table,COPY_INFO *info) { int error; char *key=0; - + info->records++; if (info->handle_duplicates == DUP_REPLACE) { while ((error=table->file->write_row(table->record[0]))) { - if (error != HA_WRITE_SKIPP) + if (error != HA_WRITE_SKIP) goto err; uint key_nr; if ((int) (key_nr = table->file->get_dup_key(error)) < 0) { - error=HA_WRITE_SKIPP; /* Database can't find key */ + error=HA_WRITE_SKIP; /* Database can't find key */ goto err; } /* @@ -364,12 +393,12 @@ int write_record(TABLE *table,COPY_INFO *info) } else { - if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) /* Not neaded with NISAM */ + if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) /* Not needed with NISAM */ { error=my_errno; goto err; } - + if (!key) { if (!(key=(char*) my_safe_alloca(table->max_unique_length, @@ -507,7 +536,7 @@ public: } ~delayed_insert() { - /* The following is not really neaded, but just for safety */ + /* The following is not really needed, but just for safety */ delayed_row *row; while ((row=rows.get())) delete row; @@ -646,7 +675,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) /* Copy error message and abort */ thd->fatal_error=1; strmov(thd->net.last_error,tmp->thd.net.last_error); - thd->net.last_errno=thd->net.last_errno; + thd->net.last_errno=tmp->thd.net.last_errno; } tmp->unlock(); pthread_mutex_unlock(&LOCK_delayed_create); @@ -710,9 +739,9 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) } client_thd->proc_info="allocating local table"; - copy= (TABLE*) sql_alloc(sizeof(*copy)+ - (table->fields+1)*sizeof(Field**)+ - table->reclength); + copy= (TABLE*) client_thd->alloc(sizeof(*copy)+ + (table->fields+1)*sizeof(Field**)+ + table->reclength); if (!copy) goto error; *copy= *table; @@ -730,7 +759,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) found_next_number_field=table->found_next_number_field; for (org_field=table->field ; *org_field ; org_field++,field++) { - if (!(*field= (*org_field)->new_field(copy))) + if (!(*field= (*org_field)->new_field(&client_thd->mem_root,copy))) return 0; (*field)->move_field(adjust_ptrs); // Point at copy->record[0] if (*org_field == found_next_number_field) @@ -959,23 +988,12 @@ static pthread_handler_decl(handle_delayed_insert,arg) if (!di->status && !di->stacked_inserts) { struct timespec abstime; -#if defined(HAVE_TIMESPEC_TS_SEC) - abstime.ts_sec=time((time_t*) 0)+(time_t) delayed_insert_timeout; - abstime.ts_nsec=0; -#elif defined(__WIN__) - abstime.tv_sec=time((time_t*) 0)+(time_t) delayed_insert_timeout; - abstime.tv_nsec=0; -#else - struct timeval tv; - gettimeofday(&tv,0); - abstime.tv_sec=tv.tv_sec+(time_t) delayed_insert_timeout; - abstime.tv_nsec=tv.tv_usec*1000; -#endif + set_timespec(abstime, delayed_insert_timeout); /* Information for pthread_kill */ di->thd.mysys_var->current_mutex= &di->mutex; di->thd.mysys_var->current_cond= &di->cond; - di->thd.proc_info=0; + di->thd.proc_info="Waiting for INSERT"; DBUG_PRINT("info",("Waiting for someone to insert rows")); while (!thd->killed) @@ -1010,6 +1028,7 @@ static pthread_handler_decl(handle_delayed_insert,arg) pthread_mutex_unlock(&di->thd.mysys_var->mutex); pthread_mutex_lock(&di->mutex); } + di->thd.proc_info=0; if (di->tables_in_use && ! thd->lock) { @@ -1198,6 +1217,7 @@ bool delayed_insert::handle_inserts(void) sql_print_error("%s",thd.net.last_error); goto err; } + query_cache.invalidate(table); if (thr_reschedule_write_lock(*thd.lock->locks)) { /* This should never happen */ @@ -1222,6 +1242,7 @@ bool delayed_insert::handle_inserts(void) sql_print_error("%s",thd.net.last_error); goto err; } + query_cache.invalidate(table); pthread_mutex_lock(&mutex); DBUG_RETURN(0); @@ -1255,7 +1276,7 @@ select_insert::prepare(List<Item> &values) restore_record(table,2); // Get empty record table->next_number_field=table->found_next_number_field; - thd->count_cuted_fields=1; /* calc cuted fields */ + thd->count_cuted_fields=1; // calc cuted fields thd->cuted_fields=0; if (info.handle_duplicates != DUP_REPLACE) table->file->extra(HA_EXTRA_WRITE_CACHE); @@ -1307,7 +1328,9 @@ void select_insert::send_error(uint errcode,const char *err) ::send_error(&thd->net,errcode,err); table->file->extra(HA_EXTRA_NO_CACHE); table->file->activate_all_index(thd); - ha_rollback(thd); + ha_rollback_stmt(thd); + if (info.copied || info.deleted) + query_cache.invalidate(table); } @@ -1319,6 +1342,8 @@ bool select_insert::send_eof() table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) error=error2; + if (info.copied || info.deleted) + query_cache.invalidate(table); if (error) { @@ -1407,6 +1432,7 @@ bool select_create::send_data(List<Item> &values) extern HASH open_cache; + bool select_create::send_eof() { bool tmp=select_insert::send_eof(); @@ -1419,7 +1445,8 @@ bool select_create::send_eof() mysql_unlock_tables(thd, lock); if (!table->tmp_table) hash_delete(&open_cache,(byte*) table); - lock=0; table=0; + lock=0; + table=0; VOID(pthread_mutex_unlock(&LOCK_open)); } return tmp; @@ -1451,7 +1478,7 @@ void select_create::abort() *****************************************************************************/ #ifdef __GNUC__ -template class List_iterator<List_item>; +template class List_iterator_fast<List_item>; template class I_List<delayed_insert>; template class I_List_iterator<delayed_insert>; template class I_List<delayed_row>; |