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

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. /* Functions to read, write and lock records */
  17. #include "mysql_priv.h"
  18. static int rr_quick(READ_RECORD *info);
  19. static int rr_sequential(READ_RECORD *info);
  20. static int rr_from_tempfile(READ_RECORD *info);
  21. static int rr_from_pointers(READ_RECORD *info);
  22. static int rr_from_cache(READ_RECORD *info);
  23. static int init_rr_cache(READ_RECORD *info);
  24. static int rr_cmp(uchar *a,uchar *b);
  25. /* init struct for read with info->read_record */
  26. void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
  27.       SQL_SELECT *select,
  28.       int use_record_cache, bool print_error)
  29. {
  30.   IO_CACHE *tempfile;
  31.   DBUG_ENTER("init_read_record");
  32.   bzero((char*) info,sizeof(*info));
  33.   info->thd=thd;
  34.   info->table=table;
  35.   info->file= table->file;
  36.   info->forms= &info->table; /* Only one table */
  37.   info->record=table->record[0];
  38.   info->ref_length=table->file->ref_length;
  39.   info->select=select;
  40.   info->print_error=print_error;
  41.   table->status=0; /* And it's allways found */
  42.   if (select && my_b_inited(&select->file))
  43.     tempfile= &select->file;
  44.   else
  45.     tempfile= table->io_cache;
  46.   if (select && select->quick && (! tempfile || !tempfile->buffer))
  47.   {
  48.     DBUG_PRINT("info",("using rr_quick"));
  49.     info->read_record=rr_quick;
  50.   }
  51.   else if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
  52.   {
  53.     DBUG_PRINT("info",("using rr_from_tempfile"));
  54.     info->read_record=rr_from_tempfile;
  55.     info->io_cache=tempfile;
  56.     reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
  57.     info->ref_pos=table->file->ref;
  58.     table->file->rnd_init(0);
  59.     if (! (specialflag & SPECIAL_SAFE_MODE) &&
  60. my_default_record_cache_size &&
  61. !table->file->fast_key_read() &&
  62. (table->db_stat & HA_READ_ONLY ||
  63.  table->reginfo.lock_type == TL_READ) &&
  64. (ulonglong) table->reclength*(table->file->records+
  65.       table->file->deleted) >
  66. (ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
  67. info->io_cache->end_of_file/info->ref_length*table->reclength >
  68. (my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
  69. !table->blob_fields)
  70.     {
  71.       if (! init_rr_cache(info))
  72.       {
  73. DBUG_PRINT("info",("using rr_from_cache"));
  74. info->read_record=rr_from_cache;
  75.       }
  76.     }
  77.   }
  78.   else if (table->record_pointers)
  79.   {
  80.     table->file->rnd_init(0);
  81.     info->cache_pos=table->record_pointers;
  82.     info->cache_end=info->cache_pos+ table->found_records*info->ref_length;
  83.     info->read_record= rr_from_pointers;
  84.   }
  85.   else
  86.   {
  87.     DBUG_PRINT("info",("using rr_sequential"));
  88.     info->read_record=rr_sequential;
  89.     table->file->rnd_init();
  90.     /* We can use record cache if we don't update dynamic length tables */
  91.     if (use_record_cache > 0 ||
  92. (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
  93. !(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
  94. (use_record_cache < 0 &&
  95.  !(table->file->option_flag() & HA_NOT_DELETE_WITH_CACHE)))
  96.       VOID(table->file->extra(HA_EXTRA_CACHE)); // Cache reads
  97.   }
  98.   DBUG_VOID_RETURN;
  99. } /* init_read_record */
  100. void end_read_record(READ_RECORD *info)
  101. { /* free cache if used */
  102.   if (info->cache)
  103.   {
  104.     my_free_lock((char*) info->cache,MYF(0));
  105.     info->cache=0;
  106.   }
  107.   if (info->table)
  108.   {
  109.     (void) info->file->extra(HA_EXTRA_NO_CACHE);
  110.     (void) info->file->rnd_end();
  111.     info->table=0;
  112.   }
  113. }
  114. /* Read a record from head-database */
  115. static int rr_quick(READ_RECORD *info)
  116. {
  117.   int tmp=info->select->quick->get_next();
  118.   if (tmp)
  119.   {
  120.     if (tmp == HA_ERR_END_OF_FILE)
  121.       tmp= -1;
  122.     else if (info->print_error)
  123.       info->file->print_error(tmp,MYF(0));
  124.   }
  125.   return tmp;
  126. }
  127. static int rr_sequential(READ_RECORD *info)
  128. {
  129.   int tmp;
  130.   while ((tmp=info->file->rnd_next(info->record)))
  131.   {
  132.     if (info->thd->killed)
  133.     {
  134.       my_error(ER_SERVER_SHUTDOWN,MYF(0));
  135.       return 1;
  136.     }
  137.     if (tmp != HA_ERR_RECORD_DELETED)
  138.     {
  139.       if (tmp == HA_ERR_END_OF_FILE)
  140. tmp= -1;
  141.       else if (info->print_error)
  142. info->table->file->print_error(tmp,MYF(0));
  143.       break;
  144.     }
  145.   }
  146.   return tmp;
  147. }
  148. static int rr_from_tempfile(READ_RECORD *info)
  149. {
  150.   if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
  151.     return -1; /* End of file */
  152.   int tmp=info->file->rnd_pos(info->record,info->ref_pos);
  153.   if (tmp)
  154.   {
  155.     if (tmp == HA_ERR_END_OF_FILE)
  156.       tmp= -1;
  157.     else if (info->print_error)
  158.       info->file->print_error(tmp,MYF(0));
  159.   }
  160.   return tmp;
  161. } /* rr_from_tempfile */
  162. static int rr_from_pointers(READ_RECORD *info)
  163. {
  164.   if (info->cache_pos == info->cache_end)
  165.     return -1; /* End of file */
  166.   byte *cache_pos=info->cache_pos;
  167.   info->cache_pos+=info->ref_length;
  168.   int tmp=info->file->rnd_pos(info->record,cache_pos);
  169.   if (tmp)
  170.   {
  171.     if (tmp == HA_ERR_END_OF_FILE)
  172.       tmp= -1;
  173.     else if (info->print_error)
  174.       info->file->print_error(tmp,MYF(0));
  175.   }
  176.   return tmp;
  177. }
  178. /* cacheing of records from a database */
  179. static int init_rr_cache(READ_RECORD *info)
  180. {
  181.   uint rec_cache_size;
  182.   DBUG_ENTER("init_rr_cache");
  183.   info->struct_length=3+MAX_REFLENGTH;
  184.   info->reclength=ALIGN_SIZE(info->table->reclength+1);
  185.   if (info->reclength < info->struct_length)
  186.     info->reclength=ALIGN_SIZE(info->struct_length);
  187.   info->error_offset=info->table->reclength;
  188.   info->cache_records=my_default_record_cache_size/
  189.     (info->reclength+info->struct_length);
  190.   rec_cache_size=info->cache_records*info->reclength;
  191.   info->rec_cache_size=info->cache_records*info->ref_length;
  192.   if (info->cache_records <= 2 ||
  193.       !(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records*
  194.    info->struct_length,
  195.    MYF(0))))
  196.     DBUG_RETURN(1);
  197. #ifdef HAVE_purify
  198.   bzero(info->cache,rec_cache_size); // Avoid warnings in qsort
  199. #endif
  200.   DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
  201.   info->read_positions=info->cache+rec_cache_size;
  202.   info->cache_pos=info->cache_end=info->cache;
  203.   DBUG_RETURN(0);
  204. } /* init_rr_cache */
  205. static int rr_from_cache(READ_RECORD *info)
  206. {
  207.   reg1 uint i;
  208.   ulong length;
  209.   my_off_t rest_of_file;
  210.   int16 error;
  211.   byte *position,*ref_position,*record_pos;
  212.   ulong record;
  213.   for (;;)
  214.   {
  215.     if (info->cache_pos != info->cache_end)
  216.     {
  217.       if (info->cache_pos[info->error_offset])
  218.       {
  219. shortget(error,info->cache_pos);
  220. if (info->print_error)
  221.   info->table->file->print_error(error,MYF(0));
  222.       }
  223.       else
  224.       {
  225. error=0;
  226. memcpy(info->record,info->cache_pos,(size_t) info->table->reclength);
  227.       }
  228.       info->cache_pos+=info->reclength;
  229.       return ((int) error);
  230.     }
  231.     length=info->rec_cache_size;
  232.     rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
  233.     if ((my_off_t) length > rest_of_file)
  234.       length= (ulong) rest_of_file;
  235.     if (!length || my_b_read(info->io_cache,info->cache,length))
  236.     {
  237.       DBUG_PRINT("info",("Found end of file"));
  238.       return -1; /* End of file */
  239.     }
  240.     length/=info->ref_length;
  241.     position=info->cache;
  242.     ref_position=info->read_positions;
  243.     for (i=0 ; i < length ; i++,position+=info->ref_length)
  244.     {
  245.       memcpy(ref_position,position,(size_s) info->ref_length);
  246.       ref_position+=MAX_REFLENGTH;
  247.       int3store(ref_position,(long) i);
  248.       ref_position+=3;
  249.     }
  250.     qsort(info->read_positions,length,info->struct_length,(qsort_cmp) rr_cmp);
  251.     position=info->read_positions;
  252.     for (i=0 ; i < length ; i++)
  253.     {
  254.       memcpy(info->ref_pos,position,(size_s) info->ref_length);
  255.       position+=MAX_REFLENGTH;
  256.       record=uint3korr(position);
  257.       position+=3;
  258.       record_pos=info->cache+record*info->reclength;
  259.       if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos)))
  260.       {
  261. record_pos[info->error_offset]=1;
  262. shortstore(record_pos,error);
  263. DBUG_PRINT("error",("Got error: %d:%d when reading row",
  264.     my_errno, error));
  265.       }
  266.       else
  267. record_pos[info->error_offset]=0;
  268.     }
  269.     info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
  270.   }
  271. } /* rr_from_cache */
  272. static int rr_cmp(uchar *a,uchar *b)
  273. {
  274.   if (a[0] != b[0])
  275.     return (int) a[0] - (int) b[0];
  276.   if (a[1] != b[1])
  277.     return (int) a[1] - (int) b[1];
  278.   if (a[2] != b[2])
  279.     return (int) a[2] - (int) b[2];
  280. #if MAX_REFLENGTH == 4
  281.   return (int) a[3] - (int) b[3];
  282. #else
  283.   if (a[3] != b[3])
  284.     return (int) a[3] - (int) b[3];
  285.   if (a[4] != b[4])
  286.     return (int) a[4] - (int) b[4];
  287.   if (a[5] != b[5])
  288.     return (int) a[1] - (int) b[5];
  289.   if (a[6] != b[6])
  290.     return (int) a[6] - (int) b[6];
  291.   return (int) a[7] - (int) b[7];
  292. #endif
  293. }