Commit 565c2fdb authored by ingo@mysql.com's avatar ingo@mysql.com

Merge mysql.com:/home/mydev/mysql-5.0

into mysql.com:/home/mydev/mysql-5.0-5000
parents 9bf63b14 b3a66285
...@@ -64,8 +64,8 @@ AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [ ...@@ -64,8 +64,8 @@ AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [
AC_ARG_WITH([ndb-ccflags], AC_ARG_WITH([ndb-ccflags],
[ [
--with-ndb-ccflags Extra CC options for ndb compile], --with-ndb-ccflags Extra CC options for ndb compile],
[ndb_cxxflags_fix=$withval], [ndb_cxxflags_fix="$ndb_cxxflags_fix $withval"],
[ndb_cxxflags_fix=]) [ndb_cxxflags_fix=$ndb_cxxflags_fix])
AC_MSG_CHECKING([for NDB Cluster options]) AC_MSG_CHECKING([for NDB Cluster options])
AC_MSG_RESULT([]) AC_MSG_RESULT([])
......
...@@ -962,6 +962,7 @@ esac ...@@ -962,6 +962,7 @@ esac
MAX_C_OPTIMIZE="-O3" MAX_C_OPTIMIZE="-O3"
MAX_CXX_OPTIMIZE="-O3" MAX_CXX_OPTIMIZE="-O3"
ndb_cxxflags_fix=
case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in
# workaround for Sun Forte/x86 see BUG#4681 # workaround for Sun Forte/x86 see BUG#4681
*solaris*-i?86-no) *solaris*-i?86-no)
......
...@@ -35,13 +35,72 @@ sub mtr_get_opts_from_file ($) { ...@@ -35,13 +35,72 @@ sub mtr_get_opts_from_file ($) {
while ( <FILE> ) while ( <FILE> )
{ {
chomp; chomp;
s/\$MYSQL_TEST_DIR/$::glob_mysql_test_dir/g;
push(@args, split(' ', $_)); # --set-variable=init_connect=set @a='a\\0c'
s/^\s+//; # Remove leading space
s/\s+$//; # Remove ending space
# This is strange, but we need to fill whitespace inside
# quotes with something, to remove later. We do this to
# be able to split on space. Else, we have trouble with
# options like
#
# --someopt="--insideopt1 --insideopt2"
#
# But still with this, we are not 100% sure it is right,
# we need a shell to do it right.
# print STDERR "\n";
# print STDERR "AAA: $_\n";
s/\'([^\'\"]*)\'/unspace($1,"\x0a")/ge;
s/\"([^\'\"]*)\"/unspace($1,"\x0b")/ge;
s/\'([^\'\"]*)\'/unspace($1,"\x0a")/ge;
s/\"([^\'\"]*)\"/unspace($1,"\x0b")/ge;
# print STDERR "BBB: $_\n";
# foreach my $arg (/(--?\w.*?)(?=\s+--?\w|$)/)
# FIXME ENV vars should be expanded!!!!
foreach my $arg (split(/[ \t]+/))
{
$arg =~ tr/\x11\x0a\x0b/ \'\"/; # Put back real chars
# The outermost quotes has to go
$arg =~ s/^([^\'\"]*)\'(.*)\'([^\'\"]*)$/$1$2$3/
or $arg =~ s/^([^\'\"]*)\"(.*)\"([^\'\"]*)$/$1$2$3/;
$arg =~ s/\\\\/\\/g;
$arg =~ s/\$\{(\w+)\}/envsubst($1)/ge;
$arg =~ s/\$(\w+)/envsubst($1)/ge;
# print STDERR "ARG: $arg\n";
push(@args, $arg);
}
} }
close FILE; close FILE;
return \@args; return \@args;
} }
sub envsubst {
my $string= shift;
if ( ! defined $ENV{$string} )
{
mtr_error("opt file referense \$$string that is unknown");
}
return $ENV{$string};
}
sub unspace {
my $string= shift;
my $quote= shift;
$string =~ s/[ \t]/\x11/g;
return "$quote$string$quote";
}
sub mtr_fromfile ($) { sub mtr_fromfile ($) {
my $file= shift; my $file= shift;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# and is part of the translation of the Bourne shell script with the # and is part of the translation of the Bourne shell script with the
# same name. # same name.
use Carp qw(cluck); #use Carp qw(cluck);
use strict; use strict;
use POSIX ":sys_wait_h"; use POSIX ":sys_wait_h";
...@@ -64,18 +64,6 @@ sub spawn_impl ($$$$$$$) { ...@@ -64,18 +64,6 @@ sub spawn_impl ($$$$$$$) {
my $error= shift; my $error= shift;
my $pid_file= shift; # FIXME my $pid_file= shift; # FIXME
# FIXME really needing a PATH???
# $ENV{'PATH'}= "/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$ENV{'PATH'}";
$ENV{'TZ'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work
$ENV{'LC_COLLATE'}= "C";
$ENV{'MYSQL_TEST_DIR'}= $::glob_mysql_test_dir;
$ENV{'MASTER_MYPORT'}= $::opt_master_myport;
$ENV{'SLAVE_MYPORT'}= $::opt_slave_myport;
# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME
$ENV{'MYSQL_TCP_PORT'}= 3306;
$ENV{'MASTER_MYSOCK'}= $::master->[0]->{'path_mysock'};
if ( $::opt_script_debug ) if ( $::opt_script_debug )
{ {
print STDERR "\n"; print STDERR "\n";
...@@ -85,17 +73,21 @@ sub spawn_impl ($$$$$$$) { ...@@ -85,17 +73,21 @@ sub spawn_impl ($$$$$$$) {
print STDERR "#### ", "STDERR $error\n" if $error; print STDERR "#### ", "STDERR $error\n" if $error;
if ( $join ) if ( $join )
{ {
print STDERR "#### ", "run"; print STDERR "#### ", "RUN ";
} }
else else
{ {
print STDERR "#### ", "spawn"; print STDERR "#### ", "SPAWN ";
} }
print STDERR "$path ", join(" ",@$arg_list_t), "\n"; print STDERR "$path ", join(" ",@$arg_list_t), "\n";
print STDERR "#### ", "-" x 78, "\n"; print STDERR "#### ", "-" x 78, "\n";
} }
my $pid= fork(); my $pid= fork();
if ( ! defined $pid )
{
mtr_error("$path ($pid) can't be forked");
}
if ( $pid ) if ( $pid )
{ {
...@@ -104,17 +96,22 @@ sub spawn_impl ($$$$$$$) { ...@@ -104,17 +96,22 @@ sub spawn_impl ($$$$$$$) {
{ {
# We run a command and wait for the result # We run a command and wait for the result
# FIXME this need to be improved # FIXME this need to be improved
waitpid($pid,0); my $res= waitpid($pid,0);
if ( $res == -1 )
{
mtr_error("$path ($pid) got lost somehow");
}
my $exit_value= $? >> 8; my $exit_value= $? >> 8;
my $signal_num= $? & 127; my $signal_num= $? & 127;
my $dumped_core= $? & 128; my $dumped_core= $? & 128;
if ( $signal_num ) if ( $signal_num )
{ {
mtr_error("spawn got signal $signal_num"); mtr_error("$path ($pid) got signal $signal_num");
} }
if ( $dumped_core ) if ( $dumped_core )
{ {
mtr_error("spawn dumped core"); mtr_error("$path ($pid) dumped core");
} }
return $exit_value; return $exit_value;
} }
...@@ -326,7 +323,8 @@ sub mtr_stop_mysqld_servers ($$) { ...@@ -326,7 +323,8 @@ sub mtr_stop_mysqld_servers ($$) {
mtr_init_args(\$args); mtr_init_args(\$args);
mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--no-defaults");
mtr_add_arg($args, "-uroot"); mtr_add_arg($args, "--user=%s", $::opt_user);
mtr_add_arg($args, "--password=");
if ( -e $srv->{'sockfile'} ) if ( -e $srv->{'sockfile'} )
{ {
mtr_add_arg($args, "--socket=%s", $srv->{'sockfile'}); mtr_add_arg($args, "--socket=%s", $srv->{'sockfile'});
...@@ -336,7 +334,8 @@ sub mtr_stop_mysqld_servers ($$) { ...@@ -336,7 +334,8 @@ sub mtr_stop_mysqld_servers ($$) {
mtr_add_arg($args, "--port=%s", $srv->{'port'}); mtr_add_arg($args, "--port=%s", $srv->{'port'});
} }
mtr_add_arg($args, "--connect_timeout=5"); mtr_add_arg($args, "--connect_timeout=5");
mtr_add_arg($args, "--shutdown_timeout=70"); mtr_add_arg($args, "--shutdown_timeout=20");
mtr_add_arg($args, "--protocol=tcp"); # FIXME new thing, will it help?!
mtr_add_arg($args, "shutdown"); mtr_add_arg($args, "shutdown");
# We don't wait for termination of mysqladmin # We don't wait for termination of mysqladmin
mtr_spawn($::exe_mysqladmin, $args, mtr_spawn($::exe_mysqladmin, $args,
...@@ -361,6 +360,10 @@ sub mtr_stop_mysqld_servers ($$) { ...@@ -361,6 +360,10 @@ sub mtr_stop_mysqld_servers ($$) {
{ {
last PIDSOCKFILEREMOVED; last PIDSOCKFILEREMOVED;
} }
if ( $loop % 20 == 1 )
{
mtr_warning("Still processes alive after 10 seconds, retrying for $loop seconds...");
}
mtr_debug("Sleep for 1 second waiting for pid and socket file removal"); mtr_debug("Sleep for 1 second waiting for pid and socket file removal");
sleep(1); # One second sleep(1); # One second
} }
...@@ -464,4 +467,40 @@ sub stop_reap_all { ...@@ -464,4 +467,40 @@ sub stop_reap_all {
$SIG{CHLD}= 'DEFAULT'; $SIG{CHLD}= 'DEFAULT';
} }
##############################################################################
#
# Wait for a file to be created
#
##############################################################################
sub sleep_until_file_created ($$) {
my $pidfile= shift;
my $timeout= shift;
my $loop= $timeout;
while ( $loop-- )
{
if ( -r $pidfile )
{
return;
}
mtr_debug("Sleep for 1 second waiting for creation of $pidfile");
if ( $loop % 20 == 1 )
{
mtr_warning("Waiting for $pidfile to be created, still trying for $loop seconds...");
}
sleep(1);
}
if ( ! -r $pidfile )
{
mtr_error("No $pidfile was created");
}
}
1; 1;
This diff is collapsed.
...@@ -973,7 +973,13 @@ start_ndbcluster() ...@@ -973,7 +973,13 @@ start_ndbcluster()
else else
NDBCLUSTER_EXTRA_OPTS="--small" NDBCLUSTER_EXTRA_OPTS="--small"
fi fi
./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --initial || exit 1 NDB_STARTED=1
./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --initial || NDB_STARTED=0
if [ x$NDB_STARTED != x1 ] ; then
if [ x$FORCE != x1 ] ; then
exit 1
fi
fi
NDB_CONNECTSTRING="host=localhost:$NDBCLUSTER_PORT" NDB_CONNECTSTRING="host=localhost:$NDBCLUSTER_PORT"
else else
NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER" NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER"
...@@ -1541,6 +1547,12 @@ run_testcase () ...@@ -1541,6 +1547,12 @@ run_testcase ()
fi fi
fi fi
fi fi
if [ "x$START_AND_EXIT" = "x1" ] ; then
echo "Servers started, exiting"
exit
fi
cd $MYSQL_TEST_DIR cd $MYSQL_TEST_DIR
if [ -f $tf ] ; then if [ -f $tf ] ; then
...@@ -1676,10 +1688,6 @@ then ...@@ -1676,10 +1688,6 @@ then
mysql_loadstd mysql_loadstd
fi fi
if [ "x$START_AND_EXIT" = "x1" ] ; then
echo "Servers started, exiting"
exit
fi
$ECHO "Starting Tests" $ECHO "Starting Tests"
......
...@@ -353,11 +353,6 @@ drop table t1; ...@@ -353,11 +353,6 @@ drop table t1;
use test2; use test2;
drop table t2; drop table t2;
drop database test2; drop database test2;
show databases;
Database
information_schema
mysql
test
use test; use test;
drop database if exists test_only_ndb_tables; drop database if exists test_only_ndb_tables;
create database test_only_ndb_tables; create database test_only_ndb_tables;
......
...@@ -449,7 +449,6 @@ drop table t1; ...@@ -449,7 +449,6 @@ drop table t1;
use test2; use test2;
drop table t2; drop table t2;
drop database test2; drop database test2;
show databases;
use test; use test;
######################################################### #########################################################
......
...@@ -2976,6 +2976,8 @@ void Dbdih::execCOPY_FRAGREF(Signal* signal) ...@@ -2976,6 +2976,8 @@ void Dbdih::execCOPY_FRAGREF(Signal* signal)
SystemError * const sysErr = (SystemError*)&signal->theData[0]; SystemError * const sysErr = (SystemError*)&signal->theData[0];
sysErr->errorCode = SystemError::CopyFragRefError; sysErr->errorCode = SystemError::CopyFragRefError;
sysErr->errorRef = reference(); sysErr->errorRef = reference();
sysErr->data1 = errorCode;
sysErr->data2 = 0;
sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal, sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,
SystemError::SignalLength, JBB); SystemError::SignalLength, JBB);
return; return;
...@@ -4492,6 +4494,8 @@ void Dbdih::handleTakeOverNewMaster(Signal* signal, Uint32 takeOverPtrI) ...@@ -4492,6 +4494,8 @@ void Dbdih::handleTakeOverNewMaster(Signal* signal, Uint32 takeOverPtrI)
SystemError * const sysErr = (SystemError*)&signal->theData[0]; SystemError * const sysErr = (SystemError*)&signal->theData[0];
sysErr->errorCode = SystemError::CopyFragRefError; sysErr->errorCode = SystemError::CopyFragRefError;
sysErr->errorRef = reference(); sysErr->errorRef = reference();
sysErr->data1= 0;
sysErr->data2= __LINE__;
sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal, sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal,
SystemError::SignalLength, JBB); SystemError::SignalLength, JBB);
} }
......
...@@ -315,7 +315,7 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, ...@@ -315,7 +315,7 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
ndbout << "Error in mgm protocol parser. " ndbout << "Error in mgm protocol parser. "
<< "cmd: '" << cmd << "cmd: '" << cmd
<< "' status=" << (Uint32)ctx.m_status << "' status=" << (Uint32)ctx.m_status
<< ", curr=" << (Uint32)ctx.m_currentToken << ", curr=" << ctx.m_currentToken
<< endl; << endl;
DBUG_PRINT("info",("parser.parse returned NULL")); DBUG_PRINT("info",("parser.parse returned NULL"));
} }
......
...@@ -973,6 +973,7 @@ inline uint field_in_record_is_null ( ...@@ -973,6 +973,7 @@ inline uint field_in_record_is_null (
int ha_federated::write_row(byte * buf) int ha_federated::write_row(byte * buf)
{ {
int x= 0, num_fields= 0; int x= 0, num_fields= 0;
Field **field;
ulong current_query_id= 1; ulong current_query_id= 1;
ulong tmp_query_id; ulong tmp_query_id;
int all_fields_have_same_query_id= 1; int all_fields_have_same_query_id= 1;
...@@ -1021,7 +1022,7 @@ int ha_federated::write_row(byte * buf) ...@@ -1021,7 +1022,7 @@ int ha_federated::write_row(byte * buf)
0 if it remains 0, then that means no fields were specified in the query 0 if it remains 0, then that means no fields were specified in the query
such as in the case of INSERT INTO table VALUES (val1, val2, valN) such as in the case of INSERT INTO table VALUES (val1, val2, valN)
*/ */
for (Field **field= table->field; *field ; field++, x++) for (field= table->field; *field ; field++, x++)
{ {
if (x > 0 && tmp_query_id != (*field)->query_id) if (x > 0 && tmp_query_id != (*field)->query_id)
all_fields_have_same_query_id= 0; all_fields_have_same_query_id= 0;
...@@ -1032,7 +1033,7 @@ int ha_federated::write_row(byte * buf) ...@@ -1032,7 +1033,7 @@ int ha_federated::write_row(byte * buf)
loop through the field pointer array, add any fields to both the values loop through the field pointer array, add any fields to both the values
list and the fields list that match the current query id list and the fields list that match the current query id
*/ */
for (Field **field= table->field; *field ; field++, x++) for (field= table->field; *field ; field++, x++)
{ {
DBUG_PRINT("ha_federated::write_row", ("field type %d", (*field)->type())); DBUG_PRINT("ha_federated::write_row", ("field type %d", (*field)->type()));
// if there is a query id and if it's equal to the current query id // if there is a query id and if it's equal to the current query id
......
...@@ -4901,7 +4901,8 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, ...@@ -4901,7 +4901,8 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
if (check == -1) if (check == -1)
break; break;
Uint64 rows, commits, size, mem; Uint64 rows, commits, mem;
Uint32 size;
pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows); pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows);
pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits); pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits);
pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&size); pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&size);
......
...@@ -725,7 +725,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, ...@@ -725,7 +725,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
key_part_info= head->key_info[index].key_part; key_part_info= head->key_info[index].key_part;
my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16); my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16);
/* 'thd' is not accessible in QUICK_RANGE_SELECT::get_next_init(). */ /* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */
multi_range_bufsiz= thd->variables.read_rnd_buff_size; multi_range_bufsiz= thd->variables.read_rnd_buff_size;
multi_range_count= thd->variables.multi_range_count; multi_range_count= thd->variables.multi_range_count;
multi_range_length= 0; multi_range_length= 0;
...@@ -749,9 +749,6 @@ int QUICK_RANGE_SELECT::init() ...@@ -749,9 +749,6 @@ int QUICK_RANGE_SELECT::init()
{ {
DBUG_ENTER("QUICK_RANGE_SELECT::init"); DBUG_ENTER("QUICK_RANGE_SELECT::init");
if ((error= get_next_init()))
DBUG_RETURN(error);
if (file->inited == handler::NONE) if (file->inited == handler::NONE)
DBUG_RETURN(error= file->ha_index_init(index)); DBUG_RETURN(error= file->ha_index_init(index));
error= 0; error= 0;
...@@ -5655,9 +5652,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() ...@@ -5655,9 +5652,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
We reuse the same instance of handler so we need to call both init and We reuse the same instance of handler so we need to call both init and
reset here. reset here.
*/ */
if (cur_quick->init()) if (cur_quick->init() || cur_quick->reset())
DBUG_RETURN(1); DBUG_RETURN(1);
cur_quick->reset();
unique= new Unique(refpos_order_cmp, (void *)head->file, unique= new Unique(refpos_order_cmp, (void *)head->file,
head->file->ref_length, head->file->ref_length,
...@@ -5675,10 +5671,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() ...@@ -5675,10 +5671,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
if (cur_quick->file->inited != handler::NONE) if (cur_quick->file->inited != handler::NONE)
cur_quick->file->ha_index_end(); cur_quick->file->ha_index_end();
if (cur_quick->init()) if (cur_quick->init() || cur_quick->reset())
DBUG_RETURN(1); DBUG_RETURN(1);
/* QUICK_RANGE_SELECT::reset never fails */
cur_quick->reset();
} }
if (result) if (result)
...@@ -5745,9 +5739,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next() ...@@ -5745,9 +5739,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
if (pk_quick_select) if (pk_quick_select)
{ {
doing_pk_scan= TRUE; doing_pk_scan= TRUE;
if ((result= pk_quick_select->init())) if ((result= pk_quick_select->init()) || (result= pk_quick_select->reset()))
DBUG_RETURN(result); DBUG_RETURN(result);
pk_quick_select->reset();
DBUG_RETURN(pk_quick_select->get_next()); DBUG_RETURN(pk_quick_select->get_next());
} }
} }
...@@ -5908,27 +5901,14 @@ int QUICK_ROR_UNION_SELECT::get_next() ...@@ -5908,27 +5901,14 @@ int QUICK_ROR_UNION_SELECT::get_next()
DBUG_RETURN(error); DBUG_RETURN(error);
} }
int QUICK_RANGE_SELECT::reset()
/*
Initialize data structures needed by get_next().
SYNOPSIS
QUICK_RANGE_SELECT::get_next_init()
DESCRIPTION
This is called from get_next() at its first call for an object.
It allocates memory buffers and sets size variables.
RETURN
0 OK.
!= 0 Error.
*/
int QUICK_RANGE_SELECT::get_next_init(void)
{ {
uint mrange_bufsiz; uint mrange_bufsiz;
byte *mrange_buff; byte *mrange_buff;
DBUG_ENTER("QUICK_RANGE_SELECT::get_next_init"); DBUG_ENTER("QUICK_RANGE_SELECT::reset");
next=0;
range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
/* Do not allocate the buffers twice. */ /* Do not allocate the buffers twice. */
if (multi_range_length) if (multi_range_length)
...@@ -5937,15 +5917,8 @@ int QUICK_RANGE_SELECT::get_next_init(void) ...@@ -5937,15 +5917,8 @@ int QUICK_RANGE_SELECT::get_next_init(void)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* If the ranges are not yet initialized, wait for the next call. */ /* Allocate the ranges array. */
if (! ranges.elements) DBUG_ASSERT(ranges.elements);
{
DBUG_RETURN(0);
}
/*
Allocate the ranges array.
*/
multi_range_length= min(multi_range_count, ranges.elements); multi_range_length= min(multi_range_count, ranges.elements);
DBUG_ASSERT(multi_range_length > 0); DBUG_ASSERT(multi_range_length > 0);
while (multi_range_length && ! (multi_range= (KEY_MULTI_RANGE*) while (multi_range_length && ! (multi_range= (KEY_MULTI_RANGE*)
...@@ -5962,9 +5935,7 @@ int QUICK_RANGE_SELECT::get_next_init(void) ...@@ -5962,9 +5935,7 @@ int QUICK_RANGE_SELECT::get_next_init(void)
DBUG_RETURN(HA_ERR_OUT_OF_MEM); DBUG_RETURN(HA_ERR_OUT_OF_MEM);
} }
/* /* Allocate the handler buffer if necessary. */
Allocate the handler buffer if necessary.
*/
if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER) if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER)
{ {
mrange_bufsiz= min(multi_range_bufsiz, mrange_bufsiz= min(multi_range_bufsiz,
...@@ -5992,9 +5963,6 @@ int QUICK_RANGE_SELECT::get_next_init(void) ...@@ -5992,9 +5963,6 @@ int QUICK_RANGE_SELECT::get_next_init(void)
multi_range_buff->buffer_end= mrange_buff + mrange_bufsiz; multi_range_buff->buffer_end= mrange_buff + mrange_bufsiz;
multi_range_buff->end_of_used_area= mrange_buff; multi_range_buff->end_of_used_area= mrange_buff;
} }
/* Initialize the current QUICK_RANGE pointer. */
cur_range= (QUICK_RANGE**) ranges.buffer;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -7948,10 +7916,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void) ...@@ -7948,10 +7916,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void)
file->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */ file->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */
result= file->ha_index_init(index); result= file->ha_index_init(index);
result= file->index_last(record); result= file->index_last(record);
if (quick_prefix_select)
quick_prefix_select->reset();
if (result) if (result)
DBUG_RETURN(result); DBUG_RETURN(result);
if (quick_prefix_select && quick_prefix_select->reset())
DBUG_RETURN(1);
/* Save the prefix of the last group. */ /* Save the prefix of the last group. */
key_copy(last_prefix, record, index_info, group_prefix_len); key_copy(last_prefix, record, index_info, group_prefix_len);
......
...@@ -59,6 +59,44 @@ class QUICK_RANGE :public Sql_alloc { ...@@ -59,6 +59,44 @@ class QUICK_RANGE :public Sql_alloc {
/* /*
Quick select interface. Quick select interface.
This class is a parent for all QUICK_*_SELECT and FT_SELECT classes. This class is a parent for all QUICK_*_SELECT and FT_SELECT classes.
The usage scenario is as follows:
1. Create quick select
quick= new QUICK_XXX_SELECT(...);
2. Perform lightweight initialization. This can be done in 2 ways:
2.a: Regular initialization
if (quick->init())
{
//the only valid action after failed init() call is delete
delete quick;
}
2.b: Special initialization for quick selects merged by QUICK_ROR_*_SELECT
if (quick->init_ror_merged_scan())
delete quick;
3. Perform zero, one, or more scans.
while (...)
{
// initialize quick select for scan. This may allocate
// buffers and/or prefetch rows.
if (quick->reset())
{
//the only valid action after failed reset() call is delete
delete quick;
//abort query
}
// perform the scan
do
{
res= quick->get_next();
} while (res && ...)
}
4. Delete the select:
delete quick;
*/ */
class QUICK_SELECT_I class QUICK_SELECT_I
...@@ -117,27 +155,16 @@ class QUICK_SELECT_I ...@@ -117,27 +155,16 @@ class QUICK_SELECT_I
reset() should be called when it is certain that row retrieval will be reset() should be called when it is certain that row retrieval will be
necessary. This call may do heavyweight initialization like buffering first necessary. This call may do heavyweight initialization like buffering first
N records etc. If reset() call fails get_next() must not be called. N records etc. If reset() call fails get_next() must not be called.
Note that reset() may be called several times if this quick select Note that reset() may be called several times if
executes in a subselect. * the quick select is executed in a subselect
* a JOIN buffer is used
RETURN RETURN
0 OK 0 OK
other Error code other Error code
*/ */
virtual int reset(void) = 0; virtual int reset(void) = 0;
/*
Initialize get_next() for row retrieval.
SYNOPSIS
get_next_init()
get_next_init() must be called before the first get_next().
If get_next_init() call fails get_next() must not be called.
RETURN
0 OK
other Error code
*/
virtual int get_next_init() { return false; }
virtual int get_next() = 0; /* get next record to retrieve */ virtual int get_next() = 0; /* get next record to retrieve */
/* Range end should be called when we have looped over the whole index */ /* Range end should be called when we have looped over the whole index */
...@@ -284,18 +311,7 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I ...@@ -284,18 +311,7 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I
~QUICK_RANGE_SELECT(); ~QUICK_RANGE_SELECT();
int init(); int init();
int reset(void) int reset(void);
{
next=0;
range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
/*
Note: in opt_range.cc there are places where it is assumed that this
function always succeeds
*/
return 0;
}
int get_next_init(void);
int get_next(); int get_next();
void range_end(); void range_end();
int get_next_prefix(uint prefix_length, byte *cur_prefix); int get_next_prefix(uint prefix_length, byte *cur_prefix);
...@@ -310,6 +326,8 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I ...@@ -310,6 +326,8 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I
#ifndef DBUG_OFF #ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose); void dbug_dump(int indent, bool verbose);
#endif #endif
private:
/* Used only by QUICK_SELECT_DESC */
QUICK_RANGE_SELECT(const QUICK_RANGE_SELECT& org) : QUICK_SELECT_I() QUICK_RANGE_SELECT(const QUICK_RANGE_SELECT& org) : QUICK_SELECT_I()
{ {
bcopy(&org, this, sizeof(*this)); bcopy(&org, this, sizeof(*this));
...@@ -685,6 +703,7 @@ class FT_SELECT: public QUICK_RANGE_SELECT { ...@@ -685,6 +703,7 @@ class FT_SELECT: public QUICK_RANGE_SELECT {
QUICK_RANGE_SELECT (thd, table, key, 1) { init(); } QUICK_RANGE_SELECT (thd, table, key, 1) { init(); }
~FT_SELECT() { file->ft_end(); } ~FT_SELECT() { file->ft_end(); }
int init() { return error=file->ft_init(); } int init() { return error=file->ft_init(); }
int reset() { return 0; }
int get_next() { return error=file->ft_read(record); } int get_next() { return error=file->ft_read(record); }
int get_type() { return QS_TYPE_FULLTEXT; } int get_type() { return QS_TYPE_FULLTEXT; }
}; };
......
...@@ -100,19 +100,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, ...@@ -100,19 +100,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
} }
else if (select && select->quick) else if (select && select->quick)
{ {
int error;
DBUG_PRINT("info",("using rr_quick")); DBUG_PRINT("info",("using rr_quick"));
if (!table->file->inited)
table->file->ha_index_init(select->quick->index);
info->read_record=rr_quick; info->read_record=rr_quick;
if ((error= select->quick->get_next_init()))
{
/* Cannot return error code here. Instead print to error log. */
table->file->print_error(error,MYF(ME_NOREFRESH));
thd->fatal_error();
}
} }
else if (table->sort.record_pointers) else if (table->sort.record_pointers)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment