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