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