Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
f4dc9215
Commit
f4dc9215
authored
Jul 10, 2012
by
Andrei Elkin
Browse files
Options
Browse Files
Download
Plain Diff
merge from 5.5 repo.
parents
aa103d02
88a74a16
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1495 additions
and
1435 deletions
+1495
-1435
client/mysqlbinlog.cc
client/mysqlbinlog.cc
+12
-1
libmysqld/examples/CMakeLists.txt
libmysqld/examples/CMakeLists.txt
+1
-0
mysys/mf_iocache2.c
mysys/mf_iocache2.c
+5
-1
sql/log.cc
sql/log.cc
+4
-1
sql/log_event.cc
sql/log_event.cc
+19
-5
sql/rpl_utility.h
sql/rpl_utility.h
+1
-1
tests/mysql_client_fw.c
tests/mysql_client_fw.c
+1418
-0
tests/mysql_client_test.c
tests/mysql_client_test.c
+35
-1426
No files found.
client/mysqlbinlog.cc
View file @
f4dc9215
...
...
@@ -792,8 +792,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
goto
end
;
}
else
{
ce
->
print
(
result_file
,
print_event_info
,
TRUE
);
if
(
head
->
error
==
-
1
)
goto
err
;
}
// If this binlog is not 3.23 ; why this test??
if
(
glob_description_event
->
binlog_version
>=
3
)
{
...
...
@@ -844,6 +847,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
ce
->
print
(
result_file
,
print_event_info
,
TRUE
);
my_free
((
void
*
)
ce
->
fname
);
delete
ce
;
if
(
head
->
error
==
-
1
)
goto
err
;
}
else
warning
(
"Ignoring Execute_load_log_event as there is no "
...
...
@@ -904,6 +909,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
{
convert_path_to_forward_slashes
(
fname
);
exlq
->
print
(
result_file
,
print_event_info
,
fname
);
if
(
head
->
error
==
-
1
)
{
if
(
fname
)
my_free
(
fname
);
goto
err
;
}
}
else
warning
(
"Ignoring Execute_load_query since there is no "
...
...
libmysqld/examples/CMakeLists.txt
View file @
f4dc9215
...
...
@@ -16,6 +16,7 @@
INCLUDE_DIRECTORIES
(
${
CMAKE_SOURCE_DIR
}
/include
${
CMAKE_SOURCE_DIR
}
/libmysqld/include
${
CMAKE_SOURCE_DIR
}
/regex
${
CMAKE_SOURCE_DIR
}
/tests
${
READLINE_INCLUDE_DIR
}
)
...
...
mysys/mf_iocache2.c
View file @
f4dc9215
...
...
@@ -433,7 +433,11 @@ size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
memset
(
buffz
,
'0'
,
minimum_width
-
length2
);
else
memset
(
buffz
,
' '
,
minimum_width
-
length2
);
my_b_write
(
info
,
buffz
,
minimum_width
-
length2
);
if
(
my_b_write
(
info
,
buffz
,
minimum_width
-
length2
))
{
my_afree
(
buffz
);
goto
err
;
}
my_afree
(
buffz
);
}
...
...
sql/log.cc
View file @
f4dc9215
...
...
@@ -2762,7 +2762,10 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
{
end
=
strxmov
(
buff
,
"# administrator command: "
,
NullS
);
buff_len
=
(
ulong
)
(
end
-
buff
);
my_b_write
(
&
log_file
,
(
uchar
*
)
buff
,
buff_len
);
DBUG_EXECUTE_IF
(
"simulate_slow_log_write_error"
,
{
DBUG_SET
(
"+d,simulate_file_write_error"
);});
if
(
my_b_write
(
&
log_file
,
(
uchar
*
)
buff
,
buff_len
))
tmp_errno
=
errno
;
}
if
(
my_b_write
(
&
log_file
,
(
uchar
*
)
sql_text
,
sql_text_len
)
||
my_b_write
(
&
log_file
,
(
uchar
*
)
";
\n
"
,
2
)
||
...
...
sql/log_event.cc
View file @
f4dc9215
...
...
@@ -6478,11 +6478,18 @@ void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info
{
Load_log_event
::
print
(
file
,
print_event_info
,
!
check_fname_outside_temp_buf
());
/*
That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
SHOW BINLOG EVENTS we don't.
*/
my_b_printf
(
&
cache
,
"#"
);
/**
reduce the size of io cache so that the write function is called
for every call to my_b_printf().
*/
DBUG_EXECUTE_IF
(
"simulate_create_event_write_error"
,
{(
&
cache
)
->
write_pos
=
(
&
cache
)
->
write_end
;
DBUG_SET
(
"+d,simulate_file_write_error"
);});
/*
That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
SHOW BINLOG EVENTS we don't.
*/
my_b_printf
(
&
cache
,
"#"
);
}
my_b_printf
(
&
cache
,
" file_id: %d block_len: %d
\n
"
,
file_id
,
block_len
);
...
...
@@ -7169,6 +7176,13 @@ void Execute_load_query_log_event::print(FILE* file,
Write_on_release_cache
cache
(
&
print_event_info
->
head_cache
,
file
);
print_query_header
(
&
cache
,
print_event_info
);
/**
reduce the size of io cache so that the write function is called
for every call to my_b_printf().
*/
DBUG_EXECUTE_IF
(
"simulate_execute_event_write_error"
,
{(
&
cache
)
->
write_pos
=
(
&
cache
)
->
write_end
;
DBUG_SET
(
"+d,simulate_file_write_error"
);});
if
(
local_fname
)
{
...
...
sql/rpl_utility.h
View file @
f4dc9215
...
...
@@ -271,7 +271,7 @@ class Deferred_log_events
public:
Deferred_log_events
(
Relay_log_info
*
rli
);
~
Deferred_log_events
();
/* queue for exection at Query-log-event time prior the Query */
;
/* queue for exection at Query-log-event time prior the Query */
int
add
(
Log_event
*
ev
);
bool
is_empty
();
bool
execute
(
Relay_log_info
*
rli
);
...
...
tests/mysql_client_fw.c
0 → 100644
View file @
f4dc9215
/* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <errmsg.h>
#include <my_getopt.h>
#include <m_string.h>
#include <mysqld_error.h>
#include <sql_common.h>
#include <mysql/client_plugin.h>
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300
/* MAX QUERY BUFFER LENGTH */
#define MAX_KEY MAX_INDEXES
#define MAX_SERVER_ARGS 64
/* set default options */
static
int
opt_testcase
=
0
;
static
char
*
opt_db
=
0
;
static
char
*
opt_user
=
0
;
static
char
*
opt_password
=
0
;
static
char
*
opt_host
=
0
;
static
char
*
opt_unix_socket
=
0
;
#ifdef HAVE_SMEM
static
char
*
shared_memory_base_name
=
0
;
#endif
static
unsigned
int
opt_port
;
static
my_bool
tty_password
=
0
,
opt_silent
=
0
;
static
MYSQL
*
mysql
=
0
;
static
char
current_db
[]
=
"client_test_db"
;
static
unsigned
int
test_count
=
0
;
static
unsigned
int
opt_count
=
0
;
static
unsigned
int
iter_count
=
0
;
static
my_bool
have_innodb
=
FALSE
;
static
char
*
opt_plugin_dir
=
0
,
*
opt_default_auth
=
0
;
static
const
char
*
opt_basedir
=
"./"
;
static
const
char
*
opt_vardir
=
"mysql-test/var"
;
static
longlong
opt_getopt_ll_test
=
0
;
static
int
embedded_server_arg_count
=
0
;
static
char
*
embedded_server_args
[
MAX_SERVER_ARGS
];
static
const
char
*
embedded_server_groups
[]
=
{
"server"
,
"embedded"
,
"mysql_client_test_SERVER"
,
NullS
};
static
time_t
start_time
,
end_time
;
static
double
total_time
;
const
char
*
default_dbug_option
=
"d:t:o,/tmp/mysql_client_test.trace"
;
struct
my_tests_st
{
const
char
*
name
;
void
(
*
function
)();
};
#define myheader(str) \
DBUG_PRINT("test", ("name: %s", str)); \
if (opt_silent < 2) \
{ \
fprintf(stdout, "\n\n#####################################\n"); \
fprintf(stdout, "%u of (%u/%u): %s", test_count++, iter_count, \
opt_count, str); \
fprintf(stdout, " \n#####################################\n"); \
}
#define myheader_r(str) \
DBUG_PRINT("test", ("name: %s", str)); \
if (!opt_silent) \
{ \
fprintf(stdout, "\n\n#####################################\n"); \
fprintf(stdout, "%s", str); \
fprintf(stdout, " \n#####################################\n"); \
}
static
void
print_error
(
const
char
*
msg
);
static
void
print_st_error
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
);
static
void
client_disconnect
(
MYSQL
*
mysql
,
my_bool
drop_db
);
/*
Abort unless given experssion is non-zero.
SYNOPSIS
DIE_UNLESS(expr)
DESCRIPTION
We can't use any kind of system assert as we need to
preserve tested invariants in release builds as well.
*/
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
#define DIE_IF(expr) \
((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0))
#define DIE(expr) \
die(__FILE__, __LINE__, #expr)
static
void
die
(
const
char
*
file
,
int
line
,
const
char
*
expr
)
{
fflush
(
stdout
);
fprintf
(
stderr
,
"%s:%d: check failed: '%s'
\n
"
,
file
,
line
,
expr
);
fflush
(
stderr
);
exit
(
1
);
}
#define myerror(msg) print_error(msg)
#define mysterror(stmt, msg) print_st_error(stmt, msg)
#define myquery(RES) \
{ \
int r= (RES); \
if (r) \
myerror(NULL); \
DIE_UNLESS(r == 0); \
}
#define myquery_r(r) \
{ \
if (r) \
myerror(NULL); \
DIE_UNLESS(r != 0); \
}
#define check_execute(stmt, r) \
{ \
if (r) \
mysterror(stmt, NULL); \
DIE_UNLESS(r == 0); \
}
#define check_execute_r(stmt, r) \
{ \
if (r) \
mysterror(stmt, NULL); \
DIE_UNLESS(r != 0); \
}
#define check_stmt(stmt) \
{ \
if ( stmt == 0) \
myerror(NULL); \
DIE_UNLESS(stmt != 0); \
}
#define check_stmt_r(stmt) \
{ \
if (stmt == 0) \
myerror(NULL); \
DIE_UNLESS(stmt == 0); \
}
#define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);}
#define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);}
/* A workaround for Sun Forte 5.6 on Solaris x86 */
static
int
cmp_double
(
double
*
a
,
double
*
b
)
{
return
*
a
==
*
b
;
}
/* Print the error message */
static
void
print_error
(
const
char
*
msg
)
{
if
(
!
opt_silent
)
{
if
(
mysql
&&
mysql_errno
(
mysql
))
{
if
(
mysql
->
server_version
)
fprintf
(
stdout
,
"
\n
[MySQL-%s]"
,
mysql
->
server_version
);
else
fprintf
(
stdout
,
"
\n
[MySQL]"
);
fprintf
(
stdout
,
"[%d] %s
\n
"
,
mysql_errno
(
mysql
),
mysql_error
(
mysql
));
}
else
if
(
msg
)
fprintf
(
stderr
,
" [MySQL] %s
\n
"
,
msg
);
}
}
static
void
print_st_error
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
)
{
if
(
!
opt_silent
)
{
if
(
stmt
&&
mysql_stmt_errno
(
stmt
))
{
if
(
stmt
->
mysql
&&
stmt
->
mysql
->
server_version
)
fprintf
(
stdout
,
"
\n
[MySQL-%s]"
,
stmt
->
mysql
->
server_version
);
else
fprintf
(
stdout
,
"
\n
[MySQL]"
);
fprintf
(
stdout
,
"[%d] %s
\n
"
,
mysql_stmt_errno
(
stmt
),
mysql_stmt_error
(
stmt
));
}
else
if
(
msg
)
fprintf
(
stderr
,
" [MySQL] %s
\n
"
,
msg
);
}
}
/*
Enhanced version of mysql_client_init(), which may also set shared memory
base on Windows.
*/
static
MYSQL
*
mysql_client_init
(
MYSQL
*
con
)
{
MYSQL
*
res
=
mysql_init
(
con
);
#ifdef HAVE_SMEM
if
(
res
&&
shared_memory_base_name
)
mysql_options
(
res
,
MYSQL_SHARED_MEMORY_BASE_NAME
,
shared_memory_base_name
);
#endif
if
(
opt_plugin_dir
&&
*
opt_plugin_dir
)
mysql_options
(
res
,
MYSQL_PLUGIN_DIR
,
opt_plugin_dir
);
if
(
opt_default_auth
&&
*
opt_default_auth
)
mysql_options
(
res
,
MYSQL_DEFAULT_AUTH
,
opt_default_auth
);
return
res
;
}
/*
Disable direct calls of mysql_init, as it disregards shared memory base.
*/
#define mysql_init(A) Please use mysql_client_init instead of mysql_init
/* Check if the connection has InnoDB tables */
static
my_bool
check_have_innodb
(
MYSQL
*
conn
)
{
MYSQL_RES
*
res
;
MYSQL_ROW
row
;
int
rc
;
my_bool
result
;
rc
=
mysql_query
(
conn
,
"show variables like 'have_innodb'"
);
myquery
(
rc
);
res
=
mysql_use_result
(
conn
);
DIE_UNLESS
(
res
);
row
=
mysql_fetch_row
(
res
);
DIE_UNLESS
(
row
);
result
=
strcmp
(
row
[
1
],
"YES"
)
==
0
;
mysql_free_result
(
res
);
return
result
;
}
/*
This is to be what mysql_query() is for mysql_real_query(), for
mysql_simple_prepare(): a variant without the 'length' parameter.
*/
static
MYSQL_STMT
*
STDCALL
mysql_simple_prepare
(
MYSQL
*
mysql_arg
,
const
char
*
query
)
{
MYSQL_STMT
*
stmt
=
mysql_stmt_init
(
mysql_arg
);
if
(
stmt
&&
mysql_stmt_prepare
(
stmt
,
query
,
(
uint
)
strlen
(
query
)))
{
mysql_stmt_close
(
stmt
);
return
0
;
}
return
stmt
;
}
/**
Connect to the server with options given by arguments to this application,
stored in global variables opt_host, opt_user, opt_password, opt_db,
opt_port and opt_unix_socket.
@param flag[in] client_flag passed on to mysql_real_connect
@param protocol[in] MYSQL_PROTOCOL_* to use for this connection
@param auto_reconnect[in] set to 1 for auto reconnect
@return pointer to initialized and connected MYSQL object
*/
static
MYSQL
*
client_connect
(
ulong
flag
,
uint
protocol
,
my_bool
auto_reconnect
)
{
MYSQL
*
mysql
;
int
rc
;
static
char
query
[
MAX_TEST_QUERY_LENGTH
];
myheader_r
(
"client_connect"
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
Establishing a connection to '%s' ..."
,
opt_host
?
opt_host
:
""
);
if
(
!
(
mysql
=
mysql_client_init
(
NULL
)))
{
opt_silent
=
0
;
myerror
(
"mysql_client_init() failed"
);
exit
(
1
);
}
/* enable local infile, in non-binary builds often disabled by default */
mysql_options
(
mysql
,
MYSQL_OPT_LOCAL_INFILE
,
0
);
mysql_options
(
mysql
,
MYSQL_OPT_PROTOCOL
,
&
protocol
);
if
(
opt_plugin_dir
&&
*
opt_plugin_dir
)
mysql_options
(
mysql
,
MYSQL_PLUGIN_DIR
,
opt_plugin_dir
);
if
(
opt_default_auth
&&
*
opt_default_auth
)
mysql_options
(
mysql
,
MYSQL_DEFAULT_AUTH
,
opt_default_auth
);
if
(
!
(
mysql_real_connect
(
mysql
,
opt_host
,
opt_user
,
opt_password
,
opt_db
?
opt_db
:
"test"
,
opt_port
,
opt_unix_socket
,
flag
)))
{
opt_silent
=
0
;
myerror
(
"connection failed"
);
mysql_close
(
mysql
);
fprintf
(
stdout
,
"
\n
Check the connection options using --help or -?
\n
"
);
exit
(
1
);
}
mysql
->
reconnect
=
auto_reconnect
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK"
);
/* set AUTOCOMMIT to ON*/
mysql_autocommit
(
mysql
,
TRUE
);
if
(
!
opt_silent
)
{
fprintf
(
stdout
,
"
\n
Connected to MySQL server version: %s (%lu)
\n
"
,
mysql_get_server_info
(
mysql
),
(
ulong
)
mysql_get_server_version
(
mysql
));
fprintf
(
stdout
,
"
\n
Creating a test database '%s' ..."
,
current_db
);
}
strxmov
(
query
,
"CREATE DATABASE IF NOT EXISTS "
,
current_db
,
NullS
);
rc
=
mysql_query
(
mysql
,
query
);
myquery
(
rc
);
strxmov
(
query
,
"USE "
,
current_db
,
NullS
);
rc
=
mysql_query
(
mysql
,
query
);
myquery
(
rc
);
have_innodb
=
check_have_innodb
(
mysql
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK"
);
return
mysql
;
}
/* Close the connection */
static
void
client_disconnect
(
MYSQL
*
mysql
,
my_bool
drop_db
)
{
static
char
query
[
MAX_TEST_QUERY_LENGTH
];
myheader_r
(
"client_disconnect"
);
if
(
mysql
)
{
if
(
drop_db
)
{
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
dropping the test database '%s' ..."
,
current_db
);
strxmov
(
query
,
"DROP DATABASE IF EXISTS "
,
current_db
,
NullS
);
mysql_query
(
mysql
,
query
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK"
);
}
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
closing the connection ..."
);
mysql_close
(
mysql
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK
\n
"
);
}
}
/* Print dashes */
static
void
my_print_dashes
(
MYSQL_RES
*
result
)
{
MYSQL_FIELD
*
field
;
unsigned
int
i
,
j
;
mysql_field_seek
(
result
,
0
);
fputc
(
'\t'
,
stdout
);
fputc
(
'+'
,
stdout
);
for
(
i
=
0
;
i
<
mysql_num_fields
(
result
);
i
++
)
{
field
=
mysql_fetch_field
(
result
);
for
(
j
=
0
;
j
<
field
->
max_length
+
2
;
j
++
)
fputc
(
'-'
,
stdout
);
fputc
(
'+'
,
stdout
);
}
fputc
(
'\n'
,
stdout
);
}
/* Print resultset metadata information */
static
void
my_print_result_metadata
(
MYSQL_RES
*
result
)
{
MYSQL_FIELD
*
field
;
unsigned
int
i
,
j
;
unsigned
int
field_count
;
mysql_field_seek
(
result
,
0
);
if
(
!
opt_silent
)
{
fputc
(
'\n'
,
stdout
);
fputc
(
'\n'
,
stdout
);
}
field_count
=
mysql_num_fields
(
result
);
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
field
=
mysql_fetch_field
(
result
);
j
=
strlen
(
field
->
name
);
if
(
j
<
field
->
max_length
)
j
=
field
->
max_length
;
if
(
j
<
4
&&
!
IS_NOT_NULL
(
field
->
flags
))
j
=
4
;
field
->
max_length
=
j
;
}
if
(
!
opt_silent
)
{
my_print_dashes
(
result
);
fputc
(
'\t'
,
stdout
);
fputc
(
'|'
,
stdout
);
}
mysql_field_seek
(
result
,
0
);
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
field
=
mysql_fetch_field
(
result
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
field
->
name
);
}
if
(
!
opt_silent
)
{
fputc
(
'\n'
,
stdout
);
my_print_dashes
(
result
);
}
}
/* Process the result set */
static
int
my_process_result_set
(
MYSQL_RES
*
result
)
{
MYSQL_ROW
row
;
MYSQL_FIELD
*
field
;
unsigned
int
i
;
unsigned
int
row_count
=
0
;
if
(
!
result
)
return
0
;
my_print_result_metadata
(
result
);
while
((
row
=
mysql_fetch_row
(
result
))
!=
NULL
)
{
mysql_field_seek
(
result
,
0
);
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'|'
,
stdout
);
}
for
(
i
=
0
;
i
<
mysql_num_fields
(
result
);
i
++
)
{
field
=
mysql_fetch_field
(
result
);
if
(
!
opt_silent
)
{
if
(
row
[
i
]
==
NULL
)
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
"NULL"
);
else
if
(
IS_NUM
(
field
->
type
))
fprintf
(
stdout
,
" %*s |"
,
(
int
)
field
->
max_length
,
row
[
i
]);
else
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
row
[
i
]);
}
}
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'\n'
,
stdout
);
}
row_count
++
;
}
if
(
!
opt_silent
)
{
if
(
row_count
)
my_print_dashes
(
result
);
if
(
mysql_errno
(
mysql
)
!=
0
)
fprintf
(
stderr
,
"
\n\t
mysql_fetch_row() failed
\n
"
);
else
fprintf
(
stdout
,
"
\n\t
%d %s returned
\n
"
,
row_count
,
row_count
==
1
?
"row"
:
"rows"
);
}
return
row_count
;
}
static
int
my_process_result
(
MYSQL
*
mysql_arg
)
{
MYSQL_RES
*
result
;
int
row_count
;
if
(
!
(
result
=
mysql_store_result
(
mysql_arg
)))
return
0
;
row_count
=
my_process_result_set
(
result
);
mysql_free_result
(
result
);
return
row_count
;
}
/* Process the statement result set */
#define MAX_RES_FIELDS 50
#define MAX_FIELD_DATA_SIZE 255
static
int
my_process_stmt_result
(
MYSQL_STMT
*
stmt
)
{
int
field_count
;
int
row_count
=
0
;
MYSQL_BIND
buffer
[
MAX_RES_FIELDS
];
MYSQL_FIELD
*
field
;
MYSQL_RES
*
result
;
char
data
[
MAX_RES_FIELDS
][
MAX_FIELD_DATA_SIZE
];
ulong
length
[
MAX_RES_FIELDS
];
my_bool
is_null
[
MAX_RES_FIELDS
];
int
rc
,
i
;
if
(
!
(
result
=
mysql_stmt_result_metadata
(
stmt
)))
/* No meta info */
{
while
(
!
mysql_stmt_fetch
(
stmt
))
row_count
++
;
return
row_count
;
}
field_count
=
min
(
mysql_num_fields
(
result
),
MAX_RES_FIELDS
);
bzero
((
char
*
)
buffer
,
sizeof
(
buffer
));
bzero
((
char
*
)
length
,
sizeof
(
length
));
bzero
((
char
*
)
is_null
,
sizeof
(
is_null
));
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
buffer
[
i
].
buffer_type
=
MYSQL_TYPE_STRING
;
buffer
[
i
].
buffer_length
=
MAX_FIELD_DATA_SIZE
;
buffer
[
i
].
length
=
&
length
[
i
];
buffer
[
i
].
buffer
=
(
void
*
)
data
[
i
];
buffer
[
i
].
is_null
=
&
is_null
[
i
];
}
rc
=
mysql_stmt_bind_result
(
stmt
,
buffer
);
check_execute
(
stmt
,
rc
);
rc
=
1
;
mysql_stmt_attr_set
(
stmt
,
STMT_ATTR_UPDATE_MAX_LENGTH
,
(
void
*
)
&
rc
);
rc
=
mysql_stmt_store_result
(
stmt
);
check_execute
(
stmt
,
rc
);
my_print_result_metadata
(
result
);
mysql_field_seek
(
result
,
0
);
while
((
rc
=
mysql_stmt_fetch
(
stmt
))
==
0
)
{
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'|'
,
stdout
);
}
mysql_field_seek
(
result
,
0
);
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
field
=
mysql_fetch_field
(
result
);
if
(
!
opt_silent
)
{
if
(
is_null
[
i
])
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
"NULL"
);
else
if
(
length
[
i
]
==
0
)
{
data
[
i
][
0
]
=
'\0'
;
/* unmodified buffer */
fprintf
(
stdout
,
" %*s |"
,
(
int
)
field
->
max_length
,
data
[
i
]);
}
else
if
(
IS_NUM
(
field
->
type
))
fprintf
(
stdout
,
" %*s |"
,
(
int
)
field
->
max_length
,
data
[
i
]);
else
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
data
[
i
]);
}
}
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'\n'
,
stdout
);
}
row_count
++
;
}
DIE_UNLESS
(
rc
==
MYSQL_NO_DATA
);
if
(
!
opt_silent
)
{
if
(
row_count
)
my_print_dashes
(
result
);
fprintf
(
stdout
,
"
\n\t
%d %s returned
\n
"
,
row_count
,
row_count
==
1
?
"row"
:
"rows"
);
}
mysql_free_result
(
result
);
return
row_count
;
}
/* Prepare statement, execute, and process result set for given query */
int
my_stmt_result
(
const
char
*
buff
)
{
MYSQL_STMT
*
stmt
;
int
row_count
;
int
rc
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n\n
%s"
,
buff
);
stmt
=
mysql_simple_prepare
(
mysql
,
buff
);
check_stmt
(
stmt
);
rc
=
mysql_stmt_execute
(
stmt
);
check_execute
(
stmt
,
rc
);
row_count
=
my_process_stmt_result
(
stmt
);
mysql_stmt_close
(
stmt
);
return
row_count
;
}
/* Print the total number of warnings and the warnings themselves. */
void
my_process_warnings
(
MYSQL
*
conn
,
unsigned
expected_warning_count
)
{
MYSQL_RES
*
result
;
int
rc
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total warnings: %u (expected: %u)
\n
"
,
mysql_warning_count
(
conn
),
expected_warning_count
);
DIE_UNLESS
(
mysql_warning_count
(
mysql
)
==
expected_warning_count
);
rc
=
mysql_query
(
conn
,
"SHOW WARNINGS"
);
DIE_UNLESS
(
rc
==
0
);
result
=
mysql_store_result
(
conn
);
mytest
(
result
);
rc
=
my_process_result_set
(
result
);
mysql_free_result
(
result
);
}
/* Utility function to verify a particular column data */
static
void
verify_col_data
(
const
char
*
table
,
const
char
*
col
,
const
char
*
exp_data
)
{
static
char
query
[
MAX_TEST_QUERY_LENGTH
];
MYSQL_RES
*
result
;
MYSQL_ROW
row
;
int
rc
,
field
=
1
;
if
(
table
&&
col
)
{
strxmov
(
query
,
"SELECT "
,
col
,
" FROM "
,
table
,
" LIMIT 1"
,
NullS
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
%s"
,
query
);
rc
=
mysql_query
(
mysql
,
query
);
myquery
(
rc
);
field
=
0
;
}
result
=
mysql_use_result
(
mysql
);
mytest
(
result
);
if
(
!
(
row
=
mysql_fetch_row
(
result
))
||
!
row
[
field
])
{
fprintf
(
stdout
,
"
\n
*** ERROR: FAILED TO GET THE RESULT ***"
);
exit
(
1
);
}
if
(
strcmp
(
row
[
field
],
exp_data
))
{
fprintf
(
stdout
,
"
\n
obtained: `%s` (expected: `%s`)"
,
row
[
field
],
exp_data
);
DIE_UNLESS
(
FALSE
);
}
mysql_free_result
(
result
);
}
/* Utility function to verify the field members */
#define verify_prepare_field(result,no,name,org_name,type,table, \
org_table,db,length,def) \
do_verify_prepare_field((result),(no),(name),(org_name),(type), \
(table),(org_table),(db),(length),(def), \
__FILE__, __LINE__)
static
void
do_verify_prepare_field
(
MYSQL_RES
*
result
,
unsigned
int
no
,
const
char
*
name
,
const
char
*
org_name
,
enum
enum_field_types
type
,
const
char
*
table
,
const
char
*
org_table
,
const
char
*
db
,
unsigned
long
length
,
const
char
*
def
,
const
char
*
file
,
int
line
)
{
MYSQL_FIELD
*
field
;
CHARSET_INFO
*
cs
;
ulonglong
expected_field_length
;
if
(
!
(
field
=
mysql_fetch_field_direct
(
result
,
no
)))
{
fprintf
(
stdout
,
"
\n
*** ERROR: FAILED TO GET THE RESULT ***"
);
exit
(
1
);
}
cs
=
get_charset
(
field
->
charsetnr
,
0
);
DIE_UNLESS
(
cs
);
if
((
expected_field_length
=
length
*
cs
->
mbmaxlen
)
>
UINT_MAX32
)
expected_field_length
=
UINT_MAX32
;
if
(
!
opt_silent
)
{
fprintf
(
stdout
,
"
\n
field[%d]:"
,
no
);
fprintf
(
stdout
,
"
\n
name :`%s`
\t
(expected: `%s`)"
,
field
->
name
,
name
);
fprintf
(
stdout
,
"
\n
org_name :`%s`
\t
(expected: `%s`)"
,
field
->
org_name
,
org_name
);
fprintf
(
stdout
,
"
\n
type :`%d`
\t
(expected: `%d`)"
,
field
->
type
,
type
);
if
(
table
)
fprintf
(
stdout
,
"
\n
table :`%s`
\t
(expected: `%s`)"
,
field
->
table
,
table
);
if
(
org_table
)
fprintf
(
stdout
,
"
\n
org_table:`%s`
\t
(expected: `%s`)"
,
field
->
org_table
,
org_table
);
fprintf
(
stdout
,
"
\n
database :`%s`
\t
(expected: `%s`)"
,
field
->
db
,
db
);
fprintf
(
stdout
,
"
\n
length :`%lu`
\t
(expected: `%llu`)"
,
field
->
length
,
expected_field_length
);
fprintf
(
stdout
,
"
\n
maxlength:`%ld`"
,
field
->
max_length
);
fprintf
(
stdout
,
"
\n
charsetnr:`%d`"
,
field
->
charsetnr
);
fprintf
(
stdout
,
"
\n
default :`%s`
\t
(expected: `%s`)"
,
field
->
def
?
field
->
def
:
"(null)"
,
def
?
def
:
"(null)"
);
fprintf
(
stdout
,
"
\n
"
);
}
DIE_UNLESS
(
strcmp
(
field
->
name
,
name
)
==
0
);
DIE_UNLESS
(
strcmp
(
field
->
org_name
,
org_name
)
==
0
);
/*
XXX: silent column specification change works based on number of
bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even
for CHAR(2) column if its character set is multibyte.
VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would
expect.
*/
if
(
cs
->
mbmaxlen
==
1
)
{
if
(
field
->
type
!=
type
)
{
fprintf
(
stderr
,
"Expected field type: %d, got type: %d in file %s, line %d
\n
"
,
(
int
)
type
,
(
int
)
field
->
type
,
file
,
line
);
DIE_UNLESS
(
field
->
type
==
type
);
}
}
if
(
table
)
DIE_UNLESS
(
strcmp
(
field
->
table
,
table
)
==
0
);
if
(
org_table
)
DIE_UNLESS
(
strcmp
(
field
->
org_table
,
org_table
)
==
0
);
DIE_UNLESS
(
strcmp
(
field
->
db
,
db
)
==
0
);
/*
Character set should be taken into account for multibyte encodings, such
as utf8. Field length is calculated as number of characters * maximum
number of bytes a character can occupy.
*/
if
(
length
&&
(
field
->
length
!=
expected_field_length
))
{
fprintf
(
stderr
,
"Expected field length: %llu, got length: %lu
\n
"
,
expected_field_length
,
field
->
length
);
DIE_UNLESS
(
field
->
length
==
expected_field_length
);
}
if
(
def
)
DIE_UNLESS
(
strcmp
(
field
->
def
,
def
)
==
0
);
}
/* Utility function to verify the parameter count */
static
void
verify_param_count
(
MYSQL_STMT
*
stmt
,
long
exp_count
)
{
long
param_count
=
mysql_stmt_param_count
(
stmt
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total parameters in stmt: `%ld` (expected: `%ld`)"
,
param_count
,
exp_count
);
DIE_UNLESS
(
param_count
==
exp_count
);
}
/* Utility function to verify the total affected rows */
static
void
verify_st_affected_rows
(
MYSQL_STMT
*
stmt
,
ulonglong
exp_count
)
{
ulonglong
affected_rows
=
mysql_stmt_affected_rows
(
stmt
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total affected rows: `%ld` (expected: `%ld`)"
,
(
long
)
affected_rows
,
(
long
)
exp_count
);
DIE_UNLESS
(
affected_rows
==
exp_count
);
}
/* Utility function to verify the total affected rows */
static
void
verify_affected_rows
(
ulonglong
exp_count
)
{
ulonglong
affected_rows
=
mysql_affected_rows
(
mysql
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total affected rows: `%ld` (expected: `%ld`)"
,
(
long
)
affected_rows
,
(
long
)
exp_count
);
DIE_UNLESS
(
affected_rows
==
exp_count
);
}
/* Utility function to verify the total fields count */
static
void
verify_field_count
(
MYSQL_RES
*
result
,
uint
exp_count
)
{
uint
field_count
=
mysql_num_fields
(
result
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total fields in the result set: `%d` (expected: `%d`)"
,
field_count
,
exp_count
);
DIE_UNLESS
(
field_count
==
exp_count
);
}
/* Utility function to execute a query using prepare-execute */
#ifndef EMBEDDED_LIBRARY
static
void
execute_prepare_query
(
const
char
*
query
,
ulonglong
exp_count
)
{
MYSQL_STMT
*
stmt
;
ulonglong
affected_rows
;
int
rc
;
stmt
=
mysql_simple_prepare
(
mysql
,
query
);
check_stmt
(
stmt
);
rc
=
mysql_stmt_execute
(
stmt
);
myquery
(
rc
);
affected_rows
=
mysql_stmt_affected_rows
(
stmt
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total affected rows: `%ld` (expected: `%ld`)"
,
(
long
)
affected_rows
,
(
long
)
exp_count
);
DIE_UNLESS
(
affected_rows
==
exp_count
);
mysql_stmt_close
(
stmt
);
}
#endif
/*
Accepts arbitrary number of queries and runs them against the database.
Used to fill tables for each test.
*/
void
fill_tables
(
const
char
**
query_list
,
unsigned
query_count
)
{
int
rc
;
const
char
**
query
;
DBUG_ENTER
(
"fill_tables"
);
for
(
query
=
query_list
;
query
<
query_list
+
query_count
;
++
query
)
{
rc
=
mysql_query
(
mysql
,
*
query
);
myquery
(
rc
);
}
DBUG_VOID_RETURN
;
}
/*
All state of fetch from one statement: statement handle, out buffers,
fetch position.
See fetch_n for for the only use case.
*/
enum
{
MAX_COLUMN_LENGTH
=
255
};
typedef
struct
st_stmt_fetch
{
const
char
*
query
;
unsigned
stmt_no
;
MYSQL_STMT
*
handle
;
my_bool
is_open
;
MYSQL_BIND
*
bind_array
;
char
**
out_data
;
unsigned
long
*
out_data_length
;
unsigned
column_count
;
unsigned
row_count
;
}
Stmt_fetch
;
/*
Create statement handle, prepare it with statement, execute and allocate
fetch buffers.
*/
void
stmt_fetch_init
(
Stmt_fetch
*
fetch
,
unsigned
stmt_no_arg
,
const
char
*
query_arg
)
{
unsigned
long
type
=
CURSOR_TYPE_READ_ONLY
;
int
rc
;
unsigned
i
;
MYSQL_RES
*
metadata
;
DBUG_ENTER
(
"stmt_fetch_init"
);
/* Save query and statement number for error messages */
fetch
->
stmt_no
=
stmt_no_arg
;
fetch
->
query
=
query_arg
;
fetch
->
handle
=
mysql_stmt_init
(
mysql
);
rc
=
mysql_stmt_prepare
(
fetch
->
handle
,
fetch
->
query
,
strlen
(
fetch
->
query
));
check_execute
(
fetch
->
handle
,
rc
);
/*
The attribute is sent to server on execute and asks to open read-only
for result set
*/
mysql_stmt_attr_set
(
fetch
->
handle
,
STMT_ATTR_CURSOR_TYPE
,
(
const
void
*
)
&
type
);
rc
=
mysql_stmt_execute
(
fetch
->
handle
);
check_execute
(
fetch
->
handle
,
rc
);
/* Find out total number of columns in result set */
metadata
=
mysql_stmt_result_metadata
(
fetch
->
handle
);
fetch
->
column_count
=
mysql_num_fields
(
metadata
);
mysql_free_result
(
metadata
);
/*
Now allocate bind handles and buffers for output data:
calloc memory to reduce number of MYSQL_BIND members we need to
set up.
*/
fetch
->
bind_array
=
(
MYSQL_BIND
*
)
calloc
(
1
,
sizeof
(
MYSQL_BIND
)
*
fetch
->
column_count
);
fetch
->
out_data
=
(
char
**
)
calloc
(
1
,
sizeof
(
char
*
)
*
fetch
->
column_count
);
fetch
->
out_data_length
=
(
ulong
*
)
calloc
(
1
,
sizeof
(
ulong
)
*
fetch
->
column_count
);
for
(
i
=
0
;
i
<
fetch
->
column_count
;
++
i
)
{
fetch
->
out_data
[
i
]
=
(
char
*
)
calloc
(
1
,
MAX_COLUMN_LENGTH
);
fetch
->
bind_array
[
i
].
buffer_type
=
MYSQL_TYPE_STRING
;
fetch
->
bind_array
[
i
].
buffer
=
fetch
->
out_data
[
i
];
fetch
->
bind_array
[
i
].
buffer_length
=
MAX_COLUMN_LENGTH
;
fetch
->
bind_array
[
i
].
length
=
fetch
->
out_data_length
+
i
;
}
mysql_stmt_bind_result
(
fetch
->
handle
,
fetch
->
bind_array
);
fetch
->
row_count
=
0
;
fetch
->
is_open
=
TRUE
;
/* Ready for reading rows */
DBUG_VOID_RETURN
;
}
/* Fetch and print one row from cursor */
int
stmt_fetch_fetch_row
(
Stmt_fetch
*
fetch
)
{
int
rc
;
unsigned
i
;
DBUG_ENTER
(
"stmt_fetch_fetch_row"
);
if
((
rc
=
mysql_stmt_fetch
(
fetch
->
handle
))
==
0
)
{
++
fetch
->
row_count
;
if
(
!
opt_silent
)
printf
(
"Stmt %d fetched row %d:
\n
"
,
fetch
->
stmt_no
,
fetch
->
row_count
);
for
(
i
=
0
;
i
<
fetch
->
column_count
;
++
i
)
{
fetch
->
out_data
[
i
][
fetch
->
out_data_length
[
i
]]
=
'\0'
;
if
(
!
opt_silent
)
printf
(
"column %d: %s
\n
"
,
i
+
1
,
fetch
->
out_data
[
i
]);
}
}
else
fetch
->
is_open
=
FALSE
;
DBUG_RETURN
(
rc
);
}
void
stmt_fetch_close
(
Stmt_fetch
*
fetch
)
{
unsigned
i
;
DBUG_ENTER
(
"stmt_fetch_close"
);
for
(
i
=
0
;
i
<
fetch
->
column_count
;
++
i
)
free
(
fetch
->
out_data
[
i
]);
free
(
fetch
->
out_data
);
free
(
fetch
->
out_data_length
);
free
(
fetch
->
bind_array
);
mysql_stmt_close
(
fetch
->
handle
);
DBUG_VOID_RETURN
;
}
/*
For given array of queries, open query_count cursors and fetch
from them in simultaneous manner.
In case there was an error in one of the cursors, continue
reading from the rest.
*/
enum
fetch_type
{
USE_ROW_BY_ROW_FETCH
=
0
,
USE_STORE_RESULT
=
1
};
my_bool
fetch_n
(
const
char
**
query_list
,
unsigned
query_count
,
enum
fetch_type
fetch_type
)
{
unsigned
open_statements
=
query_count
;
int
rc
,
error_count
=
0
;
Stmt_fetch
*
fetch_array
=
(
Stmt_fetch
*
)
calloc
(
1
,
sizeof
(
Stmt_fetch
)
*
query_count
);
Stmt_fetch
*
fetch
;
DBUG_ENTER
(
"fetch_n"
);
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
{
/* Init will exit(1) in case of error */
stmt_fetch_init
(
fetch
,
fetch
-
fetch_array
,
query_list
[
fetch
-
fetch_array
]);
}
if
(
fetch_type
==
USE_STORE_RESULT
)
{
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
{
rc
=
mysql_stmt_store_result
(
fetch
->
handle
);
check_execute
(
fetch
->
handle
,
rc
);
}
}
while
(
open_statements
)
{
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
{
if
(
fetch
->
is_open
&&
(
rc
=
stmt_fetch_fetch_row
(
fetch
)))
{
open_statements
--
;
/*
We try to fetch from the rest of the statements in case of
error
*/
if
(
rc
!=
MYSQL_NO_DATA
)
{
fprintf
(
stderr
,
"Got error reading rows from statement %d,
\n
"
"query is: %s,
\n
"
"error message: %s"
,
(
int
)
(
fetch
-
fetch_array
),
fetch
->
query
,
mysql_stmt_error
(
fetch
->
handle
));
error_count
++
;
}
}
}
}
if
(
error_count
)
fprintf
(
stderr
,
"Fetch FAILED"
);
else
{
unsigned
total_row_count
=
0
;
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
total_row_count
+=
fetch
->
row_count
;
if
(
!
opt_silent
)
printf
(
"Success, total rows fetched: %d
\n
"
,
total_row_count
);
}
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
stmt_fetch_close
(
fetch
);
free
(
fetch_array
);
DBUG_RETURN
(
error_count
!=
0
);
}
/* Separate thread query to test some cases */
static
my_bool
thread_query
(
const
char
*
query
)
{
MYSQL
*
l_mysql
;
my_bool
error
;
error
=
0
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
in thread_query(%s)"
,
query
);
if
(
!
(
l_mysql
=
mysql_client_init
(
NULL
)))
{
myerror
(
"mysql_client_init() failed"
);
return
1
;
}
if
(
!
(
mysql_real_connect
(
l_mysql
,
opt_host
,
opt_user
,
opt_password
,
current_db
,
opt_port
,
opt_unix_socket
,
0
)))
{
myerror
(
"connection failed"
);
error
=
1
;
goto
end
;
}
l_mysql
->
reconnect
=
1
;
if
(
mysql_query
(
l_mysql
,
query
))
{
fprintf
(
stderr
,
"Query failed (%s)
\n
"
,
mysql_error
(
l_mysql
));
error
=
1
;
goto
end
;
}
mysql_commit
(
l_mysql
);
end:
mysql_close
(
l_mysql
);
return
error
;
}
/*
Read and parse arguments and MySQL options from my.cnf
*/
static
const
char
*
client_test_load_default_groups
[]
=
{
"client"
,
0
};
static
char
**
defaults_argv
;
static
struct
my_option
client_test_long_options
[]
=
{
{
"basedir"
,
'b'
,
"Basedir for tests."
,
&
opt_basedir
,
&
opt_basedir
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"count"
,
't'
,
"Number of times test to be executed"
,
&
opt_count
,
&
opt_count
,
0
,
GET_UINT
,
REQUIRED_ARG
,
1
,
0
,
0
,
0
,
0
,
0
},
{
"database"
,
'D'
,
"Database to use"
,
&
opt_db
,
&
opt_db
,
0
,
GET_STR_ALLOC
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"debug"
,
'#'
,
"Output debug log"
,
&
default_dbug_option
,
&
default_dbug_option
,
0
,
GET_STR
,
OPT_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"help"
,
'?'
,
"Display this help and exit"
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"host"
,
'h'
,
"Connect to host"
,
&
opt_host
,
&
opt_host
,
0
,
GET_STR_ALLOC
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"password"
,
'p'
,
"Password to use when connecting to server. If password is not given it's asked from the tty."
,
0
,
0
,
0
,
GET_STR
,
OPT_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"port"
,
'P'
,
"Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
"/etc/services, "
#endif
"built-in default ("
STRINGIFY_ARG
(
MYSQL_PORT
)
")."
,
&
opt_port
,
&
opt_port
,
0
,
GET_UINT
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"server-arg"
,
'A'
,
"Send embedded server this as a parameter."
,
0
,
0
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"show-tests"
,
'T'
,
"Show all tests' names"
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"silent"
,
's'
,
"Be more silent"
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#ifdef HAVE_SMEM
{
"shared-memory-base-name"
,
'm'
,
"Base name of shared memory."
,
&
shared_memory_base_name
,
(
uchar
**
)
&
shared_memory_base_name
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#endif
{
"socket"
,
'S'
,
"Socket file to use for connection"
,
&
opt_unix_socket
,
&
opt_unix_socket
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"testcase"
,
'c'
,
"May disable some code when runs as mysql-test-run testcase."
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#ifndef DONT_ALLOW_USER_CHANGE
{
"user"
,
'u'
,
"User for login if not current user"
,
&
opt_user
,
&
opt_user
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#endif
{
"vardir"
,
'v'
,
"Data dir for tests."
,
&
opt_vardir
,
&
opt_vardir
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"getopt-ll-test"
,
'g'
,
"Option for testing bug in getopt library"
,
&
opt_getopt_ll_test
,
&
opt_getopt_ll_test
,
0
,
GET_LL
,
REQUIRED_ARG
,
0
,
0
,
LONGLONG_MAX
,
0
,
0
,
0
},
{
"plugin_dir"
,
0
,
"Directory for client-side plugins."
,
&
opt_plugin_dir
,
&
opt_plugin_dir
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"default_auth"
,
0
,
"Default authentication client-side plugin to use."
,
&
opt_default_auth
,
&
opt_default_auth
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
0
,
0
,
0
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
}
};
static
void
usage
(
void
)
{
/* show the usage string when the user asks for this */
putc
(
'\n'
,
stdout
);
printf
(
"%s Ver %s Distrib %s, for %s (%s)
\n
"
,
my_progname
,
VER
,
MYSQL_SERVER_VERSION
,
SYSTEM_TYPE
,
MACHINE_TYPE
);
puts
(
"By Monty, Venu, Kent and others
\n
"
);
printf
(
"\
Copyright (C) 2002-2004 MySQL AB
\n
\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
\n
\
and you are welcome to modify and redistribute it under the GPL license
\n
"
);
printf
(
"Usage: %s [OPTIONS] [TESTNAME1 TESTNAME2...]
\n
"
,
my_progname
);
my_print_help
(
client_test_long_options
);
print_defaults
(
"my"
,
client_test_load_default_groups
);
my_print_variables
(
client_test_long_options
);
}
static
struct
my_tests_st
*
get_my_tests
();
/* To be defined in main .c file */
static
struct
my_tests_st
*
my_testlist
=
0
;
static
my_bool
get_one_option
(
int
optid
,
const
struct
my_option
*
opt
__attribute__
((
unused
)),
char
*
argument
)
{
switch
(
optid
)
{
case
'#'
:
DBUG_PUSH
(
argument
?
argument
:
default_dbug_option
);
break
;
case
'c'
:
opt_testcase
=
1
;
break
;
case
'p'
:
if
(
argument
)
{
char
*
start
=
argument
;
my_free
(
opt_password
);
opt_password
=
my_strdup
(
argument
,
MYF
(
MY_FAE
));
while
(
*
argument
)
*
argument
++=
'x'
;
/* Destroy argument */
if
(
*
start
)
start
[
1
]
=
0
;
}
else
tty_password
=
1
;
break
;
case
's'
:
if
(
argument
==
disabled_my_option
)
opt_silent
=
0
;
else
opt_silent
++
;
break
;
case
'A'
:
/*
When the embedded server is being tested, the test suite needs to be
able to pass command-line arguments to the embedded server so it can
locate the language files and data directory. The test suite
(mysql-test-run) never uses config files, just command-line options.
*/
if
(
!
embedded_server_arg_count
)
{
embedded_server_arg_count
=
1
;
embedded_server_args
[
0
]
=
(
char
*
)
""
;
}
if
(
embedded_server_arg_count
==
MAX_SERVER_ARGS
-
1
||
!
(
embedded_server_args
[
embedded_server_arg_count
++
]
=
my_strdup
(
argument
,
MYF
(
MY_FAE
))))
{
DIE
(
"Can't use server argument"
);
}
break
;
case
'T'
:
{
struct
my_tests_st
*
fptr
;
printf
(
"All possible test names:
\n\n
"
);
for
(
fptr
=
my_testlist
;
fptr
->
name
;
fptr
++
)
printf
(
"%s
\n
"
,
fptr
->
name
);
exit
(
0
);
break
;
}
case
'?'
:
case
'I'
:
/* Info */
usage
();
exit
(
0
);
break
;
}
return
0
;
}
static
void
get_options
(
int
*
argc
,
char
***
argv
)
{
int
ho_error
;
if
((
ho_error
=
handle_options
(
argc
,
argv
,
client_test_long_options
,
get_one_option
)))
exit
(
ho_error
);
if
(
tty_password
)
opt_password
=
get_tty_password
(
NullS
);
return
;
}
/*
Print the test output on successful execution before exiting
*/
static
void
print_test_output
()
{
if
(
opt_silent
<
3
)
{
fprintf
(
stdout
,
"
\n\n
"
);
fprintf
(
stdout
,
"All '%d' tests were successful (in '%d' iterations)"
,
test_count
-
1
,
opt_count
);
fprintf
(
stdout
,
"
\n
Total execution time: %g SECS"
,
total_time
);
if
(
opt_count
>
1
)
fprintf
(
stdout
,
" (Avg: %g SECS)"
,
total_time
/
opt_count
);
fprintf
(
stdout
,
"
\n\n
!!! SUCCESS !!!
\n
"
);
}
}
/***************************************************************************
main routine
***************************************************************************/
int
main
(
int
argc
,
char
**
argv
)
{
struct
my_tests_st
*
fptr
;
my_testlist
=
get_my_tests
();
MY_INIT
(
argv
[
0
]);
if
(
load_defaults
(
"my"
,
client_test_load_default_groups
,
&
argc
,
&
argv
))
exit
(
1
);
defaults_argv
=
argv
;
get_options
(
&
argc
,
&
argv
);
if
(
mysql_server_init
(
embedded_server_arg_count
,
embedded_server_args
,
(
char
**
)
embedded_server_groups
))
DIE
(
"Can't initialize MySQL server"
);
/* connect to server with no flags, default protocol, auto reconnect true */
mysql
=
client_connect
(
0
,
MYSQL_PROTOCOL_DEFAULT
,
1
);
total_time
=
0
;
for
(
iter_count
=
1
;
iter_count
<=
opt_count
;
iter_count
++
)
{
/* Start of tests */
test_count
=
1
;
start_time
=
time
((
time_t
*
)
0
);
if
(
!
argc
)
{
for
(
fptr
=
my_testlist
;
fptr
->
name
;
fptr
++
)
(
*
fptr
->
function
)();
}
else
{
for
(
;
*
argv
;
argv
++
)
{
for
(
fptr
=
my_testlist
;
fptr
->
name
;
fptr
++
)
{
if
(
!
strcmp
(
fptr
->
name
,
*
argv
))
{
(
*
fptr
->
function
)();
break
;
}
}
if
(
!
fptr
->
name
)
{
fprintf
(
stderr
,
"
\n\n
Given test not found: '%s'
\n
"
,
*
argv
);
fprintf
(
stderr
,
"See legal test names with %s -T
\n\n
Aborting!
\n
"
,
my_progname
);
client_disconnect
(
mysql
,
1
);
free_defaults
(
defaults_argv
);
exit
(
1
);
}
}
}
end_time
=
time
((
time_t
*
)
0
);
total_time
+=
difftime
(
end_time
,
start_time
);
/* End of tests */
}
client_disconnect
(
mysql
,
1
);
/* disconnect from server */
free_defaults
(
defaults_argv
);
print_test_output
();
while
(
embedded_server_arg_count
>
1
)
my_free
(
embedded_server_args
[
--
embedded_server_arg_count
]);
mysql_server_end
();
my_end
(
0
);
exit
(
0
);
}
tests/mysql_client_test.c
View file @
f4dc9215
/* Copyright (c) 2002, 201
1
, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2002, 201
2
, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -26,923 +26,57 @@
*/
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <errmsg.h>
#include <my_getopt.h>
#include <m_string.h>
#include <mysqld_error.h>
#include <sql_common.h>
#include <mysql/client_plugin.h>
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300
/* MAX QUERY BUFFER LENGTH */
#define MAX_KEY MAX_INDEXES
#define MAX_SERVER_ARGS 64
/* set default options */
static
int
opt_testcase
=
0
;
static
char
*
opt_db
=
0
;
static
char
*
opt_user
=
0
;
static
char
*
opt_password
=
0
;
static
char
*
opt_host
=
0
;
static
char
*
opt_unix_socket
=
0
;
#ifdef HAVE_SMEM
static
char
*
shared_memory_base_name
=
0
;
#endif
static
unsigned
int
opt_port
;
static
my_bool
tty_password
=
0
,
opt_silent
=
0
;
static
MYSQL
*
mysql
=
0
;
static
char
current_db
[]
=
"client_test_db"
;
static
unsigned
int
test_count
=
0
;
static
unsigned
int
opt_count
=
0
;
static
unsigned
int
iter_count
=
0
;
static
my_bool
have_innodb
=
FALSE
;
static
char
*
opt_plugin_dir
=
0
,
*
opt_default_auth
=
0
;
static
const
char
*
opt_basedir
=
"./"
;
static
const
char
*
opt_vardir
=
"mysql-test/var"
;
static
longlong
opt_getopt_ll_test
=
0
;
static
int
embedded_server_arg_count
=
0
;
static
char
*
embedded_server_args
[
MAX_SERVER_ARGS
];
static
const
char
*
embedded_server_groups
[]
=
{
"server"
,
"embedded"
,
"mysql_client_test_SERVER"
,
NullS
};
static
time_t
start_time
,
end_time
;
static
double
total_time
;
const
char
*
default_dbug_option
=
"d:t:o,/tmp/mysql_client_test.trace"
;
struct
my_tests_st
{
const
char
*
name
;
void
(
*
function
)();
};
#define myheader(str) \
DBUG_PRINT("test", ("name: %s", str)); \
if (opt_silent < 2) \
{ \
fprintf(stdout, "\n\n#####################################\n"); \
fprintf(stdout, "%u of (%u/%u): %s", test_count++, iter_count, \
opt_count, str); \
fprintf(stdout, " \n#####################################\n"); \
}
#define myheader_r(str) \
DBUG_PRINT("test", ("name: %s", str)); \
if (!opt_silent) \
{ \
fprintf(stdout, "\n\n#####################################\n"); \
fprintf(stdout, "%s", str); \
fprintf(stdout, " \n#####################################\n"); \
}
static
void
print_error
(
const
char
*
msg
);
static
void
print_st_error
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
);
static
void
client_disconnect
(
MYSQL
*
mysql
,
my_bool
drop_db
);
/*
Abort unless given experssion is non-zero.
SYNOPSIS
DIE_UNLESS(expr)
DESCRIPTION
We can't use any kind of system assert as we need to
preserve tested invariants in release builds as well.
*/
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
#define DIE_IF(expr) \
((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0))
#define DIE(expr) \
die(__FILE__, __LINE__, #expr)
static
void
die
(
const
char
*
file
,
int
line
,
const
char
*
expr
)
{
fflush
(
stdout
);
fprintf
(
stderr
,
"%s:%d: check failed: '%s'
\n
"
,
file
,
line
,
expr
);
fflush
(
stderr
);
exit
(
1
);
}
#define myerror(msg) print_error(msg)
#define mysterror(stmt, msg) print_st_error(stmt, msg)
#define myquery(RES) \
{ \
int r= (RES); \
if (r) \
myerror(NULL); \
DIE_UNLESS(r == 0); \
}
#define myquery_r(r) \
{ \
if (r) \
myerror(NULL); \
DIE_UNLESS(r != 0); \
}
#define check_execute(stmt, r) \
{ \
if (r) \
mysterror(stmt, NULL); \
DIE_UNLESS(r == 0);\
}
#define check_execute_r(stmt, r) \
{ \
if (r) \
mysterror(stmt, NULL); \
DIE_UNLESS(r != 0);\
}
#define check_stmt(stmt) \
{ \
if ( stmt == 0) \
myerror(NULL); \
DIE_UNLESS(stmt != 0); \
}
#define check_stmt_r(stmt) \
{ \
if (stmt == 0) \
myerror(NULL);\
DIE_UNLESS(stmt == 0);\
}
#define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);}
#define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);}
/* A workaround for Sun Forte 5.6 on Solaris x86 */
static
int
cmp_double
(
double
*
a
,
double
*
b
)
{
return
*
a
==
*
b
;
}
/* Print the error message */
static
void
print_error
(
const
char
*
msg
)
{
if
(
!
opt_silent
)
{
if
(
mysql
&&
mysql_errno
(
mysql
))
{
if
(
mysql
->
server_version
)
fprintf
(
stdout
,
"
\n
[MySQL-%s]"
,
mysql
->
server_version
);
else
fprintf
(
stdout
,
"
\n
[MySQL]"
);
fprintf
(
stdout
,
"[%d] %s
\n
"
,
mysql_errno
(
mysql
),
mysql_error
(
mysql
));
}
else
if
(
msg
)
fprintf
(
stderr
,
" [MySQL] %s
\n
"
,
msg
);
}
}
static
void
print_st_error
(
MYSQL_STMT
*
stmt
,
const
char
*
msg
)
{
if
(
!
opt_silent
)
{
if
(
stmt
&&
mysql_stmt_errno
(
stmt
))
{
if
(
stmt
->
mysql
&&
stmt
->
mysql
->
server_version
)
fprintf
(
stdout
,
"
\n
[MySQL-%s]"
,
stmt
->
mysql
->
server_version
);
else
fprintf
(
stdout
,
"
\n
[MySQL]"
);
fprintf
(
stdout
,
"[%d] %s
\n
"
,
mysql_stmt_errno
(
stmt
),
mysql_stmt_error
(
stmt
));
}
else
if
(
msg
)
fprintf
(
stderr
,
" [MySQL] %s
\n
"
,
msg
);
}
}
/*
Enhanced version of mysql_client_init(), which may also set shared memory
base on Windows.
*/
static
MYSQL
*
mysql_client_init
(
MYSQL
*
con
)
{
MYSQL
*
res
=
mysql_init
(
con
);
#ifdef HAVE_SMEM
if
(
res
&&
shared_memory_base_name
)
mysql_options
(
res
,
MYSQL_SHARED_MEMORY_BASE_NAME
,
shared_memory_base_name
);
#endif
if
(
opt_plugin_dir
&&
*
opt_plugin_dir
)
mysql_options
(
res
,
MYSQL_PLUGIN_DIR
,
opt_plugin_dir
);
if
(
opt_default_auth
&&
*
opt_default_auth
)
mysql_options
(
res
,
MYSQL_DEFAULT_AUTH
,
opt_default_auth
);
return
res
;
}
/*
Disable direct calls of mysql_init, as it disregards shared memory base.
*/
#define mysql_init(A) Please use mysql_client_init instead of mysql_init
/* Check if the connection has InnoDB tables */
static
my_bool
check_have_innodb
(
MYSQL
*
conn
)
{
MYSQL_RES
*
res
;
MYSQL_ROW
row
;
int
rc
;
my_bool
result
;
rc
=
mysql_query
(
conn
,
"show variables like 'have_innodb'"
);
myquery
(
rc
);
res
=
mysql_use_result
(
conn
);
DIE_UNLESS
(
res
);
row
=
mysql_fetch_row
(
res
);
DIE_UNLESS
(
row
);
result
=
strcmp
(
row
[
1
],
"YES"
)
==
0
;
mysql_free_result
(
res
);
return
result
;
}
/*
This is to be what mysql_query() is for mysql_real_query(), for
mysql_simple_prepare(): a variant without the 'length' parameter.
*/
static
MYSQL_STMT
*
STDCALL
mysql_simple_prepare
(
MYSQL
*
mysql_arg
,
const
char
*
query
)
{
MYSQL_STMT
*
stmt
=
mysql_stmt_init
(
mysql_arg
);
if
(
stmt
&&
mysql_stmt_prepare
(
stmt
,
query
,
(
uint
)
strlen
(
query
)))
{
mysql_stmt_close
(
stmt
);
return
0
;
}
return
stmt
;
}
/**
Connect to the server with options given by arguments to this application,
stored in global variables opt_host, opt_user, opt_password, opt_db,
opt_port and opt_unix_socket.
@param flag[in] client_flag passed on to mysql_real_connect
@param protocol[in] MYSQL_PROTOCOL_* to use for this connection
@param auto_reconnect[in] set to 1 for auto reconnect
@return pointer to initialized and connected MYSQL object
*/
static
MYSQL
*
client_connect
(
ulong
flag
,
uint
protocol
,
my_bool
auto_reconnect
)
{
MYSQL
*
mysql
;
int
rc
;
static
char
query
[
MAX_TEST_QUERY_LENGTH
];
myheader_r
(
"client_connect"
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
Establishing a connection to '%s' ..."
,
opt_host
?
opt_host
:
""
);
if
(
!
(
mysql
=
mysql_client_init
(
NULL
)))
{
opt_silent
=
0
;
myerror
(
"mysql_client_init() failed"
);
exit
(
1
);
}
/* enable local infile, in non-binary builds often disabled by default */
mysql_options
(
mysql
,
MYSQL_OPT_LOCAL_INFILE
,
0
);
mysql_options
(
mysql
,
MYSQL_OPT_PROTOCOL
,
&
protocol
);
if
(
opt_plugin_dir
&&
*
opt_plugin_dir
)
mysql_options
(
mysql
,
MYSQL_PLUGIN_DIR
,
opt_plugin_dir
);
if
(
opt_default_auth
&&
*
opt_default_auth
)
mysql_options
(
mysql
,
MYSQL_DEFAULT_AUTH
,
opt_default_auth
);
if
(
!
(
mysql_real_connect
(
mysql
,
opt_host
,
opt_user
,
opt_password
,
opt_db
?
opt_db
:
"test"
,
opt_port
,
opt_unix_socket
,
flag
)))
{
opt_silent
=
0
;
myerror
(
"connection failed"
);
mysql_close
(
mysql
);
fprintf
(
stdout
,
"
\n
Check the connection options using --help or -?
\n
"
);
exit
(
1
);
}
mysql
->
reconnect
=
auto_reconnect
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK"
);
/* set AUTOCOMMIT to ON*/
mysql_autocommit
(
mysql
,
TRUE
);
if
(
!
opt_silent
)
{
fprintf
(
stdout
,
"
\n
Connected to MySQL server version: %s (%lu)
\n
"
,
mysql_get_server_info
(
mysql
),
(
ulong
)
mysql_get_server_version
(
mysql
));
fprintf
(
stdout
,
"
\n
Creating a test database '%s' ..."
,
current_db
);
}
strxmov
(
query
,
"CREATE DATABASE IF NOT EXISTS "
,
current_db
,
NullS
);
rc
=
mysql_query
(
mysql
,
query
);
myquery
(
rc
);
strxmov
(
query
,
"USE "
,
current_db
,
NullS
);
rc
=
mysql_query
(
mysql
,
query
);
myquery
(
rc
);
have_innodb
=
check_have_innodb
(
mysql
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK"
);
return
mysql
;
}
/* Close the connection */
static
void
client_disconnect
(
MYSQL
*
mysql
,
my_bool
drop_db
)
{
static
char
query
[
MAX_TEST_QUERY_LENGTH
];
myheader_r
(
"client_disconnect"
);
if
(
mysql
)
{
if
(
drop_db
)
{
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
dropping the test database '%s' ..."
,
current_db
);
strxmov
(
query
,
"DROP DATABASE IF EXISTS "
,
current_db
,
NullS
);
mysql_query
(
mysql
,
query
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK"
);
}
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
closing the connection ..."
);
mysql_close
(
mysql
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"OK
\n
"
);
}
}
/* Query processing */
static
void
client_query
()
{
int
rc
;
myheader
(
"client_query"
);
rc
=
mysql_query
(
mysql
,
"DROP TABLE IF EXISTS t1"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"CREATE TABLE t1("
"id int primary key auto_increment, "
"name varchar(20))"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"CREATE TABLE t1(id int, name varchar(20))"
);
myquery_r
(
rc
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('mysql')"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('monty')"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('venu')"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('deleted')"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('deleted')"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"UPDATE t1 SET name= 'updated' "
"WHERE name= 'deleted'"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"UPDATE t1 SET id= 3 WHERE name= 'updated'"
);
myquery_r
(
rc
);
myquery
(
mysql_query
(
mysql
,
"drop table t1"
));
}
/* Print dashes */
static
void
my_print_dashes
(
MYSQL_RES
*
result
)
{
MYSQL_FIELD
*
field
;
unsigned
int
i
,
j
;
mysql_field_seek
(
result
,
0
);
fputc
(
'\t'
,
stdout
);
fputc
(
'+'
,
stdout
);
for
(
i
=
0
;
i
<
mysql_num_fields
(
result
);
i
++
)
{
field
=
mysql_fetch_field
(
result
);
for
(
j
=
0
;
j
<
field
->
max_length
+
2
;
j
++
)
fputc
(
'-'
,
stdout
);
fputc
(
'+'
,
stdout
);
}
fputc
(
'\n'
,
stdout
);
}
/* Print resultset metadata information */
static
void
my_print_result_metadata
(
MYSQL_RES
*
result
)
{
MYSQL_FIELD
*
field
;
unsigned
int
i
,
j
;
unsigned
int
field_count
;
mysql_field_seek
(
result
,
0
);
if
(
!
opt_silent
)
{
fputc
(
'\n'
,
stdout
);
fputc
(
'\n'
,
stdout
);
}
field_count
=
mysql_num_fields
(
result
);
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
field
=
mysql_fetch_field
(
result
);
j
=
strlen
(
field
->
name
);
if
(
j
<
field
->
max_length
)
j
=
field
->
max_length
;
if
(
j
<
4
&&
!
IS_NOT_NULL
(
field
->
flags
))
j
=
4
;
field
->
max_length
=
j
;
}
if
(
!
opt_silent
)
{
my_print_dashes
(
result
);
fputc
(
'\t'
,
stdout
);
fputc
(
'|'
,
stdout
);
}
mysql_field_seek
(
result
,
0
);
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
field
=
mysql_fetch_field
(
result
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
field
->
name
);
}
if
(
!
opt_silent
)
{
fputc
(
'\n'
,
stdout
);
my_print_dashes
(
result
);
}
}
/* Process the result set */
static
int
my_process_result_set
(
MYSQL_RES
*
result
)
{
MYSQL_ROW
row
;
MYSQL_FIELD
*
field
;
unsigned
int
i
;
unsigned
int
row_count
=
0
;
if
(
!
result
)
return
0
;
my_print_result_metadata
(
result
);
while
((
row
=
mysql_fetch_row
(
result
))
!=
NULL
)
{
mysql_field_seek
(
result
,
0
);
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'|'
,
stdout
);
}
for
(
i
=
0
;
i
<
mysql_num_fields
(
result
);
i
++
)
{
field
=
mysql_fetch_field
(
result
);
if
(
!
opt_silent
)
{
if
(
row
[
i
]
==
NULL
)
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
"NULL"
);
else
if
(
IS_NUM
(
field
->
type
))
fprintf
(
stdout
,
" %*s |"
,
(
int
)
field
->
max_length
,
row
[
i
]);
else
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
row
[
i
]);
}
}
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'\n'
,
stdout
);
}
row_count
++
;
}
if
(
!
opt_silent
)
{
if
(
row_count
)
my_print_dashes
(
result
);
if
(
mysql_errno
(
mysql
)
!=
0
)
fprintf
(
stderr
,
"
\n\t
mysql_fetch_row() failed
\n
"
);
else
fprintf
(
stdout
,
"
\n\t
%d %s returned
\n
"
,
row_count
,
row_count
==
1
?
"row"
:
"rows"
);
}
return
row_count
;
}
static
int
my_process_result
(
MYSQL
*
mysql_arg
)
{
MYSQL_RES
*
result
;
int
row_count
;
if
(
!
(
result
=
mysql_store_result
(
mysql_arg
)))
return
0
;
row_count
=
my_process_result_set
(
result
);
mysql_free_result
(
result
);
return
row_count
;
}
/* Process the statement result set */
#define MAX_RES_FIELDS 50
#define MAX_FIELD_DATA_SIZE 255
static
int
my_process_stmt_result
(
MYSQL_STMT
*
stmt
)
{
int
field_count
;
int
row_count
=
0
;
MYSQL_BIND
buffer
[
MAX_RES_FIELDS
];
MYSQL_FIELD
*
field
;
MYSQL_RES
*
result
;
char
data
[
MAX_RES_FIELDS
][
MAX_FIELD_DATA_SIZE
];
ulong
length
[
MAX_RES_FIELDS
];
my_bool
is_null
[
MAX_RES_FIELDS
];
int
rc
,
i
;
if
(
!
(
result
=
mysql_stmt_result_metadata
(
stmt
)))
/* No meta info */
{
while
(
!
mysql_stmt_fetch
(
stmt
))
row_count
++
;
return
row_count
;
}
field_count
=
min
(
mysql_num_fields
(
result
),
MAX_RES_FIELDS
);
bzero
((
char
*
)
buffer
,
sizeof
(
buffer
));
bzero
((
char
*
)
length
,
sizeof
(
length
));
bzero
((
char
*
)
is_null
,
sizeof
(
is_null
));
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
buffer
[
i
].
buffer_type
=
MYSQL_TYPE_STRING
;
buffer
[
i
].
buffer_length
=
MAX_FIELD_DATA_SIZE
;
buffer
[
i
].
length
=
&
length
[
i
];
buffer
[
i
].
buffer
=
(
void
*
)
data
[
i
];
buffer
[
i
].
is_null
=
&
is_null
[
i
];
}
rc
=
mysql_stmt_bind_result
(
stmt
,
buffer
);
check_execute
(
stmt
,
rc
);
rc
=
1
;
mysql_stmt_attr_set
(
stmt
,
STMT_ATTR_UPDATE_MAX_LENGTH
,
(
void
*
)
&
rc
);
rc
=
mysql_stmt_store_result
(
stmt
);
check_execute
(
stmt
,
rc
);
my_print_result_metadata
(
result
);
mysql_field_seek
(
result
,
0
);
while
((
rc
=
mysql_stmt_fetch
(
stmt
))
==
0
)
{
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'|'
,
stdout
);
}
mysql_field_seek
(
result
,
0
);
for
(
i
=
0
;
i
<
field_count
;
i
++
)
{
field
=
mysql_fetch_field
(
result
);
if
(
!
opt_silent
)
{
if
(
is_null
[
i
])
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
"NULL"
);
else
if
(
length
[
i
]
==
0
)
{
data
[
i
][
0
]
=
'\0'
;
/* unmodified buffer */
fprintf
(
stdout
,
" %*s |"
,
(
int
)
field
->
max_length
,
data
[
i
]);
}
else
if
(
IS_NUM
(
field
->
type
))
fprintf
(
stdout
,
" %*s |"
,
(
int
)
field
->
max_length
,
data
[
i
]);
else
fprintf
(
stdout
,
" %-*s |"
,
(
int
)
field
->
max_length
,
data
[
i
]);
}
}
if
(
!
opt_silent
)
{
fputc
(
'\t'
,
stdout
);
fputc
(
'\n'
,
stdout
);
}
row_count
++
;
}
DIE_UNLESS
(
rc
==
MYSQL_NO_DATA
);
if
(
!
opt_silent
)
{
if
(
row_count
)
my_print_dashes
(
result
);
fprintf
(
stdout
,
"
\n\t
%d %s returned
\n
"
,
row_count
,
row_count
==
1
?
"row"
:
"rows"
);
}
mysql_free_result
(
result
);
return
row_count
;
}
/* Prepare statement, execute, and process result set for given query */
int
my_stmt_result
(
const
char
*
buff
)
{
MYSQL_STMT
*
stmt
;
int
row_count
;
int
rc
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n\n
%s"
,
buff
);
stmt
=
mysql_simple_prepare
(
mysql
,
buff
);
check_stmt
(
stmt
);
rc
=
mysql_stmt_execute
(
stmt
);
check_execute
(
stmt
,
rc
);
row_count
=
my_process_stmt_result
(
stmt
);
mysql_stmt_close
(
stmt
);
return
row_count
;
}
/* Print the total number of warnings and the warnings themselves. */
void
my_process_warnings
(
MYSQL
*
conn
,
unsigned
expected_warning_count
)
{
MYSQL_RES
*
result
;
int
rc
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total warnings: %u (expected: %u)
\n
"
,
mysql_warning_count
(
conn
),
expected_warning_count
);
DIE_UNLESS
(
mysql_warning_count
(
mysql
)
==
expected_warning_count
);
rc
=
mysql_query
(
conn
,
"SHOW WARNINGS"
);
DIE_UNLESS
(
rc
==
0
);
result
=
mysql_store_result
(
conn
);
mytest
(
result
);
rc
=
my_process_result_set
(
result
);
mysql_free_result
(
result
);
}
/* Utility function to verify a particular column data */
static
void
verify_col_data
(
const
char
*
table
,
const
char
*
col
,
const
char
*
exp_data
)
{
static
char
query
[
MAX_TEST_QUERY_LENGTH
];
MYSQL_RES
*
result
;
MYSQL_ROW
row
;
int
rc
,
field
=
1
;
if
(
table
&&
col
)
{
strxmov
(
query
,
"SELECT "
,
col
,
" FROM "
,
table
,
" LIMIT 1"
,
NullS
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
%s"
,
query
);
rc
=
mysql_query
(
mysql
,
query
);
myquery
(
rc
);
field
=
0
;
}
result
=
mysql_use_result
(
mysql
);
mytest
(
result
);
if
(
!
(
row
=
mysql_fetch_row
(
result
))
||
!
row
[
field
])
{
fprintf
(
stdout
,
"
\n
*** ERROR: FAILED TO GET THE RESULT ***"
);
exit
(
1
);
}
if
(
strcmp
(
row
[
field
],
exp_data
))
{
fprintf
(
stdout
,
"
\n
obtained: `%s` (expected: `%s`)"
,
row
[
field
],
exp_data
);
DIE_UNLESS
(
FALSE
);
}
mysql_free_result
(
result
);
}
/* Utility function to verify the field members */
#define verify_prepare_field(result,no,name,org_name,type,table,\
org_table,db,length,def) \
do_verify_prepare_field((result),(no),(name),(org_name),(type), \
(table),(org_table),(db),(length),(def), \
__FILE__, __LINE__)
static
void
do_verify_prepare_field
(
MYSQL_RES
*
result
,
unsigned
int
no
,
const
char
*
name
,
const
char
*
org_name
,
enum
enum_field_types
type
,
const
char
*
table
,
const
char
*
org_table
,
const
char
*
db
,
unsigned
long
length
,
const
char
*
def
,
const
char
*
file
,
int
line
)
{
MYSQL_FIELD
*
field
;
CHARSET_INFO
*
cs
;
ulonglong
expected_field_length
;
if
(
!
(
field
=
mysql_fetch_field_direct
(
result
,
no
)))
{
fprintf
(
stdout
,
"
\n
*** ERROR: FAILED TO GET THE RESULT ***"
);
exit
(
1
);
}
cs
=
get_charset
(
field
->
charsetnr
,
0
);
DIE_UNLESS
(
cs
);
if
((
expected_field_length
=
length
*
cs
->
mbmaxlen
)
>
UINT_MAX32
)
expected_field_length
=
UINT_MAX32
;
if
(
!
opt_silent
)
{
fprintf
(
stdout
,
"
\n
field[%d]:"
,
no
);
fprintf
(
stdout
,
"
\n
name :`%s`
\t
(expected: `%s`)"
,
field
->
name
,
name
);
fprintf
(
stdout
,
"
\n
org_name :`%s`
\t
(expected: `%s`)"
,
field
->
org_name
,
org_name
);
fprintf
(
stdout
,
"
\n
type :`%d`
\t
(expected: `%d`)"
,
field
->
type
,
type
);
if
(
table
)
fprintf
(
stdout
,
"
\n
table :`%s`
\t
(expected: `%s`)"
,
field
->
table
,
table
);
if
(
org_table
)
fprintf
(
stdout
,
"
\n
org_table:`%s`
\t
(expected: `%s`)"
,
field
->
org_table
,
org_table
);
fprintf
(
stdout
,
"
\n
database :`%s`
\t
(expected: `%s`)"
,
field
->
db
,
db
);
fprintf
(
stdout
,
"
\n
length :`%lu`
\t
(expected: `%llu`)"
,
field
->
length
,
expected_field_length
);
fprintf
(
stdout
,
"
\n
maxlength:`%ld`"
,
field
->
max_length
);
fprintf
(
stdout
,
"
\n
charsetnr:`%d`"
,
field
->
charsetnr
);
fprintf
(
stdout
,
"
\n
default :`%s`
\t
(expected: `%s`)"
,
field
->
def
?
field
->
def
:
"(null)"
,
def
?
def
:
"(null)"
);
fprintf
(
stdout
,
"
\n
"
);
}
DIE_UNLESS
(
strcmp
(
field
->
name
,
name
)
==
0
);
DIE_UNLESS
(
strcmp
(
field
->
org_name
,
org_name
)
==
0
);
/*
XXX: silent column specification change works based on number of
bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even
for CHAR(2) column if its character set is multibyte.
VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would
expect.
*/
if
(
cs
->
mbmaxlen
==
1
)
{
if
(
field
->
type
!=
type
)
{
fprintf
(
stderr
,
"Expected field type: %d, got type: %d in file %s, line %d
\n
"
,
(
int
)
type
,
(
int
)
field
->
type
,
file
,
line
);
DIE_UNLESS
(
field
->
type
==
type
);
}
}
if
(
table
)
DIE_UNLESS
(
strcmp
(
field
->
table
,
table
)
==
0
);
if
(
org_table
)
DIE_UNLESS
(
strcmp
(
field
->
org_table
,
org_table
)
==
0
);
DIE_UNLESS
(
strcmp
(
field
->
db
,
db
)
==
0
);
/*
Character set should be taken into account for multibyte encodings, such
as utf8. Field length is calculated as number of characters * maximum
number of bytes a character can occupy.
*/
if
(
length
&&
(
field
->
length
!=
expected_field_length
))
{
fprintf
(
stderr
,
"Expected field length: %llu, got length: %lu
\n
"
,
expected_field_length
,
field
->
length
);
DIE_UNLESS
(
field
->
length
==
expected_field_length
);
}
if
(
def
)
DIE_UNLESS
(
strcmp
(
field
->
def
,
def
)
==
0
);
}
/* Utility function to verify the parameter count */
static
void
verify_param_count
(
MYSQL_STMT
*
stmt
,
long
exp_count
)
{
long
param_count
=
mysql_stmt_param_count
(
stmt
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total parameters in stmt: `%ld` (expected: `%ld`)"
,
param_count
,
exp_count
);
DIE_UNLESS
(
param_count
==
exp_count
);
}
/*
The fw.c file includes all the mysql_client_test framework; this file
contains only the actual tests, plus the list of test functions to call.
*/
#include "mysql_client_fw.c"
/*
Utility function to verify the total affected rows
*/
/*
Query processing
*/
static
void
verify_st_affected_rows
(
MYSQL_STMT
*
stmt
,
ulonglong
exp_count
)
static
void
client_query
(
)
{
ulonglong
affected_rows
=
mysql_stmt_affected_rows
(
stmt
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total affected rows: `%ld` (expected: `%ld`)"
,
(
long
)
affected_rows
,
(
long
)
exp_count
);
DIE_UNLESS
(
affected_rows
==
exp_count
);
}
int
rc
;
/* Utility function to verify the total affected rows */
myheader
(
"client_query"
);
static
void
verify_affected_rows
(
ulonglong
exp_count
)
{
ulonglong
affected_rows
=
mysql_affected_rows
(
mysql
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total affected rows: `%ld` (expected: `%ld`)"
,
(
long
)
affected_rows
,
(
long
)
exp_count
);
DIE_UNLESS
(
affected_rows
==
exp_count
);
}
rc
=
mysql_query
(
mysql
,
"DROP TABLE IF EXISTS t1"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"CREATE TABLE t1("
"id int primary key auto_increment, "
"name varchar(20))"
);
myquery
(
rc
);
/* Utility function to verify the total fields count */
rc
=
mysql_query
(
mysql
,
"CREATE TABLE t1(id int, name varchar(20))"
);
myquery_r
(
rc
);
static
void
verify_field_count
(
MYSQL_RES
*
result
,
uint
exp_count
)
{
uint
field_count
=
mysql_num_fields
(
result
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total fields in the result set: `%d` (expected: `%d`)"
,
field_count
,
exp_count
);
DIE_UNLESS
(
field_count
==
exp_count
);
}
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('mysql')"
);
myquery
(
rc
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('monty')"
);
myquery
(
rc
);
/* Utility function to execute a query using prepare-execute */
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('venu')"
);
myquery
(
rc
);
#ifndef EMBEDDED_LIBRARY
static
void
execute_prepare_query
(
const
char
*
query
,
ulonglong
exp_count
)
{
MYSQL_STMT
*
stmt
;
ulonglong
affected_rows
;
int
rc
;
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('deleted')"
);
myquery
(
rc
);
stmt
=
mysql_simple_prepare
(
mysql
,
query
);
check_stmt
(
stmt
);
rc
=
mysql_query
(
mysql
,
"INSERT INTO t1(name) VALUES('deleted')"
);
myquery
(
rc
);
rc
=
mysql_stmt_execute
(
stmt
);
rc
=
mysql_query
(
mysql
,
"UPDATE t1 SET name= 'updated' "
"WHERE name= 'deleted'"
);
myquery
(
rc
);
affected_rows
=
mysql_stmt_affected_rows
(
stmt
);
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
total affected rows: `%ld` (expected: `%ld`)"
,
(
long
)
affected_rows
,
(
long
)
exp_count
);
rc
=
mysql_query
(
mysql
,
"UPDATE t1 SET id= 3 WHERE name= 'updated'"
);
myquery_r
(
rc
);
DIE_UNLESS
(
affected_rows
==
exp_count
);
mysql_stmt_close
(
stmt
);
myquery
(
mysql_query
(
mysql
,
"drop table t1"
));
}
#endif
/* Store result processing */
...
...
@@ -985,267 +119,6 @@ static void client_use_result()
}
/*
Accepts arbitrary number of queries and runs them against the database.
Used to fill tables for each test.
*/
void
fill_tables
(
const
char
**
query_list
,
unsigned
query_count
)
{
int
rc
;
const
char
**
query
;
DBUG_ENTER
(
"fill_tables"
);
for
(
query
=
query_list
;
query
<
query_list
+
query_count
;
++
query
)
{
rc
=
mysql_query
(
mysql
,
*
query
);
myquery
(
rc
);
}
DBUG_VOID_RETURN
;
}
/*
All state of fetch from one statement: statement handle, out buffers,
fetch position.
See fetch_n for for the only use case.
*/
enum
{
MAX_COLUMN_LENGTH
=
255
};
typedef
struct
st_stmt_fetch
{
const
char
*
query
;
unsigned
stmt_no
;
MYSQL_STMT
*
handle
;
my_bool
is_open
;
MYSQL_BIND
*
bind_array
;
char
**
out_data
;
unsigned
long
*
out_data_length
;
unsigned
column_count
;
unsigned
row_count
;
}
Stmt_fetch
;
/*
Create statement handle, prepare it with statement, execute and allocate
fetch buffers.
*/
void
stmt_fetch_init
(
Stmt_fetch
*
fetch
,
unsigned
stmt_no_arg
,
const
char
*
query_arg
)
{
unsigned
long
type
=
CURSOR_TYPE_READ_ONLY
;
int
rc
;
unsigned
i
;
MYSQL_RES
*
metadata
;
DBUG_ENTER
(
"stmt_fetch_init"
);
/* Save query and statement number for error messages */
fetch
->
stmt_no
=
stmt_no_arg
;
fetch
->
query
=
query_arg
;
fetch
->
handle
=
mysql_stmt_init
(
mysql
);
rc
=
mysql_stmt_prepare
(
fetch
->
handle
,
fetch
->
query
,
strlen
(
fetch
->
query
));
check_execute
(
fetch
->
handle
,
rc
);
/*
The attribute is sent to server on execute and asks to open read-only
for result set
*/
mysql_stmt_attr_set
(
fetch
->
handle
,
STMT_ATTR_CURSOR_TYPE
,
(
const
void
*
)
&
type
);
rc
=
mysql_stmt_execute
(
fetch
->
handle
);
check_execute
(
fetch
->
handle
,
rc
);
/* Find out total number of columns in result set */
metadata
=
mysql_stmt_result_metadata
(
fetch
->
handle
);
fetch
->
column_count
=
mysql_num_fields
(
metadata
);
mysql_free_result
(
metadata
);
/*
Now allocate bind handles and buffers for output data:
calloc memory to reduce number of MYSQL_BIND members we need to
set up.
*/
fetch
->
bind_array
=
(
MYSQL_BIND
*
)
calloc
(
1
,
sizeof
(
MYSQL_BIND
)
*
fetch
->
column_count
);
fetch
->
out_data
=
(
char
**
)
calloc
(
1
,
sizeof
(
char
*
)
*
fetch
->
column_count
);
fetch
->
out_data_length
=
(
ulong
*
)
calloc
(
1
,
sizeof
(
ulong
)
*
fetch
->
column_count
);
for
(
i
=
0
;
i
<
fetch
->
column_count
;
++
i
)
{
fetch
->
out_data
[
i
]
=
(
char
*
)
calloc
(
1
,
MAX_COLUMN_LENGTH
);
fetch
->
bind_array
[
i
].
buffer_type
=
MYSQL_TYPE_STRING
;
fetch
->
bind_array
[
i
].
buffer
=
fetch
->
out_data
[
i
];
fetch
->
bind_array
[
i
].
buffer_length
=
MAX_COLUMN_LENGTH
;
fetch
->
bind_array
[
i
].
length
=
fetch
->
out_data_length
+
i
;
}
mysql_stmt_bind_result
(
fetch
->
handle
,
fetch
->
bind_array
);
fetch
->
row_count
=
0
;
fetch
->
is_open
=
TRUE
;
/* Ready for reading rows */
DBUG_VOID_RETURN
;
}
/* Fetch and print one row from cursor */
int
stmt_fetch_fetch_row
(
Stmt_fetch
*
fetch
)
{
int
rc
;
unsigned
i
;
DBUG_ENTER
(
"stmt_fetch_fetch_row"
);
if
((
rc
=
mysql_stmt_fetch
(
fetch
->
handle
))
==
0
)
{
++
fetch
->
row_count
;
if
(
!
opt_silent
)
printf
(
"Stmt %d fetched row %d:
\n
"
,
fetch
->
stmt_no
,
fetch
->
row_count
);
for
(
i
=
0
;
i
<
fetch
->
column_count
;
++
i
)
{
fetch
->
out_data
[
i
][
fetch
->
out_data_length
[
i
]]
=
'\0'
;
if
(
!
opt_silent
)
printf
(
"column %d: %s
\n
"
,
i
+
1
,
fetch
->
out_data
[
i
]);
}
}
else
fetch
->
is_open
=
FALSE
;
DBUG_RETURN
(
rc
);
}
void
stmt_fetch_close
(
Stmt_fetch
*
fetch
)
{
unsigned
i
;
DBUG_ENTER
(
"stmt_fetch_close"
);
for
(
i
=
0
;
i
<
fetch
->
column_count
;
++
i
)
free
(
fetch
->
out_data
[
i
]);
free
(
fetch
->
out_data
);
free
(
fetch
->
out_data_length
);
free
(
fetch
->
bind_array
);
mysql_stmt_close
(
fetch
->
handle
);
DBUG_VOID_RETURN
;
}
/*
For given array of queries, open query_count cursors and fetch
from them in simultaneous manner.
In case there was an error in one of the cursors, continue
reading from the rest.
*/
enum
fetch_type
{
USE_ROW_BY_ROW_FETCH
=
0
,
USE_STORE_RESULT
=
1
};
my_bool
fetch_n
(
const
char
**
query_list
,
unsigned
query_count
,
enum
fetch_type
fetch_type
)
{
unsigned
open_statements
=
query_count
;
int
rc
,
error_count
=
0
;
Stmt_fetch
*
fetch_array
=
(
Stmt_fetch
*
)
calloc
(
1
,
sizeof
(
Stmt_fetch
)
*
query_count
);
Stmt_fetch
*
fetch
;
DBUG_ENTER
(
"fetch_n"
);
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
{
/* Init will exit(1) in case of error */
stmt_fetch_init
(
fetch
,
fetch
-
fetch_array
,
query_list
[
fetch
-
fetch_array
]);
}
if
(
fetch_type
==
USE_STORE_RESULT
)
{
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
{
rc
=
mysql_stmt_store_result
(
fetch
->
handle
);
check_execute
(
fetch
->
handle
,
rc
);
}
}
while
(
open_statements
)
{
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
{
if
(
fetch
->
is_open
&&
(
rc
=
stmt_fetch_fetch_row
(
fetch
)))
{
open_statements
--
;
/*
We try to fetch from the rest of the statements in case of
error
*/
if
(
rc
!=
MYSQL_NO_DATA
)
{
fprintf
(
stderr
,
"Got error reading rows from statement %d,
\n
"
"query is: %s,
\n
"
"error message: %s"
,
(
int
)
(
fetch
-
fetch_array
),
fetch
->
query
,
mysql_stmt_error
(
fetch
->
handle
));
error_count
++
;
}
}
}
}
if
(
error_count
)
fprintf
(
stderr
,
"Fetch FAILED"
);
else
{
unsigned
total_row_count
=
0
;
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
total_row_count
+=
fetch
->
row_count
;
if
(
!
opt_silent
)
printf
(
"Success, total rows fetched: %d
\n
"
,
total_row_count
);
}
for
(
fetch
=
fetch_array
;
fetch
<
fetch_array
+
query_count
;
++
fetch
)
stmt_fetch_close
(
fetch
);
free
(
fetch_array
);
DBUG_RETURN
(
error_count
!=
0
);
}
/* Separate thread query to test some cases */
static
my_bool
thread_query
(
const
char
*
query
)
{
MYSQL
*
l_mysql
;
my_bool
error
;
error
=
0
;
if
(
!
opt_silent
)
fprintf
(
stdout
,
"
\n
in thread_query(%s)"
,
query
);
if
(
!
(
l_mysql
=
mysql_client_init
(
NULL
)))
{
myerror
(
"mysql_client_init() failed"
);
return
1
;
}
if
(
!
(
mysql_real_connect
(
l_mysql
,
opt_host
,
opt_user
,
opt_password
,
current_db
,
opt_port
,
opt_unix_socket
,
0
)))
{
myerror
(
"connection failed"
);
error
=
1
;
goto
end
;
}
l_mysql
->
reconnect
=
1
;
if
(
mysql_query
(
l_mysql
,
query
))
{
fprintf
(
stderr
,
"Query failed (%s)
\n
"
,
mysql_error
(
l_mysql
));
error
=
1
;
goto
end
;
}
mysql_commit
(
l_mysql
);
end:
mysql_close
(
l_mysql
);
return
error
;
}
/* Query processing */
static
void
test_debug_example
()
...
...
@@ -19772,91 +18645,6 @@ static void test_bug13001491()
}
/*
Read and parse arguments and MySQL options from my.cnf
*/
static
const
char
*
client_test_load_default_groups
[]
=
{
"client"
,
0
};
static
char
**
defaults_argv
;
static
struct
my_option
client_test_long_options
[]
=
{
{
"basedir"
,
'b'
,
"Basedir for tests."
,
&
opt_basedir
,
&
opt_basedir
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"count"
,
't'
,
"Number of times test to be executed"
,
&
opt_count
,
&
opt_count
,
0
,
GET_UINT
,
REQUIRED_ARG
,
1
,
0
,
0
,
0
,
0
,
0
},
{
"database"
,
'D'
,
"Database to use"
,
&
opt_db
,
&
opt_db
,
0
,
GET_STR_ALLOC
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"debug"
,
'#'
,
"Output debug log"
,
&
default_dbug_option
,
&
default_dbug_option
,
0
,
GET_STR
,
OPT_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"help"
,
'?'
,
"Display this help and exit"
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"host"
,
'h'
,
"Connect to host"
,
&
opt_host
,
&
opt_host
,
0
,
GET_STR_ALLOC
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"password"
,
'p'
,
"Password to use when connecting to server. If password is not given it's asked from the tty."
,
0
,
0
,
0
,
GET_STR
,
OPT_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"port"
,
'P'
,
"Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
"/etc/services, "
#endif
"built-in default ("
STRINGIFY_ARG
(
MYSQL_PORT
)
")."
,
&
opt_port
,
&
opt_port
,
0
,
GET_UINT
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"server-arg"
,
'A'
,
"Send embedded server this as a parameter."
,
0
,
0
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"show-tests"
,
'T'
,
"Show all tests' names"
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"silent"
,
's'
,
"Be more silent"
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#ifdef HAVE_SMEM
{
"shared-memory-base-name"
,
'm'
,
"Base name of shared memory."
,
&
shared_memory_base_name
,
(
uchar
**
)
&
shared_memory_base_name
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#endif
{
"socket"
,
'S'
,
"Socket file to use for connection"
,
&
opt_unix_socket
,
&
opt_unix_socket
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"testcase"
,
'c'
,
"May disable some code when runs as mysql-test-run testcase."
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#ifndef DONT_ALLOW_USER_CHANGE
{
"user"
,
'u'
,
"User for login if not current user"
,
&
opt_user
,
&
opt_user
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
#endif
{
"vardir"
,
'v'
,
"Data dir for tests."
,
&
opt_vardir
,
&
opt_vardir
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"getopt-ll-test"
,
'g'
,
"Option for testing bug in getopt library"
,
&
opt_getopt_ll_test
,
&
opt_getopt_ll_test
,
0
,
GET_LL
,
REQUIRED_ARG
,
0
,
0
,
LONGLONG_MAX
,
0
,
0
,
0
},
{
"plugin_dir"
,
0
,
"Directory for client-side plugins."
,
&
opt_plugin_dir
,
&
opt_plugin_dir
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"default_auth"
,
0
,
"Default authentication client-side plugin to use."
,
&
opt_default_auth
,
&
opt_default_auth
,
0
,
GET_STR
,
REQUIRED_ARG
,
0
,
0
,
0
,
0
,
0
,
0
},
{
0
,
0
,
0
,
0
,
0
,
0
,
GET_NO_ARG
,
NO_ARG
,
0
,
0
,
0
,
0
,
0
,
0
}
};
static
void
usage
(
void
)
{
/* show the usage string when the user asks for this */
putc
(
'\n'
,
stdout
);
printf
(
"%s Ver %s Distrib %s, for %s (%s)
\n
"
,
my_progname
,
VER
,
MYSQL_SERVER_VERSION
,
SYSTEM_TYPE
,
MACHINE_TYPE
);
puts
(
"By Monty, Venu, Kent and others
\n
"
);
printf
(
"\
Copyright (C) 2002-2004 MySQL AB
\n
\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
\n
\
and you are welcome to modify and redistribute it under the GPL license
\n
"
);
printf
(
"Usage: %s [OPTIONS] [TESTNAME1 TESTNAME2...]
\n
"
,
my_progname
);
my_print_help
(
client_test_long_options
);
print_defaults
(
"my"
,
client_test_load_default_groups
);
my_print_variables
(
client_test_long_options
);
}
static
struct
my_tests_st
my_tests
[]
=
{
{
"disable_query_logs"
,
disable_query_logs
},
{
"test_view_sp_list_fields"
,
test_view_sp_list_fields
},
...
...
@@ -20123,183 +18911,4 @@ static struct my_tests_st my_tests[]= {
};
static
my_bool
get_one_option
(
int
optid
,
const
struct
my_option
*
opt
__attribute__
((
unused
)),
char
*
argument
)
{
switch
(
optid
)
{
case
'#'
:
DBUG_PUSH
(
argument
?
argument
:
default_dbug_option
);
break
;
case
'c'
:
opt_testcase
=
1
;
break
;
case
'p'
:
if
(
argument
)
{
char
*
start
=
argument
;
my_free
(
opt_password
);
opt_password
=
my_strdup
(
argument
,
MYF
(
MY_FAE
));
while
(
*
argument
)
*
argument
++=
'x'
;
/* Destroy argument */
if
(
*
start
)
start
[
1
]
=
0
;
}
else
tty_password
=
1
;
break
;
case
's'
:
if
(
argument
==
disabled_my_option
)
opt_silent
=
0
;
else
opt_silent
++
;
break
;
case
'A'
:
/*
When the embedded server is being tested, the test suite needs to be
able to pass command-line arguments to the embedded server so it can
locate the language files and data directory. The test suite
(mysql-test-run) never uses config files, just command-line options.
*/
if
(
!
embedded_server_arg_count
)
{
embedded_server_arg_count
=
1
;
embedded_server_args
[
0
]
=
(
char
*
)
""
;
}
if
(
embedded_server_arg_count
==
MAX_SERVER_ARGS
-
1
||
!
(
embedded_server_args
[
embedded_server_arg_count
++
]
=
my_strdup
(
argument
,
MYF
(
MY_FAE
))))
{
DIE
(
"Can't use server argument"
);
}
break
;
case
'T'
:
{
struct
my_tests_st
*
fptr
;
printf
(
"All possible test names:
\n\n
"
);
for
(
fptr
=
my_tests
;
fptr
->
name
;
fptr
++
)
printf
(
"%s
\n
"
,
fptr
->
name
);
exit
(
0
);
break
;
}
case
'?'
:
case
'I'
:
/* Info */
usage
();
exit
(
0
);
break
;
}
return
0
;
}
static
void
get_options
(
int
*
argc
,
char
***
argv
)
{
int
ho_error
;
if
((
ho_error
=
handle_options
(
argc
,
argv
,
client_test_long_options
,
get_one_option
)))
exit
(
ho_error
);
if
(
tty_password
)
opt_password
=
get_tty_password
(
NullS
);
return
;
}
/*
Print the test output on successful execution before exiting
*/
static
void
print_test_output
()
{
if
(
opt_silent
<
3
)
{
fprintf
(
stdout
,
"
\n\n
"
);
fprintf
(
stdout
,
"All '%d' tests were successful (in '%d' iterations)"
,
test_count
-
1
,
opt_count
);
fprintf
(
stdout
,
"
\n
Total execution time: %g SECS"
,
total_time
);
if
(
opt_count
>
1
)
fprintf
(
stdout
,
" (Avg: %g SECS)"
,
total_time
/
opt_count
);
fprintf
(
stdout
,
"
\n\n
!!! SUCCESS !!!
\n
"
);
}
}
/***************************************************************************
main routine
***************************************************************************/
int
main
(
int
argc
,
char
**
argv
)
{
struct
my_tests_st
*
fptr
;
MY_INIT
(
argv
[
0
]);
if
(
load_defaults
(
"my"
,
client_test_load_default_groups
,
&
argc
,
&
argv
))
exit
(
1
);
defaults_argv
=
argv
;
get_options
(
&
argc
,
&
argv
);
if
(
mysql_server_init
(
embedded_server_arg_count
,
embedded_server_args
,
(
char
**
)
embedded_server_groups
))
DIE
(
"Can't initialize MySQL server"
);
/* connect to server with no flags, default protocol, auto reconnect true */
mysql
=
client_connect
(
0
,
MYSQL_PROTOCOL_DEFAULT
,
1
);
total_time
=
0
;
for
(
iter_count
=
1
;
iter_count
<=
opt_count
;
iter_count
++
)
{
/* Start of tests */
test_count
=
1
;
start_time
=
time
((
time_t
*
)
0
);
if
(
!
argc
)
{
for
(
fptr
=
my_tests
;
fptr
->
name
;
fptr
++
)
(
*
fptr
->
function
)();
}
else
{
for
(
;
*
argv
;
argv
++
)
{
for
(
fptr
=
my_tests
;
fptr
->
name
;
fptr
++
)
{
if
(
!
strcmp
(
fptr
->
name
,
*
argv
))
{
(
*
fptr
->
function
)();
break
;
}
}
if
(
!
fptr
->
name
)
{
fprintf
(
stderr
,
"
\n\n
Given test not found: '%s'
\n
"
,
*
argv
);
fprintf
(
stderr
,
"See legal test names with %s -T
\n\n
Aborting!
\n
"
,
my_progname
);
client_disconnect
(
mysql
,
1
);
free_defaults
(
defaults_argv
);
exit
(
1
);
}
}
}
end_time
=
time
((
time_t
*
)
0
);
total_time
+=
difftime
(
end_time
,
start_time
);
/* End of tests */
}
client_disconnect
(
mysql
,
1
);
/* disconnect from server */
free_defaults
(
defaults_argv
);
print_test_output
();
while
(
embedded_server_arg_count
>
1
)
my_free
(
embedded_server_args
[
--
embedded_server_arg_count
]);
mysql_server_end
();
my_end
(
0
);
exit
(
0
);
}
static
struct
my_tests_st
*
get_my_tests
()
{
return
my_tests
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment