~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
      {
2440.2.9 by Olaf van der Spek
Refactor
642
        ((Item_user_var_as_out_param *)item)->set_value(str_ref((char*) pos, length), read_info.read_charset);
1 by brian
clean slate
643
      }
644
      else
645
      {
646
        my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
2318.6.77 by Olaf van der Spek
Refactor
647
        return 1;
1 by brian
clean slate
648
      }
649
    }
650
    if (read_info.error)
651
      break;
652
    if (skip_lines)
653
    {
654
      skip_lines--;
655
      continue;
656
    }
657
    if (item)
658
    {
1208.3.2 by brian
Update for Cursor renaming.
659
      /* Have not read any field, thus input cursor is simply ended */
2183.2.21 by Olaf van der Spek
Use List::front()
660
      if (item == &fields_vars.front())
1 by brian
clean slate
661
	break;
662
      for (; item ; item= it++)
663
      {
664
        Item *real_item= item->real_item();
665
        if (real_item->type() == Item::FIELD_ITEM)
666
        {
667
          Field *field= ((Item_field *)real_item)->field;
668
          if (field->reset())
669
          {
670
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
520.1.22 by Brian Aker
Second pass of thd cleanup
671
                     session->row_count);
2318.6.77 by Olaf van der Spek
Refactor
672
            return 1;
1 by brian
clean slate
673
          }
2046.2.1 by Brian Aker
First pass on micro timestamp.
674
          if (not field->maybe_null() and field->is_timestamp())
1999.4.9 by Brian Aker
Created EPOCH
675
              ((field::Epoch::pointer) field)->set_time();
1 by brian
clean slate
676
          /*
677
            QQ: We probably should not throw warning for each field.
678
            But how about intention to always have the same number
520.1.21 by Brian Aker
THD -> Session rename
679
            of warnings in Session::cuted_fields (and get rid of cuted_fields
1 by brian
clean slate
680
            in the end ?)
681
          */
520.1.22 by Brian Aker
Second pass of thd cleanup
682
          session->cuted_fields++;
683
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
684
                              ER_WARN_TOO_FEW_RECORDS,
520.1.22 by Brian Aker
Second pass of thd cleanup
685
                              ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
1 by brian
clean slate
686
        }
687
        else if (item->type() == Item::STRING_ITEM)
688
        {
689
          ((Item_user_var_as_out_param *)item)->set_null_value(
690
                                                  read_info.read_charset);
691
        }
692
        else
693
        {
694
          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
2318.6.77 by Olaf van der Spek
Refactor
695
          return 1;
1 by brian
clean slate
696
        }
697
      }
698
    }
699
1910.2.8 by Brian Aker
Enapsulate Kill.
700
    if (session->getKilled() ||
520.1.22 by Brian Aker
Second pass of thd cleanup
701
        fill_record(session, set_fields, set_values,
1 by brian
clean slate
702
                    ignore_check_option_errors))
2318.6.77 by Olaf van der Spek
Refactor
703
      return 1;
1 by brian
clean slate
704
520.1.22 by Brian Aker
Second pass of thd cleanup
705
    err= write_record(session, table, &info);
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
706
    table->auto_increment_field_not_null= false;
1 by brian
clean slate
707
    if (err)
2318.6.77 by Olaf van der Spek
Refactor
708
      return 1;
1 by brian
clean slate
709
    /*
710
      We don't need to reset auto-increment field since we are restoring
711
      its default value at the beginning of each loop iteration.
712
    */
713
    if (read_info.next_line())			// Skip to next line
714
      break;
715
    if (read_info.line_cuted)
716
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
717
      session->cuted_fields++;			/* To long row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
718
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
719
                          ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
720
                          session->row_count);
1910.2.8 by Brian Aker
Enapsulate Kill.
721
      if (session->getKilled())
2318.6.77 by Olaf van der Spek
Refactor
722
        return 1;
1 by brian
clean slate
723
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
724
    session->row_count++;
1 by brian
clean slate
725
  }
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
726
  return(test(read_info.error));
1 by brian
clean slate
727
}
728
729
730
/* Unescape all escape characters, mark \N as null */
731
732
char
733
READ_INFO::unescape(char chr)
734
{
735
  /* keep this switch synchornous with the ESCAPE_CHARS macro */
736
  switch(chr) {
737
  case 'n': return '\n';
738
  case 't': return '\t';
739
  case 'r': return '\r';
740
  case 'b': return '\b';
741
  case '0': return 0;				// Ascii null
1208.3.2 by brian
Update for Cursor renaming.
742
  case 'Z': return '\032';			// Win32 end of cursor
1 by brian
clean slate
743
  case 'N': found_null=1;
744
745
    /* fall through */
746
  default:  return chr;
747
  }
748
}
749
750
751
/*
752
  Read a line using buffering
753
  If last line is empty (in line mode) then it isn't outputed
754
*/
755
756
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
757
READ_INFO::READ_INFO(int file_par, size_t tot_length,
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
758
                     const charset_info_st * const cs,
1 by brian
clean slate
759
		     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
760
		     String &enclosed_par, int escape, bool is_fifo)
1208.3.2 by brian
Update for Cursor renaming.
761
  :cursor(file_par),escape_char(escape)
1 by brian
clean slate
762
{
763
  read_charset= cs;
764
  field_term_ptr=(char*) field_term.ptr();
765
  field_term_length= field_term.length();
766
  line_term_ptr=(char*) line_term.ptr();
767
  line_term_length= line_term.length();
768
  if (line_start.length() == 0)
769
  {
770
    line_start_ptr=0;
771
    start_of_line= 0;
772
  }
773
  else
774
  {
775
    line_start_ptr=(char*) line_start.ptr();
776
    line_start_end=line_start_ptr+line_start.length();
777
    start_of_line= 1;
778
  }
779
  /* If field_terminator == line_terminator, don't use line_terminator */
780
  if (field_term_length == line_term_length &&
781
      !memcmp(field_term_ptr,line_term_ptr,field_term_length))
782
  {
783
    line_term_length=0;
784
    line_term_ptr=(char*) "";
785
  }
786
  enclosed_char= (enclosed_length=enclosed_par.length()) ?
481 by Brian Aker
Remove all of uchar.
787
    (unsigned char) enclosed_par[0] : INT_MAX;
788
  field_term_char= field_term_length ? (unsigned char) field_term_ptr[0] : INT_MAX;
789
  line_term_char= line_term_length ? (unsigned char) line_term_ptr[0] : INT_MAX;
1 by brian
clean slate
790
  error=eof=found_end_of_line=found_null=line_cuted=0;
791
  buff_length=tot_length;
792
793
794
  /* 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).
795
  size_t length= max(field_term_length,line_term_length)+1;
796
  set_if_bigger(length, line_start.length());
1253.1.6 by Monty Taylor
Moved mem_root functions into drizzled::memory:: namespace.
797
  stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
1 by brian
clean slate
798
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
799
  if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
971.6.11 by Eric Day
Removed purecov messages.
800
    error=1;
1 by brian
clean slate
801
  else
802
  {
803
    end_of_buff=buffer+buff_length;
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
804
    if (cache.init_io_cache((false) ? -1 : cursor, 0,
805
                            (false) ? internal::READ_NET :
806
                            (is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
807
                            MYF(MY_WME)))
1 by brian
clean slate
808
    {
971.6.11 by Eric Day
Removed purecov messages.
809
      free((unsigned char*) buffer);
1 by brian
clean slate
810
      error=1;
811
    }
812
    else
813
    {
814
      /*
815
	init_io_cache() will not initialize read_function member
816
	if the cache is READ_NET. So we work around the problem with a
817
	manual assignment
818
      */
819
      need_end_io_cache = 1;
820
    }
821
  }
822
}
823
824
825
READ_INFO::~READ_INFO()
826
{
827
  if (!error)
828
  {
829
    if (need_end_io_cache)
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
830
      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.
831
    free(buffer);
1 by brian
clean slate
832
    error=1;
833
  }
834
}
835
836
2385.3.13 by Olaf van der Spek
Refactor iocache
837
#define GET (stack_pos != stack ? *--stack_pos : cache.get())
1 by brian
clean slate
838
#define PUSH(A) *(stack_pos++)=(A)
839
840
482 by Brian Aker
Remove uint.
841
inline int READ_INFO::terminator(char *ptr,uint32_t length)
1 by brian
clean slate
842
{
843
  int chr=0;					// Keep gcc happy
482 by Brian Aker
Remove uint.
844
  uint32_t i;
1 by brian
clean slate
845
  for (i=1 ; i < length ; i++)
846
  {
847
    if ((chr=GET) != *++ptr)
848
    {
849
      break;
850
    }
851
  }
852
  if (i == length)
853
    return 1;
854
  PUSH(chr);
855
  while (i-- > 1)
481 by Brian Aker
Remove all of uchar.
856
    PUSH((unsigned char) *--ptr);
1 by brian
clean slate
857
  return 0;
858
}
859
860
861
int READ_INFO::read_field()
862
{
863
  int chr,found_enclosed_char;
481 by Brian Aker
Remove all of uchar.
864
  unsigned char *to,*new_buffer;
1 by brian
clean slate
865
866
  found_null=0;
867
  if (found_end_of_line)
868
    return 1;					// One have to call next_line
869
870
  /* Skip until we find 'line_start' */
871
872
  if (start_of_line)
873
  {						// Skip until line_start
874
    start_of_line=0;
875
    if (find_start_of_fields())
876
      return 1;
877
  }
878
  if ((chr=GET) == my_b_EOF)
879
  {
880
    found_end_of_line=eof=1;
881
    return 1;
882
  }
883
  to=buffer;
884
  if (chr == enclosed_char)
885
  {
886
    found_enclosed_char=enclosed_char;
481 by Brian Aker
Remove all of uchar.
887
    *to++=(unsigned char) chr;				// If error
1 by brian
clean slate
888
  }
889
  else
890
  {
891
    found_enclosed_char= INT_MAX;
892
    PUSH(chr);
893
  }
894
895
  for (;;)
896
  {
897
    while ( to < end_of_buff)
898
    {
899
      chr = GET;
900
      if ((my_mbcharlen(read_charset, chr) > 1) &&
901
          to+my_mbcharlen(read_charset, chr) <= end_of_buff)
902
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
903
        unsigned char* p = (unsigned char*)to;
904
        *to++ = chr;
905
        int ml = my_mbcharlen(read_charset, chr);
906
        int i;
907
        for (i=1; i<ml; i++) {
908
          chr = GET;
909
          if (chr == my_b_EOF)
910
            goto found_eof;
911
          *to++ = chr;
912
        }
913
        if (my_ismbchar(read_charset,
914
              (const char *)p,
915
              (const char *)to))
916
          continue;
917
        for (i=0; i<ml; i++)
918
          PUSH((unsigned char) *--to);
919
        chr = GET;
1 by brian
clean slate
920
      }
921
      if (chr == my_b_EOF)
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
922
        goto found_eof;
1 by brian
clean slate
923
      if (chr == escape_char)
924
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
925
        if ((chr=GET) == my_b_EOF)
926
        {
927
          *to++= (unsigned char) escape_char;
928
          goto found_eof;
929
        }
1 by brian
clean slate
930
        /*
931
          When escape_char == enclosed_char, we treat it like we do for
932
          handling quotes in SQL parsing -- you can double-up the
933
          escape_char to include it literally, but it doesn't do escapes
934
          like \n. This allows: LOAD DATA ... ENCLOSED BY '"' ESCAPED BY '"'
935
          with data like: "fie""ld1", "field2"
936
         */
937
        if (escape_char != enclosed_char || chr == escape_char)
938
        {
481 by Brian Aker
Remove all of uchar.
939
          *to++ = (unsigned char) unescape((char) chr);
1 by brian
clean slate
940
          continue;
941
        }
942
        PUSH(chr);
943
        chr= escape_char;
944
      }
945
#ifdef ALLOW_LINESEPARATOR_IN_STRINGS
946
      if (chr == line_term_char)
947
#else
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
948
        if (chr == line_term_char && found_enclosed_char == INT_MAX)
1 by brian
clean slate
949
#endif
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
950
        {
951
          if (terminator(line_term_ptr,line_term_length))
952
          {					// Maybe unexpected linefeed
953
            enclosed=0;
954
            found_end_of_line=1;
955
            row_start=buffer;
956
            row_end=  to;
957
            return 0;
958
          }
959
        }
1 by brian
clean slate
960
      if (chr == found_enclosed_char)
961
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
962
        if ((chr=GET) == found_enclosed_char)
963
        {					// Remove dupplicated
964
          *to++ = (unsigned char) chr;
965
          continue;
966
        }
967
        // End of enclosed field if followed by field_term or line_term
968
        if (chr == my_b_EOF ||
969
            (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
970
        {					// Maybe unexpected linefeed
971
          enclosed=1;
972
          found_end_of_line=1;
973
          row_start=buffer+1;
974
          row_end=  to;
975
          return 0;
976
        }
977
        if (chr == field_term_char &&
978
            terminator(field_term_ptr,field_term_length))
979
        {
980
          enclosed=1;
981
          row_start=buffer+1;
982
          row_end=  to;
983
          return 0;
984
        }
985
        /*
986
           The string didn't terminate yet.
987
           Store back next character for the loop
988
         */
989
        PUSH(chr);
990
        /* copy the found term character to 'to' */
991
        chr= found_enclosed_char;
1 by brian
clean slate
992
      }
993
      else if (chr == field_term_char && found_enclosed_char == INT_MAX)
994
      {
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
995
        if (terminator(field_term_ptr,field_term_length))
996
        {
997
          enclosed=0;
998
          row_start=buffer;
999
          row_end=  to;
1000
          return 0;
1001
        }
1 by brian
clean slate
1002
      }
481 by Brian Aker
Remove all of uchar.
1003
      *to++ = (unsigned char) chr;
1 by brian
clean slate
1004
    }
1005
    /*
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
1006
     ** We come here if buffer is too small. Enlarge it and continue
1007
     */
2318.6.90 by Olaf van der Spek
Refactor
1008
    new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE);
1 by brian
clean slate
1009
    to=new_buffer + (to-buffer);
1010
    buffer=new_buffer;
1011
    buff_length+=IO_SIZE;
1012
    end_of_buff=buffer+buff_length;
1013
  }
1014
1015
found_eof:
1016
  enclosed=0;
1017
  found_end_of_line=eof=1;
1018
  row_start=buffer;
1019
  row_end=to;
1020
  return 0;
1021
}
1022
1023
/*
1024
  Read a row with fixed length.
1025
1026
  NOTES
1027
    The row may not be fixed size on disk if there are escape
1208.3.2 by brian
Update for Cursor renaming.
1028
    characters in the cursor.
1 by brian
clean slate
1029
1030
  IMPLEMENTATION NOTE
1031
    One can't use fixed length with multi-byte charset **
1032
1033
  RETURN
1034
    0  ok
1035
    1  error
1036
*/
1037
1038
int READ_INFO::read_fixed_length()
1039
{
1040
  int chr;
481 by Brian Aker
Remove all of uchar.
1041
  unsigned char *to;
1 by brian
clean slate
1042
  if (found_end_of_line)
1043
    return 1;					// One have to call next_line
1044
1045
  if (start_of_line)
1046
  {						// Skip until line_start
1047
    start_of_line=0;
1048
    if (find_start_of_fields())
1049
      return 1;
1050
  }
1051
1052
  to=row_start=buffer;
1053
  while (to < end_of_buff)
1054
  {
1055
    if ((chr=GET) == my_b_EOF)
1056
      goto found_eof;
1057
    if (chr == escape_char)
1058
    {
1059
      if ((chr=GET) == my_b_EOF)
1060
      {
481 by Brian Aker
Remove all of uchar.
1061
	*to++= (unsigned char) escape_char;
1 by brian
clean slate
1062
	goto found_eof;
1063
      }
481 by Brian Aker
Remove all of uchar.
1064
      *to++ =(unsigned char) unescape((char) chr);
1 by brian
clean slate
1065
      continue;
1066
    }
1067
    if (chr == line_term_char)
1068
    {
1069
      if (terminator(line_term_ptr,line_term_length))
1070
      {						// Maybe unexpected linefeed
1071
	found_end_of_line=1;
1072
	row_end=  to;
1073
	return 0;
1074
      }
1075
    }
481 by Brian Aker
Remove all of uchar.
1076
    *to++ = (unsigned char) chr;
1 by brian
clean slate
1077
  }
1078
  row_end=to;					// Found full line
1079
  return 0;
1080
1081
found_eof:
1082
  found_end_of_line=eof=1;
1083
  row_start=buffer;
1084
  row_end=to;
1085
  return to == buffer ? 1 : 0;
1086
}
1087
1088
1089
int READ_INFO::next_line()
1090
{
1091
  line_cuted=0;
1092
  start_of_line= line_start_ptr != 0;
1093
  if (found_end_of_line || eof)
1094
  {
1095
    found_end_of_line=0;
1096
    return eof;
1097
  }
1098
  found_end_of_line=0;
1099
  if (!line_term_length)
1100
    return 0;					// No lines
1101
  for (;;)
1102
  {
1103
    int chr = GET;
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
1104
    if (my_mbcharlen(read_charset, chr) > 1)
1105
    {
1106
      for (uint32_t i=1;
1107
          chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
1108
          i++)
1109
        chr = GET;
1110
      if (chr == escape_char)
1111
        continue;
1112
    }
1113
    if (chr == my_b_EOF)
1114
    {
1 by brian
clean slate
1115
      eof=1;
1116
      return 1;
1117
    }
1118
    if (chr == escape_char)
1119
    {
1120
      line_cuted=1;
1121
      if (GET == my_b_EOF)
1085.3.3 by Monty Taylor
Got rid of #ifdef have utf8 stuff.
1122
        return 1;
1 by brian
clean slate
1123
      continue;
1124
    }
1125
    if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
1126
      return 0;
1127
    line_cuted=1;
1128
  }
1129
}
1130
1131
1132
bool READ_INFO::find_start_of_fields()
1133
{
1134
  int chr;
1135
 try_again:
1136
  do
1137
  {
1138
    if ((chr=GET) == my_b_EOF)
1139
    {
1140
      found_end_of_line=eof=1;
1141
      return 1;
1142
    }
1143
  } while ((char) chr != line_start_ptr[0]);
1144
  for (char *ptr=line_start_ptr+1 ; ptr != line_start_end ; ptr++)
1145
  {
1146
    chr=GET;					// Eof will be checked later
1147
    if ((char) chr != *ptr)
1148
    {						// Can't be line_start
1149
      PUSH(chr);
1150
      while (--ptr != line_start_ptr)
1151
      {						// Restart with next char
481 by Brian Aker
Remove all of uchar.
1152
	PUSH((unsigned char) *ptr);
1 by brian
clean slate
1153
      }
1154
      goto try_again;
1155
    }
1156
  }
1157
  return 0;
1158
}
1159
1160
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1161
} /* namespace drizzled */