summaryrefslogtreecommitdiff
path: root/sql/sql_insert.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r--sql/sql_insert.cc101
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>;