Commit a6d7bfe4 authored by unknown's avatar unknown

Fixed <=>

Added mysqltest for <=>
Removed use of TAB in output from mysql-test-run


Docs/manual.texi:
  Changelog
client/mysqltest.c:
  Added missing argument;  Changed to use standard defines
mysql-test/README:
  Cleaned up
mysql-test/mysql-test-run.sh:
  Removed use of TAB in output
  (We are now also depening on sed)
sql/item_cmpfunc.cc:
  Fixed <=>
sql/item_cmpfunc.h:
  Fixed <=>
parent 139d8db8
...@@ -9232,7 +9232,6 @@ problems. @xref{Windows}. ...@@ -9232,7 +9232,6 @@ problems. @xref{Windows}.
If you are using BDB (Berkeley DB) tables, you should familiarize If you are using BDB (Berkeley DB) tables, you should familiarize
yourself with the different BDB specific startup options. @xref{BDB start}. yourself with the different BDB specific startup options. @xref{BDB start}.
@node Automatic start, Command-line options, Starting server, Post-installation @node Automatic start, Command-line options, Starting server, Post-installation
@subsection Starting and Stopping MySQL Automatically @subsection Starting and Stopping MySQL Automatically
@cindex starting, the server automatically @cindex starting, the server automatically
...@@ -28765,11 +28764,12 @@ connection and the server you are using. If you are running in the ...@@ -28765,11 +28764,12 @@ connection and the server you are using. If you are running in the
the @code{mysql} variables that affect your queries. the @code{mysql} variables that affect your queries.
@cindex @code{safe-mode} command @cindex @code{safe-mode} command
A useful startup option for beginners (introduced in @strong{MySQL} Version 3.23.11) is A useful startup option for beginners (introduced in @strong{MySQL}
@code{--safe-mode} (or @code{--i-am-a-dummy} for users that has at some Version 3.23.11) is @code{--safe-mode} (or @code{--i-am-a-dummy} for
time done a @code{DELETE FROM table_name} but forgot the @code{WHERE} users that has at some time done a @code{DELETE FROM table_name} but
clause. When using this option, @code{mysql} sends the following forgot the @code{WHERE} clause. When using this option, @code{mysql}
command to the @strong{MySQL} server when opening the connection: sends the following command to the @strong{MySQL} server when opening
the connection:
@example @example
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#, SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#,
...@@ -39782,6 +39782,8 @@ though, so Version 3.23 is not released as a stable version yet. ...@@ -39782,6 +39782,8 @@ though, so Version 3.23 is not released as a stable version yet.
@appendixsubsec Changes in release 3.23.29 @appendixsubsec Changes in release 3.23.29
@itemize @bullet @itemize @bullet
@item @item
Fixed bug in <=> operator.
@item
Fixed bug in @code{REPLACE} with BDB tables. Fixed bug in @code{REPLACE} with BDB tables.
@item @item
@code{LPAD()} and @code{RPAD()} will shorten the result string if it's longer @code{LPAD()} and @code{RPAD()} will shorten the result string if it's longer
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <errno.h> #include <errno.h>
#define MAX_QUERY 16384 #define MAX_QUERY 16384
#define MAX_RECORD_FILE 128
#define PAD_SIZE 128 #define PAD_SIZE 128
#define MAX_CONS 1024 #define MAX_CONS 1024
#define MAX_INCLUDE_DEPTH 16 #define MAX_INCLUDE_DEPTH 16
...@@ -109,7 +108,7 @@ struct query ...@@ -109,7 +108,7 @@ struct query
int first_word_len; int first_word_len;
int abort_on_error; int abort_on_error;
uint expected_errno; uint expected_errno;
char record_file[MAX_RECORD_FILE]; char record_file[FN_REFLEN];
enum {Q_CONNECTION, Q_QUERY, Q_CONNECT, enum {Q_CONNECTION, Q_QUERY, Q_CONNECT,
Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE, Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE,
Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK, Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK,
...@@ -928,6 +927,7 @@ void usage() ...@@ -928,6 +927,7 @@ void usage()
-P, --port=... Port number to use for connection.\n\ -P, --port=... Port number to use for connection.\n\
-S, --socket=... Socket file to use for connection.\n\ -S, --socket=... Socket file to use for connection.\n\
-r, --record Record output of test_file into result file.\n\ -r, --record Record output of test_file into result file.\n\
-R, --result-file=... Store result in this file\n\
-v, --verbose Write more.\n\ -v, --verbose Write more.\n\
-q, --quiet, --silent Suppress all normal output.\n\ -q, --quiet, --silent Suppress all normal output.\n\
-V, --version Output version information and exit.\n\n"); -V, --version Output version information and exit.\n\n");
...@@ -1024,22 +1024,21 @@ char* safe_str_append(char* buf, const char* str, int size) ...@@ -1024,22 +1024,21 @@ char* safe_str_append(char* buf, const char* str, int size)
void str_to_file(const char* fname, char* str, int size) void str_to_file(const char* fname, char* str, int size)
{ {
int fd; int fd;
if((fd = my_open(fname, O_WRONLY|O_CREAT, MYF(MY_WME))) < 0) if((fd = my_open(fname, O_WRONLY|O_CREAT, MYF(MY_WME | MY_FFNF))) < 0)
die("Could not open %s: errno = %d", fname, errno); die("Could not open %s: errno = %d", fname, errno);
if(my_write(fd, (byte*)str, size, MYF(MY_WME|MY_NABP))) if(my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP)))
die("write failed"); die("write failed");
my_close(fd, MYF(0)); my_close(fd, MYF(0));
} }
void reject_dump(const char* record_file, char* buf, int size) void reject_dump(const char* record_file, char* buf, int size)
{ {
char reject_file[MAX_RECORD_FILE+16]; char reject_file[FN_REFLEN];
char* p; char* p;
p = reject_file; if (strlen(record_file) >= FN_REFLEN-8)
p = safe_str_append(p, record_file, sizeof(reject_file)); die("too long path name for reject");
p = safe_str_append(p, (char*)".reject", reject_file - p + strmov(strmov(reject_file, record_file),".reject");
sizeof(reject_file));
str_to_file(reject_file, buf, size); str_to_file(reject_file, buf, size);
} }
......
...@@ -16,14 +16,27 @@ You can create your own test cases. To create a test case: ...@@ -16,14 +16,27 @@ You can create your own test cases. To create a test case:
in the file, put a set of SQL commands that will create some tables, in the file, put a set of SQL commands that will create some tables,
load test data, run some queries to manipulate it. load test data, run some queries to manipulate it.
then do ./mysql-test-run -record test_case_name We would appreciate if the test tables were called t1, t2, t3 ... (to not
and look at r/test_case_name.result - edit the result if necessary. If you conflict too much with existing tables).
have to edit it, you have found a bug.
If you are using mysqltest commands (like result file names) in your
test case you should do create the result file as follows:
mysql-test-run --record < t/test_case_name.test
If you only have a simple test cases consistent of SQL commands and comments
you can create the test case one of the following ways:
mysql < t/test_case_name.test > r/test_case_name.result
mysql-test-run --record --record-file=r/test_case_name.result < t/test_case_name.test
When this is done, take a look at r/test_case_name.result
- If the result is wrong, you have found a bug; In this case you should
edit the test result to the correct results so that we can verify
that the bug is corrected in future releases.
To submit your test case, put your .test file and .result file(s) into To submit your test case, put your .test file and .result file(s) into
a tar.gz archive, add a README that explains the problem, ftp the a tar.gz archive, add a README that explains the problem, ftp the
archive to ftp://support.mysql.com/pub/mysql/secret/ and send a mail archive to ftp://support.mysql.com/pub/mysql/secret/ and send a mail
to bugs@lists.mysql.com to bugs@lists.mysql.com
#! /bin/sh #! /bin/sh
# mysql-test-run - originally written by Matt Wagner <matt@mysql.com> # mysql-test-run - originally written by Matt Wagner <matt@mysql.com>
# modified by Sasha Pachev <sasha@mysql.com> # modified by Sasha Pachev <sasha@mysql.com>
# Sligtly updated by Monty
#++ #++
# Access Definitions # Access Definitions
...@@ -23,9 +24,9 @@ else ...@@ -23,9 +24,9 @@ else
if [ -f ./mysql-test-run ] && [ -d ../sql ] ; then if [ -f ./mysql-test-run ] && [ -d ../sql ] ; then
SOURCE_DIST=1 SOURCE_DIST=1
else else
echo "If you are using binary distribution, run me from install root as \ echo "If you are using binary distribution, run me from install root as"
scripts/mysql-test-run. On source distribution run me from source root as \ echo "scripts/mysql-test-run. On source distribution run me from source root"
mysql-test/mysql-test-run or from mysql-test as ./mysql-test-run" echo "as mysql-test/mysql-test-run or from mysql-test as ./mysql-test-run"
exit 1 exit 1
fi fi
...@@ -44,6 +45,7 @@ BASEDIR=`pwd` ...@@ -44,6 +45,7 @@ BASEDIR=`pwd`
cd $CWD cd $CWD
MYSQL_TEST_DIR=$BASEDIR/mysql-test MYSQL_TEST_DIR=$BASEDIR/mysql-test
STD_DATA=$MYSQL_TEST_DIR/std_data STD_DATA=$MYSQL_TEST_DIR/std_data
SED=sed
TESTDIR="$MYSQL_TEST_DIR/t/" TESTDIR="$MYSQL_TEST_DIR/t/"
TESTSUFFIX=test TESTSUFFIX=test
...@@ -55,7 +57,6 @@ SYST=0 ...@@ -55,7 +57,6 @@ SYST=0
REALT=0 REALT=0
MY_TMP_DIR=$MYSQL_TEST_DIR/var/tmp MY_TMP_DIR=$MYSQL_TEST_DIR/var/tmp
TIMEFILE="$MYSQL_TEST_DIR/var/tmp/mysqltest-time" TIMEFILE="$MYSQL_TEST_DIR/var/tmp/mysqltest-time"
DASHBLANK="---- ---- -------"
RES_SPACE=" " RES_SPACE=" "
MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \ MYSQLD_SRC_DIRS="strings mysys include extra regex isam merge myisam \
myisammrg heap sql" myisammrg heap sql"
...@@ -69,13 +70,7 @@ SLAVE_RUNNING=0 ...@@ -69,13 +70,7 @@ SLAVE_RUNNING=0
[ -z "$COLUMNS" ] && COLUMNS=80 [ -z "$COLUMNS" ] && COLUMNS=80
E=`expr $COLUMNS - 8` E=`expr $COLUMNS - 8`
C=0 DASH72=`expr substr '________________________________________________________________________' 1 $E`
while [ $C != $E ]
do
DASH72="${DASH72}-"
C=`expr $C + 1`
done
#++ #++
# mysqld Environment Parameters # mysqld Environment Parameters
...@@ -193,6 +188,10 @@ error () { ...@@ -193,6 +188,10 @@ error () {
exit 1 exit 1
} }
prefix_to_8() {
echo " $1" | $SED -e 's:.*\(........\)$:\1:'
}
pass_inc () { pass_inc () {
TOT_PASS=`$EXPR $TOT_PASS + 1` TOT_PASS=`$EXPR $TOT_PASS + 1`
} }
...@@ -393,8 +392,7 @@ mysql_loadstd () { ...@@ -393,8 +392,7 @@ mysql_loadstd () {
run_testcase () run_testcase ()
{ {
tf=$1 tf=$1
tname=`$BASENAME $tf` tname=`$BASENAME $tf .test`
tname=`$ECHO $tname | $CUT -d . -f 1`
master_opt_file=$TESTDIR/$tname-master.opt master_opt_file=$TESTDIR/$tname-master.opt
slave_opt_file=$TESTDIR/$tname-slave.opt slave_opt_file=$TESTDIR/$tname-slave.opt
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
...@@ -459,23 +457,27 @@ run_testcase () ...@@ -459,23 +457,27 @@ run_testcase ()
mytime=`$CAT $TIMEFILE | $TR '\n' '-'` mytime=`$CAT $TIMEFILE | $TR '\n' '-'`
USERT=`$ECHO $mytime | $CUT -d - -f 2 | $CUT -d ' ' -f 2` USERT=`$ECHO $mytime | $CUT -d - -f 2 | $CUT -d ' ' -f 2`
USERT=`prefix_to_8 $USERT`
SYST=`$ECHO $mytime | $CUT -d - -f 3 | $CUT -d ' ' -f 2` SYST=`$ECHO $mytime | $CUT -d - -f 3 | $CUT -d ' ' -f 2`
SYST=`prefix_to_8 $SYST`
REALT=`$ECHO $mytime | $CUT -d - -f 1 | $CUT -d ' ' -f 2` REALT=`$ECHO $mytime | $CUT -d - -f 1 | $CUT -d ' ' -f 2`
REALT=`prefix_to_8 $REALT`
else else
USERT="...." USERT=" ...."
SYST="...." SYST=" ...."
REALT="...." REALT=" ...."
fi fi
timestr="$USERT $SYST $REALT" timestr="$USERT $SYST $REALT"
outstr="$tname $timestr" pname=`$EXPR substr "$tname " 1 16`
$SETCOLOR_NORMAL && $ECHO -n "$pname $timestr"
total_inc total_inc
if [ $res != 0 ]; then if [ $res != 0 ]; then
fail_inc fail_inc
echo "$outstr $RES_SPACE [ fail ]" echo "$RES_SPACE [ fail ]"
$ECHO "failed output" $ECHO "failed output"
$CAT $TIMEFILE $CAT $TIMEFILE
$ECHO $ECHO
...@@ -491,7 +493,7 @@ run_testcase () ...@@ -491,7 +493,7 @@ run_testcase ()
echo "Resuming Tests" echo "Resuming Tests"
else else
pass_inc pass_inc
echo "$outstr $RES_SPACE [ pass ]" echo "$RES_SPACE [ pass ]"
fi fi
fi fi
......
0<=>0 0.0<=>0.0 "A"<=>"A" NULL<=>NULL
1 1 1 1
1<=>0 0<=>NULL NULL<=>0
0 0 0
1.0<=>0.0 0.0<=>NULL NULL<=>0.0
0 0 0
"A"<=>"B" "A"<=>NULL NULL<=>"A"
0 0 0
id value id value t1.value<=>t2.value
1 NULL 1 NULL 1
id value
1 NULL
id value
1 NULL
id value
#
# Testing of the <=> operator
#
#
# First some simple tests
#
select 0<=>0,0.0<=>0.0,"A"<=>"A",NULL<=>NULL;
select 1<=>0,0<=>NULL,NULL<=>0;
select 1.0<=>0.0,0.0<=>NULL,NULL<=>0.0;
select "A"<=>"B","A"<=>NULL,NULL<=>"A";
#
# Test with tables
#
drop table if exists t1,t2;
create table t1 (id int, value int);
create table t2 (id int, value int);
insert into t1 values (1,null);
insert into t2 values (1,null);
select t1.*, t2.*, t1.value<=>t2.value from t1, t2 where t1.id=t2.id and t1.id=1;
select * from t1 where id <=>id;
select * from t1 where value <=> value;
select * from t1 where id <=> value or value<=>id;
drop table t1,t2;
...@@ -170,15 +170,44 @@ longlong Item_func_eq::val_int() ...@@ -170,15 +170,44 @@ longlong Item_func_eq::val_int()
/* Same as Item_func_eq, but NULL = NULL */ /* Same as Item_func_eq, but NULL = NULL */
void Item_func_equal::fix_length_and_dec()
{
Item_bool_func2::fix_length_and_dec();
result_type=item_cmp_type(args[0]->result_type(),args[1]->result_type());
maybe_null=null_value=0;
}
longlong Item_func_equal::val_int() longlong Item_func_equal::val_int()
{ {
int value=(this->*cmp_func)(); switch (result_type) {
if (null_value) case STRING_RESULT:
{ {
null_value=0; String *res1,*res2;
return (args[0]->null_value && args[1]->null_value) ? 1 : 0; res1=args[0]->val_str(&tmp_value1);
res2=args[1]->val_str(&tmp_value2);
if (!res1 || !res2)
return test(res1 == res2);
return (binary ? test(stringcmp(res1,res2) == 0) :
test(sortcmp(res1,res2) == 0));
}
case REAL_RESULT:
{
double val1=args[0]->val();
double val2=args[1]->val();
if (args[0]->null_value || args[1]->null_value)
return test(args[0]->null_value && args[1]->null_value);
return test(val1 == val2);
}
case INT_RESULT:
{
longlong val1=args[0]->val_int();
longlong val2=args[1]->val_int();
if (args[0]->null_value || args[1]->null_value)
return test(args[0]->null_value && args[1]->null_value);
return test(val1 == val2);
}
} }
return value == 0; return 0; // Impossible
} }
......
...@@ -70,11 +70,11 @@ class Item_func_eq :public Item_bool_func2 ...@@ -70,11 +70,11 @@ class Item_func_eq :public Item_bool_func2
class Item_func_equal :public Item_bool_func2 class Item_func_equal :public Item_bool_func2
{ {
Item_result result_type;
public: public:
Item_func_equal(Item *a,Item *b) :Item_bool_func2(a,b) { }; Item_func_equal(Item *a,Item *b) :Item_bool_func2(a,b) { };
longlong val_int(); longlong val_int();
void fix_length_and_dec() void fix_length_and_dec();
{ Item_bool_func2::fix_length_and_dec() ; maybe_null=0; }
enum Functype functype() const { return EQUAL_FUNC; } enum Functype functype() const { return EQUAL_FUNC; }
enum Functype rev_functype() const { return EQUAL_FUNC; } enum Functype rev_functype() const { return EQUAL_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; } cond_result eq_cmp_result() const { return COND_TRUE; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment