~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_load.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/* Copy data from a textfile to table */
18
18
 
19
 
#include <drizzled/server_includes.h>
20
 
#include "sql_repl.h"
21
 
#include <drizzled/drizzled_error_messages.h>
22
 
 
 
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 drizzled;
 
36
using namespace std;
23
37
 
24
38
class READ_INFO {
25
 
  File  file;
26
 
  uchar *buffer,                        /* Buffer for read text */
27
 
        *end_of_buff;                   /* Data in bufferts ends here */
28
 
  uint  buff_length,                    /* Length of buffert */
29
 
        max_length;                     /* Max length of row */
 
39
  int   cursor;
 
40
  unsigned char *buffer;                /* Buffer for read text */
 
41
  unsigned char *end_of_buff;           /* Data in bufferts ends here */
 
42
  size_t buff_length;                   /* Length of buffert */
 
43
  size_t max_length;                    /* Max length of row */
30
44
  char  *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
31
45
  uint  field_term_length,line_term_length,enclosed_length;
32
46
  int   field_term_char,line_term_char,enclosed_char,escape_char;
34
48
  bool  found_end_of_line,start_of_line,eof;
35
49
  bool  need_end_io_cache;
36
50
  IO_CACHE cache;
37
 
  NET *io_net;
38
51
 
39
52
public:
40
53
  bool error,line_cuted,found_null,enclosed;
41
 
  uchar *row_start,                     /* Found row starts here */
 
54
  unsigned char *row_start,                     /* Found row starts here */
42
55
        *row_end;                       /* Found row ends here */
43
56
  const CHARSET_INFO *read_charset;
44
57
 
45
 
  READ_INFO(File file,uint tot_length, const CHARSET_INFO * const cs,
 
58
  READ_INFO(int cursor, size_t tot_length, const CHARSET_INFO * const cs,
46
59
            String &field_term,String &line_start,String &line_term,
47
 
            String &enclosed,int escape,bool get_it_from_net, bool is_fifo);
 
60
            String &enclosed,int escape, bool is_fifo);
48
61
  ~READ_INFO();
49
62
  int read_field();
50
63
  int read_fixed_length(void);
51
64
  int next_line(void);
52
65
  char unescape(char chr);
53
 
  int terminator(char *ptr,uint length);
 
66
  int terminator(char *ptr,uint32_t length);
54
67
  bool find_start_of_fields();
55
68
 
56
69
  /*
66
79
  /*
67
80
    Either this method, or we need to make cache public
68
81
    Arg must be set from mysql_load() since constructor does not see
69
 
    either the table or THD value
 
82
    either the table or Session value
70
83
  */
71
84
  void set_io_cache_arg(void* arg) { cache.arg = arg; }
72
85
};
73
86
 
74
 
static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
87
static int read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
75
88
                             List<Item> &fields_vars, List<Item> &set_fields,
76
89
                             List<Item> &set_values, READ_INFO &read_info,
77
90
                             uint32_t skip_lines,
78
91
                             bool ignore_check_option_errors);
79
 
static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
92
static int read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
80
93
                          List<Item> &fields_vars, List<Item> &set_fields,
81
94
                          List<Item> &set_values, READ_INFO &read_info,
82
95
                          String &enclosed, uint32_t skip_lines,
83
96
                          bool ignore_check_option_errors);
84
97
 
85
 
static bool write_execute_load_query_log_event(THD *thd,
86
 
                                               bool duplicates, bool ignore,
87
 
                                               bool transactional_table,
88
 
                                               THD::killed_state killed_status);
89
98
 
90
99
/*
91
100
  Execute LOAD DATA query
92
101
 
93
102
  SYNOPSYS
94
103
    mysql_load()
95
 
      thd - current thread
96
 
      ex  - sql_exchange object representing source file and its parsing rules
 
104
      session - current thread
 
105
      ex  - file_exchange object representing source cursor and its parsing rules
97
106
      table_list  - list of tables to which we are loading data
98
107
      fields_vars - list of fields and variables to which we read
99
 
                    data from file
 
108
                    data from cursor
100
109
      set_fields  - list of fields mentioned in set clause
101
110
      set_values  - expressions to assign to fields in previous list
102
111
      handle_duplicates - indicates whenever we should emit error or
103
112
                          replace row if we will meet duplicates.
104
113
      ignore -          - indicates whenever we should ignore duplicates
105
 
      read_file_from_client - is this LOAD DATA LOCAL ?
106
114
 
107
115
  RETURN VALUES
108
116
    true - error / false - success
109
117
*/
110
118
 
111
 
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
 
119
int mysql_load(Session *session,file_exchange *ex,TableList *table_list,
112
120
                List<Item> &fields_vars, List<Item> &set_fields,
113
121
                List<Item> &set_values,
114
 
                enum enum_duplicates handle_duplicates, bool ignore,
115
 
                bool read_file_from_client)
 
122
                enum enum_duplicates handle_duplicates, bool ignore)
116
123
{
117
124
  char name[FN_REFLEN];
118
 
  File file;
119
 
  TABLE *table= NULL;
 
125
  int file;
 
126
  Table *table= NULL;
120
127
  int error;
121
128
  String *field_term=ex->field_term,*escaped=ex->escaped;
122
129
  String *enclosed=ex->enclosed;
123
130
  bool is_fifo=0;
124
 
  LOAD_FILE_INFO lf_info;
125
 
  char *db = table_list->db;                    // This is never null
 
131
  char *db= table_list->db;                     // This is never null
 
132
  assert(db);
126
133
  /*
127
 
    If path for file is not defined, we will use the current database.
 
134
    If path for cursor is not defined, we will use the current database.
128
135
    If this is not set, we will use the directory where the table to be
129
136
    loaded is located
130
137
  */
131
 
  char *tdb= thd->db ? thd->db : db;            // Result is never null
 
138
  const char *tdb= session->db.empty() ? db  : session->db.c_str();             // Result is never null
 
139
  assert(tdb);
132
140
  uint32_t skip_lines= ex->skip_lines;
133
141
  bool transactional_table;
134
 
  THD::killed_state killed_status= THD::NOT_KILLED;
 
142
  Session::killed_state killed_status= Session::NOT_KILLED;
135
143
 
136
 
  if (escaped->length() > 1 || enclosed->length() > 1)
 
144
  /* Escape and enclosed character may be a utf8 4-byte character */
 
145
  if (escaped->length() > 4 || enclosed->length() > 4)
137
146
  {
138
 
    my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
139
 
               MYF(0));
 
147
    my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
140
148
    return(true);
141
149
  }
142
 
  if (open_and_lock_tables(thd, table_list))
 
150
 
 
151
  if (session->openTablesLock(table_list))
143
152
    return(true);
144
 
  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
145
 
                                    &thd->lex->select_lex.top_join_list,
 
153
 
 
154
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
 
155
                                    &session->lex->select_lex.top_join_list,
146
156
                                    table_list,
147
 
                                    &thd->lex->select_lex.leaf_tables, true))
 
157
                                    &session->lex->select_lex.leaf_tables, true))
148
158
     return(-1);
149
159
 
150
160
  /*
155
165
    table is marked to be 'used for insert' in which case we should never
156
166
    mark this table as 'const table' (ie, one that has only one row).
157
167
  */
158
 
  if (unique_table(thd, table_list, table_list->next_global, 0))
 
168
  if (unique_table(table_list, table_list->next_global))
159
169
  {
160
170
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
161
171
    return(true);
162
172
  }
163
173
 
164
174
  table= table_list->table;
165
 
  transactional_table= table->file->has_transactions();
 
175
  transactional_table= table->cursor->has_transactions();
166
176
 
167
177
  if (!fields_vars.elements)
168
178
  {
169
179
    Field **field;
170
180
    for (field=table->field; *field ; field++)
171
181
      fields_vars.push_back(new Item_field(*field));
172
 
    bitmap_set_all(table->write_set);
 
182
    table->setWriteSet();
173
183
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
174
184
    /*
175
185
      Let us also prepare SET clause, altough it is probably empty
176
186
      in this case.
177
187
    */
178
 
    if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
179
 
        setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
 
188
    if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
 
189
        setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
180
190
      return(true);
181
191
  }
182
192
  else
183
193
  {                                             // Part field list
184
194
    /* TODO: use this conds for 'WITH CHECK OPTIONS' */
185
 
    if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
186
 
        setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
187
 
        check_that_all_fields_are_given_values(thd, table, table_list))
 
195
    if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
 
196
        setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
 
197
        check_that_all_fields_are_given_values(session, table, table_list))
188
198
      return(true);
189
199
    /*
190
200
      Check whenever TIMESTAMP field with auto-set feature specified
192
202
    */
193
203
    if (table->timestamp_field)
194
204
    {
195
 
      if (bitmap_is_set(table->write_set,
196
 
                        table->timestamp_field->field_index))
 
205
      if (table->isWriteSet(table->timestamp_field->field_index))
197
206
        table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
198
207
      else
199
208
      {
200
 
        bitmap_set_bit(table->write_set,
201
 
                       table->timestamp_field->field_index);
 
209
        table->setWriteSet(table->timestamp_field->field_index);
202
210
      }
203
211
    }
204
212
    /* Fix the expressions in SET clause */
205
 
    if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
 
213
    if (setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
206
214
      return(true);
207
215
  }
208
216
 
209
217
  table->mark_columns_needed_for_insert();
210
218
 
211
 
  uint tot_length=0;
 
219
  size_t tot_length=0;
212
220
  bool use_blobs= 0, use_vars= 0;
213
221
  List_iterator_fast<Item> it(fields_vars);
214
222
  Item *item;
243
251
    return(true);
244
252
  }
245
253
 
246
 
  /* We can't give an error in the middle when using LOCAL files */
247
 
  if (read_file_from_client && handle_duplicates == DUP_ERROR)
248
 
    ignore= 1;
249
 
 
250
 
  if (read_file_from_client)
251
 
  {
252
 
    (void)net_request_file(&thd->net,ex->file_name);
253
 
    file = -1;
254
 
  }
255
 
  else
256
254
  {
257
255
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
258
256
    ex->file_name+=dirname_length(ex->file_name);
259
257
#endif
260
258
    if (!dirname_length(ex->file_name))
261
259
    {
262
 
      strxnmov(name, FN_REFLEN-1, mysql_real_data_home, tdb, NullS);
 
260
      strcpy(name, drizzle_real_data_home);
 
261
      strncat(name, tdb, FN_REFLEN-strlen(drizzle_real_data_home)-1);
263
262
      (void) fn_format(name, ex->file_name, name, "",
264
263
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
265
264
    }
266
265
    else
267
266
    {
268
 
      (void) fn_format(name, ex->file_name, mysql_real_data_home, "",
 
267
      (void) fn_format(name, ex->file_name, drizzle_real_data_home, "",
269
268
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
270
269
 
271
270
      if (opt_secure_file_priv &&
278
277
 
279
278
      struct stat stat_info;
280
279
      if (stat(name,&stat_info))
 
280
      {
 
281
        my_error(ER_FILE_NOT_FOUND, MYF(0), name, errno);
281
282
        return(true);
 
283
      }
282
284
 
283
 
      // if we are not in slave thread, the file must be:
284
 
      if (!thd->slave_thread &&
285
 
          !((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
286
 
            (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
287
 
            ((stat_info.st_mode & S_IFREG) == S_IFREG ||
288
 
             (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
 
285
      // if we are not in slave thread, the cursor must be:
 
286
      if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
 
287
            (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
 
288
            ((stat_info.st_mode & S_IFREG) == S_IFREG ||
 
289
             (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
289
290
      {
290
291
        my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
291
292
        return(true);
294
295
        is_fifo = 1;
295
296
    }
296
297
    if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
 
298
    {
 
299
      my_error(ER_CANT_OPEN_FILE, MYF(0), name, errno);
297
300
      return(true);
 
301
    }
298
302
  }
299
303
 
300
304
  COPY_INFO info;
303
307
  info.handle_duplicates=handle_duplicates;
304
308
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
305
309
 
306
 
  READ_INFO read_info(file,tot_length,
307
 
                      ex->cs ? ex->cs : thd->variables.collation_database,
 
310
  READ_INFO read_info(file, tot_length,
 
311
                      ex->cs ? ex->cs : get_default_db_collation(session->db.c_str()),
308
312
                      *field_term,*ex->line_start, *ex->line_term, *enclosed,
309
 
                      info.escape_char, read_file_from_client, is_fifo);
 
313
                      info.escape_char, is_fifo);
310
314
  if (read_info.error)
311
315
  {
312
316
    if  (file >= 0)
314
318
    return(true);                               // Can't allocate buffers
315
319
  }
316
320
 
317
 
  if (mysql_bin_log.is_open())
318
 
  {
319
 
    lf_info.thd = thd;
320
 
    lf_info.wrote_create_file = 0;
321
 
    lf_info.last_pos_in_file = HA_POS_ERROR;
322
 
    lf_info.log_delayed= transactional_table;
323
 
    read_info.set_io_cache_arg((void*) &lf_info);
324
 
  }
325
 
 
326
 
  thd->count_cuted_fields= CHECK_FIELD_WARN;            /* calc cuted fields */
327
 
  thd->cuted_fields=0L;
 
321
  /*
 
322
   * Per the SQL standard, inserting NULL into a NOT NULL
 
323
   * field requires an error to be thrown.
 
324
   *
 
325
   * @NOTE
 
326
   *
 
327
   * NULL check and handling occurs in field_conv.cc
 
328
   */
 
329
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
330
  session->cuted_fields=0L;
328
331
  /* Skip lines if there is a line terminator */
329
332
  if (ex->line_term->length())
330
333
  {
343
346
    table->next_number_field=table->found_next_number_field;
344
347
    if (ignore ||
345
348
        handle_duplicates == DUP_REPLACE)
346
 
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
349
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
347
350
    if (handle_duplicates == DUP_REPLACE)
348
 
        table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
349
 
    table->file->ha_start_bulk_insert((ha_rows) 0);
 
351
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
352
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
350
353
    table->copy_blobs=1;
351
354
 
352
 
    thd->abort_on_warning= (!ignore &&
353
 
                            (thd->variables.sql_mode &
354
 
                             (MODE_STRICT_TRANS_TABLES |
355
 
                              MODE_STRICT_ALL_TABLES)));
 
355
    session->abort_on_warning= true;
356
356
 
357
357
    if (!field_term->length() && !enclosed->length())
358
 
      error= read_fixed_length(thd, info, table_list, fields_vars,
 
358
      error= read_fixed_length(session, info, table_list, fields_vars,
359
359
                               set_fields, set_values, read_info,
360
360
                               skip_lines, ignore);
361
361
    else
362
 
      error= read_sep_field(thd, info, table_list, fields_vars,
 
362
      error= read_sep_field(session, info, table_list, fields_vars,
363
363
                            set_fields, set_values, read_info,
364
364
                            *enclosed, skip_lines, ignore);
365
 
    if (table->file->ha_end_bulk_insert() && !error)
 
365
    if (table->cursor->ha_end_bulk_insert() && !error)
366
366
    {
367
 
      table->file->print_error(my_errno, MYF(0));
 
367
      table->print_error(errno, MYF(0));
368
368
      error= 1;
369
369
    }
370
 
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
371
 
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
370
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
371
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
372
372
    table->next_number_field=0;
373
373
  }
374
374
  if (file >= 0)
375
375
    my_close(file,MYF(0));
376
376
  free_blobs(table);                            /* if pack_blob was used */
377
377
  table->copy_blobs=0;
378
 
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
379
 
  /* 
 
378
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
 
379
  /*
380
380
     simulated killing in the middle of per-row loop
381
381
     must be effective for binlogging
382
382
  */
383
 
  killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
 
383
  killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
384
384
  if (error)
385
385
  {
386
 
    if (read_file_from_client)
387
 
      while (!read_info.next_line())
388
 
        ;
389
 
 
390
 
    if (mysql_bin_log.is_open())
391
 
    {
392
 
      {
393
 
        /*
394
 
          Make sure last block (the one which caused the error) gets
395
 
          logged.  This is needed because otherwise after write of (to
396
 
          the binlog, not to read_info (which is a cache))
397
 
          Delete_file_log_event the bad block will remain in read_info
398
 
          (because pre_read is not called at the end of the last
399
 
          block; remember pre_read is called whenever a new block is
400
 
          read from disk).  At the end of mysql_load(), the destructor
401
 
          of read_info will call end_io_cache() which will flush
402
 
          read_info, so we will finally have this in the binlog:
403
 
 
404
 
          Append_block # The last successfull block
405
 
          Delete_file
406
 
          Append_block # The failing block
407
 
          which is nonsense.
408
 
          Or could also be (for a small file)
409
 
          Create_file  # The failing block
410
 
          which is nonsense (Delete_file is not written in this case, because:
411
 
          Create_file has not been written, so Delete_file is not written, then
412
 
          when read_info is destroyed end_io_cache() is called which writes
413
 
          Create_file.
414
 
        */
415
 
        read_info.end_io_cache();
416
 
        /* If the file was not empty, wrote_create_file is true */
417
 
        if (lf_info.wrote_create_file)
418
 
        {
419
 
          if (thd->transaction.stmt.modified_non_trans_table)
420
 
            write_execute_load_query_log_event(thd, handle_duplicates,
421
 
                                               ignore, transactional_table,
422
 
                                               killed_status);
423
 
          else
424
 
          {
425
 
            Delete_file_log_event d(thd, db, transactional_table);
426
 
            d.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
427
 
            mysql_bin_log.write(&d);
428
 
          }
429
 
        }
430
 
      }
431
 
    }
432
386
    error= -1;                          // Error on read
433
387
    goto err;
434
388
  }
435
389
  sprintf(name, ER(ER_LOAD_INFO), (uint32_t) info.records, (uint32_t) info.deleted,
436
 
          (uint32_t) (info.records - info.copied), (uint32_t) thd->cuted_fields);
437
 
 
438
 
  if (thd->transaction.stmt.modified_non_trans_table)
439
 
    thd->transaction.all.modified_non_trans_table= true;
440
 
 
441
 
  if (mysql_bin_log.is_open())
442
 
  {
443
 
    /*
444
 
      We need to do the job that is normally done inside
445
 
      binlog_query() here, which is to ensure that the pending event
446
 
      is written before tables are unlocked and before any other
447
 
      events are written.  We also need to update the table map
448
 
      version for the binary log to mark that table maps are invalid
449
 
      after this point.
450
 
     */
451
 
    if (thd->current_stmt_binlog_row_based)
452
 
      thd->binlog_flush_pending_rows_event(true);
453
 
    else
454
 
    {
455
 
      /*
456
 
        As already explained above, we need to call end_io_cache() or the last
457
 
        block will be logged only after Execute_load_query_log_event (which is
458
 
        wrong), when read_info is destroyed.
459
 
      */
460
 
      read_info.end_io_cache();
461
 
      if (lf_info.wrote_create_file)
462
 
      {
463
 
        write_execute_load_query_log_event(thd, handle_duplicates, ignore,
464
 
                                           transactional_table,killed_status);
465
 
      }
466
 
    }
467
 
  }
 
390
          (uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
 
391
 
 
392
  if (session->transaction.stmt.modified_non_trans_table)
 
393
    session->transaction.all.modified_non_trans_table= true;
468
394
 
469
395
  /* ok to client sent only after binlog write and engine commit */
470
 
  my_ok(thd, info.copied + info.deleted, 0L, name);
 
396
  session->my_ok(info.copied + info.deleted, 0, 0L, name);
471
397
err:
472
398
  assert(transactional_table || !(info.copied || info.deleted) ||
473
 
              thd->transaction.stmt.modified_non_trans_table);
474
 
  table->file->ha_release_auto_increment();
 
399
              session->transaction.stmt.modified_non_trans_table);
 
400
  table->cursor->ha_release_auto_increment();
475
401
  table->auto_increment_field_not_null= false;
476
 
  thd->abort_on_warning= 0;
 
402
  session->abort_on_warning= 0;
477
403
  return(error);
478
404
}
479
405
 
480
406
 
481
 
/* Not a very useful function; just to avoid duplication of code */
482
 
static bool write_execute_load_query_log_event(THD *thd,
483
 
                                               bool duplicates, bool ignore,
484
 
                                               bool transactional_table,
485
 
                                               THD::killed_state killed_err_arg)
486
 
{
487
 
  Execute_load_query_log_event
488
 
    e(thd, thd->query, thd->query_length,
489
 
      (char*)thd->lex->fname_start - (char*)thd->query,
490
 
      (char*)thd->lex->fname_end - (char*)thd->query,
491
 
      (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE :
492
 
      (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR),
493
 
      transactional_table, false, killed_err_arg);
494
 
  e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
495
 
  return mysql_bin_log.write(&e);
496
 
}
497
 
 
498
 
 
499
407
/****************************************************************************
500
408
** Read of rows of fixed size + optional garage + optonal newline
501
409
****************************************************************************/
502
410
 
503
411
static int
504
 
read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
412
read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
505
413
                  List<Item> &fields_vars, List<Item> &set_fields,
506
414
                  List<Item> &set_values, READ_INFO &read_info,
507
415
                  uint32_t skip_lines, bool ignore_check_option_errors)
508
416
{
509
417
  List_iterator_fast<Item> it(fields_vars);
510
418
  Item_field *sql_field;
511
 
  TABLE *table= table_list->table;
 
419
  Table *table= table_list->table;
512
420
  uint64_t id;
513
421
  bool err;
514
422
 
515
423
  id= 0;
516
 
 
 
424
 
517
425
  while (!read_info.read_fixed_length())
518
426
  {
519
 
    if (thd->killed)
 
427
    if (session->killed)
520
428
    {
521
 
      thd->send_kill_message();
 
429
      session->send_kill_message();
522
430
      return(1);
523
431
    }
524
432
    if (skip_lines)
533
441
      continue;
534
442
    }
535
443
    it.rewind();
536
 
    uchar *pos=read_info.row_start;
 
444
    unsigned char *pos=read_info.row_start;
537
445
#ifdef HAVE_purify
538
446
    read_info.row_end[0]=0;
539
447
#endif
540
448
 
541
 
    restore_record(table, s->default_values);
 
449
    table->restoreRecordAsDefault();
542
450
    /*
543
451
      There is no variables in fields_vars list in this format so
544
452
      this conversion is safe.
545
453
    */
546
454
    while ((sql_field= (Item_field*) it++))
547
455
    {
548
 
      Field *field= sql_field->field;                  
 
456
      Field *field= sql_field->field;
549
457
      if (field == table->next_number_field)
550
458
        table->auto_increment_field_not_null= true;
551
459
      /*
557
465
 
558
466
      if (pos == read_info.row_end)
559
467
      {
560
 
        thd->cuted_fields++;                    /* Not enough fields */
561
 
        push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 
562
 
                            ER_WARN_TOO_FEW_RECORDS, 
563
 
                            ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
 
468
        session->cuted_fields++;                        /* Not enough fields */
 
469
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
470
                            ER_WARN_TOO_FEW_RECORDS,
 
471
                            ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
564
472
        if (!field->maybe_null() && field->type() == DRIZZLE_TYPE_TIMESTAMP)
565
473
            ((Field_timestamp*) field)->set_time();
566
474
      }
567
475
      else
568
476
      {
569
 
        uint length;
570
 
        uchar save_chr;
571
 
        if ((length=(uint) (read_info.row_end-pos)) >
 
477
        uint32_t length;
 
478
        unsigned char save_chr;
 
479
        if ((length=(uint32_t) (read_info.row_end-pos)) >
572
480
            field->field_length)
 
481
        {
573
482
          length=field->field_length;
574
 
        save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc
 
483
        }
 
484
        save_chr=pos[length];
 
485
        pos[length]='\0'; // Add temp null terminator for store()
575
486
        field->store((char*) pos,length,read_info.read_charset);
576
487
        pos[length]=save_chr;
577
488
        if ((pos+=length) > read_info.row_end)
580
491
    }
581
492
    if (pos != read_info.row_end)
582
493
    {
583
 
      thd->cuted_fields++;                      /* To long row */
584
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 
585
 
                          ER_WARN_TOO_MANY_RECORDS, 
586
 
                          ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); 
 
494
      session->cuted_fields++;                  /* To long row */
 
495
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
496
                          ER_WARN_TOO_MANY_RECORDS,
 
497
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
587
498
    }
588
499
 
589
 
    if (thd->killed ||
590
 
        fill_record(thd, set_fields, set_values,
 
500
    if (session->killed ||
 
501
        fill_record(session, set_fields, set_values,
591
502
                    ignore_check_option_errors))
592
503
      return(1);
593
504
 
594
 
    err= write_record(thd, table, &info);
 
505
    err= write_record(session, table, &info);
595
506
    table->auto_increment_field_not_null= false;
596
507
    if (err)
597
508
      return(1);
598
 
   
 
509
 
599
510
    /*
600
511
      We don't need to reset auto-increment field since we are restoring
601
512
      its default value at the beginning of each loop iteration.
604
515
      break;
605
516
    if (read_info.line_cuted)
606
517
    {
607
 
      thd->cuted_fields++;                      /* To long row */
608
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 
609
 
                          ER_WARN_TOO_MANY_RECORDS, 
610
 
                          ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); 
 
518
      session->cuted_fields++;                  /* To long row */
 
519
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
520
                          ER_WARN_TOO_MANY_RECORDS,
 
521
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
611
522
    }
612
 
    thd->row_count++;
 
523
    session->row_count++;
613
524
  }
614
525
  return(test(read_info.error));
615
526
}
617
528
 
618
529
 
619
530
static int
620
 
read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
531
read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
621
532
               List<Item> &fields_vars, List<Item> &set_fields,
622
533
               List<Item> &set_values, READ_INFO &read_info,
623
534
               String &enclosed, uint32_t skip_lines,
625
536
{
626
537
  List_iterator_fast<Item> it(fields_vars);
627
538
  Item *item;
628
 
  TABLE *table= table_list->table;
629
 
  uint enclosed_length;
 
539
  Table *table= table_list->table;
 
540
  uint32_t enclosed_length;
630
541
  uint64_t id;
631
542
  bool err;
632
543
 
635
546
 
636
547
  for (;;it.rewind())
637
548
  {
638
 
    if (thd->killed)
 
549
    if (session->killed)
639
550
    {
640
 
      thd->send_kill_message();
 
551
      session->send_kill_message();
641
552
      return(1);
642
553
    }
643
554
 
644
 
    restore_record(table, s->default_values);
 
555
    table->restoreRecordAsDefault();
645
556
 
646
557
    while ((item= it++))
647
558
    {
648
 
      uint length;
649
 
      uchar *pos;
 
559
      uint32_t length;
 
560
      unsigned char *pos;
650
561
      Item *real_item;
651
562
 
652
563
      if (read_info.read_field())
657
568
        continue;
658
569
 
659
570
      pos=read_info.row_start;
660
 
      length=(uint) (read_info.row_end-pos);
 
571
      length=(uint32_t) (read_info.row_end-pos);
661
572
 
662
573
      real_item= item->real_item();
663
574
 
671
582
          if (field->reset())
672
583
          {
673
584
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
674
 
                     thd->row_count);
 
585
                     session->row_count);
675
586
            return(1);
676
587
          }
677
588
          field->set_null();
727
638
    }
728
639
    if (item)
729
640
    {
730
 
      /* Have not read any field, thus input file is simply ended */
 
641
      /* Have not read any field, thus input cursor is simply ended */
731
642
      if (item == fields_vars.head())
732
643
        break;
733
644
      for (; item ; item= it++)
739
650
          if (field->reset())
740
651
          {
741
652
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
742
 
                     thd->row_count);
 
653
                     session->row_count);
743
654
            return(1);
744
655
          }
745
656
          if (!field->maybe_null() && field->type() == DRIZZLE_TYPE_TIMESTAMP)
747
658
          /*
748
659
            QQ: We probably should not throw warning for each field.
749
660
            But how about intention to always have the same number
750
 
            of warnings in THD::cuted_fields (and get rid of cuted_fields
 
661
            of warnings in Session::cuted_fields (and get rid of cuted_fields
751
662
            in the end ?)
752
663
          */
753
 
          thd->cuted_fields++;
754
 
          push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
664
          session->cuted_fields++;
 
665
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
755
666
                              ER_WARN_TOO_FEW_RECORDS,
756
 
                              ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
 
667
                              ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
757
668
        }
758
669
        else if (item->type() == Item::STRING_ITEM)
759
670
        {
768
679
      }
769
680
    }
770
681
 
771
 
    if (thd->killed ||
772
 
        fill_record(thd, set_fields, set_values,
 
682
    if (session->killed ||
 
683
        fill_record(session, set_fields, set_values,
773
684
                    ignore_check_option_errors))
774
685
      return(1);
775
686
 
776
 
    err= write_record(thd, table, &info);
 
687
    err= write_record(session, table, &info);
777
688
    table->auto_increment_field_not_null= false;
778
689
    if (err)
779
690
      return(1);
785
696
      break;
786
697
    if (read_info.line_cuted)
787
698
    {
788
 
      thd->cuted_fields++;                      /* To long row */
789
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 
790
 
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS), 
791
 
                          thd->row_count);   
792
 
      if (thd->killed)
 
699
      session->cuted_fields++;                  /* To long row */
 
700
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
701
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
 
702
                          session->row_count);
 
703
      if (session->killed)
793
704
        return(1);
794
705
    }
795
 
    thd->row_count++;
 
706
    session->row_count++;
796
707
  }
797
708
  return(test(read_info.error));
798
709
}
810
721
  case 'r': return '\r';
811
722
  case 'b': return '\b';
812
723
  case '0': return 0;                           // Ascii null
813
 
  case 'Z': return '\032';                      // Win32 end of file
 
724
  case 'Z': return '\032';                      // Win32 end of cursor
814
725
  case 'N': found_null=1;
815
726
 
816
727
    /* fall through */
825
736
*/
826
737
 
827
738
 
828
 
READ_INFO::READ_INFO(File file_par, uint tot_length, const CHARSET_INFO * const cs,
 
739
READ_INFO::READ_INFO(int file_par, size_t tot_length,
 
740
                     const CHARSET_INFO * const cs,
829
741
                     String &field_term, String &line_start, String &line_term,
830
 
                     String &enclosed_par, int escape, bool get_it_from_net,
831
 
                     bool is_fifo)
832
 
  :file(file_par),escape_char(escape)
 
742
                     String &enclosed_par, int escape, bool is_fifo)
 
743
  :cursor(file_par),escape_char(escape)
833
744
{
834
745
  read_charset= cs;
835
746
  field_term_ptr=(char*) field_term.ptr();
855
766
    line_term_ptr=(char*) "";
856
767
  }
857
768
  enclosed_char= (enclosed_length=enclosed_par.length()) ?
858
 
    (uchar) enclosed_par[0] : INT_MAX;
859
 
  field_term_char= field_term_length ? (uchar) field_term_ptr[0] : INT_MAX;
860
 
  line_term_char= line_term_length ? (uchar) line_term_ptr[0] : INT_MAX;
 
769
    (unsigned char) enclosed_par[0] : INT_MAX;
 
770
  field_term_char= field_term_length ? (unsigned char) field_term_ptr[0] : INT_MAX;
 
771
  line_term_char= line_term_length ? (unsigned char) line_term_ptr[0] : INT_MAX;
861
772
  error=eof=found_end_of_line=found_null=line_cuted=0;
862
773
  buff_length=tot_length;
863
774
 
864
775
 
865
776
  /* Set of a stack for unget if long terminators */
866
 
  uint length=max(field_term_length,line_term_length)+1;
 
777
  uint32_t length= max(field_term_length,line_term_length)+1;
867
778
  set_if_bigger(length,line_start.length());
868
 
  stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);
 
779
  stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
869
780
 
870
 
  if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0))))
871
 
    error=1; /* purecov: inspected */
 
781
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
 
782
    error=1;
872
783
  else
873
784
  {
874
785
    end_of_buff=buffer+buff_length;
875
 
    if (init_io_cache(&cache,(get_it_from_net) ? -1 : file, 0,
876
 
                      (get_it_from_net) ? READ_NET :
 
786
    if (init_io_cache(&cache,(false) ? -1 : cursor, 0,
 
787
                      (false) ? READ_NET :
877
788
                      (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
878
789
                      MYF(MY_WME)))
879
790
    {
880
 
      my_free((uchar*) buffer,MYF(0)); /* purecov: inspected */
 
791
      free((unsigned char*) buffer);
881
792
      error=1;
882
793
    }
883
794
    else
888
799
        manual assignment
889
800
      */
890
801
      need_end_io_cache = 1;
891
 
 
892
 
      if (get_it_from_net)
893
 
        cache.read_function = _my_b_net_read;
894
 
 
895
 
      if (mysql_bin_log.is_open())
896
 
        cache.pre_read = cache.pre_close =
897
 
          (IO_CACHE_CALLBACK) log_loaded_block;
898
802
    }
899
803
  }
900
804
}
906
810
  {
907
811
    if (need_end_io_cache)
908
812
      ::end_io_cache(&cache);
909
 
    my_free((uchar*) buffer,MYF(0));
 
813
    free(buffer);
910
814
    error=1;
911
815
  }
912
816
}
916
820
#define PUSH(A) *(stack_pos++)=(A)
917
821
 
918
822
 
919
 
inline int READ_INFO::terminator(char *ptr,uint length)
 
823
inline int READ_INFO::terminator(char *ptr,uint32_t length)
920
824
{
921
825
  int chr=0;                                    // Keep gcc happy
922
 
  uint i;
 
826
  uint32_t i;
923
827
  for (i=1 ; i < length ; i++)
924
828
  {
925
829
    if ((chr=GET) != *++ptr)
931
835
    return 1;
932
836
  PUSH(chr);
933
837
  while (i-- > 1)
934
 
    PUSH((uchar) *--ptr);
 
838
    PUSH((unsigned char) *--ptr);
935
839
  return 0;
936
840
}
937
841
 
939
843
int READ_INFO::read_field()
940
844
{
941
845
  int chr,found_enclosed_char;
942
 
  uchar *to,*new_buffer;
 
846
  unsigned char *to,*new_buffer;
943
847
 
944
848
  found_null=0;
945
849
  if (found_end_of_line)
962
866
  if (chr == enclosed_char)
963
867
  {
964
868
    found_enclosed_char=enclosed_char;
965
 
    *to++=(uchar) chr;                          // If error
 
869
    *to++=(unsigned char) chr;                          // If error
966
870
  }
967
871
  else
968
872
  {
975
879
    while ( to < end_of_buff)
976
880
    {
977
881
      chr = GET;
978
 
#ifdef USE_MB
979
882
      if ((my_mbcharlen(read_charset, chr) > 1) &&
980
883
          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
981
884
      {
982
 
          uchar* p = (uchar*)to;
983
 
          *to++ = chr;
984
 
          int ml = my_mbcharlen(read_charset, chr);
985
 
          int i;
986
 
          for (i=1; i<ml; i++) {
987
 
              chr = GET;
988
 
              if (chr == my_b_EOF)
989
 
                  goto found_eof;
990
 
              *to++ = chr;
991
 
          }
992
 
          if (my_ismbchar(read_charset,
993
 
                          (const char *)p,
994
 
                          (const char *)to))
995
 
            continue;
996
 
          for (i=0; i<ml; i++)
997
 
            PUSH((uchar) *--to);
998
 
          chr = GET;
 
885
        unsigned char* p = (unsigned char*)to;
 
886
        *to++ = chr;
 
887
        int ml = my_mbcharlen(read_charset, chr);
 
888
        int i;
 
889
        for (i=1; i<ml; i++) {
 
890
          chr = GET;
 
891
          if (chr == my_b_EOF)
 
892
            goto found_eof;
 
893
          *to++ = chr;
 
894
        }
 
895
        if (my_ismbchar(read_charset,
 
896
              (const char *)p,
 
897
              (const char *)to))
 
898
          continue;
 
899
        for (i=0; i<ml; i++)
 
900
          PUSH((unsigned char) *--to);
 
901
        chr = GET;
999
902
      }
1000
 
#endif
1001
903
      if (chr == my_b_EOF)
1002
 
        goto found_eof;
 
904
        goto found_eof;
1003
905
      if (chr == escape_char)
1004
906
      {
1005
 
        if ((chr=GET) == my_b_EOF)
1006
 
        {
1007
 
          *to++= (uchar) escape_char;
1008
 
          goto found_eof;
1009
 
        }
 
907
        if ((chr=GET) == my_b_EOF)
 
908
        {
 
909
          *to++= (unsigned char) escape_char;
 
910
          goto found_eof;
 
911
        }
1010
912
        /*
1011
913
          When escape_char == enclosed_char, we treat it like we do for
1012
914
          handling quotes in SQL parsing -- you can double-up the
1016
918
         */
1017
919
        if (escape_char != enclosed_char || chr == escape_char)
1018
920
        {
1019
 
          *to++ = (uchar) unescape((char) chr);
 
921
          *to++ = (unsigned char) unescape((char) chr);
1020
922
          continue;
1021
923
        }
1022
924
        PUSH(chr);
1025
927
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
1026
928
      if (chr == line_term_char)
1027
929
#else
1028
 
      if (chr == line_term_char && found_enclosed_char == INT_MAX)
 
930
        if (chr == line_term_char && found_enclosed_char == INT_MAX)
1029
931
#endif
1030
 
      {
1031
 
        if (terminator(line_term_ptr,line_term_length))
1032
 
        {                                       // Maybe unexpected linefeed
1033
 
          enclosed=0;
1034
 
          found_end_of_line=1;
1035
 
          row_start=buffer;
1036
 
          row_end=  to;
1037
 
          return 0;
1038
 
        }
1039
 
      }
 
932
        {
 
933
          if (terminator(line_term_ptr,line_term_length))
 
934
          {                                     // Maybe unexpected linefeed
 
935
            enclosed=0;
 
936
            found_end_of_line=1;
 
937
            row_start=buffer;
 
938
            row_end=  to;
 
939
            return 0;
 
940
          }
 
941
        }
1040
942
      if (chr == found_enclosed_char)
1041
943
      {
1042
 
        if ((chr=GET) == found_enclosed_char)
1043
 
        {                                       // Remove dupplicated
1044
 
          *to++ = (uchar) chr;
1045
 
          continue;
1046
 
        }
1047
 
        // End of enclosed field if followed by field_term or line_term
1048
 
        if (chr == my_b_EOF ||
1049
 
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
1050
 
        {                                       // Maybe unexpected linefeed
1051
 
          enclosed=1;
1052
 
          found_end_of_line=1;
1053
 
          row_start=buffer+1;
1054
 
          row_end=  to;
1055
 
          return 0;
1056
 
        }
1057
 
        if (chr == field_term_char &&
1058
 
            terminator(field_term_ptr,field_term_length))
1059
 
        {
1060
 
          enclosed=1;
1061
 
          row_start=buffer+1;
1062
 
          row_end=  to;
1063
 
          return 0;
1064
 
        }
1065
 
        /*
1066
 
          The string didn't terminate yet.
1067
 
          Store back next character for the loop
1068
 
        */
1069
 
        PUSH(chr);
1070
 
        /* copy the found term character to 'to' */
1071
 
        chr= found_enclosed_char;
 
944
        if ((chr=GET) == found_enclosed_char)
 
945
        {                                       // Remove dupplicated
 
946
          *to++ = (unsigned char) chr;
 
947
          continue;
 
948
        }
 
949
        // End of enclosed field if followed by field_term or line_term
 
950
        if (chr == my_b_EOF ||
 
951
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
 
952
        {                                       // Maybe unexpected linefeed
 
953
          enclosed=1;
 
954
          found_end_of_line=1;
 
955
          row_start=buffer+1;
 
956
          row_end=  to;
 
957
          return 0;
 
958
        }
 
959
        if (chr == field_term_char &&
 
960
            terminator(field_term_ptr,field_term_length))
 
961
        {
 
962
          enclosed=1;
 
963
          row_start=buffer+1;
 
964
          row_end=  to;
 
965
          return 0;
 
966
        }
 
967
        /*
 
968
           The string didn't terminate yet.
 
969
           Store back next character for the loop
 
970
         */
 
971
        PUSH(chr);
 
972
        /* copy the found term character to 'to' */
 
973
        chr= found_enclosed_char;
1072
974
      }
1073
975
      else if (chr == field_term_char && found_enclosed_char == INT_MAX)
1074
976
      {
1075
 
        if (terminator(field_term_ptr,field_term_length))
1076
 
        {
1077
 
          enclosed=0;
1078
 
          row_start=buffer;
1079
 
          row_end=  to;
1080
 
          return 0;
1081
 
        }
 
977
        if (terminator(field_term_ptr,field_term_length))
 
978
        {
 
979
          enclosed=0;
 
980
          row_start=buffer;
 
981
          row_end=  to;
 
982
          return 0;
 
983
        }
1082
984
      }
1083
 
      *to++ = (uchar) chr;
 
985
      *to++ = (unsigned char) chr;
1084
986
    }
1085
987
    /*
1086
 
    ** We come here if buffer is too small. Enlarge it and continue
1087
 
    */
1088
 
    if (!(new_buffer=(uchar*) my_realloc((char*) buffer,buff_length+1+IO_SIZE,
1089
 
                                        MYF(MY_WME))))
 
988
     ** We come here if buffer is too small. Enlarge it and continue
 
989
     */
 
990
    if (!(new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE)))
1090
991
      return (error=1);
1091
992
    to=new_buffer + (to-buffer);
1092
993
    buffer=new_buffer;
1107
1008
 
1108
1009
  NOTES
1109
1010
    The row may not be fixed size on disk if there are escape
1110
 
    characters in the file.
 
1011
    characters in the cursor.
1111
1012
 
1112
1013
  IMPLEMENTATION NOTE
1113
1014
    One can't use fixed length with multi-byte charset **
1120
1021
int READ_INFO::read_fixed_length()
1121
1022
{
1122
1023
  int chr;
1123
 
  uchar *to;
 
1024
  unsigned char *to;
1124
1025
  if (found_end_of_line)
1125
1026
    return 1;                                   // One have to call next_line
1126
1027
 
1140
1041
    {
1141
1042
      if ((chr=GET) == my_b_EOF)
1142
1043
      {
1143
 
        *to++= (uchar) escape_char;
 
1044
        *to++= (unsigned char) escape_char;
1144
1045
        goto found_eof;
1145
1046
      }
1146
 
      *to++ =(uchar) unescape((char) chr);
 
1047
      *to++ =(unsigned char) unescape((char) chr);
1147
1048
      continue;
1148
1049
    }
1149
1050
    if (chr == line_term_char)
1155
1056
        return 0;
1156
1057
      }
1157
1058
    }
1158
 
    *to++ = (uchar) chr;
 
1059
    *to++ = (unsigned char) chr;
1159
1060
  }
1160
1061
  row_end=to;                                   // Found full line
1161
1062
  return 0;
1183
1084
  for (;;)
1184
1085
  {
1185
1086
    int chr = GET;
1186
 
#ifdef USE_MB
1187
 
   if (my_mbcharlen(read_charset, chr) > 1)
1188
 
   {
1189
 
       for (uint i=1;
1190
 
            chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
1191
 
            i++)
1192
 
           chr = GET;
1193
 
       if (chr == escape_char)
1194
 
           continue;
1195
 
   }
1196
 
#endif
1197
 
   if (chr == my_b_EOF)
1198
 
   {
 
1087
    if (my_mbcharlen(read_charset, chr) > 1)
 
1088
    {
 
1089
      for (uint32_t i=1;
 
1090
          chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
 
1091
          i++)
 
1092
        chr = GET;
 
1093
      if (chr == escape_char)
 
1094
        continue;
 
1095
    }
 
1096
    if (chr == my_b_EOF)
 
1097
    {
1199
1098
      eof=1;
1200
1099
      return 1;
1201
1100
    }
1203
1102
    {
1204
1103
      line_cuted=1;
1205
1104
      if (GET == my_b_EOF)
1206
 
        return 1;
 
1105
        return 1;
1207
1106
      continue;
1208
1107
    }
1209
1108
    if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1233
1132
      PUSH(chr);
1234
1133
      while (--ptr != line_start_ptr)
1235
1134
      {                                         // Restart with next char
1236
 
        PUSH((uchar) *ptr);
 
1135
        PUSH((unsigned char) *ptr);
1237
1136
      }
1238
1137
      goto try_again;
1239
1138
    }