summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <tomas@poseidon.ndb.mysql.com>2004-10-06 13:34:17 +0000
committerunknown <tomas@poseidon.ndb.mysql.com>2004-10-06 13:34:17 +0000
commit4a618a35c54dd0d11bba7d642ea59e8e3684c318 (patch)
tree120a08ed6dae287cd6d7dc75089e67f87bbf2032
parentf77811a2526818afd09deb3bc363b45702eebe54 (diff)
parente82d3d49342f4be222252f22b7f8cb7399baec6f (diff)
downloadmariadb-git-4a618a35c54dd0d11bba7d642ea59e8e3684c318.tar.gz
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-4.1
into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1-ndb2 BitKeeper/deleted/.del-ndb_subquery.result: Delete: mysql-test/r/ndb_subquery.result BitKeeper/deleted/.del-ndb_subquery.test: Delete: mysql-test/t/ndb_subquery.test ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Auto merged ndb/test/run-test/atrt-mysql-test-run: Auto merged sql/ha_ndbcluster.cc: Auto merged
-rw-r--r--innobase/include/dict0mem.h16
-rw-r--r--innobase/include/ut0mem.h10
-rw-r--r--innobase/include/ut0mem.ic2
-rw-r--r--innobase/row/row0mysql.c17
-rw-r--r--innobase/ut/ut0mem.c8
-rw-r--r--mysql-test/r/bdb.result24
-rw-r--r--mysql-test/r/ctype_utf8.result24
-rw-r--r--mysql-test/t/bdb.test20
-rw-r--r--mysql-test/t/ctype_utf8.test20
-rw-r--r--mysql-test/t/ndb_subquery.test2
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp10
-rw-r--r--sql/field.cc18
-rw-r--r--sql/ha_innodb.cc45
-rw-r--r--sql/sql_cache.cc74
14 files changed, 208 insertions, 82 deletions
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 3fc3e850987..944fad1a8c8 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -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 */
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index 2e02b3f0b6b..73ecb25101a 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -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(
diff --git a/innobase/include/ut0mem.ic b/innobase/include/ut0mem.ic
index 3bb30a80f22..76c721112a0 100644
--- a/innobase/include/ut0mem.ic
+++ b/innobase/include/ut0mem.ic
@@ -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(
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 8f5d3a216bc..152bb0291c3 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -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"
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 09410e348c2..a6002d7fd83 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -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(
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 846adaf53ef..6da3dbb929d 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -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;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 0c9ea42a0f1..0b98d9432ae 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -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;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 86214ecd5a8..069ec758ba2 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -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;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 40709443d62..4a8eb63ed36 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -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;
diff --git a/mysql-test/t/ndb_subquery.test b/mysql-test/t/ndb_subquery.test
index f1f8edfbd8f..e80d9b16b46 100644
--- a/mysql-test/t/ndb_subquery.test
+++ b/mysql-test/t/ndb_subquery.test
@@ -1,4 +1,4 @@
-#-- source include/have_ndb.inc
+-- source include/have_ndb.inc
--disable_warnings
drop table if exists t1;
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index e8f768d1968..9629c5e8904 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -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;
}
diff --git a/sql/field.cc b/sql/field.cc
index eaa1ca2bcca..ec3bd72878d 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -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));
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 132bb835d82..f5da82a8a8c 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -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;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 674452192f8..f69fb3085d3 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -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);
}
/*****************************************************************************