~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_load.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:30 UTC
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063230-4brxsra0qsmsg84q
Added -Wunused-macros.

Show diffs side-by-side

added added

removed removed

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