Commit 81bc313e authored by monty@donna.mysql.com's avatar monty@donna.mysql.com

All statements are now run in a sub transaction

Give warning if we are using non transactional tables and do ROLLBACK
Porting of crash-me and benchmarks to FrontBase
parent c6255402
This diff is collapsed.
......@@ -196,4 +196,5 @@
#define ER_UNKNOWN_SYSTEM_VARIABLE 1193
#define ER_CRASHED_ON_USAGE 1194
#define ER_CRASHED_ON_REPAIR 1195
#define ER_ERROR_MESSAGES 196
#define ER_WARNING_NOT_COMPLETE_ROLLBACK 1196
#define ER_ERROR_MESSAGES 197
......@@ -38,7 +38,7 @@ require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n";
$|=1; # Output data immediately
$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=0;
$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=0;
$opt_cmp=$opt_user=$opt_password="";
$opt_server="mysql"; $opt_dir="output";
$opt_host="localhost";$opt_database="test";
......@@ -51,7 +51,7 @@ $log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
"user", "host", "database", "password",
"use-old-results","skip-test",
"machine", "dir", "suffix", "log"));
GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","old-headers","die-on-errors","create-options=s","hires") || usage();
GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","old-headers","die-on-errors","create-options=s","hires","tcpip") || usage();
usage() if ($opt_help);
$server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc,
......@@ -256,6 +256,17 @@ sub fetch_all_rows
if (!$sth->execute)
{
print "\n" if ($opt_debug);
if (defined($server->{'error_on_execute_means_zero_rows'}) &&
!$server->abort_if_fatal_error())
{
if (defined($must_get_result) && $must_get_result)
{
die "Error: Query $query didn't return any rows\n";
}
$sth->finish;
print "0\n" if ($opt_debug);
return 0;
}
die "Error occured with execute($query)\n -> $DBI::errstr\n";
$sth->finish;
return undef;
......@@ -507,6 +518,11 @@ All benchmarks takes the following options:
different server options without overwritten old files.
When using --fast the suffix is automaticly set to '_fast'.
--tcpip
Inform test suite that we are using TCP/IP to connect to the server. In
this case we can\t do many new connections in a row as we in this case may
fill the TCP/IP stack
--time-limit (Default $opt_time_limit)
How long a test loop is allowed to take, in seconds, before the end result
is 'estimated'.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -62,7 +62,7 @@ if (!$opt_skip_create)
my $array_ref = $tables[$ti];
# This may fail if we have no table so do not check answer
$sth = $dbh->do("drop table $table_name");
$sth = $dbh->do("drop table $table_name" . $server->{'drop_attr'});
print "Creating table $table_name\n" if ($opt_verbose);
do_many($dbh,@$array_ref);
......@@ -280,7 +280,7 @@ if (!$opt_skip_delete) # Only used when testing
for ($ti = 0; $ti <= $#table_names; $ti++)
{
my $table_name = $table_names[$ti];
$sth = $dbh->do("drop table $table_name");
$sth = $dbh->do("drop table $table_name" . $server->{'drop_attr'});
}
$end_time=new Benchmark;
......@@ -381,7 +381,7 @@ sub init_data
"flight_code integer(8) NOT NULL"],
["PRIMARY KEY (connect_code, leg_number, flight_code)"]);
@connection=
$server->create("connection",
$server->create("fconnection",
["connect_code integer(8) NOT NULL",
"from_airport char(3) NOT NULL",
"to_airport char(3) NOT NULL",
......@@ -405,7 +405,7 @@ sub init_data
"dual_airline char(2) NOT NULL",
"low_flight smallint(4) NOT NULL",
"high_flight smallint(4) NOT NULL",
"connection_name char(64) NOT NULL"],
"fconnection_name char(64) NOT NULL"],
["PRIMARY KEY (main_airline, dual_airline, low_flight)",
"INDEX main_airline1 (main_airline)"]);
......@@ -540,7 +540,7 @@ sub init_data
@table_names =
("aircraft", "airline", "airport", "airport_service",
"city", "class_of_service", "code_description",
"compound_class", "connect_leg", "connection", "day_name",
"compound_class", "connect_leg", "fconnection", "day_name",
"dual_carrier", "fare", "flight", "flight_class", "flight_day",
"flight_fare", "food_service", "ground_service", "time_interval",
"month_name",
......
......@@ -68,7 +68,7 @@ $field_count= $opt_start_field_count;
$start_time=new Benchmark;
$dbh->do("drop table bench");
$dbh->do("drop table bench" . $server->{'drop_attr'});
do_many($dbh,$server->create("bench",\@fields,\@index));
print "Insert data into the table\n";
......@@ -92,9 +92,16 @@ print "Time for insert ($opt_row_count)",
$loop_time=new Benchmark;
$add= int(($opt_field_count-$opt_start_field_count)/$opt_loop_count)+1;
$add=1 if (!$limits{'alter_add_multi_col'});
$multi_add=$server->{'limits'}->{'alter_add_multi_col'} == 1;
if ($opt_fast)
{
$add=1 if (!$server->{'limits'}->{'alter_add_multi_col'});
}
else
{
$add=1 if (!$limits{'alter_add_multi_col'});
}
$count=0;
while ($field_count < $opt_field_count)
......@@ -159,7 +166,8 @@ while ($field_count > $opt_start_field_count)
{
$fields.=",DROP i${field_count}";
}
$dbh->do("ALTER TABLE bench " . substr($fields,1)) || die $DBI::errstr;
$dbh->do("ALTER TABLE bench " . substr($fields,1) . $server->{'drop_attr'})
|| die $DBI::errstr;
}
$end_time=new Benchmark;
......@@ -173,7 +181,7 @@ skip_dropcol:
#### End of the test...Finally print time used to execute the
#### whole test.
$dbh->do("drop table bench");
$dbh->do("drop table bench" . $server->{'drop_attr'});
$dbh->disconnect;
......
......@@ -53,7 +53,7 @@ print "All tests are done $opt_loop_count times with $opt_field_count fields\n\n
$dbh = $server->connect();
print "Testing table with $opt_field_count fields\n";
$sth = $dbh->do("drop table bench1");
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'});
my @fields=();
my @index=();
......@@ -81,10 +81,14 @@ test_query("Testing select * from table with 1 record",
"select * from bench1",
$dbh,$opt_loop_count);
test_query("Testing select all_fields from table with 1 record",
"Time to select_many_fields",
"select $fields from bench1",
$dbh,$opt_loop_count);
if ($limits->{'working_all_fields'})
{
test_query("Testing select all_fields from table with 1 record",
"Time to select_many_fields",
"select $fields from bench1",
$dbh,$opt_loop_count);
}
test_query("Testing insert VALUES()",
"Time to insert_many_fields",
......@@ -101,7 +105,7 @@ test_command("Testing insert (all_fields) VALUES()",
"insert into bench1 ($fields) values($values)",
$dbh,$opt_loop_count);
$sth = $dbh->do("drop table bench1") or die $DBI::errstr;
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
if ($opt_fast && defined($server->{vacuum}))
{
......
......@@ -42,6 +42,8 @@ if ($opt_small_test)
$opt_loop_count/=100;
}
$opt_loop_count=min(1000, $opt_loop_count) if ($opt_tcpip);
print "Testing the speed of connecting to the server and sending of data\n";
print "All tests are done $opt_loop_count times\n\n";
......@@ -68,11 +70,11 @@ for ($i=0 ; $i < $opt_loop_count ; $i++)
$dbh->disconnect;
last;
}
select(undef, undef, undef, 0.001);
select(undef, undef, undef, 0.01*$j);
print "$errors " if (($opt_debug));
$errors++;
}
die $DBI::errstr if ($j == $max_test);
die "Got error '$DBI::errstr' after $i connects" if ($j == $max_test);
$dbh->disconnect;
undef($dbh);
}
......@@ -128,7 +130,7 @@ if ($limits->{'select_without_from'})
#### Then we shall do $opt_loop_count selects from this table.
#### Table will contain very simple data.
$sth = $dbh->do("drop table bench1");
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'});
do_many($dbh,$server->create("bench1",
["a int NOT NULL",
"i int",
......@@ -221,7 +223,7 @@ if ($limits->{'functions'})
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}
$sth = $dbh->do("drop table bench1")
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'})
or die $DBI::errstr;
if ($opt_fast && defined($server->{vacuum}))
......@@ -234,6 +236,8 @@ if ($opt_fast && defined($server->{vacuum}))
#### huge record in it and then we'll do $opt_loop_count selects
#### from it.
goto skip_blob_test if (!$limits->{'working_blobs'});
print "Testing retrieval of big records ($str_length bytes)\n";
do_many($dbh,$server->create("bench1", ["b blob"], []));
......@@ -265,7 +269,7 @@ $end_time=new Benchmark;
print "Time to select_big ($opt_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
$sth = $dbh->do("drop table bench1")
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'})
or do
{
# Fix for Access 2000
......@@ -277,6 +281,7 @@ if ($opt_fast && defined($server->{vacuum}))
$server->vacuum(0,\$dbh);
}
skip_blob_test:
################################ END ###################################
####
......
......@@ -64,7 +64,7 @@ if ($opt_force) # If tables used in this test exist, drop 'em
print "Okay..Let's make sure that our tables don't exist yet.\n\n";
for ($i=1 ; $i <= $max_tables ; $i++)
{
$dbh->do("drop table bench_$i");
$dbh->do("drop table bench_$i" . $server->{'drop_attr'});
}
}
......@@ -90,7 +90,7 @@ for ($i=1 ; $i <= $max_tables ; $i++)
# Got an error; Do cleanup
for ($i=1 ; $i <= $max_tables ; $i++)
{
$dbh->do("drop table bench_$i");
$dbh->do("drop table bench_$i" . $server->{'drop_attr'});
}
die "Test aborted";
}
......@@ -148,13 +148,13 @@ if ($opt_fast && $server->{'limits'}->{'multi_drop'} &&
{
$query.=",bench_$i";
}
$sth = $dbh->do($query) or die $DBI::errstr;
$sth = $dbh->do($query . $server->{'drop_attr'}) or die $DBI::errstr;
}
else
{
for ($i=1 ; $i <= $max_tables ; $i++)
{
$sth = $dbh->do("drop table bench_$i")
$sth = $dbh->do("drop table bench_$i" . $server->{'drop_attr'})
or die $DBI::errstr;
}
}
......@@ -186,7 +186,7 @@ for ($i=1 ; $i <= $opt_loop_count ; $i++)
"s char(10)",
"v varchar(100)"],
["primary key (i)"]));
$sth = $dbh->do("drop table bench_$i") or die $DBI::errstr;
$sth = $dbh->do("drop table bench_$i" . $server->{'drop_attr'}) or die $DBI::errstr;
}
$end_time=new Benchmark;
......@@ -239,7 +239,7 @@ $loop_time=new Benchmark;
for ($i=1 ; $i <= $opt_loop_count ; $i++)
{
do_many($dbh,$server->create("bench_$i", \@fields, \@index));
$dbh->do("drop table bench_$i") or die $DBI::errstr;
$dbh->do("drop table bench_$i" . $server->{'drop_attr'}) or die $DBI::errstr;
}
$end_time=new Benchmark;
......
......@@ -34,6 +34,7 @@ $opt_loop_count=100000; # number of rows/3
$small_loop_count=10; # Loop for full table retrieval
$range_loop_count=$small_loop_count*50;
$many_keys_loop_count=$opt_loop_count;
$opt_read_key_loop_count=$opt_loop_count;
chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
......@@ -46,13 +47,15 @@ if ($opt_loop_count < 256)
if ($opt_small_test)
{
$opt_loop_count/=100;
$range_loop_count/=10;
$many_keys_loop_count=$opt_loop_count/10;
$range_loop_count=10;
$opt_read_key_loop_count=10;
}
elsif ($opt_small_tables)
{
$opt_loop_count=10000; # number of rows/3
$many_keys_loop_count=$opt_loop_count;
$opt_read_key_loop_count=10;
}
elsif ($opt_small_key_tables)
{
......@@ -96,9 +99,9 @@ goto keys_test if ($opt_stage == 2);
goto select_test if ($opt_skip_create);
print "Creating tables\n";
$dbh->do("drop table bench1");
$dbh->do("drop table bench2");
$dbh->do("drop table bench3");
$dbh->do("drop table bench1" . $server->{'drop_attr'});
$dbh->do("drop table bench2" . $server->{'drop_attr'});
$dbh->do("drop table bench3" . $server->{'drop_attr'});
do_many($dbh,$server->create("bench1",
["id int NOT NULL",
"id2 int NOT NULL",
......@@ -239,11 +242,11 @@ if ($limits->{'unique_index'})
die "Didn't get an error when inserting duplicate record $tmp\n";
}
}
}
$end_time=new Benchmark;
print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
$end_time=new Benchmark;
print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}
#if ($opt_fast && defined($server->{vacuum}))
#{
......@@ -332,11 +335,13 @@ else
print " for order_by_big_key2 ($small_loop_count:$rows): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$sel=$limits->{'order_by_unused'} ? "id2" : "*";
$loop_time=new Benchmark;
$estimated=$rows=0;
for ($i=1 ; $i <= $small_loop_count ; $i++)
{
$rows+=fetch_all_rows($dbh,"select id2 from bench1 order by id3",1);
$rows+=fetch_all_rows($dbh,"select $sel from bench1 order by id3",1);
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
$small_loop_count));
......@@ -349,11 +354,12 @@ print " for order_by_big_key_diff ($small_loop_count:$rows): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$sel=$limits->{'order_by_unused'} ? "id" : "*";
$loop_time=new Benchmark;
$estimated=$rows=0;
for ($i=1 ; $i <= $small_loop_count ; $i++)
{
$rows+=fetch_all_rows($dbh,"select id from bench1 order by id2,id3",1);
$rows+=fetch_all_rows($dbh,"select $sel from bench1 order by id2,id3",1);
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
$small_loop_count));
......@@ -365,13 +371,15 @@ else
print " for order_by_big ($small_loop_count:$rows): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$sel=$limits->{'order_by_unused'} ? "dummy1" : "dummy1,id3";
$loop_time=new Benchmark;
$estimated=$rows=0;
for ($i=1 ; $i <= $range_loop_count ; $i++)
{
$start=$opt_loop_count/$range_loop_count*$i;
$end=$start+$i;
$rows+=fetch_all_rows($dbh,"select dummy1 from bench1 where id>=$start and id <= $end order by id3",1);
$rows+=fetch_all_rows($dbh,"select $sel from bench1 where id>=$start and id <= $end order by id3",1);
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
$range_loop_count));
......@@ -383,14 +391,14 @@ else
print " for order_by_range ($range_loop_count:$rows): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$sel=$limits->{'order_by_unused'} ? "dummy1" : "dummy1,id";
$loop_time=new Benchmark;
$estimated=$rows=0;
for ($i=1 ; $i <= $range_loop_count ; $i++)
{
$start=$opt_loop_count/$range_loop_count*$i;
$end=$start+$i;
$rows+=fetch_all_rows($dbh,"select dummy1 from bench1 where id>=$start and id <= $end order by id",1);
$rows+=fetch_all_rows($dbh,"select $sel from bench1 where id>=$start and id <= $end order by id",1);
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
$range_loop_count));
......@@ -402,13 +410,14 @@ else
print " for order_by_key ($range_loop_count:$rows): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$sel=$limits->{'order_by_unused'} ? "id2" : "id2,id3";
$loop_time=new Benchmark;
$estimated=$rows=0;
for ($i=1 ; $i <= $range_loop_count ; $i++)
{
$start=$opt_loop_count/$range_loop_count*$i;
$end=$start+$range_loop_count;
$rows+=fetch_all_rows($dbh,"select id2 from bench1 where id3>=$start and id3 <= $end order by id3",1);
$rows+=fetch_all_rows($dbh,"select $sel from bench1 where id3>=$start and id3 <= $end order by id3",1);
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
$range_loop_count));
......@@ -674,23 +683,26 @@ if ($limits->{'group_functions'})
print "Time for count ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
$count=$estimated=0;
for ($tests=1 ; $tests <= $small_loop_count ; $tests++)
if ($limits->{'group_distinct_functions'})
{
$count+=2;
fetch_all_rows($dbh,"select count(distinct dummy1) from bench1");
fetch_all_rows($dbh,"select dummy1,count(distinct id) from bench1 group by dummy1");
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
$small_loop_count));
$loop_time=new Benchmark;
$count=$estimated=0;
for ($tests=1 ; $tests <= $small_loop_count ; $tests++)
{
$count+=2;
fetch_all_rows($dbh,"select count(distinct dummy1) from bench1");
fetch_all_rows($dbh,"select dummy1,count(distinct id) from bench1 group by dummy1");
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
$small_loop_count));
}
if ($estimated)
{ print "Estimated time"; }
else
{ print "Time"; }
print " for count_distinct_big ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
}
if ($estimated)
{ print "Estimated time"; }
else
{ print "Time"; }
print " for count_distinct_big ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
}
......@@ -1002,9 +1014,9 @@ if ($limits->{'insert_select'})
print "Time for insert_select_2_keys (1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
$sth = $dbh->do("DROP TABLE bench2") ||
$sth = $dbh->do("DROP TABLE bench2" . $server->{'drop_attr'}) ||
die $DBI::errstr;
$sth = $dbh->do("DROP TABLE bench3") ||
$sth = $dbh->do("DROP TABLE bench3" . $server->{'drop_attr'}) ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for drop table(2): " .
......@@ -1096,7 +1108,7 @@ if (!$opt_skip_delete)
{
$sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
}
$sth = $dbh->do("drop table bench1") or die $DBI::errstr;
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
}
if ($server->small_rollback_segment())
......@@ -1309,7 +1321,7 @@ $end_time=new Benchmark;
print "Time for delete_all_many_keys ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
$sth = $dbh->do("drop table bench1") or die $DBI::errstr;
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
if ($opt_fast && defined($server->{vacuum}))
{
$server->vacuum(1,\$dbh);
......@@ -1323,7 +1335,7 @@ if ($limits->{'multi_value_insert'})
{
$query_size=$limits->{'query_size'}; # Same limit for all databases
$sth = $dbh->do("drop table bench1");
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'});
do_many($dbh,$server->create("bench1",
["id int NOT NULL",
"id2 int NOT NULL",
......@@ -1375,7 +1387,7 @@ if ($limits->{'multi_value_insert'})
# A big table may take a while to drop
$loop_time=new Benchmark;
$sth = $dbh->do("drop table bench1") or die $DBI::errstr;
$sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
$end_time=new Benchmark;
print "Time for drop table(1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
......@@ -1405,7 +1417,7 @@ sub check_select_key
$estimated=0;
$loop_time=new Benchmark;
$count=0;
for ($i=1 ; $i <= $opt_loop_count; $i++)
for ($i=1 ; $i <= $opt_read_key_loop_count; $i++)
{
$count+=2;
$tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
......@@ -1437,7 +1449,7 @@ sub check_select_key2
$estimated=0;
$loop_time=new Benchmark;
$count=0;
for ($i=1 ; $i <= $opt_loop_count; $i++)
for ($i=1 ; $i <= $opt_read_key_loop_count; $i++)
{
$count+=2;
$tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
......
......@@ -61,7 +61,7 @@ $start_time=new Benchmark;
goto select_test if ($opt_skip_create);
print "Creating table\n";
$dbh->do("drop table bench1");
$dbh->do("drop table bench1" . $server->{'drop_attr'});
do_many($dbh,$server->create("bench1",
["region char(1) NOT NULL",
......@@ -213,7 +213,7 @@ print " for select_range ($count:$rows): " .
# Testing MIN() and MAX() on keys
#
if ($limits->{'group_functions'})
if ($limits->{'group_functions'} && $limits->{'order_by_unused'})
{
$loop_time=new Benchmark;
$count=0;
......@@ -230,6 +230,7 @@ if ($limits->{'group_functions'})
fetch_all_rows($dbh,"select min(region),max(region) from bench1");
}
fetch_all_rows($dbh,"select min(rev_idn) from bench1 where region='$region'");
fetch_all_rows($dbh,"select max(grp) from bench1 where region='$region'");
fetch_all_rows($dbh,"select max(idn) from bench1 where region='$region' and grp=$grp");
if ($limits->{'group_func_sql_min_str'})
......@@ -265,6 +266,10 @@ if ($limits->{'group_functions'})
print " for count_on_key ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}
if ($limits->{'group_functions'})
{
$loop_time=new Benchmark;
$rows=0;
for ($i=0 ; $i < $opt_medium_loop_count ; $i++)
......@@ -276,7 +281,7 @@ if ($limits->{'group_functions'})
timestr(timediff($end_time, $loop_time),"all") . "\n";
}
if ($limits->{'group_functions'})
if ($limits->{'group_distinct_functions'})
{
print "Testing count(distinct) on the table\n";
$loop_time=new Benchmark;
......@@ -362,7 +367,7 @@ if ($opt_lock_tables)
}
if (!$opt_skip_delete)
{
do_query($dbh,"drop table bench1");
do_query($dbh,"drop table bench1" . $server->{'drop_attr'});
}
if ($opt_fast && defined($server->{vacuum}))
......
......@@ -57,7 +57,7 @@ if (!$opt_skip_create)
my $array_ref = $tables[$ti];
# This may fail if we have no table so do not check answer
$sth = $dbh->do("drop table $table_name");
$sth = $dbh->do("drop table $table_name" . $server->{'drop_attr'});
print "Creating table $table_name\n" if ($opt_verbose);
do_many($dbh,@$array_ref);
}
......@@ -201,7 +201,7 @@ if (!$opt_skip_delete)
for ($ti = 0; $ti <= $#table_names; $ti++)
{
my $table_name = $table_names[$ti];
$sth = $dbh->do("drop table $table_name");
$sth = $dbh->do("drop table $table_name" . $server->{'drop_attr'});
}
}
......
......@@ -168,25 +168,23 @@ bool berkeley_flush_logs()
}
int berkeley_commit(THD *thd)
int berkeley_commit(THD *thd, void *trans)
{
DBUG_ENTER("berkeley_commit");
DBUG_PRINT("trans",("ending transaction"));
int error=txn_commit((DB_TXN*) thd->transaction.bdb_tid,0);
int error=txn_commit((DB_TXN*) trans,0);
#ifndef DBUG_OFF
if (error)
DBUG_PRINT("error",("error: %d",error));
#endif
thd->transaction.bdb_tid=0;
DBUG_RETURN(error);
}
int berkeley_rollback(THD *thd)
int berkeley_rollback(THD *thd, void *trans)
{
DBUG_ENTER("berkeley_rollback");
DBUG_PRINT("trans",("aborting transaction"));
int error=txn_abort((DB_TXN*) thd->transaction.bdb_tid);
thd->transaction.bdb_tid=0;
int error=txn_abort((DB_TXN*) trans);
DBUG_RETURN(error);
}
......@@ -1337,6 +1335,10 @@ int ha_berkeley::reset(void)
/*
As MySQL will execute an external lock for every new table it uses
we can use this to start the transactions.
If we are in auto_commit mode we just need to start a transaction
for the statement to be able to rollback the statement.
If not, we have to start a master transaction if there doesn't exist
one from before.
*/
int ha_berkeley::external_lock(THD *thd, int lock_type)
......@@ -1345,16 +1347,34 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
DBUG_ENTER("ha_berkeley::external_lock");
if (lock_type != F_UNLCK)
{
if (!thd->transaction.bdb_lock_count++ && !thd->transaction.bdb_tid)
if (!thd->transaction.bdb_lock_count++)
{
/* Found first lock, start transaction */
DBUG_PRINT("trans",("starting transaction"));
if ((error=txn_begin(db_env, 0,
(DB_TXN**) &thd->transaction.bdb_tid,
/* First table lock, start transaction */
if (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
!thd->transaction.all.bdb_tid)
{
/* We have to start a master transaction */
DBUG_PRINT("trans",("starting transaction"));
if ((error=txn_begin(db_env, 0,
(DB_TXN**) &thd->transaction.all.bdb_tid,
0)))
{
thd->transaction.bdb_lock_count--; // We didn't get the lock
DBUG_RETURN(error);
}
}
DBUG_PRINT("trans",("starting transaction for statement"));
if ((error=txn_begin(db_env,
(DB_TXN*) thd->transaction.all.bdb_tid,
(DB_TXN**) &thd->transaction.stmt.bdb_tid,
0)))
thd->transaction.bdb_lock_count--;
{
/* We leave the possible master transaction open */
thd->transaction.bdb_lock_count--; // We didn't get the lock
DBUG_RETURN(error);
}
}
transaction= (DB_TXN*) thd->transaction.bdb_tid;
transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid;
}
else
{
......@@ -1371,23 +1391,21 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
current_row.data=0;
if (!--thd->transaction.bdb_lock_count)
{
if (thd->transaction.bdb_tid && (thd->options & OPTION_AUTO_COMMIT)
&& !(thd->options & OPTION_BEGIN))
if (thd->transaction.stmt.bdb_tid)
{
/*
F_UNLOCK is done without a transaction commit / rollback.
This happens if the thread didn't update any rows or if
something went wrong during an update.
We can in this case silenty abort the transaction.
This happens if the thread didn't update any rows
We must in this case commit the work to keep the row locks
*/
DBUG_PRINT("trans",("aborting transaction"));
error=txn_abort((DB_TXN*) thd->transaction.bdb_tid);
thd->transaction.bdb_tid=0;
DBUG_PRINT("trans",("commiting non-updating transaction"));
error=txn_commit((DB_TXN*) thd->transaction.stmt.bdb_tid,0);
thd->transaction.stmt.bdb_tid=0;
}
}
}
DBUG_RETURN(error);
}
}
THR_LOCK_DATA **ha_berkeley::store_lock(THD *thd, THR_LOCK_DATA **to,
......
......@@ -156,5 +156,5 @@ extern TYPELIB berkeley_lock_typelib;
bool berkeley_init(void);
bool berkeley_end(void);
bool berkeley_flush_logs(void);
int berkeley_commit(THD *thd);
int berkeley_rollback(THD *thd);
int berkeley_commit(THD *thd, void *trans);
int berkeley_rollback(THD *thd, void *trans);
......@@ -174,78 +174,83 @@ int ha_panic(enum ha_panic_function flag)
} /* ha_panic */
/*
This is used to commit or rollback a single statement depending
on the value of error
*/
int ha_autocommit_or_rollback(THD *thd, int error)
{
DBUG_ENTER("ha_autocommit_or_rollback");
#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB)
if ((thd->options & OPTION_AUTO_COMMIT) && !(thd->options & OPTION_BEGIN)
&& !thd->locked_tables)
#ifdef USING_TRANSACTIONS
if (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
!thd->locked_tables)
{
if (!error)
{
if (ha_commit(thd))
if (ha_commit_stmt(thd))
error=1;
}
}
else
(void) ha_rollback(thd);
(void) ha_rollback_stmt(thd);
}
#endif
DBUG_RETURN(error);
}
int ha_commit(THD *thd)
int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
int error=0;
DBUG_ENTER("ha_commit");
#ifdef HAVE_BERKELEY_DB
if (thd->transaction.bdb_tid)
if (trans->bdb_tid)
{
int error=berkeley_commit(thd);
if (error)
if ((error=berkeley_commit(thd,trans->bdb_tid)))
{
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
trans->bdb_tid=0;
}
#endif
#ifdef HAVE_INNOBASE_DB
if (thd->transaction.innobase_tid)
{
int error=innobase_commit(thd);
if (error)
if ((error=innobase_commit(thd,trans->innobase_tid))
{
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
trans->innobase_tid=0;
}
#endif
DBUG_RETURN(error);
}
int ha_rollback(THD *thd)
int ha_rollback_trans(THD *thd, THD_TRANS *trans)
{
int error=0;
DBUG_ENTER("ha_rollback");
#ifdef HAVE_BERKELEY_DB
if (thd->transaction.bdb_tid)
if (trans->bdb_tid)
{
int error=berkeley_rollback(thd);
if (error)
if ((error=berkeley_rollback(thd, trans->bdb_tid)))
{
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
error=1;
}
trans->bdb_tid=0;
}
#endif
#ifdef HAVE_INNOBASE_DB
if (thd->transaction.innobase_tid)
if (trans->innobase_tid)
{
int error=innobase_rollback(thd);
if (error)
if ((error=innobase_rollback(thd)))
{
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
error=1;
}
trans->innobase_tid=0;
}
#endif
DBUG_RETURN(error);
......
......@@ -25,6 +25,10 @@
#define NO_HASH /* Not yet implemented */
#endif
#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB) || defined(HAVE_GEMENI_DB)
#define USING_TRANSACTIONS
#endif
// the following is for checking tables
#define HA_ADMIN_ALREADY_DONE 1
......@@ -114,6 +118,12 @@ enum row_type { ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC,
#define HA_CREATE_USED_AUTO 1
#define HA_CREATE_USED_RAID 2
typedef struct st_thd_trans {
void *bdb_tid;
void *innobase_tid;
void *gemeni_tid;
} THD_TRANS;
typedef struct st_ha_create_information
{
ulong table_options;
......@@ -294,6 +304,12 @@ class handler :public Sql_alloc
extern const char *ha_row_type[];
extern TYPELIB ha_table_typelib;
/* Wrapper functions */
#define ha_commit_stmt(thd) (ha_commit_trans((thd), &((thd)->transaction.stmt)))
#define ha_rollback_stmt(thd) (ha_rollback_trans((thd), &((thd)->transaction.stmt)))
#define ha_commit(thd) (ha_commit_trans((thd), &((thd)->transaction.all)))
#define ha_rollback(thd) (ha_rollback_trans((thd), &((thd)->transaction.all)))
handler *get_new_handler(TABLE *table, enum db_type db_type);
my_off_t ha_get_ptr(byte *ptr, uint pack_length);
void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos);
......@@ -304,8 +320,8 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info);
int ha_delete_table(enum db_type db_type, const char *path);
void ha_key_cache(void);
int ha_commit(THD *thd);
int ha_rollback(THD *thd);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
bool ha_flush_logs(void);
......@@ -134,7 +134,7 @@ void kill_one_thread(THD *thd, ulong id);
#define TEST_NO_EXTRA 128
#define TEST_CORE_ON_SIGNAL 256 /* Give core if signal */
/* options for select set by the yacc parser */
/* options for select set by the yacc parser (stored in lex->options) */
#define SELECT_DISTINCT 1
#define SELECT_STRAIGHT_JOIN 2
#define SELECT_DESCRIBE 4
......@@ -155,14 +155,17 @@ void kill_one_thread(THD *thd, ulong id);
#define OPTION_SAFE_UPDATES OPTION_ANSI_MODE*2
#define OPTION_BUFFER_RESULT OPTION_SAFE_UPDATES*2
#define OPTION_BIN_LOG OPTION_BUFFER_RESULT*2
#define OPTION_AUTO_COMMIT OPTION_BIN_LOG*2
#define OPTION_BEGIN OPTION_AUTO_COMMIT*2
#define OPTION_NOT_AUTO_COMMIT OPTION_BIN_LOG*2
#define OPTION_BEGIN OPTION_NOT_AUTO_COMMIT*2
#define OPTION_QUICK OPTION_BEGIN*2
#define OPTION_QUOTE_SHOW_CREATE OPTION_QUICK*2
/* Set if we are updating a non-transaction safe table */
#define OPTION_STATUS_NO_TRANS_UPDATE OPTION_QUOTE_SHOW_CREATE*2
/* The following is set when parsing the query */
#define OPTION_NO_INDEX_USED OPTION_QUOTE_SHOW_CREATE*2
#define OPTION_NO_GOOD_INDEX_USED OPTION_NO_INDEX_USED*2
#define QUERY_NO_INDEX_USED OPTION_STATUS_NO_TRANS_UPDATE*2
#define QUERY_NO_GOOD_INDEX_USED QUERY_NO_INDEX_USED*2
#define RAID_BLOCK_SIZE 1024
......@@ -255,6 +258,7 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
/* net_pkg.c */
void send_error(NET *net,uint sql_errno=0, const char *err=0);
void send_warning(NET *net, uint sql_errno, const char *err=0);
void net_printf(NET *net,uint sql_errno, ...);
void send_ok(NET *net,ha_rows affected_rows=0L,ulonglong id=0L,
const char *info=0);
......
......@@ -192,8 +192,7 @@ uint test_flags, select_errors=0, dropping_tables=0,ha_open_options=0;
uint volatile thread_count=0, thread_running=0, kill_cached_threads=0,
wake_thread=0, global_read_lock=0;
ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
OPTION_BIN_LOG | OPTION_AUTO_COMMIT |
OPTION_QUOTE_SHOW_CREATE );
OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE );
uint protocol_version=PROTOCOL_VERSION;
ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
max_join_size,join_buff_size,tmp_table_size,thread_stack,
......
......@@ -73,6 +73,18 @@ void send_error(NET *net, uint sql_errno, const char *err)
DBUG_VOID_RETURN;
}
/*
At some point we need to be able to distinguish between warnings and
errors; The following function will help make this easier.
*/
void send_warning(NET *net, uint sql_errno, const char *err)
{
DBUG_ENTER("send_warning");
send_error(net,sql_errno,err);
DBUG_VOID_RETURN;
}
/**
** write error package and flush to client
** It's a little too low level, but I don't want to allow another buffer
......
......@@ -211,3 +211,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -200,3 +200,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -201,3 +201,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -200,3 +200,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -199,3 +199,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -199,3 +199,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -199,3 +199,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -199,3 +199,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -201,3 +201,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -197,3 +197,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -201,3 +201,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -200,3 +200,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -205,3 +205,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -198,3 +198,4 @@
"Unknown system variable '%-.64'",
"Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Warning: Some non-transactional changed tables couldn't be rolled back",
......@@ -195,7 +195,7 @@
"Hittar inte ett FULLTEXT index i kolumnlistan",
"Kan inte exekvera kommandot emedan du har en låst tabell eller an aktiv transaktion",
"Okänd system variabel '%-.64'",
#ER_CRASHED_ON_USAGE
"Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE",
#ER_CRASHED_ON_REPAIR
"Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades",
#ER_WARNING_NOT_COMPLETE_ROLLBACK
"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
......@@ -197,3 +197,4 @@
"Okänd system variabel '%-.64'",
"Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE",
"Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades",
"Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK",
......@@ -548,8 +548,7 @@ static int init_slave_thread(THD* thd)
thd->master_access= ~0;
thd->priv_user = 0;
thd->slave_thread = 1;
thd->options = (((opt_log_slave_updates) ? OPTION_BIN_LOG:0)
| OPTION_AUTO_COMMIT | OPTION_AUTO_IS_NULL) ;
thd->options = (((opt_log_slave_updates) ? OPTION_BIN_LOG:0) | OPTION_AUTO_IS_NULL) ;
thd->system_thread = 1;
thd->client_capabilities = CLIENT_LOCAL_FILES;
slave_real_id=thd->real_id=pthread_self();
......
......@@ -79,8 +79,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
bootstrap(0),in_lock_tables(0),
global_read_lock(0)
{
host=user=db=query=ip=0;
proc_info="login";
host=user=db=query=ip=0;
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=0;
query_length=col_access=0;
......@@ -117,13 +117,12 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
ull=0;
system_thread=0;
bzero((char*) &mem_root,sizeof(mem_root));
#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB) || defined(HAVE_GEMENI_DB)
#ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction));
if (open_cached_file(&transaction.trans_log,
mysql_tmpdir,LOG_PREFIX,0,MYF(MY_WME)))
killed=1;
transaction.bdb_lock_count=0;
#endif
transaction.bdb_tid=0;
#ifdef __WIN__
real_id = 0 ;
......@@ -146,7 +145,7 @@ THD::~THD()
close_thread_tables(this);
}
close_temporary_tables(this);
#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB) || defined(HAVE_GEMENI_DB)
#ifdef USING_TRANSACTIONS
close_cached_file(&transaction.trans_log);
#endif
if (global_read_lock)
......
......@@ -244,7 +244,8 @@ class THD :public ilink {
delayed_insert *di;
struct st_transactions {
IO_CACHE trans_log;
void *bdb_tid;
THD_TRANS all; /* Trans since BEGIN WORK */
THD_TRANS stmt; /* Trans for current statement */
uint bdb_lock_count;
} transaction;
Item *free_list;
......@@ -293,7 +294,12 @@ class THD :public ilink {
}
return last_insert_id;
}
inline bool active_transaction() { return transaction.bdb_tid != 0; }
inline bool active_transaction()
{
return (transaction.all.bdb_tid != 0 ||
transaction.all.innobase_tid != 0 ||
transaction.all.gemeni_tid != 0);
}
inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
inline gptr calloc(unsigned int size)
{
......
......@@ -34,7 +34,7 @@ int generate_table(THD *thd, TABLE_LIST *table_list,
thd->proc_info="generate_table";
if(global_read_lock)
if (global_read_lock)
{
if(thd->global_read_lock)
{
......@@ -141,8 +141,8 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
use_generate_table= (!using_limit && !conds &&
!(specialflag &
(SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
(thd->options & OPTION_AUTO_COMMIT) &&
!(thd->options & OPTION_BEGIN));
!(thd->options &
(OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)));
if (use_generate_table && ! thd->open_tables)
{
error=generate_table(thd,table_list,(TABLE*) 0);
......@@ -175,7 +175,7 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
/* If running in safe sql mode, don't allow updates without keys */
if (!table->quick_keys)
{
thd->lex.options|=OPTION_NO_INDEX_USED;
thd->lex.options|=QUERY_NO_INDEX_USED;
if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
{
delete select;
......@@ -223,6 +223,8 @@ int mysql_delete(THD *thd,TABLE_LIST *table_list,COND *conds,ha_rows limit,
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
if (!table->file->has_transactions())
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (ha_autocommit_or_rollback(thd,error >= 0))
error=1;
......
......@@ -222,7 +222,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
break;
}
}
if (lock_type == TL_WRITE_DELAYED)
if (lock_type == TL_WRITE_DELAYED && ! table->file->has_transactions())
{
error=write_delayed(thd,table,duplic,query, thd->query_length, log_on);
query=0;
......@@ -262,6 +262,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
if (!table->file->has_transactions())
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
error=ha_autocommit_or_rollback(thd,error);
if (thd->lock)
......@@ -282,7 +284,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
!thd->cuted_fields))
send_ok(&thd->net,info.copied+info.deleted,id);
else {
else
{
char buff[160];
if (duplic == DUP_IGNORE)
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.records-info.copied,
......
......@@ -241,6 +241,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
send_ok(&thd->net,info.copied+info.deleted,0L,name);
mysql_update_log.write(thd,thd->query,thd->query_length);
if (!table->file->has_transactions())
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
if (!read_file_from_client)
{
ex->skip_lines = save_skip_lines;
......
......@@ -73,13 +73,12 @@ static void init_signals(void)
static inline bool end_active_trans(THD *thd)
{
if (!(thd->options & OPTION_AUTO_COMMIT) ||
(thd->options & OPTION_BEGIN))
if (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))
{
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (ha_commit(thd))
return 1;
thd->options&= ~(ulong) (OPTION_BEGIN);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
}
return 0;
}
......@@ -576,6 +575,7 @@ bool do_command(THD *thd)
thread_running++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->set_time();
thd->lex.options=0; // We store status here
switch(command) {
case COM_INIT_DB:
if (!mysql_change_db(thd,packet+1))
......@@ -827,7 +827,7 @@ bool do_command(THD *thd)
{
if ((ulong) (thd->start_time - thd->time_after_lock) > long_query_time ||
((thd->lex.options &
(OPTION_NO_INDEX_USED | OPTION_NO_GOOD_INDEX_USED)) &&
(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED)) &&
(specialflag & SPECIAL_LONG_LOG_FORMAT)))
{
long_query_count++;
......@@ -1560,12 +1560,12 @@ mysql_execute_command(void)
thd->options,(long) thd->default_select_limit));
/* Check if auto_commit mode changed */
if ((org_options ^ lex->options) & OPTION_AUTO_COMMIT)
if ((org_options ^ lex->options) & OPTION_NOT_AUTO_COMMIT)
{
if (!(org_options & OPTION_AUTO_COMMIT))
if ((org_options & OPTION_NOT_AUTO_COMMIT))
{
/* We changed to auto_commit mode */
thd->options&= ~(ulong) (OPTION_BEGIN);
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
if (ha_commit(thd))
{
......@@ -1750,7 +1750,7 @@ mysql_execute_command(void)
even if there is a problem with the OPTION_AUTO_COMMIT flag
(Which of course should never happen...)
*/
thd->options&= ~(ulong) (OPTION_BEGIN);
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_commit(thd))
send_ok(&thd->net);
......@@ -1758,12 +1758,17 @@ mysql_execute_command(void)
res= -1;
break;
case SQLCOM_ROLLBACK:
thd->options&= ~(ulong) (OPTION_BEGIN);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_rollback(thd))
send_ok(&thd->net);
{
if (thd->options & OPTION_STATUS_NO_TRANS_UPDATE)
send_warning(&thd->net,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
else
send_ok(&thd->net);
}
else
res= -1;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
break;
default: /* Impossible */
send_ok(&thd->net);
......
......@@ -2420,7 +2420,7 @@ make_join_readinfo(JOIN *join,uint options)
/* These init changes read_record */
if (tab->use_quick == 2)
{
join->thd->lex.options|=OPTION_NO_GOOD_INDEX_USED;
join->thd->lex.options|=QUERY_NO_GOOD_INDEX_USED;
tab->read_first_record= join_init_quick_read_record;
statistic_increment(select_range_check_count, &LOCK_status);
}
......@@ -2435,7 +2435,7 @@ make_join_readinfo(JOIN *join,uint options)
}
else
{
join->thd->lex.options|=OPTION_NO_INDEX_USED;
join->thd->lex.options|=QUERY_NO_INDEX_USED;
statistic_increment(select_scan_count, &LOCK_status);
}
}
......@@ -2447,7 +2447,7 @@ make_join_readinfo(JOIN *join,uint options)
}
else
{
join->thd->lex.options|=OPTION_NO_INDEX_USED;
join->thd->lex.options|=QUERY_NO_INDEX_USED;
statistic_increment(select_full_join_count, &LOCK_status);
}
}
......
......@@ -1543,7 +1543,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
}
}
if ((error = ha_commit(thd)))
/* The ALTER TABLE is always in it's own transaction */
error = ha_commit_stmt(thd);
if (ha_commit(thd))
error=1;
if (error)
{
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
......@@ -1666,7 +1670,16 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
if (to->file->activate_all_index(thd))
error=1;
if (ha_commit(thd) || to->file->external_lock(thd,F_UNLCK))
/*
Ensure that the new table is saved properly to disk so that we
can do a rename
*/
if (ha_commit_stmt(thd))
error=1;
if (ha_commit(thd))
error=1;
if (to->file->external_lock(thd,F_UNLCK))
error=1;
err:
free_io_cache(from);
......
......@@ -102,7 +102,7 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
/* If running in safe sql mode, don't allow updates without keys */
if (!table->quick_keys)
{
thd->lex.options|=OPTION_NO_INDEX_USED;
thd->lex.options|=QUERY_NO_INDEX_USED;
if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
{
delete select;
......@@ -245,6 +245,8 @@ int mysql_update(THD *thd,TABLE_LIST *table_list,List<Item> &fields,
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
if (!table->file->has_transactions())
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (ha_autocommit_or_rollback(thd, error >= 0))
error=1;
......
......@@ -1943,7 +1943,7 @@ opt_into:
*/
drop:
DROP TABLE_SYM if_exists table_list
DROP TABLE_SYM if_exists table_list opt_restrict
{
Lex->sql_command = SQLCOM_DROP_TABLE;
Lex->drop_if_exists = $3;
......@@ -2573,6 +2573,13 @@ option_value:
else
Lex->options|= $1;
}
| AUTOCOMMIT equal NUM
{
if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */
Lex->options&= ~(OPTION_NOT_AUTO_COMMIT);
else
Lex->options|= OPTION_NOT_AUTO_COMMIT;
}
| SQL_SELECT_LIMIT equal ULONG_NUM
{
Lex->select_limit= $3;
......@@ -2656,7 +2663,6 @@ text_or_password:
set_option:
SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; }
| AUTOCOMMIT { $$= OPTION_AUTO_COMMIT; }
| SQL_BIG_SELECTS { $$= OPTION_BIG_SELECTS; }
| SQL_LOG_OFF { $$= OPTION_LOG_OFF; }
| SQL_LOG_UPDATE
......
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