records.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* Functions for easy reading of records, possible through a cache */
  14. #include "mysql_priv.h"
  15. static int rr_quick(READ_RECORD *info);
  16. static int rr_sequential(READ_RECORD *info);
  17. static int rr_from_tempfile(READ_RECORD *info);
  18. static int rr_unpack_from_tempfile(READ_RECORD *info);
  19. static int rr_unpack_from_buffer(READ_RECORD *info);
  20. static int rr_from_pointers(READ_RECORD *info);
  21. static int rr_from_cache(READ_RECORD *info);
  22. static int init_rr_cache(READ_RECORD *info);
  23. static int rr_cmp(uchar *a,uchar *b);
  24. static int rr_index_first(READ_RECORD *info);
  25. static int rr_index(READ_RECORD *info);
  26. /*
  27.   Initialize READ_RECORD structure to perform full index scan
  28.   SYNOPSIS 
  29.     init_read_record_idx()
  30.       info         READ_RECORD structure to initialize.
  31.       thd          Thread handle
  32.       table        Table to be accessed 
  33.       print_error  If true, call table->file->print_error() if an error
  34.                    occurs (except for end-of-records error)
  35.       idx          index to scan
  36.   
  37.   DESCRIPTION
  38.     Initialize READ_RECORD structure to perform full index scan (in forward
  39.     direction) using read_record.read_record() interface.
  40.     
  41.     This function has been added at late stage and is used only by
  42.     UPDATE/DELETE. Other statements perform index scans using
  43.     join_read_first/next functions.
  44. */
  45. void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
  46.                           bool print_error, uint idx)
  47. {
  48.   bzero((char*) info,sizeof(*info));
  49.   info->table= table;
  50.   info->file=  table->file;
  51.   info->record= table->record[0];
  52.   info->print_error= print_error;
  53.   table->status=0; /* And it's always found */
  54.   if (!table->file->inited)
  55.   {
  56.     table->file->ha_index_init(idx);
  57.     table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
  58.   }
  59.   /* read_record will be changed to rr_index in rr_index_first */
  60.   info->read_record= rr_index_first;
  61. }
  62. /* init struct for read with info->read_record */
  63. void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
  64.       SQL_SELECT *select,
  65.       int use_record_cache, bool print_error)
  66. {
  67.   IO_CACHE *tempfile;
  68.   DBUG_ENTER("init_read_record");
  69.   bzero((char*) info,sizeof(*info));
  70.   info->thd=thd;
  71.   info->table=table;
  72.   info->file= table->file;
  73.   info->forms= &info->table; /* Only one table */
  74.   if (table->sort.addon_field)
  75.   {
  76.     info->rec_buf= table->sort.addon_buf;
  77.     info->ref_length= table->sort.addon_length;
  78.   }
  79.   else
  80.   {
  81.     info->record= table->record[0];
  82.     info->ref_length= table->file->ref_length;
  83.   }
  84.   info->select=select;
  85.   info->print_error=print_error;
  86.   info->ignore_not_found_rows= 0;
  87.   table->status=0; /* And it's always found */
  88.   if (select && my_b_inited(&select->file))
  89.     tempfile= &select->file;
  90.   else
  91.     tempfile= table->sort.io_cache;
  92.   if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
  93.   {
  94.     DBUG_PRINT("info",("using rr_from_tempfile"));
  95.     info->read_record= (table->sort.addon_field ?
  96.                         rr_unpack_from_tempfile : rr_from_tempfile);
  97.     info->io_cache=tempfile;
  98.     reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
  99.     info->ref_pos=table->file->ref;
  100.     if (!table->file->inited)
  101.       table->file->ha_rnd_init(0);
  102.     /*
  103.       table->sort.addon_field is checked because if we use addon fields,
  104.       it doesn't make sense to use cache - we don't read from the table
  105.       and table->sort.io_cache is read sequentially
  106.     */
  107.     if (!table->sort.addon_field &&
  108.         ! (specialflag & SPECIAL_SAFE_MODE) &&
  109. thd->variables.read_rnd_buff_size &&
  110. !(table->file->table_flags() & HA_FAST_KEY_READ) &&
  111. (table->db_stat & HA_READ_ONLY ||
  112.  table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
  113. (ulonglong) table->reclength*(table->file->records+
  114.       table->file->deleted) >
  115. (ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
  116. info->io_cache->end_of_file/info->ref_length*table->reclength >
  117. (my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
  118. !table->blob_fields)
  119.     {
  120.       if (! init_rr_cache(info))
  121.       {
  122. DBUG_PRINT("info",("using rr_from_cache"));
  123. info->read_record=rr_from_cache;
  124.       }
  125.     }
  126.   }
  127.   else if (select && select->quick)
  128.   {
  129.     DBUG_PRINT("info",("using rr_quick"));
  130.     if (!table->file->inited)
  131.       table->file->ha_index_init(select->quick->index);
  132.     info->read_record=rr_quick;
  133.   }
  134.   else if (table->sort.record_pointers)
  135.   {
  136.     DBUG_PRINT("info",("using record_pointers"));
  137.     table->file->ha_rnd_init(0);
  138.     info->cache_pos=table->sort.record_pointers;
  139.     info->cache_end=info->cache_pos+ 
  140.                     table->sort.found_records*info->ref_length;
  141.     info->read_record= (table->sort.addon_field ?
  142.                         rr_unpack_from_buffer : rr_from_pointers);
  143.   }
  144.   else
  145.   {
  146.     DBUG_PRINT("info",("using rr_sequential"));
  147.     info->read_record=rr_sequential;
  148.     table->file->ha_rnd_init(1);
  149.     /* We can use record cache if we don't update dynamic length tables */
  150.     if (!table->no_cache &&
  151. (use_record_cache > 0 ||
  152.  (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
  153.  !(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
  154.  (use_record_cache < 0 &&
  155.   !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))))
  156.       VOID(table->file->extra_opt(HA_EXTRA_CACHE,
  157.   thd->variables.read_buff_size));
  158.   }
  159.   DBUG_VOID_RETURN;
  160. } /* init_read_record */
  161. void end_read_record(READ_RECORD *info)
  162. {                   /* free cache if used */
  163.   if (info->cache)
  164.   {
  165.     my_free_lock((char*) info->cache,MYF(0));
  166.     info->cache=0;
  167.   }
  168.   if (info->table)
  169.   {
  170.     filesort_free_buffers(info->table);
  171.     (void) info->file->extra(HA_EXTRA_NO_CACHE);
  172.     if (info->read_record != rr_quick) // otherwise quick_range does it
  173.       (void) info->file->ha_index_or_rnd_end();
  174.     info->table=0;
  175.   }
  176. }
  177. static int rr_handle_error(READ_RECORD *info, int error)
  178. {
  179.   if (error == HA_ERR_END_OF_FILE)
  180.     error= -1;
  181.   else
  182.   {
  183.     if (info->print_error)
  184.       info->table->file->print_error(error, MYF(0));
  185.     if (error < 0)                            // Fix negative BDB errno
  186.       error= 1;
  187.   }
  188.   return error;
  189. }
  190. /* Read a record from head-database */
  191. static int rr_quick(READ_RECORD *info)
  192. {
  193.   int tmp;
  194.   while ((tmp= info->select->quick->get_next()))
  195.   {
  196.     if (info->thd->killed)
  197.     {
  198.       my_error(ER_SERVER_SHUTDOWN, MYF(0));
  199.       return 1;
  200.     }
  201.     if (tmp != HA_ERR_RECORD_DELETED)
  202.     {
  203.       tmp= rr_handle_error(info, tmp);
  204.       break;
  205.     }
  206.   }
  207.   return tmp;
  208. }
  209. /*
  210.   Reads first row in an index scan
  211.   SYNOPSIS
  212.     rr_index_first()
  213.     info   Scan info
  214.   
  215.   RETURN
  216.     0   Ok
  217.     -1  End of records 
  218.     1   Error   
  219. */
  220. static int rr_index_first(READ_RECORD *info)
  221. {
  222.   int tmp= info->file->index_first(info->record);
  223.   info->read_record= rr_index;
  224.   if (tmp)
  225.     tmp= rr_handle_error(info, tmp);
  226.   return tmp;
  227. }
  228. /*
  229.   Reads index sequentially after first row
  230.   SYNOPSIS
  231.     rr_index()
  232.       info  Scan info
  233.   
  234.   DESCRIPTION
  235.     Read the next index record (in forward direction) and translate return
  236.     value.
  237.     
  238.   RETURN
  239.     0   Ok
  240.     -1  End of records 
  241.     1   Error   
  242. */
  243. static int rr_index(READ_RECORD *info)
  244. {
  245.   int tmp= info->file->index_next(info->record);
  246.   if (tmp)
  247.     tmp= rr_handle_error(info, tmp);
  248.   return tmp;
  249. }
  250. static int rr_sequential(READ_RECORD *info)
  251. {
  252.   int tmp;
  253.   while ((tmp=info->file->rnd_next(info->record)))
  254.   {
  255.     if (info->thd->killed)
  256.     {
  257.       my_error(ER_SERVER_SHUTDOWN,MYF(0));
  258.       return 1;
  259.     }
  260.     /*
  261.       rnd_next can return RECORD_DELETED for MyISAM when one thread is
  262.       reading and another deleting without locks.
  263.     */
  264.     if (tmp != HA_ERR_RECORD_DELETED)
  265.     {
  266.       tmp= rr_handle_error(info, tmp);
  267.       break;
  268.     }
  269.   }
  270.   return tmp;
  271. }
  272. static int rr_from_tempfile(READ_RECORD *info)
  273. {
  274.   int tmp;
  275.   for (;;)
  276.   {
  277.     if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
  278.       return -1; /* End of file */
  279.     if (!(tmp=info->file->rnd_pos(info->record,info->ref_pos)))
  280.       break;
  281.     /* The following is extremely unlikely to happen */
  282.     if (tmp == HA_ERR_RECORD_DELETED ||
  283.         (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
  284.       continue;
  285.     tmp= rr_handle_error(info, tmp);
  286.     break;
  287.   }
  288.   return tmp;
  289. } /* rr_from_tempfile */
  290. /*
  291.   Read a result set record from a temporary file after sorting
  292.   SYNOPSIS
  293.     rr_unpack_from_tempfile()
  294.     info                Reference to the context including record descriptors
  295.   DESCRIPTION
  296.     The function first reads the next sorted record from the temporary file.
  297.     into a buffer. If a success it calls a callback function that unpacks 
  298.     the fields values use in the result set from this buffer into their
  299.     positions in the regular record buffer.
  300.   RETURN
  301.      0 - Record successfully read.
  302.     -1 - There is no record to be read anymore. 
  303. */
  304. static int rr_unpack_from_tempfile(READ_RECORD *info)
  305. {
  306.   if (my_b_read(info->io_cache, info->rec_buf, info->ref_length))
  307.     return -1;
  308.   TABLE *table= info->table;
  309.   (*table->sort.unpack)(table->sort.addon_field, info->rec_buf);
  310.   return 0;
  311. }
  312. static int rr_from_pointers(READ_RECORD *info)
  313. {
  314.   int tmp;
  315.   byte *cache_pos;
  316.   for (;;)
  317.   {
  318.     if (info->cache_pos == info->cache_end)
  319.       return -1; /* End of file */
  320.     cache_pos= info->cache_pos;
  321.     info->cache_pos+= info->ref_length;
  322.     if (!(tmp=info->file->rnd_pos(info->record,cache_pos)))
  323.       break;
  324.     /* The following is extremely unlikely to happen */
  325.     if (tmp == HA_ERR_RECORD_DELETED ||
  326.         (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
  327.       continue;
  328.     tmp= rr_handle_error(info, tmp);
  329.     break;
  330.   }
  331.   return tmp;
  332. }
  333. /*
  334.   Read a result set record from a buffer after sorting
  335.   SYNOPSIS
  336.     rr_unpack_from_buffer()
  337.     info                   Reference to the context including record descriptors
  338.   DESCRIPTION
  339.     The function first reads the next sorted record from the sort buffer.
  340.     If a success it calls a callback function that unpacks 
  341.     the fields values use in the result set from this buffer into their
  342.     positions in the regular record buffer.
  343.   RETURN
  344.      0 - Record successfully read.
  345.     -1 - There is no record to be read anymore. 
  346. */
  347. static int rr_unpack_from_buffer(READ_RECORD *info)
  348. {
  349.   if (info->cache_pos == info->cache_end)
  350.     return -1;                      /* End of buffer */
  351.   TABLE *table= info->table;
  352.   (*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
  353.   info->cache_pos+= info->ref_length;
  354.   return 0;
  355. }
  356. /* cacheing of records from a database */
  357. static int init_rr_cache(READ_RECORD *info)
  358. {
  359.   uint rec_cache_size;
  360.   THD *thd= current_thd;
  361.   DBUG_ENTER("init_rr_cache");
  362.   info->struct_length=3+MAX_REFLENGTH;
  363.   info->reclength=ALIGN_SIZE(info->table->reclength+1);
  364.   if (info->reclength < info->struct_length)
  365.     info->reclength=ALIGN_SIZE(info->struct_length);
  366.   info->error_offset=info->table->reclength;
  367.   info->cache_records= thd->variables.read_rnd_buff_size /
  368.     (info->reclength+info->struct_length);
  369.   rec_cache_size=info->cache_records*info->reclength;
  370.   info->rec_cache_size=info->cache_records*info->ref_length;
  371.   // We have to allocate one more byte to use uint3korr (see comments for it)
  372.   if (info->cache_records <= 2 ||
  373.       !(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records*
  374.    info->struct_length+1,
  375.    MYF(0))))
  376.     DBUG_RETURN(1);
  377. #ifdef HAVE_purify
  378.   bzero(info->cache,rec_cache_size); // Avoid warnings in qsort
  379. #endif
  380.   DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
  381.   info->read_positions=info->cache+rec_cache_size;
  382.   info->cache_pos=info->cache_end=info->cache;
  383.   DBUG_RETURN(0);
  384. } /* init_rr_cache */
  385. static int rr_from_cache(READ_RECORD *info)
  386. {
  387.   reg1 uint i;
  388.   ulong length;
  389.   my_off_t rest_of_file;
  390.   int16 error;
  391.   byte *position,*ref_position,*record_pos;
  392.   ulong record;
  393.   for (;;)
  394.   {
  395.     if (info->cache_pos != info->cache_end)
  396.     {
  397.       if (info->cache_pos[info->error_offset])
  398.       {
  399. shortget(error,info->cache_pos);
  400. if (info->print_error)
  401.   info->table->file->print_error(error,MYF(0));
  402.       }
  403.       else
  404.       {
  405. error=0;
  406. memcpy(info->record,info->cache_pos,(size_t) info->table->reclength);
  407.       }
  408.       info->cache_pos+=info->reclength;
  409.       return ((int) error);
  410.     }
  411.     length=info->rec_cache_size;
  412.     rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
  413.     if ((my_off_t) length > rest_of_file)
  414.       length= (ulong) rest_of_file;
  415.     if (!length || my_b_read(info->io_cache,info->cache,length))
  416.     {
  417.       DBUG_PRINT("info",("Found end of file"));
  418.       return -1; /* End of file */
  419.     }
  420.     length/=info->ref_length;
  421.     position=info->cache;
  422.     ref_position=info->read_positions;
  423.     for (i=0 ; i < length ; i++,position+=info->ref_length)
  424.     {
  425.       memcpy(ref_position,position,(size_s) info->ref_length);
  426.       ref_position+=MAX_REFLENGTH;
  427.       int3store(ref_position,(long) i);
  428.       ref_position+=3;
  429.     }
  430.     qsort(info->read_positions,length,info->struct_length,(qsort_cmp) rr_cmp);
  431.     position=info->read_positions;
  432.     for (i=0 ; i < length ; i++)
  433.     {
  434.       memcpy(info->ref_pos,position,(size_s) info->ref_length);
  435.       position+=MAX_REFLENGTH;
  436.       record=uint3korr(position);
  437.       position+=3;
  438.       record_pos=info->cache+record*info->reclength;
  439.       if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos)))
  440.       {
  441. record_pos[info->error_offset]=1;
  442. shortstore(record_pos,error);
  443. DBUG_PRINT("error",("Got error: %d:%d when reading row",
  444.     my_errno, error));
  445.       }
  446.       else
  447. record_pos[info->error_offset]=0;
  448.     }
  449.     info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
  450.   }
  451. } /* rr_from_cache */
  452. static int rr_cmp(uchar *a,uchar *b)
  453. {
  454.   if (a[0] != b[0])
  455.     return (int) a[0] - (int) b[0];
  456.   if (a[1] != b[1])
  457.     return (int) a[1] - (int) b[1];
  458.   if (a[2] != b[2])
  459.     return (int) a[2] - (int) b[2];
  460. #if MAX_REFLENGTH == 4
  461.   return (int) a[3] - (int) b[3];
  462. #else
  463.   if (a[3] != b[3])
  464.     return (int) a[3] - (int) b[3];
  465.   if (a[4] != b[4])
  466.     return (int) a[4] - (int) b[4];
  467.   if (a[5] != b[5])
  468.     return (int) a[1] - (int) b[5];
  469.   if (a[6] != b[6])
  470.     return (int) a[6] - (int) b[6];
  471.   return (int) a[7] - (int) b[7];
  472. #endif
  473. }