~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2478.3.1 by Stewart Smith
Partially move towards using LOCAL catalog in all path generation by removing getDataHomeCatalog() and instead using catalog::local_identifier() around the place. We do a bit of prep work in the schema engine too. Next step is to remove chdir to 'local' and generate local as part of path to all objects.
2
   Copyright (C) 2011 Stewart Smith
1 by brian
clean slate
3
4
   This program is free software; you can redistribute it and/or modify
5
   it under the terms of the GNU General Public License as published by
6
   the Free Software Foundation; version 2 of the License.
7
8
   This program is distributed in the hope that it will be useful,
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
   GNU General Public License for more details.
12
13
   You should have received a copy of the GNU General Public License
14
   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.
15
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
16
17
18
/* Copy data from a textfile to table */
19
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
20
#include <config.h>
2148.7.12 by Brian Aker
Merge in header fixes.
21
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.
22
#include <drizzled/sql_load.h>
549 by Monty Taylor
Took gettext.h out of header files.
23
#include <drizzled/error.h>
2478.3.1 by Stewart Smith
Partially move towards using LOCAL catalog in all path generation by removing getDataHomeCatalog() and instead using catalog::local_identifier() around the place. We do a bit of prep work in the schema engine too. Next step is to remove chdir to 'local' and generate local as part of path to all objects.
24
#include <drizzled/catalog/local.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.
25
#include <drizzled/session.h>
26
#include <drizzled/sql_base.h>
1999.4.9 by Brian Aker
Created EPOCH
27
#include <drizzled/field/epoch.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
28
#include <drizzled/internal/my_sys.h>
29
#include <drizzled/internal/iocache.h>
30
#include <drizzled/plugin/storage_engine.h>
2234.1.4 by Olaf van der Spek
Refactor includes
31
#include <drizzled/sql_lex.h>
2239.1.1 by Olaf van der Spek
Refactor includes
32
#include <drizzled/copy_info.h>
33
#include <drizzled/file_exchange.h>
2239.1.9 by Olaf van der Spek
Refactor includes
34
#include <drizzled/util/test.h>
2241.3.4 by Olaf van der Spek
Refactor Session::transaction
35
#include <drizzled/session/transactions.h>
1 by brian
clean slate
36
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
37
#include <sys/stat.h>
38
#include <fcntl.h>
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
39
#include <algorithm>
1241.9.24 by Monty Taylor
Removed m_string.h from server_includes.h.
40
#include <climits>
1786.3.2 by Monty Taylor
Cleaned up the initial pass at this. It's not perfect, but it does work.
41
#include <boost/filesystem.hpp>
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
42
1786.3.2 by Monty Taylor
Cleaned up the initial pass at this. It's not perfect, but it does work.
43
namespace fs=boost::filesystem;
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
44
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
45
namespace drizzled
46
{
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
47
1 by brian
clean slate
48
class READ_INFO {
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
49
  int	cursor;
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
50
  unsigned char	*buffer;                /* Buffer for read text */
51
  unsigned char *end_of_buff;           /* Data in bufferts ends here */
52
  size_t buff_length;                   /* Length of buffert */
53
  size_t max_length;                    /* Max length of row */
1 by brian
clean slate
54
  char	*field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
55
  uint	field_term_length,line_term_length,enclosed_length;
56
  int	field_term_char,line_term_char,enclosed_char,escape_char;
57
  int	*stack,*stack_pos;
58
  bool	found_end_of_line,start_of_line,eof;
59
  bool  need_end_io_cache;
2296.1.1 by Mark Atwood
Merge in Fixes of Brian's IOCACHE.
60
  internal::io_cache_st cache;
1 by brian
clean slate
61
62
public:
63
  bool error,line_cuted,found_null,enclosed;
481 by Brian Aker
Remove all of uchar.
64
  unsigned char	*row_start,			/* Found row starts here */
1 by brian
clean slate
65
	*row_end;			/* Found row ends here */
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
66
  const charset_info_st *read_charset;
1 by brian
clean slate
67
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
68
  READ_INFO(int cursor, size_t tot_length, const charset_info_st * const cs,
1 by brian
clean slate
69
	    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
70
	    String &enclosed,int escape, bool is_fifo);
1 by brian
clean slate
71
  ~READ_INFO();
72
  int read_field();
73
  int read_fixed_length(void);
74
  int next_line(void);
75
  char unescape(char chr);
482 by Brian Aker
Remove uint.
76
  int terminator(char *ptr,uint32_t length);
1 by brian
clean slate
77
  bool find_start_of_fields();
78
79
  /*
80
    We need to force cache close before destructor is invoked to log
81
    the last read block
82
  */
83
  void end_io_cache()
84
  {
1909.1.1 by Brian Aker
Encapsulation of IO_CACHE.
85
    cache.end_io_cache();
1 by brian
clean slate
86
    need_end_io_cache = 0;
87
  }
88
89
  /*
90
    Either this method, or we need to make cache public
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
91
    Arg must be set from load() since constructor does not see
520.1.21 by Brian Aker
THD -> Session rename
92
    either the table or Session value
1 by brian
clean slate
93
  */
94
  void set_io_cache_arg(void* arg) { cache.arg = arg; }
95
};
96
1711.6.1 by Brian Aker
Style on structure cleanup
97
static int read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
98
                             List<Item> &fields_vars, List<Item> &set_fields,
99
                             List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
100
			     uint32_t skip_lines,
1 by brian
clean slate
101
			     bool ignore_check_option_errors);
1711.6.1 by Brian Aker
Style on structure cleanup
102
static int read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
103
                          List<Item> &fields_vars, List<Item> &set_fields,
104
                          List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
105
			  String &enclosed, uint32_t skip_lines,
1 by brian
clean slate
106
			  bool ignore_check_option_errors);
107
108
109
/*
110
  Execute LOAD DATA query
111
112
  SYNOPSYS
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
113
    load()
520.1.22 by Brian Aker
Second pass of thd cleanup
114
      session - current thread
1208.3.2 by brian
Update for Cursor renaming.
115
      ex  - file_exchange object representing source cursor and its parsing rules
1 by brian
clean slate
116
      table_list  - list of tables to which we are loading data
117
      fields_vars - list of fields and variables to which we read
1208.3.2 by brian
Update for Cursor renaming.
118
                    data from cursor
1 by brian
clean slate
119
      set_fields  - list of fields mentioned in set clause
120
      set_values  - expressions to assign to fields in previous list
121
      handle_duplicates - indicates whenever we should emit error or
122
                          replace row if we will meet duplicates.
123
      ignore -          - indicates whenever we should ignore duplicates
124
125
  RETURN VALUES
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
126
    true - error / false - success
1 by brian
clean slate
127
*/
128
2026.2.1 by Monty Taylor
Renamed things prefixed mysql_ or mysqld_
129
int load(Session *session,file_exchange *ex,TableList *table_list,
1 by brian
clean slate
130
	        List<Item> &fields_vars, List<Item> &set_fields,
131
                List<Item> &set_values,
919.1.2 by Brian Aker
Comitting the removal of server code for LOAD DATA "LOCAL" INFILE
132
                enum enum_duplicates handle_duplicates, bool ignore)
1 by brian
clean slate
133
{
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
134
  int file;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
135
  Table *table= NULL;
1 by brian
clean slate
136
  int error;
137
  String *field_term=ex->field_term,*escaped=ex->escaped;
138
  String *enclosed=ex->enclosed;
139
  bool is_fifo=0;
1874.1.1 by Brian Aker
Encapsulate schema_name it table_list.
140
141
  assert(table_list->getSchemaName()); // This should never be null
142
1 by brian
clean slate
143
  /*
1208.3.2 by brian
Update for Cursor renaming.
144
    If path for cursor is not defined, we will use the current database.
1 by brian
clean slate
145
    If this is not set, we will use the directory where the table to be
146
    loaded is located
147
  */
2269.1.7 by Olaf van der Spek
Use util::string::ptr
148
  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
149
  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
150
  assert(tdb);
307 by Brian Aker
Minor cleanups around ulong in kernel.
151
  uint32_t skip_lines= ex->skip_lines;
1 by brian
clean slate
152
  bool transactional_table;
153
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
154
  /* Escape and enclosed character may be a utf8 4-byte character */
155
  if (escaped->length() > 4 || enclosed->length() > 4)
1 by brian
clean slate
156
  {
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
157
    my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
2318.6.55 by Olaf van der Spek
Refactor
158
    return true;
1 by brian
clean slate
159
  }
1109.1.3 by Brian Aker
Move names around a bit (to align similar methods)
160
161
  if (session->openTablesLock(table_list))
2318.6.55 by Olaf van der Spek
Refactor
162
    return true;
1109.1.3 by Brian Aker
Move names around a bit (to align similar methods)
163
2227.4.8 by Olaf van der Spek
Session::lex()
164
  if (setup_tables_and_check_access(session, &session->lex().select_lex.context,
165
                                    &session->lex().select_lex.top_join_list,
1 by brian
clean slate
166
                                    table_list,
2227.4.8 by Olaf van der Spek
Session::lex()
167
                                    &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
168
     return(-1);
1 by brian
clean slate
169
170
  /*
171
    Let us emit an error if we are loading data to table which is used
172
    in subselect in SET clause like we do it for INSERT.
173
174
    The main thing to fix to remove this restriction is to ensure that the
175
    table is marked to be 'used for insert' in which case we should never
176
    mark this table as 'const table' (ie, one that has only one row).
177
  */
1220.1.13 by Brian Aker
Remove mysql_lock_have_duplicate() (we don't have merge, and our partition
178
  if (unique_table(table_list, table_list->next_global))
1 by brian
clean slate
179
  {
1874.1.2 by Brian Aker
Encapsulate table_name from table_list.
180
    my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
2318.6.55 by Olaf van der Spek
Refactor
181
    return true;
1 by brian
clean slate
182
  }
183
184
  table= table_list->table;
1208.3.2 by brian
Update for Cursor renaming.
185
  transactional_table= table->cursor->has_transactions();
1 by brian
clean slate
186
2183.2.19 by Olaf van der Spek
Use List::size()
187
  if (!fields_vars.size())
1 by brian
clean slate
188
  {
189
    Field **field;
1578.2.16 by Brian Aker
Merge in change to getTable() to private the field objects.
190
    for (field= table->getFields(); *field ; field++)
1 by brian
clean slate
191
      fields_vars.push_back(new Item_field(*field));
1005.2.12 by Monty Taylor
Moved some things to the API.
192
    table->setWriteSet();
1 by brian
clean slate
193
    table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
194
    /*
195
      Let us also prepare SET clause, altough it is probably empty
196
      in this case.
197
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
198
    if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
199
        setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
2318.6.55 by Olaf van der Spek
Refactor
200
      return true;
1 by brian
clean slate
201
  }
202
  else
203
  {						// Part field list
204
    /* TODO: use this conds for 'WITH CHECK OPTIONS' */
520.1.22 by Brian Aker
Second pass of thd cleanup
205
    if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
206
        setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
207
        check_that_all_fields_are_given_values(session, table, table_list))
2318.6.55 by Olaf van der Spek
Refactor
208
      return true;
1 by brian
clean slate
209
    /*
210
      Check whenever TIMESTAMP field with auto-set feature specified
211
      explicitly.
212
    */
213
    if (table->timestamp_field)
214
    {
1999.4.2 by Brian Aker
Encapsulate the field's position.
215
      if (table->isWriteSet(table->timestamp_field->position()))
216
      {
1 by brian
clean slate
217
        table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1999.4.2 by Brian Aker
Encapsulate the field's position.
218
      }
1 by brian
clean slate
219
      else
220
      {
1999.4.2 by Brian Aker
Encapsulate the field's position.
221
        table->setWriteSet(table->timestamp_field->position());
1 by brian
clean slate
222
      }
223
    }
224
    /* Fix the expressions in SET clause */
520.1.22 by Brian Aker
Second pass of thd cleanup
225
    if (setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
2318.6.55 by Olaf van der Spek
Refactor
226
      return true;
1 by brian
clean slate
227
  }
228
229
  table->mark_columns_needed_for_insert();
230
1014.2.5 by Monty Taylor
Replaced a malloc with a calloc. Resisted the urge to rewrite/replace the entire class.
231
  size_t tot_length=0;
1 by brian
clean slate
232
  bool use_blobs= 0, use_vars= 0;
2183.2.12 by Olaf van der Spek
Use List::begin()
233
  List<Item>::iterator it(fields_vars.begin());
1 by brian
clean slate
234
  Item *item;
235
236
  while ((item= it++))
237
  {
238
    Item *real_item= item->real_item();
239
240
    if (real_item->type() == Item::FIELD_ITEM)
241
    {
242
      Field *field= ((Item_field*)real_item)->field;
243
      if (field->flags & BLOB_FLAG)
244
      {
245
        use_blobs= 1;
246
        tot_length+= 256;			// Will be extended if needed
247
      }
248
      else
249
        tot_length+= field->field_length;
250
    }
251
    else if (item->type() == Item::STRING_ITEM)
252
      use_vars= 1;
253
  }
254
  if (use_blobs && !ex->line_term->length() && !field_term->length())
255
  {
256
    my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
257
	       MYF(0));
2318.6.55 by Olaf van der Spek
Refactor
258
    return true;
1 by brian
clean slate
259
  }
260
  if (use_vars && !field_term->length() && !enclosed->length())
261
  {
262
    my_error(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR, MYF(0));
2318.6.55 by Olaf van der Spek
Refactor
263
    return true;
1 by brian
clean slate
264
  }
265
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
266
  fs::path to_file(ex->file_name);
2478.3.1 by Stewart Smith
Partially move towards using LOCAL catalog in all path generation by removing getDataHomeCatalog() and instead using catalog::local_identifier() around the place. We do a bit of prep work in the schema engine too. Next step is to remove chdir to 'local' and generate local as part of path to all objects.
267
  fs::path target_path(fs::system_complete(catalog::local_identifier().getPath()));
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
268
  if (not to_file.has_root_directory())
269
  {
270
    int count_elements= 0;
271
    for (fs::path::iterator iter= to_file.begin();
272
         iter != to_file.end();
273
         ++iter, ++count_elements)
274
    { }
275
276
    if (count_elements == 1)
277
    {
278
      target_path /= tdb;
279
    }
280
    target_path /= to_file;
281
  }
282
  else
283
  {
284
    target_path= to_file;
285
  }
286
287
  if (not secure_file_priv.string().empty())
288
  {
1813.2.10 by Monty Taylor
Expand secure-file-priv once at startup rather than on each path check.
289
    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.
290
    {
291
      /* Read only allowed from within dir specified by secure_file_priv */
292
      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
2318.6.55 by Olaf van der Spek
Refactor
293
      return true;
673.3.8 by Stewart Smith
fix outfile_loaddata test for drizzle.
294
    }
1 by brian
clean slate
295
  }
296
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
297
  struct stat stat_info;
298
  if (stat(target_path.file_string().c_str(), &stat_info))
299
  {
300
    my_error(ER_FILE_NOT_FOUND, MYF(0), target_path.file_string().c_str(), errno);
2318.6.55 by Olaf van der Spek
Refactor
301
    return true;
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
302
  }
303
304
  // if we are not in slave thread, the cursor must be:
305
  if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
306
        (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
307
        ((stat_info.st_mode & S_IFREG) == S_IFREG ||
308
         (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
309
  {
310
    my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), target_path.file_string().c_str());
2318.6.55 by Olaf van der Spek
Refactor
311
    return true;
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
312
  }
313
  if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
314
    is_fifo = 1;
315
316
317
  if ((file=internal::my_open(target_path.file_string().c_str(), O_RDONLY,MYF(MY_WME))) < 0)
318
  {
319
    my_error(ER_CANT_OPEN_FILE, MYF(0), target_path.file_string().c_str(), errno);
2318.6.55 by Olaf van der Spek
Refactor
320
    return true;
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
321
  }
1711.6.1 by Brian Aker
Style on structure cleanup
322
  CopyInfo info;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
323
  memset(&info, 0, sizeof(info));
1 by brian
clean slate
324
  info.ignore= ignore;
325
  info.handle_duplicates=handle_duplicates;
326
  info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
327
2087.4.1 by Brian Aker
Merge in schema identifier.
328
  identifier::Schema identifier(*schema);
1014.3.1 by Brian Aker
Simplify the calling stack for getting schema collation. We need to extend
329
  READ_INFO read_info(file, tot_length,
1415 by Brian Aker
Mass overhaul to use schema_identifier.
330
                      ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(identifier),
331
		      *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
332
		      info.escape_char, is_fifo);
1 by brian
clean slate
333
  if (read_info.error)
334
  {
335
    if	(file >= 0)
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
336
      internal::my_close(file,MYF(0));			// no files in net reading
2318.6.55 by Olaf van der Spek
Refactor
337
    return true;				// Can't allocate buffers
1 by brian
clean slate
338
  }
339
685.4.1 by Jay Pipes
Enabled the null.test.
340
  /*
341
   * Per the SQL standard, inserting NULL into a NOT NULL
342
   * field requires an error to be thrown.
343
   *
344
   * @NOTE
345
   *
346
   * NULL check and handling occurs in field_conv.cc
347
   */
348
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
520.1.22 by Brian Aker
Second pass of thd cleanup
349
  session->cuted_fields=0L;
1 by brian
clean slate
350
  /* 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
351
  if (ex->line_term->length())
1 by brian
clean slate
352
  {
353
    /* ex->skip_lines needs to be preserved for logging */
354
    while (skip_lines > 0)
355
    {
356
      skip_lines--;
357
      if (read_info.next_line())
358
	break;
359
    }
360
  }
361
362
  if (!(error=test(read_info.error)))
363
  {
364
365
    table->next_number_field=table->found_next_number_field;
366
    if (ignore ||
367
	handle_duplicates == DUP_REPLACE)
1208.3.2 by brian
Update for Cursor renaming.
368
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1 by brian
clean slate
369
    if (handle_duplicates == DUP_REPLACE)
1208.3.2 by brian
Update for Cursor renaming.
370
        table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
371
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
1 by brian
clean slate
372
    table->copy_blobs=1;
373
2114.5.1 by Brian Aker
Additional abstract around time (this also makes the abort_on_warnings in
374
    session->setAbortOnWarning(true);
1 by brian
clean slate
375
266.1.23 by Monty Taylor
Removed load xml infile. Hope nobody liked it. Now the only thing we need xml.c
376
    if (!field_term->length() && !enclosed->length())
520.1.22 by Brian Aker
Second pass of thd cleanup
377
      error= read_fixed_length(session, info, table_list, fields_vars,
1 by brian
clean slate
378
                               set_fields, set_values, read_info,
379
			       skip_lines, ignore);
380
    else
520.1.22 by Brian Aker
Second pass of thd cleanup
381
      error= read_sep_field(session, info, table_list, fields_vars,
1 by brian
clean slate
382
                            set_fields, set_values, read_info,
383
			    *enclosed, skip_lines, ignore);
1208.3.2 by brian
Update for Cursor renaming.
384
    if (table->cursor->ha_end_bulk_insert() && !error)
1 by brian
clean slate
385
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
386
      table->print_error(errno, MYF(0));
1 by brian
clean slate
387
      error= 1;
388
    }
1208.3.2 by brian
Update for Cursor renaming.
389
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
390
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1 by brian
clean slate
391
    table->next_number_field=0;
392
  }
393
  if (file >= 0)
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
394
    internal::my_close(file,MYF(0));
1 by brian
clean slate
395
  free_blobs(table);				/* if pack_blob was used */
396
  table->copy_blobs=0;
1633.4.8 by Brian Aker
Update for count_cuted_fields.
397
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
398
  /*
1 by brian
clean slate
399
     simulated killing in the middle of per-row loop
400
     must be effective for binlogging
401
  */
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)
402
  if (error) 
1 by brian
clean slate
403
  {
404
    error= -1;				// Error on read
405
    goto err;
406
  }
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
407
408
  char msg[FN_REFLEN];
409
  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.
410
	   (info.records - info.copied), session->cuted_fields);
1 by brian
clean slate
411
1273.1.13 by Jay Pipes
Style cleanup around TransactionContext::modified_non_trans_table and dead code removal
412
  if (session->transaction.stmt.hasModifiedNonTransData())
413
    session->transaction.all.markModifiedNonTransData();
1 by brian
clean slate
414
415
  /* ok to client sent only after binlog write and engine commit */
1813.2.9 by Monty Taylor
Made data_home be fs::path natively.
416
  session->my_ok(info.copied + info.deleted, 0, 0L, msg);
1 by brian
clean slate
417
err:
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
418
  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
419
              session->transaction.stmt.hasModifiedNonTransData());
1208.3.2 by brian
Update for Cursor renaming.
420
  table->cursor->ha_release_auto_increment();
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
421
  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
422
  session->setAbortOnWarning(false);
423
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
424
  return(error);
1 by brian
clean slate
425
}
426
427
428
/****************************************************************************
429
** Read of rows of fixed size + optional garage + optonal newline
430
****************************************************************************/
431
432
static int
1711.6.1 by Brian Aker
Style on structure cleanup
433
read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
434
                  List<Item> &fields_vars, List<Item> &set_fields,
435
                  List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
436
                  uint32_t skip_lines, bool ignore_check_option_errors)
1 by brian
clean slate
437
{
2183.2.12 by Olaf van der Spek
Use List::begin()
438
  List<Item>::iterator it(fields_vars.begin());
1 by brian
clean slate
439
  Item_field *sql_field;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
440
  Table *table= table_list->table;
1 by brian
clean slate
441
  bool err;
442
443
  while (!read_info.read_fixed_length())
444
  {
1910.2.8 by Brian Aker
Enapsulate Kill.
445
    if (session->getKilled())
1 by brian
clean slate
446
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
447
      session->send_kill_message();
2318.6.77 by Olaf van der Spek
Refactor
448
      return 1;
1 by brian
clean slate
449
    }
450
    if (skip_lines)
451
    {
452
      /*
453
	We could implement this with a simple seek if:
454
	- We are not using DATA INFILE LOCAL
455
	- escape character is  ""
456
	- line starting prefix is ""
457
      */
458
      skip_lines--;
459
      continue;
460
    }
2183.2.7 by Olaf van der Spek
x
461
    it= fields_vars.begin();
481 by Brian Aker
Remove all of uchar.
462
    unsigned char *pos=read_info.row_start;
1859.2.14 by Brian Aker
Add support for --with-valgrind
463
#ifdef HAVE_VALGRIND
1 by brian
clean slate
464
    read_info.row_end[0]=0;
465
#endif
466
997.5.1 by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record
467
    table->restoreRecordAsDefault();
1 by brian
clean slate
468
    /*
469
      There is no variables in fields_vars list in this format so
470
      this conversion is safe.
471
    */
472
    while ((sql_field= (Item_field*) it++))
473
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
474
      Field *field= sql_field->field;
1 by brian
clean slate
475
      if (field == table->next_number_field)
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
476
        table->auto_increment_field_not_null= true;
1 by brian
clean slate
477
      /*
478
        No fields specified in fields_vars list can be null in this format.
479
        Mark field as not null, we should do this for each row because of
480
        restore_record...
481
      */
482
      field->set_notnull();
483
484
      if (pos == read_info.row_end)
485
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
486
        session->cuted_fields++;			/* Not enough fields */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
487
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
488
                            ER_WARN_TOO_FEW_RECORDS,
520.1.22 by Brian Aker
Second pass of thd cleanup
489
                            ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
1999.4.9 by Brian Aker
Created EPOCH
490
2046.2.1 by Brian Aker
First pass on micro timestamp.
491
        if (not field->maybe_null() and field->is_timestamp())
1999.4.9 by Brian Aker
Created EPOCH
492
            ((field::Epoch::pointer) field)->set_time();
1 by brian
clean slate
493
      }
494
      else
495
      {
482 by Brian Aker
Remove uint.
496
	uint32_t length;
481 by Brian Aker
Remove all of uchar.
497
	unsigned char save_chr;
895 by Brian Aker
Completion (?) of uint conversion.
498
	if ((length=(uint32_t) (read_info.row_end-pos)) >
1 by brian
clean slate
499
	    field->field_length)
1014.2.6 by Monty Taylor
Style move.
500
        {
1 by brian
clean slate
501
	  length=field->field_length;
1014.2.6 by Monty Taylor
Style move.
502
        }
503
	save_chr=pos[length];
504
        pos[length]='\0'; // Add temp null terminator for store()
1 by brian
clean slate
505
        field->store((char*) pos,length,read_info.read_charset);
506
	pos[length]=save_chr;
507
	if ((pos+=length) > read_info.row_end)
508
	  pos= read_info.row_end;	/* Fills rest with space */
509
      }
510
    }
511
    if (pos != read_info.row_end)
512
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
513
      session->cuted_fields++;			/* To long row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
514
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
515
                          ER_WARN_TOO_MANY_RECORDS,
516
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
1 by brian
clean slate
517
    }
518
1910.2.8 by Brian Aker
Enapsulate Kill.
519
    if (session->getKilled() ||
520.1.22 by Brian Aker
Second pass of thd cleanup
520
        fill_record(session, set_fields, set_values,
1 by brian
clean slate
521
                    ignore_check_option_errors))
2318.6.77 by Olaf van der Spek
Refactor
522
      return 1;
1 by brian
clean slate
523
520.1.22 by Brian Aker
Second pass of thd cleanup
524
    err= write_record(session, table, &info);
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
525
    table->auto_increment_field_not_null= false;
1 by brian
clean slate
526
    if (err)
2318.6.77 by Olaf van der Spek
Refactor
527
      return 1;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
528
1 by brian
clean slate
529
    /*
530
      We don't need to reset auto-increment field since we are restoring
531
      its default value at the beginning of each loop iteration.
532
    */
533
    if (read_info.next_line())			// Skip to next line
534
      break;
535
    if (read_info.line_cuted)
536
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
537
      session->cuted_fields++;			/* To long row */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
538
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
539
                          ER_WARN_TOO_MANY_RECORDS,
540
                          ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
1 by brian
clean slate
541
    }
520.1.22 by Brian Aker
Second pass of thd cleanup
542
    session->row_count++;
1 by brian
clean slate
543
  }
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
544
  return(test(read_info.error));
1 by brian
clean slate
545
}
546
547
548
549
static int
1711.6.1 by Brian Aker
Style on structure cleanup
550
read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
1 by brian
clean slate
551
               List<Item> &fields_vars, List<Item> &set_fields,
552
               List<Item> &set_values, READ_INFO &read_info,
307 by Brian Aker
Minor cleanups around ulong in kernel.
553
	       String &enclosed, uint32_t skip_lines,
1 by brian
clean slate
554
	       bool ignore_check_option_errors)
555
{
2183.2.12 by Olaf van der Spek
Use List::begin()
556
  List<Item>::iterator it(fields_vars.begin());
1 by brian
clean slate
557
  Item *item;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
558
  Table *table= table_list->table;
482 by Brian Aker
Remove uint.
559
  uint32_t enclosed_length;
1 by brian
clean slate
560
  bool err;
561
562
  enclosed_length=enclosed.length();
563
2183.2.7 by Olaf van der Spek
x
564
  for (;;it= fields_vars.begin())
1 by brian
clean slate
565
  {
1910.2.8 by Brian Aker
Enapsulate Kill.
566
    if (session->getKilled())
1 by brian
clean slate
567
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
568
      session->send_kill_message();
2318.6.77 by Olaf van der Spek
Refactor
569
      return 1;
1 by brian
clean slate
570
    }
571
997.5.1 by chris
Replace macros around unireg.h, store_record,restore_record,cmp_record,empty_record
572
    table->restoreRecordAsDefault();
1 by brian
clean slate
573
574
    while ((item= it++))
575
    {
482 by Brian Aker
Remove uint.
576
      uint32_t length;
481 by Brian Aker
Remove all of uchar.
577
      unsigned char *pos;
1 by brian
clean slate
578
      Item *real_item;
579
580
      if (read_info.read_field())
581
	break;
582
583
      /* If this line is to be skipped we don't want to fill field or var */
584
      if (skip_lines)
585
        continue;
586
587
      pos=read_info.row_start;
895 by Brian Aker
Completion (?) of uint conversion.
588
      length=(uint32_t) (read_info.row_end-pos);
1 by brian
clean slate
589
590
      real_item= item->real_item();
591
592
      if ((!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos, STRING_WITH_LEN("NULL")))) ||
593
	  (length == 1 && read_info.found_null))
594
      {
595
596
        if (real_item->type() == Item::FIELD_ITEM)
597
        {
598
          Field *field= ((Item_field *)real_item)->field;
599
          if (field->reset())
600
          {
601
            my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
520.1.22 by Brian Aker
Second pass of thd cleanup
602
                     session->row_count);
2318.6.77 by Olaf van der Spek
Refactor
603
            return 1;
1 by brian
clean slate
604
          }
605
          field->set_null();
2046.2.1 by Brian Aker
First pass on micro timestamp.
606
          if (not field->maybe_null())
1 by brian
clean slate
607
          {
2046.2.1 by Brian Aker
First pass on micro timestamp.
608
            if (field->is_timestamp())
1999.4.9 by Brian Aker
Created EPOCH
609
            {
610
              ((field::Epoch::pointer) field)->set_time();
611
            }
1 by brian
clean slate
612
            else if (field != table->next_number_field)
1999.4.9 by Brian Aker
Created EPOCH
613
            {
614
              field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_NULL_TO_NOTNULL, 1);
615
            }
1 by brian
clean slate
616
          }
617
	}
618
        else if (item->type() == Item::STRING_ITEM)
619
        {
620
          ((Item_user_var_as_out_param *)item)->set_null_value(
621
                                                  read_info.read_charset);
622
        }
623
        else
624
        {
625
          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
2318.6.77 by Olaf van der Spek
Refactor
626
          return 1;
1 by brian
clean slate
627
        }
628
629
	continue;
630
      }
631
632
      if (real_item->type() == Item::FIELD_ITEM)
633
      {
634
        Field *field= ((Item_field *)real_item)->field;
635
        field->set_notnull();
636
        read_info.row_end[0]=0;			// Safe to change end marker
637
        if (field == table->next_number_field)
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
638
          table->auto_increment_field_not_null= true;
1 by brian
clean slate
639
        field->store((char*) pos, length, read_info.read_charset);
640
      }
641
      else if (item->type() == Item::STRING_ITEM)
642
      {
2440.2.9 by Olaf van der Spek
Refactor
643
        ((Item_user_var_as_out_param *)item)->set_value(str_ref((char*) pos, length), read_info.read_charset);
1 by brian
clean slate
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 */