~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_load.cc

  • Committer: Brian Aker
  • Date: 2010-02-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

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 std;
 
36
namespace drizzled
 
37
{
23
38
 
24
39
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 */
 
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 */
30
45
  char  *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
31
46
  uint  field_term_length,line_term_length,enclosed_length;
32
47
  int   field_term_char,line_term_char,enclosed_char,escape_char;
33
48
  int   *stack,*stack_pos;
34
49
  bool  found_end_of_line,start_of_line,eof;
35
50
  bool  need_end_io_cache;
36
 
  IO_CACHE cache;
37
 
  NET *io_net;
 
51
  internal::IO_CACHE cache;
38
52
 
39
53
public:
40
54
  bool error,line_cuted,found_null,enclosed;
41
 
  uchar *row_start,                     /* Found row starts here */
 
55
  unsigned char *row_start,                     /* Found row starts here */
42
56
        *row_end;                       /* Found row ends here */
43
57
  const CHARSET_INFO *read_charset;
44
58
 
45
 
  READ_INFO(File file,uint tot_length, const CHARSET_INFO * const cs,
 
59
  READ_INFO(int cursor, size_t tot_length, const CHARSET_INFO * const cs,
46
60
            String &field_term,String &line_start,String &line_term,
47
 
            String &enclosed,int escape,bool get_it_from_net, bool is_fifo);
 
61
            String &enclosed,int escape, bool is_fifo);
48
62
  ~READ_INFO();
49
63
  int read_field();
50
64
  int read_fixed_length(void);
51
65
  int next_line(void);
52
66
  char unescape(char chr);
53
 
  int terminator(char *ptr,uint length);
 
67
  int terminator(char *ptr,uint32_t length);
54
68
  bool find_start_of_fields();
55
69
 
56
70
  /*
59
73
  */
60
74
  void end_io_cache()
61
75
  {
62
 
    ::end_io_cache(&cache);
 
76
    internal::end_io_cache(&cache);
63
77
    need_end_io_cache = 0;
64
78
  }
65
79
 
66
80
  /*
67
81
    Either this method, or we need to make cache public
68
82
    Arg must be set from mysql_load() since constructor does not see
69
 
    either the table or THD value
 
83
    either the table or Session value
70
84
  */
71
85
  void set_io_cache_arg(void* arg) { cache.arg = arg; }
72
86
};
73
87
 
74
 
static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
88
static int read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
75
89
                             List<Item> &fields_vars, List<Item> &set_fields,
76
90
                             List<Item> &set_values, READ_INFO &read_info,
77
91
                             uint32_t skip_lines,
78
92
                             bool ignore_check_option_errors);
79
 
static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
93
static int read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
80
94
                          List<Item> &fields_vars, List<Item> &set_fields,
81
95
                          List<Item> &set_values, READ_INFO &read_info,
82
96
                          String &enclosed, uint32_t skip_lines,
83
97
                          bool ignore_check_option_errors);
84
98
 
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
99
 
90
100
/*
91
101
  Execute LOAD DATA query
92
102
 
93
103
  SYNOPSYS
94
104
    mysql_load()
95
 
      thd - current thread
96
 
      ex  - sql_exchange object representing source file and its parsing rules
 
105
      session - current thread
 
106
      ex  - file_exchange object representing source cursor and its parsing rules
97
107
      table_list  - list of tables to which we are loading data
98
108
      fields_vars - list of fields and variables to which we read
99
 
                    data from file
 
109
                    data from cursor
100
110
      set_fields  - list of fields mentioned in set clause
101
111
      set_values  - expressions to assign to fields in previous list
102
112
      handle_duplicates - indicates whenever we should emit error or
103
113
                          replace row if we will meet duplicates.
104
114
      ignore -          - indicates whenever we should ignore duplicates
105
 
      read_file_from_client - is this LOAD DATA LOCAL ?
106
115
 
107
116
  RETURN VALUES
108
117
    true - error / false - success
109
118
*/
110
119
 
111
 
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
 
120
int mysql_load(Session *session,file_exchange *ex,TableList *table_list,
112
121
                List<Item> &fields_vars, List<Item> &set_fields,
113
122
                List<Item> &set_values,
114
 
                enum enum_duplicates handle_duplicates, bool ignore,
115
 
                bool read_file_from_client)
 
123
                enum enum_duplicates handle_duplicates, bool ignore)
116
124
{
117
125
  char name[FN_REFLEN];
118
 
  File file;
119
 
  TABLE *table= NULL;
 
126
  int file;
 
127
  Table *table= NULL;
120
128
  int error;
121
129
  String *field_term=ex->field_term,*escaped=ex->escaped;
122
130
  String *enclosed=ex->enclosed;
123
131
  bool is_fifo=0;
124
 
  LOAD_FILE_INFO lf_info;
125
 
  char *db = table_list->db;                    // This is never null
 
132
  char *db= table_list->db;                     // This is never null
 
133
  assert(db);
126
134
  /*
127
 
    If path for file is not defined, we will use the current database.
 
135
    If path for cursor is not defined, we will use the current database.
128
136
    If this is not set, we will use the directory where the table to be
129
137
    loaded is located
130
138
  */
131
 
  char *tdb= thd->db ? thd->db : db;            // Result is never null
 
139
  const char *tdb= session->db.empty() ? db  : session->db.c_str();             // Result is never null
 
140
  assert(tdb);
132
141
  uint32_t skip_lines= ex->skip_lines;
133
142
  bool transactional_table;
134
 
  THD::killed_state killed_status= THD::NOT_KILLED;
 
143
  Session::killed_state killed_status= Session::NOT_KILLED;
135
144
 
136
 
  if (escaped->length() > 1 || enclosed->length() > 1)
 
145
  /* Escape and enclosed character may be a utf8 4-byte character */
 
146
  if (escaped->length() > 4 || enclosed->length() > 4)
137
147
  {
138
 
    my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
139
 
               MYF(0));
 
148
    my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
140
149
    return(true);
141
150
  }
142
 
  if (open_and_lock_tables(thd, table_list))
 
151
 
 
152
  if (session->openTablesLock(table_list))
143
153
    return(true);
144
 
  if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
145
 
                                    &thd->lex->select_lex.top_join_list,
 
154
 
 
155
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
 
156
                                    &session->lex->select_lex.top_join_list,
146
157
                                    table_list,
147
 
                                    &thd->lex->select_lex.leaf_tables, true))
 
158
                                    &session->lex->select_lex.leaf_tables, true))
148
159
     return(-1);
149
160
 
150
161
  /*
155
166
    table is marked to be 'used for insert' in which case we should never
156
167
    mark this table as 'const table' (ie, one that has only one row).
157
168
  */
158
 
  if (unique_table(thd, table_list, table_list->next_global, 0))
 
169
  if (unique_table(table_list, table_list->next_global))
159
170
  {
160
171
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
161
172
    return(true);
162
173
  }
163
174
 
164
175
  table= table_list->table;
165
 
  transactional_table= table->file->has_transactions();
 
176
  transactional_table= table->cursor->has_transactions();
166
177
 
167
178
  if (!fields_vars.elements)
168
179
  {
169
180
    Field **field;
170
181
    for (field=table->field; *field ; field++)
171
182
      fields_vars.push_back(new Item_field(*field));
172
 
    bitmap_set_all(table->write_set);
 
183
    table->setWriteSet();
173
184
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
174
185
    /*
175
186
      Let us also prepare SET clause, altough it is probably empty
176
187
      in this case.
177
188
    */
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))
 
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))
180
191
      return(true);
181
192
  }
182
193
  else
183
194
  {                                             // Part field list
184
195
    /* 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))
 
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))
188
199
      return(true);
189
200
    /*
190
201
      Check whenever TIMESTAMP field with auto-set feature specified
192
203
    */
193
204
    if (table->timestamp_field)
194
205
    {
195
 
      if (bitmap_is_set(table->write_set,
196
 
                        table->timestamp_field->field_index))
 
206
      if (table->isWriteSet(table->timestamp_field->field_index))
197
207
        table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
198
208
      else
199
209
      {
200
 
        bitmap_set_bit(table->write_set,
201
 
                       table->timestamp_field->field_index);
 
210
        table->setWriteSet(table->timestamp_field->field_index);
202
211
      }
203
212
    }
204
213
    /* Fix the expressions in SET clause */
205
 
    if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
 
214
    if (setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
206
215
      return(true);
207
216
  }
208
217
 
209
218
  table->mark_columns_needed_for_insert();
210
219
 
211
 
  uint tot_length=0;
 
220
  size_t tot_length=0;
212
221
  bool use_blobs= 0, use_vars= 0;
213
222
  List_iterator_fast<Item> it(fields_vars);
214
223
  Item *item;
243
252
    return(true);
244
253
  }
245
254
 
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
255
  {
257
256
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
258
257
    ex->file_name+=dirname_length(ex->file_name);
259
258
#endif
260
 
    if (!dirname_length(ex->file_name))
 
259
    if (!internal::dirname_length(ex->file_name))
261
260
    {
262
 
      strxnmov(name, FN_REFLEN-1, mysql_real_data_home, tdb, NullS);
263
 
      (void) fn_format(name, ex->file_name, name, "",
 
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, "",
264
264
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
265
265
    }
266
266
    else
267
267
    {
268
 
      (void) fn_format(name, ex->file_name, mysql_real_data_home, "",
 
268
      (void) internal::fn_format(name, ex->file_name, drizzle_real_data_home, "",
269
269
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
270
270
 
271
271
      if (opt_secure_file_priv &&
278
278
 
279
279
      struct stat stat_info;
280
280
      if (stat(name,&stat_info))
 
281
      {
 
282
        my_error(ER_FILE_NOT_FOUND, MYF(0), name, errno);
281
283
        return(true);
 
284
      }
282
285
 
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)))
 
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)))
289
291
      {
290
292
        my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
291
293
        return(true);
293
295
      if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
294
296
        is_fifo = 1;
295
297
    }
296
 
    if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
 
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);
297
301
      return(true);
 
302
    }
298
303
  }
299
304
 
300
305
  COPY_INFO info;
303
308
  info.handle_duplicates=handle_duplicates;
304
309
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
305
310
 
306
 
  READ_INFO read_info(file,tot_length,
307
 
                      ex->cs ? ex->cs : thd->variables.collation_database,
 
311
  READ_INFO read_info(file, tot_length,
 
312
                      ex->cs ? ex->cs : get_default_db_collation(session->db.c_str()),
308
313
                      *field_term,*ex->line_start, *ex->line_term, *enclosed,
309
 
                      info.escape_char, read_file_from_client, is_fifo);
 
314
                      info.escape_char, is_fifo);
310
315
  if (read_info.error)
311
316
  {
312
317
    if  (file >= 0)
313
 
      my_close(file,MYF(0));                    // no files in net reading
 
318
      internal::my_close(file,MYF(0));                  // no files in net reading
314
319
    return(true);                               // Can't allocate buffers
315
320
  }
316
321
 
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;
 
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;
328
332
  /* Skip lines if there is a line terminator */
329
333
  if (ex->line_term->length())
330
334
  {
343
347
    table->next_number_field=table->found_next_number_field;
344
348
    if (ignore ||
345
349
        handle_duplicates == DUP_REPLACE)
346
 
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
350
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
347
351
    if (handle_duplicates == DUP_REPLACE)
348
 
        table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
349
 
    table->file->ha_start_bulk_insert((ha_rows) 0);
 
352
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
353
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
350
354
    table->copy_blobs=1;
351
355
 
352
 
    thd->abort_on_warning= (!ignore &&
353
 
                            (thd->variables.sql_mode &
354
 
                             (MODE_STRICT_TRANS_TABLES |
355
 
                              MODE_STRICT_ALL_TABLES)));
 
356
    session->abort_on_warning= true;
356
357
 
357
358
    if (!field_term->length() && !enclosed->length())
358
 
      error= read_fixed_length(thd, info, table_list, fields_vars,
 
359
      error= read_fixed_length(session, info, table_list, fields_vars,
359
360
                               set_fields, set_values, read_info,
360
361
                               skip_lines, ignore);
361
362
    else
362
 
      error= read_sep_field(thd, info, table_list, fields_vars,
 
363
      error= read_sep_field(session, info, table_list, fields_vars,
363
364
                            set_fields, set_values, read_info,
364
365
                            *enclosed, skip_lines, ignore);
365
 
    if (table->file->ha_end_bulk_insert() && !error)
 
366
    if (table->cursor->ha_end_bulk_insert() && !error)
366
367
    {
367
 
      table->file->print_error(my_errno, MYF(0));
 
368
      table->print_error(errno, MYF(0));
368
369
      error= 1;
369
370
    }
370
 
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
371
 
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
371
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
372
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
372
373
    table->next_number_field=0;
373
374
  }
374
375
  if (file >= 0)
375
 
    my_close(file,MYF(0));
 
376
    internal::my_close(file,MYF(0));
376
377
  free_blobs(table);                            /* if pack_blob was used */
377
378
  table->copy_blobs=0;
378
 
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
379
 
  /* 
 
379
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
 
380
  /*
380
381
     simulated killing in the middle of per-row loop
381
382
     must be effective for binlogging
382
383
  */
383
 
  killed_status= (error == 0)? THD::NOT_KILLED : thd->killed;
 
384
  killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
384
385
  if (error)
385
386
  {
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
387
    error= -1;                          // Error on read
433
388
    goto err;
434
389
  }
435
390
  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
 
  }
 
391
          (uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
 
392
 
 
393
  if (session->transaction.stmt.modified_non_trans_table)
 
394
    session->transaction.all.modified_non_trans_table= true;
468
395
 
469
396
  /* ok to client sent only after binlog write and engine commit */
470
 
  my_ok(thd, info.copied + info.deleted, 0L, name);
 
397
  session->my_ok(info.copied + info.deleted, 0, 0L, name);
471
398
err:
472
399
  assert(transactional_table || !(info.copied || info.deleted) ||
473
 
              thd->transaction.stmt.modified_non_trans_table);
474
 
  table->file->ha_release_auto_increment();
 
400
              session->transaction.stmt.modified_non_trans_table);
 
401
  table->cursor->ha_release_auto_increment();
475
402
  table->auto_increment_field_not_null= false;
476
 
  thd->abort_on_warning= 0;
 
403
  session->abort_on_warning= 0;
477
404
  return(error);
478
405
}
479
406
 
480
407
 
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
408
/****************************************************************************
500
409
** Read of rows of fixed size + optional garage + optonal newline
501
410
****************************************************************************/
502
411
 
503
412
static int
504
 
read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
413
read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
505
414
                  List<Item> &fields_vars, List<Item> &set_fields,
506
415
                  List<Item> &set_values, READ_INFO &read_info,
507
416
                  uint32_t skip_lines, bool ignore_check_option_errors)
508
417
{
509
418
  List_iterator_fast<Item> it(fields_vars);
510
419
  Item_field *sql_field;
511
 
  TABLE *table= table_list->table;
 
420
  Table *table= table_list->table;
512
421
  uint64_t id;
513
422
  bool err;
514
423
 
515
424
  id= 0;
516
 
 
 
425
 
517
426
  while (!read_info.read_fixed_length())
518
427
  {
519
 
    if (thd->killed)
 
428
    if (session->killed)
520
429
    {
521
 
      thd->send_kill_message();
 
430
      session->send_kill_message();
522
431
      return(1);
523
432
    }
524
433
    if (skip_lines)
533
442
      continue;
534
443
    }
535
444
    it.rewind();
536
 
    uchar *pos=read_info.row_start;
 
445
    unsigned char *pos=read_info.row_start;
537
446
#ifdef HAVE_purify
538
447
    read_info.row_end[0]=0;
539
448
#endif
540
449
 
541
 
    restore_record(table, s->default_values);
 
450
    table->restoreRecordAsDefault();
542
451
    /*
543
452
      There is no variables in fields_vars list in this format so
544
453
      this conversion is safe.
545
454
    */
546
455
    while ((sql_field= (Item_field*) it++))
547
456
    {
548
 
      Field *field= sql_field->field;                  
 
457
      Field *field= sql_field->field;
549
458
      if (field == table->next_number_field)
550
459
        table->auto_increment_field_not_null= true;
551
460
      /*
557
466
 
558
467
      if (pos == read_info.row_end)
559
468
      {
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);
 
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);
564
473
        if (!field->maybe_null() && field->type() == DRIZZLE_TYPE_TIMESTAMP)
565
474
            ((Field_timestamp*) field)->set_time();
566
475
      }
567
476
      else
568
477
      {
569
 
        uint length;
570
 
        uchar save_chr;
571
 
        if ((length=(uint) (read_info.row_end-pos)) >
 
478
        uint32_t length;
 
479
        unsigned char save_chr;
 
480
        if ((length=(uint32_t) (read_info.row_end-pos)) >
572
481
            field->field_length)
 
482
        {
573
483
          length=field->field_length;
574
 
        save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc
 
484
        }
 
485
        save_chr=pos[length];
 
486
        pos[length]='\0'; // Add temp null terminator for store()
575
487
        field->store((char*) pos,length,read_info.read_charset);
576
488
        pos[length]=save_chr;
577
489
        if ((pos+=length) > read_info.row_end)
580
492
    }
581
493
    if (pos != read_info.row_end)
582
494
    {
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); 
 
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);
587
499
    }
588
500
 
589
 
    if (thd->killed ||
590
 
        fill_record(thd, set_fields, set_values,
 
501
    if (session->killed ||
 
502
        fill_record(session, set_fields, set_values,
591
503
                    ignore_check_option_errors))
592
504
      return(1);
593
505
 
594
 
    err= write_record(thd, table, &info);
 
506
    err= write_record(session, table, &info);
595
507
    table->auto_increment_field_not_null= false;
596
508
    if (err)
597
509
      return(1);
598
 
   
 
510
 
599
511
    /*
600
512
      We don't need to reset auto-increment field since we are restoring
601
513
      its default value at the beginning of each loop iteration.
604
516
      break;
605
517
    if (read_info.line_cuted)
606
518
    {
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); 
 
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);
611
523
    }
612
 
    thd->row_count++;
 
524
    session->row_count++;
613
525
  }
614
526
  return(test(read_info.error));
615
527
}
617
529
 
618
530
 
619
531
static int
620
 
read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
 
532
read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
621
533
               List<Item> &fields_vars, List<Item> &set_fields,
622
534
               List<Item> &set_values, READ_INFO &read_info,
623
535
               String &enclosed, uint32_t skip_lines,
625
537
{
626
538
  List_iterator_fast<Item> it(fields_vars);
627
539
  Item *item;
628
 
  TABLE *table= table_list->table;
629
 
  uint enclosed_length;
 
540
  Table *table= table_list->table;
 
541
  uint32_t enclosed_length;
630
542
  uint64_t id;
631
543
  bool err;
632
544
 
635
547
 
636
548
  for (;;it.rewind())
637
549
  {
638
 
    if (thd->killed)
 
550
    if (session->killed)
639
551
    {
640
 
      thd->send_kill_message();
 
552
      session->send_kill_message();
641
553
      return(1);
642
554
    }
643
555
 
644
 
    restore_record(table, s->default_values);
 
556
    table->restoreRecordAsDefault();
645
557
 
646
558
    while ((item= it++))
647
559
    {
648
 
      uint length;
649
 
      uchar *pos;
 
560
      uint32_t length;
 
561
      unsigned char *pos;
650
562
      Item *real_item;
651
563
 
652
564
      if (read_info.read_field())
657
569
        continue;
658
570
 
659
571
      pos=read_info.row_start;
660
 
      length=(uint) (read_info.row_end-pos);
 
572
      length=(uint32_t) (read_info.row_end-pos);
661
573
 
662
574
      real_item= item->real_item();
663
575
 
671
583
          if (field->reset())
672
584
          {
673
585
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
674
 
                     thd->row_count);
 
586
                     session->row_count);
675
587
            return(1);
676
588
          }
677
589
          field->set_null();
727
639
    }
728
640
    if (item)
729
641
    {
730
 
      /* Have not read any field, thus input file is simply ended */
 
642
      /* Have not read any field, thus input cursor is simply ended */
731
643
      if (item == fields_vars.head())
732
644
        break;
733
645
      for (; item ; item= it++)
739
651
          if (field->reset())
740
652
          {
741
653
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
742
 
                     thd->row_count);
 
654
                     session->row_count);
743
655
            return(1);
744
656
          }
745
657
          if (!field->maybe_null() && field->type() == DRIZZLE_TYPE_TIMESTAMP)
747
659
          /*
748
660
            QQ: We probably should not throw warning for each field.
749
661
            But how about intention to always have the same number
750
 
            of warnings in THD::cuted_fields (and get rid of cuted_fields
 
662
            of warnings in Session::cuted_fields (and get rid of cuted_fields
751
663
            in the end ?)
752
664
          */
753
 
          thd->cuted_fields++;
754
 
          push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
665
          session->cuted_fields++;
 
666
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
755
667
                              ER_WARN_TOO_FEW_RECORDS,
756
 
                              ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
 
668
                              ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
757
669
        }
758
670
        else if (item->type() == Item::STRING_ITEM)
759
671
        {
768
680
      }
769
681
    }
770
682
 
771
 
    if (thd->killed ||
772
 
        fill_record(thd, set_fields, set_values,
 
683
    if (session->killed ||
 
684
        fill_record(session, set_fields, set_values,
773
685
                    ignore_check_option_errors))
774
686
      return(1);
775
687
 
776
 
    err= write_record(thd, table, &info);
 
688
    err= write_record(session, table, &info);
777
689
    table->auto_increment_field_not_null= false;
778
690
    if (err)
779
691
      return(1);
785
697
      break;
786
698
    if (read_info.line_cuted)
787
699
    {
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)
 
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)
793
705
        return(1);
794
706
    }
795
 
    thd->row_count++;
 
707
    session->row_count++;
796
708
  }
797
709
  return(test(read_info.error));
798
710
}
810
722
  case 'r': return '\r';
811
723
  case 'b': return '\b';
812
724
  case '0': return 0;                           // Ascii null
813
 
  case 'Z': return '\032';                      // Win32 end of file
 
725
  case 'Z': return '\032';                      // Win32 end of cursor
814
726
  case 'N': found_null=1;
815
727
 
816
728
    /* fall through */
825
737
*/
826
738
 
827
739
 
828
 
READ_INFO::READ_INFO(File file_par, uint tot_length, const CHARSET_INFO * const cs,
 
740
READ_INFO::READ_INFO(int file_par, size_t tot_length,
 
741
                     const CHARSET_INFO * const cs,
829
742
                     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)
 
743
                     String &enclosed_par, int escape, bool is_fifo)
 
744
  :cursor(file_par),escape_char(escape)
833
745
{
834
746
  read_charset= cs;
835
747
  field_term_ptr=(char*) field_term.ptr();
855
767
    line_term_ptr=(char*) "";
856
768
  }
857
769
  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;
 
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;
861
773
  error=eof=found_end_of_line=found_null=line_cuted=0;
862
774
  buff_length=tot_length;
863
775
 
864
776
 
865
777
  /* Set of a stack for unget if long terminators */
866
 
  uint length=max(field_term_length,line_term_length)+1;
 
778
  uint32_t length= max(field_term_length,line_term_length)+1;
867
779
  set_if_bigger(length,line_start.length());
868
 
  stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);
 
780
  stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
869
781
 
870
 
  if (!(buffer=(uchar*) my_malloc(buff_length+1,MYF(0))))
871
 
    error=1; /* purecov: inspected */
 
782
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
 
783
    error=1;
872
784
  else
873
785
  {
874
786
    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 :
877
 
                      (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
 
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,
878
790
                      MYF(MY_WME)))
879
791
    {
880
 
      my_free((uchar*) buffer,MYF(0)); /* purecov: inspected */
 
792
      free((unsigned char*) buffer);
881
793
      error=1;
882
794
    }
883
795
    else
888
800
        manual assignment
889
801
      */
890
802
      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
803
    }
899
804
  }
900
805
}
905
810
  if (!error)
906
811
  {
907
812
    if (need_end_io_cache)
908
 
      ::end_io_cache(&cache);
909
 
    my_free((uchar*) buffer,MYF(0));
 
813
      internal::end_io_cache(&cache);
 
814
    free(buffer);
910
815
    error=1;
911
816
  }
912
817
}
916
821
#define PUSH(A) *(stack_pos++)=(A)
917
822
 
918
823
 
919
 
inline int READ_INFO::terminator(char *ptr,uint length)
 
824
inline int READ_INFO::terminator(char *ptr,uint32_t length)
920
825
{
921
826
  int chr=0;                                    // Keep gcc happy
922
 
  uint i;
 
827
  uint32_t i;
923
828
  for (i=1 ; i < length ; i++)
924
829
  {
925
830
    if ((chr=GET) != *++ptr)
931
836
    return 1;
932
837
  PUSH(chr);
933
838
  while (i-- > 1)
934
 
    PUSH((uchar) *--ptr);
 
839
    PUSH((unsigned char) *--ptr);
935
840
  return 0;
936
841
}
937
842
 
939
844
int READ_INFO::read_field()
940
845
{
941
846
  int chr,found_enclosed_char;
942
 
  uchar *to,*new_buffer;
 
847
  unsigned char *to,*new_buffer;
943
848
 
944
849
  found_null=0;
945
850
  if (found_end_of_line)
962
867
  if (chr == enclosed_char)
963
868
  {
964
869
    found_enclosed_char=enclosed_char;
965
 
    *to++=(uchar) chr;                          // If error
 
870
    *to++=(unsigned char) chr;                          // If error
966
871
  }
967
872
  else
968
873
  {
975
880
    while ( to < end_of_buff)
976
881
    {
977
882
      chr = GET;
978
 
#ifdef USE_MB
979
883
      if ((my_mbcharlen(read_charset, chr) > 1) &&
980
884
          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
981
885
      {
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;
 
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;
999
903
      }
1000
 
#endif
1001
904
      if (chr == my_b_EOF)
1002
 
        goto found_eof;
 
905
        goto found_eof;
1003
906
      if (chr == escape_char)
1004
907
      {
1005
 
        if ((chr=GET) == my_b_EOF)
1006
 
        {
1007
 
          *to++= (uchar) escape_char;
1008
 
          goto found_eof;
1009
 
        }
 
908
        if ((chr=GET) == my_b_EOF)
 
909
        {
 
910
          *to++= (unsigned char) escape_char;
 
911
          goto found_eof;
 
912
        }
1010
913
        /*
1011
914
          When escape_char == enclosed_char, we treat it like we do for
1012
915
          handling quotes in SQL parsing -- you can double-up the
1016
919
         */
1017
920
        if (escape_char != enclosed_char || chr == escape_char)
1018
921
        {
1019
 
          *to++ = (uchar) unescape((char) chr);
 
922
          *to++ = (unsigned char) unescape((char) chr);
1020
923
          continue;
1021
924
        }
1022
925
        PUSH(chr);
1025
928
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
1026
929
      if (chr == line_term_char)
1027
930
#else
1028
 
      if (chr == line_term_char && found_enclosed_char == INT_MAX)
 
931
        if (chr == line_term_char && found_enclosed_char == INT_MAX)
1029
932
#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
 
      }
 
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
        }
1040
943
      if (chr == found_enclosed_char)
1041
944
      {
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;
 
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;
1072
975
      }
1073
976
      else if (chr == field_term_char && found_enclosed_char == INT_MAX)
1074
977
      {
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
 
        }
 
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
        }
1082
985
      }
1083
 
      *to++ = (uchar) chr;
 
986
      *to++ = (unsigned char) chr;
1084
987
    }
1085
988
    /*
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))))
 
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)))
1090
992
      return (error=1);
1091
993
    to=new_buffer + (to-buffer);
1092
994
    buffer=new_buffer;
1107
1009
 
1108
1010
  NOTES
1109
1011
    The row may not be fixed size on disk if there are escape
1110
 
    characters in the file.
 
1012
    characters in the cursor.
1111
1013
 
1112
1014
  IMPLEMENTATION NOTE
1113
1015
    One can't use fixed length with multi-byte charset **
1120
1022
int READ_INFO::read_fixed_length()
1121
1023
{
1122
1024
  int chr;
1123
 
  uchar *to;
 
1025
  unsigned char *to;
1124
1026
  if (found_end_of_line)
1125
1027
    return 1;                                   // One have to call next_line
1126
1028
 
1140
1042
    {
1141
1043
      if ((chr=GET) == my_b_EOF)
1142
1044
      {
1143
 
        *to++= (uchar) escape_char;
 
1045
        *to++= (unsigned char) escape_char;
1144
1046
        goto found_eof;
1145
1047
      }
1146
 
      *to++ =(uchar) unescape((char) chr);
 
1048
      *to++ =(unsigned char) unescape((char) chr);
1147
1049
      continue;
1148
1050
    }
1149
1051
    if (chr == line_term_char)
1155
1057
        return 0;
1156
1058
      }
1157
1059
    }
1158
 
    *to++ = (uchar) chr;
 
1060
    *to++ = (unsigned char) chr;
1159
1061
  }
1160
1062
  row_end=to;                                   // Found full line
1161
1063
  return 0;
1183
1085
  for (;;)
1184
1086
  {
1185
1087
    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
 
   {
 
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
    {
1199
1099
      eof=1;
1200
1100
      return 1;
1201
1101
    }
1203
1103
    {
1204
1104
      line_cuted=1;
1205
1105
      if (GET == my_b_EOF)
1206
 
        return 1;
 
1106
        return 1;
1207
1107
      continue;
1208
1108
    }
1209
1109
    if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1233
1133
      PUSH(chr);
1234
1134
      while (--ptr != line_start_ptr)
1235
1135
      {                                         // Restart with next char
1236
 
        PUSH((uchar) *ptr);
 
1136
        PUSH((unsigned char) *ptr);
1237
1137
      }
1238
1138
      goto try_again;
1239
1139
    }
1242
1142
}
1243
1143
 
1244
1144
 
 
1145
} /* namespace drizzled */