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