Commit 21bef0ed authored by unknown's avatar unknown

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

into mysql.com:/home/my/mysql-4.1

parents c331a891 b321b7c0
......@@ -227,11 +227,12 @@ typedef struct {
} COMMANDS;
static COMMANDS commands[] = {
{ "help", 'h', com_help, 1, "Display this help." },
{ "?", '?', com_help, 1, "Synonym for `help'." },
{ "clear", 'c', com_clear, 0, "Clear command."},
{ "connect",'r', com_connect,1,
"Reconnect to the server. Optional arguments are db and host." },
{ "delimiter", 'd', com_delimiter, 1,
"Set query delimiter. " },
#ifdef USE_POPEN
{ "edit", 'e', com_edit, 0, "Edit command with $EDITOR."},
#endif
......@@ -239,6 +240,7 @@ static COMMANDS commands[] = {
"Send command to mysql server, display result vertically."},
{ "exit", 'q', com_quit, 0, "Exit mysql. Same as quit."},
{ "go", 'g', com_go, 0, "Send command to mysql server." },
{ "help", 'h', com_help, 1, "Display this help." },
#ifdef USE_POPEN
{ "nopager",'n', com_nopager,0, "Disable pager, print to stdout." },
#endif
......@@ -261,8 +263,6 @@ static COMMANDS commands[] = {
"Set outfile [to_outfile]. Append everything into given outfile." },
{ "use", 'u', com_use, 1,
"Use another database. Takes database name as argument." },
{ "delimiter", 'd', com_delimiter, 1,
"Set query delimiter. " },
/* Get bash-like expansion for some commands */
{ "create table", 0, 0, 0, ""},
{ "create database", 0, 0, 0, ""},
......@@ -1577,8 +1577,8 @@ static int
com_help(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
reg1 int i;
char * help_arg= strchr(line,' ');
reg1 int i, j;
char * help_arg= strchr(line,' '), buff[32], *end;
if (help_arg)
return com_server_help(buffer,line,help_arg+1);
......@@ -1591,8 +1591,11 @@ com_help(String *buffer __attribute__((unused)),
put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
for (i = 0; commands[i].name; i++)
{
end= strmov(buff, commands[i].name);
for (j= strlen(commands[i].name); j < 10; j++)
end= strmov(end, " ");
if (commands[i].func)
tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
commands[i].cmd_char, commands[i].doc);
}
if (connected && mysql_get_server_version(&mysql) >= 40100)
......@@ -2433,8 +2436,9 @@ com_delimiter(String *buffer __attribute__((unused)), char *line)
static int
com_use(String *buffer __attribute__((unused)), char *line)
{
char *tmp;
char buff[256];
char *tmp, buff[FN_REFLEN + 1];
MYSQL_RES *res;
MYSQL_ROW row;
bzero(buff, sizeof(buff));
strmov(buff, line);
......@@ -2444,6 +2448,31 @@ com_use(String *buffer __attribute__((unused)), char *line)
put_info("USE must be followed by a database name", INFO_ERROR);
return 0;
}
/*
We need to recheck the current database, because it may change
under our feet, for example if DROP DATABASE or RENAME DATABASE
(latter one not yet available by the time the comment was written)
*/
current_db= 0; // Let's reset current_db, assume it's gone
/*
We don't care about in case of an error below because current_db
was just set to 0.
*/
if (!mysql_query(&mysql, "SELECT DATABASE()") &&
(res= mysql_use_result(&mysql)))
{
row= mysql_fetch_row(res);
if (row[0] &&
(!current_db || cmp_database(charset_info, current_db, row[0])))
{
my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
current_db= my_strdup(row[0], MYF(MY_WME));
}
(void) mysql_fetch_row(res); // Read eof
mysql_free_result(res);
}
if (!current_db || cmp_database(charset_info, current_db, tmp))
{
if (one_database)
......
......@@ -32,6 +32,4 @@
#undef MYSQL_SERVER_SUFFIX
#define MYSQL_SERVER_SUFFIX "-embedded"
#undef HAVE_QUERY_CACHE /* Cache dosn't work yet */
#endif /* EMBEDDED_LIBRARY */
......@@ -15,6 +15,8 @@ Created 9/20/1997 Heikki Tuuri
#include "hash0hash.h"
#include "log0log.h"
extern ibool recv_replay_file_ops;
/***********************************************************************
Reads the checkpoint info needed in hot backup. */
......
......@@ -34,6 +34,11 @@ Created 9/20/1997 Heikki Tuuri
#include "dict0boot.h"
#include "fil0fil.h"
/* This is set to FALSE if the backup was originally taken with the
ibbackup --include regexp option: then we do not want to create tables in
directories which were not included */
ibool recv_replay_file_ops = TRUE;
/* Log records are stored in the hash table in chunks at most of this size;
this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */
#define RECV_DATA_BLOCK_SIZE (MEM_MAX_ALLOC_IN_BUF - sizeof(recv_data_t))
......@@ -1974,19 +1979,22 @@ loop:
|| type == MLOG_FILE_RENAME
|| type == MLOG_FILE_DELETE)) {
#ifdef UNIV_HOTBACKUP
if (recv_replay_file_ops) {
/* In ibbackup --apply-log, replay an .ibd file
operation, if possible; note that
fil_path_to_mysql_datadir is set in ibbackup to
point to the datadir we should use there */
if (NULL == fil_op_log_parse_or_replay(body, end_ptr,
type, TRUE, space)) {
if (NULL == fil_op_log_parse_or_replay(body,
end_ptr, type, TRUE, space)) {
fprintf(stderr,
"InnoDB: Error: file op log record of type %lu space %lu not complete in\n"
"InnoDB: the replay phase. Path %s\n", (ulint)type, space, (char*)(body + 2));
ut_a(0);
}
}
#endif
/* In normal mysqld crash recovery we do not try to
replay file operations */
......
......@@ -1447,7 +1447,7 @@ row_create_table_for_mysql(
fprintf(stderr,
" InnoDB: Error: table %s already exists in InnoDB internal\n"
"InnoDB: data dictionary. Have you deleted the .frm file\n"
"InnoDB: and not used DROPT ABLE? Have you used DROP DATABASE\n"
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
"InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n"
"InnoDB: See the Restrictions section of the InnoDB manual.\n",
table->name);
......
......@@ -534,6 +534,8 @@ row_purge_parse_undo_rec(
node->table = NULL;
row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
......
......@@ -1603,6 +1603,19 @@ NetWare. */
fflush(stderr);
if (trx_doublewrite_must_reset_space_ids) {
/* Actually, we did not change the undo log format between
4.0 and 4.1.1, and we would not need to run purge to
completion. Note also that the purge algorithm in 4.1.1
can process the the history list again even after a full
purge, because our algorithm does not cut the end of the
history list in all cases so that it would become empty
after a full purge. That mean that we may purge 4.0 type
undo log even after this phase.
The insert buffer record format changed between 4.0 and
4.1.1. It is essential that the insert buffer is emptied
here! */
fprintf(stderr,
"InnoDB: You are upgrading to an InnoDB version which allows multiple\n"
"InnoDB: tablespaces. Wait that purge and insert buffer merge run to\n"
......@@ -1625,8 +1638,9 @@ NetWare. */
fprintf(stderr,
"InnoDB: You have now successfully upgraded to the multiple tablespaces\n"
"InnoDB: format. You should not downgrade again to an earlier version of\n"
"InnoDB: InnoDB!\n");
"InnoDB: format. You should NOT DOWNGRADE again to an earlier version of\n"
"InnoDB: InnoDB! But if you absolutely need to downgrade, see section 4.6 of\n"
"InnoDB: http://www.innodb.com/ibman.php for instructions.\n");
}
if (srv_force_recovery == 0) {
......
......@@ -33,10 +33,10 @@ INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \
noinst_LIBRARIES = libmysqld_int.a
pkglib_LIBRARIES = libmysqld.a
SUBDIRS = . examples
libmysqld_sources= libmysqld.c lib_sql.cc
libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc
libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c
noinst_HEADERS = embedded_priv.h
noinst_HEADERS = embedded_priv.h emb_qcache.h
sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \
......
/* Copyright (C) 2000-2003 MySQL AB
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; either version 2 of the License, or
(at your option) any later version.
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 "mysql_priv.h"
#ifdef HAVE_QUERY_CACHE
#include <mysql.h>
#include "emb_qcache.h"
void Querycache_stream::store_char(char c)
{
if (data_end == cur_data)
use_next_block();
*(cur_data++)= c;
#ifndef DBUG_OFF
stored_size++;
#endif
}
void Querycache_stream::store_short(ushort s)
{
#ifndef DBUG_OFF
stored_size+= 2;
#endif
if (data_end - cur_data > 1)
{
int2store(cur_data, s);
cur_data+= 2;
return;
}
if (data_end == cur_data)
{
use_next_block();
int2store(cur_data, s);
cur_data+= 2;
return;
}
*cur_data= ((byte *)(&s))[0];
use_next_block();
*(cur_data++)= ((byte *)(&s))[1];
}
void Querycache_stream::store_int(uint i)
{
#ifndef DBUG_OFF
stored_size+= 4;
#endif
size_t rest_len= data_end - cur_data;
if (rest_len > 3)
{
int4store(cur_data, i);
cur_data+= 4;
return;
}
if (!rest_len)
{
use_next_block();
int4store(cur_data, i);
cur_data+= 4;
return;
}
memcpy(cur_data, &i, rest_len);
use_next_block();
memcpy(cur_data, ((byte*)&i)+rest_len, 4-rest_len);
cur_data+= 4-rest_len;
}
void Querycache_stream::store_ll(ulonglong ll)
{
#ifndef DBUG_OFF
stored_size+= 8;
#endif
size_t rest_len= data_end - cur_data;
if (rest_len > 7)
{
int8store(cur_data, ll);
cur_data+= 8;
return;
}
if (!rest_len)
{
use_next_block();
int8store(cur_data, ll);
cur_data+= 8;
return;
}
memcpy(cur_data, &ll, rest_len);
use_next_block();
memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len);
cur_data+= 8-rest_len;
}
void Querycache_stream::store_str_only(const char *str, uint str_len)
{
#ifndef DBUG_OFF
stored_size+= str_len;
#endif
do
{
size_t rest_len= data_end - cur_data;
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();
str_len-= rest_len;
str+= rest_len;
} while(str_len);
}
void Querycache_stream::store_str(const char *str, uint str_len)
{
store_int(str_len);
store_str_only(str, str_len);
}
void Querycache_stream::store_safe_str(const char *str, uint str_len)
{
if (str)
{
store_int(str_len+1);
store_str_only(str, str_len);
}
else
store_int(0);
}
char Querycache_stream::load_char()
{
if (cur_data == data_end)
use_next_block();
return *(cur_data++);
}
ushort Querycache_stream::load_short()
{
ushort result;
if (data_end-cur_data > 1)
{
result= uint2korr(cur_data);
cur_data+= 2;
return result;
}
if (data_end == cur_data)
{
use_next_block();
result= uint2korr(cur_data);
cur_data+= 2;
return result;
}
((byte*)&result)[0]= *cur_data;
use_next_block();
((byte*)&result)[1]= *(cur_data++);
return result;
}
uint Querycache_stream::load_int()
{
int result;
size_t rest_len= data_end - cur_data;
if (rest_len > 3)
{
result= uint4korr(cur_data);
cur_data+= 4;
return result;
}
if (!rest_len)
{
use_next_block();
result= uint4korr(cur_data);
cur_data+= 4;
return result;
}
memcpy(&result, cur_data, rest_len);
use_next_block();
memcpy(((byte*)&result)+rest_len, cur_data, 4-rest_len);
cur_data+= 4-rest_len;
return result;
}
ulonglong Querycache_stream::load_ll()
{
ulonglong result;
size_t rest_len= data_end - cur_data;
if (rest_len > 7)
{
result= uint8korr(cur_data);
cur_data+= 8;
return result;
}
if (!rest_len)
{
use_next_block();
result= uint8korr(cur_data);
cur_data+= 8;
return result;
}
memcpy(&result, cur_data, rest_len);
use_next_block();
memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len);
cur_data+= 8-rest_len;
return result;
}
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)
{
memcpy(buffer, cur_data, str_len);
cur_data+= str_len;
buffer+= str_len;
break;
}
memcpy(buffer, cur_data, rest_len);
use_next_block();
str_len-= rest_len;
buffer+= rest_len;
} while(str_len);
*buffer= 0;
}
char *Querycache_stream::load_str(MEM_ROOT *alloc, uint *str_len)
{
char *result;
*str_len= load_int();
if (!(result= alloc_root(alloc, *str_len + 1)))
return 0;
load_str_only(result, *str_len);
return result;
}
int Querycache_stream::load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len)
{
if (!(*str_len= load_int()))
{
*str= NULL;
return 0;
}
(*str_len)--;
if (!(*str= alloc_root(alloc, *str_len + 1)))
return 1;
load_str_only(*str, *str_len);
return 0;
}
int Querycache_stream::load_column(MEM_ROOT *alloc, char** column)
{
int len;
if (!(len = load_int()))
{
*column= NULL;
return 0;
}
len--;
if (!(*column= (char *)alloc_root(alloc, len + 4 + 1)))
return 1;
int4store(*column, len);
(*column)+= 4;
load_str_only(*column, len);
return 1;
}
uint emb_count_querycache_size(THD *thd)
{
uint result;
MYSQL *mysql= thd->mysql;
MYSQL_FIELD *field= mysql->fields;
MYSQL_FIELD *field_end= field + mysql->field_count;
MYSQL_ROWS *cur_row=NULL;
my_ulonglong n_rows=0;
if (!field)
return 0;
if (thd->data)
{
*thd->data->prev_ptr= NULL; // this marks the last record
cur_row= thd->data->data;
n_rows= thd->data->rows;
}
result= 4+8 + (42 + 4*n_rows)*mysql->field_count;
for(; field < field_end; field++)
{
result+= field->name_length + field->table_length +
field->org_name_length + field->org_table_length + field->db_length +
field->catalog_length;
if (field->def)
result+= field->def_length;
}
for (; cur_row; cur_row=cur_row->next)
{
MYSQL_ROW col= cur_row->data;
MYSQL_ROW col_end= col + mysql->field_count;
for (; col < col_end; col++)
if (*col)
result+= *(uint *)((*col) - sizeof(uint));
}
return result;
}
void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
{
MYSQL *mysql= thd->mysql;
MYSQL_FIELD *field= mysql->fields;
MYSQL_FIELD *field_end= field + mysql->field_count;
MYSQL_ROWS *cur_row= NULL;
my_ulonglong n_rows= 0;
if (!field)
return;
if (thd->data)
{
*thd->data->prev_ptr= NULL; // this marks the last record
cur_row= thd->data->data;
n_rows= thd->data->rows;
}
dst->store_int((uint)mysql->field_count);
dst->store_ll((uint)n_rows);
for(; field < field_end; field++)
{
dst->store_int((uint)field->length);
dst->store_int((uint)field->max_length);
dst->store_char((char)field->type);
dst->store_short((ushort)field->flags);
dst->store_short((ushort)field->charsetnr);
dst->store_char((char)field->decimals);
dst->store_str(field->name, field->name_length);
dst->store_str(field->table, field->table_length);
dst->store_str(field->org_name, field->org_name_length);
dst->store_str(field->org_table, field->org_table_length);
dst->store_str(field->db, field->db_length);
dst->store_str(field->catalog, field->catalog_length);
dst->store_safe_str(field->def, field->def_length);
}
for (; cur_row; cur_row=cur_row->next)
{
MYSQL_ROW col= cur_row->data;
MYSQL_ROW col_end= col + mysql->field_count;
for (; col < col_end; col++)
{
uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0;
dst->store_safe_str(*col, len);
}
}
DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size);
}
int emb_load_querycache_result(THD *thd, Querycache_stream *src)
{
MYSQL *mysql= thd->mysql;
MYSQL_DATA *data;
MYSQL_FIELD *field;
MYSQL_FIELD *field_end;
MEM_ROOT *f_alloc= &mysql->field_alloc;
MYSQL_ROWS *row, *end_row;
MYSQL_ROWS **prev_row;
ulonglong rows;
MYSQL_ROW columns;
mysql->field_count= src->load_int();
rows= src->load_ll();
if (!(field= (MYSQL_FIELD *)
alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD))))
goto err;
mysql->fields= field;
for(field_end= field+mysql->field_count; field < field_end; field++)
{
field->length= src->load_int();
field->max_length= (unsigned int)src->load_int();
field->type= (enum enum_field_types)src->load_char();
field->flags= (unsigned int)src->load_short();
field->charsetnr= (unsigned int)src->load_short();
field->decimals= (unsigned int)src->load_char();
if (!(field->name= src->load_str(f_alloc, &field->name_length)) ||
!(field->table= src->load_str(f_alloc,&field->table_length)) ||
!(field->org_name= src->load_str(f_alloc, &field->org_name_length)) ||
!(field->org_table= src->load_str(f_alloc, &field->org_table_length))||
!(field->db= src->load_str(f_alloc, &field->db_length)) ||
!(field->catalog= src->load_str(f_alloc, &field->catalog_length)) ||
src->load_safe_str(f_alloc, &field->def, &field->def_length))
goto err;
}
if (!rows)
return 0;
if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA),
MYF(MY_WME | MY_ZEROFILL))))
goto err;
thd->data= data;
init_alloc_root(&data->alloc, 8192,0);
row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS) +
rows * (mysql->field_count+1)*sizeof(char*));
end_row= row + rows;
columns= (MYSQL_ROW)end_row;
data->rows= rows;
data->fields= mysql->field_count;
data->data= row;
for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++)
{
*prev_row= row;
row->data= columns;
MYSQL_ROW col_end= columns + mysql->field_count;
uint len;
for (; columns < col_end; columns++)
src->load_column(&data->alloc, columns);
*(columns++)= NULL;
}
*prev_row= NULL;
data->prev_ptr= prev_row;
return 0;
err:
return 1;
}
#endif /*HAVE_QUERY_CACHE*/
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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; either version 2 of the License, or
(at your option) any later version.
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 */
class Querycache_stream
{
byte *cur_data;
byte *data_end;
Query_cache_block *block;
uint headers_len;
public:
#ifndef DBUG_OFF
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();
#ifndef DBUG_OFF
stored_size= 0;
#endif
}
void use_next_block()
{
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);
void store_ll(ulonglong ll);
void store_str_only(const char *str, uint str_len);
void store_str(const char *str, uint str_len);
void store_safe_str(const char *str, uint str_len);
char load_char();
ushort load_short();
uint load_int();
ulonglong load_ll();
void load_str_only(char *buffer, uint str_len);
char *load_str(MEM_ROOT *alloc, uint *str_len);
int load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len);
int load_column(MEM_ROOT *alloc, char **column);
};
uint emb_count_querycache_size(THD *thd);
int emb_load_querycache_result(THD *thd, Querycache_stream *src);
void emb_store_querycache_result(Querycache_stream *dst, THD* thd);
......@@ -23,9 +23,10 @@
#include <my_pthread.h>
C_MODE_START
extern void lib_connection_phase(NET *net, int phase);
extern void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
extern void *create_embedded_thd(int client_flag, char *db);
extern MYSQL_METHODS embedded_methods;
void lib_connection_phase(NET *net, int phase);
void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
void *create_embedded_thd(int client_flag, char *db);
int check_embedded_connection(MYSQL *mysql);
void free_old_query(MYSQL *mysql);
extern MYSQL_METHODS embedded_methods;
C_MODE_END
......@@ -478,7 +478,17 @@ void *create_embedded_thd(int client_flag, char *db)
return thd;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#ifdef NO_EMBEDDED_ACCESS_CHECKS
int check_embedded_connection(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
thd->host= (char*)my_localhost;
thd->host_or_ip= thd->host;
thd->user= mysql->user;
return 0;
}
#else
int check_embedded_connection(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
......@@ -486,9 +496,13 @@ int check_embedded_connection(MYSQL *mysql)
char scramble_buff[SCRAMBLE_LENGTH];
int passwd_len;
thd->host= mysql->options.client_ip ?
mysql->options.client_ip : (char*)my_localhost;
if (mysql->options.client_ip)
{
thd->host= mysql->options.client_ip;
thd->ip= thd->host;
}
else
thd->host= (char*)my_localhost;
thd->host_or_ip= thd->host;
if (acl_check_host(thd->host,thd->ip))
......@@ -566,6 +580,9 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
client_field->org_table_length= strlen(client_field->org_table);
client_field->charsetnr= server_field.charsetnr;
client_field->catalog= strdup_root(field_alloc, "std");
client_field->catalog_length= 3;
if (INTERNAL_NUM_FIELD(client_field))
client_field->flags|= NUM_FLAG;
......@@ -575,9 +592,15 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
String tmp(buff, sizeof(buff), default_charset_info), *res;
if (!(res=item->val_str(&tmp)))
{
client_field->def= strdup_root(field_alloc, "");
client_field->def_length= 0;
}
else
{
client_field->def= strdup_root(field_alloc, tmp.ptr());
client_field->def_length= tmp.length();
}
}
else
client_field->def=0;
......
......@@ -124,17 +124,14 @@ static inline int mysql_init_charset(MYSQL *mysql)
return 0;
}
int check_embedded_connection(MYSQL *mysql);
MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
uint port, const char *unix_socket,ulong client_flag)
{
char *db_name;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
char name_buff[USERNAME_LENGTH];
#endif
DBUG_ENTER("mysql_real_connect");
DBUG_PRINT("enter",("host: %s db: %s user: %s",
host ? host : "(Null)",
......@@ -165,10 +162,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (!db || !db[0])
db=mysql->options.db;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!user || !user[0])
user=mysql->options.user;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!passwd)
{
passwd=mysql->options.password;
......@@ -177,16 +174,18 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
passwd=getenv("MYSQL_PWD"); /* get it from environment */
#endif
}
mysql->passwd= passwd ? my_strdup(passwd,MYF(0)) : NULL;
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
if (!user || !user[0])
{
read_user_name(name_buff);
if (!name_buff[0])
if (name_buff[0])
user= name_buff;
}
if (!user)
user= "";
mysql->user=my_strdup(user,MYF(0));
mysql->passwd= passwd ? my_strdup(passwd,MYF(0)) : NULL;
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
port=0;
unix_socket=0;
......@@ -196,10 +195,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
init_embedded_mysql(mysql, client_flag, db_name);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_embedded_connection(mysql))
goto error;
#endif
if (mysql_init_charset(mysql))
goto error;
......
......@@ -120,3 +120,45 @@ select @a+0, @a:=@a+0+count(*), count(*), @a+0 from t1 group by i;
1 3 2 0
3 6 3 0
drop table t1;
set @a=_latin2'test';
select charset(@a),collation(@a),coercibility(@a);
charset(@a) collation(@a) coercibility(@a)
latin2 latin2_general_ci 3
select @a=_latin2'TEST';
@a=_latin2'TEST'
1
select @a=_latin2'TEST' collate latin2_bin;
@a=_latin2'TEST' collate latin2_bin
0
set @a=_latin2'test' collate latin2_general_ci;
select charset(@a),collation(@a),coercibility(@a);
charset(@a) collation(@a) coercibility(@a)
latin2 latin2_general_ci 0
select @a=_latin2'TEST';
@a=_latin2'TEST'
1
select @a=_latin2'TEST' collate latin2_bin;
ERROR HY000: Illegal mix of collations (latin2_general_ci,EXPLICIT) and (latin2_bin,EXPLICIT) for operation '='
select charset(@a:=_latin2'test');
charset(@a:=_latin2'test')
latin2
select collation(@a:=_latin2'test');
collation(@a:=_latin2'test')
latin2_general_ci
select coercibility(@a:=_latin2'test');
coercibility(@a:=_latin2'test')
3
select collation(@a:=_latin2'test' collate latin2_bin);
collation(@a:=_latin2'test' collate latin2_bin)
latin2_bin
select coercibility(@a:=_latin2'test' collate latin2_bin);
coercibility(@a:=_latin2'test' collate latin2_bin)
0
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST';
(@a:=_latin2'test' collate latin2_bin) = _latin2'TEST'
0
select charset(@a),collation(@a),coercibility(@a);
charset(@a) collation(@a) coercibility(@a)
latin2 latin2_bin 0
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST' collate latin2_general_ci;
ERROR HY000: Illegal mix of collations (latin2_bin,EXPLICIT) and (latin2_general_ci,EXPLICIT) for operation '='
......@@ -71,3 +71,31 @@ select @a:=0; select @a, @a:=@a+count(*), count(*), @a from t1 group by i;
select @a:=0; select @a+0, @a:=@a+0+count(*), count(*), @a+0 from t1 group by i;
drop table t1;
#
# Bug #2244: User variables didn't copy collation and derivation
# attributes from values they were initialized to.
#
set @a=_latin2'test';
select charset(@a),collation(@a),coercibility(@a);
select @a=_latin2'TEST';
select @a=_latin2'TEST' collate latin2_bin;
set @a=_latin2'test' collate latin2_general_ci;
select charset(@a),collation(@a),coercibility(@a);
select @a=_latin2'TEST';
--error 1266
select @a=_latin2'TEST' collate latin2_bin;
#
# Check the same invoking Item_set_user_var
#
select charset(@a:=_latin2'test');
select collation(@a:=_latin2'test');
select coercibility(@a:=_latin2'test');
select collation(@a:=_latin2'test' collate latin2_bin);
select coercibility(@a:=_latin2'test' collate latin2_bin);
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST';
select charset(@a),collation(@a),coercibility(@a);
--error 1266
select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST' collate latin2_general_ci;
......@@ -2163,6 +2163,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
is different from query_id).
*/
entry->update_query_id= thd->query_id;
entry->collation.set(args[0]->collation);
cached_result_type= args[0]->result_type();
return 0;
}
......@@ -2174,6 +2175,7 @@ Item_func_set_user_var::fix_length_and_dec()
maybe_null=args[0]->maybe_null;
max_length=args[0]->max_length;
decimals=args[0]->decimals;
collation.set(args[0]->collation);
}
......@@ -2488,6 +2490,8 @@ void Item_func_get_user_var::fix_length_and_dec()
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
null_value= 1;
else
collation.set(var_entry->collation);
if (!(opt_bin_log && is_update_query(thd->lex->sql_command)))
return;
......
<?xml version='1.0' encoding="utf-8"?>
<charsets max-id="93">
<charsets max-id="94">
<description>
This file lists all of the available character sets.
......@@ -100,6 +100,7 @@ To make maintaining easier please:
<collation name="latin1_swedish_ci" id="8" order="Finnish, Swedish" flag="primary"/>
<collation name="latin1_danish_ci" id="15" order="Danish"/>
<collation name="latin1_german2_ci" id="31" order="German Phonebook" flag="compiled"/>
<collation name="latin1_spanish_ci" id="94" order="Spanish"/>
<collation name="latin1_bin" id="47" order="Binary">
<flag>binary</flag>
<flag>compiled</flag>
......
......@@ -209,6 +209,27 @@
</collation>
<collation name="latin1_spanish_ci">
<map>
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
40 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
8F 91 93 95 98 9A A4 A6 A8 AA AF B3 B4 B5 B6 B7
B8 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
8F 91 93 95 98 9A A4 A6 A8 AA AF B9 BA BB BC BF
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
41 41 41 41 41 41 41 53 5B 5B 5B 5B 6B 6B 6B 6B
57 7F 81 81 81 81 81 BD 81 9A 9A 9A 9A AA B1 97
41 41 41 41 41 41 41 53 5B 5B 5B 5B 6B 6B 6B 6B
57 7F 81 81 81 81 81 BE 81 9A 9A 9A 9A AA B1 AA
</map>
</collation>
</charset>
</charsets>
......@@ -308,6 +308,10 @@ TODO list:
#include "../myisammrg/myrg_def.h"
#endif
#ifdef EMBEDDED_LIBRARY
#include "emb_qcache.h"
#endif
#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(M);}
......@@ -646,7 +650,7 @@ void query_cache_abort(NET *net)
}
void query_cache_end_of_result(NET *net)
void query_cache_end_of_result(THD *thd)
{
DBUG_ENTER("query_cache_end_of_result");
......@@ -655,11 +659,15 @@ void query_cache_end_of_result(NET *net)
if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN;
#endif
if (net->query_cache_query != 0) // Quick check on unlocked structure
if (thd->net.query_cache_query != 0) // Quick check on unlocked structure
{
#ifdef EMBEDDED_LIBRARY
query_cache_insert(&thd->net, (byte*)thd,
emb_count_querycache_size(thd));
#endif
STRUCT_LOCK(&query_cache.structure_guard_mutex);
Query_cache_block *query_block = ((Query_cache_block*)
net->query_cache_query);
thd->net.query_cache_query);
if (query_block)
{
DUMP(&query_cache);
......@@ -691,7 +699,7 @@ void query_cache_end_of_result(NET *net)
// Cache was flushed or resized and query was deleted => do nothing
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
}
net->query_cache_query=0;
thd->net.query_cache_query=0;
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
}
DBUG_VOID_RETURN;
......@@ -1052,6 +1060,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
/*
Send cached result to client
*/
#ifndef EMBEDDED_LIBRARY
do
{
DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)",
......@@ -1060,15 +1069,20 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
ALIGN_SIZE(sizeof(Query_cache_result))));
Query_cache_result *result = result_block->result();
#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
if (net_real_write(&thd->net, result->data(),
result_block->used -
result_block->headers_len() -
ALIGN_SIZE(sizeof(Query_cache_result))))
break; // Client aborted
#endif
result_block = result_block->next;
} while (result_block != first_result_block);
#else
{
Querycache_stream qs(result_block, result_block->headers_len() +
ALIGN_SIZE(sizeof(Query_cache_result)));
emb_load_querycache_result(thd, &qs);
}
#endif /*!EMBEDDED_LIBRARY*/
thd->limit_found_rows = query->found_rows();
......@@ -1804,6 +1818,7 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
Query_cache_block *block = *result_block;
uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
#ifndef EMBEDDED_LIBRARY
// Now fill list of blocks that created by allocate_data_chain
do
{
......@@ -1816,6 +1831,10 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
block = block->next;
type = Query_cache_block::RES_CONT;
} while (block != *result_block);
#else
Querycache_stream qs(*result_block, headers_len);
emb_store_querycache_result(&qs, (THD*)data);
#endif /*!EMBEDDED_LIBRARY*/
}
else
{
......
......@@ -392,7 +392,7 @@ protected:
void destroy();
friend void query_cache_insert(NET *net, const char *packet, ulong length);
friend void query_cache_end_of_result(NET *net);
friend void query_cache_end_of_result(THD *thd);
friend void query_cache_abort(NET *net);
/*
......@@ -416,7 +416,7 @@ protected:
extern Query_cache query_cache;
extern TYPELIB query_cache_type_typelib;
void query_cache_end_of_result(NET *net);
void query_cache_end_of_result(THD *thd);
void query_cache_abort(NET *net);
#endif
......@@ -323,12 +323,14 @@ THD::~THD()
#endif
DBUG_PRINT("info", ("freeing host"));
#ifndef EMBEDDED_LIBRARY
if (host != my_localhost) // If not pointer to constant
safeFree(host);
if (user != delayed_user)
safeFree(user);
safeFree(db);
safeFree(ip);
#endif
safeFree(db);
free_root(&warn_root,MYF(0));
free_root(&transaction.mem_root,MYF(0));
mysys_var=0; // Safety (shouldn't be needed)
......
......@@ -3877,7 +3877,7 @@ mysql_parse(THD *thd, char *inBuf, uint length)
else
{
mysql_execute_command(thd);
query_cache_end_of_result(&thd->net);
query_cache_end_of_result(thd);
}
}
}
......
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