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 bool escaped_mb= false;
1549 while ( to < end_of_buff)
1550 {
1551 chr = GET;
1552 if (chr == my_b_EOF)
1553 goto found_eof;
1554 if (chr == escape_char)
1555 {
1556 if ((chr=GET) == my_b_EOF)
1557 {
1558 *to++= (uchar) escape_char;
1559 goto found_eof;
1560 }
1561 /*
1562 When escape_char == enclosed_char, we treat it like we do for
1563 handling quotes in SQL parsing -- you can double-up the
1564 escape_char to include it literally, but it doesn't do escapes
1565 like \n. This allows: LOAD DATA ... ENCLOSED BY '"' ESCAPED BY '"'
1566 with data like: "fie""ld1", "field2"
1567 */
1568 if (escape_char != enclosed_char || chr == escape_char)
1569 {
1570 uint ml= my_mbcharlen(read_charset, chr);
1571 /*
1572 For escaped multibyte character, push back the first byte,
1573 and will handle it below.
1574 Because multibyte character's second byte is possible to be
1575 0x5C, per Query_result_export::send_data, both head byte and
1576 tail byte are escaped for such characters. So mark it if the
1577 head byte is escaped and will handle it below.
1578 */
1579 if (ml == 1)
1580 *to++= (uchar) unescape((char) chr);
1581 else
1582 {
1583 escaped_mb= true;
1584 PUSH(chr);
1585 }
1586 continue;
1587 }
1588 PUSH(chr);
1589 chr= escape_char;
1590 }
1591 #ifdef ALLOW_LINESEPARATOR_IN_STRINGS
1592 if (chr == line_term_char)
1593 #else
1594 if (chr == line_term_char && found_enclosed_char == INT_MAX)
1595 #endif
1596 {
1597 if (terminator(line_term_ptr,line_term_length))
1598 { // Maybe unexpected linefeed
1599 enclosed=0;
1600 found_end_of_line=1;
1601 row_start=buffer;
1602 row_end= to;
1603 return 0;
1604 }
1605 }
1606 if (chr == found_enclosed_char)
1607 {
1608 if ((chr=GET) == found_enclosed_char)
1609 { // Remove dupplicated
1610 *to++ = (uchar) chr;
1611 continue;
1612 }
1613 // End of enclosed field if followed by field_term or line_term
1614 if (chr == my_b_EOF ||
1615 (chr == line_term_char && terminator(line_term_ptr,
1616 line_term_length)))
1617 { // Maybe unexpected linefeed
1618 enclosed=1;
1619 found_end_of_line=1;
1620 row_start=buffer+1;
1621 row_end= to;
1622 return 0;
1623 }
1624 if (chr == field_term_char &&
1625 terminator(field_term_ptr,field_term_length))
1626 {
1627 enclosed=1;
1628 row_start=buffer+1;
1629 row_end= to;
1630 return 0;
1631 }
1632 /*
1633 The string didn't terminate yet.
1634 Store back next character for the loop
1635 */
1636 PUSH(chr);
1637 /* copy the found term character to 'to' */
1638 chr= found_enclosed_char;
1639 }
1640 else if (chr == field_term_char && found_enclosed_char == INT_MAX)
1641 {
1642 if (terminator(field_term_ptr,field_term_length))
1643 {
1644 enclosed=0;
1645 row_start=buffer;
1646 row_end= to;
1647 return 0;
1648 }
1649 }
1650 #ifdef USE_MB
1651 uint ml= my_mbcharlen(read_charset, chr);
1652 if (ml == 0)
1653 {
1654 *to= '\0';
1655 my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
1656 read_charset->csname, buffer);
1657 error= true;
1658 return 1;
1659 }
1660
1661 if (ml > 1 &&
1662 to + ml <= end_of_buff)
1663 {
1664 uchar* p= to;
1665 *to++ = chr;
1666
1667 for (uint i= 1; i < ml; i++)
1668 {
1669 chr= GET;
1670 if (chr == my_b_EOF)
1671 {
1672 /*
1673 Need to back up the bytes already ready from illformed
1674 multi-byte char
1675 */
1676 to-= i;
1677 goto found_eof;
1678 }
1679 else if (chr == escape_char && escaped_mb)
1680 {
1681 // Unescape the second byte if it is escaped.
1682 chr= GET;
1683 chr= (uchar) unescape((char) chr);
1684 }
1685 *to++ = chr;
1686 }
1687 if (escaped_mb)
1688 escaped_mb= false;
1689 if (my_ismbchar(read_charset,
1690 (const char *)p,
1691 (const char *)to))
1692 continue;
1693 for (uint i= 0; i < ml; i++)
1694 PUSH(*--to);
1695 chr= GET;
1696 }
1697 #endif
1698 else if (ml > 1)
1699 {
1700 // Buffer is too small, exit while loop, and reallocate.
1701 PUSH(chr);
1702 break;
1703 }
1704 *to++ = (uchar) chr;
1705 }
1706 /*
1707 ** We come here if buffer is too small. Enlarge it and continue
1708 */
1709 if (!(new_buffer=(uchar*) my_realloc((char*) buffer,buff_length+1+IO_SIZE,
1710 MYF(MY_WME))))
1711 return (error=true);
1712 to=new_buffer + (to-buffer);
1713 buffer=new_buffer;
1714 buff_length+=IO_SIZE;
1715 end_of_buff=buffer+buff_length;
1716 }
1717
1718 found_eof:
1719 enclosed=0;
1720 found_end_of_line=eof=1;
1721 row_start=buffer;
1722 row_end=to;
1723 return 0;
1724 }
1725
1726 /*
1727 Read a row with fixed length.
1728
1729 NOTES
1730 The row may not be fixed size on disk if there are escape
1731 characters in the file.
1732
1733 IMPLEMENTATION NOTE
1734 One can't use fixed length with multi-byte charset **
1735
1736 RETURN
1737 0 ok
1738 1 error
1739 */
1740
read_fixed_length()1741 int READ_INFO::read_fixed_length()
1742 {
1743 int chr;
1744 uchar *to;
1745 if (found_end_of_line)
1746 return 1; // One have to call next_line
1747
1748 if (start_of_line)
1749 { // Skip until line_start
1750 start_of_line=0;
1751 if (find_start_of_fields())
1752 return 1;
1753 }
1754
1755 to=row_start=buffer;
1756 while (to < end_of_buff)
1757 {
1758 if ((chr=GET) == my_b_EOF)
1759 goto found_eof;
1760 if (chr == escape_char)
1761 {
1762 if ((chr=GET) == my_b_EOF)
1763 {
1764 *to++= (uchar) escape_char;
1765 goto found_eof;
1766 }
1767 *to++ =(uchar) unescape((char) chr);
1768 continue;
1769 }
1770 if (chr == line_term_char)
1771 {
1772 if (terminator(line_term_ptr,line_term_length))
1773 { // Maybe unexpected linefeed
1774 found_end_of_line=1;
1775 row_end= to;
1776 return 0;
1777 }
1778 }
1779 *to++ = (uchar) chr;
1780 }
1781 row_end=to; // Found full line
1782 return 0;
1783
1784 found_eof:
1785 found_end_of_line=eof=1;
1786 row_start=buffer;
1787 row_end=to;
1788 return to == buffer ? 1 : 0;
1789 }
1790
1791
next_line()1792 int READ_INFO::next_line()
1793 {
1794 line_cuted=0;
1795 start_of_line= line_start_ptr != 0;
1796 if (found_end_of_line || eof)
1797 {
1798 found_end_of_line=0;
1799 return eof;
1800 }
1801 found_end_of_line=0;
1802 if (!line_term_length)
1803 return 0; // No lines
1804 for (;;)
1805 {
1806 int chr = GET;
1807 #ifdef USE_MB
1808 if (chr == my_b_EOF)
1809 {
1810 eof= 1;
1811 return 1;
1812 }
1813 if (my_mbcharlen(read_charset, chr) > 1)
1814 {
1815 for (uint i=1;
1816 chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
1817 i++)
1818 chr = GET;
1819 if (chr == escape_char)
1820 continue;
1821 }
1822 #endif
1823 if (chr == my_b_EOF)
1824 {
1825 eof=1;
1826 return 1;
1827 }
1828 if (chr == escape_char)
1829 {
1830 line_cuted=1;
1831 if (GET == my_b_EOF)
1832 return 1;
1833 continue;
1834 }
1835 if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1836 return 0;
1837 line_cuted=1;
1838 }
1839 }
1840
1841
find_start_of_fields()1842 bool READ_INFO::find_start_of_fields()
1843 {
1844 int chr;
1845 try_again:
1846 do
1847 {
1848 if ((chr=GET) == my_b_EOF)
1849 {
1850 found_end_of_line=eof=1;
1851 return 1;
1852 }
1853 } while ((char) chr != line_start_ptr[0]);
1854 for (const char *ptr=line_start_ptr+1 ; ptr != line_start_end ; ptr++)
1855 {
1856 chr=GET; // Eof will be checked later
1857 if ((char) chr != *ptr)
1858 { // Can't be line_start
1859 PUSH(chr);
1860 while (--ptr != line_start_ptr)
1861 { // Restart with next char
1862 PUSH( *ptr);
1863 }
1864 goto try_again;
1865 }
1866 }
1867 return 0;
1868 }
1869
1870
1871 /*
1872 Clear taglist from tags with a specified level
1873 */
clear_level(int level_arg)1874 int READ_INFO::clear_level(int level_arg)
1875 {
1876 DBUG_ENTER("READ_INFO::read_xml clear_level");
1877 List_iterator<XML_TAG> xmlit(taglist);
1878 xmlit.rewind();
1879 XML_TAG *tag;
1880
1881 while ((tag= xmlit++))
1882 {
1883 if(tag->level >= level_arg)
1884 {
1885 xmlit.remove();
1886 delete tag;
1887 }
1888 }
1889 DBUG_RETURN(0);
1890 }
1891
1892
1893 /*
1894 Convert an XML entity to Unicode value.
1895 Return -1 on error;
1896 */
1897 static int
my_xml_entity_to_char(const char * name,uint length)1898 my_xml_entity_to_char(const char *name, uint length)
1899 {
1900 if (length == 2)
1901 {
1902 if (!memcmp(name, "gt", length))
1903 return '>';
1904 if (!memcmp(name, "lt", length))
1905 return '<';
1906 }
1907 else if (length == 3)
1908 {
1909 if (!memcmp(name, "amp", length))
1910 return '&';
1911 }
1912 else if (length == 4)
1913 {
1914 if (!memcmp(name, "quot", length))
1915 return '"';
1916 if (!memcmp(name, "apos", length))
1917 return '\'';
1918 }
1919 return -1;
1920 }
1921
1922
1923 /**
1924 @brief Convert newline, linefeed, tab to space
1925
1926 @param chr character
1927
1928 @details According to the "XML 1.0" standard,
1929 only space (#x20) characters, carriage returns,
1930 line feeds or tabs are considered as spaces.
1931 Convert all of them to space (#x20) for parsing simplicity.
1932 */
1933 static int
my_tospace(int chr)1934 my_tospace(int chr)
1935 {
1936 return (chr == '\t' || chr == '\r' || chr == '\n') ? ' ' : chr;
1937 }
1938
1939
1940 /*
1941 Read an xml value: handle multibyte and xml escape
1942 */
read_value(int delim,String * val)1943 int READ_INFO::read_value(int delim, String *val)
1944 {
1945 int chr;
1946 String tmp;
1947
1948 for (chr= GET; my_tospace(chr) != delim && chr != my_b_EOF;)
1949 {
1950 #ifdef USE_MB
1951 uint ml= my_mbcharlen(read_charset, chr);
1952 if (ml == 0)
1953 {
1954 chr= my_b_EOF;
1955 val->length(0);
1956 return chr;
1957 }
1958
1959 if (ml > 1)
1960 {
1961 DBUG_PRINT("read_xml",("multi byte"));
1962
1963 for (uint i= 1; i < ml; i++)
1964 {
1965 val->append(chr);
1966 /*
1967 Don't use my_tospace() in the middle of a multi-byte character
1968 TODO: check that the multi-byte sequence is valid.
1969 */
1970 chr= GET;
1971 if (chr == my_b_EOF)
1972 return chr;
1973 }
1974 }
1975 #endif
1976 if(chr == '&')
1977 {
1978 tmp.length(0);
1979 for (chr= my_tospace(GET) ; chr != ';' ; chr= my_tospace(GET))
1980 {
1981 if (chr == my_b_EOF)
1982 return chr;
1983 tmp.append(chr);
1984 }
1985 if ((chr= my_xml_entity_to_char(tmp.ptr(), tmp.length())) >= 0)
1986 val->append(chr);
1987 else
1988 {
1989 val->append('&');
1990 val->append(tmp);
1991 val->append(';');
1992 }
1993 }
1994 else
1995 val->append(chr);
1996 chr= GET;
1997 }
1998 return my_tospace(chr);
1999 }
2000
2001
2002 /*
2003 Read a record in xml format
2004 tags and attributes are stored in taglist
2005 when tag set in ROWS IDENTIFIED BY is closed, we are ready and return
2006 */
read_xml()2007 int READ_INFO::read_xml()
2008 {
2009 DBUG_ENTER("READ_INFO::read_xml");
2010 int chr, chr2, chr3;
2011 int delim= 0;
2012 String tag, attribute, value;
2013 bool in_tag= false;
2014
2015 tag.length(0);
2016 attribute.length(0);
2017 value.length(0);
2018
2019 for (chr= my_tospace(GET); chr != my_b_EOF ; )
2020 {
2021 switch(chr){
2022 case '<': /* read tag */
2023 /* TODO: check if this is a comment <!-- comment --> */
2024 chr= my_tospace(GET);
2025 if(chr == '!')
2026 {
2027 chr2= GET;
2028 chr3= GET;
2029
2030 if(chr2 == '-' && chr3 == '-')
2031 {
2032 chr2= 0;
2033 chr3= 0;
2034 chr= my_tospace(GET);
2035
2036 while(chr != '>' || chr2 != '-' || chr3 != '-')
2037 {
2038 if(chr == '-')
2039 {
2040 chr3= chr2;
2041 chr2= chr;
2042 }
2043 else if (chr2 == '-')
2044 {
2045 chr2= 0;
2046 chr3= 0;
2047 }
2048 chr= my_tospace(GET);
2049 if (chr == my_b_EOF)
2050 goto found_eof;
2051 }
2052 break;
2053 }
2054 }
2055
2056 tag.length(0);
2057 while(chr != '>' && chr != ' ' && chr != '/' && chr != my_b_EOF)
2058 {
2059 if(chr != delim) /* fix for the '<field name =' format */
2060 tag.append(chr);
2061 chr= my_tospace(GET);
2062 }
2063
2064 // row tag should be in ROWS IDENTIFIED BY '<row>' - stored in line_term
2065 if((tag.length() == line_term_length -2) &&
2066 (memcmp(tag.ptr(), line_term_ptr + 1, tag.length()) == 0))
2067 {
2068 DBUG_PRINT("read_xml", ("start-of-row: %i %s %s",
2069 level,tag.c_ptr_safe(), line_term_ptr));
2070 }
2071
2072 if(chr == ' ' || chr == '>')
2073 {
2074 level++;
2075 clear_level(level + 1);
2076 }
2077
2078 if (chr == ' ')
2079 in_tag= true;
2080 else
2081 in_tag= false;
2082 break;
2083
2084 case ' ': /* read attribute */
2085 while(chr == ' ') /* skip blanks */
2086 chr= my_tospace(GET);
2087
2088 if(!in_tag)
2089 break;
2090
2091 while(chr != '=' && chr != '/' && chr != '>' && chr != my_b_EOF)
2092 {
2093 attribute.append(chr);
2094 chr= my_tospace(GET);
2095 }
2096 break;
2097
2098 case '>': /* end tag - read tag value */
2099 in_tag= false;
2100 /* Skip all whitespaces */
2101 while (' ' == (chr= my_tospace(GET)))
2102 {
2103 }
2104 /*
2105 Push the first non-whitespace char back to Stack. This char would be
2106 read in the upcoming call to read_value()
2107 */
2108 PUSH(chr);
2109 chr= read_value('<', &value);
2110 if(chr == my_b_EOF)
2111 goto found_eof;
2112
2113 /* save value to list */
2114 if(tag.length() > 0 && value.length() > 0)
2115 {
2116 DBUG_PRINT("read_xml", ("lev:%i tag:%s val:%s",
2117 level,tag.c_ptr_safe(), value.c_ptr_safe()));
2118 taglist.push_front( new XML_TAG(level, tag, value));
2119 }
2120 tag.length(0);
2121 value.length(0);
2122 attribute.length(0);
2123 break;
2124
2125 case '/': /* close tag */
2126 chr= my_tospace(GET);
2127 /* Decrease the 'level' only when (i) It's not an */
2128 /* (without space) empty tag i.e. <tag/> or, (ii) */
2129 /* It is of format <row col="val" .../> */
2130 if(chr != '>' || in_tag)
2131 {
2132 level--;
2133 in_tag= false;
2134 }
2135 if(chr != '>') /* if this is an empty tag <tag /> */
2136 tag.length(0); /* we should keep tag value */
2137 while(chr != '>' && chr != my_b_EOF)
2138 {
2139 tag.append(chr);
2140 chr= my_tospace(GET);
2141 }
2142
2143 if((tag.length() == line_term_length -2) &&
2144 (memcmp(tag.ptr(), line_term_ptr + 1, tag.length()) == 0))
2145 {
2146 DBUG_PRINT("read_xml", ("found end-of-row %i %s",
2147 level, tag.c_ptr_safe()));
2148 DBUG_RETURN(0); //normal return
2149 }
2150 chr= my_tospace(GET);
2151 break;
2152
2153 case '=': /* attribute name end - read the value */
2154 //check for tag field and attribute name
2155 if(!memcmp(tag.c_ptr_safe(), STRING_WITH_LEN("field")) &&
2156 !memcmp(attribute.c_ptr_safe(), STRING_WITH_LEN("name")))
2157 {
2158 /*
2159 this is format <field name="xx">xx</field>
2160 where actual fieldname is in attribute
2161 */
2162 delim= my_tospace(GET);
2163 tag.length(0);
2164 attribute.length(0);
2165 chr= '<'; /* we pretend that it is a tag */
2166 level--;
2167 break;
2168 }
2169
2170 //check for " or '
2171 chr= GET;
2172 if (chr == my_b_EOF)
2173 goto found_eof;
2174 if(chr == '"' || chr == '\'')
2175 {
2176 delim= chr;
2177 }
2178 else
2179 {
2180 delim= ' '; /* no delimiter, use space */
2181 PUSH(chr);
2182 }
2183
2184 chr= read_value(delim, &value);
2185 if(attribute.length() > 0 && value.length() > 0)
2186 {
2187 DBUG_PRINT("read_xml", ("lev:%i att:%s val:%s\n",
2188 level + 1,
2189 attribute.c_ptr_safe(),
2190 value.c_ptr_safe()));
2191 taglist.push_front(new XML_TAG(level + 1, attribute, value));
2192 }
2193 attribute.length(0);
2194 value.length(0);
2195 if (chr != ' ')
2196 chr= my_tospace(GET);
2197 break;
2198
2199 default:
2200 chr= my_tospace(GET);
2201 } /* end switch */
2202 } /* end while */
2203
2204 found_eof:
2205 DBUG_PRINT("read_xml",("Found eof"));
2206 eof= 1;
2207 DBUG_RETURN(1);
2208 }
2209