Commit ae87bd11 authored by tomas@poseidon.ndb.mysql.com's avatar tomas@poseidon.ndb.mysql.com

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

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1-ndb2
parents 6f0f5c1d 66923bf9
......@@ -151,7 +151,12 @@ struct dict_col_struct{
in some of the functions below */
};
#define DICT_MAX_COL_PREFIX_LEN 512
/* DICT_MAX_COL_PREFIX_LEN is measured in bytes. Starting from 4.1.6, we
set max col prefix len to < 3 * 256, so that one can create a column prefix
index on 255 characters of a TEXT field also in the UTF-8 charset. In that
charset, a character may take at most 3 bytes. */
#define DICT_MAX_COL_PREFIX_LEN 768
/* Data structure for a field in an index */
struct dict_field_struct{
......@@ -160,9 +165,12 @@ struct dict_field_struct{
ulint order; /* flags for ordering this field:
DICT_DESCEND, ... */
ulint prefix_len; /* 0 or the length of the column
prefix in a MySQL index of type, e.g.,
INDEX (textcol(25)); must be smaller
than DICT_MAX_COL_PREFIX_LEN */
prefix in bytes in a MySQL index of
type, e.g., INDEX (textcol(25));
must be smaller than
DICT_MAX_COL_PREFIX_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
};
/* Data structure for an index tree */
......
......@@ -117,7 +117,7 @@ int
ut_strcmp(const void* str1, const void* str2);
/**************************************************************************
Determine the length of a string when it is quoted with ut_strcpyq(). */
Compute strlen(ut_strcpyq(str, q)). */
UNIV_INLINE
ulint
ut_strlenq(
......@@ -127,7 +127,9 @@ ut_strlenq(
char q); /* in: the quote character */
/**************************************************************************
Make a quoted copy of a string. */
Make a quoted copy of a NUL-terminated string. Leading and trailing
quotes will not be included; only embedded quotes will be escaped.
See also ut_strlenq() and ut_memcpyq(). */
char*
ut_strcpyq(
......@@ -138,7 +140,9 @@ ut_strcpyq(
const char* src); /* in: null-terminated string */
/**************************************************************************
Make a quoted copy of a fixed-length string. */
Make a quoted copy of a fixed-length string. Leading and trailing
quotes will not be included; only embedded quotes will be escaped.
See also ut_strlenq() and ut_strcpyq(). */
char*
ut_memcpyq(
......
......@@ -49,7 +49,7 @@ ut_strcmp(const void* str1, const void* str2)
}
/**************************************************************************
Determine the length of a string when it is quoted with ut_strcpyq(). */
Compute strlen(ut_strcpyq(str, q)). */
UNIV_INLINE
ulint
ut_strlenq(
......
......@@ -1630,6 +1630,8 @@ row_create_index_for_mysql(
trx->op_info = "creating index";
trx_start_if_not_started(trx);
/* Check that the same column does not appear twice in the index.
Starting from 4.0.14, InnoDB should be able to cope with that, but
safer not to allow them. */
......@@ -1656,9 +1658,16 @@ row_create_index_for_mysql(
goto error_handling;
}
}
}
/* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */
trx_start_if_not_started(trx);
if (dict_index_get_nth_field(index, i)->prefix_len
>= DICT_MAX_COL_PREFIX_LEN) {
err = DB_TOO_BIG_RECORD;
goto error_handling;
}
}
if (row_mysql_is_recovered_tmp_table(index->table_name)) {
......@@ -1988,9 +1997,9 @@ row_discard_tablespace_for_mysql(
"new_id_high INT;\n"
"table_name CHAR;\n"
"BEGIN\n"
"table_name := ";
"table_name := '";
static const char discard_tablespace_proc2[] =
";\n"
"';\n"
"new_id_high := %lu;\n"
"new_id_low := %lu;\n"
"new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n"
......
......@@ -313,7 +313,9 @@ ut_free_all_mem(void)
}
/**************************************************************************
Make a quoted copy of a string. */
Make a quoted copy of a NUL-terminated string. Leading and trailing
quotes will not be included; only embedded quotes will be escaped.
See also ut_strlenq() and ut_memcpyq(). */
char*
ut_strcpyq(
......@@ -333,7 +335,9 @@ ut_strcpyq(
}
/**************************************************************************
Make a quoted copy of a fixed-length string. */
Make a quoted copy of a fixed-length string. Leading and trailing
quotes will not be included; only embedded quotes will be escaped.
See also ut_strlenq() and ut_strcpyq(). */
char*
ut_memcpyq(
......
......@@ -1260,3 +1260,27 @@ a length(a) char_length(a)
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 510 255
drop table t1;
SET NAMES latin1;
CREATE TABLE t1 (
id int unsigned NOT NULL auto_increment,
list_id smallint unsigned NOT NULL,
term TEXT NOT NULL,
PRIMARY KEY(id),
INDEX(list_id, term(4))
) ENGINE=BDB CHARSET=utf8;
INSERT INTO t1 SET list_id = 1, term = "letterc";
INSERT INTO t1 SET list_id = 1, term = "letterb";
INSERT INTO t1 SET list_id = 1, term = "lettera";
INSERT INTO t1 SET list_id = 1, term = "letterd";
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
id
1
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
id
2
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
id
3
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
id
4
DROP TABLE t1;
......@@ -726,3 +726,27 @@ length(subject)
3
432
DROP TABLE t1;
CREATE TABLE t1 (
id int unsigned NOT NULL auto_increment,
list_id smallint unsigned NOT NULL,
term TEXT NOT NULL,
PRIMARY KEY(id),
INDEX(list_id, term(4))
) ENGINE=MYISAM CHARSET=utf8;
INSERT INTO t1 SET list_id = 1, term = "letterc";
INSERT INTO t1 SET list_id = 1, term = "letterb";
INSERT INTO t1 SET list_id = 1, term = "lettera";
INSERT INTO t1 SET list_id = 1, term = "letterd";
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
id
1
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
id
2
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
id
3
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
id
4
DROP TABLE t1;
......@@ -909,3 +909,23 @@ insert into t1 values (@a);
select a, length(a), char_length(a) from t1;
drop table t1;
SET NAMES latin1;
#
# Bug #5832 SELECT doesn't return records in some cases
#
CREATE TABLE t1 (
id int unsigned NOT NULL auto_increment,
list_id smallint unsigned NOT NULL,
term TEXT NOT NULL,
PRIMARY KEY(id),
INDEX(list_id, term(4))
) ENGINE=BDB CHARSET=utf8;
INSERT INTO t1 SET list_id = 1, term = "letterc";
INSERT INTO t1 SET list_id = 1, term = "letterb";
INSERT INTO t1 SET list_id = 1, term = "lettera";
INSERT INTO t1 SET list_id = 1, term = "letterd";
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
DROP TABLE t1;
......@@ -572,3 +572,23 @@ INSERT INTO t1 VALUES ('aaa','bbb');
SELECT length(subject) FROM t1;
SELECT length(subject) FROM t1 ORDER BY 1;
DROP TABLE t1;
#
# Bug #5832 SELECT doesn't return records in some cases
#
CREATE TABLE t1 (
id int unsigned NOT NULL auto_increment,
list_id smallint unsigned NOT NULL,
term TEXT NOT NULL,
PRIMARY KEY(id),
INDEX(list_id, term(4))
) ENGINE=MYISAM CHARSET=utf8;
INSERT INTO t1 SET list_id = 1, term = "letterc";
INSERT INTO t1 SET list_id = 1, term = "letterb";
INSERT INTO t1 SET list_id = 1, term = "lettera";
INSERT INTO t1 SET list_id = 1, term = "letterd";
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
DROP TABLE t1;
#-- source include/have_ndb.inc
-- source include/have_ndb.inc
--disable_warnings
drop table if exists t1;
......
......@@ -3501,6 +3501,8 @@ check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>&sections,
BaseString node_group_warning, arbitration_warning;
const char *arbit_warn_fmt=
"\n arbitrator with id %d and db node with id %d on same host %s";
const char *arbit_warn_fmt2=
"\n arbitrator with id %d has no hostname specified";
ctx.m_userProperties.get("NoOfNodes", &n_nodes);
for (i= 0, n= 0; n < n_nodes; i++){
......@@ -3583,13 +3585,19 @@ check_node_vs_replicas(Vector<ConfigInfo::ConfigRuleSection>&sections,
arbitration_warning.appfmt(arbit_warn_fmt, i, ii, host);
}
}
else
{
arbitration_warning.appfmt(arbit_warn_fmt2, i);
}
}
}
}
if (db_host_count > 1 && node_group_warning.length() > 0)
ndbout_c("Cluster configuration warning:\n%s",node_group_warning.c_str());
if (db_host_count > 1 && arbitration_warning.length() > 0)
ndbout_c("Cluster configuration warning:%s",arbitration_warning.c_str());
ndbout_c("Cluster configuration warning:%s%s",arbitration_warning.c_str(),
"\n Running arbitrator on the same host as a database node may"
"\n cause complete cluster shutdown in case of host failure.");
}
return true;
}
......
......@@ -2970,6 +2970,14 @@ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
return TIMESTAMP_AUTO_SET_ON_INSERT;
case TIMESTAMP_UN_FIELD:
return TIMESTAMP_AUTO_SET_ON_UPDATE;
case TIMESTAMP_OLD_FIELD:
/*
Altough we can have several such columns in legacy tables this
function should be called only for first of them (i.e. the one
having auto-set property).
*/
DBUG_ASSERT(table->timestamp_field == this);
/* Fall-through */
case TIMESTAMP_DNUN_FIELD:
return TIMESTAMP_AUTO_SET_ON_BOTH;
default:
......@@ -5077,6 +5085,11 @@ void Field_blob::get_key_image(char *buff,uint length,
}
#endif /*HAVE_SPATIAL*/
get_ptr(&blob);
uint char_length= length / cs->mbmaxlen;
char_length= my_charpos(cs, blob, blob + length, char_length);
set_if_smaller(length, char_length);
if ((uint32) length > blob_length)
{
/*
......@@ -5087,7 +5100,6 @@ void Field_blob::get_key_image(char *buff,uint length,
length=(uint) blob_length;
}
int2store(buff,length);
get_ptr(&blob);
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
}
......@@ -5103,6 +5115,10 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
char *blob1;
uint blob_length=get_length(ptr);
memcpy_fixed(&blob1,ptr+packlength,sizeof(char*));
CHARSET_INFO *cs= charset();
uint char_length= max_key_length / cs->mbmaxlen;
char_length= my_charpos(cs, blob1, blob1+blob_length, char_length);
set_if_smaller(blob_length, char_length);
return Field_blob::cmp(blob1,min(blob_length, max_key_length),
(char*) key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr));
......
......@@ -3525,10 +3525,6 @@ create_index(
prefix_len = 0;
}
if (prefix_len >= DICT_MAX_COL_PREFIX_LEN) {
DBUG_RETURN(-1);
}
/* We assume all fields should be sorted in ascending
order, hence the '0': */
......@@ -5333,39 +5329,32 @@ innobase_get_at_most_n_mbchars(
/* If the charset is multi-byte, then we must find the length of the
first at most n chars in the string. If the string contains less
characters than n, then we return the length to the end of the last
full character. */
character. */
if (charset->mbmaxlen > 1) {
/* ulint right_value; */
/* my_charpos() returns the byte length of the first n_chars
characters, or the end of the last full character */
characters, or a value bigger than the length of str, if
there were not enough full characters in str.
Why does the code below work:
Suppose that we are looking for n UTF-8 characters.
1) If the string is long enough, then the prefix contains at
least n complete UTF-8 characters + maybe some extra
characters + an incomplete UTF-8 character. No problem in
this case. The function returns the pointer to the
end of the nth character.
2) If the string is not long enough, then the string contains
the complete value of a column, that is, only complete UTF-8
characters, and we can store in the column prefix index the
whole string. */
char_length = my_charpos(charset, str,
str + data_len, n_chars);
/*################################################*/
/* TODO: my_charpos sometimes returns a non-sensical value
that is BIGGER than data_len: try to fix this bug partly with
these heuristics. This is NOT a complete bug fix! */
if (char_length > data_len) {
char_length = data_len;
}
/*################################################*/
/* printf("data_len %lu, n_chars %lu, char_len %lu\n",
data_len, n_chars, char_length);
if (data_len < n_chars) {
right_value = data_len;
} else {
right_value = n_chars;
}
if (right_value != char_length) {
printf("ERRRRRROOORRRRRRRRRRRR!!!!!!!!!\n");
}
*/
} else {
if (data_len < prefix_len) {
char_length = data_len;
......
......@@ -1953,55 +1953,55 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
ulong len= data_len + all_headers_len;
ulong align_len= ALIGN_SIZE(len);
DBUG_ENTER("Query_cache::allocate_data_chain");
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
ulong min_size = (first_block_arg ?
get_min_first_result_data_size():
get_min_append_result_data_size());
*result_block = allocate_block(max(min_size, align_len),
min_result_data_size == 0,
all_headers_len + min_result_data_size,
1);
my_bool success = (*result_block != 0);
if (success)
Query_cache_block *prev_block= NULL;
Query_cache_block *new_block;
DBUG_ENTER("Query_cache::allocate_data_chain");
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
do
{
Query_cache_block *new_block= *result_block;
ulong len= data_len + all_headers_len;
ulong align_len= ALIGN_SIZE(len);
if (!(new_block= allocate_block(max(min_size, align_len),
min_result_data_size == 0,
all_headers_len + min_result_data_size,
1)))
{
DBUG_PRINT("warning", ("Can't allocate block for results"));
DBUG_RETURN(FALSE);
}
new_block->n_tables = 0;
new_block->used = 0;
new_block->used = min(len, new_block->length);
new_block->type = Query_cache_block::RES_INCOMPLETE;
new_block->next = new_block->prev = new_block;
Query_cache_result *header = new_block->result();
header->parent(query_block);
if (new_block->length < len)
{
/*
We got less memory then we need (no big memory blocks) =>
Continue to allocated more blocks until we got everything we need.
*/
Query_cache_block *next_block;
if ((success = allocate_data_chain(&next_block,
len - new_block->length,
query_block, first_block_arg)))
double_linked_list_join(new_block, next_block);
}
if (success)
{
new_block->used = min(len, new_block->length);
DBUG_PRINT("qcache", ("Block len %lu used %lu",
DBUG_PRINT("qcache", ("Block len %lu used %lu",
new_block->length, new_block->used));
}
if (prev_block)
double_linked_list_join(prev_block, new_block);
else
DBUG_PRINT("warning", ("Can't allocate block for continue"));
}
else
DBUG_PRINT("warning", ("Can't allocate block for results"));
DBUG_RETURN(success);
*result_block= new_block;
if (new_block->length >= len)
break;
/*
We got less memory then we need (no big memory blocks) =>
Continue to allocated more blocks until we got everything we need.
*/
data_len= len - new_block->length;
prev_block= new_block;
} while(1);
DBUG_RETURN(TRUE);
}
/*****************************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment