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