~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
16
17
/* Copy data from a textfile to table */
18
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
19
#include <config.h>
2148.7.12 by Brian Aker
Merge in header fixes.
20
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
21
#include <drizzled/sql_load.h>
549 by Monty Taylor
Took gettext.h out of header files.
22
#include <drizzled/error.h>
520.6.7 by Monty Taylor
Moved a bunch of crap out of common_includes.
23
#include <drizzled/data_home.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
24
#include <drizzled/session.h>
25
#include <drizzled/sql_base.h>
1999.4.9 by Brian Aker
Created EPOCH
26
#include <drizzled/field/epoch.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
27
#include <drizzled/internal/my_sys.h>
28
#include <drizzled/internal/iocache.h>
29
#include <drizzled/plugin/storage_engine.h>
2234.1.4 by Olaf van der Spek
Refactor includes
30
#include <drizzled/sql_lex.h>
2239.1.1 by Olaf van der Spek
Refactor includes
31
#include <drizzled/copy_info.h>
32
#include <drizzled/file_exchange.h>
2239.1.9 by Olaf van der Spek
Refactor includes
33
#include <drizzled/util/test.h>
2241.3.4 by Olaf van der Spek
Refactor Session::transaction
34
#include <drizzled/session/transactions.h>
1 by brian
clean slate
35
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
36
#include <sys/stat.h>
37
#include <fcntl.h>
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
38
#include <algorithm>
1241.9.24 by Monty Taylor
Removed m_string.h from server_includes.h.
39
#include <climits>
1786.3.2 by Monty Taylor
Cleaned up the initial pass at this. It's not perfect, but it does work.
40
#include <boost/filesystem.hpp>
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
41
1786.3.2 by Monty Taylor
Cleaned up the initial pass at this. It's not perfect, but it does work.
42
namespace fs=boost::filesystem;
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
43
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
44
namespace drizzled
45
{
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
46
1 by brian
clean slate
47
class READ_INFO {
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
48
  int	cursor;
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
49
  unsigned char	*buffer;                /* Buffer for read text */
50
  unsigned char *end_of_buff;           /* Data in bufferts ends here */
51
  size_t buff_length;                   /* Length of buffert */
52
  size_t max_length;                    /* Max length of row */
1 by brian
clean slate
53
  char	*field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
54
  uint	field_term_length,line_term_length,enclosed_length;
55
  int	field_term_char,line_term_char,enclosed_char,escape_char;
56
  int	*stack,*stack_pos;
57
  bool	found_end_of_line,start_of_line,eof;
58
  bool  need_end_io_cache;
2296.1.1 by Mark Atwood
Merge in Fixes of Brian's IOCACHE.
59
  internal::io_cache_st cache;
1 by brian
clean slate
60
61
public:
62
  bool error,line_cuted,found_null,enclosed;
481 by Brian Aker
Remove all of uchar.
63
  unsigned char	*row_start,			/* Found row starts here */
1 by brian
clean slate
64
	*row_end;			/* Found row ends here */
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
65
  const charset_info_st *read_charset;
1 by brian
clean slate
66
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
67
  READ_INFO(int cursor, size_t tot_length, const charset_info_st * const cs,
1 by brian
clean slate
68
	    String &field_term,String &line_start,String &line_term,
919.1.2 by Brian Aker
Comitting the removal of server code for LOAD DATA "LOCAL" INFILE
69
	    String &enclosed,int escape, bool is_fifo);
1 by brian
clean slate
70
  ~READ_INFO();
71
  int read_field();
72
  int read_fixed_length(void);
73
  int next_line(void);
74
  char unescape(char chr);
482 by Brian Aker
Remove uint.
75
  int terminator(char *ptr,uint32_t length);
1 by brian
clean slate
76
  bool find_start_of_fields();
77
78
  /*
79
    We need to force cache close before destructor is invoked to log
80
    the last read block
81
  */
82
  void end_io_cache()
83
  {
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
84
    cache.end_io_cache();
1 by brian
clean slate
85
    need_end_io_cache = 0;
86
  }
87
88
  /*
89
    Either this method, or we need to make cache public
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
90
    Arg must be set from load() since constructor does not see
520.1.21 by Brian Aker
THD -> Session rename
91
    either the table or Session value
1 by brian
clean slate
92
  */
93
  void set_io_cache_arg(void* arg) { cache.arg = arg; }
94
};
95
1711.6.1 by Brian Aker
Style on structure cleanup
96
static int read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
97
                             List<Item> &fields_vars, List<Item> &set_fields,
98
                             List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
99
			     uint32_t skip_lines,
1 by brian
clean slate
100
			     bool ignore_check_option_errors);
1711.6.1 by Brian Aker
Style on structure cleanup
101
static int read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
102
                          List<Item> &fields_vars, List<Item> &set_fields,
103
                          List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
104
			  String &enclosed, uint32_t skip_lines,
1 by brian
clean slate
105
			  bool ignore_check_option_errors);
106
107
108
/*
109
  Execute LOAD DATA query
110
111
  SYNOPSYS
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
112
    load()
520.1.22 by Brian Aker
Second pass of thd cleanup
113
      session - current thread
1208.3.2 by brian
Update for Cursor renaming.
114
      ex  - file_exchange object representing source cursor and its parsing rules
1 by brian
clean slate
115
      table_list  - list of tables to which we are loading data
116
      fields_vars - list of fields and variables to which we read
1208.3.2 by brian
Update for Cursor renaming.
117
                    data from cursor
1 by brian
clean slate
118
      set_fields  - list of fields mentioned in set clause
119
      set_values  - expressions to assign to fields in previous list
120
      handle_duplicates - indicates whenever we should emit error or
121
                          replace row if we will meet duplicates.
122
      ignore -          - indicates whenever we should ignore duplicates
123
124
  RETURN VALUES
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
125
    true - error / false - success
1 by brian
clean slate
126
*/
127
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
128
int load(Session *session,file_exchange *ex,TableList *table_list,
1 by brian
clean slate
129
	        List<Item> &fields_vars, List<Item> &set_fields,
130
                List<Item> &set_values,
919.1.2 by Brian Aker
Comitting the removal of server code for LOAD DATA "LOCAL" INFILE
131
                enum enum_duplicates handle_duplicates, bool ignore)
1 by brian
clean slate
132
{
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
133
  int file;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
134
  Table *table= NULL;
1 by brian
clean slate
135
  int error;
136
  String *field_term=ex->field_term,*escaped=ex->escaped;
137
  String *enclosed=ex->enclosed;
138
  bool is_fifo=0;
1874.1.1 by Brian Aker
Encapsulate schema_name it table_list.
139
140
  assert(table_list->getSchemaName()); // This should never be null
141
1 by brian
clean slate
142
  /*
1208.3.2 by brian
Update for Cursor renaming.
143
    If path for cursor is not defined, we will use the current database.
1 by brian
clean slate
144
    If this is not set, we will use the directory where the table to be
145
    loaded is located
146
  */
2269.1.7 by Olaf van der Spek
Use util::string::ptr
147
  util::string::ptr schema(session->schema());
1976.5.2 by Brian Aker
This resolves the issue where one thread may be looking at schema while
148
  const char *tdb= (schema and not schema->empty()) ? schema->c_str() : table_list->getSchemaName(); // Result should never be null
630 by Brian Aker
Removing old STMT logic from load data infile (still need to clean up the
149
  assert(tdb);
307 by Brian Aker
Minor cleanups around ulong in kernel.
150
  uint32_t skip_lines= ex->skip_lines;
1 by brian
clean slate
151
  bool transactional_table;
152
685.4.6 by Jay Pipes
Fix for Bug#308457. Gave UTF8 enclosure and escape character on LOAD DATA INFILE and changed the error message to be more descriptive
153
  /* Escape and enclosed character may be a utf8 4-byte character */
154
  if (escaped->length() > 4 || enclosed->length() > 4)
1 by brian
clean slate
155
  {
685.4.6 by Jay Pipes
Fix for Bug#308457. Gave UTF8 enclosure and escape character on LOAD DATA INFILE and changed the error message to be more descriptive
156
    my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
2318.6.55 by Olaf van der Spek
Refactor
157
    return true;
1 by brian
clean slate
158
  }
1109.1.3 by Brian Aker
Move names around a bit (to align similar methods)
159
160
  if (session->openTablesLock(table_list))
2318.6.55 by Olaf van der Spek
Refactor
161
    return true;
1109.1.3 by Brian Aker
Move names around a bit (to align similar methods)
162
2227.4.8 by Olaf van der Spek
Session::lex()
163
  if (setup_tables_and_check_access(session, &session->lex().select_lex.context,
164
                                    &session->lex().select_lex.top_join_list,
1 by brian
clean slate
165
                                    table_list,
2227.4.8 by Olaf van der Spek
Session::lex()
166
                                    &session->lex().select_lex.leaf_tables, true))
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
167
     return(-1);
1 by brian
clean slate
168
169
  /*
170
    Let us emit an error if we are loading data to table which is used
171
    in subselect in SET clause like we do it for INSERT.
172
173
    The main thing to fix to remove this restriction is to ensure that the
174
    table is marked to be 'used for insert' in which case we should never
175
    mark this table as 'const table' (ie, one that has only one row).
176
  */
1220.1.13 by Brian Aker
Remove mysql_lock_have_duplicate() (we don't have merge, and our partition
177
  if (unique_table(table_list, table_list->next_global))
1 by brian
clean slate
178
  {
1874.1.2 by Brian Aker
Encapsulate table_name from table_list.
179
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
2318.6.55 by Olaf van der Spek
Refactor
180
    return true;
1 by brian
clean slate
181
  }
182
183
  table= table_list->table;
1208.3.2 by brian
Update for Cursor renaming.
184
  transactional_table= table->cursor->has_transactions();
1 by brian
clean slate
185
2183.2.19 by Olaf van der Spek
Use List::size()
186
  if (!fields_vars.size())
1 by brian
clean slate
187
  {
188
    Field **field;
1578.2.16 by Brian Aker
Merge in change to getTable() to private the field objects.
189
    for (field= table->getFields(); *field ; field++)
1 by brian
clean slate
190
      fields_vars.push_back(new Item_field(*field));
1005.2.12 by Monty Taylor
Moved some things to the API.
191
    table->setWriteSet();
1 by brian
clean slate
192
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
193
    /*
194
      Let us also prepare SET clause, altough it is probably empty
195
      in this case.
196
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
197
    if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
198
        setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
2318.6.55 by Olaf van der Spek
Refactor
199
      return true;
1 by brian
clean slate
200
  }
201
  else
202
  {						// Part field list
203
    /* TODO: use this conds for 'WITH CHECK OPTIONS' */
520.1.22 by Brian Aker
Second pass of thd cleanup
204
    if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
205
        setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
206
        check_that_all_fields_are_given_values(session, table, table_list))
2318.6.55 by Olaf van der Spek
Refactor
207
      return true;
1 by brian
clean slate
208
    /*
209
      Check whenever TIMESTAMP field with auto-set feature specified
210
      explicitly.
211
    */
212
    if (table->timestamp_field)
213
    {
1999.4.2 by Brian Aker
Encapsulate the field's position.
214
      if (table->isWriteSet(table->timestamp_field->position()))
215
      {
1 by brian
clean slate
216
        table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1999.4.2 by Brian Aker
Encapsulate the field's position.
217
      }
1 by brian
clean slate
218
      else
219
      {
1999.4.2 by Brian Aker
Encapsulate the field's position.
220
        table->setWriteSet(table->timestamp_field->position());
1 by brian
clean slate
221
      }
222
    }
223
    /* Fix the expressions in SET clause */
520.1.22 by Brian Aker
Second pass of thd cleanup
224
    if (setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
2318.6.55 by Olaf van der Spek
Refactor
225
      return true;
1 by brian
clean slate
226
  }
227
228
  table->mark_columns_needed_for_insert();
229
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
230
  size_t tot_length=0;
1 by brian
clean slate
231
  bool use_blobs= 0, use_vars= 0;
2183.2.12 by Olaf van der Spek
Use List::begin()
232
  List<Item>::iterator it(fields_vars.begin());
1 by brian
clean slate
233
  Item *item;
234
235
  while ((item= it++))
236
  {
237
    Item *real_item= item->real_item();
238
239
    if (real_item->type() == Item::FIELD_ITEM)
240
    {
241
      Field *field= ((Item_field*)real_item)->field;
242
      if (field->flags & BLOB_FLAG)
243
      {
244
        use_blobs= 1;
245
        tot_length+= 256;			// Will be extended if needed
246
      }
247
      else
248
        tot_length+= field->field_length;
249
    }
250
    else if (item->type() == Item::STRING_ITEM)
251
      use_vars= 1;
252
  }
253
  if (use_blobs && !ex->line_term->length() && !field_term->length())
254
  {
255
    my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
256
	       MYF(0));
2318.6.55 by Olaf van der Spek
Refactor
257
    return true;
1 by brian
clean slate
258
  }
259
  if (use_vars && !field_term->length() && !enclosed->length())
260
  {
261
    my_error(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR, MYF(0));
2318.6.55 by Olaf van der Spek
Refactor
262
    return true;
1 by brian
clean slate
263
  }
264
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
265
  fs::path to_file(ex->file_name);
266
  fs::path target_path(fs::system_complete(getDataHomeCatalog()));
267
  if (not to_file.has_root_directory())
268
  {
269
    int count_elements= 0;
270
    for (fs::path::iterator iter= to_file.begin();
271
         iter != to_file.end();
272
         ++iter, ++count_elements)
273
    { }
274
275
    if (count_elements == 1)
276
    {
277
      target_path /= tdb;
278
    }
279
    target_path /= to_file;
280
  }
281
  else
282
  {
283
    target_path= to_file;
284
  }
285
286
  if (not secure_file_priv.string().empty())
287
  {
1813.2.10 by Monty Taylor
Expand secure-file-priv once at startup rather than on each path check.
288
    if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
289
    {
290
      /* Read only allowed from within dir specified by secure_file_priv */
291
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
2318.6.55 by Olaf van der Spek
Refactor
292
      return true;
673.3.8 by Stewart Smith
fix outfile_loaddata test for drizzle.
293
    }
1 by brian
clean slate
294
  }
295
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
296
  struct stat stat_info;
297
  if (stat(target_path.file_string().c_str(), &stat_info))
298
  {
299
    my_error(ER_FILE_NOT_FOUND, MYF(0), target_path.file_string().c_str(), errno);
2318.6.55 by Olaf van der Spek
Refactor
300
    return true;
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
301
  }
302
303
  // if we are not in slave thread, the cursor must be:
304
  if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
305
        (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
306
        ((stat_info.st_mode & S_IFREG) == S_IFREG ||
307
         (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
308
  {
309
    my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), target_path.file_string().c_str());
2318.6.55 by Olaf van der Spek
Refactor
310
    return true;
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
311
  }
312
  if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
313
    is_fifo = 1;
314
315
316
  if ((file=internal::my_open(target_path.file_string().c_str(), O_RDONLY,MYF(MY_WME))) < 0)
317
  {
318
    my_error(ER_CANT_OPEN_FILE, MYF(0), target_path.file_string().c_str(), errno);
2318.6.55 by Olaf van der Spek
Refactor
319
    return true;
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
320
  }
1711.6.1 by Brian Aker
Style on structure cleanup
321
  CopyInfo info;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
322
  memset(&info, 0, sizeof(info));
1 by brian
clean slate
323
  info.ignore= ignore;
324
  info.handle_duplicates=handle_duplicates;
325
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
326
2087.4.1 by Brian Aker
Merge in schema identifier.
327
  identifier::Schema identifier(*schema);
1014.3.1 by Brian Aker
Simplify the calling stack for getting schema collation. We need to extend
328
  READ_INFO read_info(file, tot_length,
1415 by Brian Aker
Mass overhaul to use schema_identifier.
329
                      ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(identifier),
330
		      *field_term, *ex->line_start, *ex->line_term, *enclosed,
919.1.2 by Brian Aker
Comitting the removal of server code for LOAD DATA "LOCAL" INFILE
331
		      info.escape_char, is_fifo);
1 by brian
clean slate
332
  if (read_info.error)
333
  {
334
    if	(file >= 0)
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
335
      internal::my_close(file,MYF(0));			// no files in net reading
2318.6.55 by Olaf van der Spek
Refactor
336
    return true;				// Can't allocate buffers
1 by brian
clean slate
337
  }
338
685.4.1 by Jay Pipes
Enabled the null.test.
339
  /*
340
   * Per the SQL standard, inserting NULL into a NOT NULL
341
   * field requires an error to be thrown.
342
   *
343
   * @NOTE
344
   *
345
   * NULL check and handling occurs in field_conv.cc
346
   */
347
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
520.1.22 by Brian Aker
Second pass of thd cleanup
348
  session->cuted_fields=0L;
1 by brian
clean slate
349
  /* Skip lines if there is a line terminator */
266.1.23 by Monty Taylor
Removed load xml infile. Hope nobody liked it. Now the only thing we need xml.c
350
  if (ex->line_term->length())
1 by brian
clean slate
351
  {
352
    /* ex->skip_lines needs to be preserved for logging */
353
    while (skip_lines > 0)
354
    {
355
      skip_lines--;
356
      if (read_info.next_line())
357
	break;
358
    }
359
  }
360
361
  if (!(error=test(read_info.error)))
362
  {
363
364
    table->next_number_field=table->found_next_number_field;
365
    if (ignore ||
366
	handle_duplicates == DUP_REPLACE)
1208.3.2 by brian
Update for Cursor renaming.
367
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1 by brian
clean slate
368
    if (handle_duplicates == DUP_REPLACE)
1208.3.2 by brian
Update for Cursor renaming.
369
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
370
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
1 by brian
clean slate
371
    table->copy_blobs=1;
372
2114.5.1 by Brian Aker
Additional abstract around time (this also makes the abort_on_warnings in
373
    session->setAbortOnWarning(true);
1 by brian
clean slate
374
266.1.23 by Monty Taylor
Removed load xml infile. Hope nobody liked it. Now the only thing we need xml.c
375
    if (!field_term->length() && !enclosed->length())
520.1.22 by Brian Aker
Second pass of thd cleanup
376
      error= read_fixed_length(session, info, table_list, fields_vars,
1 by brian
clean slate
377
                               set_fields, set_values, read_info,
378
			       skip_lines, ignore);
379
    else
520.1.22 by Brian Aker
Second pass of thd cleanup
380
      error= read_sep_field(session, info, table_list, fields_vars,
1 by brian
clean slate
381
                            set_fields, set_values, read_info,
382
			    *enclosed, skip_lines, ignore);
1208.3.2 by brian
Update for Cursor renaming.
383
    if (table->cursor->ha_end_bulk_insert() && !error)
1 by brian
clean slate
384
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
385
      table->print_error(errno, MYF(0));
1 by brian
clean slate
386
      error= 1;
387
    }
1208.3.2 by brian
Update for Cursor renaming.
388
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
389
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1 by brian
clean slate
390
    table->next_number_field=0;
391
  }
392
  if (file >= 0)
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
393
    internal::my_close(file,MYF(0));
1 by brian
clean slate
394
  free_blobs(table);				/* if pack_blob was used */
395
  table->copy_blobs=0;
1633.4.8 by Brian Aker
Update for count_cuted_fields.
396
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
397
  /*
1 by brian
clean slate
398
     simulated killing in the middle of per-row loop
399
     must be effective for binlogging
400
  */
2253.1.1 by Andrew Hutchings
Fix Drizzle to compile in GCC 4.6 (which fires warnings and therefore errors if a variable is set and not read)
401
  if (error) 
1 by brian
clean slate
402
  {
403
    error= -1;				// Error on read
404
    goto err;
405
  }
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
406
407
  char msg[FN_REFLEN];
408
  snprintf(msg, sizeof(msg), ER(ER_LOAD_INFO), info.records, info.deleted,
1717.2.1 by David Shrewsbury
Remove incorrect casting of 8-byte numbers down to 4-bytes.
409
	   (info.records - info.copied), session->cuted_fields);
1 by brian
clean slate
410
1273.1.13 by Jay Pipes
Style cleanup around TransactionContext::modified_non_trans_table and dead code removal
411
  if (session->transaction.stmt.hasModifiedNonTransData())
412
    session->transaction.all.markModifiedNonTransData();
1 by brian
clean slate
413
414
  /* ok to client sent only after binlog write and engine commit */
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
415
  session->my_ok(info.copied + info.deleted, 0, 0L, msg);
1 by brian
clean slate
416
err:
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
417
  assert(transactional_table || !(info.copied || info.deleted) ||
1273.1.13 by Jay Pipes
Style cleanup around TransactionContext::modified_non_trans_table and dead code removal
418
              session->transaction.stmt.hasModifiedNonTransData());
1208.3.2 by brian
Update for Cursor renaming.
419
  table->cursor->ha_release_auto_increment();
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
420
  table->auto_increment_field_not_null= false;
2114.5.1 by Brian Aker
Additional abstract around time (this also makes the abort_on_warnings in
421
  session->setAbortOnWarning(false);
422
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
423
  return(error);
1 by brian
clean slate
424
}
425
426
427
/****************************************************************************
428
** Read of rows of fixed size + optional garage + optonal newline
429
****************************************************************************/
430
431
static int
1711.6.1 by Brian Aker
Style on structure cleanup
432
read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
433
                  List<Item> &fields_vars, List<Item> &set_fields,
434
                  List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
435
                  uint32_t skip_lines, bool ignore_check_option_errors)
1 by brian
clean slate
436
{
2183.2.12 by Olaf van der Spek
Use List::begin()
437
  List<Item>::iterator it(fields_vars.begin());
1 by brian
clean slate
438
  Item_field *sql_field;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
439
  Table *table= table_list->table;
1 by brian
clean slate
440
  bool err;
441
442
  while (!read_info.read_fixed_length())
443
  {
1910.2.8 by Brian Aker
Enapsulate Kill.
444
    if (session->getKilled())
1 by brian
clean slate
445
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
446
      session->send_kill_message();
2318.6.77 by Olaf van der Spek
Refactor
447
      return 1;
1 by brian
clean slate
448
    }
449
    if (skip_lines)
450
    {
451
      /*
452
	We could implement this with a simple seek if:
453
	- We are not using DATA INFILE LOCAL
454
	- escape character is  ""
455
	- line starting prefix is ""
456
      */
457
      skip_lines--;
458
      continue;
459
    }
2183.2.7 by Olaf van der Spek
x
460
    it= fields_vars.begin();
481 by Brian Aker
Remove all of uchar.
461
    unsigned char *pos=read_info.row_start;
1859.2.14 by Brian Aker
Add support for --with-valgrind
462
#ifdef HAVE_VALGRIND
1 by brian
clean slate
463
    read_info.row_end[0]=0;
464
#endif
465
997.5.1 by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record
466
    table->restoreRecordAsDefault();
1 by brian
clean slate
467
    /*
468
      There is no variables in fields_vars list in this format so
469
      this conversion is safe.
470
    */
471
    while ((sql_field= (Item_field*) it++))
472
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
473
      Field *field= sql_field->field;
1 by brian
clean slate
474
      if (field == table->next_number_field)
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
475
        table->auto_increment_field_not_null= true;
1 by brian
clean slate
476
      /*
477
        No fields specified in fields_vars list can be null in this format.
478
        Mark field as not null, we should do this for each row because of
479
        restore_record...
480
      */
481
      field->set_notnull();
482
483
      if (pos == read_info.row_end)
484
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
485
        session->cuted_fields++;			/* Not enough fields */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
486
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
487
                            ER_WARN_TOO_FEW_RECORDS,
520.1.22 by Brian Aker
Second pass of thd cleanup
488
                            ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
1999.4.9 by Brian Aker
Created EPOCH
489
2046.2.1 by Brian Aker
First pass on micro timestamp.
490
        if (not field->maybe_null() and field->is_timestamp())
1999.4.9 by Brian Aker
Created EPOCH
491
            ((field::Epoch::pointer) field)->set_time();
1 by brian
clean slate
492
      }
493
      else
494
      {
482 by Brian Aker
Remove uint.
495
	uint32_t length;
481 by Brian Aker
Remove all of uchar.
496
	unsigned char save_chr;
895 by Brian Aker
Completion (?) of uint conversion.
497
	if ((length=(uint32_t) (read_info.row_end-pos)) >
1 by brian
clean slate
498
	    field->field_length)
1014.2.6 by Monty Taylor
Style move.
499
        {
1 by brian
clean slate
500
	  length=field->field_length;
1014.2.6 by Monty Taylor
Style move.
501
        }
502
	save_chr=pos[length];
503
        pos[length]='\0'; // Add temp null terminator for store()
1 by brian
clean slate
504
        field->store((char*) pos,length,read_info.read_charset);
505
	pos[length]=save_chr;
506
	if ((pos+=length) > read_info.row_end)
507
	  pos= read_info.row_end;	/* Fills rest with space */
508
      }
509
    }
510
    if (pos != read_info.row_end)
511
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
512
      session->cuted_fields++;			/* To long row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
513
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
514
                          ER_WARN_TOO_MANY_RECORDS,
515
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
1 by brian
clean slate
516
    }
517
1910.2.8 by Brian Aker
Enapsulate Kill.
518
    if (session->getKilled() ||
520.1.22 by Brian Aker
Second pass of thd cleanup
519
        fill_record(session, set_fields, set_values,
1 by brian
clean slate
520
                    ignore_check_option_errors))
2318.6.77 by Olaf van der Spek
Refactor
521
      return 1;
1 by brian
clean slate
522
520.1.22 by Brian Aker
Second pass of thd cleanup
523
    err= write_record(session, table, &info);
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
524
    table->auto_increment_field_not_null= false;
1 by brian
clean slate
525
    if (err)
2318.6.77 by Olaf van der Spek
Refactor
526
      return 1;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
527
1 by brian
clean slate
528
    /*
529
      We don't need to reset auto-increment field since we are restoring
530
      its default value at the beginning of each loop iteration.
531
    */
532
    if (read_info.next_line())			// Skip to next line
533
      break;
534
    if (read_info.line_cuted)
535
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
536
      session->cuted_fields++;			/* To long row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
537
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
538
                          ER_WARN_TOO_MANY_RECORDS,
539
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
1 by brian
clean slate
540
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
541
    session->row_count++;
1 by brian
clean slate
542
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
543
  return(test(read_info.error));
1 by brian
clean slate
544
}
545
546
547
548
static int
1711.6.1 by Brian Aker
Style on structure cleanup
549
read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
550
               List<Item> &fields_vars, List<Item> &set_fields,
551
               List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
552
	       String &enclosed, uint32_t skip_lines,
1 by brian
clean slate
553
	       bool ignore_check_option_errors)
554
{
2183.2.12 by Olaf van der Spek
Use List::begin()
555
  List<Item>::iterator it(fields_vars.begin());
1 by brian
clean slate
556
  Item *item;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
557
  Table *table= table_list->table;
482 by Brian Aker
Remove uint.
558
  uint32_t enclosed_length;
1 by brian
clean slate
559
  bool err;
560
561
  enclosed_length=enclosed.length();
562
2183.2.7 by Olaf van der Spek
x
563
  for (;;it= fields_vars.begin())
1 by brian
clean slate
564
  {
1910.2.8 by Brian Aker
Enapsulate Kill.
565
    if (session->getKilled())
1 by brian
clean slate
566
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
567
      session->send_kill_message();
2318.6.77 by Olaf van der Spek
Refactor
568
      return 1;
1 by brian
clean slate
569
    }
570
997.5.1 by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record
571
    table->restoreRecordAsDefault();
1 by brian
clean slate
572
573
    while ((item= it++))
574
    {
482 by Brian Aker
Remove uint.
575
      uint32_t length;
481 by Brian Aker
Remove all of uchar.
576
      unsigned char *pos;
1 by brian
clean slate
577
      Item *real_item;
578
579
      if (read_info.read_field())
580
	break;
581
582
      /* If this line is to be skipped we don't want to fill field or var */
583
      if (skip_lines)
584
        continue;
585
586
      pos=read_info.row_start;
895 by Brian Aker
Completion (?) of uint conversion.
587
      length=(uint32_t) (read_info.row_end-pos);
1 by brian
clean slate
588
589
      real_item= item->real_item();
590
591
      if ((!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos, STRING_WITH_LEN("NULL")))) ||
592
	  (length == 1 && read_info.found_null))
593
      {
594
595
        if (real_item->type() == Item::FIELD_ITEM)
596
        {
597
          Field *field= ((Item_field *)real_item)->field;
598
          if (field->reset())
599
          {
600
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
520.1.22 by Brian Aker
Second pass of thd cleanup
601
                     session->row_count);
2318.6.77 by Olaf van der Spek
Refactor
602
            return 1;
1 by brian
clean slate
603
          }
604
          field->set_null();
2046.2.1 by Brian Aker
First pass on micro timestamp.
605
          if (not field->maybe_null())
1 by brian
clean slate
606
          {
2046.2.1 by Brian Aker
First pass on micro timestamp.
607
            if (field->is_timestamp())
1999.4.9 by Brian Aker
Created EPOCH
608
            {
609
              ((field::Epoch::pointer) field)->set_time();
610
            }
1 by brian
clean slate
611
            else if (field != table->next_number_field)
1999.4.9 by Brian Aker
Created EPOCH
612
            {
613
              field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_NULL_TO_NOTNULL, 1);
614
            }
1 by brian
clean slate
615
          }
616
	}
617
        else if (item->type() == Item::STRING_ITEM)
618
        {
619
          ((Item_user_var_as_out_param *)item)->set_null_value(
620
                                                  read_info.read_charset);
621
        }
622
        else
623
        {
624
          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
2318.6.77 by Olaf van der Spek
Refactor
625
          return 1;
1 by brian
clean slate
626
        }
627
628
	continue;
629
      }
630
631
      if (real_item->type() == Item::FIELD_ITEM)
632
      {
633
        Field *field= ((Item_field *)real_item)->field;
634
        field->set_notnull();
635
        read_info.row_end[0]=0;			// Safe to change end marker
636
        if (field == table->next_number_field)
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
637
          table->auto_increment_field_not_null= true;
1 by brian
clean slate
638
        field->store((char*) pos, length, read_info.read_charset);
639
      }
640
      else if (item->type() == Item::STRING_ITEM)
641
      {
642
        ((Item_user_var_as_out_param *)item)->set_value((char*) pos, length,
643
                                                        read_info.read_charset);
644
      }
645
      else
646
      {
647
        my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
2318.6.77 by Olaf van der Spek
Refactor
648
        return 1;
1 by brian
clean slate
649
      }
650
    }
651
    if (read_info.error)
652
      break;
653
    if (skip_lines)
654
    {
655
      skip_lines--;
656
      continue;
657
    }
658
    if (item)
659
    {
1208.3.2 by brian
Update for Cursor renaming.
660
      /* Have not read any field, thus input cursor is simply ended */
2183.2.21 by Olaf van der Spek
Use List::front()
661
      if (item == &fields_vars.front())
1 by brian
clean slate
662
	break;
663
      for (; item ; item= it++)
664
      {
665
        Item *real_item= item->real_item();
666
        if (real_item->type() == Item::FIELD_ITEM)
667
        {
668
          Field *field= ((Item_field *)real_item)->field;
669
          if (field->reset())
670
          {
671
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
520.1.22 by Brian Aker
Second pass of thd cleanup
672
                     session->row_count);
2318.6.77 by Olaf van der Spek
Refactor
673
            return 1;
1 by brian
clean slate
674
          }
2046.2.1 by Brian Aker
First pass on micro timestamp.
675
          if (not field->maybe_null() and field->is_timestamp())
1999.4.9 by Brian Aker
Created EPOCH
676
              ((field::Epoch::pointer) field)->set_time();
1 by brian
clean slate
677
          /*
678
            QQ: We probably should not throw warning for each field.
679
            But how about intention to always have the same number
520.1.21 by Brian Aker
THD -> Session rename
680
            of warnings in Session::cuted_fields (and get rid of cuted_fields
1 by brian
clean slate
681
            in the end ?)
682
          */
520.1.22 by Brian Aker
Second pass of thd cleanup
683
          session->cuted_fields++;
684
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
685
                              ER_WARN_TOO_FEW_RECORDS,
520.1.22 by Brian Aker
Second pass of thd cleanup
686
                              ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
1 by brian
clean slate
687
        }
688
        else if (item->type() == Item::STRING_ITEM)
689
        {
690
          ((Item_user_var_as_out_param *)item)->set_null_value(
691
                                                  read_info.read_charset);
692
        }
693
        else
694
        {
695
          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
2318.6.77 by Olaf van der Spek
Refactor
696
          return 1;
1 by brian
clean slate
697
        }
698
      }
699
    }
700
1910.2.8 by Brian Aker
Enapsulate Kill.
701
    if (session->getKilled() ||
520.1.22 by Brian Aker
Second pass of thd cleanup
702
        fill_record(session, set_fields, set_values,
1 by brian
clean slate
703
                    ignore_check_option_errors))
2318.6.77 by Olaf van der Spek
Refactor
704
      return 1;
1 by brian
clean slate
705
520.1.22 by Brian Aker
Second pass of thd cleanup
706
    err= write_record(session, table, &info);
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
707
    table->auto_increment_field_not_null= false;
1 by brian
clean slate
708
    if (err)
2318.6.77 by Olaf van der Spek
Refactor
709
      return 1;
1 by brian
clean slate
710
    /*
711
      We don't need to reset auto-increment field since we are restoring
712
      its default value at the beginning of each loop iteration.
713
    */
714
    if (read_info.next_line())			// Skip to next line
715
      break;
716
    if (read_info.line_cuted)
717
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
718
      session->cuted_fields++;			/* To long row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
719
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
720
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
721
                          session->row_count);
1910.2.8 by Brian Aker
Enapsulate Kill.
722
      if (session->getKilled())
2318.6.77 by Olaf van der Spek
Refactor
723
        return 1;
1 by brian
clean slate
724
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
725
    session->row_count++;
1 by brian
clean slate
726
  }
51.1.1 by Jay Pipes
Merged PatG's removal of various DBUG stuff with still keeping DBUG_ASSERT calls since they seem to be breaking test runs
727
  return(test(read_info.error));
1 by brian
clean slate
728
}
729
730
731
/* Unescape all escape characters, mark \N as null */
732
733
char
734
READ_INFO::unescape(char chr)
735
{
736
  /* keep this switch synchornous with the ESCAPE_CHARS macro */
737
  switch(chr) {
738
  case 'n': return '\n';
739
  case 't': return '\t';
740
  case 'r': return '\r';
741
  case 'b': return '\b';
742
  case '0': return 0;				// Ascii null
1208.3.2 by brian
Update for Cursor renaming.
743
  case 'Z': return '\032';			// Win32 end of cursor
1 by brian
clean slate
744
  case 'N': found_null=1;
745
746
    /* fall through */
747
  default:  return chr;
748
  }
749
}
750
751
752
/*
753
  Read a line using buffering
754
  If last line is empty (in line mode) then it isn't outputed
755
*/
756
757
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
758
READ_INFO::READ_INFO(int file_par, size_t tot_length,
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
759
                     const charset_info_st * const cs,
1 by brian
clean slate
760
		     String &field_term, String &line_start, String &line_term,
919.1.2 by Brian Aker
Comitting the removal of server code for LOAD DATA "LOCAL" INFILE
761
		     String &enclosed_par, int escape, bool is_fifo)
1208.3.2 by brian
Update for Cursor renaming.
762
  :cursor(file_par),escape_char(escape)
1 by brian
clean slate
763
{
764
  read_charset= cs;
765
  field_term_ptr=(char*) field_term.ptr();
766
  field_term_length= field_term.length();
767
  line_term_ptr=(char*) line_term.ptr();
768
  line_term_length= line_term.length();
769
  if (line_start.length() == 0)
770
  {
771
    line_start_ptr=0;
772
    start_of_line= 0;
773
  }
774
  else
775
  {
776
    line_start_ptr=(char*) line_start.ptr();
777
    line_start_end=line_start_ptr+line_start.length();
778
    start_of_line= 1;
779
  }
780
  /* If field_terminator == line_terminator, don't use line_terminator */
781
  if (field_term_length == line_term_length &&
782
      !memcmp(field_term_ptr,line_term_ptr,field_term_length))
783
  {
784
    line_term_length=0;
785
    line_term_ptr=(char*) "";
786
  }
787
  enclosed_char= (enclosed_length=enclosed_par.length()) ?
481 by Brian Aker
Remove all of uchar.
788
    (unsigned char) enclosed_par[0] : INT_MAX;
789
  field_term_char= field_term_length ? (unsigned char) field_term_ptr[0] : INT_MAX;
790
  line_term_char= line_term_length ? (unsigned char) line_term_ptr[0] : INT_MAX;
1 by brian
clean slate
791
  error=eof=found_end_of_line=found_null=line_cuted=0;
792
  buff_length=tot_length;
793
794
795
  /* Set of a stack for unget if long terminators */
1816.3.1 by Brian Aker
Convert sql_string to use size_t (this should clean up ICC warnings).
796
  size_t length= max(field_term_length,line_term_length)+1;
797
  set_if_bigger(length, line_start.length());
1253.1.6 by Monty Taylor
Moved mem_root functions into drizzled::memory:: namespace.
798
  stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
1 by brian
clean slate
799
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
800
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
971.6.11 by Eric Day
Removed purecov messages.
801
    error=1;
1 by brian
clean slate
802
  else
803
  {
804
    end_of_buff=buffer+buff_length;
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
805
    if (cache.init_io_cache((false) ? -1 : cursor, 0,
806
                            (false) ? internal::READ_NET :
807
                            (is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
808
                            MYF(MY_WME)))
1 by brian
clean slate
809
    {
971.6.11 by Eric Day
Removed purecov messages.
810
      free((unsigned char*) buffer);
1 by brian
clean slate
811
      error=1;
812
    }
813
    else
814
    {
815
      /*
816
	init_io_cache() will not initialize read_function member
817
	if the cache is READ_NET. So we work around the problem with a
818
	manual assignment
819
      */
820
      need_end_io_cache = 1;
821
    }
822
  }
823
}
824
825
826
READ_INFO::~READ_INFO()
827
{
828
  if (!error)
829
  {
830
    if (need_end_io_cache)
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
831
      cache.end_io_cache();
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
832
    free(buffer);
1 by brian
clean slate
833
    error=1;
834
  }
835
}
836
837
2385.3.13 by Olaf van der Spek
Refactor iocache
838
#define GET (stack_pos != stack ? *--stack_pos : cache.get())
1 by brian
clean slate
839
#define PUSH(A) *(stack_pos++)=(A)
840
841
482 by Brian Aker
Remove uint.
842
inline int READ_INFO::terminator(char *ptr,uint32_t length)
1 by brian
clean slate
843
{
844
  int chr=0;					// Keep gcc happy
482 by Brian Aker
Remove uint.
845
  uint32_t i;
1 by brian
clean slate
846
  for (i=1 ; i < length ; i++)
847
  {
848
    if ((chr=GET) != *++ptr)
849
    {
850
      break;
851
    }
852
  }
853
  if (i == length)
854
    return 1;
855
  PUSH(chr);
856
  while (i-- > 1)
481 by Brian Aker
Remove all of uchar.
857
    PUSH((unsigned char) *--ptr);
1 by brian
clean slate
858
  return 0;
859
}
860
861
862
int READ_INFO::read_field()
863
{
864
  int chr,found_enclosed_char;
481 by Brian Aker
Remove all of uchar.
865
  unsigned char *to,*new_buffer;
1 by brian
clean slate
866
867
  found_null=0;
868
  if (found_end_of_line)
869
    return 1;					// One have to call next_line
870
871
  /* Skip until we find 'line_start' */
872
873
  if (start_of_line)
874
  {						// Skip until line_start
875
    start_of_line=0;
876
    if (find_start_of_fields())
877
      return 1;
878
  }
879
  if ((chr=GET) == my_b_EOF)
880
  {
881
    found_end_of_line=eof=1;
882
    return 1;
883
  }
884
  to=buffer;
885
  if (chr == enclosed_char)
886
  {
887
    found_enclosed_char=enclosed_char;
481 by Brian Aker
Remove all of uchar.
888
    *to++=(unsigned char) chr;				// If error
1 by brian
clean slate
889
  }
890
  else
891
  {
892
    found_enclosed_char= INT_MAX;
893
    PUSH(chr);
894
  }
895
896
  for (;;)
897
  {
898
    while ( to < end_of_buff)
899
    {
900
      chr = GET;
901
      if ((my_mbcharlen(read_charset, chr) > 1) &&
902
          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
903
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
904
        unsigned char* p = (unsigned char*)to;
905
        *to++ = chr;
906
        int ml = my_mbcharlen(read_charset, chr);
907
        int i;
908
        for (i=1; i<ml; i++) {
909
          chr = GET;
910
          if (chr == my_b_EOF)
911
            goto found_eof;
912
          *to++ = chr;
913
        }
914
        if (my_ismbchar(read_charset,
915
              (const char *)p,
916
              (const char *)to))
917
          continue;
918
        for (i=0; i<ml; i++)
919
          PUSH((unsigned char) *--to);
920
        chr = GET;
1 by brian
clean slate
921
      }
922
      if (chr == my_b_EOF)
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
923
        goto found_eof;
1 by brian
clean slate
924
      if (chr == escape_char)
925
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
926
        if ((chr=GET) == my_b_EOF)
927
        {
928
          *to++= (unsigned char) escape_char;
929
          goto found_eof;
930
        }
1 by brian
clean slate
931
        /*
932
          When escape_char == enclosed_char, we treat it like we do for
933
          handling quotes in SQL parsing -- you can double-up the
934
          escape_char to include it literally, but it doesn't do escapes
935
          like \n. This allows: LOAD DATA ... ENCLOSED BY '"' ESCAPED BY '"'
936
          with data like: "fie""ld1", "field2"
937
         */
938
        if (escape_char != enclosed_char || chr == escape_char)
939
        {
481 by Brian Aker
Remove all of uchar.
940
          *to++ = (unsigned char) unescape((char) chr);
1 by brian
clean slate
941
          continue;
942
        }
943
        PUSH(chr);
944
        chr= escape_char;
945
      }
946
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
947
      if (chr == line_term_char)
948
#else
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
949
        if (chr == line_term_char && found_enclosed_char == INT_MAX)
1 by brian
clean slate
950
#endif
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
951
        {
952
          if (terminator(line_term_ptr,line_term_length))
953
          {					// Maybe unexpected linefeed
954
            enclosed=0;
955
            found_end_of_line=1;
956
            row_start=buffer;
957
            row_end=  to;
958
            return 0;
959
          }
960
        }
1 by brian
clean slate
961
      if (chr == found_enclosed_char)
962
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
963
        if ((chr=GET) == found_enclosed_char)
964
        {					// Remove dupplicated
965
          *to++ = (unsigned char) chr;
966
          continue;
967
        }
968
        // End of enclosed field if followed by field_term or line_term
969
        if (chr == my_b_EOF ||
970
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
971
        {					// Maybe unexpected linefeed
972
          enclosed=1;
973
          found_end_of_line=1;
974
          row_start=buffer+1;
975
          row_end=  to;
976
          return 0;
977
        }
978
        if (chr == field_term_char &&
979
            terminator(field_term_ptr,field_term_length))
980
        {
981
          enclosed=1;
982
          row_start=buffer+1;
983
          row_end=  to;
984
          return 0;
985
        }
986
        /*
987
           The string didn't terminate yet.
988
           Store back next character for the loop
989
         */
990
        PUSH(chr);
991
        /* copy the found term character to 'to' */
992
        chr= found_enclosed_char;
1 by brian
clean slate
993
      }
994
      else if (chr == field_term_char && found_enclosed_char == INT_MAX)
995
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
996
        if (terminator(field_term_ptr,field_term_length))
997
        {
998
          enclosed=0;
999
          row_start=buffer;
1000
          row_end=  to;
1001
          return 0;
1002
        }
1 by brian
clean slate
1003
      }
481 by Brian Aker
Remove all of uchar.
1004
      *to++ = (unsigned char) chr;
1 by brian
clean slate
1005
    }
1006
    /*
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
1007
     ** We come here if buffer is too small. Enlarge it and continue
1008
     */
2318.6.90 by Olaf van der Spek
Refactor
1009
    new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE);
1 by brian
clean slate
1010
    to=new_buffer + (to-buffer);
1011
    buffer=new_buffer;
1012
    buff_length+=IO_SIZE;
1013
    end_of_buff=buffer+buff_length;
1014
  }
1015
1016
found_eof:
1017
  enclosed=0;
1018
  found_end_of_line=eof=1;
1019
  row_start=buffer;
1020
  row_end=to;
1021
  return 0;
1022
}
1023
1024
/*
1025
  Read a row with fixed length.
1026
1027
  NOTES
1028
    The row may not be fixed size on disk if there are escape
1208.3.2 by brian
Update for Cursor renaming.
1029
    characters in the cursor.
1 by brian
clean slate
1030
1031
  IMPLEMENTATION NOTE
1032
    One can't use fixed length with multi-byte charset **
1033
1034
  RETURN
1035
    0  ok
1036
    1  error
1037
*/
1038
1039
int READ_INFO::read_fixed_length()
1040
{
1041
  int chr;
481 by Brian Aker
Remove all of uchar.
1042
  unsigned char *to;
1 by brian
clean slate
1043
  if (found_end_of_line)
1044
    return 1;					// One have to call next_line
1045
1046
  if (start_of_line)
1047
  {						// Skip until line_start
1048
    start_of_line=0;
1049
    if (find_start_of_fields())
1050
      return 1;
1051
  }
1052
1053
  to=row_start=buffer;
1054
  while (to < end_of_buff)
1055
  {
1056
    if ((chr=GET) == my_b_EOF)
1057
      goto found_eof;
1058
    if (chr == escape_char)
1059
    {
1060
      if ((chr=GET) == my_b_EOF)
1061
      {
481 by Brian Aker
Remove all of uchar.
1062
	*to++= (unsigned char) escape_char;
1 by brian
clean slate
1063
	goto found_eof;
1064
      }
481 by Brian Aker
Remove all of uchar.
1065
      *to++ =(unsigned char) unescape((char) chr);
1 by brian
clean slate
1066
      continue;
1067
    }
1068
    if (chr == line_term_char)
1069
    {
1070
      if (terminator(line_term_ptr,line_term_length))
1071
      {						// Maybe unexpected linefeed
1072
	found_end_of_line=1;
1073
	row_end=  to;
1074
	return 0;
1075
      }
1076
    }
481 by Brian Aker
Remove all of uchar.
1077
    *to++ = (unsigned char) chr;
1 by brian
clean slate
1078
  }
1079
  row_end=to;					// Found full line
1080
  return 0;
1081
1082
found_eof:
1083
  found_end_of_line=eof=1;
1084
  row_start=buffer;
1085
  row_end=to;
1086
  return to == buffer ? 1 : 0;
1087
}
1088
1089
1090
int READ_INFO::next_line()
1091
{
1092
  line_cuted=0;
1093
  start_of_line= line_start_ptr != 0;
1094
  if (found_end_of_line || eof)
1095
  {
1096
    found_end_of_line=0;
1097
    return eof;
1098
  }
1099
  found_end_of_line=0;
1100
  if (!line_term_length)
1101
    return 0;					// No lines
1102
  for (;;)
1103
  {
1104
    int chr = GET;
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
1105
    if (my_mbcharlen(read_charset, chr) > 1)
1106
    {
1107
      for (uint32_t i=1;
1108
          chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
1109
          i++)
1110
        chr = GET;
1111
      if (chr == escape_char)
1112
        continue;
1113
    }
1114
    if (chr == my_b_EOF)
1115
    {
1 by brian
clean slate
1116
      eof=1;
1117
      return 1;
1118
    }
1119
    if (chr == escape_char)
1120
    {
1121
      line_cuted=1;
1122
      if (GET == my_b_EOF)
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
1123
        return 1;
1 by brian
clean slate
1124
      continue;
1125
    }
1126
    if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1127
      return 0;
1128
    line_cuted=1;
1129
  }
1130
}
1131
1132
1133
bool READ_INFO::find_start_of_fields()
1134
{
1135
  int chr;
1136
 try_again:
1137
  do
1138
  {
1139
    if ((chr=GET) == my_b_EOF)
1140
    {
1141
      found_end_of_line=eof=1;
1142
      return 1;
1143
    }
1144
  } while ((char) chr != line_start_ptr[0]);
1145
  for (char *ptr=line_start_ptr+1 ; ptr != line_start_end ; ptr++)
1146
  {
1147
    chr=GET;					// Eof will be checked later
1148
    if ((char) chr != *ptr)
1149
    {						// Can't be line_start
1150
      PUSH(chr);
1151
      while (--ptr != line_start_ptr)
1152
      {						// Restart with next char
481 by Brian Aker
Remove all of uchar.
1153
	PUSH((unsigned char) *ptr);
1 by brian
clean slate
1154
      }
1155
      goto try_again;
1156
    }
1157
  }
1158
  return 0;
1159
}
1160
1161
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1162
} /* namespace drizzled */