~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_load.cc

  • Committer: Monty Taylor
  • Date: 2009-03-20 04:49:49 UTC
  • mto: (950.1.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 958.
  • Revision ID: mordred@inaugust.com-20090320044949-nfx7ygyy89ojl6v5
RemovedĀ unusedĀ code.

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