Commit f0a6f2b6 authored by unknown's avatar unknown

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

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1-ndb-merge

parents 3466b8d5 19362856
......@@ -45,5 +45,5 @@ enum options_client
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS,
OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
OPT_SIGINT_IGNORE
OPT_SIGINT_IGNORE, OPT_HEXBLOB
};
......@@ -81,7 +81,8 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_charset,
opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
opt_delete_master_logs=0, tty_password=0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0;
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
opt_hex_blob=0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
......@@ -316,6 +317,8 @@ static struct my_option my_long_options[] =
{"comments", 'i', "Write additional information.",
(gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX. this mode does not work with extended-insert",
(gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
......@@ -1507,6 +1510,7 @@ static void dumpTable(uint numFields, char *table)
for (i = 0; i < mysql_num_fields(res); i++)
{
int is_blob;
if (!(field = mysql_fetch_field(res)))
{
sprintf(query,"%s: Not enough fields from table %s! Aborting.\n",
......@@ -1515,6 +1519,17 @@ static void dumpTable(uint numFields, char *table)
error= EX_CONSCHECK;
goto err;
}
/*
63 is my_charset_bin. If charsetnr is not 63,
we have not a BLOB but a TEXT column.
we'll dump it in hex only BLOB columns.
*/
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
(field->type == FIELD_TYPE_BLOB ||
field->type == FIELD_TYPE_LONG_BLOB ||
field->type == FIELD_TYPE_MEDIUM_BLOB ||
field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
if (extended_insert)
{
ulong length = lengths[i];
......@@ -1535,12 +1550,28 @@ static void dumpTable(uint numFields, char *table)
error= EX_EOM;
goto err;
}
dynstr_append(&extended_row,"'");
extended_row.length +=
mysql_real_escape_string(&mysql_connection,
&extended_row.str[extended_row.length],row[i],length);
extended_row.str[extended_row.length]='\0';
dynstr_append(&extended_row,"'");
if (opt_hex_blob && is_blob)
{
ulong counter;
unsigned char *ptr= row[i];
dynstr_append(&extended_row, "0x");
for (counter = 0; counter < lengths[i]; counter++)
{
char xx[3];
sprintf(xx, "%02X", ptr[counter]);
dynstr_append(&extended_row, xx);
}
}
else
{
dynstr_append(&extended_row,"'");
extended_row.length +=
mysql_real_escape_string(&mysql_connection,
&extended_row.str[extended_row.length],
row[i],length);
extended_row.str[extended_row.length]='\0';
dynstr_append(&extended_row,"'");
}
}
else
{
......@@ -1591,8 +1622,20 @@ static void dumpTable(uint numFields, char *table)
print_quoted_xml(md_result_file, row[i], lengths[i]);
fputs("</field>\n", md_result_file);
}
else
unescape(md_result_file, row[i], lengths[i]);
else if (opt_hex_blob && is_blob)
{ /* sakaik got this idea. */
ulong counter;
char xx[4];
unsigned char *ptr= row[i];
fputs("0x", md_result_file);
for (counter = 0; counter < lengths[i]; counter++)
{
sprintf(xx, "%02X", ptr[counter]);
fputs(xx, md_result_file);
}
}
else
unescape(md_result_file, row[i], lengths[i]);
}
else
{
......
......@@ -53,6 +53,30 @@ rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
/* Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
this function, you MUST change also the prototype here! */
extern
int
innobase_strcasecmp(
/*================*/
/* out: 0 if a=b, <0 if a<b, >1 if a>b */
const char* a, /* in: first string to compare */
const char* b); /* in: second string to compare */
/**********************************************************************
Makes all characters in a NUL-terminated UTF-8 string lower case.
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
this function, you MUST change also the prototype here! */
extern
void
innobase_casedn_str(
/*================*/
char* a); /* in/out: string to put in lower case */
/**************************************************************************
Adds a column to the data dictionary hash table. */
static
......@@ -2066,7 +2090,7 @@ dict_foreign_find_index(
break;
}
if (0 != ut_cmp_in_lower_case(columns[i],
if (0 != innobase_strcasecmp(columns[i],
col_name)) {
break;
}
......@@ -2436,7 +2460,7 @@ dict_scan_col(
col = dict_table_get_nth_col(table, i);
if (0 == ut_cmp_in_lower_case(col->name, *name)) {
if (0 == innobase_strcasecmp(col->name, *name)) {
/* Found */
*success = TRUE;
......@@ -2528,30 +2552,19 @@ dict_scan_table_name(
table_name_len = strlen(table_name);
/* Copy database_name, '/', table_name, '\0' */
ref = mem_heap_alloc(heap, database_name_len + table_name_len + 2);
#ifdef __WIN__
ut_cpy_in_lower_case(ref, database_name, database_name_len);
#else
if (srv_lower_case_table_names) {
ut_cpy_in_lower_case(ref, database_name, database_name_len);
} else {
memcpy(ref, database_name, database_name_len);
}
#endif
(ref)[database_name_len] = '/';
#ifdef __WIN__
ut_cpy_in_lower_case(ref + database_name_len + 1,
table_name, table_name_len + 1);
#else
memcpy(ref, database_name, database_name_len);
ref[database_name_len] = '/';
memcpy(ref + database_name_len + 1, table_name, table_name_len + 1);
#ifndef __WIN__
if (srv_lower_case_table_names) {
ut_cpy_in_lower_case(ref + database_name_len + 1,
table_name, table_name_len + 1);
} else {
strcpy(ref + database_name_len + 1, table_name);
#endif /* !__WIN__ */
/* The table name is always put to lower case on Windows. */
innobase_casedn_str(ref);
#ifndef __WIN__
}
#endif
#endif /* !__WIN__ */
*success = TRUE;
*ref_name = ref;
......
......@@ -229,25 +229,6 @@ ut_bit_set_nth(
ulint a, /* in: ulint */
ulint n, /* in: nth bit requested */
ibool val); /* in: value for the bit to set */
/****************************************************************
Copies a string to a memory location, setting characters to lower case. */
void
ut_cpy_in_lower_case(
/*=================*/
char* dest, /* in: destination */
const char* source, /* in: source */
ulint len); /* in: string length */
/****************************************************************
Compares two strings when converted to lower case. */
int
ut_cmp_in_lower_case(
/*=================*/
/* out: -1, 0, 1 if str1 < str2, str1 == str2,
str1 > str2, respectively */
const char* str1, /* in: string1 */
const char* str2); /* in: string2 */
#ifndef UNIV_NONINL
#include "ut0byte.ic"
......
......@@ -2010,6 +2010,11 @@ os_file_read(
return(TRUE);
}
fprintf(stderr,
"InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n"
"InnoDB: Was only able to read %ld.\n", (ulong)n, (ulong)offset_high,
(ulong)offset, (long)ret);
#endif
#ifdef __WIN__
error_handling:
......
......@@ -951,7 +951,13 @@ srv_conc_enter_innodb(
trx->op_info = "sleeping before joining InnoDB queue";
os_thread_sleep(50000);
/* Peter Zaitsev suggested that we take the sleep away
altogether. But the sleep may be good in pathological
situations of lots of thread switches. Simply put some
threads aside for a while to reduce the number of thread
switches. */
os_thread_sleep(10000);
trx->op_info = "";
......
......@@ -29,51 +29,3 @@ ut_dulint_sort(dulint* arr, dulint* aux_arr, ulint low, ulint high)
UT_SORT_FUNCTION_BODY(ut_dulint_sort, arr, aux_arr, low, high,
ut_dulint_cmp);
}
/****************************************************************
Copies a string to a memory location, setting characters to lower case. */
void
ut_cpy_in_lower_case(
/*=================*/
char* dest, /* in: destination */
const char* source, /* in: source */
ulint len) /* in: string length */
{
ulint i;
for (i = 0; i < len; i++) {
dest[i] = tolower(source[i]);
}
}
/****************************************************************
Compares two strings when converted to lower case. */
int
ut_cmp_in_lower_case(
/*=================*/
/* out: -1, 0, 1 if str1 < str2, str1 == str2,
str1 > str2, respectively */
const char* str1, /* in: string1 */
const char* str2) /* in: string2 */
{
for (;;) {
int c1, c2;
if (!*str1) {
return(*str2 ? -1 : 0);
} else if (!*str2) {
return 1;
}
c1 = tolower(*str1++);
c2 = tolower(*str2++);
if (c1 < c2) {
return(-1);
}
if (c1 > c2) {
return(1);
}
}
return(0);
}
......@@ -1033,3 +1033,81 @@ a
No
aaa,bbb
drop table t1,t2,t3,t4;
create table t1 as
(select _latin1'test') union
(select _latin1'TEST') union
(select _latin1'TeST');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`test` char(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
1
drop table t1;
create table t1 as
(select _latin1'test' collate latin1_bin) union
(select _latin1'TEST') union
(select _latin1'TeST');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`_latin1'test' collate latin1_bin` char(4) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
3
drop table t1;
create table t1 as
(select _latin1'test') union
(select _latin1'TEST' collate latin1_bin) union
(select _latin1'TeST');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
3
drop table t1;
create table t1 as
(select _latin1'test') union
(select _latin1'TEST') union
(select _latin1'TeST' collate latin1_bin);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
3
drop table t1;
create table t2 (
a char character set latin1 collate latin1_swedish_ci,
b char character set latin1 collate latin1_bin);
create table t1 as
(select a from t2) union
(select b from t2);
ERROR HY000: Illegal mix of collations for operation 'UNION'
create table t1 as
(select a collate latin1_german1_ci from t2) union
(select b from t2);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a collate latin1_german1_ci` char(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as
(select a from t2) union
(select b collate latin1_german1_ci from t2);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop table t2;
......@@ -595,3 +595,58 @@ select a as a from t3 union select "1";
select a as a from t4 union select a from t3;
select a as a from t1 union select a from t4;
drop table t1,t2,t3,t4;
#
# Bug #6139 UNION doesn't understand collate in the column of second select
#
create table t1 as
(select _latin1'test') union
(select _latin1'TEST') union
(select _latin1'TeST');
show create table t1;
select count(*) from t1;
drop table t1;
create table t1 as
(select _latin1'test' collate latin1_bin) union
(select _latin1'TEST') union
(select _latin1'TeST');
show create table t1;
select count(*) from t1;
drop table t1;
create table t1 as
(select _latin1'test') union
(select _latin1'TEST' collate latin1_bin) union
(select _latin1'TeST');
show create table t1;
select count(*) from t1;
drop table t1;
create table t1 as
(select _latin1'test') union
(select _latin1'TEST') union
(select _latin1'TeST' collate latin1_bin);
show create table t1;
select count(*) from t1;
drop table t1;
create table t2 (
a char character set latin1 collate latin1_swedish_ci,
b char character set latin1 collate latin1_bin);
--error 1271
create table t1 as
(select a from t2) union
(select b from t2);
create table t1 as
(select a collate latin1_german1_ci from t2) union
(select b from t2);
show create table t1;
drop table t1;
create table t1 as
(select a from t2) union
(select b collate latin1_german1_ci from t2);
show create table t1;
drop table t1;
drop table t2;
......@@ -429,6 +429,36 @@ innobase_mysql_print_thd(
putc('\n', f);
}
/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
NOTE that the exact prototype of this function has to be in
/innobase/dict/dict0dict.c! */
extern "C"
int
innobase_strcasecmp(
/*================*/
/* out: 0 if a=b, <0 if a<b, >1 if a>b */
const char* a, /* in: first string to compare */
const char* b) /* in: second string to compare */
{
return(my_strcasecmp(system_charset_info, a, b));
}
/**********************************************************************
Makes all characters in a NUL-terminated UTF-8 string lower case.
NOTE that the exact prototype of this function has to be in
/innobase/dict/dict0dict.c! */
extern "C"
void
innobase_casedn_str(
/*================*/
char* a) /* in/out: string to put in lower case */
{
my_casedn_str(system_charset_info, a);
}
/*************************************************************************
Creates a temporary file. */
extern "C"
......@@ -687,14 +717,7 @@ innobase_query_caching_of_table_permitted(
separator between db and table */
norm_name[full_name_len] = '\0';
#ifdef __WIN__
/* Put to lower case */
char* ptr = norm_name;
while (*ptr != '\0') {
*ptr = tolower(*ptr);
ptr++;
}
innobase_casedn_str(norm_name);
#endif
/* The call of row_search_.. will start a new transaction if it is
not yet started */
......@@ -1539,14 +1562,7 @@ normalize_table_name(
norm_name[name_ptr - db_ptr - 1] = '/';
#ifdef __WIN__
/* Put to lower case */
ptr = norm_name;
while (*ptr != '\0') {
*ptr = tolower(*ptr);
ptr++;
}
innobase_casedn_str(norm_name);
#endif
}
......@@ -3559,9 +3575,9 @@ create_index(
field = form->field[j];
if (0 == ut_cmp_in_lower_case(
(char*)field->field_name,
(char*)key_part->field->field_name)) {
if (0 == innobase_strcasecmp(
field->field_name,
key_part->field->field_name)) {
/* Found the corresponding column */
break;
......@@ -4003,7 +4019,7 @@ innobase_drop_database(
namebuf[len] = '/';
namebuf[len + 1] = '\0';
#ifdef __WIN__
my_casedn_str(system_charset_info, namebuf);
innobase_casedn_str(namebuf);
#endif
trx = trx_allocate_for_mysql();
trx->mysql_thd = current_thd;
......
......@@ -2558,8 +2558,8 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
if (use_new_field || use_expression_type ||
(new_result_type != item_type) || (new_length > max_length) ||
(!maybe_null && item->maybe_null) ||
(item_type == STRING_RESULT &&
!my_charset_same(collation.collation, item->collation.collation)))
(item_type == STRING_RESULT &&
collation.collation != item->collation.collation))
{
if (use_expression_type || item->type() != Item::FIELD_ITEM)
field_example= 0;
......
......@@ -264,9 +264,27 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
}
}
// it is not single select
if (first_select->next_select())
{
// it is not single select
/*
Check that it was possible to aggregate
all collations together for UNION.
*/
List_iterator_fast<Item> tp(types);
Item *type;
while ((type= tp++))
{
if (type->result_type() == STRING_RESULT &&
type->collation.derivation == DERIVATION_NONE)
{
my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
goto err;
}
}
union_result->tmp_table_param.field_count= types.elements;
if (!(table= create_tmp_table(thd_arg,
&union_result->tmp_table_param, types,
......
......@@ -58,8 +58,7 @@ using its non-default counterpart for the given character set.
binary_numner - ID of a charset+collation pair, which consists
of the same character set and the binary collation of this
character set. Not really used now. Intended to optimize
"SELECT BINARY x" in the future.
character set. Not really used now.
Names
-----
......@@ -121,7 +120,7 @@ Misc fields
e.g. Letter 'A' with two dots above is
substituted with 'AE'.
mbminlen - mininum multibyte sequence length.
Now always 1 accept ucs2. For ucs2
Now always 1 except ucs2. For ucs2
it is 2.
mbmaxlen - maximum multibyte sequence length.
1 for 8bit charsets. Can be also 2 or 3.
......
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