diff options
author | unknown <tomas@poseidon.ndb.mysql.com> | 2004-10-06 13:34:17 +0000 |
---|---|---|
committer | unknown <tomas@poseidon.ndb.mysql.com> | 2004-10-06 13:34:17 +0000 |
commit | 4a618a35c54dd0d11bba7d642ea59e8e3684c318 (patch) | |
tree | 120a08ed6dae287cd6d7dc75089e67f87bbf2032 | |
parent | f77811a2526818afd09deb3bc363b45702eebe54 (diff) | |
parent | e82d3d49342f4be222252f22b7f8cb7399baec6f (diff) | |
download | mariadb-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.h | 16 | ||||
-rw-r--r-- | innobase/include/ut0mem.h | 10 | ||||
-rw-r--r-- | innobase/include/ut0mem.ic | 2 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 17 | ||||
-rw-r--r-- | innobase/ut/ut0mem.c | 8 | ||||
-rw-r--r-- | mysql-test/r/bdb.result | 24 | ||||
-rw-r--r-- | mysql-test/r/ctype_utf8.result | 24 | ||||
-rw-r--r-- | mysql-test/t/bdb.test | 20 | ||||
-rw-r--r-- | mysql-test/t/ctype_utf8.test | 20 | ||||
-rw-r--r-- | mysql-test/t/ndb_subquery.test | 2 | ||||
-rw-r--r-- | ndb/src/mgmsrv/ConfigInfo.cpp | 10 | ||||
-rw-r--r-- | sql/field.cc | 18 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 45 | ||||
-rw-r--r-- | sql/sql_cache.cc | 74 |
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>§ions, 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>§ions, 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); } /***************************************************************************** |