Commit 2f65c531 authored by jan@hundin.mysql.fi's avatar jan@hundin.mysql.fi

Merge jlindstrom@bk-internal.mysql.com:/home/bk/mysql-4.1

into hundin.mysql.fi:/home/jan/mysql-4.1
parents d3b84946 8e87db93
......@@ -27,12 +27,20 @@
const char *config_file="my"; /* Default config file */
uint verbose= 0, opt_defaults_file_used= 0;
const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace";
static struct my_option my_long_options[] =
{
{"config-file", 'c', "The config file to be used.",
(gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
#ifdef DBUG_OFF
{"debug", '#', "This is a non-debug version. Catch this and exit",
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
{"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
(gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"defaults-file", 'c', "Synonym for --config-file.",
(gptr*) &config_file, (gptr*) &config_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
......@@ -95,6 +103,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'V':
usage(1);
exit(0);
case '#':
DBUG_PUSH(argument ? argument : default_dbug_option);
break;
}
return 0;
}
......@@ -118,7 +129,7 @@ static int get_options(int *argc,char ***argv)
int main(int argc, char **argv)
{
int count, error;
char **load_default_groups, *tmp_arguments[2],
char **load_default_groups, *tmp_arguments[3],
**argument, **arguments;
char *defaults, *extra_defaults;
MY_INIT(argv[0]);
......
......@@ -22,7 +22,7 @@
void Querycache_stream::store_char(char c)
{
if (data_end == cur_data)
use_next_block();
use_next_block(TRUE);
*(cur_data++)= c;
#ifndef DBUG_OFF
stored_size++;
......@@ -42,13 +42,13 @@ void Querycache_stream::store_short(ushort s)
}
if (data_end == cur_data)
{
use_next_block();
use_next_block(TRUE);
int2store(cur_data, s);
cur_data+= 2;
return;
}
*cur_data= ((byte *)(&s))[0];
use_next_block();
use_next_block(TRUE);
*(cur_data++)= ((byte *)(&s))[1];
}
......@@ -66,7 +66,7 @@ void Querycache_stream::store_int(uint i)
}
if (!rest_len)
{
use_next_block();
use_next_block(TRUE);
int4store(cur_data, i);
cur_data+= 4;
return;
......@@ -74,7 +74,7 @@ void Querycache_stream::store_int(uint i)
char buf[4];
int4store(buf, i);
memcpy(cur_data, buf, rest_len);
use_next_block();
use_next_block(TRUE);
memcpy(cur_data, buf+rest_len, 4-rest_len);
cur_data+= 4-rest_len;
}
......@@ -93,13 +93,13 @@ void Querycache_stream::store_ll(ulonglong ll)
}
if (!rest_len)
{
use_next_block();
use_next_block(TRUE);
int8store(cur_data, ll);
cur_data+= 8;
return;
}
memcpy(cur_data, &ll, rest_len);
use_next_block();
use_next_block(TRUE);
memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len);
cur_data+= 8-rest_len;
}
......@@ -112,14 +112,14 @@ void Querycache_stream::store_str_only(const char *str, uint str_len)
do
{
size_t rest_len= data_end - cur_data;
if (rest_len > str_len)
if (rest_len >= str_len)
{
memcpy(cur_data, str, str_len);
cur_data+= str_len;
return;
}
memcpy(cur_data, str, rest_len);
use_next_block();
use_next_block(TRUE);
str_len-= rest_len;
str+= rest_len;
} while(str_len);
......@@ -145,7 +145,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len)
char Querycache_stream::load_char()
{
if (cur_data == data_end)
use_next_block();
use_next_block(FALSE);
return *(cur_data++);
}
......@@ -160,13 +160,13 @@ ushort Querycache_stream::load_short()
}
if (data_end == cur_data)
{
use_next_block();
use_next_block(FALSE);
result= uint2korr(cur_data);
cur_data+= 2;
return result;
}
((byte*)&result)[0]= *cur_data;
use_next_block();
use_next_block(FALSE);
((byte*)&result)[1]= *(cur_data++);
return result;
}
......@@ -183,14 +183,14 @@ uint Querycache_stream::load_int()
}
if (!rest_len)
{
use_next_block();
use_next_block(FALSE);
result= uint4korr(cur_data);
cur_data+= 4;
return result;
}
char buf[4];
memcpy(buf, cur_data, rest_len);
use_next_block();
use_next_block(FALSE);
memcpy(buf+rest_len, cur_data, 4-rest_len);
cur_data+= 4-rest_len;
result= uint4korr(buf);
......@@ -209,13 +209,13 @@ ulonglong Querycache_stream::load_ll()
}
if (!rest_len)
{
use_next_block();
use_next_block(FALSE);
result= uint8korr(cur_data);
cur_data+= 8;
return result;
}
memcpy(&result, cur_data, rest_len);
use_next_block();
use_next_block(FALSE);
memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len);
cur_data+= 8-rest_len;
return result;
......@@ -226,7 +226,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
do
{
size_t rest_len= data_end - cur_data;
if (rest_len > str_len)
if (rest_len >= str_len)
{
memcpy(buffer, cur_data, str_len);
cur_data+= str_len;
......@@ -234,7 +234,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
break;
}
memcpy(buffer, cur_data, rest_len);
use_next_block();
use_next_block(FALSE);
str_len-= rest_len;
buffer+= rest_len;
} while(str_len);
......
......@@ -22,22 +22,43 @@ class Querycache_stream
uint headers_len;
public:
#ifndef DBUG_OFF
Query_cache_block *first_block;
uint stored_size;
#endif
Querycache_stream(Query_cache_block *ini_block, uint ini_headers_len) :
block(ini_block), headers_len(ini_headers_len)
{
use_next_block();
cur_data= ((byte*)block)+headers_len;
data_end= cur_data + (block->used-headers_len);
#ifndef DBUG_OFF
first_block= ini_block;
stored_size= 0;
#endif
}
void use_next_block()
void use_next_block(bool writing)
{
/*
This shouldn't be called if there is only one block, or to loop
around to the first block again. That means we're trying to write
more data than we allocated space for.
*/
DBUG_ASSERT(block->next != block);
DBUG_ASSERT(block->next != first_block);
block= block->next;
/*
While writing, update the type of each block as we write to it.
While reading, make sure that the block is of the expected type.
*/
if (writing)
block->type= Query_cache_block::RES_CONT;
else
DBUG_ASSERT(block->type == Query_cache_block::RES_CONT);
cur_data= ((byte*)block)+headers_len;
data_end= cur_data + (block->used-headers_len);
}
void store_char(char c);
void store_short(ushort s);
void store_int(uint i);
......
......@@ -685,6 +685,12 @@ then
fi
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT"
# Need to pass additional arguments to MYSQL_CLIENT_TEST for embedded server
# -A marks each argument for passing to the function which initializes the
# embedded library
if [ "x$USE_EMBEDDED_SERVER" = "x1" ]; then
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST -A --language=$LANGUAGE -A --datadir=$SLAVE_MYDDIR -A --character-sets-dir=$CHARSETSDIR"
fi
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT"
MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
......
......@@ -78,5 +78,8 @@ ERROR 42000: Not unique table/alias: 'C'
select C.a, c.a from t1 c, t2 C;
ERROR 42000: Not unique table/alias: 'C'
drop table t1, t2;
create table t1 (a int);
create table t2 like T1;
drop table t1, t2;
show tables;
Tables_in_test
This diff is collapsed.
......@@ -73,4 +73,12 @@ select * from t1 c, t2 C;
select C.a, c.a from t1 c, t2 C;
drop table t1, t2;
#
# Bug #9761: CREATE TABLE ... LIKE ... not handled correctly when
# lower_case_table_names is set
create table t1 (a int);
create table t2 like T1;
drop table t1, t2;
show tables;
......@@ -685,4 +685,49 @@ repair table t1;
show status like 'qcache_queries_in_cache';
drop table t1;
# Bug #9549: Make sure cached queries that span more than one cache block
# are handled properly in the embedded server.
# We just want a small query cache, so we can fragment it easily
set GLOBAL query_cache_size=64*1024;
# This actually gives us a usable cache size of about 48K
# Each table is about 14K
create table t1 (a text);
insert into t1 values (repeat('abcdefghijklmnopqrstuvwxyz', 550));
create table t2 (a text);
insert into t2 values (repeat('ijklmnopqrstuvwxyzabcdefgh', 550));
# Load a query from each table into the query cache
--disable_result_log
select a from t1; # Q1
select a from t2; # Q2
--enable_result_log
show status like 'Qcache_%_blocks';
# Now the cache looks like (14K for Q1)(14K for Q2)(20K free)
# Flush Q1 from the cache by adding an out-of-order chunk to t1
insert into t1 select reverse(a) from t1;
show status like 'Qcache_%_blocks';
# Now the cache looks like (14K free)(14K for Q2)(20K free)
# Load our new data into the query cache
--disable_result_log
select a from t1; # Q3
--enable_result_log
show status like 'Qcache_%_blocks';
# Now the cache should be like (14K for Q3)(14K for Q2)(14K for Q3)(6K free)
# Note that Q3 is split across two chunks!
# Load Q3 from the cache, and actually pay attention to the results
select a from t1;
flush query cache;
drop table t1, t2;
set GLOBAL query_cache_size=0;
......@@ -144,7 +144,7 @@ int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
const char **dirs, *forced_default_file;
const char **dirs, *forced_default_file, *forced_extra_defaults;
TYPELIB group;
my_bool found_print_defaults=0;
uint args_used=0;
......@@ -174,13 +174,14 @@ int load_defaults(const char *conf_file, const char **groups,
}
get_defaults_files(*argc, *argv,
(char **)&forced_default_file, &defaults_extra_file);
(char **)&forced_default_file,
(char **)&forced_extra_defaults);
if (forced_default_file)
forced_default_file= strchr(forced_default_file,'=')+1;
if (defaults_extra_file)
defaults_extra_file= strchr(defaults_extra_file,'=')+1;
if (forced_extra_defaults)
defaults_extra_file= strchr(forced_extra_defaults,'=')+1;
args_used+= (forced_default_file ? 1 : 0) + (defaults_extra_file ? 1 : 0);
args_used+= (forced_default_file ? 1 : 0) + (forced_extra_defaults ? 1 : 0);
group.count=0;
group.name= "defaults";
......
......@@ -1933,6 +1933,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
type = Query_cache_block::RES_CONT;
} while (block != *result_block);
#else
/*
Set type of first block, emb_store_querycache_result() will handle
the others.
*/
(*result_block)->type= type;
Querycache_stream qs(*result_block, headers_len);
emb_store_querycache_result(&qs, (THD*)data);
#endif /*!EMBEDDED_LIBRARY*/
......
......@@ -449,7 +449,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
uc->user_resources.connections <= uc->conn_per_hour)
{
net_printf(thd, ER_USER_LIMIT_REACHED, uc->user,
"max_connections",
"max_connections_per_hour",
(long) uc->user_resources.connections);
error=1;
goto end;
......
......@@ -2281,6 +2281,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
reg_ext, NullS);
/* Resolve symlinks (for windows) */
fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME));
if (lower_case_table_names)
my_casedn_str(files_charset_info, src_path);
if (access(src_path, F_OK))
{
my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
......
......@@ -30,6 +30,7 @@
#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
#define MAX_SERVER_ARGS 64
/* set default options */
static int opt_testcase = 0;
......@@ -48,6 +49,18 @@ static unsigned int test_count= 0;
static unsigned int opt_count= 0;
static unsigned int iter_count= 0;
static const char *opt_basedir= "./";
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;
......@@ -93,6 +106,8 @@ static void client_disconnect();
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
#define DIE(expr) \
die(__FILE__, __LINE__, #expr)
void die(const char *file, int line, const char *expr)
{
......@@ -11617,7 +11632,7 @@ static void test_bug7990()
static void test_bug8378()
{
#ifdef HAVE_CHARSET_gbk
#if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
MYSQL *lmysql;
char out[9]; /* strlen(TEST_BUG8378)*2+1 */
int len;
......@@ -11664,6 +11679,8 @@ static char **defaults_argv;
static struct my_option client_test_long_options[] =
{
{"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir,
(gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"count", 't', "Number of times test to be executed", (char **) &opt_count,
(char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use", (char **) &opt_db, (char **) &opt_db,
......@@ -11679,6 +11696,8 @@ static struct my_option client_test_long_options[] =
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection", (char **) &opt_port,
(char **) &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,
......@@ -11899,6 +11918,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
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;
......@@ -11962,11 +12000,16 @@ int main(int argc, char **argv)
DEBUGGER_OFF;
MY_INIT(argv[0]);
load_defaults("my", client_test_load_default_groups, &argc, &argv);
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");
client_connect(); /* connect to server */
total_time= 0;
......@@ -12019,6 +12062,12 @@ int main(int argc, char **argv)
client_disconnect(); /* 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],MYF(0));
mysql_server_end();
my_end(0);
exit(0);
......
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