sql_load.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:20k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
  6.    (at your option) any later version.
  7.    
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16. /* Copy data from a textfile to table */
  17. #include "mysql_priv.h"
  18. #include <my_dir.h>
  19. #include <m_ctype.h>
  20. class READ_INFO {
  21.   File file;
  22.   byte *buffer, /* Buffer for read text */
  23. *end_of_buff; /* Data in bufferts ends here */
  24.   uint buff_length, /* Length of buffert */
  25. max_length; /* Max length of row */
  26.   char *field_term_ptr,*line_term_ptr,*line_start_ptr,*line_start_end;
  27.   uint field_term_length,line_term_length,enclosed_length;
  28.   int field_term_char,line_term_char,enclosed_char,escape_char;
  29.   int *stack,*stack_pos;
  30.   bool found_end_of_line,start_of_line,eof;
  31.   IO_CACHE cache;
  32.   NET *io_net;
  33. public:
  34.   bool error,line_cuted,found_null,enclosed;
  35.   byte *row_start, /* Found row starts here */
  36. *row_end; /* Found row ends here */
  37.   READ_INFO(File file,uint tot_length,
  38.     String &field_term,String &line_start,String &line_term,
  39.     String &enclosed,int escape,bool get_it_from_net, bool is_fifo);
  40.   ~READ_INFO();
  41.   int read_field();
  42.   int read_fixed_length(void);
  43.   int next_line(void);
  44.   char unescape(char chr);
  45.   int terminator(char *ptr,uint length);
  46.   bool find_start_of_fields();
  47. };
  48. static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,
  49.      List<Item> &fields, READ_INFO &read_info);
  50. static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
  51.   List<Item> &fields, READ_INFO &read_info,
  52.   String &enclosed);
  53. int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
  54.        List<Item> &fields, enum enum_duplicates handle_duplicates,
  55.        bool read_file_from_client,thr_lock_type lock_type)
  56. {
  57.   char name[FN_REFLEN];
  58.   File file;
  59.   TABLE *table;
  60.   int error;
  61.   uint save_skip_lines = ex->skip_lines;
  62.   String *field_term=ex->field_term,*escaped=ex->escaped,
  63.     *enclosed=ex->enclosed;
  64.   bool is_fifo=0;
  65.   DBUG_ENTER("mysql_load");
  66.   if (escaped->length() > 1 || enclosed->length() > 1)
  67.   {
  68.     my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
  69.        MYF(0));
  70.     DBUG_RETURN(-1);
  71.   }
  72.   if (!(table = open_ltable(thd,table_list,lock_type)))
  73.     DBUG_RETURN(-1);
  74.   if (!fields.elements)
  75.   {
  76.     Field **field;
  77.     for (field=table->field; *field ; field++)
  78.       fields.push_back(new Item_field(*field));
  79.   }
  80.   else
  81.   { // Part field list
  82.     thd->dupp_field=0;
  83.     if (setup_fields(thd,table_list,fields,1,0) < 0)
  84.       DBUG_RETURN(-1);
  85.     if (thd->dupp_field)
  86.     {
  87.       my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dupp_field->field_name);
  88.       DBUG_RETURN(-1);
  89.     }
  90.   }
  91.   uint tot_length=0;
  92.   bool use_blobs=0,use_timestamp=0;
  93.   List_iterator<Item> it(fields);
  94.   Item_field *field;
  95.   while ((field=(Item_field*) it++))
  96.   {
  97.     if (field->field->flags & BLOB_FLAG)
  98.     {
  99.       use_blobs=1;
  100.       tot_length+=256; // Will be extended if needed
  101.     }
  102.     else
  103.       tot_length+=field->field->field_length;
  104.     if (!field_term->length() && !(field->field->flags & NOT_NULL_FLAG))
  105.       field->field->set_notnull();
  106.     if (field->field == table->timestamp_field)
  107.       use_timestamp=1;
  108.   }
  109.   if (use_blobs && !ex->line_term->length() && !field_term->length())
  110.   {
  111.     my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
  112.        MYF(0));
  113.     DBUG_RETURN(-1);
  114.   }
  115.   /* We can't give an error in the middle when using LOCAL files */
  116.   if (read_file_from_client && handle_duplicates == DUP_ERROR)
  117.     handle_duplicates=DUP_IGNORE;
  118.   if (read_file_from_client && (thd->client_capabilities & CLIENT_LOCAL_FILES))
  119.   {
  120.     char tmp [FN_REFLEN+1],*end;
  121.     DBUG_PRINT("info",("reading local file"));
  122.     tmp[0] = (char) 251; /* NULL_LENGTH */
  123.     end=strnmov(tmp+1,ex->file_name,sizeof(tmp)-2);
  124.     (void) my_net_write(&thd->net,tmp,(uint) (end-tmp));
  125.     (void) net_flush(&thd->net);
  126.     file = -1;
  127.   }
  128.   else
  129.   {
  130.     read_file_from_client=0;
  131. #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
  132.     ex->file_name+=dirname_length(ex->file_name);
  133. #endif
  134.     if (!dirname_length(ex->file_name) &&
  135. strlen(ex->file_name)+strlen(mysql_data_home)+strlen(thd->db)+3 <
  136. FN_REFLEN)
  137.     {
  138.       (void) sprintf(name,"%s/%s/%s",mysql_data_home,thd->db,ex->file_name);
  139.       unpack_filename(name,name); /* Convert to system format */
  140.     }
  141.     else
  142.     {
  143.       unpack_filename(name,ex->file_name);
  144. #ifndef __WIN__
  145.       MY_STAT stat_info;
  146.       if (!my_stat(name,&stat_info,MYF(MY_WME)))
  147. DBUG_RETURN(-1);
  148.       
  149.       // the file must be:
  150.       if (!((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
  151. #ifndef __EMX__
  152.     (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
  153. #endif
  154.     ((stat_info.st_mode & S_IFREG) == S_IFREG ||
  155.      (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
  156.       {
  157. my_error(ER_TEXTFILE_NOT_READABLE,MYF(0),name);
  158. DBUG_RETURN(-1);
  159.       }
  160.       if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
  161. is_fifo = 1;
  162. #endif
  163.     }
  164.     if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
  165.       DBUG_RETURN(-1);
  166.   }
  167.   COPY_INFO info;
  168.   bzero((char*) &info,sizeof(info));
  169.   info.handle_duplicates=handle_duplicates;
  170.   info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
  171.   READ_INFO read_info(file,tot_length,*field_term,
  172.       *ex->line_start, *ex->line_term, *enclosed,
  173.       info.escape_char, read_file_from_client, is_fifo);
  174.   if (read_info.error)
  175.   {
  176.     if (file >= 0)
  177.       my_close(file,MYF(0)); // no files in net reading
  178.     DBUG_RETURN(-1); // Can't allocate buffers
  179.   }
  180.   restore_record(table,2);
  181.   thd->count_cuted_fields=1; /* calc cuted fields */
  182.   thd->cuted_fields=0L;
  183.   if (ex->line_term->length() && field_term->length())
  184.   {
  185.     while (ex->skip_lines--)
  186.     {
  187.       if (read_info.next_line())
  188. break;
  189.     }
  190.   }
  191.   if (!(error=test(read_info.error)))
  192.   {
  193.     uint save_time_stamp=table->time_stamp;
  194.     if (use_timestamp)
  195.       table->time_stamp=0;
  196.     table->next_number_field=table->found_next_number_field;
  197.     VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
  198.     if (handle_duplicates == DUP_IGNORE ||
  199. handle_duplicates == DUP_REPLACE)
  200.       table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
  201.     table->file->deactivate_non_unique_index((ha_rows) 0);
  202.     table->copy_blobs=1;
  203.     if (!field_term->length() && !enclosed->length())
  204.       error=read_fixed_length(thd,info,table,fields,read_info);
  205.     else
  206.       error=read_sep_field(thd,info,table,fields,read_info,*enclosed);
  207.     if (table->file->extra(HA_EXTRA_NO_CACHE) ||
  208. table->file->activate_all_index(thd))
  209.       error=1; /* purecov: inspected */
  210.     table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
  211.     table->time_stamp=save_time_stamp;
  212.     table->next_number_field=0;
  213.     if (thd->lock)
  214.     {
  215.       mysql_unlock_tables(thd, thd->lock);
  216.       thd->lock=0;
  217.     }
  218.   }
  219.   if  (file >= 0) my_close(file,MYF(0));
  220.   free_blobs(table); /* if pack_blob was used */
  221.   table->copy_blobs=0;
  222.   thd->count_cuted_fields=0; /* Don`t calc cuted fields */
  223.   if (error)
  224.     DBUG_RETURN(-1); // Error on read
  225.   sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted,
  226.   info.records-info.copied,thd->cuted_fields);
  227.   send_ok(&thd->net,info.copied+info.deleted,0L,name);
  228.   // on the slave thd->query is never initialized
  229.   if(!thd->slave_thread)
  230.     mysql_update_log.write(thd,thd->query,thd->query_length);
  231.   
  232.   if (!table->file->has_transactions())
  233.     thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
  234.   if (!read_file_from_client && mysql_bin_log.is_open())
  235.   {
  236.     ex->skip_lines = save_skip_lines; 
  237.     Load_log_event qinfo(thd, ex, table->table_name, fields, 
  238.  handle_duplicates);
  239.     mysql_bin_log.write(&qinfo);
  240.   }
  241.   DBUG_RETURN(0);
  242. }
  243. /****************************************************************************
  244. ** Read of rows of fixed size + optional garage + optonal newline
  245. ****************************************************************************/
  246. static int
  247. read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
  248.   READ_INFO &read_info)
  249. {
  250.   List_iterator<Item> it(fields);
  251.   Item_field *sql_field;
  252.   DBUG_ENTER("read_fixed_length");
  253.   /* No fields can be null in this format. mark all fields as not null */
  254.   while ((sql_field= (Item_field*) it++))
  255.       sql_field->field->set_notnull();
  256.   while (!read_info.read_fixed_length())
  257.   {
  258.     if (thd->killed)
  259.     {
  260.       my_error(ER_SERVER_SHUTDOWN,MYF(0));
  261.       DBUG_RETURN(1);
  262.     }
  263.     it.rewind();
  264.     byte *pos=read_info.row_start;
  265. #ifdef HAVE_purify
  266.     read_info.row_end[0]=0;
  267. #endif
  268.     while ((sql_field= (Item_field*) it++))
  269.     {
  270.       Field *field=sql_field->field;
  271.       if (pos == read_info.row_end)
  272.       {
  273. thd->cuted_fields++; /* Not enough fields */
  274. field->reset();
  275.       }
  276.       else
  277.       {
  278. uint length;
  279. byte save_chr;
  280. if ((length=(uint) (read_info.row_end-pos)) >
  281.     field->field_length)
  282.   length=field->field_length;
  283. save_chr=pos[length]; pos[length]=''; // Safeguard aganst malloc
  284. field->store((char*) pos,length);
  285. pos[length]=save_chr;
  286. if ((pos+=length) > read_info.row_end)
  287.   pos= read_info.row_end; /* Fills rest with space */
  288.       }
  289.     }
  290.     if (pos != read_info.row_end)
  291.       thd->cuted_fields++; /* To long row */
  292.     if (write_record(table,&info))
  293.       DBUG_RETURN(1);
  294.     if (table->next_number_field)
  295.       table->next_number_field->reset(); // Clear for next record
  296.     if (read_info.next_line()) // Skipp to next line
  297.       break;
  298.     if (read_info.line_cuted)
  299.       thd->cuted_fields++; /* To long row */
  300.   }
  301.   DBUG_RETURN(test(read_info.error));
  302. }
  303. static int
  304. read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
  305.        List<Item> &fields, READ_INFO &read_info,
  306.        String &enclosed)
  307. {
  308.   List_iterator<Item> it(fields);
  309.   Item_field *sql_field;
  310.   uint enclosed_length;
  311.   DBUG_ENTER("read_sep_field");
  312.   enclosed_length=enclosed.length();
  313.   for (;;it.rewind())
  314.   {
  315.     if (thd->killed)
  316.     {
  317.       my_error(ER_SERVER_SHUTDOWN,MYF(0));
  318.       DBUG_RETURN(1);
  319.     }
  320.     while ((sql_field=(Item_field*) it++))
  321.     {
  322.       uint length;
  323.       byte *pos;
  324.       if (read_info.read_field())
  325. break;
  326.       pos=read_info.row_start;
  327.       length=(uint) (read_info.row_end-pos);
  328.       Field *field=sql_field->field;
  329.       if (!read_info.enclosed &&
  330.   (enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) ||
  331.   (length == 1 && read_info.found_null))
  332.       {
  333. field->reset();
  334. field->set_null();
  335. if (!field->maybe_null())
  336. {
  337.   if (field->type() == FIELD_TYPE_TIMESTAMP)
  338.     ((Field_timestamp*) field)->set_time();
  339.   else
  340.     thd->cuted_fields++;
  341. }
  342. continue;
  343.       }
  344.       field->set_notnull();
  345.       read_info.row_end[0]=0; // Safe to change end marker
  346.       field->store((char*) read_info.row_start,length);
  347.     }
  348.     if (read_info.error)
  349.       break;
  350.     if (sql_field)
  351.     { // Last record
  352.       if (sql_field == (Item_field*) fields.head())
  353. break;
  354.       for ( ; sql_field ; sql_field=(Item_field*) it++)
  355.       {
  356. sql_field->field->set_null();
  357. sql_field->field->reset();
  358. thd->cuted_fields++;
  359.       }
  360.     }
  361.     if (write_record(table,&info))
  362.       DBUG_RETURN(1);
  363.     if (table->next_number_field)
  364.       table->next_number_field->reset(); // Clear for next record
  365.     if (read_info.next_line()) // Skipp to next line
  366.       break;
  367.     if (read_info.line_cuted)
  368.       thd->cuted_fields++; /* To long row */
  369.   }
  370.   DBUG_RETURN(test(read_info.error));
  371. }
  372. /* Unescape all escape characters, mark N as null */
  373. char
  374. READ_INFO::unescape(char chr)
  375. {
  376.   switch(chr) {
  377.   case 'n': return 'n';
  378.   case 't': return 't';
  379.   case 'r': return 'r';
  380.   case 'b': return 'b';
  381.   case '0': return 0; // Ascii null
  382.   case 'Z': return '32'; // Win32 end of file
  383.   case 'N': found_null=1;
  384.     /* fall through */
  385.   default:  return chr;
  386.   }
  387. }
  388. /* Read a line using buffering */
  389. /* If last line is empty (in line mode) then it isn't outputed */
  390. READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
  391.      String &line_start, String &line_term,
  392.      String &enclosed_par, int escape, bool get_it_from_net,
  393.      bool is_fifo)
  394.   :file(file_par),escape_char(escape)
  395. {
  396.   field_term_ptr=(char*) field_term.ptr();
  397.   field_term_length= field_term.length();
  398.   line_term_ptr=(char*) line_term.ptr();
  399.   line_term_length= line_term.length();
  400.   if (line_start.length() == 0)
  401.   {
  402.     line_start_ptr=0;
  403.     start_of_line= 0;
  404.   }
  405.   else
  406.   {
  407.     line_start_ptr=(char*) line_start.ptr();
  408.     line_start_end=line_start_ptr+line_start.length();
  409.     start_of_line= 1;
  410.   }
  411.   /* If field_terminator == line_terminator, don't use line_terminator */
  412.   if (field_term_length == line_term_length &&
  413.       !memcmp(field_term_ptr,line_term_ptr,field_term_length))
  414.   {
  415.     line_term_length=0;
  416.     line_term_ptr=(char*) "";
  417.   }
  418.   enclosed_char= (enclosed_length=enclosed_par.length()) ?
  419.     (uchar) enclosed_par[0] : INT_MAX;
  420.   field_term_char= field_term_length ? (uchar) field_term_ptr[0] : INT_MAX;
  421.   line_term_char= line_term_length ? (uchar) line_term_ptr[0] : INT_MAX;
  422.   error=eof=found_end_of_line=found_null=line_cuted=0;
  423.   buff_length=tot_length;
  424.   /* Set of a stack for unget if long terminators */
  425.   uint length=max(field_term_length,line_term_length)+1;
  426.   set_if_bigger(length,line_start.length());
  427.   stack=stack_pos=(int*) sql_alloc(sizeof(int)*length);
  428.   if (!(buffer=(byte*) my_malloc(buff_length+1,MYF(0))))
  429.     error=1; /* purecov: inspected */
  430.   else
  431.   {
  432.     end_of_buff=buffer+buff_length;
  433.     if (init_io_cache(&cache,(get_it_from_net) ? -1 : file, 0,
  434.       (get_it_from_net) ? READ_NET :
  435.       (is_fifo ? READ_FIFO : READ_CACHE),0L,1,
  436.       MYF(MY_WME)))
  437.     {
  438.       my_free((gptr) buffer,MYF(0)); /* purecov: inspected */
  439.       error=1;
  440.     }
  441.   }
  442. }
  443. READ_INFO::~READ_INFO()
  444. {
  445.   if (!error)
  446.   {
  447.     end_io_cache(&cache);
  448.     my_free((gptr) buffer,MYF(0));
  449.     error=1;
  450.   }
  451. }
  452. #define GET (stack_pos != stack ? *--stack_pos : my_b_get(&cache))
  453. #define PUSH(A) *(stack_pos++)=(A)
  454. inline int READ_INFO::terminator(char *ptr,uint length)
  455. {
  456.   int chr=0; // Keep gcc happy
  457.   uint i;
  458.   for (i=1 ; i < length ; i++)
  459.   {
  460.     if ((chr=GET) != *++ptr)
  461.     {
  462.       break;
  463.     }
  464.   }
  465.   if (i == length)
  466.     return 1;
  467.   PUSH(chr);
  468.   while (i-- > 1)
  469.     PUSH((uchar) *--ptr);
  470.   return 0;
  471. }
  472. int READ_INFO::read_field()
  473. {
  474.   int chr,found_enclosed_char;
  475.   byte *to,*new_buffer;
  476.   found_null=0;
  477.   if (found_end_of_line)
  478.     return 1; // One have to call next_line
  479.   /* Skipp until we find 'line_start' */
  480.   if (start_of_line)
  481.   { // Skipp until line_start
  482.     start_of_line=0;
  483.     if (find_start_of_fields())
  484.       return 1;
  485.   }
  486.   if ((chr=GET) == my_b_EOF)
  487.   {
  488.     found_end_of_line=eof=1;
  489.     return 1;
  490.   }
  491.   to=buffer;
  492.   if (chr == enclosed_char)
  493.   {
  494.     found_enclosed_char=enclosed_char;
  495.     *to++=(byte) chr; // If error
  496.   }
  497.   else
  498.   {
  499.     found_enclosed_char= INT_MAX;
  500.     PUSH(chr);
  501.   }
  502.   for (;;)
  503.   {
  504.     while ( to < end_of_buff)
  505.     {
  506.       chr = GET;
  507. #ifdef USE_MB
  508.       if (use_mb(default_charset_info) &&
  509.           my_ismbhead(default_charset_info, chr) &&
  510.           to+my_mbcharlen(default_charset_info, chr) <= end_of_buff)
  511.       {
  512.   uchar* p = (uchar*)to;
  513.   *to++ = chr;
  514.   int ml = my_mbcharlen(default_charset_info, chr);
  515.   int i;
  516.   for (i=1; i<ml; i++) {
  517.       chr = GET;
  518.       if (chr == my_b_EOF)
  519.   goto found_eof;
  520.       *to++ = chr;
  521.   }
  522.   if (my_ismbchar(default_charset_info,
  523.                           (const char *)p,
  524.                           (const char *)to))
  525.     continue;
  526.   for (i=0; i<ml; i++)
  527.     PUSH((uchar) *--to);
  528.   chr = GET;
  529.       }
  530. #endif
  531.       if (chr == my_b_EOF)
  532. goto found_eof;
  533.       if (chr == escape_char)
  534.       {
  535. if ((chr=GET) == my_b_EOF)
  536. {
  537.   *to++= (byte) escape_char;
  538.   goto found_eof;
  539. }
  540. *to++ = (byte) unescape((char) chr);
  541. continue;
  542.       }
  543. #ifdef ALLOW_LINESEPARATOR_IN_STRINGS
  544.       if (chr == line_term_char)
  545. #else
  546.       if (chr == line_term_char && found_enclosed_char == INT_MAX)
  547. #endif
  548.       {
  549. if (terminator(line_term_ptr,line_term_length))
  550. { // Maybe unexpected linefeed
  551.   enclosed=0;
  552.   found_end_of_line=1;
  553.   row_start=buffer;
  554.   row_end=  to;
  555.   return 0;
  556. }
  557.       }
  558.       if (chr == found_enclosed_char)
  559.       {
  560. if ((chr=GET) == found_enclosed_char)
  561. { // Remove dupplicated
  562.   *to++ = (byte) chr;
  563.   continue;
  564. }
  565. // End of enclosed field if followed by field_term or line_term
  566. if (chr == my_b_EOF ||
  567.     chr == line_term_char && terminator(line_term_ptr,
  568. line_term_length))
  569. { // Maybe unexpected linefeed
  570.   enclosed=1;
  571.   found_end_of_line=1;
  572.   row_start=buffer+1;
  573.   row_end=  to;
  574.   return 0;
  575. }
  576. if (chr == field_term_char &&
  577.     terminator(field_term_ptr,field_term_length))
  578. {
  579.   enclosed=1;
  580.   row_start=buffer+1;
  581.   row_end=  to;
  582.   return 0;
  583. }
  584. /* Copy the found '"' character */
  585. PUSH(chr);
  586. chr='"';
  587.       }
  588.       else if (chr == field_term_char && found_enclosed_char == INT_MAX)
  589.       {
  590. if (terminator(field_term_ptr,field_term_length))
  591. {
  592.   enclosed=0;
  593.   row_start=buffer;
  594.   row_end=  to;
  595.   return 0;
  596. }
  597.       }
  598.       *to++ = (byte) chr;
  599.     }
  600.     /*
  601.     ** We come here if buffer is too small. Enlarge it and continue
  602.     */
  603.     if (!(new_buffer=(byte*) my_realloc((char*) buffer,buff_length+1+IO_SIZE,
  604. MYF(MY_WME))))
  605.       return (error=1);
  606.     to=new_buffer + (to-buffer);
  607.     buffer=new_buffer;
  608.     buff_length+=IO_SIZE;
  609.     end_of_buff=buffer+buff_length;
  610.   }
  611. found_eof:
  612.   enclosed=0;
  613.   found_end_of_line=eof=1;
  614.   row_start=buffer;
  615.   row_end=to;
  616.   return 0;
  617. }
  618. /*
  619. ** One can't use fixed length with multi-byte charset **
  620. */
  621.  
  622. int READ_INFO::read_fixed_length()
  623. {
  624.   int chr;
  625.   byte *to;
  626.   if (found_end_of_line)
  627.     return 1; // One have to call next_line
  628.   if (start_of_line)
  629.   { // Skipp until line_start
  630.     start_of_line=0;
  631.     if (find_start_of_fields())
  632.       return 1;
  633.   }
  634.   to=row_start=buffer;
  635.   while (to < end_of_buff)
  636.   {
  637.     if ((chr=GET) == my_b_EOF)
  638.       goto found_eof;
  639.     if (chr == escape_char)
  640.     {
  641.       if ((chr=GET) == my_b_EOF)
  642.       {
  643. *to++= (byte) escape_char;
  644. goto found_eof;
  645.       }
  646.       *to++ =(byte) unescape((char) chr);
  647.       continue;
  648.     }
  649.     if (chr == line_term_char)
  650.     {
  651.       if (terminator(line_term_ptr,line_term_length))
  652.       { // Maybe unexpected linefeed
  653. found_end_of_line=1;
  654. row_end=  to;
  655. return 0;
  656.       }
  657.     }
  658.     *to++ = (byte) chr;
  659.   }
  660.   row_end=to; // Found full line
  661.   return 0;
  662. found_eof:
  663.   found_end_of_line=eof=1;
  664.   row_start=buffer;
  665.   row_end=to;
  666.   return to == buffer ? 1 : 0;
  667. }
  668. int READ_INFO::next_line()
  669. {
  670.   line_cuted=0;
  671.   start_of_line= line_start_ptr != 0;
  672.   if (found_end_of_line || eof)
  673.   {
  674.     found_end_of_line=0;
  675.     return eof;
  676.   }
  677.   found_end_of_line=0;
  678.   if (!line_term_length)
  679.     return 0; // No lines
  680.   for (;;)
  681.   {
  682.     int chr = GET;
  683. #ifdef USE_MB
  684.    if (use_mb(default_charset_info) && my_ismbhead(default_charset_info, chr))
  685.    {
  686.        for (int i=1;
  687.             chr != my_b_EOF && i<my_mbcharlen(default_charset_info, chr);
  688.             i++)
  689.    chr = GET;
  690.        if (chr == escape_char)
  691.    continue;
  692.    }
  693. #endif
  694.    if (chr == my_b_EOF)
  695.    {
  696.       eof=1;
  697.       return 1;
  698.     }
  699.     if (chr == escape_char)
  700.     {
  701.       line_cuted=1;
  702.       if (GET == my_b_EOF)
  703. return 1;
  704.       continue;
  705.     }
  706.     if (chr == line_term_char && terminator(line_term_ptr,line_term_length))
  707.       return 0;
  708.     line_cuted=1;
  709.   }
  710. }
  711. bool READ_INFO::find_start_of_fields()
  712. {
  713.   int chr;
  714.  try_again:
  715.   do
  716.   {
  717.     if ((chr=GET) == my_b_EOF)
  718.     {
  719.       found_end_of_line=eof=1;
  720.       return 1;
  721.     }
  722.   } while ((char) chr != line_start_ptr[0]);
  723.   for (char *ptr=line_start_ptr+1 ; ptr != line_start_end ; ptr++)
  724.   {
  725.     chr=GET; // Eof will be checked later
  726.     if ((char) chr != *ptr)
  727.     { // Can't be line_start
  728.       PUSH(chr);
  729.       while (--ptr != line_start_ptr)
  730.       { // Restart with next char
  731. PUSH((uchar) *ptr);
  732.       }
  733.       goto try_again;
  734.     }
  735.   }
  736.   return 0;
  737. }