00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/sql_load.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/catalog/local.h>
00025 #include <drizzled/session.h>
00026 #include <drizzled/sql_base.h>
00027 #include <drizzled/field/epoch.h>
00028 #include <drizzled/internal/my_sys.h>
00029 #include <drizzled/internal/iocache.h>
00030 #include <drizzled/plugin/storage_engine.h>
00031 #include <drizzled/sql_lex.h>
00032 #include <drizzled/copy_info.h>
00033 #include <drizzled/file_exchange.h>
00034 #include <drizzled/util/test.h>
00035 #include <drizzled/session/transactions.h>
00036
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #include <algorithm>
00040 #include <climits>
00041 #include <boost/filesystem.hpp>
00042
00043 namespace fs=boost::filesystem;
00044 using namespace std;
00045 namespace drizzled
00046 {
00047
00048 class READ_INFO {
00049 int cursor;
00050 unsigned char *buffer;
00051 unsigned char *end_of_buff;
00052 size_t buff_length;
00053 size_t max_length;
00054 char *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
00055 uint field_term_length,line_term_length,enclosed_length;
00056 int field_term_char,line_term_char,enclosed_char,escape_char;
00057 int *stack,*stack_pos;
00058 bool found_end_of_line,start_of_line,eof;
00059 bool need_end_io_cache;
00060 internal::io_cache_st cache;
00061
00062 public:
00063 bool error,line_cuted,found_null,enclosed;
00064 unsigned char *row_start,
00065 *row_end;
00066 const charset_info_st *read_charset;
00067
00068 READ_INFO(int cursor, size_t tot_length, const charset_info_st * const cs,
00069 String &field_term,String &line_start,String &line_term,
00070 String &enclosed,int escape, bool is_fifo);
00071 ~READ_INFO();
00072 int read_field();
00073 int read_fixed_length(void);
00074 int next_line(void);
00075 char unescape(char chr);
00076 int terminator(char *ptr,uint32_t length);
00077 bool find_start_of_fields();
00078
00079
00080
00081
00082
00083 void end_io_cache()
00084 {
00085 cache.end_io_cache();
00086 need_end_io_cache = 0;
00087 }
00088
00089
00090
00091
00092
00093
00094 void set_io_cache_arg(void* arg) { cache.arg = arg; }
00095 };
00096
00097 static int read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
00098 List<Item> &fields_vars, List<Item> &set_fields,
00099 List<Item> &set_values, READ_INFO &read_info,
00100 uint32_t skip_lines,
00101 bool ignore_check_option_errors);
00102 static int read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
00103 List<Item> &fields_vars, List<Item> &set_fields,
00104 List<Item> &set_values, READ_INFO &read_info,
00105 String &enclosed, uint32_t skip_lines,
00106 bool ignore_check_option_errors);
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 int load(Session *session,file_exchange *ex,TableList *table_list,
00130 List<Item> &fields_vars, List<Item> &set_fields,
00131 List<Item> &set_values,
00132 enum enum_duplicates handle_duplicates, bool ignore)
00133 {
00134 int file;
00135 Table *table= NULL;
00136 int error;
00137 String *field_term=ex->field_term,*escaped=ex->escaped;
00138 String *enclosed=ex->enclosed;
00139 bool is_fifo=0;
00140
00141 assert(table_list->getSchemaName());
00142
00143
00144
00145
00146
00147
00148 util::string::ptr schema(session->schema());
00149 const char *tdb= (schema and not schema->empty()) ? schema->c_str() : table_list->getSchemaName();
00150 assert(tdb);
00151 uint32_t skip_lines= ex->skip_lines;
00152 bool transactional_table;
00153
00154
00155 if (escaped->length() > 4 || enclosed->length() > 4)
00156 {
00157 my_error(ER_WRONG_FIELD_TERMINATORS,MYF(0),enclosed->c_ptr(), enclosed->length());
00158 return true;
00159 }
00160
00161 if (session->openTablesLock(table_list))
00162 return true;
00163
00164 if (setup_tables_and_check_access(session, &session->lex().select_lex.context,
00165 &session->lex().select_lex.top_join_list,
00166 table_list,
00167 &session->lex().select_lex.leaf_tables, true))
00168 return(-1);
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 if (unique_table(table_list, table_list->next_global))
00179 {
00180 my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
00181 return true;
00182 }
00183
00184 table= table_list->table;
00185 transactional_table= table->cursor->has_transactions();
00186
00187 if (!fields_vars.size())
00188 {
00189 Field **field;
00190 for (field= table->getFields(); *field ; field++)
00191 fields_vars.push_back(new Item_field(*field));
00192 table->setWriteSet();
00193 table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
00194
00195
00196
00197
00198 if (setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
00199 setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
00200 return true;
00201 }
00202 else
00203 {
00204
00205 if (setup_fields(session, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
00206 setup_fields(session, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
00207 check_that_all_fields_are_given_values(session, table, table_list))
00208 return true;
00209
00210
00211
00212
00213 if (table->timestamp_field)
00214 {
00215 if (table->isWriteSet(table->timestamp_field->position()))
00216 {
00217 table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
00218 }
00219 else
00220 {
00221 table->setWriteSet(table->timestamp_field->position());
00222 }
00223 }
00224
00225 if (setup_fields(session, 0, set_values, MARK_COLUMNS_READ, 0, 0))
00226 return true;
00227 }
00228
00229 table->mark_columns_needed_for_insert();
00230
00231 size_t tot_length=0;
00232 bool use_blobs= 0, use_vars= 0;
00233 List<Item>::iterator it(fields_vars.begin());
00234 Item *item;
00235
00236 while ((item= it++))
00237 {
00238 Item *real_item= item->real_item();
00239
00240 if (real_item->type() == Item::FIELD_ITEM)
00241 {
00242 Field *field= ((Item_field*)real_item)->field;
00243 if (field->flags & BLOB_FLAG)
00244 {
00245 use_blobs= 1;
00246 tot_length+= 256;
00247 }
00248 else
00249 tot_length+= field->field_length;
00250 }
00251 else if (item->type() == Item::STRING_ITEM)
00252 use_vars= 1;
00253 }
00254 if (use_blobs && !ex->line_term->length() && !field_term->length())
00255 {
00256 my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
00257 MYF(0));
00258 return true;
00259 }
00260 if (use_vars && !field_term->length() && !enclosed->length())
00261 {
00262 my_error(ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR, MYF(0));
00263 return true;
00264 }
00265
00266 fs::path to_file(ex->file_name);
00267 fs::path target_path(fs::system_complete(catalog::local_identifier().getPath()));
00268 if (not to_file.has_root_directory())
00269 {
00270 int count_elements= 0;
00271 for (fs::path::iterator iter= to_file.begin();
00272 iter != to_file.end();
00273 ++iter, ++count_elements)
00274 { }
00275
00276 if (count_elements == 1)
00277 {
00278 target_path /= tdb;
00279 }
00280 target_path /= to_file;
00281 }
00282 else
00283 {
00284 target_path= to_file;
00285 }
00286
00287 if (not secure_file_priv.string().empty())
00288 {
00289 if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
00290 {
00291
00292 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
00293 return true;
00294 }
00295 }
00296
00297 struct stat stat_info;
00298 if (stat(target_path.file_string().c_str(), &stat_info))
00299 {
00300 my_error(ER_FILE_NOT_FOUND, MYF(0), target_path.file_string().c_str(), errno);
00301 return true;
00302 }
00303
00304
00305 if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&
00306 (stat_info.st_mode & S_IFLNK) != S_IFLNK &&
00307 ((stat_info.st_mode & S_IFREG) == S_IFREG ||
00308 (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
00309 {
00310 my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), target_path.file_string().c_str());
00311 return true;
00312 }
00313 if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
00314 is_fifo = 1;
00315
00316
00317 if ((file=internal::my_open(target_path.file_string().c_str(), O_RDONLY,MYF(MY_WME))) < 0)
00318 {
00319 my_error(ER_CANT_OPEN_FILE, MYF(0), target_path.file_string().c_str(), errno);
00320 return true;
00321 }
00322 CopyInfo info;
00323 memset(&info, 0, sizeof(info));
00324 info.ignore= ignore;
00325 info.handle_duplicates=handle_duplicates;
00326 info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
00327
00328 identifier::Schema identifier(*schema);
00329 READ_INFO read_info(file, tot_length,
00330 ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(identifier),
00331 *field_term, *ex->line_start, *ex->line_term, *enclosed,
00332 info.escape_char, is_fifo);
00333 if (read_info.error)
00334 {
00335 if (file >= 0)
00336 internal::my_close(file,MYF(0));
00337 return true;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00349 session->cuted_fields=0L;
00350
00351 if (ex->line_term->length())
00352 {
00353
00354 while (skip_lines > 0)
00355 {
00356 skip_lines--;
00357 if (read_info.next_line())
00358 break;
00359 }
00360 }
00361
00362 if (!(error=test(read_info.error)))
00363 {
00364
00365 table->next_number_field=table->found_next_number_field;
00366 if (ignore ||
00367 handle_duplicates == DUP_REPLACE)
00368 table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
00369 if (handle_duplicates == DUP_REPLACE)
00370 table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
00371 table->cursor->ha_start_bulk_insert((ha_rows) 0);
00372 table->copy_blobs=1;
00373
00374 session->setAbortOnWarning(true);
00375
00376 if (!field_term->length() && !enclosed->length())
00377 error= read_fixed_length(session, info, table_list, fields_vars,
00378 set_fields, set_values, read_info,
00379 skip_lines, ignore);
00380 else
00381 error= read_sep_field(session, info, table_list, fields_vars,
00382 set_fields, set_values, read_info,
00383 *enclosed, skip_lines, ignore);
00384 if (table->cursor->ha_end_bulk_insert() && !error)
00385 {
00386 table->print_error(errno, MYF(0));
00387 error= 1;
00388 }
00389 table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
00390 table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
00391 table->next_number_field=0;
00392 }
00393 if (file >= 0)
00394 internal::my_close(file,MYF(0));
00395 free_blobs(table);
00396 table->copy_blobs=0;
00397 session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00398
00399
00400
00401
00402 if (error)
00403 {
00404 error= -1;
00405 goto err;
00406 }
00407
00408 char msg[FN_REFLEN];
00409 snprintf(msg, sizeof(msg), ER(ER_LOAD_INFO), info.records, info.deleted,
00410 (info.records - info.copied), session->cuted_fields);
00411
00412 if (session->transaction.stmt.hasModifiedNonTransData())
00413 session->transaction.all.markModifiedNonTransData();
00414
00415
00416 session->my_ok(info.copied + info.deleted, 0, 0L, msg);
00417 err:
00418 assert(transactional_table || !(info.copied || info.deleted) ||
00419 session->transaction.stmt.hasModifiedNonTransData());
00420 table->cursor->ha_release_auto_increment();
00421 table->auto_increment_field_not_null= false;
00422 session->setAbortOnWarning(false);
00423
00424 return(error);
00425 }
00426
00427
00428
00429
00430
00431
00432 static int
00433 read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
00434 List<Item> &fields_vars, List<Item> &set_fields,
00435 List<Item> &set_values, READ_INFO &read_info,
00436 uint32_t skip_lines, bool ignore_check_option_errors)
00437 {
00438 List<Item>::iterator it(fields_vars.begin());
00439 Item_field *sql_field;
00440 Table *table= table_list->table;
00441 bool err;
00442
00443 while (!read_info.read_fixed_length())
00444 {
00445 if (session->getKilled())
00446 {
00447 session->send_kill_message();
00448 return 1;
00449 }
00450 if (skip_lines)
00451 {
00452
00453
00454
00455
00456
00457
00458 skip_lines--;
00459 continue;
00460 }
00461 it= fields_vars.begin();
00462 unsigned char *pos=read_info.row_start;
00463 #ifdef HAVE_VALGRIND
00464 read_info.row_end[0]=0;
00465 #endif
00466
00467 table->restoreRecordAsDefault();
00468
00469
00470
00471
00472 while ((sql_field= (Item_field*) it++))
00473 {
00474 Field *field= sql_field->field;
00475 if (field == table->next_number_field)
00476 table->auto_increment_field_not_null= true;
00477
00478
00479
00480
00481
00482 field->set_notnull();
00483
00484 if (pos == read_info.row_end)
00485 {
00486 session->cuted_fields++;
00487 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00488 ER_WARN_TOO_FEW_RECORDS,
00489 ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
00490
00491 if (not field->maybe_null() and field->is_timestamp())
00492 ((field::Epoch::pointer) field)->set_time();
00493 }
00494 else
00495 {
00496 uint32_t length;
00497 unsigned char save_chr;
00498 if ((length=(uint32_t) (read_info.row_end-pos)) >
00499 field->field_length)
00500 {
00501 length=field->field_length;
00502 }
00503 save_chr=pos[length];
00504 pos[length]='\0';
00505 field->store((char*) pos,length,read_info.read_charset);
00506 pos[length]=save_chr;
00507 if ((pos+=length) > read_info.row_end)
00508 pos= read_info.row_end;
00509 }
00510 }
00511 if (pos != read_info.row_end)
00512 {
00513 session->cuted_fields++;
00514 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00515 ER_WARN_TOO_MANY_RECORDS,
00516 ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
00517 }
00518
00519 if (session->getKilled() ||
00520 fill_record(session, set_fields, set_values,
00521 ignore_check_option_errors))
00522 return 1;
00523
00524 err= write_record(session, table, &info);
00525 table->auto_increment_field_not_null= false;
00526 if (err)
00527 return 1;
00528
00529
00530
00531
00532
00533 if (read_info.next_line())
00534 break;
00535 if (read_info.line_cuted)
00536 {
00537 session->cuted_fields++;
00538 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00539 ER_WARN_TOO_MANY_RECORDS,
00540 ER(ER_WARN_TOO_MANY_RECORDS), session->row_count);
00541 }
00542 session->row_count++;
00543 }
00544 return(test(read_info.error));
00545 }
00546
00547
00548
00549 static int
00550 read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
00551 List<Item> &fields_vars, List<Item> &set_fields,
00552 List<Item> &set_values, READ_INFO &read_info,
00553 String &enclosed, uint32_t skip_lines,
00554 bool ignore_check_option_errors)
00555 {
00556 List<Item>::iterator it(fields_vars.begin());
00557 Item *item;
00558 Table *table= table_list->table;
00559 uint32_t enclosed_length;
00560 bool err;
00561
00562 enclosed_length=enclosed.length();
00563
00564 for (;;it= fields_vars.begin())
00565 {
00566 if (session->getKilled())
00567 {
00568 session->send_kill_message();
00569 return 1;
00570 }
00571
00572 table->restoreRecordAsDefault();
00573
00574 while ((item= it++))
00575 {
00576 uint32_t length;
00577 unsigned char *pos;
00578 Item *real_item;
00579
00580 if (read_info.read_field())
00581 break;
00582
00583
00584 if (skip_lines)
00585 continue;
00586
00587 pos=read_info.row_start;
00588 length=(uint32_t) (read_info.row_end-pos);
00589
00590 real_item= item->real_item();
00591
00592 if ((!read_info.enclosed && (enclosed_length && length == 4 && !memcmp(pos, STRING_WITH_LEN("NULL")))) ||
00593 (length == 1 && read_info.found_null))
00594 {
00595
00596 if (real_item->type() == Item::FIELD_ITEM)
00597 {
00598 Field *field= ((Item_field *)real_item)->field;
00599 if (field->reset())
00600 {
00601 my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
00602 session->row_count);
00603 return 1;
00604 }
00605 field->set_null();
00606 if (not field->maybe_null())
00607 {
00608 if (field->is_timestamp())
00609 {
00610 ((field::Epoch::pointer) field)->set_time();
00611 }
00612 else if (field != table->next_number_field)
00613 {
00614 field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_NULL_TO_NOTNULL, 1);
00615 }
00616 }
00617 }
00618 else if (item->type() == Item::STRING_ITEM)
00619 {
00620 ((Item_user_var_as_out_param *)item)->set_null_value(
00621 read_info.read_charset);
00622 }
00623 else
00624 {
00625 my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
00626 return 1;
00627 }
00628
00629 continue;
00630 }
00631
00632 if (real_item->type() == Item::FIELD_ITEM)
00633 {
00634 Field *field= ((Item_field *)real_item)->field;
00635 field->set_notnull();
00636 read_info.row_end[0]=0;
00637 if (field == table->next_number_field)
00638 table->auto_increment_field_not_null= true;
00639 field->store((char*) pos, length, read_info.read_charset);
00640 }
00641 else if (item->type() == Item::STRING_ITEM)
00642 {
00643 ((Item_user_var_as_out_param *)item)->set_value(str_ref((char*) pos, length), read_info.read_charset);
00644 }
00645 else
00646 {
00647 my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
00648 return 1;
00649 }
00650 }
00651 if (read_info.error)
00652 break;
00653 if (skip_lines)
00654 {
00655 skip_lines--;
00656 continue;
00657 }
00658 if (item)
00659 {
00660
00661 if (item == &fields_vars.front())
00662 break;
00663 for (; item ; item= it++)
00664 {
00665 Item *real_item= item->real_item();
00666 if (real_item->type() == Item::FIELD_ITEM)
00667 {
00668 Field *field= ((Item_field *)real_item)->field;
00669 if (field->reset())
00670 {
00671 my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
00672 session->row_count);
00673 return 1;
00674 }
00675 if (not field->maybe_null() and field->is_timestamp())
00676 ((field::Epoch::pointer) field)->set_time();
00677
00678
00679
00680
00681
00682
00683 session->cuted_fields++;
00684 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00685 ER_WARN_TOO_FEW_RECORDS,
00686 ER(ER_WARN_TOO_FEW_RECORDS), session->row_count);
00687 }
00688 else if (item->type() == Item::STRING_ITEM)
00689 {
00690 ((Item_user_var_as_out_param *)item)->set_null_value(
00691 read_info.read_charset);
00692 }
00693 else
00694 {
00695 my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
00696 return 1;
00697 }
00698 }
00699 }
00700
00701 if (session->getKilled() ||
00702 fill_record(session, set_fields, set_values,
00703 ignore_check_option_errors))
00704 return 1;
00705
00706 err= write_record(session, table, &info);
00707 table->auto_increment_field_not_null= false;
00708 if (err)
00709 return 1;
00710
00711
00712
00713
00714 if (read_info.next_line())
00715 break;
00716 if (read_info.line_cuted)
00717 {
00718 session->cuted_fields++;
00719 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
00720 ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
00721 session->row_count);
00722 if (session->getKilled())
00723 return 1;
00724 }
00725 session->row_count++;
00726 }
00727 return(test(read_info.error));
00728 }
00729
00730
00731
00732
00733 char
00734 READ_INFO::unescape(char chr)
00735 {
00736
00737 switch(chr) {
00738 case 'n': return '\n';
00739 case 't': return '\t';
00740 case 'r': return '\r';
00741 case 'b': return '\b';
00742 case '0': return 0;
00743 case 'Z': return '\032';
00744 case 'N': found_null=1;
00745
00746
00747 default: return chr;
00748 }
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758 READ_INFO::READ_INFO(int file_par, size_t tot_length,
00759 const charset_info_st * const cs,
00760 String &field_term, String &line_start, String &line_term,
00761 String &enclosed_par, int escape, bool is_fifo)
00762 :cursor(file_par),escape_char(escape)
00763 {
00764 read_charset= cs;
00765 field_term_ptr=(char*) field_term.ptr();
00766 field_term_length= field_term.length();
00767 line_term_ptr=(char*) line_term.ptr();
00768 line_term_length= line_term.length();
00769 if (line_start.length() == 0)
00770 {
00771 line_start_ptr=0;
00772 start_of_line= 0;
00773 }
00774 else
00775 {
00776 line_start_ptr=(char*) line_start.ptr();
00777 line_start_end=line_start_ptr+line_start.length();
00778 start_of_line= 1;
00779 }
00780
00781 if (field_term_length == line_term_length &&
00782 !memcmp(field_term_ptr,line_term_ptr,field_term_length))
00783 {
00784 line_term_length=0;
00785 line_term_ptr=(char*) "";
00786 }
00787 enclosed_char= (enclosed_length=enclosed_par.length()) ?
00788 (unsigned char) enclosed_par[0] : INT_MAX;
00789 field_term_char= field_term_length ? (unsigned char) field_term_ptr[0] : INT_MAX;
00790 line_term_char= line_term_length ? (unsigned char) line_term_ptr[0] : INT_MAX;
00791 error=eof=found_end_of_line=found_null=line_cuted=0;
00792 buff_length=tot_length;
00793
00794
00795
00796 size_t length= max(field_term_length,line_term_length)+1;
00797 set_if_bigger(length, line_start.length());
00798 stack= stack_pos= (int*) memory::sql_alloc(sizeof(int)*length);
00799
00800 if (!(buffer=(unsigned char*) calloc(1, buff_length+1)))
00801 error=1;
00802 else
00803 {
00804 end_of_buff=buffer+buff_length;
00805 if (cache.init_io_cache((false) ? -1 : cursor, 0,
00806 (false) ? internal::READ_NET :
00807 (is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
00808 MYF(MY_WME)))
00809 {
00810 free((unsigned char*) buffer);
00811 error=1;
00812 }
00813 else
00814 {
00815
00816
00817
00818
00819
00820 need_end_io_cache = 1;
00821 }
00822 }
00823 }
00824
00825
00826 READ_INFO::~READ_INFO()
00827 {
00828 if (!error)
00829 {
00830 if (need_end_io_cache)
00831 cache.end_io_cache();
00832 free(buffer);
00833 error=1;
00834 }
00835 }
00836
00837
00838 #define GET (stack_pos != stack ? *--stack_pos : cache.get())
00839 #define PUSH(A) *(stack_pos++)=(A)
00840
00841
00842 inline int READ_INFO::terminator(char *ptr,uint32_t length)
00843 {
00844 int chr=0;
00845 uint32_t i;
00846 for (i=1 ; i < length ; i++)
00847 {
00848 if ((chr=GET) != *++ptr)
00849 {
00850 break;
00851 }
00852 }
00853 if (i == length)
00854 return 1;
00855 PUSH(chr);
00856 while (i-- > 1)
00857 PUSH((unsigned char) *--ptr);
00858 return 0;
00859 }
00860
00861
00862 int READ_INFO::read_field()
00863 {
00864 int chr,found_enclosed_char;
00865 unsigned char *to,*new_buffer;
00866
00867 found_null=0;
00868 if (found_end_of_line)
00869 return 1;
00870
00871
00872
00873 if (start_of_line)
00874 {
00875 start_of_line=0;
00876 if (find_start_of_fields())
00877 return 1;
00878 }
00879 if ((chr=GET) == my_b_EOF)
00880 {
00881 found_end_of_line=eof=1;
00882 return 1;
00883 }
00884 to=buffer;
00885 if (chr == enclosed_char)
00886 {
00887 found_enclosed_char=enclosed_char;
00888 *to++=(unsigned char) chr;
00889 }
00890 else
00891 {
00892 found_enclosed_char= INT_MAX;
00893 PUSH(chr);
00894 }
00895
00896 for (;;)
00897 {
00898 while ( to < end_of_buff)
00899 {
00900 chr = GET;
00901 if ((my_mbcharlen(read_charset, chr) > 1) &&
00902 to+my_mbcharlen(read_charset, chr) <= end_of_buff)
00903 {
00904 unsigned char* p = (unsigned char*)to;
00905 *to++ = chr;
00906 int ml = my_mbcharlen(read_charset, chr);
00907 int i;
00908 for (i=1; i<ml; i++) {
00909 chr = GET;
00910 if (chr == my_b_EOF)
00911 goto found_eof;
00912 *to++ = chr;
00913 }
00914 if (my_ismbchar(read_charset,
00915 (const char *)p,
00916 (const char *)to))
00917 continue;
00918 for (i=0; i<ml; i++)
00919 PUSH((unsigned char) *--to);
00920 chr = GET;
00921 }
00922 if (chr == my_b_EOF)
00923 goto found_eof;
00924 if (chr == escape_char)
00925 {
00926 if ((chr=GET) == my_b_EOF)
00927 {
00928 *to++= (unsigned char) escape_char;
00929 goto found_eof;
00930 }
00931
00932
00933
00934
00935
00936
00937
00938 if (escape_char != enclosed_char || chr == escape_char)
00939 {
00940 *to++ = (unsigned char) unescape((char) chr);
00941 continue;
00942 }
00943 PUSH(chr);
00944 chr= escape_char;
00945 }
00946 #ifdef ALLOW_LINESEPARATOR_IN_STRINGS
00947 if (chr == line_term_char)
00948 #else
00949 if (chr == line_term_char && found_enclosed_char == INT_MAX)
00950 #endif
00951 {
00952 if (terminator(line_term_ptr,line_term_length))
00953 {
00954 enclosed=0;
00955 found_end_of_line=1;
00956 row_start=buffer;
00957 row_end= to;
00958 return 0;
00959 }
00960 }
00961 if (chr == found_enclosed_char)
00962 {
00963 if ((chr=GET) == found_enclosed_char)
00964 {
00965 *to++ = (unsigned char) chr;
00966 continue;
00967 }
00968
00969 if (chr == my_b_EOF ||
00970 (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
00971 {
00972 enclosed=1;
00973 found_end_of_line=1;
00974 row_start=buffer+1;
00975 row_end= to;
00976 return 0;
00977 }
00978 if (chr == field_term_char &&
00979 terminator(field_term_ptr,field_term_length))
00980 {
00981 enclosed=1;
00982 row_start=buffer+1;
00983 row_end= to;
00984 return 0;
00985 }
00986
00987
00988
00989
00990 PUSH(chr);
00991
00992 chr= found_enclosed_char;
00993 }
00994 else if (chr == field_term_char && found_enclosed_char == INT_MAX)
00995 {
00996 if (terminator(field_term_ptr,field_term_length))
00997 {
00998 enclosed=0;
00999 row_start=buffer;
01000 row_end= to;
01001 return 0;
01002 }
01003 }
01004 *to++ = (unsigned char) chr;
01005 }
01006
01007
01008
01009 new_buffer=(unsigned char*) realloc(buffer, buff_length+1+IO_SIZE);
01010 to=new_buffer + (to-buffer);
01011 buffer=new_buffer;
01012 buff_length+=IO_SIZE;
01013 end_of_buff=buffer+buff_length;
01014 }
01015
01016 found_eof:
01017 enclosed=0;
01018 found_end_of_line=eof=1;
01019 row_start=buffer;
01020 row_end=to;
01021 return 0;
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 int READ_INFO::read_fixed_length()
01040 {
01041 int chr;
01042 unsigned char *to;
01043 if (found_end_of_line)
01044 return 1;
01045
01046 if (start_of_line)
01047 {
01048 start_of_line=0;
01049 if (find_start_of_fields())
01050 return 1;
01051 }
01052
01053 to=row_start=buffer;
01054 while (to < end_of_buff)
01055 {
01056 if ((chr=GET) == my_b_EOF)
01057 goto found_eof;
01058 if (chr == escape_char)
01059 {
01060 if ((chr=GET) == my_b_EOF)
01061 {
01062 *to++= (unsigned char) escape_char;
01063 goto found_eof;
01064 }
01065 *to++ =(unsigned char) unescape((char) chr);
01066 continue;
01067 }
01068 if (chr == line_term_char)
01069 {
01070 if (terminator(line_term_ptr,line_term_length))
01071 {
01072 found_end_of_line=1;
01073 row_end= to;
01074 return 0;
01075 }
01076 }
01077 *to++ = (unsigned char) chr;
01078 }
01079 row_end=to;
01080 return 0;
01081
01082 found_eof:
01083 found_end_of_line=eof=1;
01084 row_start=buffer;
01085 row_end=to;
01086 return to == buffer ? 1 : 0;
01087 }
01088
01089
01090 int READ_INFO::next_line()
01091 {
01092 line_cuted=0;
01093 start_of_line= line_start_ptr != 0;
01094 if (found_end_of_line || eof)
01095 {
01096 found_end_of_line=0;
01097 return eof;
01098 }
01099 found_end_of_line=0;
01100 if (!line_term_length)
01101 return 0;
01102 for (;;)
01103 {
01104 int chr = GET;
01105 if (my_mbcharlen(read_charset, chr) > 1)
01106 {
01107 for (uint32_t i=1;
01108 chr != my_b_EOF && i<my_mbcharlen(read_charset, chr);
01109 i++)
01110 chr = GET;
01111 if (chr == escape_char)
01112 continue;
01113 }
01114 if (chr == my_b_EOF)
01115 {
01116 eof=1;
01117 return 1;
01118 }
01119 if (chr == escape_char)
01120 {
01121 line_cuted=1;
01122 if (GET == my_b_EOF)
01123 return 1;
01124 continue;
01125 }
01126 if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
01127 return 0;
01128 line_cuted=1;
01129 }
01130 }
01131
01132
01133 bool READ_INFO::find_start_of_fields()
01134 {
01135 int chr;
01136 try_again:
01137 do
01138 {
01139 if ((chr=GET) == my_b_EOF)
01140 {
01141 found_end_of_line=eof=1;
01142 return 1;
01143 }
01144 } while ((char) chr != line_start_ptr[0]);
01145 for (char *ptr=line_start_ptr+1 ; ptr != line_start_end ; ptr++)
01146 {
01147 chr=GET;
01148 if ((char) chr != *ptr)
01149 {
01150 PUSH(chr);
01151 while (--ptr != line_start_ptr)
01152 {
01153 PUSH((unsigned char) *ptr);
01154 }
01155 goto try_again;
01156 }
01157 }
01158 return 0;
01159 }
01160
01161
01162 }