diff options
Diffstat (limited to 'sql/sql_load.cc')
-rw-r--r-- | sql/sql_load.cc | 152 |
1 files changed, 105 insertions, 47 deletions
diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c4f5b1427af..174ccdfab5b 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -71,14 +71,16 @@ public: void set_io_cache_arg(void* arg) { cache.arg = arg; } }; -static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table, +static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List<Item> &fields, READ_INFO &read_info, - ulong skip_lines); -static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, + ulong skip_lines, + bool ignore_check_option_errors); +static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List<Item> &fields, READ_INFO &read_info, - String &enclosed, ulong skip_lines); + String &enclosed, ulong skip_lines, + bool ignore_check_option_errors); -int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, +bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List<Item> &fields, enum enum_duplicates handle_duplicates, bool ignore, bool read_file_from_client,thr_lock_type lock_type) @@ -89,6 +91,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, int error; String *field_term=ex->field_term,*escaped=ex->escaped; String *enclosed=ex->enclosed; + Item *unused_conds= 0; bool is_fifo=0; #ifndef EMBEDDED_LIBRARY LOAD_FILE_INFO lf_info; @@ -100,8 +103,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, loaded is located */ char *tdb= thd->db ? thd->db : db; // Result is never null - bool transactional_table, log_delayed; ulong skip_lines= ex->skip_lines; + bool transactional_table; DBUG_ENTER("mysql_load"); #ifdef EMBEDDED_LIBRARY @@ -112,12 +115,23 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } - if (!(table = open_ltable(thd,table_list,lock_type))) - DBUG_RETURN(-1); + table_list->lock_type= lock_type; + if (open_and_lock_tables(thd, table_list)) + DBUG_RETURN(TRUE); + if (setup_tables(thd, table_list, &unused_conds, + &thd->lex->select_lex.leaf_tables, FALSE, FALSE)) + DBUG_RETURN(-1); + if (!table_list->table || // do not suport join view + !table_list->updatable || // and derived tables + check_key_in_view(thd, table_list)) + { + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); + DBUG_RETURN(TRUE); + } + table= table_list->table; transactional_table= table->file->has_transactions(); - log_delayed= (transactional_table || table->tmp_table); if (!fields.elements) { @@ -128,14 +142,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, else { // Part field list thd->dupp_field=0; - if (setup_tables(table_list) || - setup_fields(thd, 0, table_list, fields, 1, 0, 0)) - DBUG_RETURN(-1); + /* TODO: use this conds for 'WITH CHECK OPTIONS' */ + if (setup_fields(thd, 0, table_list, fields, 1, 0, 0)) + DBUG_RETURN(TRUE); if (thd->dupp_field) { my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dupp_field->field_name); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } + if (check_that_all_fields_are_given_values(thd, table)) + DBUG_RETURN(TRUE); } uint tot_length=0; @@ -161,7 +177,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED), MYF(0)); - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } /* We can't give an error in the middle when using LOCAL files */ @@ -193,7 +209,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, #if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__) MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(MY_WME))) - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); // if we are not in slave thread, the file must be: if (!thd->slave_thread && @@ -204,15 +220,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ((stat_info.st_mode & S_IFREG) == S_IFREG || (stat_info.st_mode & S_IFIFO) == S_IFIFO))) { - my_error(ER_TEXTFILE_NOT_READABLE,MYF(0),name); - DBUG_RETURN(-1); + my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name); + DBUG_RETURN(TRUE); } if ((stat_info.st_mode & S_IFIFO) == S_IFIFO) is_fifo = 1; #endif } if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0) - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); } COPY_INFO info; @@ -228,7 +244,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { if (file >= 0) my_close(file,MYF(0)); // no files in net reading - DBUG_RETURN(-1); // Can't allocate buffers + DBUG_RETURN(TRUE); // Can't allocate buffers } #ifndef EMBEDDED_LIBRARY @@ -237,18 +253,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, lf_info.thd = thd; lf_info.ex = ex; lf_info.db = db; - lf_info.table_name = table_list->real_name; + lf_info.table_name = table_list->table_name; lf_info.fields = &fields; lf_info.ignore= ignore; lf_info.handle_dup = handle_duplicates; lf_info.wrote_create_file = 0; lf_info.last_pos_in_file = HA_POS_ERROR; - lf_info.log_delayed= log_delayed; + lf_info.log_delayed= transactional_table; read_info.set_io_cache_arg((void*) &lf_info); } #endif /*!EMBEDDED_LIBRARY*/ - restore_record(table,default_values); + restore_record(table, s->default_values); thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ thd->cuted_fields=0L; @@ -276,12 +292,20 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ha_enable_transaction(thd, FALSE); table->file->start_bulk_insert((ha_rows) 0); table->copy_blobs=1; + + thd->no_trans_update= 0; + thd->abort_on_warning= (!ignore && + (thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | + MODE_STRICT_ALL_TABLES))); + if (!field_term->length() && !enclosed->length()) - error=read_fixed_length(thd,info,table,fields,read_info, - skip_lines); + error= read_fixed_length(thd, info, table_list, fields,read_info, + skip_lines, ignore); else - error=read_sep_field(thd,info,table,fields,read_info,*enclosed, - skip_lines); + error= read_sep_field(thd, info, table_list, fields, read_info, + *enclosed, skip_lines, + ignore); if (table->file->end_bulk_insert()) error=1; /* purecov: inspected */ ha_enable_transaction(thd, TRUE); @@ -337,7 +361,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, /* If the file was not empty, wrote_create_file is true */ if (lf_info.wrote_create_file) { - Delete_file_log_event d(thd, db, log_delayed); + Delete_file_log_event d(thd, db, transactional_table); mysql_bin_log.write(&d); } } @@ -348,11 +372,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted, (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); send_ok(thd,info.copied+info.deleted,0L,name); - // on the slave thd->query is never initialized - if (!thd->slave_thread) - mysql_update_log.write(thd,thd->query,thd->query_length); - if (!log_delayed) + if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; #ifndef EMBEDDED_LIBRARY if (mysql_bin_log.is_open()) @@ -362,22 +383,24 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, block will be logged only after Execute_load_log_event (which is wrong), when read_info is destroyed. */ - read_info.end_io_cache(); + read_info.end_io_cache(); if (lf_info.wrote_create_file) { - Execute_load_log_event e(thd, db, log_delayed); + Execute_load_log_event e(thd, db, transactional_table); mysql_bin_log.write(&e); } } #endif /*!EMBEDDED_LIBRARY*/ if (transactional_table) - error=ha_autocommit_or_rollback(thd,error); + error=ha_autocommit_or_rollback(thd,error); + err: if (thd->lock) { mysql_unlock_tables(thd, thd->lock); thd->lock=0; } + thd->abort_on_warning= 0; DBUG_RETURN(error); } @@ -386,12 +409,15 @@ err: ****************************************************************************/ static int -read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, - READ_INFO &read_info, ulong skip_lines) +read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, + List<Item> &fields, READ_INFO &read_info, ulong skip_lines, + bool ignore_check_option_errors) { List_iterator_fast<Item> it(fields); Item_field *sql_field; + TABLE *table= table_list->table; ulonglong id; + bool no_trans_update; DBUG_ENTER("read_fixed_length"); id= 0; @@ -404,7 +430,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, { if (thd->killed) { - my_error(ER_SERVER_SHUTDOWN,MYF(0)); + thd->send_kill_message(); DBUG_RETURN(1); } if (skip_lines) @@ -423,6 +449,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, #ifdef HAVE_purify read_info.row_end[0]=0; #endif + no_trans_update= !table->file->has_transactions(); while ((sql_field= (Item_field*) it++)) { Field *field= sql_field->field; @@ -442,7 +469,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, field->field_length) length=field->field_length; save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc - field->store((char*) pos,length,read_info.read_charset); + field->store((char*) pos,length,read_info.read_charset); pos[length]=save_chr; if ((pos+=length) > read_info.row_end) pos= read_info.row_end; /* Fills rest with space */ @@ -455,8 +482,20 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } - if (write_record(table,&info)) + + switch (table_list->view_check_option(thd, + ignore_check_option_errors)) { + case VIEW_CHECK_SKIP: + read_info.next_line(); + goto continue_loop; + case VIEW_CHECK_ERROR: + DBUG_RETURN(-1); + } + + if (thd->killed || write_record(thd,table,&info)) DBUG_RETURN(1); + thd->no_trans_update= no_trans_update; + /* If auto_increment values are used, save the first one for LAST_INSERT_ID() and for the binary/update log. @@ -477,6 +516,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } thd->row_count++; +continue_loop:; } if (id && !read_info.error) thd->insert_id(id); // For binary/update log @@ -486,24 +526,28 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, static int -read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, +read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List<Item> &fields, READ_INFO &read_info, - String &enclosed, ulong skip_lines) + String &enclosed, ulong skip_lines, + bool ignore_check_option_errors) { List_iterator_fast<Item> it(fields); Item_field *sql_field; + TABLE *table= table_list->table; uint enclosed_length; ulonglong id; + bool no_trans_update; DBUG_ENTER("read_sep_field"); enclosed_length=enclosed.length(); id= 0; + no_trans_update= !table->file->has_transactions(); for (;;it.rewind()) { if (thd->killed) { - my_error(ER_SERVER_SHUTDOWN,MYF(0)); + thd->send_kill_message(); DBUG_RETURN(1); } while ((sql_field=(Item_field*) it++)) @@ -559,7 +603,18 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count); } } - if (write_record(table,&info)) + + switch (table_list->view_check_option(thd, + ignore_check_option_errors)) { + case VIEW_CHECK_SKIP: + read_info.next_line(); + goto continue_loop; + case VIEW_CHECK_ERROR: + DBUG_RETURN(-1); + } + + + if (thd->killed || write_record(thd, table, &info)) DBUG_RETURN(1); /* If auto_increment values are used, save the first one @@ -571,6 +626,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, id= thd->last_insert_id; if (table->next_number_field) table->next_number_field->reset(); // Clear for next record + thd->no_trans_update= no_trans_update; if (read_info.next_line()) // Skip to next line break; if (read_info.line_cuted) @@ -579,8 +635,11 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); + if (thd->killed) + DBUG_RETURN(1); } thd->row_count++; +continue_loop:; } if (id && !read_info.error) thd->insert_id(id); // For binary/update log @@ -669,12 +728,11 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs, my_free((gptr) buffer,MYF(0)); /* purecov: inspected */ error=1; } - else + else { /* init_io_cache() will not initialize read_function member - if the cache is READ_NET. The reason is explained in - mysys/mf_iocache.c. So we work around the problem with a + if the cache is READ_NET. So we work around the problem with a manual assignment */ need_end_io_cache = 1; |