67
69
Either this method, or we need to make cache public
68
70
Arg must be set from mysql_load() since constructor does not see
69
either the table or THD value
71
either the table or Session value
71
73
void set_io_cache_arg(void* arg) { cache.arg = arg; }
74
static int read_fixed_length(THD *thd, COPY_INFO &info, TableList *table_list,
76
static int read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
75
77
List<Item> &fields_vars, List<Item> &set_fields,
76
78
List<Item> &set_values, READ_INFO &read_info,
77
79
uint32_t skip_lines,
78
80
bool ignore_check_option_errors);
79
static int read_sep_field(THD *thd, COPY_INFO &info, TableList *table_list,
81
static int read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
80
82
List<Item> &fields_vars, List<Item> &set_fields,
81
83
List<Item> &set_values, READ_INFO &read_info,
82
84
String &enclosed, uint32_t skip_lines,
83
85
bool ignore_check_option_errors);
85
static bool write_execute_load_query_log_event(THD *thd,
86
bool duplicates, bool ignore,
87
bool transactional_table,
88
THD::killed_state killed_status);
91
89
Execute LOAD DATA query
96
ex - sql_exchange object representing source file and its parsing rules
93
session - current thread
94
ex - file_exchange object representing source file and its parsing rules
97
95
table_list - list of tables to which we are loading data
98
96
fields_vars - list of fields and variables to which we read
121
117
String *field_term=ex->field_term,*escaped=ex->escaped;
122
118
String *enclosed=ex->enclosed;
124
LOAD_FILE_INFO lf_info;
125
char *db = table_list->db; // This is never null
120
char *db= table_list->db; // This is never null
127
123
If path for file is not defined, we will use the current database.
128
124
If this is not set, we will use the directory where the table to be
129
125
loaded is located
131
char *tdb= thd->db ? thd->db : db; // Result is never null
127
char *tdb= session->db ? session->db : db; // Result is never null
132
129
uint32_t skip_lines= ex->skip_lines;
133
130
bool transactional_table;
134
THD::killed_state killed_status= THD::NOT_KILLED;
131
Session::killed_state killed_status= Session::NOT_KILLED;
136
if (escaped->length() > 1 || enclosed->length() > 1)
133
/* Escape and enclosed character may be a utf8 4-byte character */
134
if (escaped->length() > 4 || enclosed->length() > 4)
138
my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
136
my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
142
if (open_and_lock_tables(thd, table_list))
139
if (open_and_lock_tables(session, table_list))
144
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
145
&thd->lex->select_lex.top_join_list,
141
if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
142
&session->lex->select_lex.top_join_list,
147
&thd->lex->select_lex.leaf_tables, true))
144
&session->lex->select_lex.leaf_tables, true))
170
167
for (field=table->field; *field ; field++)
171
168
fields_vars.push_back(new Item_field(*field));
172
bitmap_set_all(table->write_set);
169
table->write_set->set();
173
170
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
175
172
Let us also prepare SET clause, altough it is probably empty
178
if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
179
setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
175
if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
176
setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
183
180
{ // Part field list
184
181
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
185
if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
186
setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
187
check_that_all_fields_are_given_values(thd, table, table_list))
182
if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
183
setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
184
check_that_all_fields_are_given_values(session, table, table_list))
190
187
Check whenever TIMESTAMP field with auto-set feature specified
246
/* We can't give an error in the middle when using LOCAL files */
247
if (read_file_from_client && handle_duplicates == DUP_ERROR)
250
if (read_file_from_client)
252
(void)net_request_file(&thd->net,ex->file_name);
257
242
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
258
243
ex->file_name+=dirname_length(ex->file_name);
260
245
if (!dirname_length(ex->file_name))
262
strxnmov(name, FN_REFLEN-1, mysql_real_data_home, tdb, NULL);
247
strcpy(name, drizzle_real_data_home);
248
strncat(name, tdb, FN_REFLEN-strlen(drizzle_real_data_home)-1);
263
249
(void) fn_format(name, ex->file_name, name, "",
264
250
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
268
(void) fn_format(name, ex->file_name, mysql_real_data_home, "",
254
(void) fn_format(name, ex->file_name, drizzle_real_data_home, "",
269
255
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
271
257
if (opt_secure_file_priv &&
349
339
table->file->ha_start_bulk_insert((ha_rows) 0);
350
340
table->copy_blobs=1;
352
thd->abort_on_warning= true;
342
session->abort_on_warning= true;
354
344
if (!field_term->length() && !enclosed->length())
355
error= read_fixed_length(thd, info, table_list, fields_vars,
345
error= read_fixed_length(session, info, table_list, fields_vars,
356
346
set_fields, set_values, read_info,
357
347
skip_lines, ignore);
359
error= read_sep_field(thd, info, table_list, fields_vars,
349
error= read_sep_field(session, info, table_list, fields_vars,
360
350
set_fields, set_values, read_info,
361
351
*enclosed, skip_lines, ignore);
362
352
if (table->file->ha_end_bulk_insert() && !error)
372
362
my_close(file,MYF(0));
373
363
free_blobs(table); /* if pack_blob was used */
374
364
table->copy_blobs=0;
375
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
365
session->count_cuted_fields= CHECK_FIELD_IGNORE;
377
367
simulated killing in the middle of per-row loop
378
368
must be effective for binlogging
380
killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
370
killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
383
if (read_file_from_client)
384
while (!read_info.next_line())
387
if (mysql_bin_log.is_open())
391
Make sure last block (the one which caused the error) gets
392
logged. This is needed because otherwise after write of (to
393
the binlog, not to read_info (which is a cache))
394
Delete_file_log_event the bad block will remain in read_info
395
(because pre_read is not called at the end of the last
396
block; remember pre_read is called whenever a new block is
397
read from disk). At the end of mysql_load(), the destructor
398
of read_info will call end_io_cache() which will flush
399
read_info, so we will finally have this in the binlog:
401
Append_block # The last successfull block
403
Append_block # The failing block
405
Or could also be (for a small file)
406
Create_file # The failing block
407
which is nonsense (Delete_file is not written in this case, because:
408
Create_file has not been written, so Delete_file is not written, then
409
when read_info is destroyed end_io_cache() is called which writes
412
read_info.end_io_cache();
413
/* If the file was not empty, wrote_create_file is true */
414
if (lf_info.wrote_create_file)
416
if (thd->transaction.stmt.modified_non_trans_table)
417
write_execute_load_query_log_event(thd, handle_duplicates,
418
ignore, transactional_table,
422
Delete_file_log_event d(thd, db, transactional_table);
423
d.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
424
mysql_bin_log.write(&d);
429
373
error= -1; // Error on read
432
376
sprintf(name, ER(ER_LOAD_INFO), (uint32_t) info.records, (uint32_t) info.deleted,
433
(uint32_t) (info.records - info.copied), (uint32_t) thd->cuted_fields);
435
if (thd->transaction.stmt.modified_non_trans_table)
436
thd->transaction.all.modified_non_trans_table= true;
438
if (mysql_bin_log.is_open())
441
We need to do the job that is normally done inside
442
binlog_query() here, which is to ensure that the pending event
443
is written before tables are unlocked and before any other
444
events are written. We also need to update the table map
445
version for the binary log to mark that table maps are invalid
448
if (thd->current_stmt_binlog_row_based)
449
thd->binlog_flush_pending_rows_event(true);
453
As already explained above, we need to call end_io_cache() or the last
454
block will be logged only after Execute_load_query_log_event (which is
455
wrong), when read_info is destroyed.
457
read_info.end_io_cache();
458
if (lf_info.wrote_create_file)
460
write_execute_load_query_log_event(thd, handle_duplicates, ignore,
461
transactional_table,killed_status);
377
(uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
379
if (session->transaction.stmt.modified_non_trans_table)
380
session->transaction.all.modified_non_trans_table= true;
466
382
/* ok to client sent only after binlog write and engine commit */
467
my_ok(thd, info.copied + info.deleted, 0L, name);
383
session->my_ok(info.copied + info.deleted, 0L, name);
469
385
assert(transactional_table || !(info.copied || info.deleted) ||
470
thd->transaction.stmt.modified_non_trans_table);
386
session->transaction.stmt.modified_non_trans_table);
471
387
table->file->ha_release_auto_increment();
472
388
table->auto_increment_field_not_null= false;
473
thd->abort_on_warning= 0;
389
session->abort_on_warning= 0;
478
/* Not a very useful function; just to avoid duplication of code */
479
static bool write_execute_load_query_log_event(THD *thd,
480
bool duplicates, bool ignore,
481
bool transactional_table,
482
THD::killed_state killed_err_arg)
484
Execute_load_query_log_event
485
e(thd, thd->query, thd->query_length,
486
(char*)thd->lex->fname_start - (char*)thd->query,
487
(char*)thd->lex->fname_end - (char*)thd->query,
488
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
489
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
490
transactional_table, false, killed_err_arg);
491
e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
492
return mysql_bin_log.write(&e);
496
394
/****************************************************************************
497
395
** Read of rows of fixed size + optional garage + optonal newline
498
396
****************************************************************************/
501
read_fixed_length(THD *thd, COPY_INFO &info, TableList *table_list,
399
read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
502
400
List<Item> &fields_vars, List<Item> &set_fields,
503
401
List<Item> &set_values, READ_INFO &read_info,
504
402
uint32_t skip_lines, bool ignore_check_option_errors)
578
476
if (pos != read_info.row_end)
580
thd->cuted_fields++; /* To long row */
581
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
582
ER_WARN_TOO_MANY_RECORDS,
583
ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
478
session->cuted_fields++; /* To long row */
479
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
480
ER_WARN_TOO_MANY_RECORDS,
481
ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
587
fill_record(thd, set_fields, set_values,
484
if (session->killed ||
485
fill_record(session, set_fields, set_values,
588
486
ignore_check_option_errors))
591
err= write_record(thd, table, &info);
489
err= write_record(session, table, &info);
592
490
table->auto_increment_field_not_null= false;
597
495
We don't need to reset auto-increment field since we are restoring
598
496
its default value at the beginning of each loop iteration.