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