~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_load.cc

  • Committer: Brian Aker
  • Date: 2009-05-06 06:19:18 UTC
  • mto: This revision was merged to the branch mainline in revision 1007.
  • Revision ID: brian@gaz-20090506061918-3p5x847pn9cdruog
Clean up final  code bits (from previous builds).

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"
 
19
#include <drizzled/server_includes.h>
20
20
#include <drizzled/sql_load.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/data_home.h>
23
23
#include <drizzled/session.h>
24
24
#include <drizzled/sql_base.h>
25
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
 
{
40
26
 
41
27
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 */
 
28
  File  file;
 
29
  unsigned char *buffer,                        /* Buffer for read text */
 
30
        *end_of_buff;                   /* Data in bufferts ends here */
 
31
  uint  buff_length,                    /* Length of buffert */
 
32
        max_length;                     /* Max length of row */
47
33
  char  *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
48
34
  uint  field_term_length,line_term_length,enclosed_length;
49
35
  int   field_term_char,line_term_char,enclosed_char,escape_char;
50
36
  int   *stack,*stack_pos;
51
37
  bool  found_end_of_line,start_of_line,eof;
52
38
  bool  need_end_io_cache;
53
 
  internal::IO_CACHE cache;
 
39
  IO_CACHE cache;
54
40
 
55
41
public:
56
42
  bool error,line_cuted,found_null,enclosed;
58
44
        *row_end;                       /* Found row ends here */
59
45
  const CHARSET_INFO *read_charset;
60
46
 
61
 
  READ_INFO(int cursor, size_t tot_length, const CHARSET_INFO * const cs,
 
47
  READ_INFO(File file,uint32_t tot_length, const CHARSET_INFO * const cs,
62
48
            String &field_term,String &line_start,String &line_term,
63
49
            String &enclosed,int escape, bool is_fifo);
64
50
  ~READ_INFO();
75
61
  */
76
62
  void end_io_cache()
77
63
  {
78
 
    cache.end_io_cache();
 
64
    ::end_io_cache(&cache);
79
65
    need_end_io_cache = 0;
80
66
  }
81
67
 
87
73
  void set_io_cache_arg(void* arg) { cache.arg = arg; }
88
74
};
89
75
 
90
 
static int read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
 
76
static int read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
91
77
                             List<Item> &fields_vars, List<Item> &set_fields,
92
78
                             List<Item> &set_values, READ_INFO &read_info,
93
79
                             uint32_t skip_lines,
94
80
                             bool ignore_check_option_errors);
95
 
static int read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
 
81
static int read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
96
82
                          List<Item> &fields_vars, List<Item> &set_fields,
97
83
                          List<Item> &set_values, READ_INFO &read_info,
98
84
                          String &enclosed, uint32_t skip_lines,
105
91
  SYNOPSYS
106
92
    mysql_load()
107
93
      session - current thread
108
 
      ex  - file_exchange object representing source cursor and its parsing rules
 
94
      ex  - file_exchange object representing source file and its parsing rules
109
95
      table_list  - list of tables to which we are loading data
110
96
      fields_vars - list of fields and variables to which we read
111
 
                    data from cursor
 
97
                    data from file
112
98
      set_fields  - list of fields mentioned in set clause
113
99
      set_values  - expressions to assign to fields in previous list
114
100
      handle_duplicates - indicates whenever we should emit error or
124
110
                List<Item> &set_values,
125
111
                enum enum_duplicates handle_duplicates, bool ignore)
126
112
{
127
 
  int file;
 
113
  char name[FN_REFLEN];
 
114
  File file;
128
115
  Table *table= NULL;
129
116
  int error;
130
117
  String *field_term=ex->field_term,*escaped=ex->escaped;
131
118
  String *enclosed=ex->enclosed;
132
119
  bool is_fifo=0;
133
 
 
134
 
  assert(table_list->getSchemaName()); // This should never be null
135
 
 
 
120
  char *db= table_list->db;                     // This is never null
 
121
  assert(db);
136
122
  /*
137
 
    If path for cursor is not defined, we will use the current database.
 
123
    If path for file is not defined, we will use the current database.
138
124
    If this is not set, we will use the directory where the table to be
139
125
    loaded is located
140
126
  */
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
 
127
  char *tdb= session->db ? session->db : db;            // Result is never null
143
128
  assert(tdb);
144
129
  uint32_t skip_lines= ex->skip_lines;
145
130
  bool transactional_table;
146
 
  Session::killed_state_t killed_status= Session::NOT_KILLED;
 
131
  Session::killed_state killed_status= Session::NOT_KILLED;
147
132
 
148
133
  /* Escape and enclosed character may be a utf8 4-byte character */
149
134
  if (escaped->length() > 4 || enclosed->length() > 4)
151
136
    my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
152
137
    return(true);
153
138
  }
154
 
 
155
 
  if (session->openTablesLock(table_list))
 
139
  if (open_and_lock_tables(session, table_list))
156
140
    return(true);
157
 
 
158
141
  if (setup_tables_and_check_access(session, &session->lex->select_lex.context,
159
142
                                    &session->lex->select_lex.top_join_list,
160
143
                                    table_list,
169
152
    table is marked to be 'used for insert' in which case we should never
170
153
    mark this table as 'const table' (ie, one that has only one row).
171
154
  */
172
 
  if (unique_table(table_list, table_list->next_global))
 
155
  if (unique_table(session, table_list, table_list->next_global, 0))
173
156
  {
174
 
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
 
157
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
175
158
    return(true);
176
159
  }
177
160
 
178
161
  table= table_list->table;
179
 
  transactional_table= table->cursor->has_transactions();
 
162
  transactional_table= table->file->has_transactions();
180
163
 
181
164
  if (!fields_vars.elements)
182
165
  {
183
166
    Field **field;
184
 
    for (field= table->getFields(); *field ; field++)
 
167
    for (field=table->field; *field ; field++)
185
168
      fields_vars.push_back(new Item_field(*field));
186
 
    table->setWriteSet();
 
169
    table->write_set->set();
187
170
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
188
171
    /*
189
172
      Let us also prepare SET clause, altough it is probably empty
206
189
    */
207
190
    if (table->timestamp_field)
208
191
    {
209
 
      if (table->isWriteSet(table->timestamp_field->position()))
210
 
      {
 
192
      if (table->write_set->test(table->timestamp_field->field_index))
211
193
        table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
212
 
      }
213
194
      else
214
195
      {
215
 
        table->setWriteSet(table->timestamp_field->position());
 
196
        table->write_set->set(table->timestamp_field->field_index);
216
197
      }
217
198
    }
218
199
    /* Fix the expressions in SET clause */
222
203
 
223
204
  table->mark_columns_needed_for_insert();
224
205
 
225
 
  size_t tot_length=0;
 
206
  uint32_t tot_length=0;
226
207
  bool use_blobs= 0, use_vars= 0;
227
208
  List_iterator_fast<Item> it(fields_vars);
228
209
  Item *item;
257
238
    return(true);
258
239
  }
259
240
 
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())
263
 
  {
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;
275
 
  }
276
 
  else
277
 
  {
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");
 
241
  {
 
242
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
 
243
    ex->file_name+=dirname_length(ex->file_name);
 
244
#endif
 
245
    if (!dirname_length(ex->file_name))
 
246
    {
 
247
      strcpy(name, drizzle_real_data_home);
 
248
      strncat(name, tdb, FN_REFLEN-strlen(drizzle_real_data_home)-1);
 
249
      (void) fn_format(name, ex->file_name, name, "",
 
250
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
 
251
    }
 
252
    else
 
253
    {
 
254
      (void) fn_format(name, ex->file_name, drizzle_real_data_home, "",
 
255
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
 
256
 
 
257
      if (opt_secure_file_priv &&
 
258
          strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
 
259
      {
 
260
        /* Read only allowed from within dir specified by secure_file_priv */
 
261
        my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
 
262
        return(true);
 
263
      }
 
264
 
 
265
      struct stat stat_info;
 
266
      if (stat(name,&stat_info))
 
267
      {
 
268
        my_error(ER_FILE_NOT_FOUND, MYF(0), name, errno);
 
269
        return(true);
 
270
      }
 
271
 
 
272
      // if we are not in slave thread, the file must be:
 
273
      if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
 
274
            (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
 
275
            ((stat_info.st_mode & S_IFREG) == S_IFREG ||
 
276
             (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
 
277
      {
 
278
        my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
 
279
        return(true);
 
280
      }
 
281
      if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
 
282
        is_fifo = 1;
 
283
    }
 
284
    if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
 
285
    {
 
286
      my_error(ER_CANT_OPEN_FILE, MYF(0), name, my_errno);
287
287
      return(true);
288
288
    }
289
289
  }
290
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;
 
291
  COPY_INFO info;
317
292
  memset(&info, 0, sizeof(info));
318
293
  info.ignore= ignore;
319
294
  info.handle_duplicates=handle_duplicates;
320
295
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
321
296
 
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,
 
297
  READ_INFO read_info(file,tot_length,
 
298
                      ex->cs ? ex->cs : session->variables.collation_database,
 
299
                      *field_term,*ex->line_start, *ex->line_term, *enclosed,
326
300
                      info.escape_char, is_fifo);
327
301
  if (read_info.error)
328
302
  {
329
303
    if  (file >= 0)
330
 
      internal::my_close(file,MYF(0));                  // no files in net reading
 
304
      my_close(file,MYF(0));                    // no files in net reading
331
305
    return(true);                               // Can't allocate buffers
332
306
  }
333
307
 
359
333
    table->next_number_field=table->found_next_number_field;
360
334
    if (ignore ||
361
335
        handle_duplicates == DUP_REPLACE)
362
 
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
336
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
363
337
    if (handle_duplicates == DUP_REPLACE)
364
 
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
365
 
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
338
        table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
339
    table->file->ha_start_bulk_insert((ha_rows) 0);
366
340
    table->copy_blobs=1;
367
341
 
368
342
    session->abort_on_warning= true;
375
349
      error= read_sep_field(session, info, table_list, fields_vars,
376
350
                            set_fields, set_values, read_info,
377
351
                            *enclosed, skip_lines, ignore);
378
 
    if (table->cursor->ha_end_bulk_insert() && !error)
 
352
    if (table->file->ha_end_bulk_insert() && !error)
379
353
    {
380
 
      table->print_error(errno, MYF(0));
 
354
      table->file->print_error(my_errno, MYF(0));
381
355
      error= 1;
382
356
    }
383
 
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
384
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
357
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
358
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
385
359
    table->next_number_field=0;
386
360
  }
387
361
  if (file >= 0)
388
 
    internal::my_close(file,MYF(0));
 
362
    my_close(file,MYF(0));
389
363
  free_blobs(table);                            /* if pack_blob was used */
390
364
  table->copy_blobs=0;
391
 
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
365
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
392
366
  /*
393
367
     simulated killing in the middle of per-row loop
394
368
     must be effective for binlogging
395
369
  */
396
 
  killed_status= (error == 0)? Session::NOT_KILLED : session->getKilled();
 
370
  killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
397
371
  if (error)
398
372
  {
399
373
    error= -1;                          // Error on read
400
374
    goto err;
401
375
  }
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();
 
376
  sprintf(name, ER(ER_LOAD_INFO), (uint32_t) info.records, (uint32_t) info.deleted,
 
377
          (uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
 
378
 
 
379
  if (session->transaction.stmt.modified_non_trans_table)
 
380
    session->transaction.all.modified_non_trans_table= true;
409
381
 
410
382
  /* ok to client sent only after binlog write and engine commit */
411
 
  session->my_ok(info.copied + info.deleted, 0, 0L, msg);
 
383
  session->my_ok(info.copied + info.deleted, 0L, name);
412
384
err:
413
385
  assert(transactional_table || !(info.copied || info.deleted) ||
414
 
              session->transaction.stmt.hasModifiedNonTransData());
415
 
  table->cursor->ha_release_auto_increment();
 
386
              session->transaction.stmt.modified_non_trans_table);
 
387
  table->file->ha_release_auto_increment();
416
388
  table->auto_increment_field_not_null= false;
417
389
  session->abort_on_warning= 0;
418
390
  return(error);
424
396
****************************************************************************/
425
397
 
426
398
static int
427
 
read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
 
399
read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
428
400
                  List<Item> &fields_vars, List<Item> &set_fields,
429
401
                  List<Item> &set_values, READ_INFO &read_info,
430
402
                  uint32_t skip_lines, bool ignore_check_option_errors)
439
411
 
440
412
  while (!read_info.read_fixed_length())
441
413
  {
442
 
    if (session->getKilled())
 
414
    if (session->killed)
443
415
    {
444
416
      session->send_kill_message();
445
417
      return(1);
457
429
    }
458
430
    it.rewind();
459
431
    unsigned char *pos=read_info.row_start;
460
 
#ifdef HAVE_VALGRIND
 
432
#ifdef HAVE_purify
461
433
    read_info.row_end[0]=0;
462
434
#endif
463
435
 
493
465
        unsigned char save_chr;
494
466
        if ((length=(uint32_t) (read_info.row_end-pos)) >
495
467
            field->field_length)
496
 
        {
497
468
          length=field->field_length;
498
 
        }
499
 
        save_chr=pos[length];
500
 
        pos[length]='\0'; // Add temp null terminator for store()
 
469
        save_chr=pos[length]; pos[length]='\0'; // Safeguard aganst malloc
501
470
        field->store((char*) pos,length,read_info.read_charset);
502
471
        pos[length]=save_chr;
503
472
        if ((pos+=length) > read_info.row_end)
512
481
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
513
482
    }
514
483
 
515
 
    if (session->getKilled() ||
 
484
    if (session->killed ||
516
485
        fill_record(session, set_fields, set_values,
517
486
                    ignore_check_option_errors))
518
487
      return(1);
543
512
 
544
513
 
545
514
static int
546
 
read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
 
515
read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
547
516
               List<Item> &fields_vars, List<Item> &set_fields,
548
517
               List<Item> &set_values, READ_INFO &read_info,
549
518
               String &enclosed, uint32_t skip_lines,
561
530
 
562
531
  for (;;it.rewind())
563
532
  {
564
 
    if (session->getKilled())
 
533
    if (session->killed)
565
534
    {
566
535
      session->send_kill_message();
567
536
      return(1);
653
622
    }
654
623
    if (item)
655
624
    {
656
 
      /* Have not read any field, thus input cursor is simply ended */
 
625
      /* Have not read any field, thus input file is simply ended */
657
626
      if (item == fields_vars.head())
658
627
        break;
659
628
      for (; item ; item= it++)
694
663
      }
695
664
    }
696
665
 
697
 
    if (session->getKilled() ||
 
666
    if (session->killed ||
698
667
        fill_record(session, set_fields, set_values,
699
668
                    ignore_check_option_errors))
700
669
      return(1);
715
684
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
716
685
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
717
686
                          session->row_count);
718
 
      if (session->getKilled())
 
687
      if (session->killed)
719
688
        return(1);
720
689
    }
721
690
    session->row_count++;
736
705
  case 'r': return '\r';
737
706
  case 'b': return '\b';
738
707
  case '0': return 0;                           // Ascii null
739
 
  case 'Z': return '\032';                      // Win32 end of cursor
 
708
  case 'Z': return '\032';                      // Win32 end of file
740
709
  case 'N': found_null=1;
741
710
 
742
711
    /* fall through */
751
720
*/
752
721
 
753
722
 
754
 
READ_INFO::READ_INFO(int file_par, size_t tot_length,
755
 
                     const CHARSET_INFO * const cs,
 
723
READ_INFO::READ_INFO(File file_par, uint32_t tot_length, const CHARSET_INFO * const cs,
756
724
                     String &field_term, String &line_start, String &line_term,
757
725
                     String &enclosed_par, int escape, bool is_fifo)
758
 
  :cursor(file_par),escape_char(escape)
 
726
  :file(file_par),escape_char(escape)
759
727
{
760
728
  read_charset= cs;
761
729
  field_term_ptr=(char*) field_term.ptr();
789
757
 
790
758
 
791
759
  /* 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);
 
760
  uint32_t length=cmax(field_term_length,line_term_length)+1;
 
761
  set_if_bigger(length,line_start.length());
 
762
  stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);
795
763
 
796
 
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
797
 
    error=1;
 
764
  if (!(buffer=(unsigned char*) malloc(buff_length+1)))
 
765
    error=1; /* purecov: inspected */
798
766
  else
799
767
  {
800
768
    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)))
 
769
    if (init_io_cache(&cache,(false) ? -1 : file, 0,
 
770
                      (false) ? READ_NET :
 
771
                      (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
 
772
                      MYF(MY_WME)))
805
773
    {
806
 
      free((unsigned char*) buffer);
 
774
      free((unsigned char*) buffer); /* purecov: inspected */
807
775
      error=1;
808
776
    }
809
777
    else
824
792
  if (!error)
825
793
  {
826
794
    if (need_end_io_cache)
827
 
      cache.end_io_cache();
828
 
    free(buffer);
 
795
      ::end_io_cache(&cache);
 
796
    free((unsigned char*) buffer);
829
797
    error=1;
830
798
  }
831
799
}
894
862
    while ( to < end_of_buff)
895
863
    {
896
864
      chr = GET;
 
865
#ifdef USE_MB
897
866
      if ((my_mbcharlen(read_charset, chr) > 1) &&
898
867
          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
899
868
      {
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;
 
869
          unsigned char* p = (unsigned char*)to;
 
870
          *to++ = chr;
 
871
          int ml = my_mbcharlen(read_charset, chr);
 
872
          int i;
 
873
          for (i=1; i<ml; i++) {
 
874
              chr = GET;
 
875
              if (chr == my_b_EOF)
 
876
                  goto found_eof;
 
877
              *to++ = chr;
 
878
          }
 
879
          if (my_ismbchar(read_charset,
 
880
                          (const char *)p,
 
881
                          (const char *)to))
 
882
            continue;
 
883
          for (i=0; i<ml; i++)
 
884
            PUSH((unsigned char) *--to);
 
885
          chr = GET;
917
886
      }
 
887
#endif
918
888
      if (chr == my_b_EOF)
919
 
        goto found_eof;
 
889
        goto found_eof;
920
890
      if (chr == escape_char)
921
891
      {
922
 
        if ((chr=GET) == my_b_EOF)
923
 
        {
924
 
          *to++= (unsigned char) escape_char;
925
 
          goto found_eof;
926
 
        }
 
892
        if ((chr=GET) == my_b_EOF)
 
893
        {
 
894
          *to++= (unsigned char) escape_char;
 
895
          goto found_eof;
 
896
        }
927
897
        /*
928
898
          When escape_char == enclosed_char, we treat it like we do for
929
899
          handling quotes in SQL parsing -- you can double-up the
942
912
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
943
913
      if (chr == line_term_char)
944
914
#else
945
 
        if (chr == line_term_char && found_enclosed_char == INT_MAX)
 
915
      if (chr == line_term_char && found_enclosed_char == INT_MAX)
946
916
#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
 
        }
 
917
      {
 
918
        if (terminator(line_term_ptr,line_term_length))
 
919
        {                                       // Maybe unexpected linefeed
 
920
          enclosed=0;
 
921
          found_end_of_line=1;
 
922
          row_start=buffer;
 
923
          row_end=  to;
 
924
          return 0;
 
925
        }
 
926
      }
957
927
      if (chr == found_enclosed_char)
958
928
      {
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;
 
929
        if ((chr=GET) == found_enclosed_char)
 
930
        {                                       // Remove dupplicated
 
931
          *to++ = (unsigned char) chr;
 
932
          continue;
 
933
        }
 
934
        // End of enclosed field if followed by field_term or line_term
 
935
        if (chr == my_b_EOF ||
 
936
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
 
937
        {                                       // Maybe unexpected linefeed
 
938
          enclosed=1;
 
939
          found_end_of_line=1;
 
940
          row_start=buffer+1;
 
941
          row_end=  to;
 
942
          return 0;
 
943
        }
 
944
        if (chr == field_term_char &&
 
945
            terminator(field_term_ptr,field_term_length))
 
946
        {
 
947
          enclosed=1;
 
948
          row_start=buffer+1;
 
949
          row_end=  to;
 
950
          return 0;
 
951
        }
 
952
        /*
 
953
          The string didn't terminate yet.
 
954
          Store back next character for the loop
 
955
        */
 
956
        PUSH(chr);
 
957
        /* copy the found term character to 'to' */
 
958
        chr= found_enclosed_char;
989
959
      }
990
960
      else if (chr == field_term_char && found_enclosed_char == INT_MAX)
991
961
      {
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
 
        }
 
962
        if (terminator(field_term_ptr,field_term_length))
 
963
        {
 
964
          enclosed=0;
 
965
          row_start=buffer;
 
966
          row_end=  to;
 
967
          return 0;
 
968
        }
999
969
      }
1000
970
      *to++ = (unsigned char) chr;
1001
971
    }
1002
972
    /*
1003
 
     ** We come here if buffer is too small. Enlarge it and continue
1004
 
     */
 
973
    ** We come here if buffer is too small. Enlarge it and continue
 
974
    */
1005
975
    if (!(new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE)))
1006
976
      return (error=1);
1007
977
    to=new_buffer + (to-buffer);
1023
993
 
1024
994
  NOTES
1025
995
    The row may not be fixed size on disk if there are escape
1026
 
    characters in the cursor.
 
996
    characters in the file.
1027
997
 
1028
998
  IMPLEMENTATION NOTE
1029
999
    One can't use fixed length with multi-byte charset **
1099
1069
  for (;;)
1100
1070
  {
1101
1071
    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
 
    {
 
1072
#ifdef USE_MB
 
1073
   if (my_mbcharlen(read_charset, chr) > 1)
 
1074
   {
 
1075
       for (uint32_t i=1;
 
1076
            chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
 
1077
            i++)
 
1078
           chr = GET;
 
1079
       if (chr == escape_char)
 
1080
           continue;
 
1081
   }
 
1082
#endif
 
1083
   if (chr == my_b_EOF)
 
1084
   {
1113
1085
      eof=1;
1114
1086
      return 1;
1115
1087
    }
1117
1089
    {
1118
1090
      line_cuted=1;
1119
1091
      if (GET == my_b_EOF)
1120
 
        return 1;
 
1092
        return 1;
1121
1093
      continue;
1122
1094
    }
1123
1095
    if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1156
1128
}
1157
1129
 
1158
1130
 
1159
 
} /* namespace drizzled */