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