12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
17
/* Copy data from a textfile to table */
21
#include <drizzled/sql_load.h>
22
#include <drizzled/error.h>
23
#include <drizzled/data_home.h>
24
#include <drizzled/session.h>
25
#include <drizzled/sql_base.h>
26
#include <drizzled/field/epoch.h>
27
#include <drizzled/internal/my_sys.h>
28
#include <drizzled/internal/iocache.h>
29
#include <drizzled/plugin/storage_engine.h>
35
#include <boost/filesystem.hpp>
37
namespace fs=boost::filesystem;
18
/* 2006-12 Erik Wetterberg : LOAD XML added */
20
#include "mysql_priv.h"
30
XML_TAG(int l, String f, String v);
34
XML_TAG::XML_TAG(int l, String f, String v)
44
unsigned char *buffer; /* Buffer for read text */
45
unsigned char *end_of_buff; /* Data in bufferts ends here */
46
size_t buff_length; /* Length of buffert */
47
size_t max_length; /* Max length of row */
44
uchar *buffer, /* Buffer for read text */
45
*end_of_buff; /* Data in bufferts ends here */
46
uint buff_length, /* Length of buffert */
47
max_length; /* Max length of row */
48
48
char *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
49
49
uint field_term_length,line_term_length,enclosed_length;
50
50
int field_term_char,line_term_char,enclosed_char,escape_char;
51
51
int *stack,*stack_pos;
52
52
bool found_end_of_line,start_of_line,eof;
53
53
bool need_end_io_cache;
54
internal::IO_CACHE cache;
56
int level; /* for load xml */
57
59
bool error,line_cuted,found_null,enclosed;
58
unsigned char *row_start, /* Found row starts here */
60
uchar *row_start, /* Found row starts here */
59
61
*row_end; /* Found row ends here */
60
const CHARSET_INFO *read_charset;
62
CHARSET_INFO *read_charset;
62
READ_INFO(int cursor, size_t tot_length, const CHARSET_INFO * const cs,
64
READ_INFO(File file,uint tot_length,CHARSET_INFO *cs,
63
65
String &field_term,String &line_start,String &line_term,
64
String &enclosed,int escape, bool is_fifo);
66
String &enclosed,int escape,bool get_it_from_net, bool is_fifo);
67
69
int read_fixed_length(void);
68
70
int next_line(void);
69
71
char unescape(char chr);
70
int terminator(char *ptr,uint32_t length);
72
int terminator(char *ptr,uint length);
71
73
bool find_start_of_fields();
75
List<XML_TAG> taglist;
76
int read_value(int delim, String *val);
78
int clear_level(int level);
74
81
We need to force cache close before destructor is invoked to log
77
84
void end_io_cache()
86
::end_io_cache(&cache);
80
87
need_end_io_cache = 0;
84
91
Either this method, or we need to make cache public
85
Arg must be set from load() since constructor does not see
86
either the table or Session value
92
Arg must be set from mysql_load() since constructor does not see
93
either the table or THD value
88
95
void set_io_cache_arg(void* arg) { cache.arg = arg; }
91
static int read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
98
static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
92
99
List<Item> &fields_vars, List<Item> &set_fields,
93
100
List<Item> &set_values, READ_INFO &read_info,
95
102
bool ignore_check_option_errors);
96
static int read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
103
static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
97
104
List<Item> &fields_vars, List<Item> &set_fields,
98
105
List<Item> &set_values, READ_INFO &read_info,
99
String &enclosed, uint32_t skip_lines,
106
String &enclosed, ulong skip_lines,
100
107
bool ignore_check_option_errors);
109
static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
110
List<Item> &fields_vars, List<Item> &set_fields,
111
List<Item> &set_values, READ_INFO &read_info,
112
String &enclosed, ulong skip_lines,
113
bool ignore_check_option_errors);
115
static bool write_execute_load_query_log_event(THD *thd,
116
bool duplicates, bool ignore,
117
bool transactional_table,
118
THD::killed_state killed_status);
104
121
Execute LOAD DATA query
108
session - current thread
109
ex - file_exchange object representing source cursor and its parsing rules
126
ex - sql_exchange object representing source file and its parsing rules
110
127
table_list - list of tables to which we are loading data
111
128
fields_vars - list of fields and variables to which we read
113
130
set_fields - list of fields mentioned in set clause
114
131
set_values - expressions to assign to fields in previous list
115
132
handle_duplicates - indicates whenever we should emit error or
116
133
replace row if we will meet duplicates.
117
134
ignore - - indicates whenever we should ignore duplicates
135
read_file_from_client - is this LOAD DATA LOCAL ?
120
138
true - error / false - success
123
int load(Session *session,file_exchange *ex,TableList *table_list,
141
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
124
142
List<Item> &fields_vars, List<Item> &set_fields,
125
143
List<Item> &set_values,
126
enum enum_duplicates handle_duplicates, bool ignore)
144
enum enum_duplicates handle_duplicates, bool ignore,
145
bool read_file_from_client)
147
char name[FN_REFLEN];
131
151
String *field_term=ex->field_term,*escaped=ex->escaped;
132
152
String *enclosed=ex->enclosed;
135
assert(table_list->getSchemaName()); // This should never be null
154
LOAD_FILE_INFO lf_info;
155
char *db = table_list->db; // This is never null
138
If path for cursor is not defined, we will use the current database.
157
If path for file is not defined, we will use the current database.
139
158
If this is not set, we will use the directory where the table to be
140
159
loaded is located
142
util::string::const_shared_ptr schema(session->schema());
143
const char *tdb= (schema and not schema->empty()) ? schema->c_str() : table_list->getSchemaName(); // Result should never be null
145
uint32_t skip_lines= ex->skip_lines;
161
char *tdb= thd->db ? thd->db : db; // Result is never null
162
ulong skip_lines= ex->skip_lines;
146
163
bool transactional_table;
147
Session::killed_state_t killed_status= Session::NOT_KILLED;
164
THD::killed_state killed_status= THD::NOT_KILLED;
149
/* Escape and enclosed character may be a utf8 4-byte character */
150
if (escaped->length() > 4 || enclosed->length() > 4)
166
if (escaped->length() > 1 || enclosed->length() > 1)
152
my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
168
my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
156
if (session->openTablesLock(table_list))
172
if (open_and_lock_tables(thd, table_list))
159
if (setup_tables_and_check_access(session, &session->getLex()->select_lex.context,
160
&session->getLex()->select_lex.top_join_list,
174
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
175
&thd->lex->select_lex.top_join_list,
162
&session->getLex()->select_lex.leaf_tables, true))
177
&thd->lex->select_lex.leaf_tables, true))
170
185
table is marked to be 'used for insert' in which case we should never
171
186
mark this table as 'const table' (ie, one that has only one row).
173
if (unique_table(table_list, table_list->next_global))
188
if (unique_table(thd, table_list, table_list->next_global, 0))
175
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
190
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
179
194
table= table_list->table;
180
transactional_table= table->cursor->has_transactions();
195
transactional_table= table->file->has_transactions();
182
197
if (!fields_vars.elements)
185
for (field= table->getFields(); *field ; field++)
200
for (field=table->field; *field ; field++)
186
201
fields_vars.push_back(new Item_field(*field));
187
table->setWriteSet();
202
bitmap_set_all(table->write_set);
188
203
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
190
205
Let us also prepare SET clause, altough it is probably empty
193
if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
194
setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
208
if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
209
setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
198
213
{ // Part field list
199
214
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
200
if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
201
setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
202
check_that_all_fields_are_given_values(session, table, table_list))
215
if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
216
setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
217
check_that_all_fields_are_given_values(thd, table, table_list))
205
220
Check whenever TIMESTAMP field with auto-set feature specified
261
fs::path to_file(ex->file_name);
262
fs::path target_path(fs::system_complete(getDataHomeCatalog()));
263
if (not to_file.has_root_directory())
276
/* We can't give an error in the middle when using LOCAL files */
277
if (read_file_from_client && handle_duplicates == DUP_ERROR)
280
if (read_file_from_client)
265
int count_elements= 0;
266
for (fs::path::iterator iter= to_file.begin();
267
iter != to_file.end();
268
++iter, ++count_elements)
271
if (count_elements == 1)
275
target_path /= to_file;
282
(void)net_request_file(&thd->net,ex->file_name);
279
target_path= to_file;
282
if (not secure_file_priv.string().empty())
284
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
286
/* Read only allowed from within dir specified by secure_file_priv */
287
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
287
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
288
ex->file_name+=dirname_length(ex->file_name);
290
if (!dirname_length(ex->file_name))
292
strxnmov(name, FN_REFLEN-1, mysql_real_data_home, tdb, NullS);
293
(void) fn_format(name, ex->file_name, name, "",
294
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
298
(void) fn_format(name, ex->file_name, mysql_real_data_home, "",
299
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
301
if (opt_secure_file_priv &&
302
strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
304
/* Read only allowed from within dir specified by secure_file_priv */
305
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
309
struct stat stat_info;
310
if (stat(name,&stat_info))
313
// if we are not in slave thread, the file must be:
314
if (!thd->slave_thread &&
315
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
316
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
317
((stat_info.st_mode & S_IFREG) == S_IFREG ||
318
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
320
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
323
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
326
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
292
struct stat stat_info;
293
if (stat(target_path.file_string().c_str(), &stat_info))
295
my_error(ER_FILE_NOT_FOUND, MYF(0), target_path.file_string().c_str(), errno);
299
// if we are not in slave thread, the cursor must be:
300
if (!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
301
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
302
((stat_info.st_mode & S_IFREG) == S_IFREG ||
303
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
305
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), target_path.file_string().c_str());
308
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
312
if ((file=internal::my_open(target_path.file_string().c_str(), O_RDONLY,MYF(MY_WME))) < 0)
314
my_error(ER_CANT_OPEN_FILE, MYF(0), target_path.file_string().c_str(), errno);
318
memset(&info, 0, sizeof(info));
331
bzero((char*) &info,sizeof(info));
319
332
info.ignore= ignore;
320
333
info.handle_duplicates=handle_duplicates;
321
334
info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
323
identifier::Schema identifier(*schema);
324
READ_INFO read_info(file, tot_length,
325
ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(identifier),
326
*field_term, *ex->line_start, *ex->line_term, *enclosed,
327
info.escape_char, is_fifo);
336
READ_INFO read_info(file,tot_length,
337
ex->cs ? ex->cs : thd->variables.collation_database,
338
*field_term,*ex->line_start, *ex->line_term, *enclosed,
339
info.escape_char, read_file_from_client, is_fifo);
328
340
if (read_info.error)
331
internal::my_close(file,MYF(0)); // no files in net reading
343
my_close(file,MYF(0)); // no files in net reading
332
344
return(true); // Can't allocate buffers
336
* Per the SQL standard, inserting NULL into a NOT NULL
337
* field requires an error to be thrown.
341
* NULL check and handling occurs in field_conv.cc
343
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
344
session->cuted_fields=0L;
347
if (mysql_bin_log.is_open())
350
lf_info.wrote_create_file = 0;
351
lf_info.last_pos_in_file = HA_POS_ERROR;
352
lf_info.log_delayed= transactional_table;
353
read_info.set_io_cache_arg((void*) &lf_info);
356
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
357
thd->cuted_fields=0L;
345
358
/* Skip lines if there is a line terminator */
346
if (ex->line_term->length())
359
if (ex->line_term->length() && ex->filetype != FILETYPE_XML)
348
361
/* ex->skip_lines needs to be preserved for logging */
349
362
while (skip_lines > 0)
360
373
table->next_number_field=table->found_next_number_field;
362
375
handle_duplicates == DUP_REPLACE)
363
table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
376
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
364
377
if (handle_duplicates == DUP_REPLACE)
365
table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
366
table->cursor->ha_start_bulk_insert((ha_rows) 0);
378
table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
379
table->file->ha_start_bulk_insert((ha_rows) 0);
367
380
table->copy_blobs=1;
369
session->setAbortOnWarning(true);
382
thd->abort_on_warning= (!ignore &&
383
(thd->variables.sql_mode &
384
(MODE_STRICT_TRANS_TABLES |
385
MODE_STRICT_ALL_TABLES)));
371
if (!field_term->length() && !enclosed->length())
372
error= read_fixed_length(session, info, table_list, fields_vars,
387
if (ex->filetype == FILETYPE_XML) /* load xml */
388
error= read_xml_field(thd, info, table_list, fields_vars,
389
set_fields, set_values, read_info,
390
*(ex->line_term), skip_lines, ignore);
391
else if (!field_term->length() && !enclosed->length())
392
error= read_fixed_length(thd, info, table_list, fields_vars,
373
393
set_fields, set_values, read_info,
374
394
skip_lines, ignore);
376
error= read_sep_field(session, info, table_list, fields_vars,
396
error= read_sep_field(thd, info, table_list, fields_vars,
377
397
set_fields, set_values, read_info,
378
398
*enclosed, skip_lines, ignore);
379
if (table->cursor->ha_end_bulk_insert() && !error)
399
if (table->file->ha_end_bulk_insert() && !error)
381
table->print_error(errno, MYF(0));
401
table->file->print_error(my_errno, MYF(0));
384
table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
385
table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
404
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
405
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
386
406
table->next_number_field=0;
389
internal::my_close(file,MYF(0));
409
my_close(file,MYF(0));
390
410
free_blobs(table); /* if pack_blob was used */
391
411
table->copy_blobs=0;
392
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
412
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
394
414
simulated killing in the middle of per-row loop
395
415
must be effective for binlogging
397
killed_status= (error == 0)? Session::NOT_KILLED : session->getKilled();
417
killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
420
if (read_file_from_client)
421
while (!read_info.next_line())
424
if (mysql_bin_log.is_open())
428
Make sure last block (the one which caused the error) gets
429
logged. This is needed because otherwise after write of (to
430
the binlog, not to read_info (which is a cache))
431
Delete_file_log_event the bad block will remain in read_info
432
(because pre_read is not called at the end of the last
433
block; remember pre_read is called whenever a new block is
434
read from disk). At the end of mysql_load(), the destructor
435
of read_info will call end_io_cache() which will flush
436
read_info, so we will finally have this in the binlog:
438
Append_block # The last successfull block
440
Append_block # The failing block
442
Or could also be (for a small file)
443
Create_file # The failing block
444
which is nonsense (Delete_file is not written in this case, because:
445
Create_file has not been written, so Delete_file is not written, then
446
when read_info is destroyed end_io_cache() is called which writes
449
read_info.end_io_cache();
450
/* If the file was not empty, wrote_create_file is true */
451
if (lf_info.wrote_create_file)
453
if (thd->transaction.stmt.modified_non_trans_table)
454
write_execute_load_query_log_event(thd, handle_duplicates,
455
ignore, transactional_table,
459
Delete_file_log_event d(thd, db, transactional_table);
460
d.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
461
mysql_bin_log.write(&d);
400
466
error= -1; // Error on read
405
snprintf(msg, sizeof(msg), ER(ER_LOAD_INFO), info.records, info.deleted,
406
(info.records - info.copied), session->cuted_fields);
408
if (session->transaction.stmt.hasModifiedNonTransData())
409
session->transaction.all.markModifiedNonTransData();
469
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
470
(ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
472
if (thd->transaction.stmt.modified_non_trans_table)
473
thd->transaction.all.modified_non_trans_table= true;
475
if (mysql_bin_log.is_open())
478
We need to do the job that is normally done inside
479
binlog_query() here, which is to ensure that the pending event
480
is written before tables are unlocked and before any other
481
events are written. We also need to update the table map
482
version for the binary log to mark that table maps are invalid
485
if (thd->current_stmt_binlog_row_based)
486
thd->binlog_flush_pending_rows_event(true);
490
As already explained above, we need to call end_io_cache() or the last
491
block will be logged only after Execute_load_query_log_event (which is
492
wrong), when read_info is destroyed.
494
read_info.end_io_cache();
495
if (lf_info.wrote_create_file)
497
write_execute_load_query_log_event(thd, handle_duplicates, ignore,
498
transactional_table,killed_status);
411
503
/* ok to client sent only after binlog write and engine commit */
412
session->my_ok(info.copied + info.deleted, 0, 0L, msg);
504
my_ok(thd, info.copied + info.deleted, 0L, name);
414
506
assert(transactional_table || !(info.copied || info.deleted) ||
415
session->transaction.stmt.hasModifiedNonTransData());
416
table->cursor->ha_release_auto_increment();
507
thd->transaction.stmt.modified_non_trans_table);
508
table->file->ha_release_auto_increment();
417
509
table->auto_increment_field_not_null= false;
418
session->setAbortOnWarning(false);
510
thd->abort_on_warning= 0;
515
/* Not a very useful function; just to avoid duplication of code */
516
static bool write_execute_load_query_log_event(THD *thd,
517
bool duplicates, bool ignore,
518
bool transactional_table,
519
THD::killed_state killed_err_arg)
521
Execute_load_query_log_event
522
e(thd, thd->query, thd->query_length,
523
(char*)thd->lex->fname_start - (char*)thd->query,
524
(char*)thd->lex->fname_end - (char*)thd->query,
525
(duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
526
(ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
527
transactional_table, false, killed_err_arg);
528
e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
529
return mysql_bin_log.write(&e);
424
533
/****************************************************************************
425
534
** Read of rows of fixed size + optional garage + optonal newline
426
535
****************************************************************************/
429
read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
538
read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
430
539
List<Item> &fields_vars, List<Item> &set_fields,
431
540
List<Item> &set_values, READ_INFO &read_info,
432
uint32_t skip_lines, bool ignore_check_option_errors)
541
ulong skip_lines, bool ignore_check_option_errors)
434
List<Item>::iterator it(fields_vars.begin());
543
List_iterator_fast<Item> it(fields_vars);
435
544
Item_field *sql_field;
436
Table *table= table_list->table;
545
TABLE *table= table_list->table;
442
551
while (!read_info.read_fixed_length())
444
if (session->getKilled())
446
session->send_kill_message();
555
thd->send_kill_message();
718
820
if (read_info.line_cuted)
720
session->cuted_fields++; /* To long row */
721
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
722
ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
724
if (session->getKilled())
822
thd->cuted_fields++; /* To long row */
823
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
824
ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
727
session->row_count++;
729
831
return(test(read_info.error));
835
/****************************************************************************
836
** Read rows in xml format
837
****************************************************************************/
839
read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
840
List<Item> &fields_vars, List<Item> &set_fields,
841
List<Item> &set_values, READ_INFO &read_info,
842
String &row_tag __attribute__((__unused__)),
844
bool ignore_check_option_errors)
846
List_iterator_fast<Item> it(fields_vars);
848
TABLE *table= table_list->table;
849
bool no_trans_update_stmt;
850
CHARSET_INFO *cs= read_info.read_charset;
852
no_trans_update_stmt= !table->file->has_transactions();
854
for ( ; ; it.rewind())
858
thd->send_kill_message();
862
// read row tag and save values into tag list
863
if (read_info.read_xml())
866
List_iterator_fast<XML_TAG> xmlit(read_info.taglist);
871
restore_record(table, s->default_values);
875
/* If this line is to be skipped we don't want to fill field or var */
879
/* find field in tag list */
883
while(tag && strcmp(tag->field.c_ptr(), item->name) != 0)
886
if (!tag) // found null
888
if (item->type() == Item::FIELD_ITEM)
890
Field *field= ((Item_field *) item)->field;
893
if (field == table->next_number_field)
894
table->auto_increment_field_not_null= true;
895
if (!field->maybe_null())
897
if (field->type() == FIELD_TYPE_TIMESTAMP)
898
((Field_timestamp *) field)->set_time();
899
else if (field != table->next_number_field)
900
field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
901
ER_WARN_NULL_TO_NOTNULL, 1);
905
((Item_user_var_as_out_param *) item)->set_null_value(cs);
909
if (item->type() == Item::FIELD_ITEM)
912
Field *field= ((Item_field *)item)->field;
913
field->set_notnull();
914
if (field == table->next_number_field)
915
table->auto_increment_field_not_null= true;
916
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
919
((Item_user_var_as_out_param *) item)->set_value(
920
(char *) tag->value.ptr(),
921
tag->value.length(), cs);
935
/* Have not read any field, thus input file is simply ended */
936
if (item == fields_vars.head())
939
for ( ; item; item= it++)
941
if (item->type() == Item::FIELD_ITEM)
944
QQ: We probably should not throw warning for each field.
945
But how about intention to always have the same number
946
of warnings in THD::cuted_fields (and get rid of cuted_fields
950
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
951
ER_WARN_TOO_FEW_RECORDS,
952
ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
955
((Item_user_var_as_out_param *)item)->set_null_value(cs);
959
if (thd->killed || fill_record(thd, set_fields, set_values,
960
ignore_check_option_errors))
963
if (write_record(thd, table, &info))
967
We don't need to reset auto-increment field since we are restoring
968
its default value at the beginning of each loop iteration.
970
thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
973
return(test(read_info.error));
733
977
/* Unescape all escape characters, mark \N as null */
787
1032
line_term_ptr=(char*) "";
789
1034
enclosed_char= (enclosed_length=enclosed_par.length()) ?
790
(unsigned char) enclosed_par[0] : INT_MAX;
791
field_term_char= field_term_length ? (unsigned char) field_term_ptr[0] : INT_MAX;
792
line_term_char= line_term_length ? (unsigned char) line_term_ptr[0] : INT_MAX;
1035
(uchar) enclosed_par[0] : INT_MAX;
1036
field_term_char= field_term_length ? (uchar) field_term_ptr[0] : INT_MAX;
1037
line_term_char= line_term_length ? (uchar) line_term_ptr[0] : INT_MAX;
793
1038
error=eof=found_end_of_line=found_null=line_cuted=0;
794
1039
buff_length=tot_length;
797
1042
/* Set of a stack for unget if long terminators */
798
size_t length= max(field_term_length,line_term_length)+1;
799
set_if_bigger(length, line_start.length());
800
stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
1043
uint length=max(field_term_length,line_term_length)+1;
1044
set_if_bigger(length,line_start.length());
1045
stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);
802
if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
1047
if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0))))
1048
error=1; /* purecov: inspected */
806
1051
end_of_buff=buffer+buff_length;
807
if (cache.init_io_cache((false) ? -1 : cursor, 0,
808
(false) ? internal::READ_NET :
809
(is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
1052
if (init_io_cache(&cache,(get_it_from_net) ? -1 : file, 0,
1053
(get_it_from_net) ? READ_NET :
1054
(is_fifo ? READ_FIFO : READ_CACHE),0L,1,
812
free((unsigned char*) buffer);
1057
my_free((uchar*) buffer,MYF(0)); /* purecov: inspected */
948
1206
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
949
1207
if (chr == line_term_char)
951
if (chr == line_term_char && found_enclosed_char == INT_MAX)
1209
if (chr == line_term_char && found_enclosed_char == INT_MAX)
954
if (terminator(line_term_ptr,line_term_length))
955
{ // Maybe unexpected linefeed
1212
if (terminator(line_term_ptr,line_term_length))
1213
{ // Maybe unexpected linefeed
1215
found_end_of_line=1;
963
1221
if (chr == found_enclosed_char)
965
if ((chr=GET) == found_enclosed_char)
966
{ // Remove dupplicated
967
*to++ = (unsigned char) chr;
970
// End of enclosed field if followed by field_term or line_term
971
if (chr == my_b_EOF ||
972
(chr == line_term_char && terminator(line_term_ptr, line_term_length)))
973
{ // Maybe unexpected linefeed
980
if (chr == field_term_char &&
981
terminator(field_term_ptr,field_term_length))
989
The string didn't terminate yet.
990
Store back next character for the loop
993
/* copy the found term character to 'to' */
994
chr= found_enclosed_char;
1223
if ((chr=GET) == found_enclosed_char)
1224
{ // Remove dupplicated
1225
*to++ = (uchar) chr;
1228
// End of enclosed field if followed by field_term or line_term
1229
if (chr == my_b_EOF ||
1230
(chr == line_term_char && terminator(line_term_ptr, line_term_length)))
1231
{ // Maybe unexpected linefeed
1233
found_end_of_line=1;
1238
if (chr == field_term_char &&
1239
terminator(field_term_ptr,field_term_length))
1247
The string didn't terminate yet.
1248
Store back next character for the loop
1251
/* copy the found term character to 'to' */
1252
chr= found_enclosed_char;
996
1254
else if (chr == field_term_char && found_enclosed_char == INT_MAX)
998
if (terminator(field_term_ptr,field_term_length))
1256
if (terminator(field_term_ptr,field_term_length))
1006
*to++ = (unsigned char) chr;
1264
*to++ = (uchar) chr;
1009
** We come here if buffer is too small. Enlarge it and continue
1011
if (!(new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE)))
1267
** We come here if buffer is too small. Enlarge it and continue
1269
if (!(new_buffer=(uchar*) my_realloc((char*) buffer,buff_length+1+IO_SIZE,
1012
1271
return (error=1);
1013
1272
to=new_buffer + (to-buffer);
1014
1273
buffer=new_buffer;
1165
} /* namespace drizzled */
1427
Clear taglist from tags with a specified level
1429
int READ_INFO::clear_level(int level)
1431
List_iterator<XML_TAG> xmlit(taglist);
1435
while ((tag= xmlit++))
1437
if(tag->level >= level)
1448
Convert an XML entity to Unicode value.
1452
my_xml_entity_to_char(const char *name, uint length)
1456
if (!memcmp(name, "gt", length))
1458
if (!memcmp(name, "lt", length))
1461
else if (length == 3)
1463
if (!memcmp(name, "amp", length))
1466
else if (length == 4)
1468
if (!memcmp(name, "quot", length))
1470
if (!memcmp(name, "apos", length))
1478
@brief Convert newline, linefeed, tab to space
1480
@param chr character
1482
@details According to the "XML 1.0" standard,
1483
only space (#x20) characters, carriage returns,
1484
line feeds or tabs are considered as spaces.
1485
Convert all of them to space (#x20) for parsing simplicity.
1490
return (chr == '\t' || chr == '\r' || chr == '\n') ? ' ' : chr;
1495
Read an xml value: handle multibyte and xml escape
1497
int READ_INFO::read_value(int delim, String *val)
1502
for (chr= my_tospace(GET); chr != delim && chr != my_b_EOF; )
1505
if (my_mbcharlen(read_charset, chr) > 1)
1507
int i, ml= my_mbcharlen(read_charset, chr);
1508
for (i= 1; i < ml; i++)
1512
Don't use my_tospace() in the middle of a multi-byte character
1513
TODO: check that the multi-byte sequence is valid.
1516
if (chr == my_b_EOF)
1524
for (chr= my_tospace(GET) ; chr != ';' ; chr= my_tospace(GET))
1526
if (chr == my_b_EOF)
1530
if ((chr= my_xml_entity_to_char(tmp.ptr(), tmp.length())) >= 0)
1541
chr= my_tospace(GET);
1548
Read a record in xml format
1549
tags and attributes are stored in taglist
1550
when tag set in ROWS IDENTIFIED BY is closed, we are ready and return
1552
int READ_INFO::read_xml()
1554
int chr, chr2, chr3;
1556
String tag, attribute, value;
1560
attribute.length(0);
1563
for (chr= my_tospace(GET); chr != my_b_EOF ; )
1566
case '<': /* read tag */
1567
/* TODO: check if this is a comment <!-- comment --> */
1568
chr= my_tospace(GET);
1574
if(chr2 == '-' && chr3 == '-')
1578
chr= my_tospace(GET);
1580
while(chr != '>' || chr2 != '-' || chr3 != '-')
1587
else if (chr2 == '-')
1592
chr= my_tospace(GET);
1593
if (chr == my_b_EOF)
1601
while(chr != '>' && chr != ' ' && chr != '/' && chr != my_b_EOF)
1603
if(chr != delim) /* fix for the '<field name =' format */
1605
chr= my_tospace(GET);
1608
if(chr == ' ' || chr == '>')
1611
clear_level(level + 1);
1620
case ' ': /* read attribute */
1621
while(chr == ' ') /* skip blanks */
1622
chr= my_tospace(GET);
1627
while(chr != '=' && chr != '/' && chr != '>' && chr != my_b_EOF)
1629
attribute.append(chr);
1630
chr= my_tospace(GET);
1634
case '>': /* end tag - read tag value */
1636
chr= read_value('<', &value);
1640
/* save value to list */
1641
if(tag.length() > 0 && value.length() > 0)
1642
taglist.push_front( new XML_TAG(level, tag, value));
1646
attribute.length(0);
1649
case '/': /* close tag */
1651
chr= my_tospace(GET);
1652
if(chr != '>') /* if this is an empty tag <tag /> */
1653
tag.length(0); /* we should keep tag value */
1654
while(chr != '>' && chr != my_b_EOF)
1657
chr= my_tospace(GET);
1660
if((tag.length() == line_term_length -2) &&
1661
(strncmp(tag.c_ptr_safe(), line_term_ptr + 1, tag.length()) == 0))
1662
return(0); //normal return
1664
chr= my_tospace(GET);
1667
case '=': /* attribute name end - read the value */
1668
//check for tag field and attribute name
1669
if(!memcmp(tag.c_ptr_safe(), STRING_WITH_LEN("field")) &&
1670
!memcmp(attribute.c_ptr_safe(), STRING_WITH_LEN("name")))
1673
this is format <field name="xx">xx</field>
1674
where actual fieldname is in attribute
1676
delim= my_tospace(GET);
1678
attribute.length(0);
1679
chr= '<'; /* we pretend that it is a tag */
1686
if (chr == my_b_EOF)
1688
if(chr == '"' || chr == '\'')
1694
delim= ' '; /* no delimiter, use space */
1698
chr= read_value(delim, &value);
1699
if(attribute.length() > 0 && value.length() > 0)
1700
taglist.push_front(new XML_TAG(level + 1, attribute, value));
1702
attribute.length(0);
1705
chr= my_tospace(GET);
1709
chr= my_tospace(GET);