Merge mysql.com:/home/jonas/src/mysql-5.0

into mysql.com:/home/jonas/src/mysql-5.0-ndb


sql/mysqld.cc:
  Auto merged
sql/sql_insert.cc:
  Auto merged
This commit is contained in:
unknown 2005-02-03 17:05:55 +01:00
commit d595ac8df8
83 changed files with 1484 additions and 454 deletions

View file

@ -9,5 +9,5 @@ then
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
fi
CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server
CC=ecc CFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" CXX=ecc CXXFLAGS="-w1 -DEXTRA_DEBUG -DSAFEMALLOC -DSAFE_MUTEX -O2" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static --with-client-ldflags=-all-static --with-debug --with-innodb --with-embedded-server --with-archive-storage-engine
gmake

View file

@ -210,10 +210,16 @@ if (-d $target_dir)
}
else
{
&logger("Renaming $target_dir to $target_dir.old." . $$);
# Get the time stamp of "configure.in"
@stat= stat("$target_dir/configure.in");
my $mtime= $stat[9];
my ($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime);
my $mtime= sprintf("%04d-%02d-%02d-%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min);
&logger("Renaming $target_dir to $target_dir-$mtime");
$command= "mv ";
$command.= "-v " if ($opt_verbose || defined $opt_log);
$command.= "$target_dir $target_dir.old." . $$;
$command.= "$target_dir $target_dir-$mtime";
&run_command($command, "Could not rename $target_dir!");
}
}

View file

@ -7,7 +7,7 @@ use Sys::Hostname;
@config_options= ();
@make_options= ();
$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env="";
$opt_comment=$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env="";
$opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix="";
$opt_tmp=$opt_version_suffix="";
$opt_bundled_zlib=$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_one_error=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_archive=$opt_with_cluster=$opt_with_csv=$opt_with_example=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=$opt_readline=0;
@ -17,6 +17,7 @@ GetOptions(
"bdb",
"build-thread=i",
"bundled-zlib",
"comment=s",
"config-env=s" => \@config_env,
"config-extra-env=s" => \@config_extra_env,
"config-options=s" => \@config_options,
@ -111,6 +112,7 @@ $log="$pwd/Logs/$host-$major.$minor$opt_version_suffix.log";
$opt_distribution =~ /(mysql[^\/]*)\.tar/;
$ver=$1;
$gcc_version=which("gcc");
$opt_comment= "Official MySQL$opt_version_suffix binary" unless $opt_comment;
if (defined($gcc_version) && ! $opt_config_env)
{
$tmp=`$gcc_version -v 2>&1`;
@ -305,7 +307,7 @@ if ($opt_stage <= 1)
}
$prefix="/usr/local/mysql";
check_system("$opt_config_env ./configure --prefix=$prefix --localstatedir=$prefix/data --libexecdir=$prefix/bin --with-comment=\"Official MySQL$opt_version_suffix binary\" --with-extra-charsets=complex --with-server-suffix=\"$opt_version_suffix\" --enable-thread-safe-client --enable-local-infile $opt_config_options","Thank you for choosing MySQL");
check_system("$opt_config_env ./configure --prefix=$prefix --localstatedir=$prefix/data --libexecdir=$prefix/bin --with-comment=\"$opt_comment\" --with-extra-charsets=complex --with-server-suffix=\"$opt_version_suffix\" --enable-thread-safe-client --enable-local-infile $opt_config_options","Thank you for choosing MySQL");
if (-d "$pwd/$host/include-mysql")
{
safe_system("cp -r $pwd/$host/include-mysql/* $pwd/$host/$ver/include");
@ -532,6 +534,10 @@ When running several Do-compile runs in parallel, each build
should have its own thread ID, so running the test suites
does not cause conflicts with duplicate TCP port numbers.
--comment=<comment>
Replace the default compilation comment that is embedded into
the mysqld binary.
--config-env=<environment for configure>
To set up the environment, like 'CC=cc CXX=gcc CXXFLAGS=-O3'
@ -689,16 +695,20 @@ sub abort
if ($opt_user)
{
$mail_header_file="$opt_tmp/do-command.$$";
open(TMP,">$mail_header_file");
# Take the last 40 lines of the build log
open(LOG, "$log") or die $!;
my @log= <LOG>;
close LOG;
splice @log => 0, -40;
my $mail_file="$opt_tmp/do-command.$$";
open(TMP,">$mail_file") or die $!;
print TMP "From: mysqldev\@$full_host_name\n";
print TMP "To: $email\n";
print TMP "Subject: $host($uname): $ver$opt_version_suffix compilation failed\n\n";
print TMP @log;
close TMP;
system("tail -n 40 $log > $log.mail");
system("cat $mail_header_file $log.mail | $sendmail -t -f $email");
unlink($mail_header_file);
unlink("$log.mail");
system("$sendmail -t -f $email < $mail_file");
unlink($mail_file);
}
exit 1;
}

View file

@ -1009,6 +1009,7 @@ static void usage(void)
print_defaults("my",load_default_groups);
puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
create databasename Create a new database\n\
debug Instruct server to write debug information to log\n\
drop databasename Delete a database and all its tables\n\
extended-status Gives an extended status message from the server\n\
flush-hosts Flush all cached hosts\n\

View file

@ -2195,27 +2195,27 @@ static my_bool dump_all_views_in_db(char *database)
RETURN
void
*/
static void get_actual_table_name( const char *old_table_name,
char *new_table_name,
int buf_size )
static void get_actual_table_name(const char *old_table_name,
char *new_table_name,
int buf_size)
{
MYSQL_RES *tableRes;
MYSQL_ROW row;
char query[ NAME_LEN + 50 ];
MYSQL_RES *tableRes;
MYSQL_ROW row;
char query[ NAME_LEN + 50 ];
DBUG_ENTER("get_actual_table_name");
DBUG_ENTER("get_actual_table_name");
sprintf( query, "SHOW TABLES LIKE '%s'", old_table_name);
if (mysql_query_with_error_report(sock, 0, query))
{
safe_exit(EX_MYSQLERR);
}
sprintf( query, "SHOW TABLES LIKE '%s'", old_table_name );
if (mysql_query_with_error_report(sock, 0, query))
{
safe_exit(EX_MYSQLERR);
}
tableRes = mysql_store_result( sock );
row = mysql_fetch_row( tableRes );
strncpy( new_table_name, row[0], buf_size );
mysql_free_result(tableRes);
} /* get_actual_table_name */
tableRes= mysql_store_result( sock );
row= mysql_fetch_row( tableRes );
strmake(new_table_name, row[0], buf_size-1);
mysql_free_result(tableRes);
}
static int dump_selected_tables(char *db, char **table_names, int tables)

View file

@ -218,12 +218,14 @@ int main(int argc,char *argv[])
string 'Unknown Error'. To avoid printing it we try to find the
error string by asking for an impossible big error message.
*/
msg = strerror(10000);
msg= strerror(10000);
/* allocate a buffer for unknown_error since strerror always returns the same pointer
on some platforms such as Windows */
unknown_error = malloc( strlen(msg)+1 );
strcpy( unknown_error, msg );
/*
Allocate a buffer for unknown_error since strerror always returns
the same pointer on some platforms such as Windows
*/
unknown_error= malloc(strlen(msg)+1);
strmov(unknown_error, msg);
for ( ; argc-- > 0 ; argv++)
{
@ -276,7 +278,7 @@ int main(int argc,char *argv[])
/* if we allocated a buffer for unknown_error, free it now */
if (unknown_error)
free(unknown_error);
free(unknown_error);
exit(error);
return error;

View file

@ -686,7 +686,9 @@ buf_read_recv_pages(
fprintf(stderr,
"InnoDB: Error: InnoDB has waited for 50 seconds for pending\n"
"InnoDB: reads to the buffer pool to be finished.\n"
"InnoDB: Number of pending reads %lu\n", (ulong) buf_pool->n_pend_reads);
"InnoDB: Number of pending reads %lu, pending pread calls %lu\n",
(ulong) buf_pool->n_pend_reads,
(ulong)os_file_n_pending_preads);
os_aio_print_debug = TRUE;
}

View file

@ -3013,8 +3013,8 @@ fil_load_single_table_tablespaces(void)
/* printf(
" Looking at file %s\n", fileinfo.name); */
if (fileinfo.type == OS_FILE_TYPE_DIR
|| dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
if (fileinfo.type == OS_FILE_TYPE_DIR) {
goto next_file_item;
}

View file

@ -279,7 +279,15 @@ rec_get_next_offs(
/* Note that for 64 KiB pages, field_value can 'wrap around'
and the debug assertion is not valid */
ut_ad((int16_t)field_value
/* In the following assertion, field_value is interpreted
as signed 16-bit integer in 2's complement arithmetics.
If all platforms defined int16_t in the standard headers,
the expression could be written simpler as
(int16_t) field_value + ut_align_offset(...) < UNIV_PAGE_SIZE
*/
ut_ad((field_value >= 32768
? field_value - 65536
: field_value)
+ ut_align_offset(rec, UNIV_PAGE_SIZE)
< UNIV_PAGE_SIZE);
#endif

View file

@ -225,6 +225,21 @@ trx_savepoint_for_mysql(
position corresponding to this
connection at the time of the
savepoint */
/***********************************************************************
Releases a named savepoint. Savepoints which
were set after this savepoint are deleted. */
ulint
trx_release_savepoint_for_mysql(
/*================================*/
/* out: if no savepoint
of the name found then
DB_NO_SAVEPOINT,
otherwise DB_SUCCESS */
trx_t* trx, /* in: transaction handle */
const char* savepoint_name); /* in: savepoint name */
/***********************************************************************
Frees savepoint structs. */

View file

@ -80,10 +80,6 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */
#ifdef DBUG_ON
#define UNIV_DEBUG
#endif /* DBUG_ON */
/*
#define UNIV_DEBUG
#define UNIV_MEM_DEBUG

View file

@ -711,12 +711,12 @@ http://www.mysql.com/doc/en/Windows_symbolic_links.html */
} else if (lpFindFileData->dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY) {
info->type = OS_FILE_TYPE_DIR;
} else if (lpFindFileData->dwFileAttributes
& FILE_ATTRIBUTE_NORMAL) {
/* TODO: are FILE_ATTRIBUTE_NORMAL files really all normal files? */
info->type = OS_FILE_TYPE_FILE;
} else {
info->type = OS_FILE_TYPE_UNKNOWN;
/* It is probably safest to assume that all other
file types are normal. Better to check them rather
than blindly skip them. */
info->type = OS_FILE_TYPE_FILE;
}
}
@ -834,7 +834,7 @@ os_file_create_directory(
rcode = CreateDirectory(pathname, NULL);
if (!(rcode != 0 ||
(GetLastError() == ERROR_FILE_EXISTS && !fail_if_exists))) {
(GetLastError() == ERROR_ALREADY_EXISTS && !fail_if_exists))) {
/* failure */
os_file_handle_error(pathname, "CreateDirectory");
@ -918,8 +918,9 @@ try_again:
file = CreateFile(name,
access,
FILE_SHARE_READ,/* file can be read also by other
processes */
FILE_SHARE_READ | FILE_SHARE_WRITE,
/* file can be read ansd written also
by other processes */
NULL, /* default security attributes */
create_flag,
attributes,
@ -1024,7 +1025,7 @@ os_file_create_simple_no_error_handling(
DWORD create_flag;
DWORD access;
DWORD attributes = 0;
DWORD share_mode = FILE_SHARE_READ;
DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
ut_a(name);
@ -1347,7 +1348,7 @@ loop:
return(TRUE);
}
if (GetLastError() == ERROR_PATH_NOT_FOUND) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
/* the file does not exist, this not an error */
return(TRUE);
@ -1408,7 +1409,7 @@ loop:
return(TRUE);
}
if (GetLastError() == ERROR_PATH_NOT_FOUND) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
/* If the file does not exist, we classify this as a 'mild'
error and return */

View file

@ -51,14 +51,19 @@ innobase_invalidate_query_cache(
chars count */
/**********************************************************************
This function returns true if SQL-query in the current thread
This function returns true if
1) SQL-query in the current thread
is either REPLACE or LOAD DATA INFILE REPLACE.
2) SQL-query in the current thread
is INSERT ON DUPLICATE KEY UPDATE.
NOTE that /mysql/innobase/row/row0ins.c must contain the
prototype for this function ! */
ibool
innobase_query_is_replace(void);
/*===========================*/
innobase_query_is_update(void);
/*************************************************************************
Creates an insert node struct. */
@ -1597,12 +1602,12 @@ row_ins_scan_sec_index_for_duplicate(
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
if (innobase_query_is_replace()) {
if (innobase_query_is_update()) {
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
+ INSERT. Therefore, we should take X-lock for
duplicates */
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
INSERT ON DUPLICATE KEY UPDATE). */
err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY,
rec, index, offsets, thr);
@ -1720,12 +1725,12 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
if (innobase_query_is_replace()) {
if (innobase_query_is_update()) {
/* The manual defines the REPLACE semantics
that it is either an INSERT or DELETE(s)
for duplicate key + INSERT. Therefore, we
should take X-lock for duplicates */
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
INSERT ON DUPLICATE KEY UPDATE). */
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,rec,cursor->index,
@ -1759,12 +1764,12 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
+ INSERT. Therefore, we should take X-lock for
duplicates. */
if (innobase_query_is_update()) {
if (innobase_query_is_replace()) {
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
INSERT ON DUPLICATE KEY UPDATE). */
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP, rec,

View file

@ -316,6 +316,51 @@ trx_savepoint_for_mysql(
return(DB_SUCCESS);
}
/***********************************************************************
Releases a named savepoint. Savepoints which
were set after this savepoint are deleted. */
ulint
trx_release_savepoint_for_mysql(
/*================================*/
/* out: if no savepoint
of the name found then
DB_NO_SAVEPOINT,
otherwise DB_SUCCESS */
trx_t* trx, /* in: transaction handle */
const char* savepoint_name) /* in: savepoint name */
{
trx_named_savept_t* savep;
savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
while (savep != NULL) {
if (0 == ut_strcmp(savep->name, savepoint_name)) {
/* Found */
break;
}
savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
}
if (savep == NULL) {
return(DB_NO_SAVEPOINT);
}
/* We can now free all savepoints strictly later than this one */
trx_roll_savepoints_free(trx, savep);
/* Now we can free this savepoint too */
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
mem_free(savep->name);
mem_free(savep);
return(DB_SUCCESS);
}
/***********************************************************************
Returns a transaction savepoint taken at this point in time. */

View file

@ -44,13 +44,13 @@ ut_get_high32(
/* out: a >> 32 */
ulint a) /* in: ulint */
{
#if SIZEOF_LONG == 4
UT_NOT_USED(a);
ib_longlong i;
return 0;
#else
return(a >> 32);
#endif
i = (ib_longlong)a;
i = i >> 32;
return((ulint)i);
}
/************************************************************

View file

@ -500,6 +500,7 @@ export MASTER_MYPORT MASTER_MYPORT1 SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MA
NDBCLUSTER_BASE_PORT=`expr $NDBCLUSTER_PORT + 2`
NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --port-base=$NDBCLUSTER_BASE_PORT --data-dir=$MYSQL_TEST_DIR/var --ndb_mgm-extra-opts=$NDB_MGM_EXTRA_OPTS --ndb_mgmd-extra-opts=$NDB_MGMD_EXTRA_OPTS --ndbd-extra-opts=$NDBD_EXTRA_OPTS"
NDB_BACKUP_DIR=$MYSQL_TEST_DIR/var/ndbcluster-$NDBCLUSTER_PORT
NDB_TOOLS_OUTPUT=$MYSQL_TEST_DIR/var/log/ndb_tools.log
if [ x$SOURCE_DIST = x1 ] ; then
MY_BASEDIR=$MYSQL_TEST_DIR
@ -700,6 +701,7 @@ export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR
export NDB_TOOLS_DIR
export NDB_MGM
export NDB_BACKUP_DIR
export NDB_TOOLS_OUTPUT
export PURIFYOPTIONS
MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \
@ -1071,6 +1073,7 @@ start_ndbcluster()
{
if [ ! -z "$USE_NDBCLUSTER" ]
then
rm -f $NDB_TOOLS_OUTPUT
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
echo "Starting ndbcluster"

View file

@ -39,3 +39,6 @@ DROP TABLE t1;
SELECT CHAR(31) = '', '' = CHAR(31);
CHAR(31) = '' '' = CHAR(31)
0 0
SELECT CHAR(30) = '', '' = CHAR(30);
CHAR(30) = '' '' = CHAR(30)
0 0

View file

@ -330,6 +330,15 @@ SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MA
min max avg
10.00 10.00 10
DROP TABLE t1;
create table t1 (a integer, b integer);
insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1);
select distinct sum(b) from t1 group by a;
sum(b)
4
select distinct sum(b) from (select a,b from t1) y group by a;
sum(b)
4
drop table t1;
CREATE TABLE t1 (a char(10), b char(10));
INSERT INTO t1 VALUES ('root','localhost'), ('root','%');
SELECT * FROM (SELECT (SELECT a.a FROM t1 AS a WHERE a.a = b.a) FROM t1 AS b) AS c;

View file

@ -328,6 +328,19 @@ trim(trailing 'foo' from 'foo')
select trim(leading 'foo' from 'foo');
trim(leading 'foo' from 'foo')
select quote(ltrim(concat(' ', 'a')));
quote(ltrim(concat(' ', 'a')))
'a'
select quote(trim(concat(' ', 'a')));
quote(trim(concat(' ', 'a')))
'a'
CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3;
SELECT QUOTE('A') FROM t1;
QUOTE('A')
'A'
'A'
'A'
DROP TABLE t1;
select 1=_latin1'1';
1=_latin1'1'
1
@ -694,12 +707,6 @@ select count(*) as total, left(c,10) as reg from t1 group by reg order by reg de
total reg
10 2004-12-10
drop table t1;
select quote(ltrim(concat(' ', 'a')));
quote(ltrim(concat(' ', 'a')))
'a'
select quote(trim(concat(' ', 'a')));
quote(trim(concat(' ', 'a')))
'a'
select trim(null from 'kate') as "must_be_null";
must_be_null
NULL
@ -712,3 +719,26 @@ NULL
select trim(trailing NULL from 'xyz') as "must_be_null";
must_be_null
NULL
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
a bigint(20) unsigned default NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;
INSERT INTO t1 VALUES
('0','16307858876001849059');
SELECT CONV('e251273eb74a8ee3', 16, 10);
CONV('e251273eb74a8ee3', 16, 10)
16307858876001849059
EXPLAIN
SELECT id
FROM t1
WHERE a = 16307858876001849059;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
EXPLAIN
SELECT id
FROM t1
WHERE a = CONV('e251273eb74a8ee3', 16, 10);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
DROP TABLE t1;

View file

@ -371,11 +371,11 @@ alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(20
update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7 = 1 or B.key8=1);
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7or16 = 1 or A.key8=1)
and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7or16 = 1 or B.key8=1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where
1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7,i8 i2,i3,i4,i5,i6,i8 4,4,4,4,4,4 NULL 16 Using union(intersect(i2,i3,i4,i5,i6),i8); Using where
1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where
1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where
select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)

View file

@ -249,6 +249,30 @@ n
4
5
6
set autocommit=0;
begin;
savepoint `my_savepoint`;
insert into t1 values (7);
savepoint `savept2`;
insert into t1 values (3);
select n from t1;
n
3
4
5
6
7
rollback to savepoint `savept2`;
release savepoint `my_savepoint`;
select n from t1;
n
4
5
6
7
rollback to savepoint `my_savepoint`;
ERROR HY000: Got error 153 during ROLLBACK
set autocommit=1;
rollback;
drop table t1;
create table t1 (n int not null primary key) engine=innodb;
@ -1609,14 +1633,14 @@ t2 CREATE TABLE `t2` (
drop table t2, t1;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 24
Binlog_cache_use 25
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 25
Binlog_cache_use 26
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@ -1625,7 +1649,7 @@ delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
Binlog_cache_use 26
Binlog_cache_use 27
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@ -1693,10 +1717,10 @@ Variable_name Value
Innodb_rows_deleted 2070
show status like "Innodb_rows_inserted";
Variable_name Value
Innodb_rows_inserted 31706
Innodb_rows_inserted 31708
show status like "Innodb_rows_read";
Variable_name Value
Innodb_rows_read 80153
Innodb_rows_read 80162
show status like "Innodb_rows_updated";
Variable_name Value
Innodb_rows_updated 29530

View file

@ -2168,3 +2168,51 @@ ERROR 42S22: Unknown column 'a2' in 'scalar IN/ALL/ANY subquery'
select * from t1 where a1 > any(select b1 from t2);
a1
drop table t1,t2;
create table t1 (a integer, b integer);
select (select * from t1) = (select 1,2);
(select * from t1) = (select 1,2)
NULL
select (select 1,2) = (select * from t1);
(select 1,2) = (select * from t1)
NULL
select row(1,2) = ANY (select * from t1);
row(1,2) = ANY (select * from t1)
0
select row(1,2) != ALL (select * from t1);
row(1,2) != ALL (select * from t1)
1
drop table t1;
create table t1 (a integer, b integer);
select row(1,(2,2)) in (select * from t1 );
ERROR 21000: Operand should contain 2 column(s)
select row(1,(2,2)) = (select * from t1 );
ERROR 21000: Operand should contain 2 column(s)
select (select * from t1) = row(1,(2,2));
ERROR 21000: Operand should contain 1 column(s)
drop table t1;
create table t1 (a integer);
insert into t1 values (1);
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx ;
ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
select 1 as xx, 1 = ALL ( select 1 from t1 where 1 = xx );
xx 1 = ALL ( select 1 from t1 where 1 = xx )
1 1
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL;
ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
drop table t1;
CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
CREATE TABLE t2 LIKE t1;
INSERT INTO t1 VALUES (1,1,1);
INSERT INTO t2 VALUES (1,1,1);
PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
EXECUTE my_stmt;
b count(*)
EXECUTE my_stmt;
b count(*)
deallocate prepare my_stmt;
drop table t1,t2;

View file

@ -33,3 +33,5 @@ DROP TABLE t1;
# Bug #8134: Comparison against CHAR(31) at end of string
SELECT CHAR(31) = '', '' = CHAR(31);
# Extra test
SELECT CHAR(30) = '', '' = CHAR(30);

View file

@ -214,6 +214,16 @@ insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10);
SELECT MIN(price) min, MAX(price) max, AVG(price) avg FROM (SELECT SUBSTRING( MAX(concat(date_,";",price)), 12) price FROM t1 WHERE itemid=128 AND grpid='rozn' GROUP BY itemid, grpid, vendor) lastprices;
DROP TABLE t1;
#
# DISTINCT over grouped select on subquery in the FROM clause
#
create table t1 (a integer, b integer);
insert into t1 values (1,4), (2,2),(2,2), (4,1),(4,1),(4,1),(4,1);
select distinct sum(b) from t1 group by a;
select distinct sum(b) from (select a,b from t1) y group by a;
drop table t1;
#
# Test for bug #7413 "Subquery with non-scalar results participating in
# select list of derived table crashes server" aka "VIEW with sub query can

View file

@ -196,6 +196,18 @@ select trim(trailing 'foo' from 'foo');
select trim(leading 'foo' from 'foo');
#
# crashing bug with QUOTE() and LTRIM() or TRIM() fixed
# Bug #7495
#
select quote(ltrim(concat(' ', 'a')));
select quote(trim(concat(' ', 'a')));
# Bad results from QUOTE(). Bug #8248
CREATE TABLE t1 SELECT 1 UNION SELECT 2 UNION SELECT 3;
SELECT QUOTE('A') FROM t1;
DROP TABLE t1;
# Test collation and coercibility
#
@ -430,12 +442,6 @@ create table t1 (a int not null primary key, b varchar(40), c datetime);
insert into t1 (a,b,c) values (1,'Tom','2004-12-10 12:13:14'),(2,'ball games','2004-12-10 12:13:14'), (3,'Basil','2004-12-10 12:13:14'), (4,'Dean','2004-12-10 12:13:14'),(5,'Ellis','2004-12-10 12:13:14'), (6,'Serg','2004-12-10 12:13:14'), (7,'Sergei','2004-12-10 12:13:14'),(8,'Georg','2004-12-10 12:13:14'),(9,'Salle','2004-12-10 12:13:14'),(10,'Sinisa','2004-12-10 12:13:14');
select count(*) as total, left(c,10) as reg from t1 group by reg order by reg desc limit 0,12;
drop table t1;
# crashing bug with QUOTE() and LTRIM() or TRIM() fixed
# Bug #7495
#
select quote(ltrim(concat(' ', 'a')));
select quote(trim(concat(' ', 'a')));
#
# Bug#7455 unexpected result: TRIM(<NULL> FROM <whatever>) gives NOT NULL
@ -446,3 +452,30 @@ select trim(null from 'kate') as "must_be_null";
select trim('xyz' from null) as "must_be_null";
select trim(leading NULL from 'kate') as "must_be_null";
select trim(trailing NULL from 'xyz') as "must_be_null";
#
# Bug #7751 - conversion for a bigint unsigned constant
#
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
a bigint(20) unsigned default NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM;
INSERT INTO t1 VALUES
('0','16307858876001849059');
SELECT CONV('e251273eb74a8ee3', 16, 10);
EXPLAIN
SELECT id
FROM t1
WHERE a = 16307858876001849059;
EXPLAIN
SELECT id
FROM t1
WHERE a = CONV('e251273eb74a8ee3', 16, 10);
DROP TABLE t1;

View file

@ -306,6 +306,11 @@ select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4
alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(200);
update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500;
# The next query will not use index i7 in intersection if the OS doesn't
# support file sizes > 2GB. (ha_myisam::ref_length depends on this and index
# scan cost estimates depend on ha_myisam::ref_length)
--replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?" 7 7or16 16 7or16
explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5)
from t0 as A, t0 as B
where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1)

View file

@ -129,6 +129,19 @@ insert into t1 values (6);
-- error 1062
insert into t1 values (4);
select n from t1;
set autocommit=0;
begin;
savepoint `my_savepoint`;
insert into t1 values (7);
savepoint `savept2`;
insert into t1 values (3);
select n from t1;
rollback to savepoint `savept2`;
release savepoint `my_savepoint`;
select n from t1;
-- error 1181
rollback to savepoint `my_savepoint`;
set autocommit=1;
# nop
rollback;
drop table t1;

View file

@ -199,7 +199,7 @@ insert into t4 values (1, "Automatic");
select * from t4;
# Remove the table from NDB
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ;
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 >> $NDB_TOOLS_OUTPUT ;
#
# Test that correct error is returned
@ -230,7 +230,7 @@ select * from t4;
flush tables;
# Remove the table from NDB
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ;
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 >> $NDB_TOOLS_OUTPUT ;
SHOW TABLES;
@ -264,8 +264,8 @@ insert into t8 values (8, "myisam table 8");
insert into t9 values (9);
# Remove t3, t5 from NDB
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ;
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ;
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 >> $NDB_TOOLS_OUTPUT ;
system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 >> $NDB_TOOLS_OUTPUT ;
# Remove t6, t7 from disk
system rm var/master-data/test/t6.frm > /dev/null ;
system rm var/master-data/test/t7.frm > /dev/null ;
@ -498,4 +498,4 @@ create table t10 (
insert into t10 values (1, 'kalle');
--exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` > /dev/null 2>&1 || true
--exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` >> $NDB_TOOLS_OUTPUT 2>&1 || true

View file

@ -142,10 +142,10 @@ create table t8_c engine=ndbcluster as select * from t8;
create table t9_c engine=ndbcluster as select * from t9;
--exec $NDB_MGM --no-defaults -e "start backup" > /dev/null
--exec $NDB_MGM --no-defaults -e "start backup" >> $NDB_TOOLS_OUTPUT
drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 > /tmp/ndb_restore.out
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 > /tmp/ndb_restore.out
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT
show tables;

View file

@ -1419,8 +1419,11 @@ SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000);
drop table t1,t2;
#
# Test for BUG#7885: Server crash when 'any' subselect compared to
# non-existant field.
#
create table t1 (a1 int);
create table t2 (b1 int);
--error 1054
@ -1428,3 +1431,56 @@ select * from t1 where a2 > any(select b1 from t2);
select * from t1 where a1 > any(select b1 from t2);
drop table t1,t2;
#
# Comparison subquery with * and row
#
create table t1 (a integer, b integer);
select (select * from t1) = (select 1,2);
select (select 1,2) = (select * from t1);
# queries whih can be converted to IN
select row(1,2) = ANY (select * from t1);
select row(1,2) != ALL (select * from t1);
drop table t1;
#
# Comparison subquery and row with nested rows
#
create table t1 (a integer, b integer);
-- error 1241
select row(1,(2,2)) in (select * from t1 );
-- error 1241
select row(1,(2,2)) = (select * from t1 );
-- error 1241
select (select * from t1) = row(1,(2,2));
drop table t1;
#
# Forward reference detection
#
create table t1 (a integer);
insert into t1 values (1);
-- error 1247
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx ;
-- error 1247
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
select 1 as xx, 1 = ALL ( select 1 from t1 where 1 = xx );
-- error 1247
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
-- error 1247
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL;
drop table t1;
#
# cleaning up of results of subselects (BUG#8125)
#
CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
CREATE TABLE t2 LIKE t1;
INSERT INTO t1 VALUES (1,1,1);
INSERT INTO t2 VALUES (1,1,1);
PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
EXECUTE my_stmt;
EXECUTE my_stmt;
deallocate prepare my_stmt;
drop table t1,t2;

View file

@ -43,7 +43,7 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
return 0;
if (skip_end_space && a_length != b_length)
{
int swap= 0;
int swap= 1;
/*
We are using space compression. We have to check if longer key
has next character < ' ', in which case it's less than the shorter
@ -57,12 +57,12 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
/* put shorter key in a */
a_length= b_length;
a= b;
swap= -1 ^ 1; /* swap sign of result */
swap= -1; /* swap sign of result */
}
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
return 0;
}

View file

@ -804,6 +804,8 @@ private:
void remove_list(NdbOperation*& head, NdbOperation*);
void define_scan_op(NdbIndexScanOperation*);
friend class HugoOperations;
};
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL

View file

@ -3201,7 +3201,7 @@ Backup::execSTART_BACKUP_REQ(Signal* signal)
return;
}//if
tabPtr.p->triggerAllocated[i] = true;
tabPtr.p->triggerAllocated[j] = true;
trigPtr.p->backupPtr = ptr.i;
trigPtr.p->tableId = tabPtr.p->tableId;
trigPtr.p->tab_ptr_i = tabPtr.i;

View file

@ -4385,7 +4385,8 @@ void Dbacc::commitOperation(Signal* signal)
Uint32 tmp2Olq;
if ((operationRecPtr.p->commitDeleteCheckFlag == ZFALSE) &&
(operationRecPtr.p->operation != ZSCAN_OP)) {
(operationRecPtr.p->operation != ZSCAN_OP) &&
(operationRecPtr.p->operation != ZREAD)) {
jam();
/* This method is used to check whether the end result of the transaction
will be to delete the tuple. In this case all operation will be marked

View file

@ -33,6 +33,8 @@ public:
int closeTransaction(Ndb*);
NdbTransaction* getTransaction();
void refresh();
void setTransactionId(Uint64);
int pkInsertRecord(Ndb*,
int recordNo,

View file

@ -191,7 +191,7 @@ public:
NDBT_TestCase(NDBT_TestSuite* psuite,
const char* name,
const char* comment);
virtual ~NDBT_TestCase(){}
virtual ~NDBT_TestCase() {}
// This is the default executor of a test case
// When a test case is executed it will need to be suplied with a number of
@ -228,6 +228,8 @@ protected:
void stopTimer(NDBT_Context*);
void printTimer(NDBT_Context*);
BaseString _name;
BaseString _comment;
const char* name;
const char* comment;
NDBT_TestSuite* suite;

View file

@ -98,6 +98,15 @@ OperationTestCase matrix[] = {
result = NDBT_FAILED; \
break; }
#define C3(b) if (!(b)) { \
g_err << "ERR: "<< step->getName() \
<< " failed on line " << __LINE__ << endl; \
abort(); return NDBT_FAILED; }
#define C3(b) if (!(b)) { \
g_err << "ERR: failed on line " << __LINE__ << endl; \
return NDBT_FAILED; }
int
runOp(HugoOperations & hugoOps,
Ndb * pNdb,
@ -228,11 +237,369 @@ runClearTable(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
enum OPS { o_DONE= 0, o_INS= 1, o_UPD= 2, o_DEL= 3 };
typedef Vector<OPS> Sequence;
static
bool
valid(const Sequence& s)
{
if(s.size() == 0)
return false;
for(size_t i = 1; i<s.size(); i++)
{
switch(s[i]){
case o_INS:
if(s[i-1] != o_DEL)
return false;
break;
case o_UPD:
case o_DEL:
if(s[i-1] == o_DEL)
return false;
break;
case o_DONE:
return true;
}
}
return true;
}
static
NdbOut& operator<<(NdbOut& out, const Sequence& s)
{
out << "[ ";
for(size_t i = 0; i<s.size(); i++)
{
switch(s[i]){
case o_INS:
out << "INS ";
break;
case o_DEL:
out << "DEL ";
break;
case o_UPD:
out << "UPD ";
break;
case o_DONE:
abort();
}
}
out << "]";
return out;
}
static
void
generate(Sequence& out, int no)
{
while(no & 3)
{
out.push_back((OPS)(no & 3));
no >>= 2;
}
}
static
void
generate(Vector<int>& out, size_t len)
{
int max= 1;
while(len)
{
max <<= 2;
len--;
}
len= 1;
for(int i = 0; i<max; i++)
{
Sequence tmp;
generate(tmp, i);
if(tmp.size() >= len && valid(tmp))
{
out.push_back(i);
len= tmp.size();
}
else
{
//ndbout << "DISCARD: " << tmp << endl;
}
}
}
static const Uint32 DUMMY = 0;
static const Uint32 ROW = 1;
int
verify_other(NDBT_Context* ctx,
Ndb* pNdb, int seq, OPS latest, bool initial_row, bool commit)
{
Uint32 no_wait = NdbOperation::LM_CommittedRead*
ctx->getProperty("NoWait", (Uint32)1);
for(size_t j = no_wait; j<3; j++)
{
HugoOperations other(*ctx->getTab());
C3(other.startTransaction(pNdb) == 0);
C3(other.pkReadRecord(pNdb, ROW, 1, (NdbOperation::LockMode)j) == 0);
int tmp= other.execute_Commit(pNdb);
if(seq == 0){
if(j == NdbOperation::LM_CommittedRead)
{
C3(initial_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626);
}
else
{
C3(tmp == 266);
}
}
else if(commit)
{
switch(latest){
case o_INS:
case o_UPD:
C3(tmp == 0 && other.verifyUpdatesValue(seq) == 0);
break;
case o_DEL:
C3(tmp == 626);
break;
case o_DONE:
abort();
}
}
else
{
// rollback
C3(initial_row? tmp==0 && other.verifyUpdatesValue(0) == 0 : tmp==626);
}
}
return NDBT_OK;
}
int
verify_savepoint(NDBT_Context* ctx,
Ndb* pNdb, int seq, OPS latest,
Uint64 transactionId)
{
bool initial_row= (seq == 0) && latest == o_INS;
for(size_t j = 0; j<3; j++)
{
const NdbOperation::LockMode lm= (NdbOperation::LockMode)j;
HugoOperations same(*ctx->getTab());
C3(same.startTransaction(pNdb) == 0);
same.setTransactionId(transactionId); // Cheat
/**
* Increase savepoint to <em>k</em>
*/
for(size_t l = 1; l<=seq; l++)
{
C3(same.pkReadRecord(pNdb, DUMMY, 1, lm) == 0); // Read dummy row
C3(same.execute_NoCommit(pNdb) == 0);
g_info << "savepoint: " << l << endl;
}
g_info << "op(" << seq << "): "
<< " lock mode " << lm << endl;
C3(same.pkReadRecord(pNdb, ROW, 1, lm) == 0); // Read real row
int tmp= same.execute_Commit(pNdb);
if(seq == 0)
{
if(initial_row)
{
C3(tmp == 0 && same.verifyUpdatesValue(0) == 0);
} else
{
C3(tmp == 626);
}
}
else
{
switch(latest){
case o_INS:
case o_UPD:
C3(tmp == 0 && same.verifyUpdatesValue(seq) == 0);
break;
case o_DEL:
C3(tmp == 626);
break;
case o_DONE:
abort();
}
}
}
return NDBT_OK;
}
int
runOperations(NDBT_Context* ctx, NDBT_Step* step)
{
int tmp;
Ndb* pNdb = GETNDB(step);
Uint32 seqNo = ctx->getProperty("Sequence", (Uint32)0);
Uint32 commit= ctx->getProperty("Commit", (Uint32)1);
if(seqNo == 0)
{
return NDBT_FAILED;
}
Sequence seq;
generate(seq, seqNo);
{
// Dummy row
HugoOperations hugoOps(*ctx->getTab());
C3(hugoOps.startTransaction(pNdb) == 0);
C3(hugoOps.pkInsertRecord(pNdb, DUMMY, 1, 0) == 0);
C3(hugoOps.execute_Commit(pNdb) == 0);
}
const bool initial_row= (seq[0] != o_INS);
if(initial_row)
{
HugoOperations hugoOps(*ctx->getTab());
C3(hugoOps.startTransaction(pNdb) == 0);
C3(hugoOps.pkInsertRecord(pNdb, ROW, 1, 0) == 0);
C3(hugoOps.execute_Commit(pNdb) == 0);
}
HugoOperations trans1(*ctx->getTab());
C3(trans1.startTransaction(pNdb) == 0);
for(size_t i = 0; i<seq.size(); i++)
{
/**
* Perform operation
*/
switch(seq[i]){
case o_INS:
C3(trans1.pkInsertRecord(pNdb, ROW, 1, i+1) == 0);
break;
case o_UPD:
C3(trans1.pkUpdateRecord(pNdb, ROW, 1, i+1) == 0);
break;
case o_DEL:
C3(trans1.pkDeleteRecord(pNdb, ROW, 1) == 0);
break;
case o_DONE:
abort();
}
C3(trans1.execute_NoCommit(pNdb) == 0);
/**
* Verify other transaction
*/
if(verify_other(ctx, pNdb, 0, seq[0], initial_row, commit) != NDBT_OK)
return NDBT_FAILED;
/**
* Verify savepoint read
*/
Uint64 transactionId= trans1.getTransaction()->getTransactionId();
for(size_t k=0; k<=i+1; k++)
{
if(verify_savepoint(ctx, pNdb, k,
k>0 ? seq[k-1] : initial_row ? o_INS : o_DONE,
transactionId) != NDBT_OK)
return NDBT_FAILED;
}
}
if(commit)
{
C3(trans1.execute_Commit(pNdb) == 0);
}
else
{
C3(trans1.execute_Rollback(pNdb) == 0);
}
if(verify_other(ctx, pNdb, seq.size(), seq.back(),
initial_row, commit) != NDBT_OK)
return NDBT_FAILED;
return NDBT_OK;
}
int
main(int argc, const char** argv){
ndb_init();
Vector<int> tmp;
generate(tmp, 5);
NDBT_TestSuite ts("testOperations");
for(size_t i = 0; i<tmp.size(); i++)
{
BaseString name;
Sequence s;
generate(s, tmp[i]);
for(size_t j = 0; j<s.size(); j++){
switch(s[j]){
case o_INS:
name.append("_INS");
break;
case o_DEL:
name.append("_DEL");
break;
case o_UPD:
name.append("_UPD");
break;
case o_DONE:
abort();
}
}
BaseString n1;
n1.append(name);
n1.append("_COMMIT");
NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts,
n1.c_str()+1, "");
pt->setProperty("Sequence", tmp[i]);
pt->addInitializer(new NDBT_Initializer(pt,
"runClearTable",
runClearTable));
pt->addStep(new NDBT_ParallelStep(pt,
"run",
runOperations));
pt->addFinalizer(new NDBT_Finalizer(pt,
"runClearTable",
runClearTable));
ts.addTest(pt);
name.append("_ABORT");
pt = new NDBT_TestCaseImpl1(&ts, name.c_str()+1, "");
pt->setProperty("Sequence", tmp[i]);
pt->setProperty("Commit", (Uint32)0);
pt->addInitializer(new NDBT_Initializer(pt,
"runClearTable",
runClearTable));
pt->addStep(new NDBT_ParallelStep(pt,
"run",
runOperations));
pt->addFinalizer(new NDBT_Finalizer(pt,
"runClearTable",
runClearTable));
ts.addTest(pt);
}
for(Uint32 i = 0; i<sizeof(matrix)/sizeof(matrix[0]); i++){
NDBT_TestCaseImpl1 *pt = new NDBT_TestCaseImpl1(&ts, matrix[i].name, "");
@ -270,3 +637,5 @@ main(int argc, const char** argv){
return ts.execute(argc, argv);
}
template class Vector<OPS>;
template class Vector<Sequence>;

View file

@ -45,6 +45,13 @@ int HugoOperations::setTransaction(NdbTransaction* new_trans){
return NDBT_OK;
}
void
HugoOperations::setTransactionId(Uint64 id){
if (pTrans != NULL){
pTrans->setTransactionId(id);
}
}
int HugoOperations::closeTransaction(Ndb* pNdb){
if (pTrans != NULL){
@ -369,6 +376,10 @@ HugoOperations::HugoOperations(const NdbDictionary::Table& _tab,
HugoOperations::~HugoOperations(){
deallocRows();
if (pTrans != NULL){
pTrans->close();
pTrans = NULL;
}
}

View file

@ -68,20 +68,20 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
pOp = getScanOperation(pTrans);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
if( pOp ->readTuples(lm, 0, parallelism) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->interpret_exit_ok();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -89,7 +89,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -99,13 +99,13 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
const NdbError err = pTrans->getNdbError();
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -124,7 +124,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
while((eof = pOp->nextResult(true)) == 0){
rows++;
if (calc.verifyRowValues(&row) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -134,11 +134,11 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
pOp->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_OK;
}
}
@ -147,7 +147,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR_INFO(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
switch (err.code){
case 488:
@ -161,17 +161,17 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
g_info << rows << " rows have been read" << endl;
if (records != 0 && rows != records){
g_err << "Check expected number of records failed" << endl
<< " expected=" << records <<", " << endl
<< " read=" << rows << endl;
<< " expected=" << records <<", " << endl
<< " read=" << rows << endl;
return NDBT_FAILED;
}
@ -241,7 +241,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -251,13 +251,13 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
const NdbError err = pTrans->getNdbError();
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -276,7 +276,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
while((eof = pOp->nextResult(true)) == 0){
rows++;
if (calc.verifyRowValues(&row) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -286,11 +286,11 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
pOp->close();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_OK;
}
}
@ -299,7 +299,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR_INFO(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
switch (err.code){
case 488:
@ -313,17 +313,17 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
g_info << rows << " rows have been read" << endl;
if (records != 0 && rows != records){
g_err << "Check expected number of records failed" << endl
<< " expected=" << records <<", " << endl
<< " read=" << rows << endl;
<< " expected=" << records <<", " << endl
<< " read=" << rows << endl;
return NDBT_FAILED;
}
@ -337,9 +337,9 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
int
HugoTransactions::scanUpdateRecords(Ndb* pNdb,
int records,
int abortPercent,
int parallelism){
int records,
int abortPercent,
int parallelism){
if(m_defaultScanUpdateMethod == 1){
return scanUpdateRecords1(pNdb, records, abortPercent, parallelism);
} else if(m_defaultScanUpdateMethod == 2){
@ -383,7 +383,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
while (true){
restart:
restart:
if (retryAttempt++ >= retryMax){
g_info << "ERROR: has retried this operation " << retryAttempt
<< " times, failing!" << endl;
@ -404,13 +404,13 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
pOp = getScanOperation(pTrans);
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
if( pOp->readTuplesExclusive(parallelism) ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -418,7 +418,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
for(a=0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) = pOp->getValue(tab.getColumn(a)->getName())) == NULL){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -427,7 +427,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
if (err.status == NdbError::TemporaryError){
NdbSleep_MilliSleep(50);
continue;
@ -452,7 +452,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
NdbOperation* pUp = pOp->updateCurrentTuple();
if(pUp == 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
const int updates = calc.getUpdatesValue(&row) + 1;
@ -461,7 +461,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pUp, a, r, updates ) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -470,7 +470,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
if (rows == abortCount && abortTrans == true){
g_info << "Scan is aborted" << endl;
// This scan should be aborted
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_OK;
}
} while((check = pOp->nextResult(false)) == 0);
@ -482,7 +482,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
const NdbError err = pTrans->getNdbError();
if( check == -1 ) {
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
ERR(err);
if (err.status == NdbError::TemporaryError){
NdbSleep_MilliSleep(50);
@ -494,7 +494,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
const NdbError err = pTrans->getNdbError();
if( check == -1 ) {
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
ERR(err);
if (err.status == NdbError::TemporaryError){
NdbSleep_MilliSleep(50);
@ -503,7 +503,7 @@ HugoTransactions::scanUpdateRecords3(Ndb* pNdb,
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
g_info << rows << " rows have been updated" << endl;
return NDBT_OK;
@ -575,7 +575,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
if(pkInsertRecord(pNdb, c, batch) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -591,7 +591,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
}
if(check == -1 ) {
const NdbError err = pTrans->getNdbError();
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
pTrans= 0;
switch(err.status){
case NdbError::Success:
@ -633,7 +633,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
}
else{
if (closeTrans) {
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
pTrans= 0;
}
}
@ -644,7 +644,7 @@ HugoTransactions::loadTable(Ndb* pNdb,
}
if(pTrans)
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_OK;
}
@ -696,7 +696,7 @@ HugoTransactions::fillTable(Ndb* pNdb,
if(pkInsertRecord(pNdb, c, batch) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -704,7 +704,7 @@ HugoTransactions::fillTable(Ndb* pNdb,
check = pTrans->execute( Commit, CommitAsMuchAsPossible );
if(check == -1 ) {
const NdbError err = pTrans->getNdbError();
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
switch(err.status){
case NdbError::Success:
@ -756,7 +756,7 @@ HugoTransactions::fillTable(Ndb* pNdb,
}
}
else{
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
}
// Step to next record
@ -1088,7 +1088,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
if(pkReadRecord(pNdb, r, batch, lm) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1098,7 +1098,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
@ -1111,7 +1111,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
default:
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
} else {
@ -1122,13 +1122,13 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
{
rows_found++;
if (calc.verifyRowValues(rows[0]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
if(check != 1 || rows_found > batch)
{
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
else if(rows_found < batch)
@ -1146,7 +1146,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
{
for (int b=0; (b<batch) && (r+b<records); b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
reads++;
@ -1155,7 +1155,7 @@ HugoTransactions::pkReadRecords(Ndb* pNdb,
}
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
}
deallocRows();
g_info << reads << " records read" << endl;
@ -1209,7 +1209,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
if(pkReadRecord(pNdb, r, batch, NdbOperation::LM_Exclusive) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1219,13 +1219,13 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1237,7 +1237,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
do {
if (calc.verifyRowValues(rows[0]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1246,7 +1246,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
if(pkUpdateRecord(pNdb, r+rows_found, 1, updates) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
rows_found++;
@ -1259,7 +1259,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
}
if(check != 1 || rows_found != batch)
{
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1269,7 +1269,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
{
if (calc.verifyRowValues(rows[b]) != 0)
{
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1278,7 +1278,7 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
if(pkUpdateRecord(pNdb, r+b, 1, updates) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1289,21 +1289,21 @@ HugoTransactions::pkUpdateRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
ndbout << "r = " << r << endl;
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
else{
updated += batch;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
r += batch; // Read next record
}
@ -1348,15 +1348,15 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
NdbOperation* pOp = pTrans->getNdbOperation(tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->readTupleExclusive();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
closeTransaction(pNdb);
return NDBT_FAILED;
}
// Define primary keys
@ -1364,7 +1364,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1376,7 +1376,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
if((row.attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1388,13 +1388,13 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1404,14 +1404,14 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
pUpdOp = pTrans->getNdbOperation(tab.getName());
if (pUpdOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pUpdOp->interpretedUpdateTuple();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1420,7 +1420,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pUpdOp, a, r) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1437,7 +1437,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
check = pUpdOp->incValue(attr->getName(), valToIncWith);
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1449,7 +1449,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
(calc.isUpdateCol(a) == false)){
if(setValueForAttr(pUpdOp, a, r, updates ) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1463,14 +1463,14 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
ndbout << "r = " << r << endl;
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
else{
@ -1478,7 +1478,7 @@ HugoTransactions::pkInterpretedUpdateRecords(Ndb* pNdb,
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
r++; // Read next record
@ -1533,7 +1533,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
if(pkDeleteRecord(pNdb, r, batch) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1544,7 +1544,7 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
switch(err.status){
case NdbError::TemporaryError:
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
@ -1563,20 +1563,20 @@ HugoTransactions::pkDelRecords(Ndb* pNdb,
}
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
break;
default:
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
else {
deleted += batch;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
r += batch; // Read next record
@ -1641,7 +1641,7 @@ HugoTransactions::lockRecords(Ndb* pNdb,
if(pkReadRecord(pNdb, r, lockBatch, lm) != NDBT_OK)
{
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1656,18 +1656,18 @@ HugoTransactions::lockRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
for (int b=0; (b<lockBatch) && (r+b<records); b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1682,26 +1682,26 @@ HugoTransactions::lockRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
}
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
else{
for (int b=0; (b<lockBatch) && (r<records); b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
r++; // Read next record
}
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
}
deallocRows();
@ -1765,7 +1765,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->readTuple();
@ -1773,7 +1773,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName());
if (sOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
check = sOp->readTuples();
@ -1781,7 +1781,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1790,7 +1790,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1801,7 +1801,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1814,7 +1814,7 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
if (err.status == NdbError::TemporaryError){
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
NdbSleep_MilliSleep(50);
retryAttempt++;
continue;
@ -1827,13 +1827,13 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
default:
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
} else{
for (int b=0; (b<batch) && (r+b<records); b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
reads++;
@ -1842,11 +1842,11 @@ HugoTransactions::indexReadRecords(Ndb* pNdb,
if(ordered && sOp->nextResult(true) == 0){
ndbout << "Error when comparing records "
<< " - index op next_result to many" << endl;
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
}
deallocRows();
g_info << reads << " records read" << endl;
@ -1905,21 +1905,21 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
pOp = pTrans->getNdbIndexOperation(idxName, tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
check = pOp->readTupleExclusive();
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
} else {
pOp = sOp = pTrans->getNdbIndexScanOperation(idxName, tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1932,7 +1932,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1943,7 +1943,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if((rows[b]->attributeStore(a) =
pOp->getValue(tab.getColumn(a)->getName())) == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -1954,7 +1954,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
if (err.status == NdbError::TemporaryError){
NdbSleep_MilliSleep(50);
@ -1966,13 +1966,13 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if(ordered && check != 0){
g_err << check << " - Row: " << r << " not found!!" << endl;
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
for(b = 0; b<batch && (b+r)<records; b++){
if (calc.verifyRowValues(rows[b]) != 0){
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -1988,13 +1988,13 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if (pUpdOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
if( check == -1 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
@ -2003,7 +2003,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == true){
if(equalForAttr(pUpdOp, a, r+b) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -2014,7 +2014,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if (tab.getColumn(a)->getPrimaryKey() == false){
if(setValueForAttr(pUpdOp, a, r+b, updates ) != 0){
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
return NDBT_FAILED;
}
}
@ -2025,7 +2025,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
if( check == -1 ) {
const NdbError err = pTrans->getNdbError();
ERR(err);
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
if (err.status == NdbError::TemporaryError){
NdbSleep_MilliSleep(50);
@ -2038,7 +2038,7 @@ HugoTransactions::indexUpdateRecords(Ndb* pNdb,
updated += batch;
}
pNdb->closeTransaction(pTrans);
closeTransaction(pNdb);
r+= batch; // Read next record
}

View file

@ -330,13 +330,17 @@ NDBT_Finalizer::NDBT_Finalizer(NDBT_TestCase* ptest,
NDBT_TestCase::NDBT_TestCase(NDBT_TestSuite* psuite,
const char* pname,
const char* pcomment) :
name(pname) ,
comment(pcomment),
suite(psuite){
name(strdup(pname)) ,
comment(strdup(pcomment)),
suite(psuite)
{
_name.assign(pname);
_comment.assign(pcomment);
name= _name.c_str();
comment= _comment.c_str();
assert(suite != NULL);
}
NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite,
const char* pname,
const char* pcomment) :

View file

@ -106,8 +106,11 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
client/mysql$BS client/mysqlshow$BS client/mysqladmin$BS \
client/mysqldump$BS client/mysqlimport$BS \
client/mysqltest$BS client/mysqlcheck$BS \
client/mysqlbinlog$BS \
";
client/mysqlbinlog$BS \
tests/mysql_client_test$BS \
libmysqld/examples/mysql_client_test_embedded$BS \
libmysqld/examples/mysqltest_embedded$BS \
";
# Platform-specific bin files:
if [ $BASE_SYSTEM = "netware" ] ; then
@ -126,8 +129,9 @@ else
client/.libs/mysqltest client/.libs/mysqlcheck \
client/.libs/mysqlbinlog client/.libs/mysqlmanagerc \
client/.libs/mysqlmanager-pwgen tools/.libs/mysqlmanager \
tests/.libs/mysql_client_test libmysqld/examples/mysql_client_test_embedded \
libmysqld/examples/mysqltest_embedded \
tests/.libs/mysql_client_test \
libmysqld/examples/.libs/mysql_client_test_embedded \
libmysqld/examples/.libs/mysqltest_embedded \
";
fi

View file

@ -43,18 +43,20 @@
handle bulk inserts as well (that is if someone was trying to read at
the same time since we would want to flush).
A "meta" file is kept. All this file does is contain information on
the number of rows.
A "meta" file is kept alongside the data file. This file serves two purpose.
The first purpose is to track the number of rows in the table. The second
purpose is to determine if the table was closed properly or not. When the
meta file is first opened it is marked as dirty. It is opened when the table
itself is opened for writing. When the table is closed the new count for rows
is written to the meta file and the file is marked as clean. If the meta file
is opened and it is marked as dirty, it is assumed that a crash occured. At
this point an error occurs and the user is told to rebuild the file.
A rebuild scans the rows and rewrites the meta file. If corruption is found
in the data file then the meta file is not repaired.
No attempts at durability are made. You can corrupt your data. A repair
method was added to repair the meta file that stores row information,
but if your data file gets corrupted I haven't solved that. I could
create a repair that would solve this, but do you want to take a
chance of loosing your data?
At some point a recovery method for such a drastic case needs to be divised.
Locks are row level, and you will get a consistant read. Transactions
will be added later (they are not that hard to add at this
stage).
Locks are row level, and you will get a consistant read.
For performance as far as table scans go it is quite fast. I don't have
good numbers but locally it has out performed both Innodb and MyISAM. For
@ -89,7 +91,6 @@
compression but may speed up ordered searches).
Checkpoint the meta file to allow for faster rebuilds.
Dirty open (right now the meta file is repaired if a crash occured).
Transactions.
Option to allow for dirty reads, this would lower the sync calls, which would make
inserts a lot faster, but would mean highly arbitrary reads.
@ -347,6 +348,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
share->crashed= TRUE;
else
(void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
/*
It is expensive to open and close the data files and since you can't have
a gzip file that can be both read and written we keep a writer open
@ -393,7 +395,8 @@ int ha_archive::free_share(ARCHIVE_SHARE *share)
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
if (gzclose(share->archive_write) == Z_ERRNO)
rc= 1;
my_close(share->meta_file,MYF(0));
if (my_close(share->meta_file, MYF(0)))
rc= 1;
my_free((gptr) share, MYF(0));
}
pthread_mutex_unlock(&archive_mutex);

View file

@ -586,16 +586,13 @@ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row)
DBUG_RETURN(0);
}
bool ha_federated::create_where_from_key(
String *to,
KEY *key_info,
const byte *key,
uint key_length
)
bool ha_federated::create_where_from_key(String *to, KEY *key_info,
const byte *key, uint key_length)
{
uint second_loop= 0;
KEY_PART_INFO *key_part;
bool needs_quotes;
String tmp;
DBUG_ENTER("ha_federated::create_where_from_key");
for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++)
@ -656,7 +653,9 @@ bool ha_federated::create_where_from_key(
uint blob_length= uint2korr(key);
key+= HA_KEY_BLOB_LENGTH;
key_length-= HA_KEY_BLOB_LENGTH;
if (append_escaped(to, (char *)(key), blob_length))
tmp.set_quick((char*) key, blob_length, &my_charset_bin);
if (append_escaped(to, &tmp))
DBUG_RETURN(1);
DBUG_PRINT("ha_federated::create_where_from_key", ("blob type %s", to->c_ptr_quick()));
@ -666,7 +665,8 @@ bool ha_federated::create_where_from_key(
{
length= uint2korr(key);
key+= HA_KEY_BLOB_LENGTH;
if (append_escaped(to, (char *)(key), length))
tmp.set_quick((char*) key, length, &my_charset_bin);
if (append_escaped(to, &tmp))
DBUG_RETURN(1);
DBUG_PRINT("ha_federated::create_where_from_key", ("varchar type %s", to->c_ptr_quick()));
@ -680,7 +680,7 @@ bool ha_federated::create_where_from_key(
res= field->val_str(&str, (char *)(key));
if (field->result_type() == STRING_RESULT)
{
if (append_escaped(to, (char *) res->ptr(), res->length()))
if (append_escaped(to, res))
DBUG_RETURN(1);
res= field->val_str(&str, (char *)(key));
@ -1235,7 +1235,7 @@ int ha_federated::update_row(
update_string.append(new_field_value);
new_field_value.length(0);
if (x+1 < table->s->fields)
if ((uint) x+1 < table->s->fields)
{
update_string.append(", ");
if (! has_a_primary_key)
@ -1311,7 +1311,7 @@ int ha_federated::delete_row(const byte * buf)
delete_string.append(data_string);
data_string.length(0);
if (x+1 < table->s->fields)
if ((uint) x+1 < table->s->fields)
delete_string.append(" AND ");
}

View file

@ -1612,6 +1612,31 @@ innobase_rollback_to_savepoint(
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
/*********************************************************************
Release transaction savepoint name. */
int
innobase_release_savepoint_name(
/*===========================*/
/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
no savepoint with the given name */
THD* thd, /* in: handle to the MySQL thread of the user
whose transaction should be rolled back */
char* savepoint_name) /* in: savepoint name */
{
ib_longlong mysql_binlog_cache_pos;
int error = 0;
trx_t* trx;
DBUG_ENTER("innobase_release_savepoint_name");
trx = check_trx_exists(thd);
error = trx_release_savepoint_for_mysql(trx, savepoint_name);
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
/*********************************************************************
Sets a transaction savepoint. */
@ -4846,12 +4871,12 @@ ha_innobase::update_table_comment(
dict_print_info_on_foreign_keys(FALSE, file,
prebuilt->trx, prebuilt->table);
flen = ftell(file);
if(length + flen + 3 > 64000) {
if (flen < 0) {
flen = 0;
} else if (length + flen + 3 > 64000) {
flen = 64000 - 3 - length;
}
ut_ad(flen > 0);
/* allocate buffer for the full string, and
read the contents of the temporary file */
@ -4915,12 +4940,12 @@ ha_innobase::get_foreign_key_create_info(void)
prebuilt->trx->op_info = (char*)"";
flen = ftell(file);
if(flen > 64000 - 1) {
if (flen < 0) {
flen = 0;
} else if(flen > 64000 - 1) {
flen = 64000 - 1;
}
ut_ad(flen >= 0);
/* allocate buffer for the string, and
read the contents of the temporary file */
@ -5521,12 +5546,12 @@ innodb_show_status(
srv_printf_innodb_monitor(srv_monitor_file);
flen = ftell(srv_monitor_file);
os_file_set_eof(srv_monitor_file);
if(flen > 64000 - 1) {
if (flen < 0) {
flen = 0;
} else if (flen > 64000 - 1) {
flen = 64000 - 1;
}
ut_ad(flen > 0);
/* allocate buffer for the string, and
read the contents of the temporary file */
@ -6117,13 +6142,19 @@ innobase_get_at_most_n_mbchars(
extern "C" {
/**********************************************************************
This function returns true if SQL-query in the current thread
This function returns true if
1) SQL-query in the current thread
is either REPLACE or LOAD DATA INFILE REPLACE.
2) SQL-query in the current thread
is INSERT ON DUPLICATE KEY UPDATE.
NOTE that /mysql/innobase/row/row0ins.c must contain the
prototype for this function ! */
ibool
innobase_query_is_replace(void)
innobase_query_is_update(void)
/*===========================*/
{
THD* thd;
@ -6135,9 +6166,14 @@ innobase_query_is_replace(void)
( thd->lex->sql_command == SQLCOM_LOAD &&
thd->lex->duplicates == DUP_REPLACE )) {
return true;
} else {
return false;
}
if ( thd->lex->sql_command == SQLCOM_INSERT &&
thd->lex->duplicates == DUP_UPDATE ) {
return true;
}
return false;
}
}

View file

@ -244,6 +244,9 @@ int innobase_savepoint(
THD* thd,
char* savepoint_name,
my_off_t binlog_cache_pos);
int innobase_release_savepoint_name(
THD* thd,
char* savepoint_name);
int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path);
bool innodb_show_status(THD* thd);

View file

@ -869,6 +869,35 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name)
DBUG_RETURN(error);
}
int ha_release_savepoint_name(THD *thd, char *savepoint_name)
{
my_off_t binlog_cache_pos=0;
bool operation_done=0;
int error=0;
DBUG_ENTER("ha_release_savepoint_name");
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
#ifdef HAVE_INNOBASE_DB
if ((error=innobase_release_savepoint_name(thd, savepoint_name)))
{
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), error);
error=1;
}
else if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
if (mysql_bin_log.write(&qinfo))
error= 1;
}
operation_done=1;
#endif
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
}
/*
Sets a transaction savepoint.

View file

@ -653,6 +653,7 @@ int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_to_savepoint(THD *thd, char *savepoint_name);
int ha_savepoint(THD *thd, char *savepoint_name);
int ha_release_savepoint_name(THD *thd, char *savepoint_name);
int ha_autocommit_or_rollback(THD *thd, int error);
void ha_set_spin_retries(uint retries);
bool ha_flush_logs(void);

View file

@ -1775,12 +1775,13 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
if (select_ref != not_found_item && !ambiguous_fields)
{
DBUG_ASSERT(*select_ref);
if (! (*select_ref)->fixed)
if (!select->ref_pointer_array[counter])
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0),
ref->name, "forward reference in item list");
return NULL;
}
DBUG_ASSERT((*select_ref)->fixed);
return (select->ref_pointer_array + counter);
}
if (group_by_ref)

View file

@ -215,7 +215,7 @@ class Item_bool_rowready_func2 :public Item_bool_func2
public:
Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
{
allowed_arg_cols= a->cols();
allowed_arg_cols= 0; // Fetch this value from first argument
}
Item *neg_transformer(THD *thd);
virtual Item *negated_item();
@ -427,7 +427,10 @@ class Item_func_interval :public Item_int_func
double *intervals;
public:
Item_func_interval(Item_row *a)
:Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); }
:Item_int_func(a),row(a),intervals(0)
{
allowed_arg_cols= 0; // Fetch this value from first argument
}
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
@ -780,7 +783,7 @@ class Item_func_in :public Item_int_func
Item_func_in(List<Item> &list)
:Item_int_func(list), array(0), in_item(0), have_null(0)
{
allowed_arg_cols= args[0]->cols();
allowed_arg_cols= 0; // Fetch this value from first argument
}
longlong val_int();
void fix_length_and_dec();

View file

@ -308,10 +308,23 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
We can't yet set item to *arg as fix_fields may change *arg
We shouldn't call fix_fields() twice, so check 'fixed' field first
*/
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
(*arg)->check_cols(allowed_arg_cols))
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
return TRUE; /* purecov: inspected */
item= *arg;
if (allowed_arg_cols)
{
if (item->check_cols(allowed_arg_cols))
return 1;
}
else
{
/* we have to fetch allowed_arg_cols from first argument */
DBUG_ASSERT(arg == args); // it is first argument
allowed_arg_cols= item->cols();
DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
}
if (item->maybe_null)
maybe_null=1;

View file

@ -32,6 +32,10 @@ class Item_func :public Item_result_field
{
protected:
Item **args, *tmp_arg[2];
/*
Allowed numbers of columns in result (usually 1, which means scalar value)
0 means get this number from first argument
*/
uint allowed_arg_cols;
public:
uint arg_count;

View file

@ -2189,6 +2189,7 @@ String *Item_func_conv::val_str(String *str)
return 0;
}
null_value=0;
unsigned_flag= !(from_base < 0);
if (from_base < 0)
dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err);
else
@ -2643,18 +2644,13 @@ String *Item_func_quote::val_str(String *str)
for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
new_length+= get_esc_bit(escmask, (uchar) *from);
/*
We have to use realloc() instead of alloc() as we want to keep the
old result in arg
*/
if (arg->realloc(new_length))
if (tmp_value.alloc(new_length))
goto null;
/*
As 'arg' and 'str' may be the same string, we must replace characters
from the end to the beginning
We replace characters from the end to the beginning
*/
to= (char*) arg->ptr() + new_length - 1;
to= (char*) tmp_value.ptr() + new_length - 1;
*to--= '\'';
for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
{
@ -2682,10 +2678,10 @@ String *Item_func_quote::val_str(String *str)
}
}
*to= '\'';
arg->length(new_length);
str->set_charset(collation.collation);
tmp_value.length(new_length);
tmp_value.set_charset(collation.collation);
null_value= 0;
return arg;
return &tmp_value;
null:
null_value= 1;

View file

@ -596,6 +596,7 @@ public:
class Item_func_quote :public Item_str_func
{
String tmp_value;
public:
Item_func_quote(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "quote"; }

View file

@ -995,6 +995,10 @@ Item_in_subselect::row_value_transformer(JOIN *join)
List_iterator_fast<Item> li(select_lex->item_list);
for (uint i= 0; i < n; i++)
{
DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed);
if (select_lex->ref_pointer_array[i]->
check_cols(left_expr->el(i)->cols()))
goto err;
Item *func= new Item_ref_null_helper(this,
select_lex->ref_pointer_array+i,
(char *) "<no matter>",
@ -1117,6 +1121,7 @@ void subselect_single_select_engine::cleanup()
DBUG_ENTER("subselect_single_select_engine::cleanup");
prepared= optimized= executed= 0;
join= 0;
result->cleanup();
DBUG_VOID_RETURN;
}
@ -1125,6 +1130,7 @@ void subselect_union_engine::cleanup()
{
DBUG_ENTER("subselect_union_engine::cleanup");
unit->reinit_exec_mechanism();
result->cleanup();
DBUG_VOID_RETURN;
}
@ -1132,6 +1138,10 @@ void subselect_union_engine::cleanup()
void subselect_uniquesubquery_engine::cleanup()
{
DBUG_ENTER("subselect_uniquesubquery_engine::cleanup");
/*
subselect_uniquesubquery_engine have not 'result' assigbed, so we do not
cleanup() it
*/
DBUG_VOID_RETURN;
}
@ -1415,13 +1425,15 @@ int subselect_indexsubquery_engine::exec()
uint subselect_single_select_engine::cols()
{
return select_lex->item_list.elements;
DBUG_ASSERT(select_lex->join); // should be called after fix_fields()
return select_lex->join->fields_list.elements;
}
uint subselect_union_engine::cols()
{
return unit->first_select()->item_list.elements;
DBUG_ASSERT(unit->is_prepared()); // should be called after fix_fields()
return unit->types.elements;
}

View file

@ -99,6 +99,7 @@ static SYMBOL symbols[] = {
{ "CASCADE", SYM(CASCADE)},
{ "CASCADED", SYM(CASCADED)},
{ "CASE", SYM(CASE_SYM)},
{ "CHAIN", SYM(CHAIN_SYM)},
{ "CHANGE", SYM(CHANGE)},
{ "CHANGED", SYM(CHANGED)},
{ "CHAR", SYM(CHAR_SYM)},
@ -385,6 +386,7 @@ static SYMBOL symbols[] = {
{ "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)},
{ "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)},
{ "RELAY_THREAD", SYM(RELAY_THREAD)},
{ "RELEASE", SYM(RELEASE_SYM)},
{ "RELOAD", SYM(RELOAD)},
{ "RENAME", SYM(RENAME)},
{ "REPAIR", SYM(REPAIR)},

View file

@ -715,7 +715,6 @@ bool mysql_do(THD *thd, List<Item> &values);
/* sql_analyse.h */
bool append_escaped(String *to_str, String *from_str);
bool append_escaped(String *to_str, char *from, uint from_len);
/* sql_show.cc */
bool mysqld_show_open_tables(THD *thd,const char *wild);

View file

@ -4176,7 +4176,7 @@ enum options_mysqld
OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION,
OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION,
OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
@ -4251,7 +4251,11 @@ enum options_mysqld
OPT_RANGE_ALLOC_BLOCK_SIZE,
OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
OPT_SYNC_FRM, OPT_SYNC_BINLOG, OPT_BDB_NOSYNC,
OPT_SYNC_FRM, OPT_SYNC_BINLOG,
OPT_SYNC_REPLICATION,
OPT_SYNC_REPLICATION_SLAVE_ID,
OPT_SYNC_REPLICATION_TIMEOUT,
OPT_BDB_NOSYNC,
OPT_ENABLE_SHARED_MEMORY,
OPT_SHARED_MEMORY_BASE_NAME,
OPT_OLD_PASSWORDS,
@ -4363,6 +4367,10 @@ Disable with --skip-bdb (will save memory).",
{"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.",
(gptr*) &default_collation_name, (gptr*) &default_collation_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"completion-type", OPT_COMPLETION_TYPE, "Default completion type.",
(gptr*) &global_system_variables.completion_type,
(gptr*) &max_system_variables.completion_type, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
{"concurrent-insert", OPT_CONCURRENT_INSERT,
"Use concurrent insert with MyISAM. Disable with --skip-concurrent-insert.",
(gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert,
@ -5443,6 +5451,23 @@ The minimum value for this variable is 4096.",
(gptr*) &sync_binlog_period,
(gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1,
0},
#ifdef DOES_NOTHING_YET
{"sync-replication", OPT_SYNC_REPLICATION,
"Enable synchronous replication",
(gptr*) &global_system_variables.sync_replication,
(gptr*) &global_system_variables.sync_replication,
0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
{"sync-replication-slave-id", OPT_SYNC_REPLICATION_SLAVE_ID,
"Synchronous replication is wished for this slave",
(gptr*) &global_system_variables.sync_replication_slave_id,
(gptr*) &global_system_variables.sync_replication_slave_id,
0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
{"sync-replication-timeout", OPT_SYNC_REPLICATION_TIMEOUT,
"Synchronous replication timeout",
(gptr*) &global_system_variables.sync_replication_timeout,
(gptr*) &global_system_variables.sync_replication_timeout,
0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0},
#endif
{"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default",
(gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
0, 0, 0, 0},

View file

@ -100,6 +100,8 @@ static int check_pseudo_thread_id(THD *thd, set_var *var);
static bool set_log_bin(THD *thd, set_var *var);
static void fix_low_priority_updates(THD *thd, enum_var_type type);
static void fix_tx_isolation(THD *thd, enum_var_type type);
static int check_completion_type(THD *thd, set_var *var);
static void fix_completion_type(THD *thd, enum_var_type type);
static void fix_net_read_timeout(THD *thd, enum_var_type type);
static void fix_net_write_timeout(THD *thd, enum_var_type type);
static void fix_net_retry_count(THD *thd, enum_var_type type);
@ -149,6 +151,10 @@ sys_var_character_set_database sys_character_set_database("character_set_databas
sys_var_character_set_client sys_character_set_client("character_set_client");
sys_var_character_set_connection sys_character_set_connection("character_set_connection");
sys_var_character_set_results sys_character_set_results("character_set_results");
sys_var_thd_ulong sys_completion_type("completion_type",
&SV::completion_type,
check_completion_type,
fix_completion_type);
sys_var_collation_connection sys_collation_connection("collation_connection");
sys_var_collation_database sys_collation_database("collation_database");
sys_var_collation_server sys_collation_server("collation_server");
@ -352,6 +358,14 @@ sys_var_thd_storage_engine sys_storage_engine("storage_engine",
&SV::table_type);
#ifdef HAVE_REPLICATION
sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period);
sys_var_thd_ulong sys_sync_replication("sync_replication",
&SV::sync_replication);
sys_var_thd_ulong sys_sync_replication_slave_id(
"sync_replication_slave_id",
&SV::sync_replication_slave_id);
sys_var_thd_ulong sys_sync_replication_timeout(
"sync_replication_timeout",
&SV::sync_replication_timeout);
#endif
sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm);
sys_var_long_ptr sys_table_cache_size("table_cache",
@ -532,6 +546,7 @@ sys_var *sys_variables[]=
&sys_collation_connection,
&sys_collation_database,
&sys_collation_server,
&sys_completion_type,
&sys_concurrent_insert,
&sys_connect_timeout,
&sys_date_format,
@ -640,6 +655,9 @@ sys_var *sys_variables[]=
&sys_storage_engine,
#ifdef HAVE_REPLICATION
&sys_sync_binlog_period,
&sys_sync_replication,
&sys_sync_replication_slave_id,
&sys_sync_replication_timeout,
#endif
&sys_sync_frm,
&sys_table_cache_size,
@ -708,6 +726,7 @@ struct show_var_st init_vars[]= {
{sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
{sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS},
{sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS},
{sys_completion_type.name, (char*) &sys_completion_type, SHOW_SYS},
{sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS},
{sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS},
{"datadir", mysql_real_data_home, SHOW_CHAR},
@ -907,6 +926,9 @@ struct show_var_st init_vars[]= {
{sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS},
#ifdef HAVE_REPLICATION
{sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period, SHOW_SYS},
{sys_sync_replication.name, (char*) &sys_sync_replication, SHOW_SYS},
{sys_sync_replication_slave_id.name, (char*) &sys_sync_replication_slave_id,SHOW_SYS},
{sys_sync_replication_timeout.name, (char*) &sys_sync_replication_timeout,SHOW_SYS},
#endif
{sys_sync_frm.name, (char*) &sys_sync_frm, SHOW_SYS},
#ifdef HAVE_TZNAME
@ -1122,6 +1144,21 @@ static void fix_tx_isolation(THD *thd, enum_var_type type)
thd->variables.tx_isolation);
}
static void fix_completion_type(THD *thd __attribute__(unused),
enum_var_type type __attribute__(unused)) {}
static int check_completion_type(THD *thd, set_var *var)
{
longlong val= var->value->val_int();
if (val < 0 || val > 2)
{
char buf[64];
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
return 1;
}
return 0;
}
/*
If we are changing the thread variable, we have to copy it to NET too

View file

@ -59,8 +59,6 @@ int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
return compare_ulonglong(s,t);
}
bool append_escaped(String *to_str, String *from_str);
bool append_escaped(String *to_str, char *from, uint from_len);
Procedure *
proc_analyse_init(THD *thd, ORDER *param, select_result *result,
@ -1087,38 +1085,3 @@ bool append_escaped(String *to_str, String *from_str)
}
return 0;
}
bool append_escaped(String *to_str, char *from, uint from_len)
{
char *end, c;
if (to_str->realloc(to_str->length() + from_len))
return 1;
end= from + from_len;
for (; from < end; from++)
{
c= *from;
switch (c) {
case '\0':
c= '0';
break;
case '\032':
c= 'Z';
break;
case '\\':
case '\'':
break;
default:
goto normal_character;
}
if (to_str->append('\\'))
return 1;
normal_character:
if (to_str->append(c))
return 1;
}
return 0;
}

View file

@ -2758,6 +2758,20 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
/*
To prevent fail on forward lookup we fill it with zerows,
then if we got pointer on zero after find_item_in_list we will know
that it is forward lookup.
There is other way to solve problem: fill array with pointers to list,
but it will be slower.
TODO: remove it when (if) we made one list for allfields and
ref_pointer_array
*/
if (ref_pointer_array)
bzero(ref_pointer_array, sizeof(Item *) * fields.elements);
Item **ref= ref_pointer_array;
while ((item= it++))
{

View file

@ -1303,6 +1303,14 @@ bool select_singlerow_subselect::send_data(List<Item> &items)
}
void select_max_min_finder_subselect::cleanup()
{
DBUG_ENTER("select_max_min_finder_subselect::cleanup");
cache= 0;
DBUG_VOID_RETURN;
}
bool select_max_min_finder_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_max_min_finder_subselect::send_data");

View file

@ -408,6 +408,7 @@ struct system_variables
ulong table_type;
ulong tmp_table_size;
ulong tx_isolation;
ulong completion_type;
/* Determines which non-standard SQL behaviour should be enabled */
ulong sql_mode;
/* check of key presence in updatable view */
@ -430,6 +431,11 @@ struct system_variables
my_bool low_priority_updates;
my_bool new_mode;
my_bool query_cache_wlock_invalidate;
#ifdef HAVE_REPLICATION
ulong sync_replication;
ulong sync_replication_slave_id;
ulong sync_replication_timeout;
#endif /* HAVE_REPLICATION */
#ifdef HAVE_INNOBASE_DB
my_bool innodb_table_locks;
#endif /* HAVE_INNOBASE_DB */
@ -1509,6 +1515,7 @@ public:
select_max_min_finder_subselect(Item_subselect *item, bool mx)
:select_subselect(item), cache(0), fmax(mx)
{}
void cleanup();
bool send_data(List<Item> &items);
bool cmp_real();
bool cmp_int();

View file

@ -1811,13 +1811,13 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
is the same table (Bug #6034). Do the preparation after the select phase
in select_insert::prepare2().
*/
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
table->file->start_bulk_insert((ha_rows) 0);
}
restore_record(table,s->default_values); // Get empty record
table->next_number_field=table->found_next_number_field;
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->no_trans_update= 0;
thd->abort_on_warning= (!info.ignore &&
(thd->variables.sql_mode &
@ -1847,14 +1847,9 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
int select_insert::prepare2(void)
{
DBUG_ENTER("select_insert::prepare2");
if (thd->lex->current_select->options & OPTION_BUFFER_RESULT)
{
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
table->file->start_bulk_insert((ha_rows) 0);
}
return 0;
DBUG_RETURN(0);
}

View file

@ -177,7 +177,10 @@ void lex_start(THD *thd, uchar *buf,uint length)
void lex_end(LEX *lex)
{
lex->select_lex.expr_list.delete_elements(); // If error when parsing sql-varargs
for (SELECT_LEX *sl= lex->all_selects_list;
sl;
sl= sl->next_select_in_list())
sl->expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs);
}

View file

@ -67,7 +67,7 @@ enum enum_sql_command {
SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
@ -416,6 +416,7 @@ public:
void print(String *str);
ulong init_prepare_fake_select_lex(THD *thd);
inline bool is_prepared() { return prepared; }
bool change_result(select_subselect *result, select_subselect *old_result);
void set_limit(st_select_lex *values, st_select_lex *sl);
@ -718,6 +719,7 @@ typedef struct st_lex
uint8 create_view_check;
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
bool in_comment, ignore_space, verbose, no_write_to_binlog;
bool tx_chain, tx_release;
/* special JOIN::prepare mode: changing of query is prohibited */
bool view_prepare_mode;
bool safe_to_cache_query;

View file

@ -134,6 +134,28 @@ static bool end_active_trans(THD *thd)
DBUG_RETURN(error);
}
static bool begin_trans(THD *thd)
{
int error=0;
if (thd->locked_tables)
{
thd->lock=thd->locked_tables;
thd->locked_tables=0; // Will be automatically closed
close_thread_tables(thd); // Free tables
}
if (end_active_trans(thd))
error= -1;
else
{
LEX *lex= thd->lex;
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
error= ha_start_consistent_snapshot(thd);
}
return error;
}
#ifdef HAVE_REPLICATION
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
@ -690,6 +712,8 @@ static int check_connection(THD *thd)
DBUG_PRINT("info",
("New connection received on %s", vio_description(net->vio)));
vio_in_addr(net->vio,&thd->remote.sin_addr);
if (!thd->host) // If TCP/IP connection
{
char ip[30];
@ -734,7 +758,6 @@ static int check_connection(THD *thd)
DBUG_PRINT("info",("Host: %s",thd->host));
thd->host_or_ip= thd->host;
thd->ip= 0;
bzero((char*) &thd->remote, sizeof(struct sockaddr));
}
vio_keepalive(net->vio, TRUE);
ulong pkt_len= 0;
@ -1262,6 +1285,127 @@ err:
DBUG_RETURN(error);
}
/*
Ends the current transaction and (maybe) begin the next
First uint4 in packet is completion type
Remainder is savepoint name (if required)
SYNOPSIS
mysql_endtrans()
thd Current thread
completion Completion type
savepoint_name Savepoint when doing ROLLBACK_SAVEPOINT_NAME
or RELEASE_SAVEPOINT_NAME
release (OUT) indicator for release operation
RETURN
0 - OK
*/
enum enum_mysql_completiontype {
ROLLBACK_RELEASE=-2,
COMMIT_RELEASE=-1,
COMMIT=0,
ROLLBACK=1,
SAVEPOINT_NAME_ROLLBACK=2,
SAVEPOINT_NAME_RELEASE=4,
COMMIT_AND_CHAIN=6,
ROLLBACK_AND_CHAIN=7,
};
int mysql_endtrans(THD *thd, enum enum_mysql_completiontype completion,
char *savepoint_name)
{
bool do_release= 0;
int res= 0;
LEX *lex= thd->lex;
DBUG_ENTER("mysql_endtrans");
switch (completion) {
case COMMIT:
/*
We don't use end_active_trans() here to ensure that this works
even if there is a problem with the OPTION_AUTO_COMMIT flag
(Which of course should never happen...)
*/
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!(res= ha_commit(thd)))
send_ok(thd);
break;
case COMMIT_RELEASE:
do_release= 1;
case COMMIT_AND_CHAIN:
res= end_active_trans(thd);
if (!res && completion == COMMIT_AND_CHAIN)
res= begin_trans(thd);
if (!res)
send_ok(thd);
break;
case ROLLBACK_RELEASE:
do_release= 1;
case ROLLBACK:
case ROLLBACK_AND_CHAIN:
{
bool warn= 0;
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_rollback(thd))
{
/*
If a non-transactional table was updated, warn; don't warn if this is a
slave thread (because when a slave thread executes a ROLLBACK, it has
been read from the binary log, so it's 100% sure and normal to produce
error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
slave SQL thread, it would not stop the thread but just be printed in
the error log; but we don't want users to wonder why they have this
message in the error log, so we don't send it.
*/
warn= (thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
!thd->slave_thread;
}
else
res= -1;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
if (!res && (completion == ROLLBACK_AND_CHAIN))
res= begin_trans(thd);
if (!res)
{
if (warn)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
send_ok(thd);
}
break;
}
case SAVEPOINT_NAME_ROLLBACK:
if (!(res=ha_rollback_to_savepoint(thd, savepoint_name)))
{
if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
send_ok(thd);
}
break;
case SAVEPOINT_NAME_RELEASE:
if (!(res=ha_release_savepoint_name(thd, savepoint_name)))
send_ok(thd);
break;
default:
res= -1;
my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
DBUG_RETURN(-1);
}
if (res < 0)
my_error(thd->killed_errno(), MYF(0));
else if ((res == 0) && do_release)
thd->killed= THD::KILL_CONNECTION;
DBUG_RETURN(res);
}
#ifndef EMBEDDED_LIBRARY
@ -3648,74 +3792,23 @@ unsent_create_error:
break;
case SQLCOM_BEGIN:
if (thd->locked_tables)
{
thd->lock=thd->locked_tables;
thd->locked_tables=0; // Will be automatically closed
close_thread_tables(thd); // Free tables
}
if (end_active_trans(thd))
if (begin_trans(thd))
goto error;
else
{
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
if (!(lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) ||
!(res= ha_start_consistent_snapshot(thd)))
send_ok(thd);
}
send_ok(thd);
break;
case SQLCOM_COMMIT:
/*
We don't use end_active_trans() here to ensure that this works
even if there is a problem with the OPTION_AUTO_COMMIT flag
(Which of course should never happen...)
*/
{
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_commit(thd))
{
send_ok(thd);
}
else
if (mysql_endtrans(thd, lex->tx_release ? COMMIT_RELEASE :
lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT, 0))
goto error;
break;
}
case SQLCOM_ROLLBACK:
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (!ha_rollback(thd))
{
/*
If a non-transactional table was updated, warn; don't warn if this is a
slave thread (because when a slave thread executes a ROLLBACK, it has
been read from the binary log, so it's 100% sure and normal to produce
error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
slave SQL thread, it would not stop the thread but just be printed in
the error log; but we don't want users to wonder why they have this
message in the error log, so we don't send it.
*/
if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
send_ok(thd);
}
else
res= TRUE;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
if (mysql_endtrans(thd, lex->tx_release ? ROLLBACK_RELEASE :
lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK, 0))
goto error;
break;
case SQLCOM_ROLLBACK_TO_SAVEPOINT:
if (!ha_rollback_to_savepoint(thd, lex->savepoint_name))
{
if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
send_ok(thd);
}
else
if (mysql_endtrans(thd, SAVEPOINT_NAME_ROLLBACK, lex->savepoint_name))
goto error;
break;
case SQLCOM_SAVEPOINT:
@ -3724,6 +3817,10 @@ unsent_create_error:
else
goto error;
break;
case SQLCOM_RELEASE_SAVEPOINT:
if (mysql_endtrans(thd, SAVEPOINT_NAME_RELEASE, lex->savepoint_name))
goto error;
break;
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
{

View file

@ -1435,7 +1435,7 @@ JOIN::exec()
curr_join->select_distinct=0; /* Each row is unique */
curr_join->join_free(0); /* Free quick selects */
if (select_distinct && ! group_list)
if (curr_join->select_distinct && ! curr_join->group_list)
{
thd->proc_info="Removing duplicates";
if (curr_join->tmp_having)

View file

@ -1786,7 +1786,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
enum enum_schema_tables schema_table_idx;
thr_lock_type lock_type;
List<char> bases;
List_iterator_fast<char> it(bases);
COND *partial_cond;
int error= 1;
DBUG_ENTER("get_all_tables");
LINT_INIT(end);
@ -1803,13 +1805,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (schema_table->process_table(thd, show_table_list,
table, res, show_table_list->db,
show_table_list->alias))
{
DBUG_RETURN(1);
}
goto err;
close_thread_tables(thd, 0, 0, old_open_tables);
show_table_list->table= 0;
lex->all_selects_list= select_lex;
DBUG_RETURN(0);
error= 0;
goto err;
}
lex->all_selects_list= &sel;
@ -1822,14 +1822,14 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
/* information schema name always is first in list */
if (schema_db_add(thd, &bases, idx_field_vals.db_value, &with_i_schema))
return 1;
goto err;
if (mysql_find_files(thd, &bases, NullS, mysql_data_home,
idx_field_vals.db_value, 1))
return 1;
goto err;
List_iterator_fast<char> it(bases);
partial_cond= make_cond_for_info_schema(cond, tables);
it.rewind(); /* To get access to new elements in basis list */
while ((base_name= it++) ||
/*
generate error for non existing database.
@ -1851,7 +1851,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (with_i_schema) // information schema table names
{
if (schema_tables_add(thd, &files, idx_field_vals.table_value))
DBUG_RETURN(1);
goto err;
}
else
{
@ -1860,7 +1860,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
len= FN_LEN - len;
if (mysql_find_files(thd, &files, base_name,
path, idx_field_vals.table_value, 0))
DBUG_RETURN(1);
goto err;
}
List_iterator_fast<char> it_files(files);
@ -1906,16 +1906,14 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
int res;
TABLE *old_open_tables= thd->open_tables;
if (make_table_list(thd, &sel, base_name, file_name))
DBUG_RETURN(1);
goto err;
TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
show_table_list->lock_type= lock_type;
res= open_and_lock_tables(thd, show_table_list);
if (schema_table->process_table(thd, show_table_list, table,
res, base_name,
show_table_list->alias))
{
DBUG_RETURN(1);
}
goto err;
close_thread_tables(thd, 0, 0, old_open_tables);
}
}
@ -1927,8 +1925,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
with_i_schema= 0;
}
}
error= 0;
err:
lex->all_selects_list= select_lex;
DBUG_RETURN(0);
DBUG_RETURN(error);
}

View file

@ -2394,7 +2394,10 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
strxmov(src_path, (*tmp_table)->s->path, reg_ext, NullS);
else
{
fn_format( src_path, src_table, src_db, reg_ext, MYF(MY_UNPACK_FILENAME));
strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
reg_ext, NullS);
/* Resolve symlinks (for windows) */
fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME));
if (access(src_path, F_OK))
{
my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
@ -2421,7 +2424,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
}
else
{
fn_format( dst_path, table_name, db, reg_ext, MYF(MY_UNPACK_FILENAME));
strxmov(dst_path, mysql_data_home, "/", db, "/", table_name,
reg_ext, NullS);
fn_format(dst_path, dst_path, "", "", MYF(MY_UNPACK_FILENAME));
if (!access(dst_path, F_OK))
goto table_exists;
}

View file

@ -120,7 +120,7 @@ int mysql_update(THD *thd,
bool used_key_is_modified, transactional_table, log_delayed;
int res;
int error=0;
uint used_index= MAX_KEY;
uint used_index;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint want_privilege;
#endif
@ -264,7 +264,10 @@ int mysql_update(THD *thd,
else if ((used_index=table->file->key_used_on_scan) < MAX_KEY)
used_key_is_modified=check_if_key_used(table, used_index, fields);
else
{
used_key_is_modified=0;
used_index= MAX_KEY;
}
if (used_key_is_modified || order)
{
/*

View file

@ -219,6 +219,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CASCADE
%token CASCADED
%token CAST_SYM
%token CHAIN_SYM
%token CHARSET
%token CHECKSUM_SYM
%token CHECK_SYM
@ -385,6 +386,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token REDUNDANT_SYM
%token REFERENCES
%token REGEXP
%token RELEASE_SYM
%token RELOAD
%token RENAME
%token REPEATABLE_SYM
@ -690,7 +692,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type
opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
start_transaction_opts
start_transaction_opts opt_chain opt_work_and_chain opt_release
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@ -777,7 +779,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
show describe load alter optimize keycache preload flush
reset purge begin commit rollback savepoint
reset purge begin commit rollback savepoint release
slave master_def master_defs master_file_def slave_until_opts
repair restore backup analyze check start checksum
field_list field_list_item field_spec kill column_def key_def
@ -876,6 +878,7 @@ statement:
| preload
| prepare
| purge
| release
| rename
| repair
| replace
@ -6901,6 +6904,7 @@ keyword:
| BTREE_SYM {}
| CACHE_SYM {}
| CASCADED {}
| CHAIN_SYM {}
| CHANGED {}
| CHARSET {}
| CHECKSUM_SYM {}
@ -7854,25 +7858,66 @@ opt_work:
| WORK_SYM {;}
;
opt_chain:
/* empty */ { $$= (Lex->thd->variables.completion_type == 1); }
| AND_SYM NO_SYM CHAIN_SYM { $$=0; }
| AND_SYM CHAIN_SYM { $$=1; }
;
opt_release:
/* empty */ { $$= (Lex->thd->variables.completion_type == 2); }
| RELEASE_SYM { $$=1; }
| NO_SYM RELEASE_SYM { $$=0; }
;
opt_work_and_chain:
opt_work opt_chain { $$=$2; }
;
opt_savepoint:
/* empty */ {}
| SAVEPOINT_SYM {}
;
commit:
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
COMMIT_SYM opt_work_and_chain opt_release
{
Lex->sql_command= SQLCOM_COMMIT;
Lex->tx_chain= $2;
Lex->tx_release= $3;
}
;
rollback:
ROLLBACK_SYM
{
Lex->sql_command = SQLCOM_ROLLBACK;
ROLLBACK_SYM opt_work_and_chain opt_release
{
Lex->sql_command= SQLCOM_ROLLBACK;
Lex->tx_chain= $2;
Lex->tx_release= $3;
}
| ROLLBACK_SYM TO_SYM SAVEPOINT_SYM ident
| ROLLBACK_SYM opt_work
TO_SYM opt_savepoint ident
{
Lex->sql_command = SQLCOM_ROLLBACK_TO_SAVEPOINT;
Lex->savepoint_name = $4.str;
};
Lex->savepoint_name = $5.str;
}
;
savepoint:
SAVEPOINT_SYM ident
{
Lex->sql_command = SQLCOM_SAVEPOINT;
Lex->savepoint_name = $2.str;
};
}
;
release:
RELEASE_SYM SAVEPOINT_SYM ident
{
Lex->sql_command = SQLCOM_RELEASE_SAVEPOINT;
Lex->savepoint_name = $3.str;
}
;
/*
UNIONS : glue selects together

View file

@ -277,7 +277,7 @@ static int my_strnncollsp_big5(CHARSET_INFO * cs __attribute__((unused)),
if (!res && a_length != b_length)
{
const uchar *end;
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -295,7 +295,7 @@ static int my_strnncollsp_big5(CHARSET_INFO * cs __attribute__((unused)),
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -169,7 +169,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
res= 0;
if (a_length != b_length)
{
int swap= 0;
int swap= 1;
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@ -187,7 +187,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -2638,7 +2638,7 @@ static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)),
if (!res && a_length != b_length)
{
const uchar *end;
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -2656,7 +2656,7 @@ static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)),
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -617,7 +617,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
res= 0;
if (a != a_end || b != b_end)
{
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -635,7 +635,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
for ( ; a < a_end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -399,7 +399,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
res= 0;
if (a_length != b_length)
{
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -417,7 +417,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -162,7 +162,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
res= 0;
if (a_length != b_length)
{
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -174,13 +174,13 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
/* put shorter key in s */
a_length= b_length;
a= b;
swap= -1^1; /* swap sign of result */
swap= -1; /* swap sign of result */
res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -256,7 +256,7 @@ static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)),
if (!res && (a != a_end || b != b_end))
{
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -274,7 +274,7 @@ static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)),
for (; a < a_end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
return (*a < ' ') ? -swap : swap;
}
}
return res;

View file

@ -593,7 +593,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
}
if (a_length != b_length)
{
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
/*
@ -612,7 +612,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
{
if (*a != ' ')
{
res= ((int) *a - (int) ' ') ^ swap;
res= (*a < ' ') ? -swap : swap;
goto ret;
}
}

View file

@ -280,7 +280,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
if (slen != tlen)
{
int swap= 0;
int swap= 1;
if (slen < tlen)
{
s= t;
@ -291,7 +291,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
for ( ; s < se ; s+= 2)
{
if (s[0] || s[1] != ' ')
return (((int)s[0] << 8) + (int) s[1] - (int) ' ') ^ swap;
return (s[0] == 0 && s[1] < ' ') ? -swap : swap;
}
}
return 0;

View file

@ -2093,7 +2093,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
if (slen != tlen)
{
int swap= 0;
int swap= 1;
if (diff_if_only_endspace_difference)
res= 1; /* Assume 'a' is bigger */
if (slen < tlen)
@ -2117,7 +2117,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
for ( ; s < se; s++)
{
if (*s != ' ')
return ((int)*s - (int) ' ') ^ swap;
return (*s < ' ') ? -swap : swap;
}
}
return res;

View file

@ -276,7 +276,7 @@ void vio_in_addr(Vio *vio, struct in_addr *in)
{
DBUG_ENTER("vio_in_addr");
if (vio->localhost)
bzero((char*) in, sizeof(*in)); /* This should never be executed */
bzero((char*) in, sizeof(*in));
else
*in=vio->remote.sin_addr;
DBUG_VOID_RETURN;

View file

@ -259,7 +259,7 @@ void vio_ssl_in_addr(Vio *vio, struct in_addr *in)
{
DBUG_ENTER("vio_ssl_in_addr");
if (vio->localhost)
bzero((char*) in, sizeof(*in)); /* This should never be executed */
bzero((char*) in, sizeof(*in));
else
*in=vio->remote.sin_addr;
DBUG_VOID_RETURN;