~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_load.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* Copy data from a textfile to table */
18
 
 
19
 
#include "config.h"
20
 
#include <drizzled/sql_load.h>
21
 
#include <drizzled/error.h>
22
 
#include <drizzled/data_home.h>
23
 
#include <drizzled/session.h>
24
 
#include <drizzled/sql_base.h>
25
 
#include <drizzled/field/timestamp.h>
26
 
#include "drizzled/internal/my_sys.h"
27
 
#include "drizzled/internal/iocache.h"
28
 
#include <drizzled/db.h>
29
 
 
30
 
#include <sys/stat.h>
31
 
#include <fcntl.h>
32
 
#include <algorithm>
33
 
#include <climits>
34
 
 
35
 
using namespace std;
36
 
namespace drizzled
 
18
/* 2006-12 Erik Wetterberg : LOAD XML added */
 
19
 
 
20
#include "mysql_priv.h"
 
21
#include <my_dir.h>
 
22
#include <m_ctype.h>
 
23
#include "sql_repl.h"
 
24
 
 
25
class XML_TAG {
 
26
public:
 
27
  int level;
 
28
  String field;
 
29
  String value;
 
30
  XML_TAG(int l, String f, String v);
 
31
};
 
32
 
 
33
 
 
34
XML_TAG::XML_TAG(int l, String f, String v)
37
35
{
 
36
  level= l;
 
37
  field.append(f);
 
38
  value.append(v);
 
39
}
 
40
 
38
41
 
39
42
class READ_INFO {
40
 
  int   cursor;
41
 
  unsigned char *buffer;                /* Buffer for read text */
42
 
  unsigned char *end_of_buff;           /* Data in bufferts ends here */
43
 
  size_t buff_length;                   /* Length of buffert */
44
 
  size_t max_length;                    /* Max length of row */
 
43
  File  file;
 
44
  uchar *buffer,                        /* Buffer for read text */
 
45
        *end_of_buff;                   /* Data in bufferts ends here */
 
46
  uint  buff_length,                    /* Length of buffert */
 
47
        max_length;                     /* Max length of row */
45
48
  char  *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
46
49
  uint  field_term_length,line_term_length,enclosed_length;
47
50
  int   field_term_char,line_term_char,enclosed_char,escape_char;
48
51
  int   *stack,*stack_pos;
49
52
  bool  found_end_of_line,start_of_line,eof;
50
53
  bool  need_end_io_cache;
51
 
  internal::IO_CACHE cache;
 
54
  IO_CACHE cache;
 
55
  NET *io_net;
 
56
  int level; /* for load xml */
52
57
 
53
58
public:
54
59
  bool error,line_cuted,found_null,enclosed;
55
 
  unsigned char *row_start,                     /* Found row starts here */
 
60
  uchar *row_start,                     /* Found row starts here */
56
61
        *row_end;                       /* Found row ends here */
57
 
  const CHARSET_INFO *read_charset;
 
62
  CHARSET_INFO *read_charset;
58
63
 
59
 
  READ_INFO(int cursor, size_t tot_length, const CHARSET_INFO * const cs,
 
64
  READ_INFO(File file,uint tot_length,CHARSET_INFO *cs,
60
65
            String &field_term,String &line_start,String &line_term,
61
 
            String &enclosed,int escape, bool is_fifo);
 
66
            String &enclosed,int escape,bool get_it_from_net, bool is_fifo);
62
67
  ~READ_INFO();
63
68
  int read_field();
64
69
  int read_fixed_length(void);
65
70
  int next_line(void);
66
71
  char unescape(char chr);
67
 
  int terminator(char *ptr,uint32_t length);
 
72
  int terminator(char *ptr,uint length);
68
73
  bool find_start_of_fields();
 
74
  /* load xml */
 
75
  List<XML_TAG> taglist;
 
76
  int read_value(int delim, String *val);
 
77
  int read_xml();
 
78
  int clear_level(int level);
69
79
 
70
80
  /*
71
81
    We need to force cache close before destructor is invoked to log
73
83
  */
74
84
  void end_io_cache()
75
85
  {
76
 
    internal::end_io_cache(&cache);
 
86
    ::end_io_cache(&cache);
77
87
    need_end_io_cache = 0;
78
88
  }
79
89
 
80
90
  /*
81
91
    Either this method, or we need to make cache public
82
92
    Arg must be set from mysql_load() since constructor does not see
83
 
    either the table or Session value
 
93
    either the table or THD value
84
94
  */
85
95
  void set_io_cache_arg(void* arg) { cache.arg = arg; }
86
96
};
87
97
 
88
 
static int read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
 
98
static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
89
99
                             List<Item> &fields_vars, List<Item> &set_fields,
90
100
                             List<Item> &set_values, READ_INFO &read_info,
91
 
                             uint32_t skip_lines,
 
101
                             ulong skip_lines,
92
102
                             bool ignore_check_option_errors);
93
 
static int read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
 
103
static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
94
104
                          List<Item> &fields_vars, List<Item> &set_fields,
95
105
                          List<Item> &set_values, READ_INFO &read_info,
96
 
                          String &enclosed, uint32_t skip_lines,
 
106
                          String &enclosed, ulong skip_lines,
97
107
                          bool ignore_check_option_errors);
98
108
 
 
109
static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
110
                          List<Item> &fields_vars, List<Item> &set_fields,
 
111
                          List<Item> &set_values, READ_INFO &read_info,
 
112
                          String &enclosed, ulong skip_lines,
 
113
                          bool ignore_check_option_errors);
 
114
 
 
115
static bool write_execute_load_query_log_event(THD *thd,
 
116
                                               bool duplicates, bool ignore,
 
117
                                               bool transactional_table,
 
118
                                               THD::killed_state killed_status);
99
119
 
100
120
/*
101
121
  Execute LOAD DATA query
102
122
 
103
123
  SYNOPSYS
104
124
    mysql_load()
105
 
      session - current thread
106
 
      ex  - file_exchange object representing source cursor and its parsing rules
 
125
      thd - current thread
 
126
      ex  - sql_exchange object representing source file and its parsing rules
107
127
      table_list  - list of tables to which we are loading data
108
128
      fields_vars - list of fields and variables to which we read
109
 
                    data from cursor
 
129
                    data from file
110
130
      set_fields  - list of fields mentioned in set clause
111
131
      set_values  - expressions to assign to fields in previous list
112
132
      handle_duplicates - indicates whenever we should emit error or
113
133
                          replace row if we will meet duplicates.
114
134
      ignore -          - indicates whenever we should ignore duplicates
 
135
      read_file_from_client - is this LOAD DATA LOCAL ?
115
136
 
116
137
  RETURN VALUES
117
 
    true - error / false - success
 
138
    TRUE - error / FALSE - success
118
139
*/
119
140
 
120
 
int mysql_load(Session *session,file_exchange *ex,TableList *table_list,
 
141
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
121
142
                List<Item> &fields_vars, List<Item> &set_fields,
122
143
                List<Item> &set_values,
123
 
                enum enum_duplicates handle_duplicates, bool ignore)
 
144
                enum enum_duplicates handle_duplicates, bool ignore,
 
145
                bool read_file_from_client)
124
146
{
125
147
  char name[FN_REFLEN];
126
 
  int file;
127
 
  Table *table= NULL;
 
148
  File file;
 
149
  TABLE *table= NULL;
128
150
  int error;
129
151
  String *field_term=ex->field_term,*escaped=ex->escaped;
130
152
  String *enclosed=ex->enclosed;
131
153
  bool is_fifo=0;
132
 
  char *db= table_list->db;                     // This is never null
133
 
  assert(db);
 
154
  LOAD_FILE_INFO lf_info;
 
155
  char *db = table_list->db;                    // This is never null
134
156
  /*
135
 
    If path for cursor is not defined, we will use the current database.
 
157
    If path for file is not defined, we will use the current database.
136
158
    If this is not set, we will use the directory where the table to be
137
159
    loaded is located
138
160
  */
139
 
  const char *tdb= session->db.empty() ? db  : session->db.c_str();             // Result is never null
140
 
  assert(tdb);
141
 
  uint32_t skip_lines= ex->skip_lines;
 
161
  char *tdb= thd->db ? thd->db : db;            // Result is never null
 
162
  ulong skip_lines= ex->skip_lines;
142
163
  bool transactional_table;
143
 
  Session::killed_state killed_status= Session::NOT_KILLED;
 
164
  THD::killed_state killed_status= THD::NOT_KILLED;
 
165
  DBUG_ENTER("mysql_load");
144
166
 
145
 
  /* Escape and enclosed character may be a utf8 4-byte character */
146
 
  if (escaped->length() > 4 || enclosed->length() > 4)
 
167
  if (escaped->length() > 1 || enclosed->length() > 1)
147
168
  {
148
 
    my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
149
 
    return(true);
 
169
    my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
 
170
               MYF(0));
 
171
    DBUG_RETURN(TRUE);
150
172
  }
151
 
 
152
 
  if (session->openTablesLock(table_list))
153
 
    return(true);
154
 
 
155
 
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
156
 
                                    &session->lex->select_lex.top_join_list,
 
173
  if (open_and_lock_tables(thd, table_list))
 
174
    DBUG_RETURN(TRUE);
 
175
  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
 
176
                                    &thd->lex->select_lex.top_join_list,
157
177
                                    table_list,
158
 
                                    &session->lex->select_lex.leaf_tables, true))
159
 
     return(-1);
 
178
                                    &thd->lex->select_lex.leaf_tables, true))
 
179
     DBUG_RETURN(-1);
160
180
 
161
181
  /*
162
182
    Let us emit an error if we are loading data to table which is used
166
186
    table is marked to be 'used for insert' in which case we should never
167
187
    mark this table as 'const table' (ie, one that has only one row).
168
188
  */
169
 
  if (unique_table(table_list, table_list->next_global))
 
189
  if (unique_table(thd, table_list, table_list->next_global, 0))
170
190
  {
171
191
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
172
 
    return(true);
 
192
    DBUG_RETURN(TRUE);
173
193
  }
174
194
 
175
195
  table= table_list->table;
176
 
  transactional_table= table->cursor->has_transactions();
 
196
  transactional_table= table->file->has_transactions();
177
197
 
178
198
  if (!fields_vars.elements)
179
199
  {
180
200
    Field **field;
181
201
    for (field=table->field; *field ; field++)
182
202
      fields_vars.push_back(new Item_field(*field));
183
 
    table->setWriteSet();
 
203
    bitmap_set_all(table->write_set);
184
204
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
185
205
    /*
186
206
      Let us also prepare SET clause, altough it is probably empty
187
207
      in this case.
188
208
    */
189
 
    if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
190
 
        setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
191
 
      return(true);
 
209
    if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
 
210
        setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
 
211
      DBUG_RETURN(TRUE);
192
212
  }
193
213
  else
194
214
  {                                             // Part field list
195
215
    /* TODO: use this conds for 'WITH CHECK OPTIONS' */
196
 
    if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
197
 
        setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
198
 
        check_that_all_fields_are_given_values(session, table, table_list))
199
 
      return(true);
 
216
    if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
 
217
        setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
 
218
        check_that_all_fields_are_given_values(thd, table, table_list))
 
219
      DBUG_RETURN(TRUE);
200
220
    /*
201
221
      Check whenever TIMESTAMP field with auto-set feature specified
202
222
      explicitly.
203
223
    */
204
224
    if (table->timestamp_field)
205
225
    {
206
 
      if (table->isWriteSet(table->timestamp_field->field_index))
 
226
      if (bitmap_is_set(table->write_set,
 
227
                        table->timestamp_field->field_index))
207
228
        table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
208
229
      else
209
230
      {
210
 
        table->setWriteSet(table->timestamp_field->field_index);
 
231
        bitmap_set_bit(table->write_set,
 
232
                       table->timestamp_field->field_index);
211
233
      }
212
234
    }
213
235
    /* Fix the expressions in SET clause */
214
 
    if (setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
215
 
      return(true);
 
236
    if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
 
237
      DBUG_RETURN(TRUE);
216
238
  }
217
239
 
218
240
  table->mark_columns_needed_for_insert();
219
241
 
220
 
  size_t tot_length=0;
 
242
  uint tot_length=0;
221
243
  bool use_blobs= 0, use_vars= 0;
222
244
  List_iterator_fast<Item> it(fields_vars);
223
245
  Item *item;
244
266
  {
245
267
    my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
246
268
               MYF(0));
247
 
    return(true);
 
269
    DBUG_RETURN(TRUE);
248
270
  }
249
271
  if (use_vars && !field_term->length() && !enclosed->length())
250
272
  {
251
273
    my_error(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR, MYF(0));
252
 
    return(true);
253
 
  }
254
 
 
 
274
    DBUG_RETURN(TRUE);
 
275
  }
 
276
 
 
277
  /* We can't give an error in the middle when using LOCAL files */
 
278
  if (read_file_from_client && handle_duplicates == DUP_ERROR)
 
279
    ignore= 1;
 
280
 
 
281
  if (read_file_from_client)
 
282
  {
 
283
    (void)net_request_file(&thd->net,ex->file_name);
 
284
    file = -1;
 
285
  }
 
286
  else
255
287
  {
256
288
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
257
289
    ex->file_name+=dirname_length(ex->file_name);
258
290
#endif
259
 
    if (!internal::dirname_length(ex->file_name))
 
291
    if (!dirname_length(ex->file_name))
260
292
    {
261
 
      strcpy(name, drizzle_real_data_home);
262
 
      strncat(name, tdb, FN_REFLEN-strlen(drizzle_real_data_home)-1);
263
 
      (void) internal::fn_format(name, ex->file_name, name, "",
 
293
      strxnmov(name, FN_REFLEN-1, mysql_real_data_home, tdb, NullS);
 
294
      (void) fn_format(name, ex->file_name, name, "",
264
295
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
265
296
    }
266
297
    else
267
298
    {
268
 
      (void) internal::fn_format(name, ex->file_name, drizzle_real_data_home, "",
 
299
      (void) fn_format(name, ex->file_name, mysql_real_data_home, "",
269
300
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
270
301
 
271
302
      if (opt_secure_file_priv &&
273
304
      {
274
305
        /* Read only allowed from within dir specified by secure_file_priv */
275
306
        my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
276
 
        return(true);
277
 
      }
278
 
 
279
 
      struct stat stat_info;
280
 
      if (stat(name,&stat_info))
281
 
      {
282
 
        my_error(ER_FILE_NOT_FOUND, MYF(0), name, errno);
283
 
        return(true);
284
 
      }
285
 
 
286
 
      // if we are not in slave thread, the cursor must be:
287
 
      if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
288
 
            (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
289
 
            ((stat_info.st_mode & S_IFREG) == S_IFREG ||
290
 
             (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
 
307
        DBUG_RETURN(TRUE);
 
308
      }
 
309
 
 
310
      MY_STAT stat_info;
 
311
      if (!my_stat(name,&stat_info,MYF(MY_WME)))
 
312
        DBUG_RETURN(TRUE);
 
313
 
 
314
      // if we are not in slave thread, the file must be:
 
315
      if (!thd->slave_thread &&
 
316
          !((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
 
317
            (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
 
318
            ((stat_info.st_mode & S_IFREG) == S_IFREG ||
 
319
             (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
291
320
      {
292
321
        my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
293
 
        return(true);
 
322
        DBUG_RETURN(TRUE);
294
323
      }
295
324
      if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
296
325
        is_fifo = 1;
297
326
    }
298
 
    if ((file=internal::my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
299
 
    {
300
 
      my_error(ER_CANT_OPEN_FILE, MYF(0), name, errno);
301
 
      return(true);
302
 
    }
 
327
    if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
 
328
      DBUG_RETURN(TRUE);
303
329
  }
304
330
 
305
331
  COPY_INFO info;
306
 
  memset(&info, 0, sizeof(info));
 
332
  bzero((char*) &info,sizeof(info));
307
333
  info.ignore= ignore;
308
334
  info.handle_duplicates=handle_duplicates;
309
335
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
310
336
 
311
 
  READ_INFO read_info(file, tot_length,
312
 
                      ex->cs ? ex->cs : get_default_db_collation(session->db.c_str()),
 
337
  READ_INFO read_info(file,tot_length,
 
338
                      ex->cs ? ex->cs : thd->variables.collation_database,
313
339
                      *field_term,*ex->line_start, *ex->line_term, *enclosed,
314
 
                      info.escape_char, is_fifo);
 
340
                      info.escape_char, read_file_from_client, is_fifo);
315
341
  if (read_info.error)
316
342
  {
317
343
    if  (file >= 0)
318
 
      internal::my_close(file,MYF(0));                  // no files in net reading
319
 
    return(true);                               // Can't allocate buffers
320
 
  }
321
 
 
322
 
  /*
323
 
   * Per the SQL standard, inserting NULL into a NOT NULL
324
 
   * field requires an error to be thrown.
325
 
   *
326
 
   * @NOTE
327
 
   *
328
 
   * NULL check and handling occurs in field_conv.cc
329
 
   */
330
 
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
331
 
  session->cuted_fields=0L;
 
344
      my_close(file,MYF(0));                    // no files in net reading
 
345
    DBUG_RETURN(TRUE);                          // Can't allocate buffers
 
346
  }
 
347
 
 
348
  if (mysql_bin_log.is_open())
 
349
  {
 
350
    lf_info.thd = thd;
 
351
    lf_info.wrote_create_file = 0;
 
352
    lf_info.last_pos_in_file = HA_POS_ERROR;
 
353
    lf_info.log_delayed= transactional_table;
 
354
    read_info.set_io_cache_arg((void*) &lf_info);
 
355
  }
 
356
 
 
357
  thd->count_cuted_fields= CHECK_FIELD_WARN;            /* calc cuted fields */
 
358
  thd->cuted_fields=0L;
332
359
  /* Skip lines if there is a line terminator */
333
 
  if (ex->line_term->length())
 
360
  if (ex->line_term->length() && ex->filetype != FILETYPE_XML)
334
361
  {
335
362
    /* ex->skip_lines needs to be preserved for logging */
336
363
    while (skip_lines > 0)
347
374
    table->next_number_field=table->found_next_number_field;
348
375
    if (ignore ||
349
376
        handle_duplicates == DUP_REPLACE)
350
 
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
377
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
351
378
    if (handle_duplicates == DUP_REPLACE)
352
 
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
353
 
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
379
        table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
380
    table->file->ha_start_bulk_insert((ha_rows) 0);
354
381
    table->copy_blobs=1;
355
382
 
356
 
    session->abort_on_warning= true;
 
383
    thd->abort_on_warning= (!ignore &&
 
384
                            (thd->variables.sql_mode &
 
385
                             (MODE_STRICT_TRANS_TABLES |
 
386
                              MODE_STRICT_ALL_TABLES)));
357
387
 
358
 
    if (!field_term->length() && !enclosed->length())
359
 
      error= read_fixed_length(session, info, table_list, fields_vars,
 
388
    if (ex->filetype == FILETYPE_XML) /* load xml */
 
389
      error= read_xml_field(thd, info, table_list, fields_vars,
 
390
                            set_fields, set_values, read_info,
 
391
                            *(ex->line_term), skip_lines, ignore);
 
392
    else if (!field_term->length() && !enclosed->length())
 
393
      error= read_fixed_length(thd, info, table_list, fields_vars,
360
394
                               set_fields, set_values, read_info,
361
395
                               skip_lines, ignore);
362
396
    else
363
 
      error= read_sep_field(session, info, table_list, fields_vars,
 
397
      error= read_sep_field(thd, info, table_list, fields_vars,
364
398
                            set_fields, set_values, read_info,
365
399
                            *enclosed, skip_lines, ignore);
366
 
    if (table->cursor->ha_end_bulk_insert() && !error)
 
400
    if (table->file->ha_end_bulk_insert() && !error)
367
401
    {
368
 
      table->print_error(errno, MYF(0));
 
402
      table->file->print_error(my_errno, MYF(0));
369
403
      error= 1;
370
404
    }
371
 
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
372
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
405
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
406
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
373
407
    table->next_number_field=0;
374
408
  }
375
409
  if (file >= 0)
376
 
    internal::my_close(file,MYF(0));
 
410
    my_close(file,MYF(0));
377
411
  free_blobs(table);                            /* if pack_blob was used */
378
412
  table->copy_blobs=0;
379
 
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
380
 
  /*
 
413
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
414
  /* 
381
415
     simulated killing in the middle of per-row loop
382
416
     must be effective for binlogging
383
417
  */
384
 
  killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
 
418
  DBUG_EXECUTE_IF("simulate_kill_bug27571",
 
419
                  {
 
420
                    error=1;
 
421
                    thd->killed= THD::KILL_QUERY;
 
422
                  };);
 
423
  killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
385
424
  if (error)
386
425
  {
 
426
    if (read_file_from_client)
 
427
      while (!read_info.next_line())
 
428
        ;
 
429
 
 
430
    if (mysql_bin_log.is_open())
 
431
    {
 
432
      {
 
433
        /*
 
434
          Make sure last block (the one which caused the error) gets
 
435
          logged.  This is needed because otherwise after write of (to
 
436
          the binlog, not to read_info (which is a cache))
 
437
          Delete_file_log_event the bad block will remain in read_info
 
438
          (because pre_read is not called at the end of the last
 
439
          block; remember pre_read is called whenever a new block is
 
440
          read from disk).  At the end of mysql_load(), the destructor
 
441
          of read_info will call end_io_cache() which will flush
 
442
          read_info, so we will finally have this in the binlog:
 
443
 
 
444
          Append_block # The last successfull block
 
445
          Delete_file
 
446
          Append_block # The failing block
 
447
          which is nonsense.
 
448
          Or could also be (for a small file)
 
449
          Create_file  # The failing block
 
450
          which is nonsense (Delete_file is not written in this case, because:
 
451
          Create_file has not been written, so Delete_file is not written, then
 
452
          when read_info is destroyed end_io_cache() is called which writes
 
453
          Create_file.
 
454
        */
 
455
        read_info.end_io_cache();
 
456
        /* If the file was not empty, wrote_create_file is true */
 
457
        if (lf_info.wrote_create_file)
 
458
        {
 
459
          if (thd->transaction.stmt.modified_non_trans_table)
 
460
            write_execute_load_query_log_event(thd, handle_duplicates,
 
461
                                               ignore, transactional_table,
 
462
                                               killed_status);
 
463
          else
 
464
          {
 
465
            Delete_file_log_event d(thd, db, transactional_table);
 
466
            d.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
 
467
            mysql_bin_log.write(&d);
 
468
          }
 
469
        }
 
470
      }
 
471
    }
387
472
    error= -1;                          // Error on read
388
473
    goto err;
389
474
  }
390
 
  sprintf(name, ER(ER_LOAD_INFO), (uint32_t) info.records, (uint32_t) info.deleted,
391
 
          (uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
392
 
 
393
 
  if (session->transaction.stmt.hasModifiedNonTransData())
394
 
    session->transaction.all.markModifiedNonTransData();
 
475
  sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
 
476
          (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
 
477
 
 
478
  if (thd->transaction.stmt.modified_non_trans_table)
 
479
    thd->transaction.all.modified_non_trans_table= TRUE;
 
480
 
 
481
  if (mysql_bin_log.is_open())
 
482
  {
 
483
    /*
 
484
      We need to do the job that is normally done inside
 
485
      binlog_query() here, which is to ensure that the pending event
 
486
      is written before tables are unlocked and before any other
 
487
      events are written.  We also need to update the table map
 
488
      version for the binary log to mark that table maps are invalid
 
489
      after this point.
 
490
     */
 
491
    if (thd->current_stmt_binlog_row_based)
 
492
      thd->binlog_flush_pending_rows_event(true);
 
493
    else
 
494
    {
 
495
      /*
 
496
        As already explained above, we need to call end_io_cache() or the last
 
497
        block will be logged only after Execute_load_query_log_event (which is
 
498
        wrong), when read_info is destroyed.
 
499
      */
 
500
      read_info.end_io_cache();
 
501
      if (lf_info.wrote_create_file)
 
502
      {
 
503
        write_execute_load_query_log_event(thd, handle_duplicates, ignore,
 
504
                                           transactional_table,killed_status);
 
505
      }
 
506
    }
 
507
  }
395
508
 
396
509
  /* ok to client sent only after binlog write and engine commit */
397
 
  session->my_ok(info.copied + info.deleted, 0, 0L, name);
 
510
  my_ok(thd, info.copied + info.deleted, 0L, name);
398
511
err:
399
 
  assert(transactional_table || !(info.copied || info.deleted) ||
400
 
              session->transaction.stmt.hasModifiedNonTransData());
401
 
  table->cursor->ha_release_auto_increment();
402
 
  table->auto_increment_field_not_null= false;
403
 
  session->abort_on_warning= 0;
404
 
  return(error);
 
512
  DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) ||
 
513
              thd->transaction.stmt.modified_non_trans_table);
 
514
  table->file->ha_release_auto_increment();
 
515
  table->auto_increment_field_not_null= FALSE;
 
516
  thd->abort_on_warning= 0;
 
517
  DBUG_RETURN(error);
 
518
}
 
519
 
 
520
 
 
521
/* Not a very useful function; just to avoid duplication of code */
 
522
static bool write_execute_load_query_log_event(THD *thd,
 
523
                                               bool duplicates, bool ignore,
 
524
                                               bool transactional_table,
 
525
                                               THD::killed_state killed_err_arg)
 
526
{
 
527
  Execute_load_query_log_event
 
528
    e(thd, thd->query, thd->query_length,
 
529
      (char*)thd->lex->fname_start - (char*)thd->query,
 
530
      (char*)thd->lex->fname_end - (char*)thd->query,
 
531
      (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
 
532
      (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
 
533
      transactional_table, FALSE, killed_err_arg);
 
534
  e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
 
535
  return mysql_bin_log.write(&e);
405
536
}
406
537
 
407
538
 
410
541
****************************************************************************/
411
542
 
412
543
static int
413
 
read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
 
544
read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
414
545
                  List<Item> &fields_vars, List<Item> &set_fields,
415
546
                  List<Item> &set_values, READ_INFO &read_info,
416
 
                  uint32_t skip_lines, bool ignore_check_option_errors)
 
547
                  ulong skip_lines, bool ignore_check_option_errors)
417
548
{
418
549
  List_iterator_fast<Item> it(fields_vars);
419
550
  Item_field *sql_field;
420
 
  Table *table= table_list->table;
421
 
  uint64_t id;
 
551
  TABLE *table= table_list->table;
 
552
  ulonglong id;
422
553
  bool err;
 
554
  DBUG_ENTER("read_fixed_length");
423
555
 
424
556
  id= 0;
425
 
 
 
557
 
426
558
  while (!read_info.read_fixed_length())
427
559
  {
428
 
    if (session->killed)
 
560
    if (thd->killed)
429
561
    {
430
 
      session->send_kill_message();
431
 
      return(1);
 
562
      thd->send_kill_message();
 
563
      DBUG_RETURN(1);
432
564
    }
433
565
    if (skip_lines)
434
566
    {
442
574
      continue;
443
575
    }
444
576
    it.rewind();
445
 
    unsigned char *pos=read_info.row_start;
 
577
    uchar *pos=read_info.row_start;
446
578
#ifdef HAVE_purify
447
579
    read_info.row_end[0]=0;
448
580
#endif
449
581
 
450
 
    table->restoreRecordAsDefault();
 
582
    restore_record(table, s->default_values);
451
583
    /*
452
584
      There is no variables in fields_vars list in this format so
453
585
      this conversion is safe.
454
586
    */
455
587
    while ((sql_field= (Item_field*) it++))
456
588
    {
457
 
      Field *field= sql_field->field;
 
589
      Field *field= sql_field->field;                  
458
590
      if (field == table->next_number_field)
459
 
        table->auto_increment_field_not_null= true;
 
591
        table->auto_increment_field_not_null= TRUE;
460
592
      /*
461
593
        No fields specified in fields_vars list can be null in this format.
462
594
        Mark field as not null, we should do this for each row because of
466
598
 
467
599
      if (pos == read_info.row_end)
468
600
      {
469
 
        session->cuted_fields++;                        /* Not enough fields */
470
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
471
 
                            ER_WARN_TOO_FEW_RECORDS,
472
 
                            ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
473
 
        if (!field->maybe_null() && field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
601
        thd->cuted_fields++;                    /* Not enough fields */
 
602
        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
603
                            ER_WARN_TOO_FEW_RECORDS, 
 
604
                            ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
 
605
        if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
474
606
            ((Field_timestamp*) field)->set_time();
475
607
      }
476
608
      else
477
609
      {
478
 
        uint32_t length;
479
 
        unsigned char save_chr;
480
 
        if ((length=(uint32_t) (read_info.row_end-pos)) >
 
610
        uint length;
 
611
        uchar save_chr;
 
612
        if ((length=(uint) (read_info.row_end-pos)) >
481
613
            field->field_length)
482
 
        {
483
614
          length=field->field_length;
484
 
        }
485
 
        save_chr=pos[length];
486
 
        pos[length]='\0'; // Add temp null terminator for store()
 
615
        save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc
487
616
        field->store((char*) pos,length,read_info.read_charset);
488
617
        pos[length]=save_chr;
489
618
        if ((pos+=length) > read_info.row_end)
492
621
    }
493
622
    if (pos != read_info.row_end)
494
623
    {
495
 
      session->cuted_fields++;                  /* To long row */
496
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
497
 
                          ER_WARN_TOO_MANY_RECORDS,
498
 
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
 
624
      thd->cuted_fields++;                      /* To long row */
 
625
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
626
                          ER_WARN_TOO_MANY_RECORDS, 
 
627
                          ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); 
499
628
    }
500
629
 
501
 
    if (session->killed ||
502
 
        fill_record(session, set_fields, set_values,
 
630
    if (thd->killed ||
 
631
        fill_record(thd, set_fields, set_values,
503
632
                    ignore_check_option_errors))
504
 
      return(1);
 
633
      DBUG_RETURN(1);
505
634
 
506
 
    err= write_record(session, table, &info);
507
 
    table->auto_increment_field_not_null= false;
 
635
    err= write_record(thd, table, &info);
 
636
    table->auto_increment_field_not_null= FALSE;
508
637
    if (err)
509
 
      return(1);
510
 
 
 
638
      DBUG_RETURN(1);
 
639
   
511
640
    /*
512
641
      We don't need to reset auto-increment field since we are restoring
513
642
      its default value at the beginning of each loop iteration.
516
645
      break;
517
646
    if (read_info.line_cuted)
518
647
    {
519
 
      session->cuted_fields++;                  /* To long row */
520
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
521
 
                          ER_WARN_TOO_MANY_RECORDS,
522
 
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
 
648
      thd->cuted_fields++;                      /* To long row */
 
649
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
650
                          ER_WARN_TOO_MANY_RECORDS, 
 
651
                          ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); 
523
652
    }
524
 
    session->row_count++;
 
653
    thd->row_count++;
525
654
  }
526
 
  return(test(read_info.error));
 
655
  DBUG_RETURN(test(read_info.error));
527
656
}
528
657
 
529
658
 
530
659
 
531
660
static int
532
 
read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
 
661
read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
533
662
               List<Item> &fields_vars, List<Item> &set_fields,
534
663
               List<Item> &set_values, READ_INFO &read_info,
535
 
               String &enclosed, uint32_t skip_lines,
 
664
               String &enclosed, ulong skip_lines,
536
665
               bool ignore_check_option_errors)
537
666
{
538
667
  List_iterator_fast<Item> it(fields_vars);
539
668
  Item *item;
540
 
  Table *table= table_list->table;
541
 
  uint32_t enclosed_length;
542
 
  uint64_t id;
 
669
  TABLE *table= table_list->table;
 
670
  uint enclosed_length;
 
671
  ulonglong id;
543
672
  bool err;
 
673
  DBUG_ENTER("read_sep_field");
544
674
 
545
675
  enclosed_length=enclosed.length();
546
676
  id= 0;
547
677
 
548
678
  for (;;it.rewind())
549
679
  {
550
 
    if (session->killed)
 
680
    if (thd->killed)
551
681
    {
552
 
      session->send_kill_message();
553
 
      return(1);
 
682
      thd->send_kill_message();
 
683
      DBUG_RETURN(1);
554
684
    }
555
685
 
556
 
    table->restoreRecordAsDefault();
 
686
    restore_record(table, s->default_values);
557
687
 
558
688
    while ((item= it++))
559
689
    {
560
 
      uint32_t length;
561
 
      unsigned char *pos;
 
690
      uint length;
 
691
      uchar *pos;
562
692
      Item *real_item;
563
693
 
564
694
      if (read_info.read_field())
569
699
        continue;
570
700
 
571
701
      pos=read_info.row_start;
572
 
      length=(uint32_t) (read_info.row_end-pos);
 
702
      length=(uint) (read_info.row_end-pos);
573
703
 
574
704
      real_item= item->real_item();
575
705
 
583
713
          if (field->reset())
584
714
          {
585
715
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
586
 
                     session->row_count);
587
 
            return(1);
 
716
                     thd->row_count);
 
717
            DBUG_RETURN(1);
588
718
          }
589
719
          field->set_null();
590
720
          if (!field->maybe_null())
591
721
          {
592
 
            if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
722
            if (field->type() == MYSQL_TYPE_TIMESTAMP)
593
723
              ((Field_timestamp*) field)->set_time();
594
724
            else if (field != table->next_number_field)
595
 
              field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
725
              field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
596
726
                                 ER_WARN_NULL_TO_NOTNULL, 1);
597
727
          }
598
728
        }
604
734
        else
605
735
        {
606
736
          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
607
 
          return(1);
 
737
          DBUG_RETURN(1);
608
738
        }
609
739
 
610
740
        continue;
616
746
        field->set_notnull();
617
747
        read_info.row_end[0]=0;                 // Safe to change end marker
618
748
        if (field == table->next_number_field)
619
 
          table->auto_increment_field_not_null= true;
 
749
          table->auto_increment_field_not_null= TRUE;
620
750
        field->store((char*) pos, length, read_info.read_charset);
621
751
      }
622
752
      else if (item->type() == Item::STRING_ITEM)
627
757
      else
628
758
      {
629
759
        my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
630
 
        return(1);
 
760
        DBUG_RETURN(1);
631
761
      }
632
762
    }
633
763
    if (read_info.error)
639
769
    }
640
770
    if (item)
641
771
    {
642
 
      /* Have not read any field, thus input cursor is simply ended */
 
772
      /* Have not read any field, thus input file is simply ended */
643
773
      if (item == fields_vars.head())
644
774
        break;
645
775
      for (; item ; item= it++)
651
781
          if (field->reset())
652
782
          {
653
783
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
654
 
                     session->row_count);
655
 
            return(1);
 
784
                     thd->row_count);
 
785
            DBUG_RETURN(1);
656
786
          }
657
 
          if (!field->maybe_null() && field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
787
          if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
658
788
              ((Field_timestamp*) field)->set_time();
659
789
          /*
660
790
            QQ: We probably should not throw warning for each field.
661
791
            But how about intention to always have the same number
662
 
            of warnings in Session::cuted_fields (and get rid of cuted_fields
 
792
            of warnings in THD::cuted_fields (and get rid of cuted_fields
663
793
            in the end ?)
664
794
          */
665
 
          session->cuted_fields++;
666
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
795
          thd->cuted_fields++;
 
796
          push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
667
797
                              ER_WARN_TOO_FEW_RECORDS,
668
 
                              ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
 
798
                              ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
669
799
        }
670
800
        else if (item->type() == Item::STRING_ITEM)
671
801
        {
675
805
        else
676
806
        {
677
807
          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
678
 
          return(1);
 
808
          DBUG_RETURN(1);
679
809
        }
680
810
      }
681
811
    }
682
812
 
683
 
    if (session->killed ||
684
 
        fill_record(session, set_fields, set_values,
 
813
    if (thd->killed ||
 
814
        fill_record(thd, set_fields, set_values,
685
815
                    ignore_check_option_errors))
686
 
      return(1);
 
816
      DBUG_RETURN(1);
687
817
 
688
 
    err= write_record(session, table, &info);
689
 
    table->auto_increment_field_not_null= false;
 
818
    err= write_record(thd, table, &info);
 
819
    table->auto_increment_field_not_null= FALSE;
690
820
    if (err)
691
 
      return(1);
 
821
      DBUG_RETURN(1);
692
822
    /*
693
823
      We don't need to reset auto-increment field since we are restoring
694
824
      its default value at the beginning of each loop iteration.
697
827
      break;
698
828
    if (read_info.line_cuted)
699
829
    {
700
 
      session->cuted_fields++;                  /* To long row */
701
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
702
 
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
703
 
                          session->row_count);
704
 
      if (session->killed)
705
 
        return(1);
 
830
      thd->cuted_fields++;                      /* To long row */
 
831
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
832
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS), 
 
833
                          thd->row_count);   
 
834
      if (thd->killed)
 
835
        DBUG_RETURN(1);
706
836
    }
707
 
    session->row_count++;
 
837
    thd->row_count++;
708
838
  }
709
 
  return(test(read_info.error));
 
839
  DBUG_RETURN(test(read_info.error));
710
840
}
711
841
 
712
842
 
 
843
/****************************************************************************
 
844
** Read rows in xml format
 
845
****************************************************************************/
 
846
static int
 
847
read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
848
               List<Item> &fields_vars, List<Item> &set_fields,
 
849
               List<Item> &set_values, READ_INFO &read_info,
 
850
               String &row_tag, ulong skip_lines,
 
851
               bool ignore_check_option_errors)
 
852
{
 
853
  List_iterator_fast<Item> it(fields_vars);
 
854
  Item *item;
 
855
  TABLE *table= table_list->table;
 
856
  bool no_trans_update_stmt;
 
857
  CHARSET_INFO *cs= read_info.read_charset;
 
858
  DBUG_ENTER("read_xml_field");
 
859
  
 
860
  no_trans_update_stmt= !table->file->has_transactions();
 
861
  
 
862
  for ( ; ; it.rewind())
 
863
  {
 
864
    if (thd->killed)
 
865
    {
 
866
      thd->send_kill_message();
 
867
      DBUG_RETURN(1);
 
868
    }
 
869
    
 
870
    // read row tag and save values into tag list
 
871
    if (read_info.read_xml())
 
872
      break;
 
873
    
 
874
    List_iterator_fast<XML_TAG> xmlit(read_info.taglist);
 
875
    xmlit.rewind();
 
876
    XML_TAG *tag= NULL;
 
877
    
 
878
#ifndef DBUG_OFF
 
879
    DBUG_PRINT("read_xml_field", ("skip_lines=%d", (int) skip_lines));
 
880
    while ((tag= xmlit++))
 
881
    {
 
882
      DBUG_PRINT("read_xml_field", ("got tag:%i '%s' '%s'",
 
883
                                    tag->level, tag->field.c_ptr(),
 
884
                                    tag->value.c_ptr()));
 
885
    }
 
886
#endif
 
887
    
 
888
    restore_record(table, s->default_values);
 
889
    
 
890
    while ((item= it++))
 
891
    {
 
892
      /* If this line is to be skipped we don't want to fill field or var */
 
893
      if (skip_lines)
 
894
        continue;
 
895
      
 
896
      /* find field in tag list */
 
897
      xmlit.rewind();
 
898
      tag= xmlit++;
 
899
      
 
900
      while(tag && strcmp(tag->field.c_ptr(), item->name) != 0)
 
901
        tag= xmlit++;
 
902
      
 
903
      if (!tag) // found null
 
904
      {
 
905
        if (item->type() == Item::FIELD_ITEM)
 
906
        {
 
907
          Field *field= ((Item_field *) item)->field;
 
908
          field->reset();
 
909
          field->set_null();
 
910
          if (field == table->next_number_field)
 
911
            table->auto_increment_field_not_null= TRUE;
 
912
          if (!field->maybe_null())
 
913
          {
 
914
            if (field->type() == FIELD_TYPE_TIMESTAMP)
 
915
              ((Field_timestamp *) field)->set_time();
 
916
            else if (field != table->next_number_field)
 
917
              field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
 
918
                                 ER_WARN_NULL_TO_NOTNULL, 1);
 
919
          }
 
920
        }
 
921
        else
 
922
          ((Item_user_var_as_out_param *) item)->set_null_value(cs);
 
923
        continue;
 
924
      }
 
925
 
 
926
      if (item->type() == Item::FIELD_ITEM)
 
927
      {
 
928
 
 
929
        Field *field= ((Item_field *)item)->field;
 
930
        field->set_notnull();
 
931
        if (field == table->next_number_field)
 
932
          table->auto_increment_field_not_null= TRUE;
 
933
        field->store((char *) tag->value.ptr(), tag->value.length(), cs);
 
934
      }
 
935
      else
 
936
        ((Item_user_var_as_out_param *) item)->set_value(
 
937
                                                 (char *) tag->value.ptr(), 
 
938
                                                 tag->value.length(), cs);
 
939
    }
 
940
    
 
941
    if (read_info.error)
 
942
      break;
 
943
    
 
944
    if (skip_lines)
 
945
    {
 
946
      skip_lines--;
 
947
      continue;
 
948
    }
 
949
    
 
950
    if (item)
 
951
    {
 
952
      /* Have not read any field, thus input file is simply ended */
 
953
      if (item == fields_vars.head())
 
954
        break;
 
955
      
 
956
      for ( ; item; item= it++)
 
957
      {
 
958
        if (item->type() == Item::FIELD_ITEM)
 
959
        {
 
960
          /*
 
961
            QQ: We probably should not throw warning for each field.
 
962
            But how about intention to always have the same number
 
963
            of warnings in THD::cuted_fields (and get rid of cuted_fields
 
964
            in the end ?)
 
965
          */
 
966
          thd->cuted_fields++;
 
967
          push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
968
                              ER_WARN_TOO_FEW_RECORDS,
 
969
                              ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
 
970
        }
 
971
        else
 
972
          ((Item_user_var_as_out_param *)item)->set_null_value(cs);
 
973
      }
 
974
    }
 
975
 
 
976
    if (thd->killed || fill_record(thd, set_fields, set_values,
 
977
                    ignore_check_option_errors))
 
978
      DBUG_RETURN(1);
 
979
 
 
980
    if (write_record(thd, table, &info))
 
981
      DBUG_RETURN(1);
 
982
    
 
983
    /*
 
984
      We don't need to reset auto-increment field since we are restoring
 
985
      its default value at the beginning of each loop iteration.
 
986
    */
 
987
    thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
 
988
    thd->row_count++;
 
989
  }
 
990
  DBUG_RETURN(test(read_info.error));
 
991
} /* load xml end */
 
992
 
 
993
 
713
994
/* Unescape all escape characters, mark \N as null */
714
995
 
715
996
char
722
1003
  case 'r': return '\r';
723
1004
  case 'b': return '\b';
724
1005
  case '0': return 0;                           // Ascii null
725
 
  case 'Z': return '\032';                      // Win32 end of cursor
 
1006
  case 'Z': return '\032';                      // Win32 end of file
726
1007
  case 'N': found_null=1;
727
1008
 
728
1009
    /* fall through */
737
1018
*/
738
1019
 
739
1020
 
740
 
READ_INFO::READ_INFO(int file_par, size_t tot_length,
741
 
                     const CHARSET_INFO * const cs,
 
1021
READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs,
742
1022
                     String &field_term, String &line_start, String &line_term,
743
 
                     String &enclosed_par, int escape, bool is_fifo)
744
 
  :cursor(file_par),escape_char(escape)
 
1023
                     String &enclosed_par, int escape, bool get_it_from_net,
 
1024
                     bool is_fifo)
 
1025
  :file(file_par),escape_char(escape)
745
1026
{
746
1027
  read_charset= cs;
747
1028
  field_term_ptr=(char*) field_term.ptr();
748
1029
  field_term_length= field_term.length();
749
1030
  line_term_ptr=(char*) line_term.ptr();
750
1031
  line_term_length= line_term.length();
 
1032
  level= 0; /* for load xml */
751
1033
  if (line_start.length() == 0)
752
1034
  {
753
1035
    line_start_ptr=0;
767
1049
    line_term_ptr=(char*) "";
768
1050
  }
769
1051
  enclosed_char= (enclosed_length=enclosed_par.length()) ?
770
 
    (unsigned char) enclosed_par[0] : INT_MAX;
771
 
  field_term_char= field_term_length ? (unsigned char) field_term_ptr[0] : INT_MAX;
772
 
  line_term_char= line_term_length ? (unsigned char) line_term_ptr[0] : INT_MAX;
 
1052
    (uchar) enclosed_par[0] : INT_MAX;
 
1053
  field_term_char= field_term_length ? (uchar) field_term_ptr[0] : INT_MAX;
 
1054
  line_term_char= line_term_length ? (uchar) line_term_ptr[0] : INT_MAX;
773
1055
  error=eof=found_end_of_line=found_null=line_cuted=0;
774
1056
  buff_length=tot_length;
775
1057
 
776
1058
 
777
1059
  /* Set of a stack for unget if long terminators */
778
 
  uint32_t length= max(field_term_length,line_term_length)+1;
 
1060
  uint length=max(field_term_length,line_term_length)+1;
779
1061
  set_if_bigger(length,line_start.length());
780
 
  stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
 
1062
  stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);
781
1063
 
782
 
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
783
 
    error=1;
 
1064
  if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0))))
 
1065
    error=1; /* purecov: inspected */
784
1066
  else
785
1067
  {
786
1068
    end_of_buff=buffer+buff_length;
787
 
    if (init_io_cache(&cache,(false) ? -1 : cursor, 0,
788
 
                      (false) ? internal::READ_NET :
789
 
                      (is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
 
1069
    if (init_io_cache(&cache,(get_it_from_net) ? -1 : file, 0,
 
1070
                      (get_it_from_net) ? READ_NET :
 
1071
                      (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
790
1072
                      MYF(MY_WME)))
791
1073
    {
792
 
      free((unsigned char*) buffer);
 
1074
      my_free((uchar*) buffer,MYF(0)); /* purecov: inspected */
793
1075
      error=1;
794
1076
    }
795
1077
    else
800
1082
        manual assignment
801
1083
      */
802
1084
      need_end_io_cache = 1;
 
1085
 
 
1086
      if (get_it_from_net)
 
1087
        cache.read_function = _my_b_net_read;
 
1088
 
 
1089
      if (mysql_bin_log.is_open())
 
1090
        cache.pre_read = cache.pre_close =
 
1091
          (IO_CACHE_CALLBACK) log_loaded_block;
803
1092
    }
804
1093
  }
805
1094
}
810
1099
  if (!error)
811
1100
  {
812
1101
    if (need_end_io_cache)
813
 
      internal::end_io_cache(&cache);
814
 
    free(buffer);
 
1102
      ::end_io_cache(&cache);
 
1103
    my_free((uchar*) buffer,MYF(0));
815
1104
    error=1;
816
1105
  }
 
1106
  List_iterator<XML_TAG> xmlit(taglist);
 
1107
  XML_TAG *t;
 
1108
  while ((t= xmlit++))
 
1109
    delete(t);
817
1110
}
818
1111
 
819
1112
 
821
1114
#define PUSH(A) *(stack_pos++)=(A)
822
1115
 
823
1116
 
824
 
inline int READ_INFO::terminator(char *ptr,uint32_t length)
 
1117
inline int READ_INFO::terminator(char *ptr,uint length)
825
1118
{
826
1119
  int chr=0;                                    // Keep gcc happy
827
 
  uint32_t i;
 
1120
  uint i;
828
1121
  for (i=1 ; i < length ; i++)
829
1122
  {
830
1123
    if ((chr=GET) != *++ptr)
836
1129
    return 1;
837
1130
  PUSH(chr);
838
1131
  while (i-- > 1)
839
 
    PUSH((unsigned char) *--ptr);
 
1132
    PUSH((uchar) *--ptr);
840
1133
  return 0;
841
1134
}
842
1135
 
844
1137
int READ_INFO::read_field()
845
1138
{
846
1139
  int chr,found_enclosed_char;
847
 
  unsigned char *to,*new_buffer;
 
1140
  uchar *to,*new_buffer;
848
1141
 
849
1142
  found_null=0;
850
1143
  if (found_end_of_line)
867
1160
  if (chr == enclosed_char)
868
1161
  {
869
1162
    found_enclosed_char=enclosed_char;
870
 
    *to++=(unsigned char) chr;                          // If error
 
1163
    *to++=(uchar) chr;                          // If error
871
1164
  }
872
1165
  else
873
1166
  {
880
1173
    while ( to < end_of_buff)
881
1174
    {
882
1175
      chr = GET;
 
1176
#ifdef USE_MB
883
1177
      if ((my_mbcharlen(read_charset, chr) > 1) &&
884
1178
          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
885
1179
      {
886
 
        unsigned char* p = (unsigned char*)to;
887
 
        *to++ = chr;
888
 
        int ml = my_mbcharlen(read_charset, chr);
889
 
        int i;
890
 
        for (i=1; i<ml; i++) {
891
 
          chr = GET;
892
 
          if (chr == my_b_EOF)
893
 
            goto found_eof;
894
 
          *to++ = chr;
895
 
        }
896
 
        if (my_ismbchar(read_charset,
897
 
              (const char *)p,
898
 
              (const char *)to))
899
 
          continue;
900
 
        for (i=0; i<ml; i++)
901
 
          PUSH((unsigned char) *--to);
902
 
        chr = GET;
 
1180
          uchar* p = (uchar*)to;
 
1181
          *to++ = chr;
 
1182
          int ml = my_mbcharlen(read_charset, chr);
 
1183
          int i;
 
1184
          for (i=1; i<ml; i++) {
 
1185
              chr = GET;
 
1186
              if (chr == my_b_EOF)
 
1187
                  goto found_eof;
 
1188
              *to++ = chr;
 
1189
          }
 
1190
          if (my_ismbchar(read_charset,
 
1191
                          (const char *)p,
 
1192
                          (const char *)to))
 
1193
            continue;
 
1194
          for (i=0; i<ml; i++)
 
1195
            PUSH((uchar) *--to);
 
1196
          chr = GET;
903
1197
      }
 
1198
#endif
904
1199
      if (chr == my_b_EOF)
905
 
        goto found_eof;
 
1200
        goto found_eof;
906
1201
      if (chr == escape_char)
907
1202
      {
908
 
        if ((chr=GET) == my_b_EOF)
909
 
        {
910
 
          *to++= (unsigned char) escape_char;
911
 
          goto found_eof;
912
 
        }
 
1203
        if ((chr=GET) == my_b_EOF)
 
1204
        {
 
1205
          *to++= (uchar) escape_char;
 
1206
          goto found_eof;
 
1207
        }
913
1208
        /*
914
1209
          When escape_char == enclosed_char, we treat it like we do for
915
1210
          handling quotes in SQL parsing -- you can double-up the
919
1214
         */
920
1215
        if (escape_char != enclosed_char || chr == escape_char)
921
1216
        {
922
 
          *to++ = (unsigned char) unescape((char) chr);
 
1217
          *to++ = (uchar) unescape((char) chr);
923
1218
          continue;
924
1219
        }
925
1220
        PUSH(chr);
928
1223
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
929
1224
      if (chr == line_term_char)
930
1225
#else
931
 
        if (chr == line_term_char && found_enclosed_char == INT_MAX)
 
1226
      if (chr == line_term_char && found_enclosed_char == INT_MAX)
932
1227
#endif
933
 
        {
934
 
          if (terminator(line_term_ptr,line_term_length))
935
 
          {                                     // Maybe unexpected linefeed
936
 
            enclosed=0;
937
 
            found_end_of_line=1;
938
 
            row_start=buffer;
939
 
            row_end=  to;
940
 
            return 0;
941
 
          }
942
 
        }
 
1228
      {
 
1229
        if (terminator(line_term_ptr,line_term_length))
 
1230
        {                                       // Maybe unexpected linefeed
 
1231
          enclosed=0;
 
1232
          found_end_of_line=1;
 
1233
          row_start=buffer;
 
1234
          row_end=  to;
 
1235
          return 0;
 
1236
        }
 
1237
      }
943
1238
      if (chr == found_enclosed_char)
944
1239
      {
945
 
        if ((chr=GET) == found_enclosed_char)
946
 
        {                                       // Remove dupplicated
947
 
          *to++ = (unsigned char) chr;
948
 
          continue;
949
 
        }
950
 
        // End of enclosed field if followed by field_term or line_term
951
 
        if (chr == my_b_EOF ||
952
 
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
953
 
        {                                       // Maybe unexpected linefeed
954
 
          enclosed=1;
955
 
          found_end_of_line=1;
956
 
          row_start=buffer+1;
957
 
          row_end=  to;
958
 
          return 0;
959
 
        }
960
 
        if (chr == field_term_char &&
961
 
            terminator(field_term_ptr,field_term_length))
962
 
        {
963
 
          enclosed=1;
964
 
          row_start=buffer+1;
965
 
          row_end=  to;
966
 
          return 0;
967
 
        }
968
 
        /*
969
 
           The string didn't terminate yet.
970
 
           Store back next character for the loop
971
 
         */
972
 
        PUSH(chr);
973
 
        /* copy the found term character to 'to' */
974
 
        chr= found_enclosed_char;
 
1240
        if ((chr=GET) == found_enclosed_char)
 
1241
        {                                       // Remove dupplicated
 
1242
          *to++ = (uchar) chr;
 
1243
          continue;
 
1244
        }
 
1245
        // End of enclosed field if followed by field_term or line_term
 
1246
        if (chr == my_b_EOF ||
 
1247
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
 
1248
        {                                       // Maybe unexpected linefeed
 
1249
          enclosed=1;
 
1250
          found_end_of_line=1;
 
1251
          row_start=buffer+1;
 
1252
          row_end=  to;
 
1253
          return 0;
 
1254
        }
 
1255
        if (chr == field_term_char &&
 
1256
            terminator(field_term_ptr,field_term_length))
 
1257
        {
 
1258
          enclosed=1;
 
1259
          row_start=buffer+1;
 
1260
          row_end=  to;
 
1261
          return 0;
 
1262
        }
 
1263
        /*
 
1264
          The string didn't terminate yet.
 
1265
          Store back next character for the loop
 
1266
        */
 
1267
        PUSH(chr);
 
1268
        /* copy the found term character to 'to' */
 
1269
        chr= found_enclosed_char;
975
1270
      }
976
1271
      else if (chr == field_term_char && found_enclosed_char == INT_MAX)
977
1272
      {
978
 
        if (terminator(field_term_ptr,field_term_length))
979
 
        {
980
 
          enclosed=0;
981
 
          row_start=buffer;
982
 
          row_end=  to;
983
 
          return 0;
984
 
        }
 
1273
        if (terminator(field_term_ptr,field_term_length))
 
1274
        {
 
1275
          enclosed=0;
 
1276
          row_start=buffer;
 
1277
          row_end=  to;
 
1278
          return 0;
 
1279
        }
985
1280
      }
986
 
      *to++ = (unsigned char) chr;
 
1281
      *to++ = (uchar) chr;
987
1282
    }
988
1283
    /*
989
 
     ** We come here if buffer is too small. Enlarge it and continue
990
 
     */
991
 
    if (!(new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE)))
 
1284
    ** We come here if buffer is too small. Enlarge it and continue
 
1285
    */
 
1286
    if (!(new_buffer=(uchar*) my_realloc((char*) buffer,buff_length+1+IO_SIZE,
 
1287
                                        MYF(MY_WME))))
992
1288
      return (error=1);
993
1289
    to=new_buffer + (to-buffer);
994
1290
    buffer=new_buffer;
1009
1305
 
1010
1306
  NOTES
1011
1307
    The row may not be fixed size on disk if there are escape
1012
 
    characters in the cursor.
 
1308
    characters in the file.
1013
1309
 
1014
1310
  IMPLEMENTATION NOTE
1015
1311
    One can't use fixed length with multi-byte charset **
1022
1318
int READ_INFO::read_fixed_length()
1023
1319
{
1024
1320
  int chr;
1025
 
  unsigned char *to;
 
1321
  uchar *to;
1026
1322
  if (found_end_of_line)
1027
1323
    return 1;                                   // One have to call next_line
1028
1324
 
1042
1338
    {
1043
1339
      if ((chr=GET) == my_b_EOF)
1044
1340
      {
1045
 
        *to++= (unsigned char) escape_char;
 
1341
        *to++= (uchar) escape_char;
1046
1342
        goto found_eof;
1047
1343
      }
1048
 
      *to++ =(unsigned char) unescape((char) chr);
 
1344
      *to++ =(uchar) unescape((char) chr);
1049
1345
      continue;
1050
1346
    }
1051
1347
    if (chr == line_term_char)
1057
1353
        return 0;
1058
1354
      }
1059
1355
    }
1060
 
    *to++ = (unsigned char) chr;
 
1356
    *to++ = (uchar) chr;
1061
1357
  }
1062
1358
  row_end=to;                                   // Found full line
1063
1359
  return 0;
1085
1381
  for (;;)
1086
1382
  {
1087
1383
    int chr = GET;
1088
 
    if (my_mbcharlen(read_charset, chr) > 1)
1089
 
    {
1090
 
      for (uint32_t i=1;
1091
 
          chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
1092
 
          i++)
1093
 
        chr = GET;
1094
 
      if (chr == escape_char)
1095
 
        continue;
1096
 
    }
1097
 
    if (chr == my_b_EOF)
1098
 
    {
 
1384
#ifdef USE_MB
 
1385
   if (my_mbcharlen(read_charset, chr) > 1)
 
1386
   {
 
1387
       for (uint i=1;
 
1388
            chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
 
1389
            i++)
 
1390
           chr = GET;
 
1391
       if (chr == escape_char)
 
1392
           continue;
 
1393
   }
 
1394
#endif
 
1395
   if (chr == my_b_EOF)
 
1396
   {
1099
1397
      eof=1;
1100
1398
      return 1;
1101
1399
    }
1103
1401
    {
1104
1402
      line_cuted=1;
1105
1403
      if (GET == my_b_EOF)
1106
 
        return 1;
 
1404
        return 1;
1107
1405
      continue;
1108
1406
    }
1109
1407
    if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1133
1431
      PUSH(chr);
1134
1432
      while (--ptr != line_start_ptr)
1135
1433
      {                                         // Restart with next char
1136
 
        PUSH((unsigned char) *ptr);
 
1434
        PUSH((uchar) *ptr);
1137
1435
      }
1138
1436
      goto try_again;
1139
1437
    }
1142
1440
}
1143
1441
 
1144
1442
 
1145
 
} /* namespace drizzled */
 
1443
/*
 
1444
  Clear taglist from tags with a specified level
 
1445
*/
 
1446
int READ_INFO::clear_level(int level)
 
1447
{
 
1448
  DBUG_ENTER("READ_INFO::read_xml clear_level");
 
1449
  List_iterator<XML_TAG> xmlit(taglist);
 
1450
  xmlit.rewind();
 
1451
  XML_TAG *tag;
 
1452
  
 
1453
  while ((tag= xmlit++))
 
1454
  {
 
1455
     if(tag->level >= level)
 
1456
     {
 
1457
       xmlit.remove();
 
1458
       delete tag;
 
1459
     }
 
1460
  }
 
1461
  DBUG_RETURN(0);
 
1462
}
 
1463
 
 
1464
 
 
1465
/*
 
1466
  Convert an XML entity to Unicode value.
 
1467
  Return -1 on error;
 
1468
*/
 
1469
static int
 
1470
my_xml_entity_to_char(const char *name, uint length)
 
1471
{
 
1472
  if (length == 2)
 
1473
  {
 
1474
    if (!memcmp(name, "gt", length))
 
1475
      return '>';
 
1476
    if (!memcmp(name, "lt", length))
 
1477
      return '<';
 
1478
  }
 
1479
  else if (length == 3)
 
1480
  {
 
1481
    if (!memcmp(name, "amp", length))
 
1482
      return '&';
 
1483
  }
 
1484
  else if (length == 4)
 
1485
  {
 
1486
    if (!memcmp(name, "quot", length))
 
1487
      return '"';
 
1488
    if (!memcmp(name, "apos", length))
 
1489
      return '\'';
 
1490
  }
 
1491
  return -1;
 
1492
}
 
1493
 
 
1494
 
 
1495
/**
 
1496
  @brief Convert newline, linefeed, tab to space
 
1497
  
 
1498
  @param chr    character
 
1499
  
 
1500
  @details According to the "XML 1.0" standard,
 
1501
           only space (#x20) characters, carriage returns,
 
1502
           line feeds or tabs are considered as spaces.
 
1503
           Convert all of them to space (#x20) for parsing simplicity.
 
1504
*/
 
1505
static int
 
1506
my_tospace(int chr)
 
1507
{
 
1508
  return (chr == '\t' || chr == '\r' || chr == '\n') ? ' ' : chr;
 
1509
}
 
1510
 
 
1511
 
 
1512
/*
 
1513
  Read an xml value: handle multibyte and xml escape
 
1514
*/
 
1515
int READ_INFO::read_value(int delim, String *val)
 
1516
{
 
1517
  int chr;
 
1518
  String tmp;
 
1519
 
 
1520
  for (chr= my_tospace(GET); chr != delim && chr != my_b_EOF; )
 
1521
  {
 
1522
#ifdef USE_MB
 
1523
    if (my_mbcharlen(read_charset, chr) > 1)
 
1524
    {
 
1525
      DBUG_PRINT("read_xml",("multi byte"));
 
1526
      int i, ml= my_mbcharlen(read_charset, chr);
 
1527
      for (i= 1; i < ml; i++) 
 
1528
      {
 
1529
        val->append(chr);
 
1530
        /*
 
1531
          Don't use my_tospace() in the middle of a multi-byte character
 
1532
          TODO: check that the multi-byte sequence is valid.
 
1533
        */
 
1534
        chr= GET; 
 
1535
        if (chr == my_b_EOF)
 
1536
          return chr;
 
1537
      }
 
1538
    }
 
1539
#endif
 
1540
    if(chr == '&')
 
1541
    {
 
1542
      tmp.length(0);
 
1543
      for (chr= my_tospace(GET) ; chr != ';' ; chr= my_tospace(GET))
 
1544
      {
 
1545
        if (chr == my_b_EOF)
 
1546
          return chr;
 
1547
        tmp.append(chr);
 
1548
      }
 
1549
      if ((chr= my_xml_entity_to_char(tmp.ptr(), tmp.length())) >= 0)
 
1550
        val->append(chr);
 
1551
      else
 
1552
      {
 
1553
        val->append('&');
 
1554
        val->append(tmp);
 
1555
        val->append(';'); 
 
1556
      }
 
1557
    }
 
1558
    else
 
1559
      val->append(chr);
 
1560
    chr= my_tospace(GET);
 
1561
  }            
 
1562
  return chr;
 
1563
}
 
1564
 
 
1565
 
 
1566
/*
 
1567
  Read a record in xml format
 
1568
  tags and attributes are stored in taglist
 
1569
  when tag set in ROWS IDENTIFIED BY is closed, we are ready and return
 
1570
*/
 
1571
int READ_INFO::read_xml()
 
1572
{
 
1573
  DBUG_ENTER("READ_INFO::read_xml");
 
1574
  int chr, chr2, chr3;
 
1575
  int delim= 0;
 
1576
  String tag, attribute, value;
 
1577
  bool in_tag= false;
 
1578
  
 
1579
  tag.length(0);
 
1580
  attribute.length(0);
 
1581
  value.length(0);
 
1582
  
 
1583
  for (chr= my_tospace(GET); chr != my_b_EOF ; )
 
1584
  {
 
1585
    switch(chr){
 
1586
    case '<':  /* read tag */
 
1587
        /* TODO: check if this is a comment <!-- comment -->  */
 
1588
      chr= my_tospace(GET);
 
1589
      if(chr == '!')
 
1590
      {
 
1591
        chr2= GET;
 
1592
        chr3= GET;
 
1593
        
 
1594
        if(chr2 == '-' && chr3 == '-')
 
1595
        {
 
1596
          chr2= 0;
 
1597
          chr3= 0;
 
1598
          chr= my_tospace(GET);
 
1599
          
 
1600
          while(chr != '>' || chr2 != '-' || chr3 != '-')
 
1601
          {
 
1602
            if(chr == '-')
 
1603
            {
 
1604
              chr3= chr2;
 
1605
              chr2= chr;
 
1606
            }
 
1607
            else if (chr2 == '-')
 
1608
            {
 
1609
              chr2= 0;
 
1610
              chr3= 0;
 
1611
            }
 
1612
            chr= my_tospace(GET);
 
1613
            if (chr == my_b_EOF)
 
1614
              goto found_eof;
 
1615
          }
 
1616
          break;
 
1617
        }
 
1618
      }
 
1619
      
 
1620
      tag.length(0);
 
1621
      while(chr != '>' && chr != ' ' && chr != '/' && chr != my_b_EOF)
 
1622
      {
 
1623
        if(chr != delim) /* fix for the '<field name =' format */
 
1624
          tag.append(chr);
 
1625
        chr= my_tospace(GET);
 
1626
      }
 
1627
      
 
1628
      // row tag should be in ROWS IDENTIFIED BY '<row>' - stored in line_term 
 
1629
      if((tag.length() == line_term_length -2) &&
 
1630
         (strncmp(tag.c_ptr_safe(), line_term_ptr + 1, tag.length()) == 0))
 
1631
      {
 
1632
        DBUG_PRINT("read_xml", ("start-of-row: %i %s %s", 
 
1633
                                level,tag.c_ptr_safe(), line_term_ptr));
 
1634
      }
 
1635
      
 
1636
      if(chr == ' ' || chr == '>')
 
1637
      {
 
1638
        level++;
 
1639
        clear_level(level + 1);
 
1640
      }
 
1641
      
 
1642
      if (chr == ' ')
 
1643
        in_tag= true;
 
1644
      else 
 
1645
        in_tag= false;
 
1646
      break;
 
1647
      
 
1648
    case ' ': /* read attribute */
 
1649
      while(chr == ' ')  /* skip blanks */
 
1650
        chr= my_tospace(GET);
 
1651
      
 
1652
      if(!in_tag)
 
1653
        break;
 
1654
      
 
1655
      while(chr != '=' && chr != '/' && chr != '>' && chr != my_b_EOF)
 
1656
      {
 
1657
        attribute.append(chr);
 
1658
        chr= my_tospace(GET);
 
1659
      }
 
1660
      break;
 
1661
      
 
1662
    case '>': /* end tag - read tag value */
 
1663
      in_tag= false;
 
1664
      chr= read_value('<', &value);
 
1665
      if(chr == my_b_EOF)
 
1666
        goto found_eof;
 
1667
      
 
1668
      /* save value to list */
 
1669
      if(tag.length() > 0 && value.length() > 0)
 
1670
      {
 
1671
        DBUG_PRINT("read_xml", ("lev:%i tag:%s val:%s",
 
1672
                                level,tag.c_ptr_safe(), value.c_ptr_safe()));
 
1673
        taglist.push_front( new XML_TAG(level, tag, value));
 
1674
      }
 
1675
      tag.length(0);
 
1676
      value.length(0);
 
1677
      attribute.length(0);
 
1678
      break;
 
1679
      
 
1680
    case '/': /* close tag */
 
1681
      level--;
 
1682
      chr= my_tospace(GET);
 
1683
      if(chr != '>')   /* if this is an empty tag <tag   /> */
 
1684
        tag.length(0); /* we should keep tag value          */
 
1685
      while(chr != '>' && chr != my_b_EOF)
 
1686
      {
 
1687
        tag.append(chr);
 
1688
        chr= my_tospace(GET);
 
1689
      }
 
1690
      
 
1691
      if((tag.length() == line_term_length -2) &&
 
1692
         (strncmp(tag.c_ptr_safe(), line_term_ptr + 1, tag.length()) == 0))
 
1693
      {
 
1694
         DBUG_PRINT("read_xml", ("found end-of-row %i %s", 
 
1695
                                 level, tag.c_ptr_safe()));
 
1696
         DBUG_RETURN(0); //normal return
 
1697
      }
 
1698
      chr= my_tospace(GET);
 
1699
      break;   
 
1700
      
 
1701
    case '=': /* attribute name end - read the value */
 
1702
      //check for tag field and attribute name
 
1703
      if(!memcmp(tag.c_ptr_safe(), STRING_WITH_LEN("field")) &&
 
1704
         !memcmp(attribute.c_ptr_safe(), STRING_WITH_LEN("name")))
 
1705
      {
 
1706
        /*
 
1707
          this is format <field name="xx">xx</field>
 
1708
          where actual fieldname is in attribute
 
1709
        */
 
1710
        delim= my_tospace(GET);
 
1711
        tag.length(0);
 
1712
        attribute.length(0);
 
1713
        chr= '<'; /* we pretend that it is a tag */
 
1714
        level--;
 
1715
        break;
 
1716
      }
 
1717
      
 
1718
      //check for " or '
 
1719
      chr= GET;
 
1720
      if (chr == my_b_EOF)
 
1721
        goto found_eof;
 
1722
      if(chr == '"' || chr == '\'')
 
1723
      {
 
1724
        delim= chr;
 
1725
      }
 
1726
      else
 
1727
      {
 
1728
        delim= ' '; /* no delimiter, use space */
 
1729
        PUSH(chr);
 
1730
      }
 
1731
      
 
1732
      chr= read_value(delim, &value);
 
1733
      if(attribute.length() > 0 && value.length() > 0)
 
1734
      {
 
1735
        DBUG_PRINT("read_xml", ("lev:%i att:%s val:%s\n",
 
1736
                                level + 1,
 
1737
                                attribute.c_ptr_safe(),
 
1738
                                value.c_ptr_safe()));
 
1739
        taglist.push_front(new XML_TAG(level + 1, attribute, value));
 
1740
      }
 
1741
      attribute.length(0);
 
1742
      value.length(0);
 
1743
      if (chr != ' ')
 
1744
        chr= my_tospace(GET);
 
1745
      break;
 
1746
    
 
1747
    default:
 
1748
      chr= my_tospace(GET);
 
1749
    } /* end switch */
 
1750
  } /* end while */
 
1751
  
 
1752
found_eof:
 
1753
  DBUG_PRINT("read_xml",("Found eof"));
 
1754
  eof= 1;
 
1755
  DBUG_RETURN(1);
 
1756
}