Drizzled Public API Documentation

sql_load.cc
00001 /* Copyright (C) 2000-2006 MySQL AB
00002    Copyright (C) 2011 Stewart Smith
00003 
00004    This program is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; version 2 of the License.
00007 
00008    This program is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011    GNU General Public License for more details.
00012 
00013    You should have received a copy of the GNU General Public License
00014    along with this program; if not, write to the Free Software
00015    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00016 
00017 
00018 /* Copy data from a textfile to table */
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;                /* Buffer for read text */
00051   unsigned char *end_of_buff;           /* Data in bufferts ends here */
00052   size_t buff_length;                   /* Length of buffert */
00053   size_t max_length;                    /* Max length of row */
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,     /* Found row starts here */
00065   *row_end;     /* Found row ends here */
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     We need to force cache close before destructor is invoked to log
00081     the last read block
00082   */
00083   void end_io_cache()
00084   {
00085     cache.end_io_cache();
00086     need_end_io_cache = 0;
00087   }
00088 
00089   /*
00090     Either this method, or we need to make cache public
00091     Arg must be set from load() since constructor does not see
00092     either the table or Session value
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   Execute LOAD DATA query
00111 
00112   SYNOPSYS
00113     load()
00114       session - current thread
00115       ex  - file_exchange object representing source cursor and its parsing rules
00116       table_list  - list of tables to which we are loading data
00117       fields_vars - list of fields and variables to which we read
00118                     data from cursor
00119       set_fields  - list of fields mentioned in set clause
00120       set_values  - expressions to assign to fields in previous list
00121       handle_duplicates - indicates whenever we should emit error or
00122                           replace row if we will meet duplicates.
00123       ignore -          - indicates whenever we should ignore duplicates
00124 
00125   RETURN VALUES
00126     true - error / false - success
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()); // This should never be null
00142 
00143   /*
00144     If path for cursor is not defined, we will use the current database.
00145     If this is not set, we will use the directory where the table to be
00146     loaded is located
00147   */
00148   util::string::ptr schema(session->schema());
00149   const char *tdb= (schema and not schema->empty()) ? schema->c_str() : table_list->getSchemaName(); // Result should never be null
00150   assert(tdb);
00151   uint32_t skip_lines= ex->skip_lines;
00152   bool transactional_table;
00153 
00154   /* Escape and enclosed character may be a utf8 4-byte character */
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     Let us emit an error if we are loading data to table which is used
00172     in subselect in SET clause like we do it for INSERT.
00173 
00174     The main thing to fix to remove this restriction is to ensure that the
00175     table is marked to be 'used for insert' in which case we should never
00176     mark this table as 'const table' (ie, one that has only one row).
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       Let us also prepare SET clause, altough it is probably empty
00196       in this case.
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   {           // Part field list
00204     /* TODO: use this conds for 'WITH CHECK OPTIONS' */
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       Check whenever TIMESTAMP field with auto-set feature specified
00211       explicitly.
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     /* Fix the expressions in SET clause */
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;     // Will be extended if needed
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       /* Read only allowed from within dir specified by secure_file_priv */
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   // if we are not in slave thread, the cursor must be:
00305   if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
00306         (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
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));      // no files in net reading
00337     return true;        // Can't allocate buffers
00338   }
00339 
00340   /*
00341    * Per the SQL standard, inserting NULL into a NOT NULL
00342    * field requires an error to be thrown.
00343    *
00344    * @NOTE
00345    *
00346    * NULL check and handling occurs in field_conv.cc
00347    */
00348   session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00349   session->cuted_fields=0L;
00350   /* Skip lines if there is a line terminator */
00351   if (ex->line_term->length())
00352   {
00353     /* ex->skip_lines needs to be preserved for logging */
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);        /* if pack_blob was used */
00396   table->copy_blobs=0;
00397   session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00398   /*
00399      simulated killing in the middle of per-row loop
00400      must be effective for binlogging
00401   */
00402   if (error) 
00403   {
00404     error= -1;        // Error on read
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   /* ok to client sent only after binlog write and engine commit */
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 ** Read of rows of fixed size + optional garage + optonal newline
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   We could implement this with a simple seek if:
00454   - We are not using DATA INFILE LOCAL
00455   - escape character is  ""
00456   - line starting prefix is ""
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       There is no variables in fields_vars list in this format so
00470       this conversion is safe.
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         No fields specified in fields_vars list can be null in this format.
00479         Mark field as not null, we should do this for each row because of
00480         restore_record...
00481       */
00482       field->set_notnull();
00483 
00484       if (pos == read_info.row_end)
00485       {
00486         session->cuted_fields++;      /* Not enough 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'; // Add temp null terminator for store()
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; /* Fills rest with space */
00509       }
00510     }
00511     if (pos != read_info.row_end)
00512     {
00513       session->cuted_fields++;      /* To long row */
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       We don't need to reset auto-increment field since we are restoring
00531       its default value at the beginning of each loop iteration.
00532     */
00533     if (read_info.next_line())      // Skip to next line
00534       break;
00535     if (read_info.line_cuted)
00536     {
00537       session->cuted_fields++;      /* To long row */
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       /* If this line is to be skipped we don't want to fill field or var */
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;     // Safe to change end marker
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       /* Have not read any field, thus input cursor is simply ended */
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             QQ: We probably should not throw warning for each field.
00679             But how about intention to always have the same number
00680             of warnings in Session::cuted_fields (and get rid of cuted_fields
00681             in the end ?)
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       We don't need to reset auto-increment field since we are restoring
00712       its default value at the beginning of each loop iteration.
00713     */
00714     if (read_info.next_line())      // Skip to next line
00715       break;
00716     if (read_info.line_cuted)
00717     {
00718       session->cuted_fields++;      /* To long row */
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 /* Unescape all escape characters, mark \N as null */
00732 
00733 char
00734 READ_INFO::unescape(char chr)
00735 {
00736   /* keep this switch synchornous with the ESCAPE_CHARS macro */
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;       // Ascii null
00743   case 'Z': return '\032';      // Win32 end of cursor
00744   case 'N': found_null=1;
00745 
00746     /* fall through */
00747   default:  return chr;
00748   }
00749 }
00750 
00751 
00752 /*
00753   Read a line using buffering
00754   If last line is empty (in line mode) then it isn't outputed
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   /* If field_terminator == line_terminator, don't use line_terminator */
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   /* Set of a stack for unget if long terminators */
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   init_io_cache() will not initialize read_function member
00817   if the cache is READ_NET. So we work around the problem with a
00818   manual assignment
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;          // Keep gcc happy
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;         // One have to call next_line
00870 
00871   /* Skip until we find 'line_start' */
00872 
00873   if (start_of_line)
00874   {           // Skip until line_start
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;        // If error
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           When escape_char == enclosed_char, we treat it like we do for
00933           handling quotes in SQL parsing -- you can double-up the
00934           escape_char to include it literally, but it doesn't do escapes
00935           like \n. This allows: LOAD DATA ... ENCLOSED BY '"' ESCAPED BY '"'
00936           with data like: "fie""ld1", "field2"
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           {         // Maybe unexpected linefeed
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         {         // Remove dupplicated
00965           *to++ = (unsigned char) chr;
00966           continue;
00967         }
00968         // End of enclosed field if followed by field_term or line_term
00969         if (chr == my_b_EOF ||
00970             (chr == line_term_char && terminator(line_term_ptr, line_term_length)))
00971         {         // Maybe unexpected linefeed
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            The string didn't terminate yet.
00988            Store back next character for the loop
00989          */
00990         PUSH(chr);
00991         /* copy the found term character to 'to' */
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      ** We come here if buffer is too small. Enlarge it and continue
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   Read a row with fixed length.
01026 
01027   NOTES
01028     The row may not be fixed size on disk if there are escape
01029     characters in the cursor.
01030 
01031   IMPLEMENTATION NOTE
01032     One can't use fixed length with multi-byte charset **
01033 
01034   RETURN
01035     0  ok
01036     1  error
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;         // One have to call next_line
01045 
01046   if (start_of_line)
01047   {           // Skip until line_start
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       {           // Maybe unexpected linefeed
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;         // Found full line
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;         // No lines
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;          // Eof will be checked later
01148     if ((char) chr != *ptr)
01149     {           // Can't be line_start
01150       PUSH(chr);
01151       while (--ptr != line_start_ptr)
01152       {           // Restart with next char
01153   PUSH((unsigned char) *ptr);
01154       }
01155       goto try_again;
01156     }
01157   }
01158   return 0;
01159 }
01160 
01161 
01162 } /* namespace drizzled */