mariadb/sql/records.cc
unknown 7032486889 Fixes for valgrind
Added optimzation for clustered index
Fixed bug in UPDATE ... ORDER BY
Fixed handling of UPDATE ... LIMIT


BitKeeper/deleted/.del-.cvsignore~7e29af89a3559f4c:
  Delete: Images/.cvsignore
BitKeeper/deleted/.del-README~d5a4e7ca3a2e87a9:
  Delete: repl-tests/README
BitKeeper/deleted/.del-run-all-tests~4deb6479a13e4568:
  Delete: repl-tests/run-all-tests
BitKeeper/deleted/.del-run.test~3dc5b9bd1e9feea5:
  Delete: repl-tests/test-repl-alter/run.test
BitKeeper/deleted/.del-run.test~4020771cff278f14:
  Delete: repl-tests/test-bad-query/run.test
BitKeeper/deleted/.del-run.test~452f2b66537404a8:
  Delete: repl-tests/test-dump/run.test
BitKeeper/deleted/.del-run.test~b1f0c1f96554df8:
  Delete: repl-tests/test-auto-inc/run.test
BitKeeper/deleted/.del-table-dump-check.master~e13afeb8c79264b5:
  Delete: repl-tests/test-dump/table-dump-check.master
BitKeeper/deleted/.del-table-dump-select.master~744acb955e33f3db:
  Delete: repl-tests/test-dump/table-dump-select.master
BitKeeper/deleted/.del-x.master~29a93ed7956c8693:
  Delete: repl-tests/test-auto-inc/x.master
BitKeeper/deleted/.del-x.master~3b248cbac9abda2b:
  Delete: repl-tests/test-bad-query/x.master
BitKeeper/deleted/.del-foo-dump-master.master~b49ae6bec1e918ee:
  Delete: repl-tests/test-repl/foo-dump-master.master
BitKeeper/deleted/.del-foo-dump-slave.master~f16ed20457d59be9:
  Delete: repl-tests/test-repl/foo-dump-slave.master
BitKeeper/deleted/.del-repl-timestamp.master.reject~3492d2b74b413771:
  Delete: repl-tests/test-repl-ts/repl-timestamp.master.reject
BitKeeper/deleted/.del-repl-timestamp.master~4b7782da5cc13161:
  Delete: repl-tests/test-repl-ts/repl-timestamp.master
BitKeeper/deleted/.del-run.test~a1e32ea1e4253af4:
  Delete: repl-tests/test-repl/run.test
BitKeeper/deleted/.del-run.test~ce5e626c91b760ec:
  Delete: repl-tests/test-repl-ts/run.test
BitKeeper/deleted/.del-sum-wlen-master.master~1a5ea625c79e978:
  Delete: repl-tests/test-repl/sum-wlen-master.master
BitKeeper/deleted/.del-sum-wlen-slave.master~f016d98833433084:
  Delete: repl-tests/test-repl/sum-wlen-slave.master
BitKeeper/deleted/.del-test.master~5829e7b3770179db:
  Delete: repl-tests/test-repl-alter/test.master
BitKeeper/deleted/.del-master-slave.inc~6775f6ae10137c39:
  Delete: repl-tests/include/master-slave.inc
include/my_global.h:
  Fix for purify/valgrind
myisam/mi_info.c:
  Updated comment
mysql-test/r/group_by.result:
  New test results
mysql-test/r/innodb.result:
  New test results
mysql-test/r/join_outer.result:
  New test results
mysql-test/r/multi_update.result:
  New test results
mysql-test/r/null_key.result:
  New test results
mysql-test/r/update.result:
  New test results
mysql-test/t/group_by.test:
  Added extra explain to 'suspicious' test.
mysql-test/t/innodb.test:
  Added test for UPDATE ... ORDER BY
mysql-test/t/join_outer.test:
  Changed test to be repeatable
mysql-test/t/multi_update.test:
  Slight change of test to catch more bugs
mysql-test/t/update.test:
  Better test for UPDATE ... ORDER BY
sql/field.cc:
  Simple optimization
sql/ha_heap.h:
  Added optimzation for clustered index
sql/ha_innodb.cc:
  Added optimzation for clustered index
sql/ha_innodb.h:
  Added optimzation for clustered index
sql/handler.h:
  Added optimzation for clustered index
sql/item_sum.cc:
  Removed some usage of current_thd
sql/mysqld.cc:
  Fix bug when compiling for purify/valgrind
sql/opt_range.cc:
  Added optimzation for clustered index
sql/records.cc:
  Fixed comment
sql/sql_list.h:
  Fixed comment
sql/sql_select.cc:
  Removed some usage of current_thd
sql/sql_select.h:
  Removed some usage of current_thd
sql/sql_union.cc:
  Removed some usage of current_thd
sql/sql_update.cc:
  Fixed bug in UPDATE ... ORDER BY
  Fixed handling of UPDATE ... LIMIT
support-files/my-huge.cnf.sh:
  Added default size for query cache
support-files/my-large.cnf.sh:
  Added default size for query cache
2003-04-23 21:52:16 +03:00

359 lines
9.7 KiB
C++

/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions for easy reading of records, possible through a cache */
#include "mysql_priv.h"
static int rr_quick(READ_RECORD *info);
static int rr_sequential(READ_RECORD *info);
static int rr_from_tempfile(READ_RECORD *info);
static int rr_from_pointers(READ_RECORD *info);
static int rr_from_cache(READ_RECORD *info);
static int init_rr_cache(READ_RECORD *info);
static int rr_cmp(uchar *a,uchar *b);
/* init struct for read with info->read_record */
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
SQL_SELECT *select,
int use_record_cache, bool print_error)
{
IO_CACHE *tempfile;
DBUG_ENTER("init_read_record");
bzero((char*) info,sizeof(*info));
info->thd=thd;
info->table=table;
info->file= table->file;
info->forms= &info->table; /* Only one table */
info->record=table->record[0];
info->ref_length=table->file->ref_length;
info->select=select;
info->print_error=print_error;
info->ignore_not_found_rows= 0;
table->status=0; /* And it's always found */
if (select && my_b_inited(&select->file))
tempfile= &select->file;
else
tempfile= table->io_cache;
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
{
DBUG_PRINT("info",("using rr_from_tempfile"));
info->read_record=rr_from_tempfile;
info->io_cache=tempfile;
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
info->ref_pos=table->file->ref;
table->file->rnd_init(0);
if (! (specialflag & SPECIAL_SAFE_MODE) &&
thd->variables.read_rnd_buff_size &&
!table->file->fast_key_read() &&
(table->db_stat & HA_READ_ONLY ||
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
(ulonglong) table->reclength*(table->file->records+
table->file->deleted) >
(ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
info->io_cache->end_of_file/info->ref_length*table->reclength >
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
!table->blob_fields)
{
if (! init_rr_cache(info))
{
DBUG_PRINT("info",("using rr_from_cache"));
info->read_record=rr_from_cache;
}
}
}
else if (select && select->quick)
{
DBUG_PRINT("info",("using rr_quick"));
info->read_record=rr_quick;
}
else if (table->record_pointers)
{
DBUG_PRINT("info",("using record_pointers"));
table->file->rnd_init(0);
info->cache_pos=table->record_pointers;
info->cache_end=info->cache_pos+ table->found_records*info->ref_length;
info->read_record= rr_from_pointers;
}
else
{
DBUG_PRINT("info",("using rr_sequential"));
info->read_record=rr_sequential;
table->file->rnd_init();
/* We can use record cache if we don't update dynamic length tables */
if (use_record_cache > 0 ||
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
!(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
(use_record_cache < 0 &&
!(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE)))
VOID(table->file->extra_opt(HA_EXTRA_CACHE,
thd->variables.read_buff_size));
}
DBUG_VOID_RETURN;
} /* init_read_record */
void end_read_record(READ_RECORD *info)
{ /* free cache if used */
if (info->cache)
{
my_free_lock((char*) info->cache,MYF(0));
info->cache=0;
}
if (info->table)
{
(void) info->file->extra(HA_EXTRA_NO_CACHE);
(void) info->file->rnd_end();
info->table=0;
}
}
/* Read a record from head-database */
static int rr_quick(READ_RECORD *info)
{
int tmp=info->select->quick->get_next();
if (tmp)
{
if (tmp == HA_ERR_END_OF_FILE)
tmp= -1;
else
{
if (info->print_error)
info->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
}
return tmp;
}
static int rr_sequential(READ_RECORD *info)
{
int tmp;
while ((tmp=info->file->rnd_next(info->record)))
{
if (info->thd->killed)
{
my_error(ER_SERVER_SHUTDOWN,MYF(0));
return 1;
}
if (tmp != HA_ERR_RECORD_DELETED)
{
if (tmp == HA_ERR_END_OF_FILE)
tmp= -1;
else
{
if (info->print_error)
info->table->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
break;
}
}
return tmp;
}
static int rr_from_tempfile(READ_RECORD *info)
{
int tmp;
tryNext:
if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
return -1; /* End of file */
if ((tmp=info->file->rnd_pos(info->record,info->ref_pos)))
{
if (tmp == HA_ERR_END_OF_FILE)
tmp= -1;
else if (tmp == HA_ERR_RECORD_DELETED ||
(tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
goto tryNext;
else
{
if (info->print_error)
info->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
}
return tmp;
} /* rr_from_tempfile */
static int rr_from_pointers(READ_RECORD *info)
{
int tmp;
byte *cache_pos;
tryNext:
if (info->cache_pos == info->cache_end)
return -1; /* End of file */
cache_pos=info->cache_pos;
info->cache_pos+=info->ref_length;
if ((tmp=info->file->rnd_pos(info->record,cache_pos)))
{
if (tmp == HA_ERR_END_OF_FILE)
tmp= -1;
else if (tmp == HA_ERR_RECORD_DELETED ||
(tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
goto tryNext;
else
{
if (info->print_error)
info->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
}
return tmp;
}
/* cacheing of records from a database */
static int init_rr_cache(READ_RECORD *info)
{
uint rec_cache_size;
THD *thd= current_thd;
DBUG_ENTER("init_rr_cache");
info->struct_length=3+MAX_REFLENGTH;
info->reclength=ALIGN_SIZE(info->table->reclength+1);
if (info->reclength < info->struct_length)
info->reclength=ALIGN_SIZE(info->struct_length);
info->error_offset=info->table->reclength;
info->cache_records= thd->variables.read_rnd_buff_size /
(info->reclength+info->struct_length);
rec_cache_size=info->cache_records*info->reclength;
info->rec_cache_size=info->cache_records*info->ref_length;
if (info->cache_records <= 2 ||
!(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records*
info->struct_length,
MYF(0))))
DBUG_RETURN(1);
#ifdef HAVE_purify
bzero(info->cache,rec_cache_size); // Avoid warnings in qsort
#endif
DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
info->read_positions=info->cache+rec_cache_size;
info->cache_pos=info->cache_end=info->cache;
DBUG_RETURN(0);
} /* init_rr_cache */
static int rr_from_cache(READ_RECORD *info)
{
reg1 uint i;
ulong length;
my_off_t rest_of_file;
int16 error;
byte *position,*ref_position,*record_pos;
ulong record;
for (;;)
{
if (info->cache_pos != info->cache_end)
{
if (info->cache_pos[info->error_offset])
{
shortget(error,info->cache_pos);
if (info->print_error)
info->table->file->print_error(error,MYF(0));
}
else
{
error=0;
memcpy(info->record,info->cache_pos,(size_t) info->table->reclength);
}
info->cache_pos+=info->reclength;
return ((int) error);
}
length=info->rec_cache_size;
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
if ((my_off_t) length > rest_of_file)
length= (ulong) rest_of_file;
if (!length || my_b_read(info->io_cache,info->cache,length))
{
DBUG_PRINT("info",("Found end of file"));
return -1; /* End of file */
}
length/=info->ref_length;
position=info->cache;
ref_position=info->read_positions;
for (i=0 ; i < length ; i++,position+=info->ref_length)
{
memcpy(ref_position,position,(size_s) info->ref_length);
ref_position+=MAX_REFLENGTH;
int3store(ref_position,(long) i);
ref_position+=3;
}
qsort(info->read_positions,length,info->struct_length,(qsort_cmp) rr_cmp);
position=info->read_positions;
for (i=0 ; i < length ; i++)
{
memcpy(info->ref_pos,position,(size_s) info->ref_length);
position+=MAX_REFLENGTH;
record=uint3korr(position);
position+=3;
record_pos=info->cache+record*info->reclength;
if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos)))
{
record_pos[info->error_offset]=1;
shortstore(record_pos,error);
DBUG_PRINT("error",("Got error: %d:%d when reading row",
my_errno, error));
}
else
record_pos[info->error_offset]=0;
}
info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
}
} /* rr_from_cache */
static int rr_cmp(uchar *a,uchar *b)
{
if (a[0] != b[0])
return (int) a[0] - (int) b[0];
if (a[1] != b[1])
return (int) a[1] - (int) b[1];
if (a[2] != b[2])
return (int) a[2] - (int) b[2];
#if MAX_REFLENGTH == 4
return (int) a[3] - (int) b[3];
#else
if (a[3] != b[3])
return (int) a[3] - (int) b[3];
if (a[4] != b[4])
return (int) a[4] - (int) b[4];
if (a[5] != b[5])
return (int) a[1] - (int) b[5];
if (a[6] != b[6])
return (int) a[6] - (int) b[6];
return (int) a[7] - (int) b[7];
#endif
}