~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_load.cc

Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/* Copy data from a textfile to table */
18
18
 
19
 
#include <drizzled/server_includes.h>
 
19
#include "config.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>
26
29
 
 
30
#include <sys/stat.h>
 
31
#include <fcntl.h>
27
32
#include <algorithm>
 
33
#include <climits>
28
34
 
29
35
using namespace std;
 
36
namespace drizzled
 
37
{
30
38
 
31
39
class READ_INFO {
32
 
  File  file;
 
40
  int   cursor;
33
41
  unsigned char *buffer;                /* Buffer for read text */
34
42
  unsigned char *end_of_buff;           /* Data in bufferts ends here */
35
43
  size_t buff_length;                   /* Length of buffert */
40
48
  int   *stack,*stack_pos;
41
49
  bool  found_end_of_line,start_of_line,eof;
42
50
  bool  need_end_io_cache;
43
 
  IO_CACHE cache;
 
51
  internal::IO_CACHE cache;
44
52
 
45
53
public:
46
54
  bool error,line_cuted,found_null,enclosed;
48
56
        *row_end;                       /* Found row ends here */
49
57
  const CHARSET_INFO *read_charset;
50
58
 
51
 
  READ_INFO(File file, size_t tot_length, const CHARSET_INFO * const cs,
 
59
  READ_INFO(int cursor, size_t tot_length, const CHARSET_INFO * const cs,
52
60
            String &field_term,String &line_start,String &line_term,
53
61
            String &enclosed,int escape, bool is_fifo);
54
62
  ~READ_INFO();
65
73
  */
66
74
  void end_io_cache()
67
75
  {
68
 
    ::end_io_cache(&cache);
 
76
    internal::end_io_cache(&cache);
69
77
    need_end_io_cache = 0;
70
78
  }
71
79
 
95
103
  SYNOPSYS
96
104
    mysql_load()
97
105
      session - current thread
98
 
      ex  - file_exchange object representing source file and its parsing rules
 
106
      ex  - file_exchange object representing source cursor and its parsing rules
99
107
      table_list  - list of tables to which we are loading data
100
108
      fields_vars - list of fields and variables to which we read
101
 
                    data from file
 
109
                    data from cursor
102
110
      set_fields  - list of fields mentioned in set clause
103
111
      set_values  - expressions to assign to fields in previous list
104
112
      handle_duplicates - indicates whenever we should emit error or
115
123
                enum enum_duplicates handle_duplicates, bool ignore)
116
124
{
117
125
  char name[FN_REFLEN];
118
 
  File file;
 
126
  int file;
119
127
  Table *table= NULL;
120
128
  int error;
121
129
  String *field_term=ex->field_term,*escaped=ex->escaped;
124
132
  char *db= table_list->db;                     // This is never null
125
133
  assert(db);
126
134
  /*
127
 
    If path for file is not defined, we will use the current database.
 
135
    If path for cursor is not defined, we will use the current database.
128
136
    If this is not set, we will use the directory where the table to be
129
137
    loaded is located
130
138
  */
131
 
  char *tdb= session->db ? session->db : db;            // Result is never null
 
139
  const char *tdb= session->db.empty() ? db  : session->db.c_str();             // Result is never null
132
140
  assert(tdb);
133
141
  uint32_t skip_lines= ex->skip_lines;
134
142
  bool transactional_table;
158
166
    table is marked to be 'used for insert' in which case we should never
159
167
    mark this table as 'const table' (ie, one that has only one row).
160
168
  */
161
 
  if (unique_table(session, table_list, table_list->next_global, 0))
 
169
  if (unique_table(table_list, table_list->next_global))
162
170
  {
163
171
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
164
172
    return(true);
165
173
  }
166
174
 
167
175
  table= table_list->table;
168
 
  transactional_table= table->file->has_transactions();
 
176
  transactional_table= table->cursor->has_transactions();
169
177
 
170
178
  if (!fields_vars.elements)
171
179
  {
248
256
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
249
257
    ex->file_name+=dirname_length(ex->file_name);
250
258
#endif
251
 
    if (!dirname_length(ex->file_name))
 
259
    if (!internal::dirname_length(ex->file_name))
252
260
    {
253
261
      strcpy(name, drizzle_real_data_home);
254
262
      strncat(name, tdb, FN_REFLEN-strlen(drizzle_real_data_home)-1);
255
 
      (void) fn_format(name, ex->file_name, name, "",
 
263
      (void) internal::fn_format(name, ex->file_name, name, "",
256
264
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
257
265
    }
258
266
    else
259
267
    {
260
 
      (void) fn_format(name, ex->file_name, drizzle_real_data_home, "",
 
268
      (void) internal::fn_format(name, ex->file_name, drizzle_real_data_home, "",
261
269
                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
262
270
 
263
271
      if (opt_secure_file_priv &&
275
283
        return(true);
276
284
      }
277
285
 
278
 
      // if we are not in slave thread, the file must be:
 
286
      // if we are not in slave thread, the cursor must be:
279
287
      if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
280
288
            (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
281
289
            ((stat_info.st_mode & S_IFREG) == S_IFREG ||
287
295
      if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
288
296
        is_fifo = 1;
289
297
    }
290
 
    if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
 
298
    if ((file=internal::my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
291
299
    {
292
 
      my_error(ER_CANT_OPEN_FILE, MYF(0), name, my_errno);
 
300
      my_error(ER_CANT_OPEN_FILE, MYF(0), name, errno);
293
301
      return(true);
294
302
    }
295
303
  }
301
309
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
302
310
 
303
311
  READ_INFO read_info(file, tot_length,
304
 
                      ex->cs ? ex->cs : get_default_db_collation(session->db),
 
312
                      ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(session->db.c_str()),
305
313
                      *field_term,*ex->line_start, *ex->line_term, *enclosed,
306
314
                      info.escape_char, is_fifo);
307
315
  if (read_info.error)
308
316
  {
309
317
    if  (file >= 0)
310
 
      my_close(file,MYF(0));                    // no files in net reading
 
318
      internal::my_close(file,MYF(0));                  // no files in net reading
311
319
    return(true);                               // Can't allocate buffers
312
320
  }
313
321
 
339
347
    table->next_number_field=table->found_next_number_field;
340
348
    if (ignore ||
341
349
        handle_duplicates == DUP_REPLACE)
342
 
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
350
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
343
351
    if (handle_duplicates == DUP_REPLACE)
344
 
        table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
345
 
    table->file->ha_start_bulk_insert((ha_rows) 0);
 
352
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
353
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
346
354
    table->copy_blobs=1;
347
355
 
348
356
    session->abort_on_warning= true;
355
363
      error= read_sep_field(session, info, table_list, fields_vars,
356
364
                            set_fields, set_values, read_info,
357
365
                            *enclosed, skip_lines, ignore);
358
 
    if (table->file->ha_end_bulk_insert() && !error)
 
366
    if (table->cursor->ha_end_bulk_insert() && !error)
359
367
    {
360
 
      table->file->print_error(my_errno, MYF(0));
 
368
      table->print_error(errno, MYF(0));
361
369
      error= 1;
362
370
    }
363
 
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
364
 
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
371
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
372
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
365
373
    table->next_number_field=0;
366
374
  }
367
375
  if (file >= 0)
368
 
    my_close(file,MYF(0));
 
376
    internal::my_close(file,MYF(0));
369
377
  free_blobs(table);                            /* if pack_blob was used */
370
378
  table->copy_blobs=0;
371
379
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
382
390
  sprintf(name, ER(ER_LOAD_INFO), (uint32_t) info.records, (uint32_t) info.deleted,
383
391
          (uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
384
392
 
385
 
  if (session->transaction.stmt.modified_non_trans_table)
386
 
    session->transaction.all.modified_non_trans_table= true;
 
393
  if (session->transaction.stmt.hasModifiedNonTransData())
 
394
    session->transaction.all.markModifiedNonTransData();
387
395
 
388
396
  /* ok to client sent only after binlog write and engine commit */
389
397
  session->my_ok(info.copied + info.deleted, 0, 0L, name);
390
398
err:
391
399
  assert(transactional_table || !(info.copied || info.deleted) ||
392
 
              session->transaction.stmt.modified_non_trans_table);
393
 
  table->file->ha_release_auto_increment();
 
400
              session->transaction.stmt.hasModifiedNonTransData());
 
401
  table->cursor->ha_release_auto_increment();
394
402
  table->auto_increment_field_not_null= false;
395
403
  session->abort_on_warning= 0;
396
404
  return(error);
631
639
    }
632
640
    if (item)
633
641
    {
634
 
      /* Have not read any field, thus input file is simply ended */
 
642
      /* Have not read any field, thus input cursor is simply ended */
635
643
      if (item == fields_vars.head())
636
644
        break;
637
645
      for (; item ; item= it++)
714
722
  case 'r': return '\r';
715
723
  case 'b': return '\b';
716
724
  case '0': return 0;                           // Ascii null
717
 
  case 'Z': return '\032';                      // Win32 end of file
 
725
  case 'Z': return '\032';                      // Win32 end of cursor
718
726
  case 'N': found_null=1;
719
727
 
720
728
    /* fall through */
729
737
*/
730
738
 
731
739
 
732
 
READ_INFO::READ_INFO(File file_par, size_t tot_length,
 
740
READ_INFO::READ_INFO(int file_par, size_t tot_length,
733
741
                     const CHARSET_INFO * const cs,
734
742
                     String &field_term, String &line_start, String &line_term,
735
743
                     String &enclosed_par, int escape, bool is_fifo)
736
 
  :file(file_par),escape_char(escape)
 
744
  :cursor(file_par),escape_char(escape)
737
745
{
738
746
  read_charset= cs;
739
747
  field_term_ptr=(char*) field_term.ptr();
769
777
  /* Set of a stack for unget if long terminators */
770
778
  uint32_t length= max(field_term_length,line_term_length)+1;
771
779
  set_if_bigger(length,line_start.length());
772
 
  stack= stack_pos= (int*) sql_alloc(sizeof(int)*length);
 
780
  stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
773
781
 
774
782
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
775
 
    error=1; /* purecov: inspected */
 
783
    error=1;
776
784
  else
777
785
  {
778
786
    end_of_buff=buffer+buff_length;
779
 
    if (init_io_cache(&cache,(false) ? -1 : file, 0,
780
 
                      (false) ? READ_NET :
781
 
                      (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
 
787
    if (init_io_cache(&cache,(false) ? -1 : cursor, 0,
 
788
                      (false) ? internal::READ_NET :
 
789
                      (is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
782
790
                      MYF(MY_WME)))
783
791
    {
784
 
      free((unsigned char*) buffer); /* purecov: inspected */
 
792
      free((unsigned char*) buffer);
785
793
      error=1;
786
794
    }
787
795
    else
802
810
  if (!error)
803
811
  {
804
812
    if (need_end_io_cache)
805
 
      ::end_io_cache(&cache);
 
813
      internal::end_io_cache(&cache);
806
814
    free(buffer);
807
815
    error=1;
808
816
  }
1001
1009
 
1002
1010
  NOTES
1003
1011
    The row may not be fixed size on disk if there are escape
1004
 
    characters in the file.
 
1012
    characters in the cursor.
1005
1013
 
1006
1014
  IMPLEMENTATION NOTE
1007
1015
    One can't use fixed length with multi-byte charset **
1134
1142
}
1135
1143
 
1136
1144
 
 
1145
} /* namespace drizzled */