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