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