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