~drizzle-trunk/drizzle/development

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