1 /*
2 Copyright (c) 2000, 2016, Oracle and/or its affiliates.
3 Copyright (c) 2010, 2018, MariaDB Corporation.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
17
18
19 /* Copy data from a textfile to table */
20 /* 2006-12 Erik Wetterberg : LOAD XML added */
21
22 #include "mariadb.h"
23 #include "sql_priv.h"
24 #include "unireg.h"
25 #include "sql_load.h"
26 #include "sql_load.h"
27 #include "sql_cache.h" // query_cache_*
28 #include "sql_base.h" // fill_record_n_invoke_before_triggers
29 #include <my_dir.h>
30 #include "sql_view.h" // check_key_in_view
31 #include "sql_insert.h" // check_that_all_fields_are_given_values,
32 // write_record
33 #include "sql_acl.h" // INSERT_ACL, UPDATE_ACL
34 #include "log_event.h" // Delete_file_log_event,
35 // Execute_load_query_log_event,
36 // LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F
37 #include <m_ctype.h>
38 #include "rpl_mi.h"
39 #include "sql_repl.h"
40 #include "sp_head.h"
41 #include "sql_trigger.h"
42 #include "sql_derived.h"
43 #include "sql_show.h"
44 #include "debug_sync.h"
45
46 extern "C" int _my_b_net_read(IO_CACHE *info, uchar *Buffer, size_t Count);
47
48 class XML_TAG {
49 public:
50 int level;
51 String field;
52 String value;
53 XML_TAG(int l, String f, String v);
54 };
55
56
XML_TAG(int l,String f,String v)57 XML_TAG::XML_TAG(int l, String f, String v)
58 {
59 level= l;
60 field.append(f);
61 value.append(v);
62 }
63
64
65 /*
66 Field and line terminators must be interpreted as sequence of unsigned char.
67 Otherwise, non-ascii terminators will be negative on some platforms,
68 and positive on others (depending on the implementation of char).
69 */
70 class Term_string
71 {
72 const uchar *m_ptr;
73 uint m_length;
74 int m_initial_byte;
75 public:
Term_string(const String & str)76 Term_string(const String &str) :
77 m_ptr(static_cast<const uchar*>(static_cast<const void*>(str.ptr()))),
78 m_length(str.length()),
79 m_initial_byte((uchar) (str.length() ? str.ptr()[0] : INT_MAX))
80 { }
set(const uchar * str,uint length,int initial_byte)81 void set(const uchar *str, uint length, int initial_byte)
82 {
83 m_ptr= str;
84 m_length= length;
85 m_initial_byte= initial_byte;
86 }
reset()87 void reset() { set(NULL, 0, INT_MAX); }
ptr() const88 const uchar *ptr() const { return m_ptr; }
length() const89 uint length() const { return m_length; }
initial_byte() const90 int initial_byte() const { return m_initial_byte; }
eq(const Term_string & other) const91 bool eq(const Term_string &other) const
92 {
93 return length() == other.length() && !memcmp(ptr(), other.ptr(), length());
94 }
95 };
96
97
98 #define GET (stack_pos != stack ? *--stack_pos : my_b_get(&cache))
99 #define PUSH(A) *(stack_pos++)=(A)
100
101 #ifdef WITH_WSREP
102 /** If requested by wsrep_load_data_splitting, commit and restart
103 the transaction after every 10,000 inserted rows. */
104
wsrep_load_data_split(THD * thd,const TABLE * table,const COPY_INFO & info)105 static bool wsrep_load_data_split(THD *thd, const TABLE *table,
106 const COPY_INFO &info)
107 {
108 DBUG_ENTER("wsrep_load_data_split");
109
110 if (!wsrep_load_data_splitting || !wsrep_on(thd)
111 || !info.records || (info.records % 10000)
112 || !thd->transaction.stmt.ha_list
113 || thd->transaction.stmt.ha_list->ht() != binlog_hton
114 || !thd->transaction.stmt.ha_list->next()
115 || thd->transaction.stmt.ha_list->next()->next())
116 DBUG_RETURN(false);
117
118 if (handlerton* hton= thd->transaction.stmt.ha_list->next()->ht())
119 {
120 if (hton->db_type != DB_TYPE_INNODB)
121 DBUG_RETURN(false);
122 WSREP_DEBUG("intermediate transaction commit in LOAD DATA");
123 wsrep_set_load_multi_commit(thd, true);
124 if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true);
125 if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true);
126 wsrep_post_commit(thd, true);
127 hton->commit(hton, thd, true);
128 wsrep_set_load_multi_commit(thd, false);
129 DEBUG_SYNC(thd, "intermediate_transaction_commit");
130 table->file->extra(HA_EXTRA_FAKE_START_STMT);
131 }
132
133 DBUG_RETURN(false);
134 }
135 /*
136 If the commit fails, then an early return from
137 the function occurs there and therefore we need
138 to reset the table->auto_increment_field_not_null
139 flag, which is usually reset after calling
140 the write_record():
141 */
142 #define WSREP_LOAD_DATA_SPLIT(thd,table,info) \
143 if (wsrep_load_data_split(thd,table,info)) \
144 { \
145 table->auto_increment_field_not_null= FALSE; \
146 DBUG_RETURN(1); \
147 }
148 #else /* WITH_WSREP */
149 #define WSREP_LOAD_DATA_SPLIT(thd,table,info) /* empty */
150 #endif /* WITH_WSREP */
151
152 #define WRITE_RECORD(thd,table,info) \
153 do { \
154 int err_= write_record(thd, table, &info); \
155 table->auto_increment_field_not_null= FALSE; \
156 if (err_) \
157 DBUG_RETURN(1); \
158 } while (0)
159
160 class READ_INFO: public Load_data_param
161 {
162 File file;
163 String data; /* Read buffer */
164 Term_string m_field_term; /* FIELDS TERMINATED BY 'string' */
165 Term_string m_line_term; /* LINES TERMINATED BY 'string' */
166 Term_string m_line_start; /* LINES STARTING BY 'string' */
167 int enclosed_char,escape_char;
168 int *stack,*stack_pos;
169 bool found_end_of_line,start_of_line,eof;
170 int level; /* for load xml */
171
getbyte(char * to)172 bool getbyte(char *to)
173 {
174 int chr= GET;
175 if (chr == my_b_EOF)
176 return (eof= true);
177 *to= chr;
178 return false;
179 }
180
181 /**
182 Read a tail of a multi-byte character.
183 The first byte of the character is assumed to be already
184 read from the file and appended to "str".
185
186 @returns true - if EOF happened unexpectedly
187 @returns false - no EOF happened: found a good multi-byte character,
188 or a bad byte sequence
189
190 Note:
191 The return value depends only on EOF:
192 - read_mbtail() returns "false" is a good character was read, but also
193 - read_mbtail() returns "false" if an incomplete byte sequence was found
194 and no EOF happened.
195
196 For example, suppose we have an ujis file with bytes 0x8FA10A, where:
197 - 0x8FA1 is an incomplete prefix of a 3-byte character
198 (it should be [8F][A1-FE][A1-FE] to make a full 3-byte character)
199 - 0x0A is a line demiliter
200 This file has some broken data, the trailing [A1-FE] is missing.
201
202 In this example it works as follows:
203 - 0x8F is read from the file and put into "data" before the call
204 for read_mbtail()
205 - 0xA1 is read from the file and put into "data" by read_mbtail()
206 - 0x0A is kept in the read queue, so the next read iteration after
207 the current read_mbtail() call will normally find it and recognize as
208 a line delimiter
209 - the current call for read_mbtail() returns "false",
210 because no EOF happened
211 */
read_mbtail(String * str)212 bool read_mbtail(String *str)
213 {
214 int chlen;
215 if ((chlen= my_charlen(charset(), str->end() - 1, str->end())) == 1)
216 return false; // Single byte character found
217 for (uint32 length0= str->length() - 1 ; MY_CS_IS_TOOSMALL(chlen); )
218 {
219 int chr= GET;
220 if (chr == my_b_EOF)
221 {
222 DBUG_PRINT("info", ("read_mbtail: chlen=%d; unexpected EOF", chlen));
223 return true; // EOF
224 }
225 str->append(chr);
226 chlen= my_charlen(charset(), str->ptr() + length0, str->end());
227 if (chlen == MY_CS_ILSEQ)
228 {
229 /**
230 It has been an incomplete (but a valid) sequence so far,
231 but the last byte turned it into a bad byte sequence.
232 Unget the very last byte.
233 */
234 str->length(str->length() - 1);
235 PUSH(chr);
236 DBUG_PRINT("info", ("read_mbtail: ILSEQ"));
237 return false; // Bad byte sequence
238 }
239 }
240 DBUG_PRINT("info", ("read_mbtail: chlen=%d", chlen));
241 return false; // Good multi-byte character
242 }
243
244 public:
245 bool error,line_cuted,found_null,enclosed;
246 uchar *row_start, /* Found row starts here */
247 *row_end; /* Found row ends here */
248 LOAD_FILE_IO_CACHE cache;
249
250 READ_INFO(THD *thd, File file, const Load_data_param ¶m,
251 String &field_term,String &line_start,String &line_term,
252 String &enclosed,int escape,bool get_it_from_net, bool is_fifo);
253 ~READ_INFO();
254 int read_field();
255 int read_fixed_length(void);
256 int next_line(void);
257 char unescape(char chr);
258 bool terminator(const uchar *ptr, uint length);
terminator(const Term_string & str)259 bool terminator(const Term_string &str)
260 { return terminator(str.ptr(), str.length()); }
terminator(int chr,const Term_string & str)261 bool terminator(int chr, const Term_string &str)
262 { return str.initial_byte() == chr && terminator(str); }
263 bool find_start_of_fields();
264 /* load xml */
265 List<XML_TAG> taglist;
266 int read_value(int delim, String *val);
267 int read_xml(THD *thd);
268 int clear_level(int level);
269
file_length()270 my_off_t file_length() { return cache.end_of_file; }
position()271 my_off_t position() { return my_b_tell(&cache); }
272
273 /**
274 skip all data till the eof.
275 */
skip_data_till_eof()276 void skip_data_till_eof()
277 {
278 while (GET != my_b_EOF)
279 ;
280 }
281 };
282
283 static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
284 List<Item> &fields_vars, List<Item> &set_fields,
285 List<Item> &set_values, READ_INFO &read_info,
286 ulong skip_lines,
287 bool ignore_check_option_errors);
288 static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
289 List<Item> &fields_vars, List<Item> &set_fields,
290 List<Item> &set_values, READ_INFO &read_info,
291 String &enclosed, ulong skip_lines,
292 bool ignore_check_option_errors);
293
294 static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
295 List<Item> &fields_vars, List<Item> &set_fields,
296 List<Item> &set_values, READ_INFO &read_info,
297 String &enclosed, ulong skip_lines,
298 bool ignore_check_option_errors);
299
300 #ifndef EMBEDDED_LIBRARY
301 static bool write_execute_load_query_log_event(THD *, const sql_exchange*, const
302 char*, const char*, bool, enum enum_duplicates, bool, bool, int);
303 #endif /* EMBEDDED_LIBRARY */
304
305
add_outvar_field(THD * thd,const Field * field)306 bool Load_data_param::add_outvar_field(THD *thd, const Field *field)
307 {
308 if (field->flags & BLOB_FLAG)
309 {
310 m_use_blobs= true;
311 m_fixed_length+= 256; // Will be extended if needed
312 }
313 else
314 m_fixed_length+= field->field_length;
315 return false;
316 }
317
318
add_outvar_user_var(THD * thd)319 bool Load_data_param::add_outvar_user_var(THD *thd)
320 {
321 if (m_is_fixed_length)
322 {
323 my_error(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR, MYF(0));
324 return true;
325 }
326 return false;
327 }
328
329
330 /*
331 Execute LOAD DATA query
332
333 SYNOPSYS
334 mysql_load()
335 thd - current thread
336 ex - sql_exchange object representing source file and its parsing rules
337 table_list - list of tables to which we are loading data
338 fields_vars - list of fields and variables to which we read
339 data from file
340 set_fields - list of fields mentioned in set clause
341 set_values - expressions to assign to fields in previous list
342 handle_duplicates - indicates whenever we should emit error or
343 replace row if we will meet duplicates.
344 ignore - - indicates whenever we should ignore duplicates
345 read_file_from_client - is this LOAD DATA LOCAL ?
346
347 RETURN VALUES
348 TRUE - error / FALSE - success
349 */
350
mysql_load(THD * thd,const sql_exchange * ex,TABLE_LIST * table_list,List<Item> & fields_vars,List<Item> & set_fields,List<Item> & set_values,enum enum_duplicates handle_duplicates,bool ignore,bool read_file_from_client)351 int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list,
352 List<Item> &fields_vars, List<Item> &set_fields,
353 List<Item> &set_values,
354 enum enum_duplicates handle_duplicates, bool ignore,
355 bool read_file_from_client)
356 {
357 char name[FN_REFLEN];
358 File file;
359 TABLE *table= NULL;
360 int error= 0;
361 bool is_fifo=0;
362 #ifndef EMBEDDED_LIBRARY
363 killed_state killed_status;
364 bool is_concurrent;
365 #endif
366 const char *db= table_list->db.str; // This is never null
367 /*
368 If path for file is not defined, we will use the current database.
369 If this is not set, we will use the directory where the table to be
370 loaded is located
371 */
372 const char *tdb= thd->db.str ? thd->db.str : db; // Result is never null
373 ulong skip_lines= ex->skip_lines;
374 bool transactional_table __attribute__((unused));
375 DBUG_ENTER("mysql_load");
376
377 /*
378 Bug #34283
379 mysqlbinlog leaves tmpfile after termination if binlog contains
380 load data infile, so in mixed mode we go to row-based for
381 avoiding the problem.
382 */
383 thd->set_current_stmt_binlog_format_row_if_mixed();
384
385 #ifdef EMBEDDED_LIBRARY
386 read_file_from_client = 0; //server is always in the same process
387 #endif
388
389 if (ex->escaped->length() > 1 || ex->enclosed->length() > 1)
390 {
391 my_message(ER_WRONG_FIELD_TERMINATORS,
392 ER_THD(thd, ER_WRONG_FIELD_TERMINATORS),
393 MYF(0));
394 DBUG_RETURN(TRUE);
395 }
396
397 /* Report problems with non-ascii separators */
398 if (!ex->escaped->is_ascii() || !ex->enclosed->is_ascii() ||
399 !ex->field_term->is_ascii() ||
400 !ex->line_term->is_ascii() || !ex->line_start->is_ascii())
401 {
402 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
403 WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED,
404 ER_THD(thd, WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED));
405 }
406
407 if (open_and_lock_tables(thd, table_list, TRUE, 0))
408 DBUG_RETURN(TRUE);
409 if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
410 DBUG_RETURN(TRUE);
411 if (thd->lex->handle_list_of_derived(table_list, DT_PREPARE))
412 DBUG_RETURN(TRUE);
413 if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
414 &thd->lex->select_lex.top_join_list,
415 table_list,
416 thd->lex->select_lex.leaf_tables, FALSE,
417 INSERT_ACL | UPDATE_ACL,
418 INSERT_ACL | UPDATE_ACL, FALSE))
419 DBUG_RETURN(-1);
420 if (!table_list->table || // do not suport join view
421 !table_list->single_table_updatable() || // and derived tables
422 check_key_in_view(thd, table_list))
423 {
424 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "LOAD");
425 DBUG_RETURN(TRUE);
426 }
427 if (table_list->is_multitable())
428 {
429 my_error(ER_WRONG_USAGE, MYF(0), "Multi-table VIEW", "LOAD");
430 DBUG_RETURN(TRUE);
431 }
432 if (table_list->prepare_where(thd, 0, TRUE) ||
433 table_list->prepare_check_option(thd))
434 {
435 DBUG_RETURN(TRUE);
436 }
437 thd_proc_info(thd, "Executing");
438 /*
439 Let us emit an error if we are loading data to table which is used
440 in subselect in SET clause like we do it for INSERT.
441
442 The main thing to fix to remove this restriction is to ensure that the
443 table is marked to be 'used for insert' in which case we should never
444 mark this table as 'const table' (ie, one that has only one row).
445 */
446 if (unique_table(thd, table_list, table_list->next_global, 0))
447 {
448 my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name.str,
449 "LOAD DATA");
450 DBUG_RETURN(TRUE);
451 }
452
453 table= table_list->table;
454 transactional_table= table->file->has_transactions();
455 #ifndef EMBEDDED_LIBRARY
456 is_concurrent= (table_list->lock_type == TL_WRITE_CONCURRENT_INSERT);
457 #endif
458
459 if (!fields_vars.elements)
460 {
461 Field_iterator_table_ref field_iterator;
462 field_iterator.set(table_list);
463 for (; !field_iterator.end_of_fields(); field_iterator.next())
464 {
465 if (field_iterator.field() &&
466 field_iterator.field()->invisible > VISIBLE)
467 continue;
468 Item *item;
469 if (!(item= field_iterator.create_item(thd)))
470 DBUG_RETURN(TRUE);
471 fields_vars.push_back(item->real_item(), thd->mem_root);
472 }
473 bitmap_set_all(table->write_set);
474 /*
475 Let us also prepare SET clause, altough it is probably empty
476 in this case.
477 */
478 if (setup_fields(thd, Ref_ptr_array(),
479 set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
480 setup_fields(thd, Ref_ptr_array(),
481 set_values, MARK_COLUMNS_READ, 0, NULL, 0))
482 DBUG_RETURN(TRUE);
483 }
484 else
485 { // Part field list
486 /* TODO: use this conds for 'WITH CHECK OPTIONS' */
487 if (setup_fields(thd, Ref_ptr_array(),
488 fields_vars, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
489 setup_fields(thd, Ref_ptr_array(),
490 set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
491 check_that_all_fields_are_given_values(thd, table, table_list))
492 DBUG_RETURN(TRUE);
493 /* Fix the expressions in SET clause */
494 if (setup_fields(thd, Ref_ptr_array(),
495 set_values, MARK_COLUMNS_READ, 0, NULL, 0))
496 DBUG_RETURN(TRUE);
497 }
498 switch_to_nullable_trigger_fields(fields_vars, table);
499 switch_to_nullable_trigger_fields(set_fields, table);
500 switch_to_nullable_trigger_fields(set_values, table);
501
502 table->prepare_triggers_for_insert_stmt_or_event();
503 table->mark_columns_needed_for_insert();
504
505 Load_data_param param(ex->cs ? ex->cs : thd->variables.collation_database,
506 !ex->field_term->length() && !ex->enclosed->length());
507 List_iterator_fast<Item> it(fields_vars);
508 Item *item;
509
510 while ((item= it++))
511 {
512 const Load_data_outvar *var= item->get_load_data_outvar_or_error();
513 if (!var || var->load_data_add_outvar(thd, ¶m))
514 DBUG_RETURN(true);
515 }
516 if (param.use_blobs() && !ex->line_term->length() && !ex->field_term->length())
517 {
518 my_message(ER_BLOBS_AND_NO_TERMINATED,
519 ER_THD(thd, ER_BLOBS_AND_NO_TERMINATED), MYF(0));
520 DBUG_RETURN(TRUE);
521 }
522
523 /* We can't give an error in the middle when using LOCAL files */
524 if (read_file_from_client && handle_duplicates == DUP_ERROR)
525 ignore= 1;
526
527 #ifndef EMBEDDED_LIBRARY
528 if (read_file_from_client)
529 {
530 (void)net_request_file(&thd->net,ex->file_name);
531 file = -1;
532 }
533 else
534 #endif
535 {
536 #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
537 ex->file_name+=dirname_length(ex->file_name);
538 #endif
539 if (!dirname_length(ex->file_name))
540 {
541 strxnmov(name, FN_REFLEN-1, mysql_real_data_home, tdb, NullS);
542 (void) fn_format(name, ex->file_name, name, "",
543 MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
544 }
545 else
546 {
547 (void) fn_format(name, ex->file_name, mysql_real_data_home, "",
548 MY_RELATIVE_PATH | MY_UNPACK_FILENAME |
549 MY_RETURN_REAL_PATH);
550 }
551
552 if (thd->rgi_slave)
553 {
554 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
555 if (strncmp(thd->rgi_slave->rli->slave_patternload_file, name,
556 thd->rgi_slave->rli->slave_patternload_file_size))
557 {
558 /*
559 LOAD DATA INFILE in the slave SQL Thread can only read from
560 --slave-load-tmpdir". This should never happen. Please, report a bug.
561 */
562
563 sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
564 "Please, report a bug.");
565 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
566 DBUG_RETURN(TRUE);
567 }
568 #else
569 /*
570 This is impossible and should never happen.
571 */
572 DBUG_ASSERT(FALSE);
573 #endif
574 }
575 else if (!is_secure_file_path(name))
576 {
577 /* Read only allowed from within dir specified by secure_file_priv */
578 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
579 DBUG_RETURN(TRUE);
580 }
581
582 #if !defined(__WIN__) && ! defined(__NETWARE__)
583 MY_STAT stat_info;
584 if (!my_stat(name, &stat_info, MYF(MY_WME)))
585 DBUG_RETURN(TRUE);
586
587 // if we are not in slave thread, the file must be:
588 if (!thd->slave_thread &&
589 !((stat_info.st_mode & S_IFLNK) != S_IFLNK && // symlink
590 ((stat_info.st_mode & S_IFREG) == S_IFREG || // regular file
591 (stat_info.st_mode & S_IFIFO) == S_IFIFO))) // named pipe
592 {
593 my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
594 DBUG_RETURN(TRUE);
595 }
596 if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
597 is_fifo= 1;
598 #endif
599 if ((file= mysql_file_open(key_file_load,
600 name, O_RDONLY, MYF(MY_WME))) < 0)
601
602 DBUG_RETURN(TRUE);
603 }
604
605 COPY_INFO info;
606 bzero((char*) &info,sizeof(info));
607 info.ignore= ignore;
608 info.handle_duplicates=handle_duplicates;
609 info.escape_char= (ex->escaped->length() && (ex->escaped_given() ||
610 !(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)))
611 ? (*ex->escaped)[0] : INT_MAX;
612
613 READ_INFO read_info(thd, file, param,
614 *ex->field_term, *ex->line_start,
615 *ex->line_term, *ex->enclosed,
616 info.escape_char, read_file_from_client, is_fifo);
617 if (unlikely(read_info.error))
618 {
619 if (file >= 0)
620 mysql_file_close(file, MYF(0)); // no files in net reading
621 DBUG_RETURN(TRUE); // Can't allocate buffers
622 }
623
624 #ifndef EMBEDDED_LIBRARY
625 if (mysql_bin_log.is_open())
626 {
627 read_info.cache.thd = thd;
628 read_info.cache.wrote_create_file = 0;
629 read_info.cache.last_pos_in_file = HA_POS_ERROR;
630 read_info.cache.log_delayed= transactional_table;
631 }
632 #endif /*!EMBEDDED_LIBRARY*/
633
634 thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
635 thd->cuted_fields=0L;
636 /* Skip lines if there is a line terminator */
637 if (ex->line_term->length() && ex->filetype != FILETYPE_XML)
638 {
639 /* ex->skip_lines needs to be preserved for logging */
640 while (skip_lines > 0)
641 {
642 skip_lines--;
643 if (read_info.next_line())
644 break;
645 }
646 }
647
648 thd_proc_info(thd, "Reading file");
649 if (likely(!(error= MY_TEST(read_info.error))))
650 {
651 table->reset_default_fields();
652 table->next_number_field=table->found_next_number_field;
653 if (ignore ||
654 handle_duplicates == DUP_REPLACE)
655 table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
656 if (handle_duplicates == DUP_REPLACE &&
657 (!table->triggers ||
658 !table->triggers->has_delete_triggers()))
659 table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
660 if (thd->locked_tables_mode <= LTM_LOCK_TABLES)
661 table->file->ha_start_bulk_insert((ha_rows) 0);
662 table->copy_blobs=1;
663
664 thd->abort_on_warning= !ignore && thd->is_strict_mode();
665
666 if ((table_list->table->file->ha_table_flags() & HA_DUPLICATE_POS) &&
667 (error= table_list->table->file->ha_rnd_init_with_error(0)))
668 goto err;
669
670 thd_progress_init(thd, 2);
671 if (table_list->table->validate_default_values_of_unset_fields(thd))
672 {
673 read_info.error= true;
674 error= 1;
675 }
676 else if (ex->filetype == FILETYPE_XML) /* load xml */
677 error= read_xml_field(thd, info, table_list, fields_vars,
678 set_fields, set_values, read_info,
679 *(ex->line_term), skip_lines, ignore);
680 else if (read_info.is_fixed_length())
681 error= read_fixed_length(thd, info, table_list, fields_vars,
682 set_fields, set_values, read_info,
683 skip_lines, ignore);
684 else
685 error= read_sep_field(thd, info, table_list, fields_vars,
686 set_fields, set_values, read_info,
687 *ex->enclosed, skip_lines, ignore);
688
689 if (table_list->table->file->ha_table_flags() & HA_DUPLICATE_POS)
690 table_list->table->file->ha_rnd_end();
691
692 thd_proc_info(thd, "End bulk insert");
693 if (likely(!error))
694 thd_progress_next_stage(thd);
695 if (thd->locked_tables_mode <= LTM_LOCK_TABLES &&
696 table->file->ha_end_bulk_insert() && !error)
697 {
698 table->file->print_error(my_errno, MYF(0));
699 error= 1;
700 }
701 table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
702 table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
703 table->next_number_field=0;
704 }
705 if (file >= 0)
706 mysql_file_close(file, MYF(0));
707 free_blobs(table); /* if pack_blob was used */
708 table->copy_blobs=0;
709 thd->count_cuted_fields= CHECK_FIELD_IGNORE;
710 /*
711 simulated killing in the middle of per-row loop
712 must be effective for binlogging
713 */
714 DBUG_EXECUTE_IF("simulate_kill_bug27571",
715 {
716 error=1;
717 thd->set_killed(KILL_QUERY);
718 };);
719
720 #ifndef EMBEDDED_LIBRARY
721 killed_status= (error == 0) ? NOT_KILLED : thd->killed;
722 #endif
723
724 /*
725 We must invalidate the table in query cache before binlog writing and
726 ha_autocommit_...
727 */
728 query_cache_invalidate3(thd, table_list, 0);
729 if (error)
730 {
731 if (read_file_from_client)
732 read_info.skip_data_till_eof();
733
734 #ifndef EMBEDDED_LIBRARY
735 if (mysql_bin_log.is_open())
736 {
737 {
738 /*
739 Make sure last block (the one which caused the error) gets
740 logged.
741 */
742 log_loaded_block(&read_info.cache, 0, 0);
743 /* If the file was not empty, wrote_create_file is true */
744 if (read_info.cache.wrote_create_file)
745 {
746 int errcode= query_error_code(thd, killed_status == NOT_KILLED);
747
748 /* since there is already an error, the possible error of
749 writing binary log will be ignored */
750 if (thd->transaction.stmt.modified_non_trans_table)
751 (void) write_execute_load_query_log_event(thd, ex,
752 table_list->db.str,
753 table_list->table_name.str,
754 is_concurrent,
755 handle_duplicates, ignore,
756 transactional_table,
757 errcode);
758 else
759 {
760 Delete_file_log_event d(thd, db, transactional_table);
761 (void) mysql_bin_log.write(&d);
762 }
763 }
764 }
765 }
766 #endif /*!EMBEDDED_LIBRARY*/
767 error= -1; // Error on read
768 goto err;
769 }
770 sprintf(name, ER_THD(thd, ER_LOAD_INFO),
771 (ulong) info.records, (ulong) info.deleted,
772 (ulong) (info.records - info.copied),
773 (long) thd->get_stmt_da()->current_statement_warn_count());
774
775 if (thd->transaction.stmt.modified_non_trans_table)
776 thd->transaction.all.modified_non_trans_table= TRUE;
777 thd->transaction.all.m_unsafe_rollback_flags|=
778 (thd->transaction.stmt.m_unsafe_rollback_flags & THD_TRANS::DID_WAIT);
779 #ifndef EMBEDDED_LIBRARY
780 if (mysql_bin_log.is_open())
781 {
782 /*
783 We need to do the job that is normally done inside
784 binlog_query() here, which is to ensure that the pending event
785 is written before tables are unlocked and before any other
786 events are written. We also need to update the table map
787 version for the binary log to mark that table maps are invalid
788 after this point.
789 */
790 if (thd->is_current_stmt_binlog_format_row())
791 error= thd->binlog_flush_pending_rows_event(TRUE, transactional_table);
792 else
793 {
794 /*
795 As already explained above, we need to call log_loaded_block() to have
796 the last block logged
797 */
798 log_loaded_block(&read_info.cache, 0, 0);
799 if (read_info.cache.wrote_create_file)
800 {
801 int errcode= query_error_code(thd, killed_status == NOT_KILLED);
802 error= write_execute_load_query_log_event(thd, ex,
803 table_list->db.str,
804 table_list->table_name.str,
805 is_concurrent,
806 handle_duplicates, ignore,
807 transactional_table,
808 errcode);
809 }
810
811 /*
812 Flushing the IO CACHE while writing the execute load query log event
813 may result in error (for instance, because the max_binlog_size has been
814 reached, and rotation of the binary log failed).
815 */
816 error= error || mysql_bin_log.get_log_file()->error;
817 }
818 if (unlikely(error))
819 goto err;
820 }
821 #endif /*!EMBEDDED_LIBRARY*/
822
823 /* ok to client sent only after binlog write and engine commit */
824 my_ok(thd, info.copied + info.deleted, 0L, name);
825 err:
826 DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) ||
827 thd->transaction.stmt.modified_non_trans_table);
828 table->file->ha_release_auto_increment();
829 table->auto_increment_field_not_null= FALSE;
830 thd->abort_on_warning= 0;
831 DBUG_RETURN(error);
832 }
833
834
835 #ifndef EMBEDDED_LIBRARY
836
837 /* Not a very useful function; just to avoid duplication of code */
write_execute_load_query_log_event(THD * thd,const sql_exchange * ex,const char * db_arg,const char * table_name_arg,bool is_concurrent,enum enum_duplicates duplicates,bool ignore,bool transactional_table,int errcode)838 static bool write_execute_load_query_log_event(THD *thd, const sql_exchange* ex,
839 const char* db_arg, /* table's database */
840 const char* table_name_arg,
841 bool is_concurrent,
842 enum enum_duplicates duplicates,
843 bool ignore,
844 bool transactional_table,
845 int errcode)
846 {
847 char *load_data_query;
848 my_off_t fname_start,
849 fname_end;
850 List<Item> fv;
851 Item *item, *val;
852 int n;
853 const char *tdb= (thd->db.str != NULL ? thd->db.str : db_arg);
854 const char *qualify_db= NULL;
855 char command_buffer[1024];
856 String query_str(command_buffer, sizeof(command_buffer),
857 system_charset_info);
858
859 Load_log_event lle(thd, ex, tdb, table_name_arg, fv, is_concurrent,
860 duplicates, ignore, transactional_table);
861
862 /*
863 force in a LOCAL if there was one in the original.
864 */
865 if (thd->lex->local_file)
866 lle.set_fname_outside_temp_buf(ex->file_name, strlen(ex->file_name));
867
868 query_str.length(0);
869 if (!thd->db.str || strcmp(db_arg, thd->db.str))
870 {
871 /*
872 If used database differs from table's database,
873 prefix table name with database name so that it
874 becomes a FQ name.
875 */
876 qualify_db= db_arg;
877 }
878 lle.print_query(thd, FALSE, (const char *) ex->cs?ex->cs->csname:NULL,
879 &query_str, &fname_start, &fname_end, qualify_db);
880
881 /*
882 prepare fields-list and SET if needed; print_query won't do that for us.
883 */
884 if (!thd->lex->field_list.is_empty())
885 {
886 List_iterator<Item> li(thd->lex->field_list);
887
888 query_str.append(" (");
889 n= 0;
890
891 while ((item= li++))
892 {
893 if (n++)
894 query_str.append(", ");
895 const Load_data_outvar *var= item->get_load_data_outvar();
896 DBUG_ASSERT(var);
897 var->load_data_print_for_log_event(thd, &query_str);
898 }
899 query_str.append(")");
900 }
901
902 if (!thd->lex->update_list.is_empty())
903 {
904 List_iterator<Item> lu(thd->lex->update_list);
905 List_iterator<Item> lv(thd->lex->value_list);
906
907 query_str.append(STRING_WITH_LEN(" SET "));
908 n= 0;
909
910 while ((item= lu++))
911 {
912 val= lv++;
913 if (n++)
914 query_str.append(STRING_WITH_LEN(", "));
915 append_identifier(thd, &query_str, &item->name);
916 query_str.append(&val->name);
917 }
918 }
919
920 if (!(load_data_query= (char *)thd->strmake(query_str.ptr(), query_str.length())))
921 return TRUE;
922
923 Execute_load_query_log_event
924 e(thd, load_data_query, query_str.length(),
925 (uint) (fname_start - 1), (uint) fname_end,
926 (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
927 (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
928 transactional_table, FALSE, FALSE, errcode);
929 return mysql_bin_log.write(&e);
930 }
931
932 #endif
933
934 /****************************************************************************
935 ** Read of rows of fixed size + optional garage + optonal newline
936 ****************************************************************************/
937
938 static int
read_fixed_length(THD * thd,COPY_INFO & info,TABLE_LIST * table_list,List<Item> & fields_vars,List<Item> & set_fields,List<Item> & set_values,READ_INFO & read_info,ulong skip_lines,bool ignore_check_option_errors)939 read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
940 List<Item> &fields_vars, List<Item> &set_fields,
941 List<Item> &set_values, READ_INFO &read_info,
942 ulong skip_lines, bool ignore_check_option_errors)
943 {
944 List_iterator_fast<Item> it(fields_vars);
945 Item *item;
946 TABLE *table= table_list->table;
947 bool progress_reports;
948 ulonglong counter, time_to_report_progress;
949 DBUG_ENTER("read_fixed_length");
950
951 counter= 0;
952 time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
953 progress_reports= 1;
954 if ((thd->progress.max_counter= read_info.file_length()) == ~(my_off_t) 0)
955 progress_reports= 0;
956
957 while (!read_info.read_fixed_length())
958 {
959 if (thd->killed)
960 {
961 thd->send_kill_message();
962 DBUG_RETURN(1);
963 }
964 if (progress_reports)
965 {
966 thd->progress.counter= read_info.position();
967 if (++counter >= time_to_report_progress)
968 {
969 time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10;
970 thd_progress_report(thd, thd->progress.counter,
971 thd->progress.max_counter);
972 }
973 }
974 if (skip_lines)
975 {
976 /*
977 We could implement this with a simple seek if:
978 - We are not using DATA INFILE LOCAL
979 - escape character is ""
980 - line starting prefix is ""
981 */
982 skip_lines--;
983 continue;
984 }
985 it.rewind();
986 uchar *pos=read_info.row_start;
987 #ifdef HAVE_valgrind
988 read_info.row_end[0]=0;
989 #endif
990
991 restore_record(table, s->default_values);
992
993 while ((item= it++))
994 {
995 Load_data_outvar *dst= item->get_load_data_outvar();
996 DBUG_ASSERT(dst);
997 if (pos == read_info.row_end)
998 {
999 if (dst->load_data_set_no_data(thd, &read_info))
1000 DBUG_RETURN(1);
1001 }
1002 else
1003 {
1004 uint length, fixed_length= dst->load_data_fixed_length();
1005 uchar save_chr;
1006 if ((length=(uint) (read_info.row_end - pos)) > fixed_length)
1007 length= fixed_length;
1008 save_chr= pos[length]; pos[length]= '\0'; // Safeguard aganst malloc
1009 dst->load_data_set_value(thd, (const char *) pos, length, &read_info);
1010 pos[length]= save_chr;
1011 if ((pos+= length) > read_info.row_end)
1012 pos= read_info.row_end; // Fills rest with space
1013 }
1014 }
1015 if (pos != read_info.row_end)
1016 {
1017 thd->cuted_fields++; /* To long row */
1018 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1019 ER_WARN_TOO_MANY_RECORDS,
1020 ER_THD(thd, ER_WARN_TOO_MANY_RECORDS),
1021 thd->get_stmt_da()->current_row_for_warning());
1022 }
1023
1024 if (thd->killed ||
1025 fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
1026 ignore_check_option_errors,
1027 TRG_EVENT_INSERT))
1028 DBUG_RETURN(1);
1029
1030 switch (table_list->view_check_option(thd, ignore_check_option_errors)) {
1031 case VIEW_CHECK_SKIP:
1032 read_info.next_line();
1033 goto continue_loop;
1034 case VIEW_CHECK_ERROR:
1035 DBUG_RETURN(-1);
1036 }
1037
1038 WSREP_LOAD_DATA_SPLIT(thd, table, info);
1039 WRITE_RECORD(thd, table, info);
1040
1041 /*
1042 We don't need to reset auto-increment field since we are restoring
1043 its default value at the beginning of each loop iteration.
1044 */
1045 if (read_info.next_line()) // Skip to next line
1046 break;
1047 if (read_info.line_cuted)
1048 {
1049 thd->cuted_fields++; /* To long row */
1050 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1051 ER_WARN_TOO_MANY_RECORDS,
1052 ER_THD(thd, ER_WARN_TOO_MANY_RECORDS),
1053 thd->get_stmt_da()->current_row_for_warning());
1054 }
1055 thd->get_stmt_da()->inc_current_row_for_warning();
1056 continue_loop:;
1057 }
1058 DBUG_RETURN(MY_TEST(read_info.error));
1059 }
1060
1061
1062 static int
read_sep_field(THD * thd,COPY_INFO & info,TABLE_LIST * table_list,List<Item> & fields_vars,List<Item> & set_fields,List<Item> & set_values,READ_INFO & read_info,String & enclosed,ulong skip_lines,bool ignore_check_option_errors)1063 read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
1064 List<Item> &fields_vars, List<Item> &set_fields,
1065 List<Item> &set_values, READ_INFO &read_info,
1066 String &enclosed, ulong skip_lines,
1067 bool ignore_check_option_errors)
1068 {
1069 List_iterator_fast<Item> it(fields_vars);
1070 Item *item;
1071 TABLE *table= table_list->table;
1072 uint enclosed_length;
1073 bool progress_reports;
1074 ulonglong counter, time_to_report_progress;
1075 DBUG_ENTER("read_sep_field");
1076
1077 enclosed_length=enclosed.length();
1078
1079 counter= 0;
1080 time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
1081 progress_reports= 1;
1082 if ((thd->progress.max_counter= read_info.file_length()) == ~(my_off_t) 0)
1083 progress_reports= 0;
1084
1085 for (;;it.rewind())
1086 {
1087 if (thd->killed)
1088 {
1089 thd->send_kill_message();
1090 DBUG_RETURN(1);
1091 }
1092
1093 if (progress_reports)
1094 {
1095 thd->progress.counter= read_info.position();
1096 if (++counter >= time_to_report_progress)
1097 {
1098 time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10;
1099 thd_progress_report(thd, thd->progress.counter,
1100 thd->progress.max_counter);
1101 }
1102 }
1103 restore_record(table, s->default_values);
1104
1105 while ((item= it++))
1106 {
1107 uint length;
1108 uchar *pos;
1109 if (read_info.read_field())
1110 break;
1111
1112 /* If this line is to be skipped we don't want to fill field or var */
1113 if (skip_lines)
1114 continue;
1115
1116 pos=read_info.row_start;
1117 length=(uint) (read_info.row_end-pos);
1118
1119 Load_data_outvar *dst= item->get_load_data_outvar_or_error();
1120 DBUG_ASSERT(dst);
1121
1122 if ((!read_info.enclosed &&
1123 (enclosed_length && length == 4 &&
1124 !memcmp(pos, STRING_WITH_LEN("NULL")))) ||
1125 (length == 1 && read_info.found_null))
1126 {
1127 if (dst->load_data_set_null(thd, &read_info))
1128 DBUG_RETURN(1);
1129 }
1130 else
1131 {
1132 read_info.row_end[0]= 0; // Safe to change end marker
1133 if (dst->load_data_set_value(thd, (const char *) pos, length, &read_info))
1134 DBUG_RETURN(1);
1135 }
1136 }
1137
1138 if (unlikely(thd->is_error()))
1139 read_info.error= 1;
1140 if (unlikely(read_info.error))
1141 break;
1142
1143 if (skip_lines)
1144 {
1145 skip_lines--;
1146 continue;
1147 }
1148 if (item)
1149 {
1150 /* Have not read any field, thus input file is simply ended */
1151 if (item == fields_vars.head())
1152 break;
1153 for (; item ; item= it++)
1154 {
1155 Load_data_outvar *dst= item->get_load_data_outvar_or_error();
1156 DBUG_ASSERT(dst);
1157 if (unlikely(dst->load_data_set_no_data(thd, &read_info)))
1158 DBUG_RETURN(1);
1159 }
1160 }
1161
1162 if (unlikely(thd->killed) ||
1163 unlikely(fill_record_n_invoke_before_triggers(thd, table, set_fields,
1164 set_values,
1165 ignore_check_option_errors,
1166 TRG_EVENT_INSERT)))
1167 DBUG_RETURN(1);
1168
1169 switch (table_list->view_check_option(thd,
1170 ignore_check_option_errors)) {
1171 case VIEW_CHECK_SKIP:
1172 read_info.next_line();
1173 goto continue_loop;
1174 case VIEW_CHECK_ERROR:
1175 DBUG_RETURN(-1);
1176 }
1177
1178 WSREP_LOAD_DATA_SPLIT(thd, table, info);
1179 WRITE_RECORD(thd, table, info);
1180
1181 /*
1182 We don't need to reset auto-increment field since we are restoring
1183 its default value at the beginning of each loop iteration.
1184 */
1185 if (read_info.next_line()) // Skip to next line
1186 break;
1187 if (read_info.line_cuted)
1188 {
1189 thd->cuted_fields++; /* To long row */
1190 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1191 ER_WARN_TOO_MANY_RECORDS,
1192 ER_THD(thd, ER_WARN_TOO_MANY_RECORDS),
1193 thd->get_stmt_da()->current_row_for_warning());
1194 if (thd->killed)
1195 DBUG_RETURN(1);
1196 }
1197 thd->get_stmt_da()->inc_current_row_for_warning();
1198 continue_loop:;
1199 }
1200 DBUG_RETURN(MY_TEST(read_info.error));
1201 }
1202
1203
1204 /****************************************************************************
1205 ** Read rows in xml format
1206 ****************************************************************************/
1207 static int
read_xml_field(THD * thd,COPY_INFO & info,TABLE_LIST * table_list,List<Item> & fields_vars,List<Item> & set_fields,List<Item> & set_values,READ_INFO & read_info,String & row_tag,ulong skip_lines,bool ignore_check_option_errors)1208 read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
1209 List<Item> &fields_vars, List<Item> &set_fields,
1210 List<Item> &set_values, READ_INFO &read_info,
1211 String &row_tag, ulong skip_lines,
1212 bool ignore_check_option_errors)
1213 {
1214 List_iterator_fast<Item> it(fields_vars);
1215 Item *item;
1216 TABLE *table= table_list->table;
1217 bool no_trans_update_stmt;
1218 DBUG_ENTER("read_xml_field");
1219
1220 no_trans_update_stmt= !table->file->has_transactions();
1221
1222 for ( ; ; it.rewind())
1223 {
1224 if (thd->killed)
1225 {
1226 thd->send_kill_message();
1227 DBUG_RETURN(1);
1228 }
1229
1230 // read row tag and save values into tag list
1231 if (read_info.read_xml(thd))
1232 break;
1233
1234 List_iterator_fast<XML_TAG> xmlit(read_info.taglist);
1235 xmlit.rewind();
1236 XML_TAG *tag= NULL;
1237
1238 #ifndef DBUG_OFF
1239 DBUG_PRINT("read_xml_field", ("skip_lines=%d", (int) skip_lines));
1240 while ((tag= xmlit++))
1241 {
1242 DBUG_PRINT("read_xml_field", ("got tag:%i '%s' '%s'",
1243 tag->level, tag->field.c_ptr(),
1244 tag->value.c_ptr()));
1245 }
1246 #endif
1247
1248 restore_record(table, s->default_values);
1249
1250 while ((item= it++))
1251 {
1252 /* If this line is to be skipped we don't want to fill field or var */
1253 if (skip_lines)
1254 continue;
1255
1256 /* find field in tag list */
1257 xmlit.rewind();
1258 tag= xmlit++;
1259
1260 while(tag && strcmp(tag->field.c_ptr(), item->name.str) != 0)
1261 tag= xmlit++;
1262
1263 Load_data_outvar *dst= item->get_load_data_outvar_or_error();
1264 DBUG_ASSERT(dst);
1265 if (!tag ? dst->load_data_set_null(thd, &read_info) :
1266 dst->load_data_set_value(thd, tag->value.ptr(),
1267 tag->value.length(),
1268 &read_info))
1269 DBUG_RETURN(1);
1270 }
1271
1272 if (unlikely(read_info.error))
1273 break;
1274
1275 if (skip_lines)
1276 {
1277 skip_lines--;
1278 continue;
1279 }
1280
1281 DBUG_ASSERT(!item);
1282
1283 if (thd->killed ||
1284 fill_record_n_invoke_before_triggers(thd, table, set_fields, set_values,
1285 ignore_check_option_errors,
1286 TRG_EVENT_INSERT))
1287 DBUG_RETURN(1);
1288
1289 switch (table_list->view_check_option(thd,
1290 ignore_check_option_errors)) {
1291 case VIEW_CHECK_SKIP:
1292 read_info.next_line();
1293 goto continue_loop;
1294 case VIEW_CHECK_ERROR:
1295 DBUG_RETURN(-1);
1296 }
1297
1298 WSREP_LOAD_DATA_SPLIT(thd, table, info);
1299 WRITE_RECORD(thd, table, info);
1300
1301 /*
1302 We don't need to reset auto-increment field since we are restoring
1303 its default value at the beginning of each loop iteration.
1304 */
1305 thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
1306 thd->get_stmt_da()->inc_current_row_for_warning();
1307 continue_loop:;
1308 }
1309 DBUG_RETURN(MY_TEST(read_info.error) || thd->is_error());
1310 } /* load xml end */
1311
1312
1313 /* Unescape all escape characters, mark \N as null */
1314
1315 char
unescape(char chr)1316 READ_INFO::unescape(char chr)
1317 {
1318 /* keep this switch synchornous with the ESCAPE_CHARS macro */
1319 switch(chr) {
1320 case 'n': return '\n';
1321 case 't': return '\t';
1322 case 'r': return '\r';
1323 case 'b': return '\b';
1324 case '0': return 0; // Ascii null
1325 case 'Z': return '\032'; // Win32 end of file
1326 case 'N': found_null=1;
1327
1328 /* fall through */
1329 default: return chr;
1330 }
1331 }
1332
1333
1334 /*
1335 Read a line using buffering
1336 If last line is empty (in line mode) then it isn't outputed
1337 */
1338
1339
READ_INFO(THD * thd,File file_par,const Load_data_param & param,String & field_term,String & line_start,String & line_term,String & enclosed_par,int escape,bool get_it_from_net,bool is_fifo)1340 READ_INFO::READ_INFO(THD *thd, File file_par,
1341 const Load_data_param ¶m,
1342 String &field_term, String &line_start, String &line_term,
1343 String &enclosed_par, int escape, bool get_it_from_net,
1344 bool is_fifo)
1345 :Load_data_param(param),
1346 file(file_par),
1347 m_field_term(field_term), m_line_term(line_term), m_line_start(line_start),
1348 escape_char(escape), found_end_of_line(false), eof(false),
1349 error(false), line_cuted(false), found_null(false)
1350 {
1351 data.set_thread_specific();
1352 /*
1353 Field and line terminators must be interpreted as sequence of unsigned char.
1354 Otherwise, non-ascii terminators will be negative on some platforms,
1355 and positive on others (depending on the implementation of char).
1356 */
1357
1358 level= 0; /* for load xml */
1359 start_of_line= line_start.length() != 0;
1360 /* If field_terminator == line_terminator, don't use line_terminator */
1361 if (m_field_term.eq(m_line_term))
1362 m_line_term.reset();
1363 enclosed_char= enclosed_par.length() ? (uchar) enclosed_par[0] : INT_MAX;
1364
1365 /* Set of a stack for unget if long terminators */
1366 uint length= MY_MAX(charset()->mbmaxlen, MY_MAX(m_field_term.length(),
1367 m_line_term.length())) + 1;
1368 set_if_bigger(length,line_start.length());
1369 stack= stack_pos= (int*) thd->alloc(sizeof(int) * length);
1370
1371 DBUG_ASSERT(m_fixed_length < UINT_MAX32);
1372 if (data.reserve((size_t) m_fixed_length))
1373 error=1; /* purecov: inspected */
1374 else
1375 {
1376 if (init_io_cache(&cache,(get_it_from_net) ? -1 : file, 0,
1377 (get_it_from_net) ? READ_NET :
1378 (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
1379 MYF(MY_WME | MY_THREAD_SPECIFIC)))
1380 {
1381 error=1;
1382 }
1383 else
1384 {
1385 #ifndef EMBEDDED_LIBRARY
1386 if (get_it_from_net)
1387 cache.read_function = _my_b_net_read;
1388
1389 if (mysql_bin_log.is_open())
1390 {
1391 cache.real_read_function= cache.read_function;
1392 cache.read_function= log_loaded_block;
1393 }
1394 #endif
1395 }
1396 }
1397 }
1398
1399
~READ_INFO()1400 READ_INFO::~READ_INFO()
1401 {
1402 ::end_io_cache(&cache);
1403 List_iterator<XML_TAG> xmlit(taglist);
1404 XML_TAG *t;
1405 while ((t= xmlit++))
1406 delete(t);
1407 }
1408
1409
terminator(const uchar * ptr,uint length)1410 inline bool READ_INFO::terminator(const uchar *ptr, uint length)
1411 {
1412 int chr=0; // Keep gcc happy
1413 uint i;
1414 for (i=1 ; i < length ; i++)
1415 {
1416 if ((chr=GET) != *(uchar*)++ptr)
1417 {
1418 break;
1419 }
1420 }
1421 if (i == length)
1422 return true;
1423 PUSH(chr);
1424 while (i-- > 1)
1425 PUSH(*--ptr);
1426 return false;
1427 }
1428
1429
1430 /**
1431 Read a field.
1432
1433 The data in the loaded file was presumably escaped using
1434 - either select_export::send_data() OUTFILE
1435 - or mysql_real_escape_string()
1436 using the same character set with the one specified in the current
1437 "LOAD DATA INFILE ... CHARACTER SET ..." (or the default LOAD character set).
1438
1439 Note, non-escaped multi-byte characters are scanned as a single entity.
1440 This is needed to correctly distinguish between:
1441 - 0x5C as an escape character versus
1442 - 0x5C as the second byte in a multi-byte sequence (big5, cp932, gbk, sjis)
1443
1444 Parts of escaped multi-byte characters are scanned on different loop
1445 iterations. See the comment about 0x5C handling in select_export::send_data()
1446 in sql_class.cc.
1447
1448 READ_INFO::read_field() does not check wellformedness.
1449 Raising wellformedness errors or warnings in READ_INFO::read_field()
1450 would be wrong, as the data after unescaping can go into a BLOB field,
1451 or into a TEXT/VARCHAR field of a different character set.
1452 The loop below only makes sure to revert escaping made by
1453 select_export::send_data() or mysql_real_escape_string().
1454 Wellformedness is checked later, during Field::store(str,length,cs) time.
1455
1456 Note, in some cases users can supply data which did not go through
1457 escaping properly. For example, utf8 "\<C3><A4>"
1458 (backslash followed by LATIN SMALL LETTER A WITH DIAERESIS)
1459 is improperly escaped data that could not be generated by
1460 select_export::send_data() / mysql_real_escape_string():
1461 - either there should be two backslashes: "\\<C3><A4>"
1462 - or there should be no backslashes at all: "<C3><A4>"
1463 "\<C3>" and "<A4> are scanned on two different loop iterations and
1464 store "<C3><A4>" into the field.
1465
1466 Note, adding useless escapes before multi-byte characters like in the
1467 example above is safe in case of utf8, but is not safe in case of
1468 character sets that have escape_with_backslash_is_dangerous==TRUE,
1469 such as big5, cp932, gbk, sjis. This can lead to mis-interpretation of the
1470 data. Suppose we have a big5 character "<EE><5C>" followed by <30> (digit 0).
1471 If we add an extra escape before this sequence, then we'll get
1472 <5C><EE><5C><30>. The first loop iteration will turn <5C><EE> into <EE>.
1473 The second loop iteration will turn <5C><30> into <30>.
1474 So the program that generates a dump file for further use with LOAD DATA
1475 must make sure to use escapes properly.
1476 */
1477
read_field()1478 int READ_INFO::read_field()
1479 {
1480 int chr,found_enclosed_char;
1481
1482 found_null=0;
1483 if (found_end_of_line)
1484 return 1; // One have to call next_line
1485
1486 /* Skip until we find 'line_start' */
1487
1488 if (start_of_line)
1489 { // Skip until line_start
1490 start_of_line=0;
1491 if (find_start_of_fields())
1492 return 1;
1493 }
1494 if ((chr=GET) == my_b_EOF)
1495 {
1496 found_end_of_line=eof=1;
1497 return 1;
1498 }
1499 data.length(0);
1500 if (chr == enclosed_char)
1501 {
1502 found_enclosed_char=enclosed_char;
1503 data.append(chr); // If error
1504 }
1505 else
1506 {
1507 found_enclosed_char= INT_MAX;
1508 PUSH(chr);
1509 }
1510
1511 for (;;)
1512 {
1513 // Make sure we have enough space for the longest multi-byte character.
1514 while (data.length() + charset()->mbmaxlen <= data.alloced_length())
1515 {
1516 chr = GET;
1517 if (chr == my_b_EOF)
1518 goto found_eof;
1519 if (chr == escape_char)
1520 {
1521 if ((chr=GET) == my_b_EOF)
1522 {
1523 data.append(escape_char);
1524 goto found_eof;
1525 }
1526 /*
1527 When escape_char == enclosed_char, we treat it like we do for
1528 handling quotes in SQL parsing -- you can double-up the
1529 escape_char to include it literally, but it doesn't do escapes
1530 like \n. This allows: LOAD DATA ... ENCLOSED BY '"' ESCAPED BY '"'
1531 with data like: "fie""ld1", "field2"
1532 */
1533 if (escape_char != enclosed_char || chr == escape_char)
1534 {
1535 data.append(unescape((char) chr));
1536 continue;
1537 }
1538 PUSH(chr);
1539 chr= escape_char;
1540 }
1541 #ifdef ALLOW_LINESEPARATOR_IN_STRINGS
1542 if (chr == m_line_term.initial_byte())
1543 #else
1544 if (chr == m_line_term.initial_byte() && found_enclosed_char == INT_MAX)
1545 #endif
1546 {
1547 if (terminator(m_line_term))
1548 { // Maybe unexpected linefeed
1549 enclosed=0;
1550 found_end_of_line=1;
1551 row_start= (uchar *) data.ptr();
1552 row_end= (uchar *) data.end();
1553 return 0;
1554 }
1555 }
1556 if (chr == found_enclosed_char)
1557 {
1558 if ((chr=GET) == found_enclosed_char)
1559 { // Remove dupplicated
1560 data.append(chr);
1561 continue;
1562 }
1563 // End of enclosed field if followed by field_term or line_term
1564 if (chr == my_b_EOF || terminator(chr, m_line_term))
1565 {
1566 /* Maybe unexpected linefeed */
1567 enclosed=1;
1568 found_end_of_line=1;
1569 row_start= (uchar *) data.ptr() + 1;
1570 row_end= (uchar *) data.end();
1571 return 0;
1572 }
1573 if (terminator(chr, m_field_term))
1574 {
1575 enclosed=1;
1576 row_start= (uchar *) data.ptr() + 1;
1577 row_end= (uchar *) data.end();
1578 return 0;
1579 }
1580 /*
1581 The string didn't terminate yet.
1582 Store back next character for the loop
1583 */
1584 PUSH(chr);
1585 /* copy the found term character to 'to' */
1586 chr= found_enclosed_char;
1587 }
1588 else if (chr == m_field_term.initial_byte() &&
1589 found_enclosed_char == INT_MAX)
1590 {
1591 if (terminator(m_field_term))
1592 {
1593 enclosed=0;
1594 row_start= (uchar *) data.ptr();
1595 row_end= (uchar *) data.end();
1596 return 0;
1597 }
1598 }
1599 data.append(chr);
1600 if (use_mb(charset()) && read_mbtail(&data))
1601 goto found_eof;
1602 }
1603 /*
1604 ** We come here if buffer is too small. Enlarge it and continue
1605 */
1606 if (data.reserve(IO_SIZE))
1607 return (error= 1);
1608 }
1609
1610 found_eof:
1611 enclosed=0;
1612 found_end_of_line=eof=1;
1613 row_start= (uchar *) data.ptr();
1614 row_end= (uchar *) data.end();
1615 return 0;
1616 }
1617
1618 /*
1619 Read a row with fixed length.
1620
1621 NOTES
1622 The row may not be fixed size on disk if there are escape
1623 characters in the file.
1624
1625 IMPLEMENTATION NOTE
1626 One can't use fixed length with multi-byte charset **
1627
1628 RETURN
1629 0 ok
1630 1 error
1631 */
1632
read_fixed_length()1633 int READ_INFO::read_fixed_length()
1634 {
1635 int chr;
1636 if (found_end_of_line)
1637 return 1; // One have to call next_line
1638
1639 if (start_of_line)
1640 { // Skip until line_start
1641 start_of_line=0;
1642 if (find_start_of_fields())
1643 return 1;
1644 }
1645
1646 for (data.length(0); data.length() < m_fixed_length ; )
1647 {
1648 if ((chr=GET) == my_b_EOF)
1649 goto found_eof;
1650 if (chr == escape_char)
1651 {
1652 if ((chr=GET) == my_b_EOF)
1653 {
1654 data.append(escape_char);
1655 goto found_eof;
1656 }
1657 data.append((uchar) unescape((char) chr));
1658 continue;
1659 }
1660 if (terminator(chr, m_line_term))
1661 { // Maybe unexpected linefeed
1662 found_end_of_line= true;
1663 break;
1664 }
1665 data.append(chr);
1666 }
1667 row_start= (uchar *) data.ptr();
1668 row_end= (uchar *) data.end(); // Found full line
1669 return 0;
1670
1671 found_eof:
1672 found_end_of_line=eof=1;
1673 row_start= (uchar *) data.ptr();
1674 row_end= (uchar *) data.end();
1675 return data.length() == 0 ? 1 : 0;
1676 }
1677
1678
next_line()1679 int READ_INFO::next_line()
1680 {
1681 line_cuted=0;
1682 start_of_line= m_line_start.length() != 0;
1683 if (found_end_of_line || eof)
1684 {
1685 found_end_of_line=0;
1686 return eof;
1687 }
1688 found_end_of_line=0;
1689 if (!m_line_term.length())
1690 return 0; // No lines
1691 for (;;)
1692 {
1693 int chlen;
1694 char buf[MY_CS_MBMAXLEN];
1695
1696 if (getbyte(&buf[0]))
1697 return 1; // EOF
1698
1699 if (use_mb(charset()) &&
1700 (chlen= my_charlen(charset(), buf, buf + 1)) != 1)
1701 {
1702 uint i;
1703 for (i= 1; MY_CS_IS_TOOSMALL(chlen); )
1704 {
1705 DBUG_ASSERT(i < sizeof(buf));
1706 DBUG_ASSERT(chlen != 1);
1707 if (getbyte(&buf[i++]))
1708 return 1; // EOF
1709 chlen= my_charlen(charset(), buf, buf + i);
1710 }
1711
1712 /*
1713 Either a complete multi-byte sequence,
1714 or a broken byte sequence was found.
1715 Check if the sequence is a prefix of the "LINES TERMINATED BY" string.
1716 */
1717 if ((uchar) buf[0] == m_line_term.initial_byte() &&
1718 i <= m_line_term.length() &&
1719 !memcmp(buf, m_line_term.ptr(), i))
1720 {
1721 if (m_line_term.length() == i)
1722 {
1723 /*
1724 We found a "LINES TERMINATED BY" string that consists
1725 of a single multi-byte character.
1726 */
1727 return 0;
1728 }
1729 /*
1730 buf[] is a prefix of "LINES TERMINATED BY".
1731 Now check the suffix. Length of the suffix of line_term_ptr
1732 that still needs to be checked is (line_term_length - i).
1733 Note, READ_INFO::terminator() assumes that the leftmost byte of the
1734 argument is already scanned from the file and is checked to
1735 be a known prefix (e.g. against line_term.initial_char()).
1736 So we need to pass one extra byte.
1737 */
1738 if (terminator(m_line_term.ptr() + i - 1,
1739 m_line_term.length() - i + 1))
1740 return 0;
1741 }
1742 /*
1743 Here we have a good multi-byte sequence or a broken byte sequence,
1744 and the sequence is not equal to "LINES TERMINATED BY".
1745 No needs to check for escape_char, because:
1746 - multi-byte escape characters in "FIELDS ESCAPED BY" are not
1747 supported and are rejected at parse time.
1748 - broken single-byte sequences are not recognized as escapes,
1749 they are considered to be a part of the data and are converted to
1750 question marks.
1751 */
1752 line_cuted= true;
1753 continue;
1754 }
1755 if (buf[0] == escape_char)
1756 {
1757 line_cuted= true;
1758 if (GET == my_b_EOF)
1759 return 1;
1760 continue;
1761 }
1762 if (terminator(buf[0], m_line_term))
1763 return 0;
1764 line_cuted= true;
1765 }
1766 }
1767
1768
find_start_of_fields()1769 bool READ_INFO::find_start_of_fields()
1770 {
1771 for (int chr= GET ; chr != my_b_EOF ; chr= GET)
1772 {
1773 if (terminator(chr, m_line_start))
1774 return false;
1775 }
1776 return (found_end_of_line= eof= true);
1777 }
1778
1779
1780 /*
1781 Clear taglist from tags with a specified level
1782 */
clear_level(int level_arg)1783 int READ_INFO::clear_level(int level_arg)
1784 {
1785 DBUG_ENTER("READ_INFO::read_xml clear_level");
1786 List_iterator<XML_TAG> xmlit(taglist);
1787 xmlit.rewind();
1788 XML_TAG *tag;
1789
1790 while ((tag= xmlit++))
1791 {
1792 if(tag->level >= level_arg)
1793 {
1794 xmlit.remove();
1795 delete tag;
1796 }
1797 }
1798 DBUG_RETURN(0);
1799 }
1800
1801
1802 /*
1803 Convert an XML entity to Unicode value.
1804 Return -1 on error;
1805 */
1806 static int
my_xml_entity_to_char(const char * name,uint length)1807 my_xml_entity_to_char(const char *name, uint length)
1808 {
1809 if (length == 2)
1810 {
1811 if (!memcmp(name, "gt", length))
1812 return '>';
1813 if (!memcmp(name, "lt", length))
1814 return '<';
1815 }
1816 else if (length == 3)
1817 {
1818 if (!memcmp(name, "amp", length))
1819 return '&';
1820 }
1821 else if (length == 4)
1822 {
1823 if (!memcmp(name, "quot", length))
1824 return '"';
1825 if (!memcmp(name, "apos", length))
1826 return '\'';
1827 }
1828 return -1;
1829 }
1830
1831
1832 /**
1833 @brief Convert newline, linefeed, tab to space
1834
1835 @param chr character
1836
1837 @details According to the "XML 1.0" standard,
1838 only space (#x20) characters, carriage returns,
1839 line feeds or tabs are considered as spaces.
1840 Convert all of them to space (#x20) for parsing simplicity.
1841 */
1842 static int
my_tospace(int chr)1843 my_tospace(int chr)
1844 {
1845 return (chr == '\t' || chr == '\r' || chr == '\n') ? ' ' : chr;
1846 }
1847
1848
1849 /*
1850 Read an xml value: handle multibyte and xml escape
1851 */
read_value(int delim,String * val)1852 int READ_INFO::read_value(int delim, String *val)
1853 {
1854 int chr;
1855 String tmp;
1856
1857 for (chr= GET; my_tospace(chr) != delim && chr != my_b_EOF; chr= GET)
1858 {
1859 if(chr == '&')
1860 {
1861 tmp.length(0);
1862 for (chr= my_tospace(GET) ; chr != ';' ; chr= my_tospace(GET))
1863 {
1864 if (chr == my_b_EOF)
1865 return chr;
1866 tmp.append(chr);
1867 }
1868 if ((chr= my_xml_entity_to_char(tmp.ptr(), tmp.length())) >= 0)
1869 val->append(chr);
1870 else
1871 {
1872 val->append('&');
1873 val->append(tmp);
1874 val->append(';');
1875 }
1876 }
1877 else
1878 {
1879 val->append(chr);
1880 if (use_mb(charset()) && read_mbtail(val))
1881 return my_b_EOF;
1882 }
1883 }
1884 return my_tospace(chr);
1885 }
1886
1887
1888 /*
1889 Read a record in xml format
1890 tags and attributes are stored in taglist
1891 when tag set in ROWS IDENTIFIED BY is closed, we are ready and return
1892 */
read_xml(THD * thd)1893 int READ_INFO::read_xml(THD *thd)
1894 {
1895 DBUG_ENTER("READ_INFO::read_xml");
1896 int chr, chr2, chr3;
1897 int delim= 0;
1898 String tag, attribute, value;
1899 bool in_tag= false;
1900
1901 tag.length(0);
1902 attribute.length(0);
1903 value.length(0);
1904
1905 for (chr= my_tospace(GET); chr != my_b_EOF ; )
1906 {
1907 switch(chr){
1908 case '<': /* read tag */
1909 /* TODO: check if this is a comment <!-- comment --> */
1910 chr= my_tospace(GET);
1911 if(chr == '!')
1912 {
1913 chr2= GET;
1914 chr3= GET;
1915
1916 if(chr2 == '-' && chr3 == '-')
1917 {
1918 chr2= 0;
1919 chr3= 0;
1920 chr= my_tospace(GET);
1921
1922 while(chr != '>' || chr2 != '-' || chr3 != '-')
1923 {
1924 if(chr == '-')
1925 {
1926 chr3= chr2;
1927 chr2= chr;
1928 }
1929 else if (chr2 == '-')
1930 {
1931 chr2= 0;
1932 chr3= 0;
1933 }
1934 chr= my_tospace(GET);
1935 if (chr == my_b_EOF)
1936 goto found_eof;
1937 }
1938 break;
1939 }
1940 }
1941
1942 tag.length(0);
1943 while(chr != '>' && chr != ' ' && chr != '/' && chr != my_b_EOF)
1944 {
1945 if(chr != delim) /* fix for the '<field name =' format */
1946 tag.append(chr);
1947 chr= my_tospace(GET);
1948 }
1949
1950 // row tag should be in ROWS IDENTIFIED BY '<row>' - stored in line_term
1951 if((tag.length() == m_line_term.length() - 2) &&
1952 (memcmp(tag.ptr(), m_line_term.ptr() + 1, tag.length()) == 0))
1953 {
1954 DBUG_PRINT("read_xml", ("start-of-row: %i %s %s",
1955 level,tag.c_ptr_safe(), m_line_term.ptr()));
1956 }
1957
1958 if(chr == ' ' || chr == '>')
1959 {
1960 level++;
1961 clear_level(level + 1);
1962 }
1963
1964 if (chr == ' ')
1965 in_tag= true;
1966 else
1967 in_tag= false;
1968 break;
1969
1970 case ' ': /* read attribute */
1971 while(chr == ' ') /* skip blanks */
1972 chr= my_tospace(GET);
1973
1974 if(!in_tag)
1975 break;
1976
1977 while(chr != '=' && chr != '/' && chr != '>' && chr != my_b_EOF)
1978 {
1979 attribute.append(chr);
1980 chr= my_tospace(GET);
1981 }
1982 break;
1983
1984 case '>': /* end tag - read tag value */
1985 in_tag= false;
1986 chr= read_value('<', &value);
1987 if(chr == my_b_EOF)
1988 goto found_eof;
1989
1990 /* save value to list */
1991 if (tag.length() > 0 && value.length() > 0)
1992 {
1993 DBUG_PRINT("read_xml", ("lev:%i tag:%s val:%s",
1994 level,tag.c_ptr_safe(), value.c_ptr_safe()));
1995 XML_TAG *tmp= new XML_TAG(level, tag, value);
1996 if (!tmp || taglist.push_front(tmp, thd->mem_root))
1997 DBUG_RETURN(1); // End of memory
1998 }
1999 tag.length(0);
2000 value.length(0);
2001 attribute.length(0);
2002 break;
2003
2004 case '/': /* close tag */
2005 chr= my_tospace(GET);
2006 /* Decrease the 'level' only when (i) It's not an */
2007 /* (without space) empty tag i.e. <tag/> or, (ii) */
2008 /* It is of format <row col="val" .../> */
2009 if(chr != '>' || in_tag)
2010 {
2011 level--;
2012 in_tag= false;
2013 }
2014 if(chr != '>') /* if this is an empty tag <tag /> */
2015 tag.length(0); /* we should keep tag value */
2016 while(chr != '>' && chr != my_b_EOF)
2017 {
2018 tag.append(chr);
2019 chr= my_tospace(GET);
2020 }
2021
2022 if((tag.length() == m_line_term.length() - 2) &&
2023 (memcmp(tag.ptr(), m_line_term.ptr() + 1, tag.length()) == 0))
2024 {
2025 DBUG_PRINT("read_xml", ("found end-of-row %i %s",
2026 level, tag.c_ptr_safe()));
2027 DBUG_RETURN(0); //normal return
2028 }
2029 chr= my_tospace(GET);
2030 break;
2031
2032 case '=': /* attribute name end - read the value */
2033 //check for tag field and attribute name
2034 if(!strcmp(tag.c_ptr_safe(), "field") &&
2035 !strcmp(attribute.c_ptr_safe(), "name"))
2036 {
2037 /*
2038 this is format <field name="xx">xx</field>
2039 where actual fieldname is in attribute
2040 */
2041 delim= my_tospace(GET);
2042 tag.length(0);
2043 attribute.length(0);
2044 chr= '<'; /* we pretend that it is a tag */
2045 level--;
2046 break;
2047 }
2048
2049 //check for " or '
2050 chr= GET;
2051 if (chr == my_b_EOF)
2052 goto found_eof;
2053 if(chr == '"' || chr == '\'')
2054 {
2055 delim= chr;
2056 }
2057 else
2058 {
2059 delim= ' '; /* no delimiter, use space */
2060 PUSH(chr);
2061 }
2062
2063 chr= read_value(delim, &value);
2064 if (attribute.length() > 0 && value.length() > 0)
2065 {
2066 DBUG_PRINT("read_xml", ("lev:%i att:%s val:%s",
2067 level + 1,
2068 attribute.c_ptr_safe(),
2069 value.c_ptr_safe()));
2070 XML_TAG *tmp= new XML_TAG(level + 1, attribute, value);
2071 if (!tmp || taglist.push_front(tmp, thd->mem_root))
2072 DBUG_RETURN(1); // End of memory
2073 }
2074 attribute.length(0);
2075 value.length(0);
2076 if (chr != ' ')
2077 chr= my_tospace(GET);
2078 break;
2079
2080 default:
2081 chr= my_tospace(GET);
2082 } /* end switch */
2083 } /* end while */
2084
2085 found_eof:
2086 DBUG_PRINT("read_xml",("Found eof"));
2087 eof= 1;
2088 DBUG_RETURN(1);
2089 }
2090