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